From cedc9a478d8c6265879dc3839ef3d4849a709184 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 5 Oct 2005 07:13:30 -0400 Subject: libata: fix ATAPI DMA alignment issues ATAPI needs to be padded to next 4 byte boundary, if misaligned. Original work by me, many fixes from Tejun Heo. --- include/linux/libata.h | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/libata.h b/include/linux/libata.h index ceee1fc42c60..3ab67622ef93 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -154,6 +154,10 @@ enum { ATA_SHIFT_UDMA = 0, ATA_SHIFT_MWDMA = 8, ATA_SHIFT_PIO = 11, + + /* size of buffer to pad xfers ending on unaligned boundaries */ + ATA_DMA_PAD_SZ = 4, + ATA_DMA_PAD_BUF_SZ = ATA_DMA_PAD_SZ * ATA_MAX_QUEUE, }; enum pio_task_states { @@ -237,9 +241,12 @@ struct ata_queued_cmd { unsigned long flags; /* ATA_QCFLAG_xxx */ unsigned int tag; unsigned int n_elem; + unsigned int orig_n_elem; int dma_dir; + unsigned int pad_len; + unsigned int nsect; unsigned int cursect; @@ -250,9 +257,11 @@ struct ata_queued_cmd { unsigned int cursg_ofs; struct scatterlist sgent; + struct scatterlist pad_sgent; void *buf_virt; - struct scatterlist *sg; + /* DO NOT iterate over __sg manually, use ata_for_each_sg() */ + struct scatterlist *__sg; ata_qc_cb_t complete_fn; @@ -295,6 +304,9 @@ struct ata_port { struct ata_prd *prd; /* our SG list */ dma_addr_t prd_dma; /* and its DMA mapping */ + void *pad; /* array of DMA pad buffers */ + dma_addr_t pad_dma; + struct ata_ioports ioaddr; /* ATA cmd/ctl/dma register blocks */ u8 ctl; /* cache of ATA control register */ @@ -458,6 +470,19 @@ extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits); #endif /* CONFIG_PCI */ +static inline struct scatterlist * +ata_qc_next_sg(struct scatterlist *sg, struct ata_queued_cmd *qc) +{ + if (sg == &qc->pad_sgent) + return NULL; + if (++sg - qc->__sg < qc->n_elem) + return sg; + return qc->pad_len ? &qc->pad_sgent : NULL; +} + +#define ata_for_each_sg(sg, qc) \ + for (sg = qc->__sg; sg; sg = ata_qc_next_sg(sg, qc)) + static inline unsigned int ata_tag_valid(unsigned int tag) { return (tag < ATA_MAX_QUEUE) ? 1 : 0; -- cgit v1.2.3 From 972c26bdd6b58e7534473c4f7928584578cf43f4 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Tue, 18 Oct 2005 22:14:54 -0400 Subject: libata: add ata_sg_is_last() helper, use it in several drivers --- drivers/scsi/pdc_adma.c | 8 ++++---- drivers/scsi/sata_mv.c | 16 +++++++++------- drivers/scsi/sata_sil24.c | 15 ++++++++++----- include/linux/libata.h | 12 ++++++++++++ 4 files changed, 35 insertions(+), 16 deletions(-) (limited to 'include/linux') diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index 53b8db4be1a9..c6825da6ae20 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -293,14 +293,14 @@ static void adma_eng_timeout(struct ata_port *ap) static int adma_fill_sg(struct ata_queued_cmd *qc) { - struct scatterlist *sg = qc->sg; + struct scatterlist *sg; struct ata_port *ap = qc->ap; struct adma_port_priv *pp = ap->private_data; u8 *buf = pp->pkt; - int nelem, i = (2 + buf[3]) * 8; + int i = (2 + buf[3]) * 8; u8 pFLAGS = pORD | ((qc->tf.flags & ATA_TFLAG_WRITE) ? pDIRO : 0); - for (nelem = 0; nelem < qc->n_elem; nelem++,sg++) { + ata_for_each_sg(sg, qc) { u32 addr; u32 len; @@ -312,7 +312,7 @@ static int adma_fill_sg(struct ata_queued_cmd *qc) *(__le32 *)(buf + i) = cpu_to_le32(len); i += 4; - if ((nelem + 1) == qc->n_elem) + if (ata_sg_is_last(sg, qc)) pFLAGS |= pEND; buf[i++] = pFLAGS; buf[i++] = qc->dev->dma_mode & 0xf; diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index d457f5673476..be7c378dcd36 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -785,22 +785,24 @@ static void mv_port_stop(struct ata_port *ap) static void mv_fill_sg(struct ata_queued_cmd *qc) { struct mv_port_priv *pp = qc->ap->private_data; - unsigned int i; + unsigned int i = 0; + struct scatterlist *sg; - for (i = 0; i < qc->n_elem; i++) { + ata_for_each_sg(sg, qc) { u32 sg_len; dma_addr_t addr; - addr = sg_dma_address(&qc->sg[i]); - sg_len = sg_dma_len(&qc->sg[i]); + addr = sg_dma_address(sg); + sg_len = sg_dma_len(sg); pp->sg_tbl[i].addr = cpu_to_le32(addr & 0xffffffff); pp->sg_tbl[i].addr_hi = cpu_to_le32((addr >> 16) >> 16); assert(0 == (sg_len & ~MV_DMA_BOUNDARY)); pp->sg_tbl[i].flags_size = cpu_to_le32(sg_len); - } - if (0 < qc->n_elem) { - pp->sg_tbl[qc->n_elem - 1].flags_size |= EPRD_FLAG_END_OF_TBL; + if (ata_sg_is_last(sg, qc)) + pp->sg_tbl[i].flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL); + + i++; } } diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 19857814d69f..e16d1815cda0 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -416,15 +416,20 @@ static void sil24_phy_reset(struct ata_port *ap) static inline void sil24_fill_sg(struct ata_queued_cmd *qc, struct sil24_cmd_block *cb) { - struct scatterlist *sg = qc->sg; struct sil24_sge *sge = cb->sge; - unsigned i; + struct scatterlist *sg; + unsigned int idx = 0; - for (i = 0; i < qc->n_elem; i++, sg++, sge++) { + ata_for_each_sg(sg, qc) { sge->addr = cpu_to_le64(sg_dma_address(sg)); sge->cnt = cpu_to_le32(sg_dma_len(sg)); - sge->flags = 0; - sge->flags = i < qc->n_elem - 1 ? 0 : cpu_to_le32(SGE_TRM); + if (ata_sg_is_last(sg, qc)) + sge->flags = cpu_to_le32(SGE_TRM); + else + sge->flags = 0; + + sge++; + idx++; } } diff --git a/include/linux/libata.h b/include/linux/libata.h index d3f58a796c3a..d3dfefefabec 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -480,6 +480,18 @@ extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits); #endif /* CONFIG_PCI */ +static inline int +ata_sg_is_last(struct scatterlist *sg, struct ata_queued_cmd *qc) +{ + if (sg == &qc->pad_sgent) + return 1; + if (qc->pad_len) + return 0; + if (((sg - qc->__sg) + 1) == qc->n_elem) + return 1; + return 0; +} + static inline struct scatterlist * ata_qc_next_sg(struct scatterlist *sg, struct ata_queued_cmd *qc) { -- cgit v1.2.3 From 2407534f8be8015d585104bcc4374870b6b70fe7 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 1 Nov 2005 16:52:11 -0800 Subject: [ETHERNET]: Optimize is_broadcast_ether_addr Optimize the match for broadcast address by using bit operations instead of comparison. This saves a number of conditional branches, and generates smaller code. Signed-off-by: Stephen Hemminger Signed-off-by: Arnaldo Carvalho de Melo --- include/linux/etherdevice.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h index cc84934f9059..17460c85df7b 100644 --- a/include/linux/etherdevice.h +++ b/include/linux/etherdevice.h @@ -71,8 +71,7 @@ static inline int is_multicast_ether_addr(const u8 *addr) static inline int is_broadcast_ether_addr(const u8 *addr) { - return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) && - (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff)); + return (addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5]) == 0xff; } /** -- cgit v1.2.3 From c2da8acaf488b8651edfb04ebf3ab089f3a7830f Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 1 Nov 2005 17:05:09 -0800 Subject: [ETHERNET]: Add ether stuff to docbook Fix up etherdevice docbook comments and make them (and other networking stuff) get dragged into the kernel-api. Delete the old 8390 stuff, it really isn't interesting anymore. Signed-off-by: Stephen Hemminger Signed-off-by: Arnaldo Carvalho de Melo --- Documentation/DocBook/kernel-api.tmpl | 6 +++--- include/linux/etherdevice.h | 24 +++++++++++++++--------- 2 files changed, 18 insertions(+), 12 deletions(-) (limited to 'include/linux') diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index 4d9b66d8b4db..ec474e5a25ed 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl @@ -239,9 +239,9 @@ X!Ilib/string.c Network device support Driver Support !Enet/core/dev.c - - 8390 Based Network Cards -!Edrivers/net/8390.c +!Enet/ethernet/eth.c +!Einclude/linux/etherdevice.h +!Enet/core/wireless.c Synchronous PPP !Edrivers/net/wan/syncppp.c diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h index 17460c85df7b..5f49a30eb6f2 100644 --- a/include/linux/etherdevice.h +++ b/include/linux/etherdevice.h @@ -48,8 +48,10 @@ static inline void eth_copy_and_sum (struct sk_buff *dest, } /** - * is_zero_ether_addr - Determine if give Ethernet address is all - * zeros. + * is_zero_ether_addr - Determine if give Ethernet address is all zeros. + * @addr: Pointer to a six-byte array containing the Ethernet address + * + * Return true if the address is all zeroes. */ static inline int is_zero_ether_addr(const u8 *addr) { @@ -57,9 +59,7 @@ static inline int is_zero_ether_addr(const u8 *addr) } /** - * is_multicast_ether_addr - Determine if the given Ethernet address is a - * multicast address. - * + * is_multicast_ether_addr - Determine if the Ethernet address is a multicast. * @addr: Pointer to a six-byte array containing the Ethernet address * * Return true if the address is a multicast address. @@ -69,6 +69,12 @@ static inline int is_multicast_ether_addr(const u8 *addr) return ((addr[0] != 0xff) && (0x01 & addr[0])); } +/** + * is_broadcast_ether_addr - Determine if the Ethernet address is broadcast + * @addr: Pointer to a six-byte array containing the Ethernet address + * + * Return true if the address is the broadcast address. + */ static inline int is_broadcast_ether_addr(const u8 *addr) { return (addr[0] & addr[1] & addr[2] & addr[3] & addr[4] & addr[5]) == 0xff; @@ -107,14 +113,14 @@ static inline void random_ether_addr(u8 *addr) /** * compare_ether_addr - Compare two Ethernet addresses * @addr1: Pointer to a six-byte array containing the Ethernet address - * @addr2 Pointer other six-byte array containing the Ethernet address + * @addr2: Pointer other six-byte array containing the Ethernet address * * Compare two ethernet addresses, returns 0 if equal */ -static inline unsigned compare_ether_addr(const u8 *_a, const u8 *_b) +static inline unsigned compare_ether_addr(const u8 *addr1, const u8 *addr2) { - const u16 *a = (const u16 *) _a; - const u16 *b = (const u16 *) _b; + const u16 *a = (const u16 *) addr1; + const u16 *b = (const u16 *) addr2; BUILD_BUG_ON(ETH_ALEN != 6); return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2])) != 0; -- cgit v1.2.3 From 436d7d3060fdeca91d0dd67a9ae21d4915f1410f Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Thu, 3 Nov 2005 13:50:05 +1100 Subject: [XFS] Update XFS quota header license to match the SGI boilerplate. Signed-off-by: Nathan Scott --- include/linux/dqblk_xfs.h | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'include/linux') diff --git a/include/linux/dqblk_xfs.h b/include/linux/dqblk_xfs.h index cb31719ee192..c90997d9cc1e 100644 --- a/include/linux/dqblk_xfs.h +++ b/include/linux/dqblk_xfs.h @@ -1,22 +1,18 @@ /* * Copyright (c) 1995-2001,2004 Silicon Graphics, Inc. All Rights Reserved. * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2.1 of the GNU Lesser General Public License + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - * - * Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane, - * Mountain View, CA 94043, USA, or: http://www.sgi.com + * You should have received a copy of the GNU Lesset General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef _LINUX_DQBLK_XFS_H #define _LINUX_DQBLK_XFS_H -- cgit v1.2.3 From a2f8e178ad3e576d107f5d9d47c056dd57221857 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Thu, 3 Nov 2005 13:51:23 +1100 Subject: [XFS] Add the project quota type into the XFS quota header. Signed-off-by: Nathan Scott --- include/linux/dqblk_xfs.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/dqblk_xfs.h b/include/linux/dqblk_xfs.h index c90997d9cc1e..6ad85bbd0d17 100644 --- a/include/linux/dqblk_xfs.h +++ b/include/linux/dqblk_xfs.h @@ -28,7 +28,8 @@ #define XQM_USRQUOTA 0 /* system call user quota type */ #define XQM_GRPQUOTA 1 /* system call group quota type */ -#define XQM_MAXQUOTAS 2 +#define XQM_PRJQUOTA 2 /* system call project quota type */ +#define XQM_MAXQUOTAS 3 #define Q_XQUOTAON XQM_CMD(1) /* enable accounting/enforcement */ #define Q_XQUOTAOFF XQM_CMD(2) /* disable accounting/enforcement */ -- cgit v1.2.3 From de69e5f44ecbf1d9faca4f473f4210473d26cd41 Mon Sep 17 00:00:00 2001 From: Nathan Scott Date: Thu, 3 Nov 2005 13:53:34 +1100 Subject: [XFS] Add a mechanism for XFS to use the generic quota sync method. This is now used to issue a delayed allocation flush before reporting quota, which allows the used space quota report to match reality. Signed-off-by: Nathan Scott --- fs/quota.c | 8 +++++++- include/linux/dqblk_xfs.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/fs/quota.c b/fs/quota.c index f5d1cff55196..1df7832b4e08 100644 --- a/fs/quota.c +++ b/fs/quota.c @@ -118,6 +118,10 @@ static int xqm_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t i if (!sb->s_qcop->get_xquota) return -ENOSYS; break; + case Q_XQUOTASYNC: + if (!sb->s_qcop->quota_sync) + return -ENOSYS; + break; default: return -EINVAL; } @@ -128,7 +132,7 @@ static int xqm_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t i (type == XQM_GRPQUOTA && !in_egroup_p(id))) && !capable(CAP_SYS_ADMIN)) return -EPERM; - } else if (cmd != Q_XGETQSTAT) { + } else if (cmd != Q_XGETQSTAT && cmd != Q_XQUOTASYNC) { if (!capable(CAP_SYS_ADMIN)) return -EPERM; } @@ -322,6 +326,8 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, void return -EFAULT; return 0; } + case Q_XQUOTASYNC: + return sb->s_qcop->quota_sync(sb, type); /* We never reach here unless validity check is broken */ default: BUG(); diff --git a/include/linux/dqblk_xfs.h b/include/linux/dqblk_xfs.h index 6ad85bbd0d17..2fda1b2aabd9 100644 --- a/include/linux/dqblk_xfs.h +++ b/include/linux/dqblk_xfs.h @@ -37,6 +37,7 @@ #define Q_XSETQLIM XQM_CMD(4) /* set disk limits */ #define Q_XGETQSTAT XQM_CMD(5) /* get quota subsystem status */ #define Q_XQUOTARM XQM_CMD(6) /* free disk space used by dquots */ +#define Q_XQUOTASYNC XQM_CMD(7) /* delalloc flush, updates dquots */ /* * fs_disk_quota structure: -- cgit v1.2.3 From 5f94548982ad8cb9867297e9e18e50ec7b8accea Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Wed, 2 Nov 2005 22:51:46 -0500 Subject: Input: do not register statically allocated devices Do not register statically allocated input devices to prevent OOPS when attaching input interfaces since it requires class device to be properly initialized. Signed-off-by: Dmitry Torokhov --- drivers/input/input.c | 26 +++++++++++++++----------- include/linux/input.h | 2 +- 2 files changed, 16 insertions(+), 12 deletions(-) (limited to 'include/linux') diff --git a/drivers/input/input.c b/drivers/input/input.c index 1a1654caedd5..d543c0ce5229 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -377,7 +377,7 @@ static int input_devices_read(char *buf, char **start, off_t pos, int count, int list_for_each_entry(dev, &input_dev_list, node) { - path = dev->dynalloc ? kobject_get_path(&dev->cdev.kobj, GFP_KERNEL) : NULL; + path = kobject_get_path(&dev->cdev.kobj, GFP_KERNEL); len = sprintf(buf, "I: Bus=%04x Vendor=%04x Product=%04x Version=%04x\n", dev->id.bustype, dev->id.vendor, dev->id.product, dev->id.version); @@ -741,15 +741,21 @@ static void input_register_classdevice(struct input_dev *dev) sysfs_create_group(&dev->cdev.kobj, &input_dev_caps_attr_group); } -void input_register_device(struct input_dev *dev) +int input_register_device(struct input_dev *dev) { struct input_handle *handle; struct input_handler *handler; struct input_device_id *id; - set_bit(EV_SYN, dev->evbit); + if (!dev->dynalloc) { + printk(KERN_WARNING "input: device %s is statically allocated, will not register\n" + "Please convert to input_allocate_device() or contact dtor_core@ameritech.net\n", + dev->name ? dev->name : ""); + return -EINVAL; + } init_MUTEX(&dev->sem); + set_bit(EV_SYN, dev->evbit); /* * If delay and period are pre-set by the driver, then autorepeating @@ -767,8 +773,7 @@ void input_register_device(struct input_dev *dev) INIT_LIST_HEAD(&dev->h_list); list_add_tail(&dev->node, &input_dev_list); - if (dev->dynalloc) - input_register_classdevice(dev); + input_register_classdevice(dev); list_for_each_entry(handler, &input_handler_list, node) if (!handler->blacklist || !input_match_device(handler->blacklist, dev)) @@ -776,8 +781,9 @@ void input_register_device(struct input_dev *dev) if ((handle = handler->connect(handler, dev, id))) input_link_handle(handle); - input_wakeup_procfs_readers(); + + return 0; } void input_unregister_device(struct input_dev *dev) @@ -797,11 +803,9 @@ void input_unregister_device(struct input_dev *dev) list_del_init(&dev->node); - if (dev->dynalloc) { - sysfs_remove_group(&dev->cdev.kobj, &input_dev_caps_attr_group); - sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group); - class_device_unregister(&dev->cdev); - } + sysfs_remove_group(&dev->cdev.kobj, &input_dev_caps_attr_group); + sysfs_remove_group(&dev->cdev.kobj, &input_dev_id_attr_group); + class_device_unregister(&dev->cdev); input_wakeup_procfs_readers(); } diff --git a/include/linux/input.h b/include/linux/input.h index f623c745c21c..3c5823368ddb 100644 --- a/include/linux/input.h +++ b/include/linux/input.h @@ -1007,7 +1007,7 @@ static inline void input_put_device(struct input_dev *dev) class_device_put(&dev->cdev); } -void input_register_device(struct input_dev *); +int input_register_device(struct input_dev *); void input_unregister_device(struct input_dev *); void input_register_handler(struct input_handler *); -- cgit v1.2.3 From d530838bfa507d67b40d13b00d9cbd7a46a47e78 Mon Sep 17 00:00:00 2001 From: Trond Myklebust Date: Fri, 4 Nov 2005 15:33:38 -0500 Subject: NFSv4: Fix problem with OPEN_DOWNGRADE RFC 3530 states that for OPEN_DOWNGRADE "The share_access and share_deny bits specified must be exactly equal to the union of the share_access and share_deny bits specified for some subset of the OPENs in effect for current openowner on the current file. Setattr is currently violating the NFSv4 rules for OPEN_DOWNGRADE in that it may cause a downgrade from OPEN4_SHARE_ACCESS_BOTH to OPEN4_SHARE_ACCESS_WRITE despite the fact that there exists no open file with O_WRONLY access mode. Fix the problem by replacing nfs4_find_state() with a modified version of nfs_find_open_context(). Signed-off-by: Trond Myklebust --- fs/nfs/inode.c | 7 ++++++- fs/nfs/nfs4_fs.h | 1 - fs/nfs/nfs4proc.c | 23 ++++++++++------------- fs/nfs/nfs4state.c | 33 --------------------------------- fs/nfs/read.c | 4 ++-- fs/nfs/write.c | 2 +- include/linux/nfs_fs.h | 2 +- 7 files changed, 20 insertions(+), 52 deletions(-) (limited to 'include/linux') diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index fc0f12ba89cc..24d2fbf549bd 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -1009,13 +1009,18 @@ void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx) spin_unlock(&inode->i_lock); } -struct nfs_open_context *nfs_find_open_context(struct inode *inode, int mode) +/* + * Given an inode, search for an open context with the desired characteristics + */ +struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, int mode) { struct nfs_inode *nfsi = NFS_I(inode); struct nfs_open_context *pos, *ctx = NULL; spin_lock(&inode->i_lock); list_for_each_entry(pos, &nfsi->open_files, list) { + if (cred != NULL && pos->cred != cred) + continue; if ((pos->mode & mode) == mode) { ctx = get_nfs_open_context(pos); break; diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index 53969022d239..b7f262dcb6e3 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -247,7 +247,6 @@ extern void nfs4_drop_state_owner(struct nfs4_state_owner *); extern struct nfs4_state * nfs4_get_open_state(struct inode *, struct nfs4_state_owner *); extern void nfs4_put_open_state(struct nfs4_state *); extern void nfs4_close_state(struct nfs4_state *, mode_t); -extern struct nfs4_state *nfs4_find_state(struct inode *, struct rpc_cred *, mode_t mode); extern void nfs4_state_set_mode_locked(struct nfs4_state *, mode_t); extern void nfs4_schedule_state_recovery(struct nfs4_client *); extern void nfs4_put_lock_state(struct nfs4_lock_state *lsp); diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 02fddd0e27e8..9e492c2261c0 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -214,7 +214,7 @@ static void update_open_stateid(struct nfs4_state *state, nfs4_stateid *stateid, struct inode *inode = state->inode; open_flags &= (FMODE_READ|FMODE_WRITE); - /* Protect against nfs4_find_state() */ + /* Protect against nfs4_find_state_byowner() */ spin_lock(&state->owner->so_lock); spin_lock(&inode->i_lock); memcpy(&state->stateid, stateid, sizeof(state->stateid)); @@ -1274,7 +1274,8 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, { struct rpc_cred *cred; struct inode *inode = dentry->d_inode; - struct nfs4_state *state; + struct nfs_open_context *ctx; + struct nfs4_state *state = NULL; int status; nfs_fattr_init(fattr); @@ -1282,22 +1283,18 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, cred = rpcauth_lookupcred(NFS_SERVER(inode)->client->cl_auth, 0); if (IS_ERR(cred)) return PTR_ERR(cred); - /* Search for an existing WRITE delegation first */ - state = nfs4_open_delegated(inode, FMODE_WRITE, cred); - if (!IS_ERR(state)) { - /* NB: nfs4_open_delegated() bumps the inode->i_count */ - iput(inode); - } else { - /* Search for an existing open(O_WRITE) stateid */ - state = nfs4_find_state(inode, cred, FMODE_WRITE); - } + + /* Search for an existing open(O_WRITE) file */ + ctx = nfs_find_open_context(inode, cred, FMODE_WRITE); + if (ctx != NULL) + state = ctx->state; status = nfs4_do_setattr(NFS_SERVER(inode), fattr, NFS_FH(inode), sattr, state); if (status == 0) nfs_setattr_update_inode(inode, sattr); - if (state != NULL) - nfs4_close_state(state, FMODE_WRITE); + if (ctx != NULL) + put_nfs_open_context(ctx); put_rpccred(cred); return status; } diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index 959374d833a7..81d964bfd8a7 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -383,28 +383,6 @@ nfs4_state_set_mode_locked(struct nfs4_state *state, mode_t mode) state->state = mode; } -static struct nfs4_state * -__nfs4_find_state(struct inode *inode, struct rpc_cred *cred, mode_t mode) -{ - struct nfs_inode *nfsi = NFS_I(inode); - struct nfs4_state *state; - - mode &= (FMODE_READ|FMODE_WRITE); - list_for_each_entry(state, &nfsi->open_states, inode_states) { - if (state->owner->so_cred != cred) - continue; - if ((state->state & mode) != mode) - continue; - atomic_inc(&state->count); - if (mode & FMODE_READ) - state->nreaders++; - if (mode & FMODE_WRITE) - state->nwriters++; - return state; - } - return NULL; -} - static struct nfs4_state * __nfs4_find_state_byowner(struct inode *inode, struct nfs4_state_owner *owner) { @@ -423,17 +401,6 @@ __nfs4_find_state_byowner(struct inode *inode, struct nfs4_state_owner *owner) return NULL; } -struct nfs4_state * -nfs4_find_state(struct inode *inode, struct rpc_cred *cred, mode_t mode) -{ - struct nfs4_state *state; - - spin_lock(&inode->i_lock); - state = __nfs4_find_state(inode, cred, mode); - spin_unlock(&inode->i_lock); - return state; -} - static void nfs4_free_open_state(struct nfs4_state *state) { diff --git a/fs/nfs/read.c b/fs/nfs/read.c index 43b03b19731b..5f20eafba8ec 100644 --- a/fs/nfs/read.c +++ b/fs/nfs/read.c @@ -507,7 +507,7 @@ int nfs_readpage(struct file *file, struct page *page) goto out_error; if (file == NULL) { - ctx = nfs_find_open_context(inode, FMODE_READ); + ctx = nfs_find_open_context(inode, NULL, FMODE_READ); if (ctx == NULL) return -EBADF; } else @@ -576,7 +576,7 @@ int nfs_readpages(struct file *filp, struct address_space *mapping, nr_pages); if (filp == NULL) { - desc.ctx = nfs_find_open_context(inode, FMODE_READ); + desc.ctx = nfs_find_open_context(inode, NULL, FMODE_READ); if (desc.ctx == NULL) return -EBADF; } else diff --git a/fs/nfs/write.c b/fs/nfs/write.c index 819a65f5071f..1bdbd4f9fdd2 100644 --- a/fs/nfs/write.c +++ b/fs/nfs/write.c @@ -294,7 +294,7 @@ int nfs_writepage(struct page *page, struct writeback_control *wbc) if (page->index >= end_index+1 || !offset) goto out; do_it: - ctx = nfs_find_open_context(inode, FMODE_WRITE); + ctx = nfs_find_open_context(inode, NULL, FMODE_WRITE); if (ctx == NULL) { err = -EBADF; goto out; diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 325fe7ae49bb..12787a9b0259 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -316,7 +316,7 @@ extern struct nfs_open_context *alloc_nfs_open_context(struct dentry *dentry, st extern struct nfs_open_context *get_nfs_open_context(struct nfs_open_context *ctx); extern void put_nfs_open_context(struct nfs_open_context *ctx); extern void nfs_file_set_open_context(struct file *filp, struct nfs_open_context *ctx); -extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, int mode); +extern struct nfs_open_context *nfs_find_open_context(struct inode *inode, struct rpc_cred *cred, int mode); extern void nfs_file_clear_open_context(struct file *filp); /* linux/net/ipv4/ipconfig.c: trims ip addr off front of name, too. */ -- cgit v1.2.3 From 7015faa7df829876a0f931cd18aa6d7c24a1b581 Mon Sep 17 00:00:00 2001 From: "Calin A. Culianu" Date: Fri, 4 Nov 2005 20:38:04 -0500 Subject: [PATCH] nvidiafb: Geforce 7800 series support added This adds support for the Nvidia Geforce 7800 series of cards to the nvidiafb framebuffer driver. All it does is add the PCI device id for the 7800, 7800 GTX, 7800 GO, and 7800 GTX GO cards to the module device table for the nvidiafb.ko driver, so that nvidiafb.ko will actually work on these cards. I also added the relevant PCI device ids to linux/pci_ids.h I tested it on my 7800 GTX here and it works like a charm. I now can get framebuffer support on this card! Woo hoo!! Nothing like 200x75 text mode to make your eyes BLEED. ;) Signed-off-by: Linus Torvalds --- drivers/video/nvidia/nvidia.c | 8 ++++++++ include/linux/pci_ids.h | 4 ++++ 2 files changed, 12 insertions(+) (limited to 'include/linux') diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index a7f020ada630..308defc389a2 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -384,6 +384,14 @@ static struct pci_device_id nvidiafb_pci_tbl[] = { PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_6800B_GT, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GT, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GTX, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800_GTX, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NVIDIA, 0x021d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_NVIDIA, 0x021e, diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 56192005fa4d..88de3f8ce1a2 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -990,6 +990,10 @@ #define PCI_DEVICE_ID_NVIDIA_CK8_AUDIO 0x008a #define PCI_DEVICE_ID_NVIDIA_NVENET_5 0x008c #define PCI_DEVICE_ID_NVIDIA_NFORCE2S_SATA 0x008e +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GT 0x0090 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_7800_GTX 0x0091 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800 0x0098 +#define PCI_DEVICE_ID_NVIDIA_GEFORCE_GO_7800_GTX 0x0099 #define PCI_DEVICE_ID_NVIDIA_ITNT2 0x00A0 #define PCI_DEVICE_ID_GEFORCE_6800A 0x00c1 #define PCI_DEVICE_ID_GEFORCE_6800A_LE 0x00c2 -- cgit v1.2.3 From 6037d6bbdff65eb5a84fe35e140f4da4f7cc103a Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 4 Nov 2005 22:08:00 -0500 Subject: [libata] ATAPI pad allocation fixes/cleanup Use ata_pad_{alloc,free} in two drivers, to factor out common code. Add ata_pad_{alloc,free} to two other drivers, which needed the padding but had not been updated. --- drivers/scsi/ahci.c | 11 ++++++----- drivers/scsi/libata-core.c | 9 +++++---- drivers/scsi/sata_mv.c | 31 +++++++++++++++++++++++-------- drivers/scsi/sata_sil24.c | 33 ++++++++++++++++++++++++--------- include/linux/libata.h | 13 +++++++++++++ 5 files changed, 71 insertions(+), 26 deletions(-) (limited to 'include/linux') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 8420204c2eaa..4612312c0c2d 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -307,21 +307,22 @@ static int ahci_port_start(struct ata_port *ap) void __iomem *port_mmio = ahci_port_base(mmio, ap->port_no); void *mem; dma_addr_t mem_dma; + int rc; pp = kmalloc(sizeof(*pp), GFP_KERNEL); if (!pp) return -ENOMEM; memset(pp, 0, sizeof(*pp)); - ap->pad = dma_alloc_coherent(dev, ATA_DMA_PAD_BUF_SZ, &ap->pad_dma, GFP_KERNEL); - if (!ap->pad) { + rc = ata_pad_alloc(ap, dev); + if (rc) { kfree(pp); - return -ENOMEM; + return rc; } mem = dma_alloc_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL); if (!mem) { - dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma); + ata_pad_free(ap, dev); kfree(pp); return -ENOMEM; } @@ -397,7 +398,7 @@ static void ahci_port_stop(struct ata_port *ap) ap->private_data = NULL; dma_free_coherent(dev, AHCI_PORT_PRIV_DMA_SZ, pp->cmd_slot, pp->cmd_slot_dma); - dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma); + ata_pad_free(ap, dev); kfree(pp); } diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index ae2475e4291c..e1346cddd37f 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -4091,15 +4091,16 @@ err_out: int ata_port_start (struct ata_port *ap) { struct device *dev = ap->host_set->dev; + int rc; ap->prd = dma_alloc_coherent(dev, ATA_PRD_TBL_SZ, &ap->prd_dma, GFP_KERNEL); if (!ap->prd) return -ENOMEM; - ap->pad = dma_alloc_coherent(dev, ATA_DMA_PAD_BUF_SZ, &ap->pad_dma, GFP_KERNEL); - if (!ap->pad) { + rc = ata_pad_alloc(ap, dev); + if (rc) { dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma); - return -ENOMEM; + return rc; } DPRINTK("prd alloc, virt %p, dma %llx\n", ap->prd, (unsigned long long) ap->prd_dma); @@ -4125,7 +4126,7 @@ void ata_port_stop (struct ata_port *ap) struct device *dev = ap->host_set->dev; dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma); - dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma); + ata_pad_free(ap, dev); } void ata_host_stop (struct ata_host_set *host_set) diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 64af334e71f4..0f469e3dabe2 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -670,6 +670,11 @@ static void mv_host_stop(struct ata_host_set *host_set) ata_host_stop(host_set); } +static inline void mv_priv_free(struct mv_port_priv *pp, struct device *dev) +{ + dma_free_coherent(dev, MV_PORT_PRIV_DMA_SZ, pp->crpb, pp->crpb_dma); +} + /** * mv_port_start - Port specific init/start routine. * @ap: ATA channel to manipulate @@ -687,21 +692,23 @@ static int mv_port_start(struct ata_port *ap) void __iomem *port_mmio = mv_ap_base(ap); void *mem; dma_addr_t mem_dma; + int rc = -ENOMEM; pp = kmalloc(sizeof(*pp), GFP_KERNEL); - if (!pp) { - return -ENOMEM; - } + if (!pp) + goto err_out; memset(pp, 0, sizeof(*pp)); mem = dma_alloc_coherent(dev, MV_PORT_PRIV_DMA_SZ, &mem_dma, GFP_KERNEL); - if (!mem) { - kfree(pp); - return -ENOMEM; - } + if (!mem) + goto err_out_pp; memset(mem, 0, MV_PORT_PRIV_DMA_SZ); + rc = ata_pad_alloc(ap, dev); + if (rc) + goto err_out_priv; + /* First item in chunk of DMA memory: * 32-slot command request table (CRQB), 32 bytes each in size */ @@ -746,6 +753,13 @@ static int mv_port_start(struct ata_port *ap) */ ap->private_data = pp; return 0; + +err_out_priv: + mv_priv_free(pp, dev); +err_out_pp: + kfree(pp); +err_out: + return rc; } /** @@ -768,7 +782,8 @@ static void mv_port_stop(struct ata_port *ap) spin_unlock_irqrestore(&ap->host_set->lock, flags); ap->private_data = NULL; - dma_free_coherent(dev, MV_PORT_PRIV_DMA_SZ, pp->crpb, pp->crpb_dma); + ata_pad_free(ap, dev); + mv_priv_free(pp, dev); kfree(pp); } diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index 211ec7eebc9c..e6c8e89c226f 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -635,6 +635,13 @@ static irqreturn_t sil24_interrupt(int irq, void *dev_instance, struct pt_regs * return IRQ_RETVAL(handled); } +static inline void sil24_cblk_free(struct sil24_port_priv *pp, struct device *dev) +{ + const size_t cb_size = sizeof(*pp->cmd_block); + + dma_free_coherent(dev, cb_size, pp->cmd_block, pp->cmd_block_dma); +} + static int sil24_port_start(struct ata_port *ap) { struct device *dev = ap->host_set->dev; @@ -642,36 +649,44 @@ static int sil24_port_start(struct ata_port *ap) struct sil24_cmd_block *cb; size_t cb_size = sizeof(*cb); dma_addr_t cb_dma; + int rc = -ENOMEM; - pp = kmalloc(sizeof(*pp), GFP_KERNEL); + pp = kzalloc(sizeof(*pp), GFP_KERNEL); if (!pp) - return -ENOMEM; - memset(pp, 0, sizeof(*pp)); + goto err_out; pp->tf.command = ATA_DRDY; cb = dma_alloc_coherent(dev, cb_size, &cb_dma, GFP_KERNEL); - if (!cb) { - kfree(pp); - return -ENOMEM; - } + if (!cb) + goto err_out_pp; memset(cb, 0, cb_size); + rc = ata_pad_alloc(ap, dev); + if (rc) + goto err_out_pad; + pp->cmd_block = cb; pp->cmd_block_dma = cb_dma; ap->private_data = pp; return 0; + +err_out_pad: + sil24_cblk_free(pp, dev); +err_out_pp: + kfree(pp); +err_out: + return rc; } static void sil24_port_stop(struct ata_port *ap) { struct device *dev = ap->host_set->dev; struct sil24_port_priv *pp = ap->private_data; - size_t cb_size = sizeof(*pp->cmd_block); - dma_free_coherent(dev, cb_size, pp->cmd_block, pp->cmd_block_dma); + sil24_cblk_free(pp, dev); kfree(pp); } diff --git a/include/linux/libata.h b/include/linux/libata.h index 6225b78fa65b..dcd17e7458ab 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -777,4 +777,17 @@ static inline unsigned int __ac_err_mask(u8 status) return mask; } +static inline int ata_pad_alloc(struct ata_port *ap, struct device *dev) +{ + ap->pad_dma = 0; + ap->pad = dma_alloc_coherent(dev, ATA_DMA_PAD_BUF_SZ, + &ap->pad_dma, GFP_KERNEL); + return (ap->pad == NULL) ? -ENOMEM : 0; +} + +static inline void ata_pad_free(struct ata_port *ap, struct device *dev) +{ + dma_free_coherent(dev, ATA_DMA_PAD_BUF_SZ, ap->pad, ap->pad_dma); +} + #endif /* __LINUX_LIBATA_H__ */ -- cgit v1.2.3 From f896424cbc61225e8f029fe23e5aae3e32103229 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Wed, 2 Nov 2005 16:13:06 -0700 Subject: [PATCH] phy address mask support for generic phy layer Adds a phy_mask field to struct mii_bus and uses it. This field indicates each phy address to be ignored when probing the mdio bus. This support is needed for the fs_enet and ibm_emac drivers to be converted to the generic phy layer among other drivers. Many systems lock up on probing certain phy addresses or probing doesn't return 0xffff when nothing is found at the address. A new driver I'm working on also makes use of this mask. Signed-off-by: Matt Porter Signed-off-by: Jeff Garzik --- drivers/net/phy/mdio_bus.c | 3 +++ include/linux/phy.h | 3 +++ 2 files changed, 6 insertions(+) (limited to 'include/linux') diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index ad93b0da87f0..5eab9c42a111 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -61,6 +61,9 @@ int mdiobus_register(struct mii_bus *bus) for (i = 0; i < PHY_MAX_ADDR; i++) { struct phy_device *phydev; + if (bus->phy_mask & (1 << i)) + continue; + phydev = get_phy_device(bus, i); if (IS_ERR(phydev)) diff --git a/include/linux/phy.h b/include/linux/phy.h index 72cb67b66e0c..92a9696fdebe 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -72,6 +72,9 @@ struct mii_bus { /* list of all PHYs on bus */ struct phy_device *phy_map[PHY_MAX_ADDR]; + /* Phy addresses to be ignored when probing */ + u32 phy_mask; + /* Pointer to an array of interrupts, each PHY's * interrupt at the index matching its address */ int *irq; -- cgit v1.2.3 From 1e4dfaf9b99a8b652e8421936fd5fe2459da8265 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:25 +0100 Subject: [PKT_SCHED]: GRED: Cleanup and remove unnecessary code Removes unnecessary includes, initializers, and simplifies the code a bit. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- include/linux/pkt_sched.h | 48 ++++++++++------------ net/sched/sch_gred.c | 100 ++++++++++++++-------------------------------- 2 files changed, 53 insertions(+), 95 deletions(-) (limited to 'include/linux') diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index 60ffcb9c5791..d053add3dca7 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -194,38 +194,34 @@ enum #define TCA_GRED_MAX (__TCA_GRED_MAX - 1) -#define TCA_SET_OFF TCA_GRED_PARMS struct tc_gred_qopt { - __u32 limit; /* HARD maximal queue length (bytes) -*/ - __u32 qth_min; /* Min average length threshold (bytes) -*/ - __u32 qth_max; /* Max average length threshold (bytes) -*/ - __u32 DP; /* upto 2^32 DPs */ - __u32 backlog; - __u32 qave; - __u32 forced; - __u32 early; - __u32 other; - __u32 pdrop; - - unsigned char Wlog; /* log(W) */ - unsigned char Plog; /* log(P_max/(qth_max-qth_min)) */ - unsigned char Scell_log; /* cell size for idle damping */ - __u8 prio; /* prio of this VQ */ - __u32 packets; - __u32 bytesin; + __u32 limit; /* HARD maximal queue length (bytes) */ + __u32 qth_min; /* Min average length threshold (bytes) */ + __u32 qth_max; /* Max average length threshold (bytes) */ + __u32 DP; /* upto 2^32 DPs */ + __u32 backlog; + __u32 qave; + __u32 forced; + __u32 early; + __u32 other; + __u32 pdrop; + __u8 Wlog; /* log(W) */ + __u8 Plog; /* log(P_max/(qth_max-qth_min)) */ + __u8 Scell_log; /* cell size for idle damping */ + __u8 prio; /* prio of this VQ */ + __u32 packets; + __u32 bytesin; }; + /* gred setup */ struct tc_gred_sopt { - __u32 DPs; - __u32 def_DP; - __u8 grio; - __u8 pad1; - __u16 pad2; + __u32 DPs; + __u32 def_DP; + __u8 grio; + __u8 pad1; + __u16 pad2; }; /* HTB section */ diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 897e6df81b1f..1fb34be32f7c 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -15,50 +15,18 @@ * from Ren Liu * - More error checks * - * - * - * For all the glorious comments look at Alexey's sch_red.c + * For all the glorious comments look at include/net/red.h */ #include #include -#include -#include -#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include #include -#include #include #include -#if 1 /* control */ -#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args) -#else -#define DPRINTK(format,args...) -#endif - -#if 0 /* data */ -#define D2PRINTK(format,args...) printk(KERN_DEBUG format,##args) -#else -#define D2PRINTK(format,args...) -#endif - #define GRED_DEF_PRIO (MAX_DPs / 2) #define GRED_VQ_MASK (MAX_DPs - 1) @@ -72,7 +40,7 @@ struct gred_sched_data u32 bytesin; /* bytes seen on virtualQ so far*/ u32 packetsin; /* packets seen on virtualQ so far*/ u32 backlog; /* bytes on the virtualQ */ - u8 prio; /* the prio of this vq */ + u8 prio; /* the prio of this vq */ struct red_parms parms; struct red_stats stats; @@ -87,8 +55,8 @@ struct gred_sched { struct gred_sched_data *tab[MAX_DPs]; unsigned long flags; - u32 DPs; - u32 def; + u32 DPs; + u32 def; struct red_parms wred_set; }; @@ -172,13 +140,11 @@ static inline void gred_store_wred_set(struct gred_sched *table, table->wred_set.qavg = q->parms.qavg; } -static int -gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) +static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) { struct gred_sched_data *q=NULL; struct gred_sched *t= qdisc_priv(sch); unsigned long qavg = 0; - int i=0; u16 dp = tc_index_to_dp(skb); if (dp >= t->DPs || (q = t->tab[dp]) == NULL) { @@ -200,26 +166,23 @@ gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) skb->tc_index = (skb->tc_index & ~GRED_VQ_MASK) | dp; } - /* sum up all the qaves of prios <= to ours to get the new qave*/ + /* sum up all the qaves of prios <= to ours to get the new qave */ if (!gred_wred_mode(t) && gred_rio_mode(t)) { - for (i=0;iDPs;i++) { - if ((!t->tab[i]) || (i==q->DP)) - continue; - - if (t->tab[i]->prio < q->prio && + int i; + + for (i = 0; i < t->DPs; i++) { + if (t->tab[i] && t->tab[i]->prio < q->prio && !red_is_idling(&t->tab[i]->parms)) qavg +=t->tab[i]->parms.qavg; } - + } q->packetsin++; - q->bytesin+=skb->len; + q->bytesin += skb->len; - if (gred_wred_mode(t)) { - qavg = 0; + if (gred_wred_mode(t)) gred_load_wred_set(t, q); - } q->parms.qavg = red_calc_qavg(&q->parms, gred_backlog(t, q, sch)); @@ -258,8 +221,7 @@ congestion_drop: return NET_XMIT_CN; } -static int -gred_requeue(struct sk_buff *skb, struct Qdisc* sch) +static int gred_requeue(struct sk_buff *skb, struct Qdisc* sch) { struct gred_sched *t = qdisc_priv(sch); struct gred_sched_data *q; @@ -279,16 +241,15 @@ gred_requeue(struct sk_buff *skb, struct Qdisc* sch) return qdisc_requeue(skb, sch); } -static struct sk_buff * -gred_dequeue(struct Qdisc* sch) +static struct sk_buff *gred_dequeue(struct Qdisc* sch) { struct sk_buff *skb; - struct gred_sched_data *q; - struct gred_sched *t= qdisc_priv(sch); + struct gred_sched *t = qdisc_priv(sch); skb = qdisc_dequeue_head(sch); if (skb) { + struct gred_sched_data *q; u16 dp = tc_index_to_dp(skb); if (dp >= t->DPs || (q = t->tab[dp]) == NULL) { @@ -315,13 +276,12 @@ gred_dequeue(struct Qdisc* sch) static unsigned int gred_drop(struct Qdisc* sch) { struct sk_buff *skb; - - struct gred_sched_data *q; - struct gred_sched *t= qdisc_priv(sch); + struct gred_sched *t = qdisc_priv(sch); skb = qdisc_dequeue_tail(sch); if (skb) { unsigned int len = skb->len; + struct gred_sched_data *q; u16 dp = tc_index_to_dp(skb); if (dp >= t->DPs || (q = t->tab[dp]) == NULL) { @@ -351,15 +311,16 @@ static unsigned int gred_drop(struct Qdisc* sch) static void gred_reset(struct Qdisc* sch) { int i; - struct gred_sched_data *q; - struct gred_sched *t= qdisc_priv(sch); + struct gred_sched *t = qdisc_priv(sch); qdisc_reset_queue(sch); - for (i=0;iDPs;i++) { - q= t->tab[i]; - if (!q) - continue; + for (i = 0; i < t->DPs; i++) { + struct gred_sched_data *q = t->tab[i]; + + if (!q) + continue; + red_restart(&q->parms); q->backlog = 0; } @@ -590,15 +551,13 @@ static void gred_destroy(struct Qdisc *sch) struct gred_sched *table = qdisc_priv(sch); int i; - for (i = 0;i < table->DPs; i++) { + for (i = 0; i < table->DPs; i++) { if (table->tab[i]) gred_destroy_vq(table->tab[i]); } } static struct Qdisc_ops gred_qdisc_ops = { - .next = NULL, - .cl_ops = NULL, .id = "gred", .priv_size = sizeof(struct gred_sched), .enqueue = gred_enqueue, @@ -617,10 +576,13 @@ static int __init gred_module_init(void) { return register_qdisc(&gred_qdisc_ops); } -static void __exit gred_module_exit(void) + +static void __exit gred_module_exit(void) { unregister_qdisc(&gred_qdisc_ops); } + module_init(gred_module_init) module_exit(gred_module_exit) + MODULE_LICENSE("GPL"); -- cgit v1.2.3 From b38c7eef7e536d12051cc3d5864032f2f907cdfe Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:27 +0100 Subject: [PKT_SCHED]: GRED: Support ECN marking Adds a new u8 flags in a unused padding area of the netlink message. Adds ECN marking support to be used instead of dropping packets immediately. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- include/linux/pkt_sched.h | 4 ++-- net/sched/sch_gred.c | 25 +++++++++++++++++++++---- 2 files changed, 23 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index d053add3dca7..0ebe320223e2 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -220,8 +220,8 @@ struct tc_gred_sopt __u32 DPs; __u32 def_DP; __u8 grio; - __u8 pad1; - __u16 pad2; + __u8 flags; + __u16 pad1; }; /* HTB section */ diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 69f0fd45d4c3..079b0a4ea1c2 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -55,6 +55,7 @@ struct gred_sched { struct gred_sched_data *tab[MAX_DPs]; unsigned long flags; + u32 red_flags; u32 DPs; u32 def; struct red_parms wred_set; @@ -140,6 +141,11 @@ static inline void gred_store_wred_set(struct gred_sched *table, table->wred_set.qavg = q->parms.qavg; } +static inline int gred_use_ecn(struct gred_sched *t) +{ + return t->red_flags & TC_RED_ECN; +} + static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) { struct gred_sched_data *q=NULL; @@ -198,13 +204,22 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) case RED_PROB_MARK: sch->qstats.overlimits++; - q->stats.prob_drop++; - goto congestion_drop; + if (!gred_use_ecn(t) || !INET_ECN_set_ce(skb)) { + q->stats.prob_drop++; + goto congestion_drop; + } + + q->stats.prob_mark++; + break; case RED_HARD_MARK: sch->qstats.overlimits++; - q->stats.forced_drop++; - goto congestion_drop; + if (!gred_use_ecn(t) || !INET_ECN_set_ce(skb)) { + q->stats.forced_drop++; + goto congestion_drop; + } + q->stats.forced_mark++; + break; } if (q->backlog + skb->len <= q->limit) { @@ -348,6 +363,7 @@ static inline int gred_change_table_def(struct Qdisc *sch, struct rtattr *dps) sch_tree_lock(sch); table->DPs = sopt->DPs; table->def = sopt->def_DP; + table->red_flags = sopt->flags; /* * Every entry point to GRED is synchronized with the above code @@ -489,6 +505,7 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb) .DPs = table->DPs, .def_DP = table->def, .grio = gred_rio_mode(table), + .flags = table->red_flags, }; opts = RTA_NEST(skb, TCA_OPTIONS); -- cgit v1.2.3 From bdc450a0bb1d48144ced1f899cc8366ec8e85024 Mon Sep 17 00:00:00 2001 From: Thomas Graf Date: Sat, 5 Nov 2005 21:14:28 +0100 Subject: [PKT_SCHED]: (G)RED: Introduce hard dropping Introduces a new flag TC_RED_HARDDROP which specifies that if ECN marking is enabled packets should still be dropped once the average queue length exceeds the maximum threshold. This _may_ help to avoid global synchronisation during small bursts of peers advertising but not caring about ECN. Use this option very carefully, it does more harm than good if (qth_max - qth_min) does not cover at least two average burst cycles. The difference to the current behaviour, in which we'd run into the hard queue limit, is that due to the low pass filter of RED short bursts are less likely to cause a global synchronisation. Signed-off-by: Thomas Graf Signed-off-by: Arnaldo Carvalho de Melo --- include/linux/pkt_sched.h | 2 ++ net/sched/sch_gred.c | 8 +++++++- net/sched/sch_red.c | 8 +++++++- 3 files changed, 16 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/pkt_sched.h b/include/linux/pkt_sched.h index 0ebe320223e2..e87b233615b3 100644 --- a/include/linux/pkt_sched.h +++ b/include/linux/pkt_sched.h @@ -93,6 +93,7 @@ struct tc_fifo_qopt /* PRIO section */ #define TCQ_PRIO_BANDS 16 +#define TCQ_MIN_PRIO_BANDS 2 struct tc_prio_qopt { @@ -169,6 +170,7 @@ struct tc_red_qopt unsigned char Scell_log; /* cell size for idle damping */ unsigned char flags; #define TC_RED_ECN 1 +#define TC_RED_HARDDROP 2 }; struct tc_red_xstats diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c index 079b0a4ea1c2..29a2dd9f3029 100644 --- a/net/sched/sch_gred.c +++ b/net/sched/sch_gred.c @@ -146,6 +146,11 @@ static inline int gred_use_ecn(struct gred_sched *t) return t->red_flags & TC_RED_ECN; } +static inline int gred_use_harddrop(struct gred_sched *t) +{ + return t->red_flags & TC_RED_HARDDROP; +} + static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) { struct gred_sched_data *q=NULL; @@ -214,7 +219,8 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc* sch) case RED_HARD_MARK: sch->qstats.overlimits++; - if (!gred_use_ecn(t) || !INET_ECN_set_ce(skb)) { + if (gred_use_harddrop(t) || !gred_use_ecn(t) || + !INET_ECN_set_ce(skb)) { q->stats.forced_drop++; goto congestion_drop; } diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c index 0d89dee751a9..dccfa44c2d71 100644 --- a/net/sched/sch_red.c +++ b/net/sched/sch_red.c @@ -51,6 +51,11 @@ static inline int red_use_ecn(struct red_sched_data *q) return q->flags & TC_RED_ECN; } +static inline int red_use_harddrop(struct red_sched_data *q) +{ + return q->flags & TC_RED_HARDDROP; +} + static int red_enqueue(struct sk_buff *skb, struct Qdisc* sch) { struct red_sched_data *q = qdisc_priv(sch); @@ -76,7 +81,8 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc* sch) case RED_HARD_MARK: sch->qstats.overlimits++; - if (!red_use_ecn(q) || !INET_ECN_set_ce(skb)) { + if (red_use_harddrop(q) || !red_use_ecn(q) || + !INET_ECN_set_ce(skb)) { q->stats.forced_drop++; goto congestion_drop; } -- cgit v1.2.3 From 37c12e7497b6fe2b6a890814f0ff4edce696d862 Mon Sep 17 00:00:00 2001 From: Russell King Date: Sat, 5 Nov 2005 21:19:33 +0000 Subject: [DRIVER MODEL] Improved dynamically allocated platform_device interface Re-jig the simple platform device support to allow private data to be attached to a platform device, as well as allowing the parent device to be set. Example usage: pdev = platform_device_alloc("mydev", id); if (pdev) { err = platform_device_add_resources(pdev, &resources, ARRAY_SIZE(resources)); if (err == 0) err = platform_device_add_data(pdev, &platform_data, sizeof(platform_data)); if (err == 0) err = platform_device_add(pdev); } else { err = -ENOMEM; } if (err) platform_device_put(pdev); Signed-off-by: Russell King Acked-by: Greg Kroah-Hartman --- drivers/base/platform.c | 153 +++++++++++++++++++++++++++++++++------- include/linux/platform_device.h | 6 ++ 2 files changed, 132 insertions(+), 27 deletions(-) (limited to 'include/linux') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index d597c922af11..6d4736e89f1a 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -116,12 +116,115 @@ int platform_add_devices(struct platform_device **devs, int num) return ret; } +struct platform_object { + struct platform_device pdev; + char name[1]; +}; + /** - * platform_device_register - add a platform-level device + * platform_device_put + * @pdev: platform device to free + * + * Free all memory associated with a platform device. This function + * must _only_ be externally called in error cases. All other usage + * is a bug. + */ +void platform_device_put(struct platform_device *pdev) +{ + if (pdev) + put_device(&pdev->dev); +} +EXPORT_SYMBOL_GPL(platform_device_put); + +static void platform_device_release(struct device *dev) +{ + struct platform_object *pa = container_of(dev, struct platform_object, pdev.dev); + + kfree(pa->pdev.dev.platform_data); + kfree(pa->pdev.resource); + kfree(pa); +} + +/** + * platform_device_alloc + * @name: base name of the device we're adding + * @id: instance id + * + * Create a platform device object which can have other objects attached + * to it, and which will have attached objects freed when it is released. + */ +struct platform_device *platform_device_alloc(const char *name, unsigned int id) +{ + struct platform_object *pa; + + pa = kzalloc(sizeof(struct platform_object) + strlen(name), GFP_KERNEL); + if (pa) { + strcpy(pa->name, name); + pa->pdev.name = pa->name; + pa->pdev.id = id; + device_initialize(&pa->pdev.dev); + pa->pdev.dev.release = platform_device_release; + } + + return pa ? &pa->pdev : NULL; +} +EXPORT_SYMBOL_GPL(platform_device_alloc); + +/** + * platform_device_add_resources + * @pdev: platform device allocated by platform_device_alloc to add resources to + * @res: set of resources that needs to be allocated for the device + * @num: number of resources + * + * Add a copy of the resources to the platform device. The memory + * associated with the resources will be freed when the platform + * device is released. + */ +int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num) +{ + struct resource *r; + + r = kmalloc(sizeof(struct resource) * num, GFP_KERNEL); + if (r) { + memcpy(r, res, sizeof(struct resource) * num); + pdev->resource = r; + pdev->num_resources = num; + } + return r ? 0 : -ENOMEM; +} +EXPORT_SYMBOL_GPL(platform_device_add_resources); + +/** + * platform_device_add_data + * @pdev: platform device allocated by platform_device_alloc to add resources to + * @data: platform specific data for this platform device + * @size: size of platform specific data + * + * Add a copy of platform specific data to the platform device's platform_data + * pointer. The memory associated with the platform data will be freed + * when the platform device is released. + */ +int platform_device_add_data(struct platform_device *pdev, void *data, size_t size) +{ + void *d; + + d = kmalloc(size, GFP_KERNEL); + if (d) { + memcpy(d, data, size); + pdev->dev.platform_data = d; + } + return d ? 0 : -ENOMEM; +} +EXPORT_SYMBOL_GPL(platform_device_add_data); + +/** + * platform_device_add - add a platform device to device hierarchy * @pdev: platform device we're adding * + * This is part 2 of platform_device_register(), though may be called + * separately _iff_ pdev was allocated by platform_device_alloc(). */ -int platform_device_register(struct platform_device * pdev) +int platform_device_add(struct platform_device *pdev) { int i, ret = 0; @@ -174,6 +277,18 @@ int platform_device_register(struct platform_device * pdev) release_resource(&pdev->resource[i]); return ret; } +EXPORT_SYMBOL_GPL(platform_device_add); + +/** + * platform_device_register - add a platform-level device + * @pdev: platform device we're adding + * + */ +int platform_device_register(struct platform_device * pdev) +{ + device_initialize(&pdev->dev); + return platform_device_add(pdev); +} /** * platform_device_unregister - remove a platform-level device @@ -197,18 +312,6 @@ void platform_device_unregister(struct platform_device * pdev) } } -struct platform_object { - struct platform_device pdev; - struct resource resources[0]; -}; - -static void platform_device_release_simple(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - - kfree(container_of(pdev, struct platform_object, pdev)); -} - /** * platform_device_register_simple * @name: base name of the device we're adding @@ -225,33 +328,29 @@ static void platform_device_release_simple(struct device *dev) struct platform_device *platform_device_register_simple(char *name, unsigned int id, struct resource *res, unsigned int num) { - struct platform_object *pobj; + struct platform_device *pdev; int retval; - pobj = kzalloc(sizeof(*pobj) + sizeof(struct resource) * num, GFP_KERNEL); - if (!pobj) { + pdev = platform_device_alloc(name, id); + if (!pdev) { retval = -ENOMEM; goto error; } - pobj->pdev.name = name; - pobj->pdev.id = id; - pobj->pdev.dev.release = platform_device_release_simple; - if (num) { - memcpy(pobj->resources, res, sizeof(struct resource) * num); - pobj->pdev.resource = pobj->resources; - pobj->pdev.num_resources = num; + retval = platform_device_add_resources(pdev, res, num); + if (retval) + goto error; } - retval = platform_device_register(&pobj->pdev); + retval = platform_device_add(pdev); if (retval) goto error; - return &pobj->pdev; + return pdev; error: - kfree(pobj); + platform_device_put(pdev); return ERR_PTR(retval); } diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index a726225e0afe..1a165b7ae01b 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -37,4 +37,10 @@ extern int platform_add_devices(struct platform_device **, int); extern struct platform_device *platform_device_register_simple(char *, unsigned int, struct resource *, unsigned int); +extern struct platform_device *platform_device_alloc(const char *name, unsigned int id); +extern int platform_device_add_resources(struct platform_device *pdev, struct resource *res, unsigned int num); +extern int platform_device_add_data(struct platform_device *pdev, void *data, size_t size); +extern int platform_device_add(struct platform_device *pdev); +extern void platform_device_put(struct platform_device *pdev); + #endif /* _PLATFORM_DEVICE_H_ */ -- cgit v1.2.3 From 300ce174ebc2fcf2b5111a50fa42f79d891927dd Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Sun, 30 Oct 2005 13:47:34 -0800 Subject: [NETEM]: Support time based reordering Change netem to support packets getting reordered because of variations in delay. Introduce a special case version of FIFO that queues packets in order based on the netem delay. Since netem is classful, those users that don't want jitter based reordering can just insert a pfifo instead of the default. This required changes to generic skbuff code to allow finer grain manipulation of sk_buff_head. Insertion into the middle and reverse walk. Signed-off-by: Stephen Hemminger Signed-off-by: Arnaldo Carvalho de Melo --- include/linux/skbuff.h | 38 +++++++++++++++++----- net/sched/sch_netem.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 114 insertions(+), 9 deletions(-) (limited to 'include/linux') diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 4286d832166f..fdfb8fe8c38c 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -603,29 +603,46 @@ static inline void skb_queue_head_init(struct sk_buff_head *list) */ /** - * __skb_queue_head - queue a buffer at the list head + * __skb_queue_after - queue a buffer at the list head * @list: list to use + * @prev: place after this buffer * @newsk: buffer to queue * - * Queue a buffer at the start of a list. This function takes no locks + * Queue a buffer int the middle of a list. This function takes no locks * and you must therefore hold required locks before calling it. * * A buffer cannot be placed on two lists at the same time. */ -extern void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk); -static inline void __skb_queue_head(struct sk_buff_head *list, - struct sk_buff *newsk) +static inline void __skb_queue_after(struct sk_buff_head *list, + struct sk_buff *prev, + struct sk_buff *newsk) { - struct sk_buff *prev, *next; - + struct sk_buff *next; list->qlen++; - prev = (struct sk_buff *)list; + next = prev->next; newsk->next = next; newsk->prev = prev; next->prev = prev->next = newsk; } +/** + * __skb_queue_head - queue a buffer at the list head + * @list: list to use + * @newsk: buffer to queue + * + * Queue a buffer at the start of a list. This function takes no locks + * and you must therefore hold required locks before calling it. + * + * A buffer cannot be placed on two lists at the same time. + */ +extern void skb_queue_head(struct sk_buff_head *list, struct sk_buff *newsk); +static inline void __skb_queue_head(struct sk_buff_head *list, + struct sk_buff *newsk) +{ + __skb_queue_after(list, (struct sk_buff *)list, newsk); +} + /** * __skb_queue_tail - queue a buffer at the list tail * @list: list to use @@ -1203,6 +1220,11 @@ static inline void kunmap_skb_frag(void *vaddr) prefetch(skb->next), (skb != (struct sk_buff *)(queue)); \ skb = skb->next) +#define skb_queue_reverse_walk(queue, skb) \ + for (skb = (queue)->prev; \ + prefetch(skb->prev), (skb != (struct sk_buff *)(queue)); \ + skb = skb->prev) + extern struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock, int *err); diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index d871fe7f81a9..7c10ef3457d7 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -300,11 +300,16 @@ static void netem_reset(struct Qdisc *sch) del_timer_sync(&q->timer); } +/* Pass size change message down to embedded FIFO */ static int set_fifo_limit(struct Qdisc *q, int limit) { struct rtattr *rta; int ret = -ENOMEM; + /* Hack to avoid sending change message to non-FIFO */ + if (strncmp(q->ops->id + 1, "fifo", 4) != 0) + return 0; + rta = kmalloc(RTA_LENGTH(sizeof(struct tc_fifo_qopt)), GFP_KERNEL); if (rta) { rta->rta_type = RTM_NEWQDISC; @@ -436,6 +441,84 @@ static int netem_change(struct Qdisc *sch, struct rtattr *opt) return 0; } +/* + * Special case version of FIFO queue for use by netem. + * It queues in order based on timestamps in skb's + */ +struct fifo_sched_data { + u32 limit; +}; + +static int tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch) +{ + struct fifo_sched_data *q = qdisc_priv(sch); + struct sk_buff_head *list = &sch->q; + const struct netem_skb_cb *ncb + = (const struct netem_skb_cb *)nskb->cb; + struct sk_buff *skb; + + if (likely(skb_queue_len(list) < q->limit)) { + skb_queue_reverse_walk(list, skb) { + const struct netem_skb_cb *cb + = (const struct netem_skb_cb *)skb->cb; + + if (PSCHED_TLESS(cb->time_to_send, ncb->time_to_send)) + break; + } + + __skb_queue_after(list, skb, nskb); + + sch->qstats.backlog += nskb->len; + sch->bstats.bytes += nskb->len; + sch->bstats.packets++; + + return NET_XMIT_SUCCESS; + } + + return qdisc_drop(nskb, sch); +} + +static int tfifo_init(struct Qdisc *sch, struct rtattr *opt) +{ + struct fifo_sched_data *q = qdisc_priv(sch); + + if (opt) { + struct tc_fifo_qopt *ctl = RTA_DATA(opt); + if (RTA_PAYLOAD(opt) < sizeof(*ctl)) + return -EINVAL; + + q->limit = ctl->limit; + } else + q->limit = max_t(u32, sch->dev->tx_queue_len, 1); + + return 0; +} + +static int tfifo_dump(struct Qdisc *sch, struct sk_buff *skb) +{ + struct fifo_sched_data *q = qdisc_priv(sch); + struct tc_fifo_qopt opt = { .limit = q->limit }; + + RTA_PUT(skb, TCA_OPTIONS, sizeof(opt), &opt); + return skb->len; + +rtattr_failure: + return -1; +} + +static struct Qdisc_ops tfifo_qdisc_ops = { + .id = "tfifo", + .priv_size = sizeof(struct fifo_sched_data), + .enqueue = tfifo_enqueue, + .dequeue = qdisc_dequeue_head, + .requeue = qdisc_requeue, + .drop = qdisc_queue_drop, + .init = tfifo_init, + .reset = qdisc_reset_queue, + .change = tfifo_init, + .dump = tfifo_dump, +}; + static int netem_init(struct Qdisc *sch, struct rtattr *opt) { struct netem_sched_data *q = qdisc_priv(sch); @@ -448,7 +531,7 @@ static int netem_init(struct Qdisc *sch, struct rtattr *opt) q->timer.function = netem_watchdog; q->timer.data = (unsigned long) sch; - q->qdisc = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops); + q->qdisc = qdisc_create_dflt(sch->dev, &tfifo_qdisc_ops); if (!q->qdisc) { pr_debug("netem: qdisc create failed\n"); return -ENOMEM; -- cgit v1.2.3 From 5b0c76ad94faf95ca50fa0de9ab07460bea19568 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Fri, 4 Nov 2005 08:45:49 -0800 Subject: [PATCH] bnx2: add 5708 support Add 5708 copper and serdes basic support, including 2.5 Gbps support on 5708 serdes. SPEED_2500 is also added to ethtool.h Signed-off-by: Michael Chan Signed-off-by: John W. Linville --- drivers/net/bnx2.c | 217 ++++++++++++++++++++++++++++++++++++++++++------ drivers/net/bnx2.h | 63 +++++++++++++- include/linux/ethtool.h | 3 +- include/linux/pci_ids.h | 2 + 4 files changed, 256 insertions(+), 29 deletions(-) (limited to 'include/linux') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 11d252318221..671393a18469 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -41,6 +41,8 @@ typedef enum { NC370I, BCM5706S, NC370F, + BCM5708, + BCM5708S, } board_t; /* indexed by board_t, above */ @@ -52,6 +54,8 @@ static struct { { "HP NC370i Multifunction Gigabit Server Adapter" }, { "Broadcom NetXtreme II BCM5706 1000Base-SX" }, { "HP NC370F Multifunction Gigabit Server Adapter" }, + { "Broadcom NetXtreme II BCM5708 1000Base-T" }, + { "Broadcom NetXtreme II BCM5708 1000Base-SX" }, }; static struct pci_device_id bnx2_pci_tbl[] = { @@ -61,10 +65,14 @@ static struct pci_device_id bnx2_pci_tbl[] = { PCI_VENDOR_ID_HP, 0x3106, 0, 0, NC370I }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5706 }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5708, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5708 }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706S, PCI_VENDOR_ID_HP, 0x3102, 0, 0, NC370F }, { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5706S, PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5706S }, + { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_NX2_5708S, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, BCM5708S }, { 0, } }; @@ -430,6 +438,18 @@ bnx2_resolve_flow_ctrl(struct bnx2 *bp) return; } + if ((bp->phy_flags & PHY_SERDES_FLAG) && + (CHIP_NUM(bp) == CHIP_NUM_5708)) { + u32 val; + + bnx2_read_phy(bp, BCM5708S_1000X_STAT1, &val); + if (val & BCM5708S_1000X_STAT1_TX_PAUSE) + bp->flow_ctrl |= FLOW_CTRL_TX; + if (val & BCM5708S_1000X_STAT1_RX_PAUSE) + bp->flow_ctrl |= FLOW_CTRL_RX; + return; + } + bnx2_read_phy(bp, MII_ADVERTISE, &local_adv); bnx2_read_phy(bp, MII_LPA, &remote_adv); @@ -476,7 +496,36 @@ bnx2_resolve_flow_ctrl(struct bnx2 *bp) } static int -bnx2_serdes_linkup(struct bnx2 *bp) +bnx2_5708s_linkup(struct bnx2 *bp) +{ + u32 val; + + bp->link_up = 1; + bnx2_read_phy(bp, BCM5708S_1000X_STAT1, &val); + switch (val & BCM5708S_1000X_STAT1_SPEED_MASK) { + case BCM5708S_1000X_STAT1_SPEED_10: + bp->line_speed = SPEED_10; + break; + case BCM5708S_1000X_STAT1_SPEED_100: + bp->line_speed = SPEED_100; + break; + case BCM5708S_1000X_STAT1_SPEED_1G: + bp->line_speed = SPEED_1000; + break; + case BCM5708S_1000X_STAT1_SPEED_2G5: + bp->line_speed = SPEED_2500; + break; + } + if (val & BCM5708S_1000X_STAT1_FD) + bp->duplex = DUPLEX_FULL; + else + bp->duplex = DUPLEX_HALF; + + return 0; +} + +static int +bnx2_5706s_linkup(struct bnx2 *bp) { u32 bmcr, local_adv, remote_adv, common; @@ -593,13 +642,27 @@ bnx2_set_mac_link(struct bnx2 *bp) val = REG_RD(bp, BNX2_EMAC_MODE); val &= ~(BNX2_EMAC_MODE_PORT | BNX2_EMAC_MODE_HALF_DUPLEX | - BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK); + BNX2_EMAC_MODE_MAC_LOOP | BNX2_EMAC_MODE_FORCE_LINK | + BNX2_EMAC_MODE_25G); if (bp->link_up) { - if (bp->line_speed != SPEED_1000) - val |= BNX2_EMAC_MODE_PORT_MII; - else - val |= BNX2_EMAC_MODE_PORT_GMII; + switch (bp->line_speed) { + case SPEED_10: + if (CHIP_NUM(bp) == CHIP_NUM_5708) { + val |= BNX2_EMAC_MODE_PORT_MII_10; + break; + } + /* fall through */ + case SPEED_100: + val |= BNX2_EMAC_MODE_PORT_MII; + break; + case SPEED_2500: + val |= BNX2_EMAC_MODE_25G; + /* fall through */ + case SPEED_1000: + val |= BNX2_EMAC_MODE_PORT_GMII; + break; + } } else { val |= BNX2_EMAC_MODE_PORT_GMII; @@ -662,7 +725,10 @@ bnx2_set_link(struct bnx2 *bp) bp->link_up = 1; if (bp->phy_flags & PHY_SERDES_FLAG) { - bnx2_serdes_linkup(bp); + if (CHIP_NUM(bp) == CHIP_NUM_5706) + bnx2_5706s_linkup(bp); + else if (CHIP_NUM(bp) == CHIP_NUM_5708) + bnx2_5708s_linkup(bp); } else { bnx2_copper_linkup(bp); @@ -755,39 +821,61 @@ bnx2_phy_get_pause_adv(struct bnx2 *bp) static int bnx2_setup_serdes_phy(struct bnx2 *bp) { - u32 adv, bmcr; + u32 adv, bmcr, up1; u32 new_adv = 0; if (!(bp->autoneg & AUTONEG_SPEED)) { u32 new_bmcr; + int force_link_down = 0; + + if (CHIP_NUM(bp) == CHIP_NUM_5708) { + bnx2_read_phy(bp, BCM5708S_UP1, &up1); + if (up1 & BCM5708S_UP1_2G5) { + up1 &= ~BCM5708S_UP1_2G5; + bnx2_write_phy(bp, BCM5708S_UP1, up1); + force_link_down = 1; + } + } + + bnx2_read_phy(bp, MII_ADVERTISE, &adv); + adv &= ~(ADVERTISE_1000XFULL | ADVERTISE_1000XHALF); bnx2_read_phy(bp, MII_BMCR, &bmcr); new_bmcr = bmcr & ~BMCR_ANENABLE; new_bmcr |= BMCR_SPEED1000; if (bp->req_duplex == DUPLEX_FULL) { + adv |= ADVERTISE_1000XFULL; new_bmcr |= BMCR_FULLDPLX; } else { + adv |= ADVERTISE_1000XHALF; new_bmcr &= ~BMCR_FULLDPLX; } - if (new_bmcr != bmcr) { + if ((new_bmcr != bmcr) || (force_link_down)) { /* Force a link down visible on the other side */ if (bp->link_up) { - bnx2_read_phy(bp, MII_ADVERTISE, &adv); - adv &= ~(ADVERTISE_1000XFULL | - ADVERTISE_1000XHALF); - bnx2_write_phy(bp, MII_ADVERTISE, adv); + bnx2_write_phy(bp, MII_ADVERTISE, adv & + ~(ADVERTISE_1000XFULL | + ADVERTISE_1000XHALF)); bnx2_write_phy(bp, MII_BMCR, bmcr | BMCR_ANRESTART | BMCR_ANENABLE); bp->link_up = 0; netif_carrier_off(bp->dev); + bnx2_write_phy(bp, MII_BMCR, new_bmcr); } + bnx2_write_phy(bp, MII_ADVERTISE, adv); bnx2_write_phy(bp, MII_BMCR, new_bmcr); } return 0; } + if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) { + bnx2_read_phy(bp, BCM5708S_UP1, &up1); + up1 |= BCM5708S_UP1_2G5; + bnx2_write_phy(bp, BCM5708S_UP1, up1); + } + if (bp->advertising & ADVERTISED_1000baseT_Full) new_adv |= ADVERTISE_1000XFULL; @@ -952,7 +1040,60 @@ bnx2_setup_phy(struct bnx2 *bp) } static int -bnx2_init_serdes_phy(struct bnx2 *bp) +bnx2_init_5708s_phy(struct bnx2 *bp) +{ + u32 val; + + bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG3); + bnx2_write_phy(bp, BCM5708S_DIG_3_0, BCM5708S_DIG_3_0_USE_IEEE); + bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG); + + bnx2_read_phy(bp, BCM5708S_1000X_CTL1, &val); + val |= BCM5708S_1000X_CTL1_FIBER_MODE | BCM5708S_1000X_CTL1_AUTODET_EN; + bnx2_write_phy(bp, BCM5708S_1000X_CTL1, val); + + bnx2_read_phy(bp, BCM5708S_1000X_CTL2, &val); + val |= BCM5708S_1000X_CTL2_PLLEL_DET_EN; + bnx2_write_phy(bp, BCM5708S_1000X_CTL2, val); + + if (bp->phy_flags & PHY_2_5G_CAPABLE_FLAG) { + bnx2_read_phy(bp, BCM5708S_UP1, &val); + val |= BCM5708S_UP1_2G5; + bnx2_write_phy(bp, BCM5708S_UP1, val); + } + + if ((CHIP_ID(bp) == CHIP_ID_5708_A0) || + (CHIP_ID(bp) == CHIP_ID_5708_B0)) { + /* increase tx signal amplitude */ + bnx2_write_phy(bp, BCM5708S_BLK_ADDR, + BCM5708S_BLK_ADDR_TX_MISC); + bnx2_read_phy(bp, BCM5708S_TX_ACTL1, &val); + val &= ~BCM5708S_TX_ACTL1_DRIVER_VCM; + bnx2_write_phy(bp, BCM5708S_TX_ACTL1, val); + bnx2_write_phy(bp, BCM5708S_BLK_ADDR, BCM5708S_BLK_ADDR_DIG); + } + + val = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + BNX2_PORT_HW_CFG_CONFIG) & + BNX2_PORT_HW_CFG_CFG_TXCTL3_MASK; + + if (val) { + u32 is_backplane; + + is_backplane = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + + BNX2_SHARED_HW_CFG_CONFIG); + if (is_backplane & BNX2_SHARED_HW_CFG_PHY_BACKPLANE) { + bnx2_write_phy(bp, BCM5708S_BLK_ADDR, + BCM5708S_BLK_ADDR_TX_MISC); + bnx2_write_phy(bp, BCM5708S_TX_ACTL3, val); + bnx2_write_phy(bp, BCM5708S_BLK_ADDR, + BCM5708S_BLK_ADDR_DIG); + } + } + return 0; +} + +static int +bnx2_init_5706s_phy(struct bnx2 *bp) { bp->phy_flags &= ~PHY_PARALLEL_DETECT_FLAG; @@ -990,6 +1131,8 @@ bnx2_init_serdes_phy(struct bnx2 *bp) static int bnx2_init_copper_phy(struct bnx2 *bp) { + u32 val; + bp->phy_flags |= PHY_CRC_FIX_FLAG; if (bp->phy_flags & PHY_CRC_FIX_FLAG) { @@ -1004,8 +1147,6 @@ bnx2_init_copper_phy(struct bnx2 *bp) } if (bp->dev->mtu > 1500) { - u32 val; - /* Set extended packet length bit */ bnx2_write_phy(bp, 0x18, 0x7); bnx2_read_phy(bp, 0x18, &val); @@ -1015,8 +1156,6 @@ bnx2_init_copper_phy(struct bnx2 *bp) bnx2_write_phy(bp, 0x10, val | 0x1); } else { - u32 val; - bnx2_write_phy(bp, 0x18, 0x7); bnx2_read_phy(bp, 0x18, &val); bnx2_write_phy(bp, 0x18, val & ~0x4007); @@ -1025,6 +1164,10 @@ bnx2_init_copper_phy(struct bnx2 *bp) bnx2_write_phy(bp, 0x10, val & ~0x1); } + /* ethernet@wirespeed */ + bnx2_write_phy(bp, 0x18, 0x7007); + bnx2_read_phy(bp, 0x18, &val); + bnx2_write_phy(bp, 0x18, val | (1 << 15) | (1 << 4)); return 0; } @@ -1048,7 +1191,10 @@ bnx2_init_phy(struct bnx2 *bp) bp->phy_id |= val & 0xffff; if (bp->phy_flags & PHY_SERDES_FLAG) { - rc = bnx2_init_serdes_phy(bp); + if (CHIP_NUM(bp) == CHIP_NUM_5706) + rc = bnx2_init_5706s_phy(bp); + else if (CHIP_NUM(bp) == CHIP_NUM_5708) + rc = bnx2_init_5708s_phy(bp); } else { rc = bnx2_init_copper_phy(bp); @@ -3234,7 +3380,7 @@ bnx2_test_registers(struct bnx2 *bp) { 0x1408, 0, 0x01c00800, 0x00000000 }, { 0x149c, 0, 0x8000ffff, 0x00000000 }, { 0x14a8, 0, 0x00000000, 0x000001ff }, - { 0x14ac, 0, 0x4fffffff, 0x10000000 }, + { 0x14ac, 0, 0x0fffffff, 0x10000000 }, { 0x14b0, 0, 0x00000002, 0x00000001 }, { 0x14b8, 0, 0x00000000, 0x00000000 }, { 0x14c0, 0, 0x00000000, 0x00000009 }, @@ -3577,7 +3723,7 @@ bnx2_test_memory(struct bnx2 *bp) u32 len; } mem_tbl[] = { { 0x60000, 0x4000 }, - { 0xa0000, 0x4000 }, + { 0xa0000, 0x3000 }, { 0xe0000, 0x4000 }, { 0x120000, 0x4000 }, { 0x1a0000, 0x4000 }, @@ -4264,7 +4410,8 @@ bnx2_get_stats(struct net_device *dev) (unsigned long) (stats_blk->stat_Dot3StatsExcessiveCollisions + stats_blk->stat_Dot3StatsLateCollisions); - if (CHIP_NUM(bp) == CHIP_NUM_5706) + if ((CHIP_NUM(bp) == CHIP_NUM_5706) || + (CHIP_ID(bp) == CHIP_ID_5708_A0)) net_stats->tx_carrier_errors = 0; else { net_stats->tx_carrier_errors = @@ -4814,6 +4961,14 @@ static u8 bnx2_5706_stats_len_arr[BNX2_NUM_STATS] = { 4,4,4,4,4, }; +static u8 bnx2_5708_stats_len_arr[BNX2_NUM_STATS] = { + 8,0,8,8,8,8,8,8,8,8, + 4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4,4,4,4,4,4, + 4,4,4,4,4, +}; + #define BNX2_NUM_TESTS 6 static struct { @@ -4922,8 +5077,13 @@ bnx2_get_ethtool_stats(struct net_device *dev, return; } - if (CHIP_NUM(bp) == CHIP_NUM_5706) + if ((CHIP_ID(bp) == CHIP_ID_5706_A0) || + (CHIP_ID(bp) == CHIP_ID_5706_A1) || + (CHIP_ID(bp) == CHIP_ID_5706_A2) || + (CHIP_ID(bp) == CHIP_ID_5708_A0)) stats_len_arr = bnx2_5706_stats_len_arr; + else + stats_len_arr = bnx2_5708_stats_len_arr; for (i = 0; i < BNX2_NUM_STATS; i++) { if (stats_len_arr[i] == 0) { @@ -5205,8 +5365,6 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->chip_id = REG_RD(bp, BNX2_MISC_ID); - bp->phy_addr = 1; - /* Get bus information. */ reg = REG_RD(bp, BNX2_PCICFG_MISC_STATUS); if (reg & BNX2_PCICFG_MISC_STATUS_PCIX_DET) { @@ -5316,10 +5474,19 @@ bnx2_init_board(struct pci_dev *pdev, struct net_device *dev) bp->timer_interval = HZ; bp->current_interval = HZ; + bp->phy_addr = 1; + /* Disable WOL support if we are running on a SERDES chip. */ if (CHIP_BOND_ID(bp) & CHIP_BOND_ID_SERDES_BIT) { bp->phy_flags |= PHY_SERDES_FLAG; bp->flags |= NO_WOL_FLAG; + if (CHIP_NUM(bp) == CHIP_NUM_5708) { + bp->phy_addr = 2; + reg = REG_RD_IND(bp, HOST_VIEW_SHMEM_BASE + + BNX2_SHARED_HW_CFG_CONFIG); + if (reg & BNX2_SHARED_HW_CFG_PHY_2_5G) + bp->phy_flags |= PHY_2_5G_CAPABLE_FLAG; + } } if (CHIP_ID(bp) == CHIP_ID_5706_A0) { diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 62857b6a6ee4..c0e88f850493 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h @@ -1449,8 +1449,9 @@ struct l2_fhdr { #define BNX2_EMAC_MODE_PORT_NONE (0L<<2) #define BNX2_EMAC_MODE_PORT_MII (1L<<2) #define BNX2_EMAC_MODE_PORT_GMII (2L<<2) -#define BNX2_EMAC_MODE_PORT_UNDEF (3L<<2) +#define BNX2_EMAC_MODE_PORT_MII_10 (3L<<2) #define BNX2_EMAC_MODE_MAC_LOOP (1L<<4) +#define BNX2_EMAC_MODE_25G (1L<<5) #define BNX2_EMAC_MODE_TAGGED_MAC_CTL (1L<<7) #define BNX2_EMAC_MODE_TX_BURST (1L<<8) #define BNX2_EMAC_MODE_MAX_DEFER_DROP_ENA (1L<<9) @@ -3724,6 +3725,53 @@ struct l2_fhdr { #define PHY_ID(id) ((id) & 0xfffffff0) #define PHY_REV_ID(id) ((id) & 0xf) +/* 5708 Serdes PHY registers */ + +#define BCM5708S_UP1 0xb + +#define BCM5708S_UP1_2G5 0x1 + +#define BCM5708S_BLK_ADDR 0x1f + +#define BCM5708S_BLK_ADDR_DIG 0x0000 +#define BCM5708S_BLK_ADDR_DIG3 0x0002 +#define BCM5708S_BLK_ADDR_TX_MISC 0x0005 + +/* Digital Block */ +#define BCM5708S_1000X_CTL1 0x10 + +#define BCM5708S_1000X_CTL1_FIBER_MODE 0x0001 +#define BCM5708S_1000X_CTL1_AUTODET_EN 0x0010 + +#define BCM5708S_1000X_CTL2 0x11 + +#define BCM5708S_1000X_CTL2_PLLEL_DET_EN 0x0001 + +#define BCM5708S_1000X_STAT1 0x14 + +#define BCM5708S_1000X_STAT1_SGMII 0x0001 +#define BCM5708S_1000X_STAT1_LINK 0x0002 +#define BCM5708S_1000X_STAT1_FD 0x0004 +#define BCM5708S_1000X_STAT1_SPEED_MASK 0x0018 +#define BCM5708S_1000X_STAT1_SPEED_10 0x0000 +#define BCM5708S_1000X_STAT1_SPEED_100 0x0008 +#define BCM5708S_1000X_STAT1_SPEED_1G 0x0010 +#define BCM5708S_1000X_STAT1_SPEED_2G5 0x0018 +#define BCM5708S_1000X_STAT1_TX_PAUSE 0x0020 +#define BCM5708S_1000X_STAT1_RX_PAUSE 0x0040 + +/* Digital3 Block */ +#define BCM5708S_DIG_3_0 0x10 + +#define BCM5708S_DIG_3_0_USE_IEEE 0x0001 + +/* Tx/Misc Block */ +#define BCM5708S_TX_ACTL1 0x15 + +#define BCM5708S_TX_ACTL1_DRIVER_VCM 0x30 + +#define BCM5708S_TX_ACTL3 0x17 + #define MIN_ETHERNET_PACKET_SIZE 60 #define MAX_ETHERNET_PACKET_SIZE 1514 #define MAX_ETHERNET_JUMBO_PACKET_SIZE 9014 @@ -3893,6 +3941,7 @@ struct bnx2 { #define PHY_SERDES_FLAG 1 #define PHY_CRC_FIX_FLAG 2 #define PHY_PARALLEL_DETECT_FLAG 4 +#define PHY_2_5G_CAPABLE_FLAG 8 #define PHY_INT_MODE_MASK_FLAG 0x300 #define PHY_INT_MODE_AUTO_POLLING_FLAG 0x100 #define PHY_INT_MODE_LINK_READY_FLAG 0x200 @@ -3901,6 +3950,7 @@ struct bnx2 { /* chip num:16-31, rev:12-15, metal:4-11, bond_id:0-3 */ #define CHIP_NUM(bp) (((bp)->chip_id) & 0xffff0000) #define CHIP_NUM_5706 0x57060000 +#define CHIP_NUM_5708 0x57080000 #define CHIP_REV(bp) (((bp)->chip_id) & 0x0000f000) #define CHIP_REV_Ax 0x00000000 @@ -3913,6 +3963,9 @@ struct bnx2 { #define CHIP_ID(bp) (((bp)->chip_id) & 0xfffffff0) #define CHIP_ID_5706_A0 0x57060000 #define CHIP_ID_5706_A1 0x57060010 +#define CHIP_ID_5706_A2 0x57060020 +#define CHIP_ID_5708_A0 0x57080000 +#define CHIP_ID_5708_B0 0x57081000 #define CHIP_BOND_ID(bp) (((bp)->chip_id) & 0xf) @@ -4132,12 +4185,12 @@ struct fw_info { #define BNX2_LINK_STATUS 0x0000000c #define BNX2_DRV_PULSE_MB 0x00000010 -#define BNX2_DRV_PULSE_SEQ_MASK 0x0000ffff +#define BNX2_DRV_PULSE_SEQ_MASK 0x00007fff /* Indicate to the firmware not to go into the * OS absent when it is not getting driver pulse. * This is used for debugging. */ -#define BNX2_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE 0x00010000 +#define BNX2_DRV_MSG_DATA_PULSE_CODE_ALWAYS_ALIVE 0x00080000 #define BNX2_DEV_INFO_SIGNATURE 0x00000020 #define BNX2_DEV_INFO_SIGNATURE_MAGIC 0x44564900 @@ -4160,6 +4213,8 @@ struct fw_info { #define BNX2_SHARED_HW_CFG_DESIGN_LOM 0x1 #define BNX2_SHARED_HW_CFG_PHY_COPPER 0 #define BNX2_SHARED_HW_CFG_PHY_FIBER 0x2 +#define BNX2_SHARED_HW_CFG_PHY_2_5G 0x20 +#define BNX2_SHARED_HW_CFG_PHY_BACKPLANE 0x40 #define BNX2_SHARED_HW_CFG_LED_MODE_SHIFT_BITS 8 #define BNX2_SHARED_HW_CFG_LED_MODE_MASK 0x300 #define BNX2_SHARED_HW_CFG_LED_MODE_MAC 0 @@ -4173,9 +4228,11 @@ struct fw_info { #define BNX2_PORT_HW_CFG_MAC_LOWER 0x00000054 #define BNX2_PORT_HW_CFG_CONFIG 0x00000058 +#define BNX2_PORT_HW_CFG_CFG_TXCTL3_MASK 0x0000ffff #define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_MASK 0x001f0000 #define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_AN 0x00000000 #define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_1G 0x00030000 +#define BNX2_PORT_HW_CFG_CFG_DFLT_LINK_2_5G 0x00040000 #define BNX2_PORT_HW_CFG_IMD_MAC_A_UPPER 0x00000068 #define BNX2_PORT_HW_CFG_IMD_MAC_A_LOWER 0x0000006c diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index d2c390eff1b2..93535f093216 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -453,10 +453,11 @@ struct ethtool_ops { * it was foced up into this mode or autonegotiated. */ -/* The forced speed, 10Mb, 100Mb, gigabit, 10GbE. */ +/* The forced speed, 10Mb, 100Mb, gigabit, 2.5Gb, 10GbE. */ #define SPEED_10 10 #define SPEED_100 100 #define SPEED_1000 1000 +#define SPEED_2500 2500 #define SPEED_10000 10000 /* Duplex, half or full. */ diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 88de3f8ce1a2..8cadfdeef674 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1785,6 +1785,7 @@ #define PCI_DEVICE_ID_TIGON3_5704 0x1648 #define PCI_DEVICE_ID_TIGON3_5704S_2 0x1649 #define PCI_DEVICE_ID_NX2_5706 0x164a +#define PCI_DEVICE_ID_NX2_5708 0x164c #define PCI_DEVICE_ID_TIGON3_5702FE 0x164d #define PCI_DEVICE_ID_TIGON3_5705 0x1653 #define PCI_DEVICE_ID_TIGON3_5705_2 0x1654 @@ -1809,6 +1810,7 @@ #define PCI_DEVICE_ID_TIGON3_5703X 0x16a7 #define PCI_DEVICE_ID_TIGON3_5704S 0x16a8 #define PCI_DEVICE_ID_NX2_5706S 0x16aa +#define PCI_DEVICE_ID_NX2_5708S 0x16ac #define PCI_DEVICE_ID_TIGON3_5702A3 0x16c6 #define PCI_DEVICE_ID_TIGON3_5703A3 0x16c7 #define PCI_DEVICE_ID_TIGON3_5781 0x16dd -- cgit v1.2.3 From 21c614a7899046ab108b3d327d76c33443a8ebf2 Mon Sep 17 00:00:00 2001 From: Pantelis Antoniou Date: Sun, 6 Nov 2005 09:07:03 +0000 Subject: [SERIAL] Support Au1x00 8250 UARTs using the generic 8250 driver. The offsets of the registers are in a different place, and some parts cannot handle a full set of modem control signals. Signed-off-by: Pantelis Antoniou Signed-off-by: Russell King --- drivers/serial/8250.c | 73 +++++++++++++++++++++++++++++-- drivers/serial/8250.h | 1 + drivers/serial/8250_au1x00.c | 102 +++++++++++++++++++++++++++++++++++++++++++ drivers/serial/Kconfig | 8 ++++ drivers/serial/Makefile | 1 + drivers/serial/serial_core.c | 1 + include/linux/serial_8250.h | 1 + include/linux/serial_core.h | 1 + 8 files changed, 185 insertions(+), 3 deletions(-) create mode 100644 drivers/serial/8250_au1x00.c (limited to 'include/linux') diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index f47d2c454e33..186e96c47b3d 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -251,9 +251,53 @@ static const struct serial8250_config uart_config[] = { }, }; +#ifdef CONFIG_SERIAL_8250_AU1X00 + +/* Au1x00 UART hardware has a weird register layout */ +static const u8 au_io_in_map[] = { + [UART_RX] = 0, + [UART_IER] = 2, + [UART_IIR] = 3, + [UART_LCR] = 5, + [UART_MCR] = 6, + [UART_LSR] = 7, + [UART_MSR] = 8, +}; + +static const u8 au_io_out_map[] = { + [UART_TX] = 1, + [UART_IER] = 2, + [UART_FCR] = 4, + [UART_LCR] = 5, + [UART_MCR] = 6, +}; + +/* sane hardware needs no mapping */ +static inline int map_8250_in_reg(struct uart_8250_port *up, int offset) +{ + if (up->port.iotype != UPIO_AU) + return offset; + return au_io_in_map[offset]; +} + +static inline int map_8250_out_reg(struct uart_8250_port *up, int offset) +{ + if (up->port.iotype != UPIO_AU) + return offset; + return au_io_out_map[offset]; +} + +#else + +/* sane hardware needs no mapping */ +#define map_8250_in_reg(up, offset) (offset) +#define map_8250_out_reg(up, offset) (offset) + +#endif + static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset) { - offset <<= up->port.regshift; + offset = map_8250_in_reg(up, offset) << up->port.regshift; switch (up->port.iotype) { case UPIO_HUB6: @@ -266,6 +310,11 @@ static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset) case UPIO_MEM32: return readl(up->port.membase + offset); +#ifdef CONFIG_SERIAL_8250_AU1X00 + case UPIO_AU: + return __raw_readl(up->port.membase + offset); +#endif + default: return inb(up->port.iobase + offset); } @@ -274,7 +323,7 @@ static _INLINE_ unsigned int serial_in(struct uart_8250_port *up, int offset) static _INLINE_ void serial_out(struct uart_8250_port *up, int offset, int value) { - offset <<= up->port.regshift; + offset = map_8250_out_reg(up, offset) << up->port.regshift; switch (up->port.iotype) { case UPIO_HUB6: @@ -290,6 +339,12 @@ serial_out(struct uart_8250_port *up, int offset, int value) writel(value, up->port.membase + offset); break; +#ifdef CONFIG_SERIAL_8250_AU1X00 + case UPIO_AU: + __raw_writel(value, up->port.membase + offset); + break; +#endif + default: outb(value, up->port.iobase + offset); } @@ -910,6 +965,13 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags) } } #endif + +#ifdef CONFIG_SERIAL_8250_AU1X00 + /* if access method is AU, it is a 16550 with a quirk */ + if (up->port.type == PORT_16550A && up->port.iotype == UPIO_AU) + up->bugs |= UART_BUG_NOMSR; +#endif + serial_outp(up, UART_LCR, save_lcr); if (up->capabilities != uart_config[up->port.type].flags) { @@ -1057,6 +1119,10 @@ static void serial8250_enable_ms(struct uart_port *port) { struct uart_8250_port *up = (struct uart_8250_port *)port; + /* no MSR capabilities */ + if (up->bugs & UART_BUG_NOMSR) + return; + up->ier |= UART_IER_MSI; serial_out(up, UART_IER, up->ier); } @@ -1774,7 +1840,8 @@ serial8250_set_termios(struct uart_port *port, struct termios *termios, * CTS flow control flag and modem status interrupts */ up->ier &= ~UART_IER_MSI; - if (UART_ENABLE_MS(&up->port, termios->c_cflag)) + if (!(up->bugs & UART_BUG_NOMSR) && + UART_ENABLE_MS(&up->port, termios->c_cflag)) up->ier |= UART_IER_MSI; if (up->capabilities & UART_CAP_UUE) up->ier |= UART_IER_UUE | UART_IER_RTOIE; diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h index b1b459efda52..a607b98016db 100644 --- a/drivers/serial/8250.h +++ b/drivers/serial/8250.h @@ -49,6 +49,7 @@ struct serial8250_config { #define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ +#define UART_BUG_NOMSR (1 << 2) /* UART has buggy MSR status bits (Au1x00) */ #if defined(__i386__) && (defined(CONFIG_M386) || defined(CONFIG_M486)) #define _INLINE_ inline diff --git a/drivers/serial/8250_au1x00.c b/drivers/serial/8250_au1x00.c new file mode 100644 index 000000000000..06ae8fbcc947 --- /dev/null +++ b/drivers/serial/8250_au1x00.c @@ -0,0 +1,102 @@ +/* + * Serial Device Initialisation for Au1x00 + * + * (C) Copyright Embedded Alley Solutions, Inc 2005 + * Author: Pantelis Antoniou + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +#include "8250.h" + +#define PORT(_base, _irq) \ + { \ + .iobase = _base, \ + .membase = (void __iomem *)_base,\ + .mapbase = _base, \ + .irq = _irq, \ + .uartclk = 0, /* filled */ \ + .regshift = 2, \ + .iotype = UPIO_AU, \ + .flags = UPF_SKIP_TEST | \ + UPF_IOREMAP, \ + } + +static struct plat_serial8250_port au1x00_data[] = { +#if defined(CONFIG_SOC_AU1000) + PORT(UART0_ADDR, AU1000_UART0_INT), + PORT(UART1_ADDR, AU1000_UART1_INT), + PORT(UART2_ADDR, AU1000_UART2_INT), + PORT(UART3_ADDR, AU1000_UART3_INT), +#elif defined(CONFIG_SOC_AU1500) + PORT(UART0_ADDR, AU1500_UART0_INT), + PORT(UART3_ADDR, AU1500_UART3_INT), +#elif defined(CONFIG_SOC_AU1100) + PORT(UART0_ADDR, AU1100_UART0_INT), + PORT(UART1_ADDR, AU1100_UART1_INT), + PORT(UART2_ADDR, AU1100_UART2_INT), + PORT(UART3_ADDR, AU1100_UART3_INT), +#elif defined(CONFIG_SOC_AU1550) + PORT(UART0_ADDR, AU1550_UART0_INT), + PORT(UART1_ADDR, AU1550_UART1_INT), + PORT(UART2_ADDR, AU1550_UART2_INT), + PORT(UART3_ADDR, AU1550_UART3_INT), +#elif defined(CONFIG_SOC_AU1200) + PORT(UART0_ADDR, AU1200_UART0_INT), + PORT(UART1_ADDR, AU1200_UART1_INT), +#endif + { }, +}; + +static struct platform_device au1x00_device = { + .name = "serial8250", + .id = PLAT8250_DEV_AU1X00, + .dev = { + .platform_data = au1x00_data, + }, +}; + +static int __init au1x00_init(void) +{ + int i; + unsigned int uartclk; + + /* get uart clock */ + uartclk = get_au1x00_uart_baud_base() * 16; + + /* fill up uartclk */ + for (i = 0; au1x00_data[i].flags ; i++) + au1x00_data[i].uartclk = uartclk; + + return platform_device_register(&au1x00_device); +} + +/* XXX: Yes, I know this doesn't yet work. */ +static void __exit au1x00_exit(void) +{ + platform_device_unregister(&au1x00_device); +} + +module_init(au1x00_init); +module_exit(au1x00_exit); + +MODULE_AUTHOR("Pantelis Antoniou "); +MODULE_DESCRIPTION("8250 serial probe module for Au1x000 cards"); +MODULE_LICENSE("GPL"); diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index b745a1b9e835..ff36f0c9fdad 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig @@ -207,6 +207,14 @@ config SERIAL_8250_ACORN system, say Y to this option. The driver can handle 1, 2, or 3 port cards. If unsure, say N. +config SERIAL_8250_AU1X00 + bool "AU1X00 serial port support" + depends on SERIAL_8250 != n && SOC_AU1X00 + help + If you have an Au1x00 board and want to use the serial port, say Y + to this option. The driver can handle 1 or 2 serial ports. + If unsure, say N. + comment "Non-8250 serial port support" config SERIAL_AMBA_PL010 diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index 11c7dc483f93..d7c7c7180e33 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile @@ -22,6 +22,7 @@ obj-$(CONFIG_SERIAL_8250_ACCENT) += 8250_accent.o obj-$(CONFIG_SERIAL_8250_BOCA) += 8250_boca.o obj-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o obj-$(CONFIG_SERIAL_8250_MCA) += 8250_mca.o +obj-$(CONFIG_SERIAL_8250_AU1X00) += 8250_au1x00.o obj-$(CONFIG_SERIAL_AMBA_PL010) += amba-pl010.o obj-$(CONFIG_SERIAL_AMBA_PL011) += amba-pl011.o obj-$(CONFIG_SERIAL_CLPS711X) += clps711x.o diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c index 0745ce782974..427a23858076 100644 --- a/drivers/serial/serial_core.c +++ b/drivers/serial/serial_core.c @@ -1959,6 +1959,7 @@ uart_report_port(struct uart_driver *drv, struct uart_port *port) break; case UPIO_MEM: case UPIO_MEM32: + case UPIO_AU: snprintf(address, sizeof(address), "MMIO 0x%lx", port->mapbase); break; diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index 2b799d40d669..cee302aefdb7 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h @@ -42,6 +42,7 @@ enum { PLAT8250_DEV_BOCA, PLAT8250_DEV_HUB6, PLAT8250_DEV_MCA, + PLAT8250_DEV_AU1X00, }; /* diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 9d2579230689..a3ac92b19aca 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -211,6 +211,7 @@ struct uart_port { #define UPIO_HUB6 (1) #define UPIO_MEM (2) #define UPIO_MEM32 (3) +#define UPIO_AU (4) /* Au1x00 type IO */ unsigned int read_status_mask; /* driver specific */ unsigned int ignore_status_mask; /* driver specific */ -- cgit v1.2.3 From 2dd34b488a99135ad2a529e33087ddd6a09e992a Mon Sep 17 00:00:00 2001 From: Russell King Date: Sun, 30 Oct 2005 22:42:11 +0100 Subject: [PATCH] kbuild: permanently fix kernel configuration include mess Include autoconf.h into every kernel compilation via the gcc command line using -imacros. This ensures that we have the kernel configuration included from the start, rather than relying on each file having #include as appropriate. History has shown that this is something which is difficult to get right. Since we now include the kernel configuration automatically, make configcheck becomes meaningless, so remove it. Signed-off-by: Russell King Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg --- Makefile | 8 ++------ include/linux/config.h | 4 +++- 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'include/linux') diff --git a/Makefile b/Makefile index 79601320ac3e..2dac8010c142 100644 --- a/Makefile +++ b/Makefile @@ -346,7 +346,8 @@ AFLAGS_KERNEL = # Use LINUXINCLUDE when you must reference the include/ directory. # Needed to be compatible with the O= option LINUXINCLUDE := -Iinclude \ - $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) + $(if $(KBUILD_SRC),-Iinclude2 -I$(srctree)/include) \ + -imacros include/linux/autoconf.h CPPFLAGS := -D__KERNEL__ $(LINUXINCLUDE) @@ -1249,11 +1250,6 @@ tags: FORCE # Scripts to check various things for consistency # --------------------------------------------------------------------------- -configcheck: - find * $(RCS_FIND_IGNORE) \ - -name '*.[hcS]' -type f -print | sort \ - | xargs $(PERL) -w scripts/checkconfig.pl - includecheck: find * $(RCS_FIND_IGNORE) \ -name '*.[hcS]' -type f -print | sort \ diff --git a/include/linux/config.h b/include/linux/config.h index 9d1c14f7ad6d..a91f5e55b525 100644 --- a/include/linux/config.h +++ b/include/linux/config.h @@ -1,6 +1,8 @@ #ifndef _LINUX_CONFIG_H #define _LINUX_CONFIG_H - +/* This file is no longer in use and kept only for backward compatibility. + * autoconf.h is now included via -imacros on the commandline + */ #include #endif -- cgit v1.2.3 From 2b79adcca147c9f8fd1094ab4cb342d7e1790d70 Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Sun, 17 Jul 2005 12:13:51 +0100 Subject: [JFFS2] Use f->target instead of f->dents for symlink target JFFS2 uses f->dents to store the pointer to the symlink target string (in case the inode is symlink). This is somewhat ugly to use the same field for different reasons. Introduce distinct field f->target for this purpose. Note, f->fragtree, f->dents, f->target may probably be put in a union. Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/dir.c | 12 ++++++------ fs/jffs2/os-linux.h | 3 ++- fs/jffs2/readinode.c | 45 ++++++++++++++++++++------------------------- fs/jffs2/symlink.c | 26 ++++++++++++-------------- include/linux/jffs2_fs_i.h | 5 ++++- 5 files changed, 44 insertions(+), 47 deletions(-) (limited to 'include/linux') diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 3ca0d25eef1d..5738df223775 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: dir.c,v 1.86 2005/07/06 12:13:09 dwmw2 Exp $ + * $Id: dir.c,v 1.87 2005/07/17 11:13:46 dedekind Exp $ * */ @@ -344,9 +344,9 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char return PTR_ERR(fn); } - /* We use f->dents field to store the target path. */ - f->dents = kmalloc(targetlen + 1, GFP_KERNEL); - if (!f->dents) { + /* We use f->target field to store the target path. */ + f->target = kmalloc(targetlen + 1, GFP_KERNEL); + if (!f->target) { printk(KERN_WARNING "Can't allocate %d bytes of memory\n", targetlen + 1); up(&f->sem); jffs2_complete_reservation(c); @@ -354,8 +354,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char return -ENOMEM; } - memcpy(f->dents, target, targetlen + 1); - D1(printk(KERN_DEBUG "jffs2_symlink: symlink's target '%s' cached\n", (char *)f->dents)); + memcpy(f->target, target, targetlen + 1); + D1(printk(KERN_DEBUG "jffs2_symlink: symlink's target '%s' cached\n", (char *)f->target)); /* No data here. Only a metadata node, which will be obsoleted by the first data write diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index d900c8929b09..0fc952eaf8c8 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: os-linux.h,v 1.58 2005/07/12 02:34:35 tpoynor Exp $ + * $Id: os-linux.h,v 1.59 2005/07/17 11:13:46 dedekind Exp $ * */ @@ -57,6 +57,7 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) f->fragtree = RB_ROOT; f->metadata = NULL; f->dents = NULL; + f->target = NULL; f->flags = 0; f->usercompr = 0; } diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index cf39bcf3e3cf..49da1a6cfc81 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.126 2005/07/17 06:56:21 dedekind Exp $ + * $Id: readinode.c,v 1.127 2005/07/17 11:13:46 dedekind Exp $ * */ @@ -547,11 +547,10 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, if (f->inocache->state != INO_STATE_CHECKING) { /* Symlink's inode data is the target path. Read it and - * keep in RAM to facilitate quick follow symlink operation. - * We use f->dents field to store the target path, which - * is somewhat ugly. */ - f->dents = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL); - if (!f->dents) { + * keep in RAM to facilitate quick follow symlink + * operation. */ + f->target = kmalloc(je32_to_cpu(latest_node->csize) + 1, GFP_KERNEL); + if (!f->target) { printk(KERN_WARNING "Can't allocate %d bytes of memory " "for the symlink target path cache\n", je32_to_cpu(latest_node->csize)); @@ -561,21 +560,21 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, } ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node), - je32_to_cpu(latest_node->csize), &retlen, (char *)f->dents); + je32_to_cpu(latest_node->csize), &retlen, (char *)f->target); if (ret || retlen != je32_to_cpu(latest_node->csize)) { if (retlen != je32_to_cpu(latest_node->csize)) ret = -EIO; - kfree(f->dents); - f->dents = NULL; + kfree(f->target); + f->target = NULL; up(&f->sem); jffs2_do_clear_inode(c, f); return -ret; } - ((char *)f->dents)[je32_to_cpu(latest_node->csize)] = '\0'; + f->target[je32_to_cpu(latest_node->csize)] = '\0'; D1(printk(KERN_DEBUG "jffs2_do_read_inode(): symlink's target '%s' cached\n", - (char *)f->dents)); + f->target)); } /* fall through... */ @@ -638,20 +637,16 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f) jffs2_kill_fragtree(&f->fragtree, deleted?c:NULL); - /* For symlink inodes we us f->dents to store the target path name */ - if (S_ISLNK(OFNI_EDONI_2SFFJ(f)->i_mode)) { - if (f->dents) { - kfree(f->dents); - f->dents = NULL; - } - } else { - fds = f->dents; - - while(fds) { - fd = fds; - fds = fd->next; - jffs2_free_full_dirent(fd); - } + if (f->target) { + kfree(f->target); + f->target = NULL; + } + + fds = f->dents; + while(fds) { + fd = fds; + fds = fd->next; + jffs2_free_full_dirent(fd); } if (f->inocache && f->inocache->state != INO_STATE_CHECKING) { diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c index 82ef484f5e12..6fd5ee4f90b7 100644 --- a/fs/jffs2/symlink.c +++ b/fs/jffs2/symlink.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: symlink.c,v 1.16 2005/03/01 10:50:48 dedekind Exp $ + * $Id: symlink.c,v 1.18 2005/11/06 11:03:27 gleixner Exp $ * */ @@ -30,35 +30,33 @@ struct inode_operations jffs2_symlink_inode_operations = static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) { struct jffs2_inode_info *f = JFFS2_INODE_INFO(dentry->d_inode); - char *p = (char *)f->dents; - + char *p = (char *)f->target; + /* * We don't acquire the f->sem mutex here since the only data we - * use is f->dents which in case of the symlink inode points to the - * symlink's target path. + * use is f->target. * - * 1. If we are here the inode has already built and f->dents has + * 1. If we are here the inode has already built and f->target has * to point to the target path. - * 2. Nobody uses f->dents (if the inode is symlink's inode). The - * exception is inode freeing function which frees f->dents. But + * 2. Nobody uses f->target (if the inode is symlink's inode). The + * exception is inode freeing function which frees f->target. But * it can't be called while we are here and before VFS has - * stopped using our f->dents string which we provide by means of + * stopped using our f->target string which we provide by means of * nd_set_link() call. */ if (!p) { printk(KERN_ERR "jffs2_follow_link(): can't find symlink taerget\n"); p = ERR_PTR(-EIO); - } else { - D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->dents)); } + D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->target)); nd_set_link(nd, p); /* - * We unlock the f->sem mutex but VFS will use the f->dents string. This is safe - * since the only way that may cause f->dents to be changed is iput() operation. - * But VFS will not use f->dents after iput() has been called. + * We will unlock the f->sem mutex but VFS will use the f->target string. This is safe + * since the only way that may cause f->target to be changed is iput() operation. + * But VFS will not use f->target after iput() has been called. */ return NULL; } diff --git a/include/linux/jffs2_fs_i.h b/include/linux/jffs2_fs_i.h index 6dbb1cce6646..a5db884ec607 100644 --- a/include/linux/jffs2_fs_i.h +++ b/include/linux/jffs2_fs_i.h @@ -1,4 +1,4 @@ -/* $Id: jffs2_fs_i.h,v 1.17 2004/11/11 23:51:27 dwmw2 Exp $ */ +/* $Id: jffs2_fs_i.h,v 1.18 2005/07/17 11:13:48 dedekind Exp $ */ #ifndef _JFFS2_FS_I #define _JFFS2_FS_I @@ -32,6 +32,9 @@ struct jffs2_inode_info { /* Directory entries */ struct jffs2_full_dirent *dents; + /* The target path if this is the inode of a symlink */ + unsigned char *target; + /* Some stuff we just have to keep in-core at all times, for each inode. */ struct jffs2_inode_cache *inocache; -- cgit v1.2.3 From f302cd028c90ddbca20cb5388458ae0f0dd03d9b Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Sun, 24 Jul 2005 16:29:59 +0100 Subject: [JFFS2] Namespace clean up Rename functions to a name matching the functionality. Remove stall debug code Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/debug.h | 21 +-------------------- fs/jffs2/fs.c | 4 ++-- fs/jffs2/nodelist.h | 4 ++-- fs/jffs2/readinode.c | 6 +++--- include/linux/jffs2.h | 6 +++--- 5 files changed, 11 insertions(+), 30 deletions(-) (limited to 'include/linux') diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index 51ff099a6502..3c3c2940f272 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.h,v 1.5 2005/07/24 15:14:14 dedekind Exp $ + * $Id: debug.h,v 1.6 2005/07/24 15:18:26 dedekind Exp $ * */ #ifndef _JFFS2_DEBUG_H_ @@ -15,25 +15,6 @@ #include -/* ------------------------------------------------ */ -/* TODO: remove */ -#undef CONFIG_JFFS2_FS_DEBUG -#define CONFIG_JFFS2_FS_DEBUG 0 -//#define JFFS2_DBG_PARANOIA_CHECKS -//#define JFFS2_DBG_DUMPS -#define JFFS2_DBG_READINODE_MESSAGES -//#define JFFS2_DBG_FRAGTREE_MESSAGES -//#define JFFS2_DBG_FRAGTREE2_MESSAGES -#undef KERN_DEBUG -#undef KERN_WARNING -#undef KERN_NOTICE -#undef KERN_ERR -#define KERN_DEBUG KERN_CRIT -#define KERN_WARNING KERN_CRIT -#define KERN_NOTICE KERN_CRIT -#define KERN_ERR KERN_CRIT -/* ------------------------------------------------ */ - #ifndef CONFIG_JFFS2_FS_DEBUG #define CONFIG_JFFS2_FS_DEBUG 1 #endif diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 34731614b57a..cc18b92234c4 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: fs.c,v 1.60 2005/07/22 10:32:08 dedekind Exp $ + * $Id: fs.c,v 1.61 2005/07/24 15:29:56 dedekind Exp $ * */ @@ -147,7 +147,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) old_metadata = f->metadata; if (ivalid & ATTR_SIZE && inode->i_size > iattr->ia_size) - jffs2_truncate_fraglist (c, &f->fragtree, iattr->ia_size); + jffs2_truncate_fragtree (c, &f->fragtree, iattr->ia_size); if (ivalid & ATTR_SIZE && inode->i_size < iattr->ia_size) { jffs2_add_full_dnode_to_inode(c, f, new_metadata); diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index dde9b86e43b5..0058e395641b 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.h,v 1.133 2005/07/22 10:32:08 dedekind Exp $ + * $Id: nodelist.h,v 1.134 2005/07/24 15:29:56 dedekind Exp $ * */ @@ -336,7 +336,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint /* readinode.c */ -void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); +void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t ino, struct jffs2_raw_inode *latest_node); diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 02b02c1146bf..339ba46320fa 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.129 2005/07/22 10:32:08 dedekind Exp $ + * $Id: readinode.c,v 1.130 2005/07/24 15:29:56 dedekind Exp $ * */ @@ -273,7 +273,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *l return 0; } -void jffs2_truncate_fraglist (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size) +void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size) { struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size); @@ -534,7 +534,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, case S_IFREG: /* If it was a regular file, truncate it to the latest node's isize */ - jffs2_truncate_fraglist(c, &f->fragtree, je32_to_cpu(latest_node->isize)); + jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize)); break; case S_IFLNK: diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h index 419fc953ac16..7bc51add62fa 100644 --- a/include/linux/jffs2.h +++ b/include/linux/jffs2.h @@ -8,7 +8,7 @@ * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * - * $Id: jffs2.h,v 1.34 2004/11/16 20:36:14 dwmw2 Exp $ + * $Id: jffs2.h,v 1.35 2005/07/24 15:15:51 dedekind Exp $ * */ @@ -101,7 +101,7 @@ struct jffs2_unknown_node struct jffs2_raw_dirent { jint16_t magic; - jint16_t nodetype; /* == JFFS_NODETYPE_DIRENT */ + jint16_t nodetype; /* == JFFS2_NODETYPE_DIRENT */ jint32_t totlen; jint32_t hdr_crc; jint32_t pino; @@ -125,7 +125,7 @@ struct jffs2_raw_dirent struct jffs2_raw_inode { jint16_t magic; /* A constant magic number. */ - jint16_t nodetype; /* == JFFS_NODETYPE_INODE */ + jint16_t nodetype; /* == JFFS2_NODETYPE_INODE */ jint32_t totlen; /* Total length of this node (inc data, etc.) */ jint32_t hdr_crc; jint32_t ino; /* Inode number. */ -- cgit v1.2.3 From 2227c0ba4bc177a014d95b380b4d888454a127a9 Mon Sep 17 00:00:00 2001 From: Ferenc Havasi Date: Tue, 26 Jul 2005 14:24:43 +0100 Subject: [jffs2] Remove compressor lzo and lzari Remove unused compressor code Signed-off-by: Ferenc Havasi Signed-off-by: Thomas Gleixner --- fs/jffs2/compr.c | 14 +------------- fs/jffs2/compr.h | 10 +--------- include/linux/jffs2.h | 4 +--- 3 files changed, 3 insertions(+), 25 deletions(-) (limited to 'include/linux') diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c index af922a9618ac..c9e54b97dba8 100644 --- a/fs/jffs2/compr.c +++ b/fs/jffs2/compr.c @@ -9,7 +9,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: compr.c,v 1.42 2004/08/07 21:56:08 dwmw2 Exp $ + * $Id: compr.c,v 1.45 2005/07/26 13:24:40 havasi Exp $ * */ @@ -425,12 +425,6 @@ int jffs2_compressors_init(void) jffs2_rubinmips_init(); jffs2_dynrubin_init(); #endif -#ifdef CONFIG_JFFS2_LZARI - jffs2_lzari_init(); -#endif -#ifdef CONFIG_JFFS2_LZO - jffs2_lzo_init(); -#endif /* Setting default compression mode */ #ifdef CONFIG_JFFS2_CMODE_NONE jffs2_compression_mode = JFFS2_COMPR_MODE_NONE; @@ -449,12 +443,6 @@ int jffs2_compressors_init(void) int jffs2_compressors_exit(void) { /* Unregistering compressors */ -#ifdef CONFIG_JFFS2_LZO - jffs2_lzo_exit(); -#endif -#ifdef CONFIG_JFFS2_LZARI - jffs2_lzari_exit(); -#endif #ifdef CONFIG_JFFS2_RUBIN jffs2_dynrubin_exit(); jffs2_rubinmips_exit(); diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h index 89ceeed201eb..9ec6e37d3833 100644 --- a/fs/jffs2/compr.h +++ b/fs/jffs2/compr.h @@ -7,7 +7,7 @@ * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * - * $Id: compr.h,v 1.6 2004/07/16 15:17:57 dwmw2 Exp $ + * $Id: compr.h,v 1.8 2005/07/26 13:24:40 havasi Exp $ * */ @@ -103,13 +103,5 @@ void jffs2_rtime_exit(void); int jffs2_zlib_init(void); void jffs2_zlib_exit(void); #endif -#ifdef CONFIG_JFFS2_LZARI -int jffs2_lzari_init(void); -void jffs2_lzari_exit(void); -#endif -#ifdef CONFIG_JFFS2_LZO -int jffs2_lzo_init(void); -void jffs2_lzo_exit(void); -#endif #endif /* __JFFS2_COMPR_H__ */ diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h index 7bc51add62fa..a66d0a8b70e4 100644 --- a/include/linux/jffs2.h +++ b/include/linux/jffs2.h @@ -8,7 +8,7 @@ * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * - * $Id: jffs2.h,v 1.35 2005/07/24 15:15:51 dedekind Exp $ + * $Id: jffs2.h,v 1.36 2005/07/26 13:19:36 havasi Exp $ * */ @@ -43,8 +43,6 @@ #define JFFS2_COMPR_COPY 0x04 #define JFFS2_COMPR_DYNRUBIN 0x05 #define JFFS2_COMPR_ZLIB 0x06 -#define JFFS2_COMPR_LZO 0x07 -#define JFFS2_COMPR_LZARI 0x08 /* Compatibility flags. */ #define JFFS2_COMPAT_MASK 0xc000 /* What do to if an unknown nodetype is found */ #define JFFS2_NODE_ACCURATE 0x2000 -- cgit v1.2.3 From 638d983840bb64e02c29bdd6160bb9963f4090f7 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 6 Aug 2005 05:40:46 +0100 Subject: {MTD] add support for Intel's "Sibley" flash This updates the Primary Vendor-Specific Extended Query parsing to version 1.4 in order to get the information about the Configurable Programming Mode regions implemented in the Sibley flash, as well as selecting the appropriate write command code. This flash does not behave like traditional NOR flash when writing data. While mtdblock should just work, further changes are needed for JFFS2 use. Signed-off-by: Nicolas Pitre Signed-off-by: Thomas Gleixner --- drivers/mtd/chips/cfi_cmdset_0001.c | 88 +++++++++++++++++++++++++++---------- drivers/mtd/chips/gen_probe.c | 3 +- include/linux/mtd/cfi.h | 13 +++++- include/linux/mtd/mtd.h | 14 +++++- include/mtd/mtd-abi.h | 3 +- 5 files changed, 92 insertions(+), 29 deletions(-) (limited to 'include/linux') diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 308855e80f66..10c50604bcd5 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -4,7 +4,7 @@ * * (C) 2000 Red Hat. GPL'd * - * $Id: cfi_cmdset_0001.c,v 1.181 2005/08/06 04:16:48 nico Exp $ + * $Id: cfi_cmdset_0001.c,v 1.182 2005/08/06 04:40:41 nico Exp $ * * * 10/10/2000 Nicolas Pitre @@ -105,6 +105,7 @@ static struct mtd_chip_driver cfi_intelext_chipdrv = { static void cfi_tell_features(struct cfi_pri_intelext *extp) { int i; + printk(" Extended Query version %c.%c\n", extp->MajorVersion, extp->MinorVersion); printk(" Feature/Command Support: %4.4X\n", extp->FeatureSupport); printk(" - Chip Erase: %s\n", extp->FeatureSupport&1?"supported":"unsupported"); printk(" - Suspend Erase: %s\n", extp->FeatureSupport&2?"supported":"unsupported"); @@ -116,7 +117,8 @@ static void cfi_tell_features(struct cfi_pri_intelext *extp) printk(" - Page-mode read: %s\n", extp->FeatureSupport&128?"supported":"unsupported"); printk(" - Synchronous read: %s\n", extp->FeatureSupport&256?"supported":"unsupported"); printk(" - Simultaneous operations: %s\n", extp->FeatureSupport&512?"supported":"unsupported"); - for (i=10; i<32; i++) { + printk(" - Extended Flash Array: %s\n", extp->FeatureSupport&1024?"supported":"unsupported"); + for (i=11; i<32; i++) { if (extp->FeatureSupport & (1<BlkStatusRegMask); printk(" - Lock Bit Active: %s\n", extp->BlkStatusRegMask&1?"yes":"no"); - printk(" - Valid Bit Active: %s\n", extp->BlkStatusRegMask&2?"yes":"no"); - for (i=2; i<16; i++) { + printk(" - Lock-Down Bit Active: %s\n", extp->BlkStatusRegMask&2?"yes":"no"); + for (i=2; i<3; i++) { if (extp->BlkStatusRegMask & (1<BlkStatusRegMask&16?"yes":"no"); + printk(" - EFA Lock-Down Bit: %s\n", extp->BlkStatusRegMask&32?"yes":"no"); + for (i=6; i<16; i++) { + if (extp->BlkStatusRegMask & (1<VccOptimal >> 4, extp->VccOptimal & 0xf); if (extp->VppOptimal) @@ -253,7 +261,7 @@ read_pri_intelext(struct map_info *map, __u16 adr) return NULL; if (extp->MajorVersion != '1' || - (extp->MinorVersion < '0' || extp->MinorVersion > '3')) { + (extp->MinorVersion < '0' || extp->MinorVersion > '4')) { printk(KERN_ERR " Unknown Intel/Sharp Extended Query " "version %c.%c.\n", extp->MajorVersion, extp->MinorVersion); @@ -266,7 +274,7 @@ read_pri_intelext(struct map_info *map, __u16 adr) extp->BlkStatusRegMask = le16_to_cpu(extp->BlkStatusRegMask); extp->ProtRegAddr = le16_to_cpu(extp->ProtRegAddr); - if (extp->MajorVersion == '1' && extp->MinorVersion == '3') { + if (extp->MajorVersion == '1' && extp->MinorVersion >= '3') { unsigned int extra_size = 0; int nb_parts, i; @@ -275,7 +283,7 @@ read_pri_intelext(struct map_info *map, __u16 adr) sizeof(struct cfi_intelext_otpinfo); /* Burst Read info */ - extra_size += 6; + extra_size += (extp->MinorVersion < '4') ? 6 : 5; /* Number of hardware-partitions */ extra_size += 1; @@ -283,6 +291,10 @@ read_pri_intelext(struct map_info *map, __u16 adr) goto need_more; nb_parts = extp->extra[extra_size - 1]; + /* skip the sizeof(partregion) field in CFI 1.4 */ + if (extp->MinorVersion >= '4') + extra_size += 2; + for (i = 0; i < nb_parts; i++) { struct cfi_intelext_regioninfo *rinfo; rinfo = (struct cfi_intelext_regioninfo *)&extp->extra[extra_size]; @@ -294,6 +306,9 @@ read_pri_intelext(struct map_info *map, __u16 adr) * sizeof(struct cfi_intelext_blockinfo); } + if (extp->MinorVersion >= '4') + extra_size += sizeof(struct cfi_intelext_programming_regioninfo); + if (extp_size < sizeof(*extp) + extra_size) { need_more: extp_size = sizeof(*extp) + extra_size; @@ -490,7 +505,7 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd, * arrangement at this point. This can be rearranged in the future * if someone feels motivated enough. --nico */ - if (extp && extp->MajorVersion == '1' && extp->MinorVersion == '3' + if (extp && extp->MajorVersion == '1' && extp->MinorVersion >= '3' && extp->FeatureSupport & (1 << 9)) { struct cfi_private *newcfi; struct flchip *chip; @@ -502,12 +517,16 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd, sizeof(struct cfi_intelext_otpinfo); /* Burst Read info */ - offs += 6; + offs += (extp->MinorVersion < '4') ? 6 : 5; /* Number of partition regions */ numregions = extp->extra[offs]; offs += 1; + /* skip the sizeof(partregion) field in CFI 1.4 */ + if (extp->MinorVersion >= '4') + offs += 2; + /* Number of hardware partitions */ numparts = 0; for (i = 0; i < numregions; i++) { @@ -519,6 +538,20 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd, sizeof(struct cfi_intelext_blockinfo); } + /* Programming Region info */ + if (extp->MinorVersion >= '4') { + struct cfi_intelext_programming_regioninfo *prinfo; + prinfo = (struct cfi_intelext_programming_regioninfo *)&extp->extra[offs]; + MTD_PROGREGION_SIZE(mtd) = cfi->interleave << prinfo->ProgRegShift; + MTD_PROGREGION_CTRLMODE_VALID(mtd) = cfi->interleave * prinfo->ControlValid; + MTD_PROGREGION_CTRLMODE_INVALID(mtd) = cfi->interleave * prinfo->ControlInvalid; + mtd->flags |= MTD_PROGRAM_REGIONS; + printk(KERN_DEBUG "%s: program region size/ctrl_valid/ctrl_inval = %d/%d/%d\n", + map->name, MTD_PROGREGION_SIZE(mtd), + MTD_PROGREGION_CTRLMODE_VALID(mtd), + MTD_PROGREGION_CTRLMODE_INVALID(mtd)); + } + /* * All functions below currently rely on all chips having * the same geometry so we'll just assume that all hardware @@ -1222,12 +1255,17 @@ static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, adr += chip->start; - /* Let's determine this according to the interleave only once */ + /* Let's determine those according to the interleave only once */ status_OK = CMD(0x80); switch (mode) { - case FL_WRITING: write_cmd = CMD(0x40); break; - case FL_OTP_WRITE: write_cmd = CMD(0xc0); break; - default: return -EINVAL; + case FL_WRITING: + write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0x40) : CMD(0x41); + break; + case FL_OTP_WRITE: + write_cmd = CMD(0xc0); + break; + default: + return -EINVAL; } spin_lock(chip->mutex); @@ -1410,16 +1448,17 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, unsigned long adr, const u_char *buf, int len) { struct cfi_private *cfi = map->fldrv_priv; - map_word status, status_OK; + map_word status, status_OK, write_cmd; unsigned long cmd_adr, timeo; int wbufsize, z, ret=0, bytes, words; wbufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize; adr += chip->start; cmd_adr = adr & ~(wbufsize-1); - + /* Let's determine this according to the interleave only once */ status_OK = CMD(0x80); + write_cmd = (cfi->cfiq->P_ID != 0x0200) ? CMD(0xe8) : CMD(0xe9); spin_lock(chip->mutex); ret = get_chip(map, chip, cmd_adr, FL_WRITING); @@ -1451,7 +1490,7 @@ static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, z = 0; for (;;) { - map_write(map, CMD(0xe8), cmd_adr); + map_write(map, write_cmd, cmd_adr); status = map_read(map, cmd_adr); if (map_word_andequal(map, status, status_OK, status_OK)) @@ -2380,20 +2419,23 @@ static void cfi_intelext_destroy(struct mtd_info *mtd) kfree(mtd->eraseregions); } -static char im_name_1[]="cfi_cmdset_0001"; -static char im_name_3[]="cfi_cmdset_0003"; +static char im_name_0001[] = "cfi_cmdset_0001"; +static char im_name_0003[] = "cfi_cmdset_0003"; +static char im_name_0200[] = "cfi_cmdset_0200"; static int __init cfi_intelext_init(void) { - inter_module_register(im_name_1, THIS_MODULE, &cfi_cmdset_0001); - inter_module_register(im_name_3, THIS_MODULE, &cfi_cmdset_0001); + inter_module_register(im_name_0001, THIS_MODULE, &cfi_cmdset_0001); + inter_module_register(im_name_0003, THIS_MODULE, &cfi_cmdset_0001); + inter_module_register(im_name_0200, THIS_MODULE, &cfi_cmdset_0001); return 0; } static void __exit cfi_intelext_exit(void) { - inter_module_unregister(im_name_1); - inter_module_unregister(im_name_3); + inter_module_unregister(im_name_0001); + inter_module_unregister(im_name_0003); + inter_module_unregister(im_name_0200); } module_init(cfi_intelext_init); diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c index dc065b22f79e..28807eb9fc86 100644 --- a/drivers/mtd/chips/gen_probe.c +++ b/drivers/mtd/chips/gen_probe.c @@ -2,7 +2,7 @@ * Routines common to all CFI-type probes. * (C) 2001-2003 Red Hat, Inc. * GPL'd - * $Id: gen_probe.c,v 1.22 2005/01/24 23:49:50 rmk Exp $ + * $Id: gen_probe.c,v 1.23 2005/08/06 04:40:41 nico Exp $ */ #include @@ -235,6 +235,7 @@ static struct mtd_info *check_cmd_set(struct map_info *map, int primary) #ifdef CONFIG_MTD_CFI_INTELEXT case 0x0001: case 0x0003: + case 0x0200: return cfi_cmdset_0001(map, primary); #endif #ifdef CONFIG_MTD_CFI_AMDSTD diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index e6b6a1c66bd5..360cf626c288 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h @@ -1,7 +1,7 @@ /* Common Flash Interface structures * See http://support.intel.com/design/flash/technote/index.htm - * $Id: cfi.h,v 1.54 2005/06/06 23:04:36 tpoynor Exp $ + * $Id: cfi.h,v 1.55 2005/08/06 04:40:42 nico Exp $ */ #ifndef __MTD_CFI_H__ @@ -173,6 +173,15 @@ struct cfi_intelext_regioninfo { struct cfi_intelext_blockinfo BlockTypes[1]; } __attribute__((packed)); +struct cfi_intelext_programming_regioninfo { + uint8_t ProgRegShift; + uint8_t Reserved1; + uint8_t ControlValid; + uint8_t Reserved2; + uint8_t ControlInvalid; + uint8_t Reserved3; +} __attribute__((packed)); + /* Vendor-Specific PRI for AMD/Fujitsu Extended Command Set (0x0002) */ struct cfi_pri_amdstd { @@ -316,7 +325,7 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf #define CMD(x) cfi_build_cmd((x), map, cfi) -static inline unsigned char cfi_merge_status(map_word val, struct map_info *map, +static inline unsigned long cfi_merge_status(map_word val, struct map_info *map, struct cfi_private *cfi) { int wordwidth, words_per_bus, chip_mode, chips_per_word; diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index c50c3f3927d9..ab5804183916 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -1,5 +1,5 @@ /* - * $Id: mtd.h,v 1.59 2005/04/11 10:19:02 gleixner Exp $ + * $Id: mtd.h,v 1.60 2005/08/06 04:40:42 nico Exp $ * * Copyright (C) 1999-2003 David Woodhouse et al. * @@ -72,7 +72,17 @@ struct mtd_info { u_int32_t oobsize; // Amount of OOB data per block (e.g. 16) u_int32_t ecctype; u_int32_t eccsize; - + + /* + * Reuse some of the above unused fields in the case of NOR flash + * with configurable programming regions to avoid modifying the + * user visible structure layout/size. Only valid when the + * MTD_PROGRAM_REGIONS flag is set. + * (Maybe we should have an union for those?) + */ +#define MTD_PROGREGION_SIZE(mtd) (mtd)->oobblock +#define MTD_PROGREGION_CTRLMODE_VALID(mtd) (mtd)->oobsize +#define MTD_PROGREGION_CTRLMODE_INVALID(mtd) (mtd)->ecctype // Kernel-only stuff starts here. char *name; diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h index 428d9122940b..16e74cafd0b4 100644 --- a/include/mtd/mtd-abi.h +++ b/include/mtd/mtd-abi.h @@ -1,5 +1,5 @@ /* - * $Id: mtd-abi.h,v 1.11 2005/05/19 16:08:58 gleixner Exp $ + * $Id: mtd-abi.h,v 1.12 2005/08/06 04:40:43 nico Exp $ * * Portions of MTD ABI definition which are shared by kernel and user space */ @@ -42,6 +42,7 @@ struct mtd_oob_buf { #define MTD_OOB 64 // Out-of-band data (NAND flash) #define MTD_ECC 128 // Device capable of automatic ECC #define MTD_NO_VIRTBLOCKS 256 // Virtual blocks not allowed +#define MTD_PROGRAM_REGIONS 512 // Configurable Programming Regions // Some common devices / combinations of capabilities #define MTD_CAP_ROM 0 -- cgit v1.2.3 From cd5f6346bc28a41375412b49b290d22ee4e4bbe8 Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Mon, 11 Jul 2005 11:41:53 +0100 Subject: [MTD] Add initial support for OneNAND flash chips OneNAND is a new flash technology from Samsung with integrated SRAM buffers and logic interface. Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/Kconfig | 10 +- drivers/mtd/Makefile | 4 +- drivers/mtd/onenand/Kconfig | 32 + drivers/mtd/onenand/Makefile | 9 + drivers/mtd/onenand/omap-onenand.c | 178 +++++ drivers/mtd/onenand/onenand_base.c | 1462 ++++++++++++++++++++++++++++++++++++ include/linux/mtd/onenand.h | 134 ++++ include/linux/mtd/onenand_regs.h | 167 ++++ 8 files changed, 1990 insertions(+), 6 deletions(-) create mode 100644 drivers/mtd/onenand/Kconfig create mode 100644 drivers/mtd/onenand/Makefile create mode 100644 drivers/mtd/onenand/omap-onenand.c create mode 100644 drivers/mtd/onenand/onenand_base.c create mode 100644 include/linux/mtd/onenand.h create mode 100644 include/linux/mtd/onenand_regs.h (limited to 'include/linux') diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig index 843a1cbe0866..3dbfbafb3481 100644 --- a/drivers/mtd/Kconfig +++ b/drivers/mtd/Kconfig @@ -1,4 +1,4 @@ -# $Id: Kconfig,v 1.9 2005/06/16 08:49:29 sean Exp $ +# $Id: Kconfig,v 1.10 2005/07/11 10:39:27 gleixner Exp $ menu "Memory Technology Devices (MTD)" @@ -259,9 +259,9 @@ config RFD_FTL ---help--- This provides support for the flash translation layer known as the Resident Flash Disk (RFD), as used by the Embedded BIOS - of General Software. - See http://www.gensw.com/pages/prod/bios/rfd.htm for further - information. + of General Software. There is a blurb at: + + http://www.gensw.com/pages/prod/bios/rfd.htm source "drivers/mtd/chips/Kconfig" @@ -271,5 +271,7 @@ source "drivers/mtd/devices/Kconfig" source "drivers/mtd/nand/Kconfig" +source "drivers/mtd/onenand/Kconfig" + endmenu diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile index cb16b7d478ce..fc9374407c2b 100644 --- a/drivers/mtd/Makefile +++ b/drivers/mtd/Makefile @@ -1,7 +1,7 @@ # # Makefile for the memory technology device drivers. # -# $Id: Makefile.common,v 1.6 2005/06/16 08:49:29 sean Exp $ +# $Id: Makefile.common,v 1.7 2005/07/11 10:39:27 gleixner Exp $ # Core functionality. mtd-y := mtdcore.o @@ -25,4 +25,4 @@ obj-$(CONFIG_RFD_FTL) += rfd_ftl.o mtd_blkdevs.o nftl-objs := nftlcore.o nftlmount.o inftl-objs := inftlcore.o inftlmount.o -obj-y += chips/ maps/ devices/ nand/ +obj-y += chips/ maps/ devices/ nand/ onenand/ diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig new file mode 100644 index 000000000000..7d76ede984d8 --- /dev/null +++ b/drivers/mtd/onenand/Kconfig @@ -0,0 +1,32 @@ +# +# linux/drivers/mtd/onenand/Kconfig +# + +menu "OneNAND Flash Device Drivers (EXPERIMENTAL)" + depends on MTD != n && EXPERIMENTAL + +config MTD_ONENAND + tristate "OneNAND Device Support" + depends on MTD + help + This enables support for accessing all type of OneNAND flash + devices. For further information see + . + +config MTD_ONENAND_VERIFY_WRITE + bool "Verify OneNAND page writes" + depends on MTD_ONENAND + help + This adds an extra check when data is written to the flash. The + OneNAND flash device internally checks only bits transitioning + from 1 to 0. There is a rare possibility that even though the + device thinks the write was successful, a bit could have been + flipped accidentaly due to device wear or something else. + +config MTD_ONENAND_OMAP + tristate "OneNAND Flash device on OMAP board" + depends on ARCH_OMAP && MTD_ONENAND + help + Support for OneNAND flash on TI OMAP board. + +endmenu diff --git a/drivers/mtd/onenand/Makefile b/drivers/mtd/onenand/Makefile new file mode 100644 index 000000000000..f4e75864d8b5 --- /dev/null +++ b/drivers/mtd/onenand/Makefile @@ -0,0 +1,9 @@ +# +# Makefile for the OneNAND MTD +# + +# Core functionality. +obj-$(CONFIG_MTD_ONENAND) += onenand_base.o + +# Board specific. +obj-$(CONFIG_MTD_ONENAND_OMAP) += omap-onenand.o diff --git a/drivers/mtd/onenand/omap-onenand.c b/drivers/mtd/onenand/omap-onenand.c new file mode 100644 index 000000000000..56e1aec6b835 --- /dev/null +++ b/drivers/mtd/onenand/omap-onenand.c @@ -0,0 +1,178 @@ +/* + * linux/drivers/mtd/onenand/omap-onenand.c + * + * Copyright (c) 2005 Samsung Electronics + * Kyungmin Park + * + * Derived from linux/drivers/mtd/nand/omap-nand-flash.c + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Overview: + * This is a device driver for the OneNAND flash device for TI OMAP boards. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define OMAP_ONENAND_FLASH_START1 OMAP_CS2A_PHYS +#define OMAP_ONENAND_FLASH_START2 OMAP_CS0_PHYS +/* + * MTD structure for OMAP board + */ +static struct mtd_info *omap_onenand_mtd = NULL; + +/* + * Define partitions for flash devices + */ + +#ifdef CONFIG_MTD_PARTITIONS +static struct mtd_partition static_partition[] = { + { + .name = "X-Loader + U-Boot", + .offset = 0, + .size = SZ_128K, + .mask_flags = MTD_WRITEABLE /* force read-only */ + }, + { + .name = "U-Boot Environment", + .offset = MTDPART_OFS_APPEND, + .size = SZ_128K, + .mask_flags = MTD_WRITEABLE /* force read-only */ + }, + { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = 2 * SZ_1M + }, + { + .name = "filesystem0", + .offset = MTDPART_OFS_APPEND, + .size = SZ_16M, + }, + { + .name = "filesystem1", + .offset = MTDPART_OFS_APPEND, + .size = MTDPART_SIZ_FULL, + }, +}; + +const char *part_probes[] = { "cmdlinepart", NULL, }; + +#endif + +/* Scan to find existance of the device at base. + This also allocates oob and data internal buffers */ +static char onenand_name[] = "onenand"; + +/* + * Main initialization routine + */ +static int __init omap_onenand_init (void) +{ + struct onenand_chip *this; + struct mtd_partition *dynamic_partition = 0; + int err = 0; + + /* Allocate memory for MTD device structure and private data */ + omap_onenand_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct onenand_chip), + GFP_KERNEL); + if (!omap_onenand_mtd) { + printk (KERN_WARNING "Unable to allocate OneNAND MTD device structure.\n"); + err = -ENOMEM; + goto out; + } + + /* Get pointer to private data */ + this = (struct onenand_chip *) (&omap_onenand_mtd[1]); + + /* Initialize structures */ + memset((char *) omap_onenand_mtd, 0, sizeof(struct mtd_info) + sizeof(struct onenand_chip)); + + /* Link the private data with the MTD structure */ + omap_onenand_mtd->priv = this; + + /* try the first address */ + this->base = ioremap(OMAP_ONENAND_FLASH_START1, SZ_128K); + omap_onenand_mtd->name = onenand_name; + if (onenand_scan(omap_onenand_mtd, 1)){ + /* try the second address */ + iounmap(this->base); + this->base = ioremap(OMAP_ONENAND_FLASH_START2, SZ_128K); + if (onenand_scan(omap_onenand_mtd, 1)) { + iounmap(this->base); + err = -ENXIO; + goto out_mtd; + } + } + + /* Register the partitions */ + switch (omap_onenand_mtd->size) { + case SZ_128M: + case SZ_64M: + case SZ_32M: +#ifdef CONFIG_MTD_PARTITIONS + err = parse_mtd_partitions(omap_onenand_mtd, part_probes, + &dynamic_partition, 0); + if (err > 0) + err = add_mtd_partitions(omap_onenand_mtd, + dynamic_partition, err); + else if (1) + err = add_mtd_partitions(omap_onenand_mtd, + static_partition, + ARRAY_SIZE(static_partition)); + else +#endif + err = add_mtd_device(omap_onenand_mtd); + if (err) + goto out_buf; + break; + + default: + printk(KERN_WARNING "Unsupported OneNAND device\n"); + err = -ENXIO; + goto out_buf; + } + + return 0; + +out_buf: + onenand_release(omap_onenand_mtd); + iounmap(this->base); +out_mtd: + kfree(omap_onenand_mtd); +out: + return err; +} + +/* + * Clean up routine + */ +static void __exit omap_onenand_cleanup (void) +{ + struct onenand_chip *this = omap_onenand_mtd->priv; + + /* onenand_release frees MTD partitions, MTD structure + and onenand internal buffers */ + onenand_release(omap_onenand_mtd); + iounmap(this->base); + kfree(omap_onenand_mtd); +} + +module_init(omap_onenand_init); +module_exit(omap_onenand_cleanup); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Kyungmin Park "); +MODULE_DESCRIPTION("Glue layer for OneNAND flash on OMAP boards"); diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c new file mode 100644 index 000000000000..bcce22ae3cb1 --- /dev/null +++ b/drivers/mtd/onenand/onenand_base.c @@ -0,0 +1,1462 @@ +/* + * linux/drivers/mtd/onenand/onenand_base.c + * + * Copyright (C) 2005 Samsung Electronics + * Kyungmin Park + * + * 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 +#include +#include +#include +#include +#include + +#include + +/** + * onenand_oob_64 - oob info for large (2KB) page + */ +static struct nand_oobinfo onenand_oob_64 = { + .useecc = MTD_NANDECC_AUTOPLACE, + .eccbytes = 20, + .eccpos = { + 8, 9, 10, 11, 12, + 24, 25, 26, 27, 28, + 40, 41, 42, 43, 44, + 56, 57, 58, 59, 60, + }, + .oobfree = { + {2, 3}, {14, 2}, {18, 3}, {30, 2}, + {24, 3}, {46, 2}, {40, 3}, {62, 2} } +}; + +/** + * onenand_oob_32 - oob info for middle (1KB) page + */ +static struct nand_oobinfo onenand_oob_32 = { + .useecc = MTD_NANDECC_AUTOPLACE, + .eccbytes = 10, + .eccpos = { + 8, 9, 10, 11, 12, + 24, 25, 26, 27, 28, + }, + .oobfree = { {2, 3}, {14, 2}, {18, 3}, {30, 2} } +}; + +static const unsigned char ffchars[] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 16 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 32 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 48 */ + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 64 */ +}; + +/** + * onenand_readw - [OneNAND Interface] Read OneNAND register + * @param addr address to read + * + * Read OneNAND register + */ +static unsigned short onenand_readw(void __iomem *addr) +{ + return readw(addr); +} + +/** + * onenand_writew - [OneNAND Interface] Write OneNAND register with value + * @param value value to write + * @param addr address to write + * + * Write OneNAND register with value + */ +static void onenand_writew(unsigned short value, void __iomem *addr) +{ + writew(value, addr); +} + +/** + * onenand_block_address - [DEFAULT] Get block address + * @param device the device id + * @param block the block + * @return translated block address if DDP, otherwise same + * + * Setup Start Address 1 Register (F100h) + */ +static int onenand_block_address(int device, int block) +{ + if (device & ONENAND_DEVICE_IS_DDP) { + /* Device Flash Core select, NAND Flash Block Address */ + int dfs = 0, density, mask; + + density = device >> ONENAND_DEVICE_DENSITY_SHIFT; + mask = (1 << (density + 6)); + + if (block & mask) + dfs = 1; + + return (dfs << ONENAND_DDP_SHIFT) | (block & (mask - 1)); + } + + return block; +} + +/** + * onenand_bufferram_address - [DEFAULT] Get bufferram address + * @param device the device id + * @param block the block + * @return set DBS value if DDP, otherwise 0 + * + * Setup Start Address 2 Register (F101h) for DDP + */ +static int onenand_bufferram_address(int device, int block) +{ + if (device & ONENAND_DEVICE_IS_DDP) { + /* Device BufferRAM Select */ + int dbs = 0, density, mask; + + density = device >> ONENAND_DEVICE_DENSITY_SHIFT; + mask = (1 << (density + 6)); + + if (block & mask) + dbs = 1; + + return (dbs << ONENAND_DDP_SHIFT); + } + + return 0; +} + +/** + * onenand_page_address - [DEFAULT] Get page address + * @param page the page address + * @param sector the sector address + * @return combined page and sector address + * + * Setup Start Address 8 Register (F107h) + */ +static int onenand_page_address(int page, int sector) +{ + /* Flash Page Address, Flash Sector Address */ + int fpa, fsa; + + fpa = page & ONENAND_FPA_MASK; + fsa = sector & ONENAND_FSA_MASK; + + return ((fpa << ONENAND_FPA_SHIFT) | fsa); +} + +/** + * onenand_buffer_address - [DEFAULT] Get buffer address + * @param dataram1 DataRAM index + * @param sectors the sector address + * @param count the number of sectors + * @return the start buffer value + * + * Setup Start Buffer Register (F200h) + */ +static int onenand_buffer_address(int dataram1, int sectors, int count) +{ + int bsa, bsc; + + /* BufferRAM Sector Address */ + bsa = sectors & ONENAND_BSA_MASK; + + if (dataram1) + bsa |= ONENAND_BSA_DATARAM1; /* DataRAM1 */ + else + bsa |= ONENAND_BSA_DATARAM0; /* DataRAM0 */ + + /* BufferRAM Sector Count */ + bsc = count & ONENAND_BSC_MASK; + + return ((bsa << ONENAND_BSA_SHIFT) | bsc); +} + +/** + * onenand_command - [DEFAULT] Send command to OneNAND device + * @param mtd MTD device structure + * @param cmd the command to be sent + * @param addr offset to read from or write to + * @param len number of bytes to read or write + * + * Send command to OneNAND device. This function is used for middle/large page + * devices (1KB/2KB Bytes per page) + */ +static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t len) +{ + struct onenand_chip *this = mtd->priv; + int value, readcmd = 0; + int block, page; + /* Now we use page size operation */ + int sectors = 4, count = 4; + + /* Address translation */ + switch (cmd) { + case ONENAND_CMD_UNLOCK: + case ONENAND_CMD_LOCK: + case ONENAND_CMD_LOCK_TIGHT: + block = -1; + page = -1; + break; + + case ONENAND_CMD_ERASE: + case ONENAND_CMD_BUFFERRAM: + block = (int) (addr >> this->erase_shift); + page = -1; + break; + + default: + block = (int) (addr >> this->erase_shift); + page = (int) (addr >> this->page_shift); + page &= this->page_mask; + break; + } + + /* NOTE: The setting order of the registers is very important! */ + if (cmd == ONENAND_CMD_BUFFERRAM) { + /* Select DataRAM for DDP */ + value = onenand_bufferram_address(this->device_id, block); + this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); + + /* Switch to the next data buffer */ + ONENAND_SET_NEXT_BUFFERRAM(this); + + return 0; + } + + if (block != -1) { + /* Write 'DFS, FBA' of Flash */ + value = onenand_block_address(this->device_id, block); + this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); + } + + if (page != -1) { + int dataram; + + switch (cmd) { + case ONENAND_CMD_READ: + case ONENAND_CMD_READOOB: + dataram = ONENAND_SET_NEXT_BUFFERRAM(this); + readcmd = 1; + break; + + default: + dataram = ONENAND_CURRENT_BUFFERRAM(this); + break; + } + + /* Write 'FPA, FSA' of Flash */ + value = onenand_page_address(page, sectors); + this->write_word(value, this->base + ONENAND_REG_START_ADDRESS8); + + /* Write 'BSA, BSC' of DataRAM */ + value = onenand_buffer_address(dataram, sectors, count); + this->write_word(value, this->base + ONENAND_REG_START_BUFFER); + + if (readcmd) { + /* Select DataRAM for DDP */ + value = onenand_bufferram_address(this->device_id, block); + this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); + } + } + + /* Interrupt clear */ + this->write_word(ONENAND_INT_CLEAR, this->base + ONENAND_REG_INTERRUPT); + + /* Write command */ + this->write_word(cmd, this->base + ONENAND_REG_COMMAND); + + return 0; +} + +/** + * onenand_wait - [DEFAULT] wait until the command is done + * @param mtd MTD device structure + * @param state state to select the max. timeout value + * + * Wait for command done. This applies to all OneNAND command + * Read can take up to 30us, erase up to 2ms and program up to 350us + * according to general OneNAND specs + */ +static int onenand_wait(struct mtd_info *mtd, int state) +{ + struct onenand_chip * this = mtd->priv; + unsigned long timeout; + unsigned int flags = ONENAND_INT_MASTER; + unsigned int interrupt = 0; + unsigned int ctrl, ecc; + + /* The 20 msec is enough */ + timeout = jiffies + msecs_to_jiffies(20); + while (time_before(jiffies, timeout)) { + interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT); + + if (interrupt & flags) + break; + + if (state != FL_READING) + cond_resched(); + } + /* To get correct interrupt status in timeout case */ + interrupt = this->read_word(this->base + ONENAND_REG_INTERRUPT); + + ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS); + + if (ctrl & ONENAND_CTRL_ERROR) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x", ctrl); + return -EIO; + } + + if (ctrl & ONENAND_CTRL_LOCK) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error = 0x%04x", ctrl); + return -EIO; + } + + if (interrupt & ONENAND_INT_READ) { + ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS); + if (ecc & ONENAND_ECC_2BIT_ALL) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x", ecc); + return -EBADMSG; + } + } + + return 0; +} + +/** + * onenand_bufferram_offset - [DEFAULT] BufferRAM offset + * @param mtd MTD data structure + * @param area BufferRAM area + * @return offset given area + * + * Return BufferRAM offset given area + */ +static inline int onenand_bufferram_offset(struct mtd_info *mtd, int area) +{ + struct onenand_chip *this = mtd->priv; + + if (ONENAND_CURRENT_BUFFERRAM(this)) { + if (area == ONENAND_DATARAM) + return mtd->oobblock; + if (area == ONENAND_SPARERAM) + return mtd->oobsize; + } + + return 0; +} + +/** + * onenand_read_bufferram - [OneNAND Interface] Read the bufferram area + * @param mtd MTD data structure + * @param area BufferRAM area + * @param buffer the databuffer to put/get data + * @param offset offset to read from or write to + * @param count number of bytes to read/write + * + * Read the BufferRAM area + */ +static int onenand_read_bufferram(struct mtd_info *mtd, int area, + unsigned char *buffer, int offset, size_t count) +{ + struct onenand_chip *this = mtd->priv; + void __iomem *bufferram; + + bufferram = this->base + area; + + bufferram += onenand_bufferram_offset(mtd, area); + + memcpy(buffer, bufferram + offset, count); + + return 0; +} + +/** + * onenand_write_bufferram - [OneNAND Interface] Write the bufferram area + * @param mtd MTD data structure + * @param area BufferRAM area + * @param buffer the databuffer to put/get data + * @param offset offset to read from or write to + * @param count number of bytes to read/write + * + * Write the BufferRAM area + */ +static int onenand_write_bufferram(struct mtd_info *mtd, int area, + const unsigned char *buffer, int offset, size_t count) +{ + struct onenand_chip *this = mtd->priv; + void __iomem *bufferram; + + bufferram = this->base + area; + + bufferram += onenand_bufferram_offset(mtd, area); + + memcpy(bufferram + offset, buffer, count); + + return 0; +} + +/** + * onenand_check_bufferram - [GENERIC] Check BufferRAM information + * @param mtd MTD data structure + * @param addr address to check + * @return 1 if there are valid data, otherwise 0 + * + * Check bufferram if there is data we required + */ +static int onenand_check_bufferram(struct mtd_info *mtd, loff_t addr) +{ + struct onenand_chip *this = mtd->priv; + int block, page; + int i; + + block = (int) (addr >> this->erase_shift); + page = (int) (addr >> this->page_shift); + page &= this->page_mask; + + i = ONENAND_CURRENT_BUFFERRAM(this); + + /* Is there valid data? */ + if (this->bufferram[i].block == block && + this->bufferram[i].page == page && + this->bufferram[i].valid) + return 1; + + return 0; +} + +/** + * onenand_update_bufferram - [GENERIC] Update BufferRAM information + * @param mtd MTD data structure + * @param addr address to update + * @param valid valid flag + * + * Update BufferRAM information + */ +static int onenand_update_bufferram(struct mtd_info *mtd, loff_t addr, + int valid) +{ + struct onenand_chip *this = mtd->priv; + int block, page; + int i; + + block = (int) (addr >> this->erase_shift); + page = (int) (addr >> this->page_shift); + page &= this->page_mask; + + /* Invalidate BufferRAM */ + for (i = 0; i < MAX_BUFFERRAM; i++) { + if (this->bufferram[i].block == block && + this->bufferram[i].page == page) + this->bufferram[i].valid = 0; + } + + /* Update BufferRAM */ + i = ONENAND_CURRENT_BUFFERRAM(this); + this->bufferram[i].block = block; + this->bufferram[i].page = page; + this->bufferram[i].valid = valid; + + return 0; +} + +/** + * onenand_get_device - [GENERIC] Get chip for selected access + * @param mtd MTD device structure + * @param new_state the state which is requested + * + * Get the device and lock it for exclusive access + */ +static void onenand_get_device(struct mtd_info *mtd, int new_state) +{ + struct onenand_chip *this = mtd->priv; + DECLARE_WAITQUEUE(wait, current); + + /* + * Grab the lock and see if the device is available + */ + while (1) { + spin_lock(&this->chip_lock); + if (this->state == FL_READY) { + this->state = new_state; + spin_unlock(&this->chip_lock); + break; + } + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&this->wq, &wait); + spin_unlock(&this->chip_lock); + schedule(); + remove_wait_queue(&this->wq, &wait); + } +} + +/** + * onenand_release_device - [GENERIC] release chip + * @param mtd MTD device structure + * + * Deselect, release chip lock and wake up anyone waiting on the device + */ +static void onenand_release_device(struct mtd_info *mtd) +{ + struct onenand_chip *this = mtd->priv; + + /* Release the chip */ + spin_lock(&this->chip_lock); + this->state = FL_READY; + wake_up(&this->wq); + spin_unlock(&this->chip_lock); +} + +/** + * onenand_read_ecc - [MTD Interface] Read data with ECC + * @param mtd MTD device structure + * @param from offset to read from + * @param len number of bytes to read + * @param retlen pointer to variable to store the number of read bytes + * @param buf the databuffer to put data + * @param oob_buf filesystem supplied oob data buffer + * @param oobsel oob selection structure + * + * OneNAND read with ECC + */ +static int onenand_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf, + u_char *oob_buf, struct nand_oobinfo *oobsel) +{ + struct onenand_chip *this = mtd->priv; + int read = 0, column; + int thislen; + int ret = 0; + + DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_ecc: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); + + /* Do not allow reads past end of device */ + if ((from + len) > mtd->size) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_ecc: Attempt read beyond end of device\n"); + *retlen = 0; + return -EINVAL; + } + + /* Grab the lock and see if the device is available */ + onenand_get_device(mtd, FL_READING); + + /* TODO handling oob */ + + while (read < len) { + thislen = min_t(int, mtd->oobblock, len - read); + + column = from & (mtd->oobblock - 1); + if (column + thislen > mtd->oobblock) + thislen = mtd->oobblock - column; + + if (!onenand_check_bufferram(mtd, from)) { + this->command(mtd, ONENAND_CMD_READ, from, mtd->oobblock); + + ret = this->wait(mtd, FL_READING); + /* First copy data and check return value for ECC handling */ + onenand_update_bufferram(mtd, from, 1); + } + + this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen); + + read += thislen; + + if (read == len) + break; + + if (ret) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_ecc: read failed = %d\n", ret); + goto out; + } + + from += thislen; + buf += thislen; + } + +out: + /* Deselect and wake up anyone waiting on the device */ + onenand_release_device(mtd); + + /* + * Return success, if no ECC failures, else -EBADMSG + * fs driver will take care of that, because + * retlen == desired len and result == -EBADMSG + */ + *retlen = read; + return ret; +} + +/** + * onenand_read - [MTD Interface] MTD compability function for onenand_read_ecc + * @param mtd MTD device structure + * @param from offset to read from + * @param len number of bytes to read + * @param retlen pointer to variable to store the number of read bytes + * @param buf the databuffer to put data + * + * This function simply calls onenand_read_ecc with oob buffer and oobsel = NULL +*/ +static int onenand_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + return onenand_read_ecc(mtd, from, len, retlen, buf, NULL, NULL); +} + +/** + * onenand_read_oob - [MTD Interface] OneNAND read out-of-band + * @param mtd MTD device structure + * @param from offset to read from + * @param len number of bytes to read + * @param retlen pointer to variable to store the number of read bytes + * @param buf the databuffer to put data + * + * OneNAND read out-of-band data from the spare area + */ +static int onenand_read_oob(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct onenand_chip *this = mtd->priv; + int read = 0, thislen, column; + int ret = 0; + + DEBUG(MTD_DEBUG_LEVEL3, "onenand_read_oob: from = 0x%08x, len = %i\n", (unsigned int) from, (int) len); + + /* Initialize return length value */ + *retlen = 0; + + /* Do not allow reads past end of device */ + if (unlikely((from + len) > mtd->size)) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: Attempt read beyond end of device\n"); + return -EINVAL; + } + + /* Grab the lock and see if the device is available */ + onenand_get_device(mtd, FL_READING); + + column = from & (mtd->oobsize - 1); + + while (read < len) { + thislen = mtd->oobsize - column; + thislen = min_t(int, thislen, len); + + this->command(mtd, ONENAND_CMD_READOOB, from, mtd->oobsize); + + onenand_update_bufferram(mtd, from, 0); + + ret = this->wait(mtd, FL_READING); + /* First copy data and check return value for ECC handling */ + + this->read_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen); + + read += thislen; + + if (read == len) + break; + + if (ret) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_read_oob: read failed = %d\n", ret); + goto out; + } + + buf += thislen; + + /* Read more? */ + if (read < len) { + /* Page size */ + from += mtd->oobblock; + column = 0; + } + } + +out: + /* Deselect and wake up anyone waiting on the device */ + onenand_release_device(mtd); + + *retlen = read; + return ret; +} + +#ifdef CONFIG_MTD_ONENAND_VERIFY_WRITE +/** + * onenand_verify_page - [GENERIC] verify the chip contents after a write + * @param mtd MTD device structure + * @param buf the databuffer to verify + * @param block block address + * @param page page address + * + * Check DataRAM area directly + */ +static int onenand_verify_page(struct mtd_info *mtd, u_char *buf, + loff_t addr, int block, int page) +{ + struct onenand_chip *this = mtd->priv; + void __iomem *dataram0, *dataram1; + int ret = 0; + + this->command(mtd, ONENAND_CMD_READ, addr, mtd->oobblock); + + ret = this->wait(mtd, FL_READING); + if (ret) + return ret; + + onenand_update_bufferram(mtd, addr, 1); + + /* Check, if the two dataram areas are same */ + dataram0 = this->base + ONENAND_DATARAM; + dataram1 = dataram0 + mtd->oobblock; + + if (memcmp(dataram0, dataram1, mtd->oobblock)) + return -EBADMSG; + + return 0; +} +#else +#define onenand_verify_page(...) (0) +#endif + +#define NOTALIGNED(x) ((x & (mtd->oobblock - 1)) != 0) + +/** + * onenand_write_ecc - [MTD Interface] OneNAND write with ECC + * @param mtd MTD device structure + * @param to offset to write to + * @param len number of bytes to write + * @param retlen pointer to variable to store the number of written bytes + * @param buf the data to write + * @param eccbuf filesystem supplied oob data buffer + * @param oobsel oob selection structure + * + * OneNAND write with ECC + */ +static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf, + u_char *eccbuf, struct nand_oobinfo *oobsel) +{ + struct onenand_chip *this = mtd->priv; + int written = 0; + int ret = 0; + + DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_ecc: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); + + /* Initialize retlen, in case of early exit */ + *retlen = 0; + + /* Do not allow writes past end of device */ + if (unlikely((to + len) > mtd->size)) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: Attempt write to past end of device\n"); + return -EINVAL; + } + + /* Reject writes, which are not page aligned */ + if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(len))) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: Attempt to write not page aligned data\n"); + return -EINVAL; + } + + /* Grab the lock and see if the device is available */ + onenand_get_device(mtd, FL_WRITING); + + /* Loop until all data write */ + while (written < len) { + int thislen = min_t(int, mtd->oobblock, len - written); + + this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobblock); + + this->write_bufferram(mtd, ONENAND_DATARAM, buf, 0, thislen); + this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize); + + this->command(mtd, ONENAND_CMD_PROG, to, mtd->oobblock); + + onenand_update_bufferram(mtd, to, 1); + + ret = this->wait(mtd, FL_WRITING); + if (ret) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: write filaed %d\n", ret); + goto out; + } + + written += thislen; + + /* Only check verify write turn on */ + ret = onenand_verify_page(mtd, (u_char *) buf, to, block, page); + if (ret) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: verify failed %d\n", ret); + goto out; + } + + if (written == len) + break; + + to += thislen; + buf += thislen; + } + +out: + /* Deselect and wake up anyone waiting on the device */ + onenand_release_device(mtd); + + *retlen = written; + + return ret; +} + +/** + * onenand_write - [MTD Interface] compability function for onenand_write_ecc + * @param mtd MTD device structure + * @param to offset to write to + * @param len number of bytes to write + * @param retlen pointer to variable to store the number of written bytes + * @param buf the data to write + * + * This function simply calls onenand_write_ecc + * with oob buffer and oobsel = NULL + */ +static int onenand_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + return onenand_write_ecc(mtd, to, len, retlen, buf, NULL, NULL); +} + +/** + * onenand_write_oob - [MTD Interface] OneNAND write out-of-band + * @param mtd MTD device structure + * @param to offset to write to + * @param len number of bytes to write + * @param retlen pointer to variable to store the number of written bytes + * @param buf the data to write + * + * OneNAND write out-of-band + */ +static int onenand_write_oob(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + struct onenand_chip *this = mtd->priv; + int column, status; + int written = 0; + + DEBUG(MTD_DEBUG_LEVEL3, "onenand_write_oob: to = 0x%08x, len = %i\n", (unsigned int) to, (int) len); + + /* Initialize retlen, in case of early exit */ + *retlen = 0; + + /* Do not allow writes past end of device */ + if (unlikely((to + len) > mtd->size)) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_oob: Attempt write to past end of device\n"); + return -EINVAL; + } + + /* Grab the lock and see if the device is available */ + onenand_get_device(mtd, FL_WRITING); + + /* Loop until all data write */ + while (written < len) { + int thislen = min_t(int, mtd->oobsize, len - written); + + column = to & (mtd->oobsize - 1); + + this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobsize); + + this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize); + this->write_bufferram(mtd, ONENAND_SPARERAM, buf, column, thislen); + + this->command(mtd, ONENAND_CMD_PROGOOB, to, mtd->oobsize); + + onenand_update_bufferram(mtd, to, 0); + + status = this->wait(mtd, FL_WRITING); + if (status) + goto out; + + written += thislen; + + if (written == len) + break; + + to += thislen; + buf += thislen; + } + +out: + /* Deselect and wake up anyone waiting on the device */ + onenand_release_device(mtd); + + *retlen = written; + + return 0; +} + +/** + * onenand_writev_ecc - [MTD Interface] write with iovec with ecc + * @param mtd MTD device structure + * @param vecs the iovectors to write + * @param count number of vectors + * @param to offset to write to + * @param retlen pointer to variable to store the number of written bytes + * @param eccbuf filesystem supplied oob data buffer + * @param oobsel oob selection structure + * + * OneNAND write with iovec with ecc + */ +static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, + unsigned long count, loff_t to, size_t *retlen, + u_char *eccbuf, struct nand_oobinfo *oobsel) +{ + struct onenand_chip *this = mtd->priv; + unsigned char buffer[mtd->oobblock], *pbuf; + size_t total_len, len; + int i, written = 0; + int ret = 0; + + /* Preset written len for early exit */ + *retlen = 0; + + /* Calculate total length of data */ + total_len = 0; + for (i = 0; i < count; i++) + total_len += vecs[i].iov_len; + + DEBUG(MTD_DEBUG_LEVEL3, "onenand_writev_ecc: to = 0x%08x, len = %i, count = %ld\n", (unsigned int) to, (unsigned int) total_len, count); + + /* Do not allow write past end of the device */ + if (unlikely((to + total_len) > mtd->size)) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: Attempted write past end of device\n"); + return -EINVAL; + } + + /* Reject writes, which are not page aligned */ + if (unlikely(NOTALIGNED(to)) || unlikely(NOTALIGNED(total_len))) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: Attempt to write not page aligned data\n"); + return -EINVAL; + } + + /* Grab the lock and see if the device is available */ + onenand_get_device(mtd, FL_WRITING); + + /* TODO handling oob */ + + /* Loop until all keve's data has been written */ + len = 0; + while (count) { + pbuf = buffer; + /* + * If the given tuple is >= pagesize then + * write it out from the iov + */ + if ((vecs->iov_len - len) >= mtd->oobblock) { + pbuf = vecs->iov_base + len; + + len += mtd->oobblock; + + /* Check, if we have to switch to the next tuple */ + if (len >= (int) vecs->iov_len) { + vecs++; + len = 0; + count--; + } + } else { + int cnt = 0, thislen; + while (cnt < mtd->oobblock) { + thislen = min_t(int, mtd->oobblock - cnt, vecs->iov_len - len); + memcpy(buffer + cnt, vecs->iov_base + len, thislen); + cnt += thislen; + len += thislen; + + /* Check, if we have to switch to the next tuple */ + if (len >= (int) vecs->iov_len) { + vecs++; + len = 0; + count--; + } + } + } + + this->command(mtd, ONENAND_CMD_BUFFERRAM, to, mtd->oobblock); + + this->write_bufferram(mtd, ONENAND_DATARAM, pbuf, 0, mtd->oobblock); + this->write_bufferram(mtd, ONENAND_SPARERAM, ffchars, 0, mtd->oobsize); + + this->command(mtd, ONENAND_CMD_PROG, to, mtd->oobblock); + + onenand_update_bufferram(mtd, to, 1); + + ret = this->wait(mtd, FL_WRITING); + if (ret) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: write failed %d\n", ret); + goto out; + } + + + /* Only check verify write turn on */ + ret = onenand_verify_page(mtd, (u_char *) pbuf, to, block, page); + if (ret) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: verify failed %d\n", ret); + goto out; + } + + written += mtd->oobblock; + + to += mtd->oobblock; + } + +out: + /* Deselect and wakt up anyone waiting on the device */ + onenand_release_device(mtd); + + *retlen = written; + + return 0; +} + +/** + * onenand_writev - [MTD Interface] compabilty function for onenand_writev_ecc + * @param mtd MTD device structure + * @param vecs the iovectors to write + * @param count number of vectors + * @param to offset to write to + * @param retlen pointer to variable to store the number of written bytes + * + * OneNAND write with kvec. This just calls the ecc function + */ +static int onenand_writev(struct mtd_info *mtd, const struct kvec *vecs, + unsigned long count, loff_t to, size_t *retlen) +{ + return onenand_writev_ecc(mtd, vecs, count, to, retlen, NULL, NULL); +} + +/** + * onenand_erase - [MTD Interface] erase block(s) + * @param mtd MTD device structure + * @param instr erase instruction + * + * Erase one ore more blocks + */ +static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + struct onenand_chip *this = mtd->priv; + unsigned int block_size; + loff_t addr; + int len; + int ret = 0; + + DEBUG(MTD_DEBUG_LEVEL3, "onenand_erase: start = 0x%08x, len = %i\n", (unsigned int) instr->addr, (unsigned int) instr->len); + + block_size = (1 << this->erase_shift); + + /* Start address must align on block boundary */ + if (unlikely(instr->addr & (block_size - 1))) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Unaligned address\n"); + return -EINVAL; + } + + /* Length must align on block boundary */ + if (unlikely(instr->len & (block_size - 1))) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Length not block aligned\n"); + return -EINVAL; + } + + /* Do not allow erase past end of device */ + if (unlikely((instr->len + instr->addr) > mtd->size)) { + DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Erase past end of device\n"); + return -EINVAL; + } + + instr->fail_addr = 0xffffffff; + + /* Grab the lock and see if the device is available */ + onenand_get_device(mtd, FL_ERASING); + + /* Loop throught the pages */ + len = instr->len; + addr = instr->addr; + + instr->state = MTD_ERASING; + + while (len) { + + /* TODO Check badblock */ + + this->command(mtd, ONENAND_CMD_ERASE, addr, block_size); + + ret = this->wait(mtd, FL_ERASING); + /* Check, if it is write protected */ + if (ret) { + if (ret == -EPERM) + DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Device is write protected!!!\n"); + else + DEBUG(MTD_DEBUG_LEVEL0, "onenand_erase: Failed erase, block %d\n", (unsigned) (addr >> this->erase_shift)); + instr->state = MTD_ERASE_FAILED; + instr->fail_addr = addr; + goto erase_exit; + } + + len -= block_size; + addr += block_size; + } + + instr->state = MTD_ERASE_DONE; + +erase_exit: + + ret = instr->state == MTD_ERASE_DONE ? 0 : -EIO; + /* Do call back function */ + if (!ret) + mtd_erase_callback(instr); + + /* Deselect and wake up anyone waiting on the device */ + onenand_release_device(mtd); + + return ret; +} + +/** + * onenand_sync - [MTD Interface] sync + * @param mtd MTD device structure + * + * Sync is actually a wait for chip ready function + */ +static void onenand_sync(struct mtd_info *mtd) +{ + DEBUG(MTD_DEBUG_LEVEL3, "onenand_sync: called\n"); + + /* Grab the lock and see if the device is available */ + onenand_get_device(mtd, FL_SYNCING); + + /* Release it and go back */ + onenand_release_device(mtd); +} + +/** + * onenand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad + * @param mtd MTD device structure + * @param ofs offset relative to mtd start + */ +static int onenand_block_isbad(struct mtd_info *mtd, loff_t ofs) +{ + /* + * TODO + * 1. Bad block table (BBT) + * -> using NAND BBT to support JFFS2 + * 2. Bad block management (BBM) + * -> bad block replace scheme + * + * Currently we do nothing + */ + return 0; +} + +/** + * onenand_block_markbad - [MTD Interface] Mark the block at the given offset as bad + * @param mtd MTD device structure + * @param ofs offset relative to mtd start + */ +static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs) +{ + /* see above */ + return 0; +} + +/** + * onenand_unlock - [MTD Interface] Unlock block(s) + * @param mtd MTD device structure + * @param ofs offset relative to mtd start + * @param len number of bytes to unlock + * + * Unlock one or more blocks + */ +static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) +{ + struct onenand_chip *this = mtd->priv; + int start, end, block, value, status; + + start = ofs >> this->erase_shift; + end = len >> this->erase_shift; + + /* Continuous lock scheme */ + if (this->options & ONENAND_CONT_LOCK) { + /* Set start block address */ + this->write_word(start, this->base + ONENAND_REG_START_BLOCK_ADDRESS); + /* Set end block address */ + this->write_word(end - 1, this->base + ONENAND_REG_END_BLOCK_ADDRESS); + /* Write unlock command */ + this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0); + + /* There's no return value */ + this->wait(mtd, FL_UNLOCKING); + + /* Sanity check */ + while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS) + & ONENAND_CTRL_ONGO) + continue; + + /* Check lock status */ + status = this->read_word(this->base + ONENAND_REG_WP_STATUS); + if (!(status & ONENAND_WP_US)) + printk(KERN_ERR "wp status = 0x%x\n", status); + + return 0; + } + + /* Block lock scheme */ + for (block = start; block < end; block++) { + /* Set start block address */ + this->write_word(block, this->base + ONENAND_REG_START_BLOCK_ADDRESS); + /* Write unlock command */ + this->command(mtd, ONENAND_CMD_UNLOCK, 0, 0); + + /* There's no return value */ + this->wait(mtd, FL_UNLOCKING); + + /* Sanity check */ + while (this->read_word(this->base + ONENAND_REG_CTRL_STATUS) + & ONENAND_CTRL_ONGO) + continue; + + /* Set block address for read block status */ + value = onenand_block_address(this->device_id, block); + this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); + + /* Check lock status */ + status = this->read_word(this->base + ONENAND_REG_WP_STATUS); + if (!(status & ONENAND_WP_US)) + printk(KERN_ERR "block = %d, wp status = 0x%x\n", block, status); + } + + return 0; +} + +/** + * onenand_print_device_info - Print device ID + * @param device device ID + * + * Print device ID + */ +static void onenand_print_device_info(int device) +{ + int vcc, demuxed, ddp, density; + + vcc = device & ONENAND_DEVICE_VCC_MASK; + demuxed = device & ONENAND_DEVICE_IS_DEMUX; + ddp = device & ONENAND_DEVICE_IS_DDP; + density = device >> ONENAND_DEVICE_DENSITY_SHIFT; + printk(KERN_INFO "%sOneNAND%s %dMB %sV 16-bit (0x%02x)\n", + demuxed ? "" : "Muxed ", + ddp ? "(DDP)" : "", + (16 << density), + vcc ? "2.65/3.3" : "1.8", + device); +} + +static const struct onenand_manufacturers onenand_manuf_ids[] = { + {ONENAND_MFR_SAMSUNG, "Samsung"}, + {ONENAND_MFR_UNKNOWN, "Unknown"} +}; + +/** + * onenand_check_maf - Check manufacturer ID + * @param manuf manufacturer ID + * + * Check manufacturer ID + */ +static int onenand_check_maf(int manuf) +{ + int i; + + for (i = 0; onenand_manuf_ids[i].id; i++) { + if (manuf == onenand_manuf_ids[i].id) + break; + } + + printk(KERN_DEBUG "OneNAND Manufacturer: %s\n", + onenand_manuf_ids[i].name); + + return (i != ONENAND_MFR_UNKNOWN); +} + +/** + * onenand_probe - [OneNAND Interface] Probe the OneNAND device + * @param mtd MTD device structure + * + * OneNAND detection method: + * Compare the the values from command with ones from register + */ +static int onenand_probe(struct mtd_info *mtd) +{ + struct onenand_chip *this = mtd->priv; + int bram_maf_id, bram_dev_id, maf_id, dev_id; + int version_id; + int density; + + /* Send the command for reading device ID from BootRAM */ + this->write_word(ONENAND_CMD_READID, this->base + ONENAND_BOOTRAM); + + /* Read manufacturer and device IDs from BootRAM */ + bram_maf_id = this->read_word(this->base + ONENAND_BOOTRAM + 0x0); + bram_dev_id = this->read_word(this->base + ONENAND_BOOTRAM + 0x2); + + /* Check manufacturer ID */ + if (onenand_check_maf(bram_maf_id)) + return -ENXIO; + + /* Reset OneNAND to read default register values */ + this->write_word(ONENAND_CMD_RESET, this->base + ONENAND_BOOTRAM); + + /* Read manufacturer and device IDs from Register */ + maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); + dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); + + /* Check OneNAND device */ + if (maf_id != bram_maf_id || dev_id != bram_dev_id) + return -ENXIO; + + /* Flash device information */ + onenand_print_device_info(dev_id); + this->device_id = dev_id; + + density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT; + this->chipsize = (16 << density) << 20; + + /* OneNAND page size & block size */ + /* The data buffer size is equal to page size */ + mtd->oobblock = this->read_word(this->base + ONENAND_REG_DATA_BUFFER_SIZE); + mtd->oobsize = mtd->oobblock >> 5; + /* Pagers per block is always 64 in OneNAND */ + mtd->erasesize = mtd->oobblock << 6; + + this->erase_shift = ffs(mtd->erasesize) - 1; + this->page_shift = ffs(mtd->oobblock) - 1; + this->ppb_shift = (this->erase_shift - this->page_shift); + this->page_mask = (mtd->erasesize / mtd->oobblock) - 1; + + /* REVIST: Multichip handling */ + + mtd->size = this->chipsize; + + /* Version ID */ + version_id = this->read_word(this->base + ONENAND_REG_VERSION_ID); + printk(KERN_DEBUG "OneNAND version = 0x%04x\n", version_id); + + /* Lock scheme */ + if (density <= ONENAND_DEVICE_DENSITY_512Mb && + !(version_id >> ONENAND_VERSION_PROCESS_SHIFT)) { + printk(KERN_INFO "Lock scheme is Continues Lock\n"); + this->options |= ONENAND_CONT_LOCK; + } + + return 0; +} + + +/** + * onenand_scan - [OneNAND Interface] Scan for the OneNAND device + * @param mtd MTD device structure + * @param maxchips Number of chips to scan for + * + * This fills out all the not initialized function pointers + * with the defaults. + * The flash ID is read and the mtd/chip structures are + * filled with the appropriate values. + */ +int onenand_scan(struct mtd_info *mtd, int maxchips) +{ + struct onenand_chip *this = mtd->priv; + + if (!this->read_word) + this->read_word = onenand_readw; + if (!this->write_word) + this->write_word = onenand_writew; + + if (!this->command) + this->command = onenand_command; + if (!this->wait) + this->wait = onenand_wait; + + if (!this->read_bufferram) + this->read_bufferram = onenand_read_bufferram; + if (!this->write_bufferram) + this->write_bufferram = onenand_write_bufferram; + + if (onenand_probe(mtd)) + return -ENXIO; + + this->state = FL_READY; + init_waitqueue_head(&this->wq); + spin_lock_init(&this->chip_lock); + + switch (mtd->oobsize) { + case 64: + this->autooob = &onenand_oob_64; + break; + + case 32: + this->autooob = &onenand_oob_32; + break; + + default: + printk(KERN_WARNING "No OOB scheme defined for oobsize %d\n", + mtd->oobsize); + /* To prevent kernel oops */ + this->autooob = &onenand_oob_32; + break; + } + + memcpy(&mtd->oobinfo, this->autooob, sizeof(mtd->oobinfo)); + + /* Fill in remaining MTD driver data */ + mtd->type = MTD_NANDFLASH; + mtd->flags = MTD_CAP_NANDFLASH | MTD_ECC; + mtd->ecctype = MTD_ECC_SW; + mtd->erase = onenand_erase; + mtd->point = NULL; + mtd->unpoint = NULL; + mtd->read = onenand_read; + mtd->write = onenand_write; + mtd->read_ecc = onenand_read_ecc; + mtd->write_ecc = onenand_write_ecc; + mtd->read_oob = onenand_read_oob; + mtd->write_oob = onenand_write_oob; + mtd->readv = NULL; + mtd->readv_ecc = NULL; + mtd->writev = onenand_writev; + mtd->writev_ecc = onenand_writev_ecc; + mtd->sync = onenand_sync; + mtd->lock = NULL; + mtd->unlock = onenand_unlock; + mtd->suspend = NULL; + mtd->resume = NULL; + mtd->block_isbad = onenand_block_isbad; + mtd->block_markbad = onenand_block_markbad; + mtd->owner = THIS_MODULE; + + /* Unlock whole block */ + mtd->unlock(mtd, 0x0, this->chipsize); + + return 0; +} + +/** + * onenand_release - [OneNAND Interface] Free resources held by the OneNAND device + * @param mtd MTD device structure + */ +void onenand_release(struct mtd_info *mtd) +{ +#ifdef CONFIG_MTD_PARTITIONS + /* Deregister partitions */ + del_mtd_partitions (mtd); +#endif + /* Deregister the device */ + del_mtd_device (mtd); +} + +EXPORT_SYMBOL_GPL(onenand_scan); +EXPORT_SYMBOL_GPL(onenand_release); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Kyungmin Park "); +MODULE_DESCRIPTION("Generic OneNAND flash driver code"); diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h new file mode 100644 index 000000000000..b9a64117d646 --- /dev/null +++ b/include/linux/mtd/onenand.h @@ -0,0 +1,134 @@ +/* + * linux/include/linux/mtd/onenand.h + * + * Copyright (C) 2005 Samsung Electronics + * Kyungmin Park + * + * 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. + */ + +#ifndef __LINUX_MTD_ONENAND_H +#define __LINUX_MTD_ONENAND_H + +#include +#include + +#define MAX_BUFFERRAM 2 + +/* Scan and identify a OneNAND device */ +extern int onenand_scan(struct mtd_info *mtd, int max_chips); +/* Free resources held by the OneNAND device */ +extern void onenand_release(struct mtd_info *mtd); + +/** + * onenand_state_t - chip states + * Enumeration for OneNAND flash chip state + */ +typedef enum { + FL_READY, + FL_READING, + FL_WRITING, + FL_ERASING, + FL_SYNCING, + FL_UNLOCKING, + FL_LOCKING, +} onenand_state_t; + +/** + * struct onenand_bufferram - OneNAND BufferRAM Data + * @param block block address in BufferRAM + * @param page page address in BufferRAM + * @param valid valid flag + */ +struct onenand_bufferram { + int block; + int page; + int valid; +}; + +/** + * struct onenand_chip - OneNAND Private Flash Chip Data + * @param base [BOARDSPECIFIC] address to access OneNAND + * @param chipsize [INTERN] the size of one chip for multichip arrays + * @param device_id [INTERN] device ID + * @param verstion_id [INTERN] version ID + * @param options [BOARDSPECIFIC] various chip options. They can partly be set to inform onenand_scan about + * @param erase_shift [INTERN] number of address bits in a block + * @param page_shift [INTERN] number of address bits in a page + * @param ppb_shift [INTERN] number of address bits in a pages per block + * @param page_mask [INTERN] a page per block mask + * @param bufferam_index [INTERN] BufferRAM index + * @param bufferam [INTERN] BufferRAM info + * @param readw [REPLACEABLE] hardware specific function for read short + * @param writew [REPLACEABLE] hardware specific function for write short + * @param command [REPLACEABLE] hardware specific function for writing commands to the chip + * @param wait [REPLACEABLE] hardware specific function for wait on ready + * @param read_bufferram [REPLACEABLE] hardware specific function for BufferRAM Area + * @param write_bufferram [REPLACEABLE] hardware specific function for BufferRAM Area + * @param chip_lock [INTERN] spinlock used to protect access to this structure and the chip + * @param wq [INTERN] wait queue to sleep on if a OneNAND operation is in progress + * @param state [INTERN] the current state of the OneNAND device + * @param autooob [REPLACEABLE] the default (auto)placement scheme + * @param priv [OPTIONAL] pointer to private chip date + */ +struct onenand_chip { + void __iomem *base; + unsigned int chipsize; + unsigned int device_id; + unsigned int options; + + unsigned int erase_shift; + unsigned int page_shift; + unsigned int ppb_shift; /* Pages per block shift */ + unsigned int page_mask; + + unsigned int bufferram_index; + struct onenand_bufferram bufferram[MAX_BUFFERRAM]; + + int (*command)(struct mtd_info *mtd, int cmd, loff_t address, size_t len); + int (*wait)(struct mtd_info *mtd, int state); + int (*read_bufferram)(struct mtd_info *mtd, int area, + unsigned char *buffer, int offset, size_t count); + int (*write_bufferram)(struct mtd_info *mtd, int area, + const unsigned char *buffer, int offset, size_t count); + unsigned short (*read_word)(void __iomem *addr); + void (*write_word)(unsigned short value, void __iomem *addr); + + spinlock_t chip_lock; + wait_queue_head_t wq; + onenand_state_t state; + + struct nand_oobinfo *autooob; + + void *priv; +}; + +#define ONENAND_CURRENT_BUFFERRAM(this) (this->bufferram_index) +#define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1) +#define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1) + +/* + * Options bits + */ +#define ONENAND_CONT_LOCK (0x0001) + + +/* + * OneNAND Flash Manufacturer ID Codes + */ +#define ONENAND_MFR_SAMSUNG 0xec +#define ONENAND_MFR_UNKNOWN 0x00 + +/** + * struct nand_manufacturers - NAND Flash Manufacturer ID Structure + * @param name: Manufacturer name + * @param id: manufacturer ID code of device. +*/ +struct onenand_manufacturers { + int id; + char *name; +}; + +#endif /* __LINUX_MTD_ONENAND_H */ diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h new file mode 100644 index 000000000000..4a2daad7d738 --- /dev/null +++ b/include/linux/mtd/onenand_regs.h @@ -0,0 +1,167 @@ +/* + * linux/include/linux/mtd/onenand_regs.h + * + * OneNAND Register header file + * + * Copyright (C) 2005 Samsung Electronics + * + * 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. + */ + +#ifndef __ONENAND_REG_H +#define __ONENAND_REG_H + +/* Memory Address Map Translation (Word order) */ +#define ONENAND_MEMORY_MAP(x) ((x) << 1) + +/* + * External BufferRAM area + */ +#define ONENAND_BOOTRAM ONENAND_MEMORY_MAP(0x0000) +#define ONENAND_DATARAM ONENAND_MEMORY_MAP(0x0200) +#define ONENAND_SPARERAM ONENAND_MEMORY_MAP(0x8010) + +/* + * OneNAND Registers + */ +#define ONENAND_REG_MANUFACTURER_ID ONENAND_MEMORY_MAP(0xF000) +#define ONENAND_REG_DEVICE_ID ONENAND_MEMORY_MAP(0xF001) +#define ONENAND_REG_VERSION_ID ONENAND_MEMORY_MAP(0xF002) +#define ONENAND_REG_DATA_BUFFER_SIZE ONENAND_MEMORY_MAP(0xF003) +#define ONENAND_REG_BOOT_BUFFER_SIZE ONENAND_MEMORY_MAP(0xF004) +#define ONENAND_REG_NUM_BUFFERS ONENAND_MEMORY_MAP(0xF005) +#define ONENAND_REG_TECHNOLOGY ONENAND_MEMORY_MAP(0xF006) + +#define ONENAND_REG_START_ADDRESS1 ONENAND_MEMORY_MAP(0xF100) +#define ONENAND_REG_START_ADDRESS2 ONENAND_MEMORY_MAP(0xF101) +#define ONENAND_REG_START_ADDRESS3 ONENAND_MEMORY_MAP(0xF102) +#define ONENAND_REG_START_ADDRESS4 ONENAND_MEMORY_MAP(0xF103) +#define ONENAND_REG_START_ADDRESS5 ONENAND_MEMORY_MAP(0xF104) +#define ONENAND_REG_START_ADDRESS6 ONENAND_MEMORY_MAP(0xF105) +#define ONENAND_REG_START_ADDRESS7 ONENAND_MEMORY_MAP(0xF106) +#define ONENAND_REG_START_ADDRESS8 ONENAND_MEMORY_MAP(0xF107) + +#define ONENAND_REG_START_BUFFER ONENAND_MEMORY_MAP(0xF200) +#define ONENAND_REG_COMMAND ONENAND_MEMORY_MAP(0xF220) +#define ONENAND_REG_SYS_CFG1 ONENAND_MEMORY_MAP(0xF221) +#define ONENAND_REG_SYS_CFG2 ONENAND_MEMORY_MAP(0xF222) +#define ONENAND_REG_CTRL_STATUS ONENAND_MEMORY_MAP(0xF240) +#define ONENAND_REG_INTERRUPT ONENAND_MEMORY_MAP(0xF241) +#define ONENAND_REG_START_BLOCK_ADDRESS ONENAND_MEMORY_MAP(0xF24C) +#define ONENAND_REG_END_BLOCK_ADDRESS ONENAND_MEMORY_MAP(0xF24D) +#define ONENAND_REG_WP_STATUS ONENAND_MEMORY_MAP(0xF24E) + +#define ONENAND_REG_ECC_STATUS ONENAND_MEMORY_MAP(0xFF00) +#define ONENAND_REG_ECC_M0 ONENAND_MEMORY_MAP(0xFF01) +#define ONENAND_REG_ECC_S0 ONENAND_MEMORY_MAP(0xFF02) +#define ONENAND_REG_ECC_M1 ONENAND_MEMORY_MAP(0xFF03) +#define ONENAND_REG_ECC_S1 ONENAND_MEMORY_MAP(0xFF04) +#define ONENAND_REG_ECC_M2 ONENAND_MEMORY_MAP(0xFF05) +#define ONENAND_REG_ECC_S2 ONENAND_MEMORY_MAP(0xFF06) +#define ONENAND_REG_ECC_M3 ONENAND_MEMORY_MAP(0xFF07) +#define ONENAND_REG_ECC_S3 ONENAND_MEMORY_MAP(0xFF08) + +/* + * Device ID Register F001h (R) + */ +#define ONENAND_DEVICE_DENSITY_SHIFT (4) +#define ONENAND_DEVICE_IS_DDP (1 << 3) +#define ONENAND_DEVICE_IS_DEMUX (1 << 2) +#define ONENAND_DEVICE_VCC_MASK (0x3) + +#define ONENAND_DEVICE_DENSITY_512Mb (0x002) + +/* + * Version ID Register F002h (R) + */ +#define ONENAND_VERSION_PROCESS_SHIFT (8) + +/* + * Start Address 1 F100h (R/W) + */ +#define ONENAND_DDP_SHIFT (15) + +/* + * Start Address 8 F107h (R/W) + */ +#define ONENAND_FPA_MASK (0x3f) +#define ONENAND_FPA_SHIFT (2) +#define ONENAND_FSA_MASK (0x03) + +/* + * Start Buffer Register F200h (R/W) + */ +#define ONENAND_BSA_MASK (0x03) +#define ONENAND_BSA_SHIFT (8) +#define ONENAND_BSA_BOOTRAM (0 << 2) +#define ONENAND_BSA_DATARAM0 (2 << 2) +#define ONENAND_BSA_DATARAM1 (3 << 2) +#define ONENAND_BSC_MASK (0x03) + +/* + * Command Register F220h (R/W) + */ +#define ONENAND_CMD_READ (0x00) +#define ONENAND_CMD_READOOB (0x13) +#define ONENAND_CMD_PROG (0x80) +#define ONENAND_CMD_PROGOOB (0x1A) +#define ONENAND_CMD_UNLOCK (0x23) +#define ONENAND_CMD_LOCK (0x2A) +#define ONENAND_CMD_LOCK_TIGHT (0x2C) +#define ONENAND_CMD_ERASE (0x94) +#define ONENAND_CMD_RESET (0xF0) +#define ONENAND_CMD_READID (0x90) + +/* NOTE: Those are not *REAL* commands */ +#define ONENAND_CMD_BUFFERRAM (0x1978) + +/* + * System Configuration 1 Register F221h (R, R/W) + */ +#define ONENAND_SYS_CFG1_SYNC_READ (1 << 15) +#define ONENAND_SYS_CFG1_BRL (1 << 12) +#define ONENAND_SYS_CFG1_BL (1 << 9) +#define ONENAND_SYS_CFG1_NO_ECC (1 << 8) +#define ONENAND_SYS_CFG1_RDY (1 << 7) +#define ONENAND_SYS_CFG1_INT (1 << 6) +#define ONENAND_SYS_CFG1_IOBE (1 << 5) +#define ONENAND_SYS_CFG1_RDY_CONF (1 << 4) + +/* + * Controller Status Register F240h (R) + */ +#define ONENAND_CTRL_ONGO (1 << 15) +#define ONENAND_CTRL_LOCK (1 << 14) +#define ONENAND_CTRL_LOAD (1 << 13) +#define ONENAND_CTRL_PROGRAM (1 << 12) +#define ONENAND_CTRL_ERASE (1 << 11) +#define ONENAND_CTRL_ERROR (1 << 10) +#define ONENAND_CTRL_RSTB (1 << 7) + +/* + * Interrupt Status Register F241h (R) + */ +#define ONENAND_INT_MASTER (1 << 15) +#define ONENAND_INT_READ (1 << 7) +#define ONENAND_INT_WRITE (1 << 6) +#define ONENAND_INT_ERASE (1 << 5) +#define ONENAND_INT_RESET (1 << 4) +#define ONENAND_INT_CLEAR (0 << 0) + +/* + * NAND Flash Write Protection Status Register F24Eh (R) + */ +#define ONENAND_WP_US (1 << 2) +#define ONENAND_WP_LS (1 << 1) +#define ONENAND_WP_LTS (1 << 0) + +/* + * ECC Status Reigser FF00h (R) + */ +#define ONENAND_ECC_1BIT (1 << 0) +#define ONENAND_ECC_2BIT (1 << 1) +#define ONENAND_ECC_2BIT_ALL (0xAAAA) + +#endif /* __ONENAND_REG_H */ -- cgit v1.2.3 From 52b0eea73de05df33c51ca652e288a3ba1bba03b Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Sat, 3 Sep 2005 07:07:19 +0100 Subject: [PATCH] OneNAND: Sync. Burst Read support Add OneNAND Sync. Burst Read support Tested with OMAP platform Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/Kconfig | 6 ++++ drivers/mtd/onenand/omap-onenand.c | 66 ++++++++++++++++++++++++++++++++++++-- drivers/mtd/onenand/onenand_base.c | 39 ++++++++++++++++++++-- include/linux/mtd/onenand.h | 1 + include/linux/mtd/onenand_regs.h | 17 ++++++++-- 5 files changed, 123 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/drivers/mtd/onenand/Kconfig b/drivers/mtd/onenand/Kconfig index 7d76ede984d8..186ea9dc0942 100644 --- a/drivers/mtd/onenand/Kconfig +++ b/drivers/mtd/onenand/Kconfig @@ -29,4 +29,10 @@ config MTD_ONENAND_OMAP help Support for OneNAND flash on TI OMAP board. +config MTD_ONENAND_SYNC_READ + bool "OneNAND Sync. Burst Read Support" + depends on ARCH_OMAP + help + This enables support for Sync. Burst Read. + endmenu diff --git a/drivers/mtd/onenand/omap-onenand.c b/drivers/mtd/onenand/omap-onenand.c index 56e1aec6b835..7c89549f7f58 100644 --- a/drivers/mtd/onenand/omap-onenand.c +++ b/drivers/mtd/onenand/omap-onenand.c @@ -25,9 +25,10 @@ #include #include #include +#include #define OMAP_ONENAND_FLASH_START1 OMAP_CS2A_PHYS -#define OMAP_ONENAND_FLASH_START2 OMAP_CS0_PHYS +#define OMAP_ONENAND_FLASH_START2 omap_cs3_phys() /* * MTD structure for OMAP board */ @@ -68,10 +69,66 @@ static struct mtd_partition static_partition[] = { }, }; -const char *part_probes[] = { "cmdlinepart", NULL, }; +static const char *part_probes[] = { "cmdlinepart", NULL, }; #endif +#ifdef CONFIG_MTD_ONENAND_SYNC_READ +static unsigned int omap_emifs_cs; + +static void omap_find_emifs_cs(unsigned int addr) +{ + /* Check CS3 */ + if (OMAP_EMIFS_CONFIG_REG & OMAP_EMIFS_CONFIG_BM && addr == 0x0) { + omap_emifs_cs = 3; + } else { + omap_emifs_cs = (addr >> 26); + } +} + +/** + * omap_onenand_mmcontrol - Control OMAP EMIFS + */ +static void omap_onenand_mmcontrol(struct mtd_info *mtd, int sync_read) +{ + struct onenand_chip *this = mtd->priv; + static unsigned long omap_emifs_ccs, omap_emifs_acs; + static unsigned long onenand_sys_cfg1; + int config, emifs_ccs, emifs_acs; + + if (sync_read) { + /* + * Note: BRL and RDWST is equal + */ + omap_emifs_ccs = EMIFS_CCS(omap_emifs_cs); + omap_emifs_acs = EMIFS_ACS(omap_emifs_cs); + + emifs_ccs = 0x41141; + emifs_acs = 0x1; + + /* OneNAND System Configuration 1 */ + onenand_sys_cfg1 = this->read_word(this->base + ONENAND_REG_SYS_CFG1); + config = (onenand_sys_cfg1 + & ~(0x3f << ONENAND_SYS_CFG1_BL_SHIFT)) + | ONENAND_SYS_CFG1_SYNC_READ + | ONENAND_SYS_CFG1_BRL_4 + | ONENAND_SYS_CFG1_BL_8; + } else { + emifs_ccs = omap_emifs_ccs; + emifs_acs = omap_emifs_acs; + config = onenand_sys_cfg1; + } + + this->write_word(config, this->base + ONENAND_REG_SYS_CFG1); + EMIFS_CCS(omap_emifs_cs) = emifs_ccs; + EMIFS_ACS(omap_emifs_cs) = emifs_acs; +} +#else +#define omap_find_emifs_cs(x) do { } while (0) +#define omap_onenand_mmcontrol NULL +#endif + + /* Scan to find existance of the device at base. This also allocates oob and data internal buffers */ static char onenand_name[] = "onenand"; @@ -102,14 +159,19 @@ static int __init omap_onenand_init (void) /* Link the private data with the MTD structure */ omap_onenand_mtd->priv = this; + this->mmcontrol = omap_onenand_mmcontrol; /* try the first address */ this->base = ioremap(OMAP_ONENAND_FLASH_START1, SZ_128K); + omap_find_emifs_cs(OMAP_ONENAND_FLASH_START1); + omap_onenand_mtd->name = onenand_name; if (onenand_scan(omap_onenand_mtd, 1)){ /* try the second address */ iounmap(this->base); this->base = ioremap(OMAP_ONENAND_FLASH_START2, SZ_128K); + omap_find_emifs_cs(OMAP_ONENAND_FLASH_START2); + if (onenand_scan(omap_onenand_mtd, 1)) { iounmap(this->base); err = -ENXIO; diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index bcce22ae3cb1..e87489505772 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -378,6 +378,35 @@ static int onenand_read_bufferram(struct mtd_info *mtd, int area, return 0; } +/** + * onenand_sync_read_bufferram - [OneNAND Interface] Read the bufferram area with Sync. Burst mode + * @param mtd MTD data structure + * @param area BufferRAM area + * @param buffer the databuffer to put/get data + * @param offset offset to read from or write to + * @param count number of bytes to read/write + * + * Read the BufferRAM area with Sync. Burst Mode + */ +static int onenand_sync_read_bufferram(struct mtd_info *mtd, int area, + unsigned char *buffer, int offset, size_t count) +{ + struct onenand_chip *this = mtd->priv; + void __iomem *bufferram; + + bufferram = this->base + area; + + bufferram += onenand_bufferram_offset(mtd, area); + + this->mmcontrol(mtd, ONENAND_SYS_CFG1_SYNC_READ); + + memcpy(buffer, bufferram + offset, count); + + this->mmcontrol(mtd, 0); + + return 0; +} + /** * onenand_write_bufferram - [OneNAND Interface] Write the bufferram area * @param mtd MTD data structure @@ -1273,8 +1302,8 @@ static int onenand_check_maf(int manuf) break; } - printk(KERN_DEBUG "OneNAND Manufacturer: %s\n", - onenand_manuf_ids[i].name); + printk(KERN_DEBUG "OneNAND Manufacturer: %s (0x%0x)\n", + onenand_manuf_ids[i].name, manuf); return (i != ONENAND_MFR_UNKNOWN); } @@ -1385,6 +1414,12 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) if (onenand_probe(mtd)) return -ENXIO; + /* Set Sync. Burst Read after probing */ + if (this->mmcontrol) { + printk(KERN_INFO "OneNAND Sync. Burst Read support\n"); + this->read_bufferram = onenand_sync_read_bufferram; + } + this->state = FL_READY; init_waitqueue_head(&this->wq); spin_lock_init(&this->chip_lock); diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index b9a64117d646..c557caa24a6c 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -95,6 +95,7 @@ struct onenand_chip { const unsigned char *buffer, int offset, size_t count); unsigned short (*read_word)(void __iomem *addr); void (*write_word)(unsigned short value, void __iomem *addr); + void (*mmcontrol)(struct mtd_info *mtd, int sync_read); spinlock_t chip_lock; wait_queue_head_t wq; diff --git a/include/linux/mtd/onenand_regs.h b/include/linux/mtd/onenand_regs.h index 4a2daad7d738..d7832ef8ed63 100644 --- a/include/linux/mtd/onenand_regs.h +++ b/include/linux/mtd/onenand_regs.h @@ -121,8 +121,21 @@ * System Configuration 1 Register F221h (R, R/W) */ #define ONENAND_SYS_CFG1_SYNC_READ (1 << 15) -#define ONENAND_SYS_CFG1_BRL (1 << 12) -#define ONENAND_SYS_CFG1_BL (1 << 9) +#define ONENAND_SYS_CFG1_BRL_7 (7 << 12) +#define ONENAND_SYS_CFG1_BRL_6 (6 << 12) +#define ONENAND_SYS_CFG1_BRL_5 (5 << 12) +#define ONENAND_SYS_CFG1_BRL_4 (4 << 12) +#define ONENAND_SYS_CFG1_BRL_3 (3 << 12) +#define ONENAND_SYS_CFG1_BRL_10 (2 << 12) +#define ONENAND_SYS_CFG1_BRL_9 (1 << 12) +#define ONENAND_SYS_CFG1_BRL_8 (0 << 12) +#define ONENAND_SYS_CFG1_BRL_SHIFT (12) +#define ONENAND_SYS_CFG1_BL_32 (4 << 9) +#define ONENAND_SYS_CFG1_BL_16 (3 << 9) +#define ONENAND_SYS_CFG1_BL_8 (2 << 9) +#define ONENAND_SYS_CFG1_BL_4 (1 << 9) +#define ONENAND_SYS_CFG1_BL_CONT (0 << 9) +#define ONENAND_SYS_CFG1_BL_SHIFT (9) #define ONENAND_SYS_CFG1_NO_ECC (1 << 8) #define ONENAND_SYS_CFG1_RDY (1 << 7) #define ONENAND_SYS_CFG1_INT (1 << 6) -- cgit v1.2.3 From cdc001305da4f057353911018e28f26f8f879061 Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Sat, 3 Sep 2005 07:15:48 +0100 Subject: [PATCH] OneNAND: Simple Bad Block handling support Based on NAND memory bad block table code Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/Makefile | 4 +- drivers/mtd/onenand/onenand_base.c | 105 ++++++++++++++++++++++++++++++------- include/linux/mtd/onenand.h | 9 ++++ 3 files changed, 98 insertions(+), 20 deletions(-) (limited to 'include/linux') diff --git a/drivers/mtd/onenand/Makefile b/drivers/mtd/onenand/Makefile index f4e75864d8b5..243c7592a111 100644 --- a/drivers/mtd/onenand/Makefile +++ b/drivers/mtd/onenand/Makefile @@ -3,7 +3,9 @@ # # Core functionality. -obj-$(CONFIG_MTD_ONENAND) += onenand_base.o +obj-$(CONFIG_MTD_ONENAND) += onenand.o # Board specific. obj-$(CONFIG_MTD_ONENAND_OMAP) += omap-onenand.o + +onenand-objs = onenand_base.o onenand_bbt.o diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index e87489505772..bdeac01e659f 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -311,19 +311,21 @@ static int onenand_wait(struct mtd_info *mtd, int state) ctrl = this->read_word(this->base + ONENAND_REG_CTRL_STATUS); if (ctrl & ONENAND_CTRL_ERROR) { - DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x", ctrl); - return -EIO; + /* It maybe occur at initial bad block */ + DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: controller error = 0x%04x\n", ctrl); + /* Clear other interrupt bits for preventing ECC error */ + interrupt &= ONENAND_INT_MASTER; } if (ctrl & ONENAND_CTRL_LOCK) { - DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error = 0x%04x", ctrl); - return -EIO; + DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: it's locked error = 0x%04x\n", ctrl); + return -EACCES; } if (interrupt & ONENAND_INT_READ) { ecc = this->read_word(this->base + ONENAND_REG_ECC_STATUS); if (ecc & ONENAND_ECC_2BIT_ALL) { - DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x", ecc); + DEBUG(MTD_DEBUG_LEVEL0, "onenand_wait: ECC error = 0x%04x\n", ecc); return -EBADMSG; } } @@ -1059,6 +1061,25 @@ static int onenand_writev(struct mtd_info *mtd, const struct kvec *vecs, return onenand_writev_ecc(mtd, vecs, count, to, retlen, NULL, NULL); } +/** + * onenand_block_checkbad - [GENERIC] Check if a block is marked bad + * @param mtd MTD device structure + * @param ofs offset from device start + * @param getchip 0, if the chip is already selected + * @param allowbbt 1, if its allowed to access the bbt area + * + * Check, if the block is bad. Either by reading the bad block table or + * calling of the scan function. + */ +static int onenand_block_checkbad(struct mtd_info *mtd, loff_t ofs, int getchip, int allowbbt) +{ + struct onenand_chip *this = mtd->priv; + struct bbm_info *bbm = this->bbm; + + /* Return info from the table */ + return bbm->isbad_bbt(mtd, ofs, allowbbt); +} + /** * onenand_erase - [MTD Interface] erase block(s) * @param mtd MTD device structure @@ -1109,7 +1130,12 @@ static int onenand_erase(struct mtd_info *mtd, struct erase_info *instr) while (len) { - /* TODO Check badblock */ + /* Check if we have a bad block, we do not erase bad blocks */ + if (onenand_block_checkbad(mtd, addr, 0, 0)) { + printk (KERN_WARNING "onenand_erase: attempt to erase a bad block at addr 0x%08x\n", (unsigned int) addr); + instr->state = MTD_ERASE_FAILED; + goto erase_exit; + } this->command(mtd, ONENAND_CMD_ERASE, addr, block_size); @@ -1161,34 +1187,70 @@ static void onenand_sync(struct mtd_info *mtd) onenand_release_device(mtd); } + /** * onenand_block_isbad - [MTD Interface] Check whether the block at the given offset is bad * @param mtd MTD device structure * @param ofs offset relative to mtd start + * + * Check whether the block is bad */ static int onenand_block_isbad(struct mtd_info *mtd, loff_t ofs) { - /* - * TODO - * 1. Bad block table (BBT) - * -> using NAND BBT to support JFFS2 - * 2. Bad block management (BBM) - * -> bad block replace scheme - * - * Currently we do nothing - */ - return 0; + /* Check for invalid offset */ + if (ofs > mtd->size) + return -EINVAL; + + return onenand_block_checkbad(mtd, ofs, 1, 0); +} + +/** + * onenand_default_block_markbad - [DEFAULT] mark a block bad + * @param mtd MTD device structure + * @param ofs offset from device start + * + * This is the default implementation, which can be overridden by + * a hardware specific driver. + */ +static int onenand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) +{ + struct onenand_chip *this = mtd->priv; + struct bbm_info *bbm = this->bbm; + u_char buf[2] = {0, 0}; + size_t retlen; + int block; + + /* Get block number */ + block = ((int) ofs) >> bbm->bbt_erase_shift; + if (bbm->bbt) + bbm->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); + + /* We write two bytes, so we dont have to mess with 16 bit access */ + ofs += mtd->oobsize + (bbm->badblockpos & ~0x01); + return mtd->write_oob(mtd, ofs , 2, &retlen, buf); } /** * onenand_block_markbad - [MTD Interface] Mark the block at the given offset as bad * @param mtd MTD device structure * @param ofs offset relative to mtd start + * + * Mark the block as bad */ static int onenand_block_markbad(struct mtd_info *mtd, loff_t ofs) { - /* see above */ - return 0; + struct onenand_chip *this = mtd->priv; + int ret; + + ret = onenand_block_isbad(mtd, ofs); + if (ret) { + /* If it was bad already, return success and do nothing */ + if (ret > 0) + return 0; + return ret; + } + + return this->block_markbad(mtd, ofs); } /** @@ -1411,6 +1473,11 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) if (!this->write_bufferram) this->write_bufferram = onenand_write_bufferram; + if (!this->block_markbad) + this->block_markbad = onenand_default_block_markbad; + if (!this->scan_bbt) + this->scan_bbt = onenand_default_bbt; + if (onenand_probe(mtd)) return -ENXIO; @@ -1472,7 +1539,7 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) /* Unlock whole block */ mtd->unlock(mtd, 0x0, this->chipsize); - return 0; + return this->scan_bbt(mtd); } /** diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index c557caa24a6c..89aaffbc9576 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -14,6 +14,7 @@ #include #include +#include #define MAX_BUFFERRAM 2 @@ -67,10 +68,14 @@ struct onenand_bufferram { * @param wait [REPLACEABLE] hardware specific function for wait on ready * @param read_bufferram [REPLACEABLE] hardware specific function for BufferRAM Area * @param write_bufferram [REPLACEABLE] hardware specific function for BufferRAM Area + * @param read_word [REPLACEABLE] hardware specific function for read register of OneNAND + * @param write_word [REPLACEABLE] hardware specific function for write register of OneNAND + * @param scan_bbt [REPLACEALBE] hardware specific function for scaning Bad block Table * @param chip_lock [INTERN] spinlock used to protect access to this structure and the chip * @param wq [INTERN] wait queue to sleep on if a OneNAND operation is in progress * @param state [INTERN] the current state of the OneNAND device * @param autooob [REPLACEABLE] the default (auto)placement scheme + * @param bbm [REPLACEABLE] pointer to Bad Block Management * @param priv [OPTIONAL] pointer to private chip date */ struct onenand_chip { @@ -96,6 +101,8 @@ struct onenand_chip { unsigned short (*read_word)(void __iomem *addr); void (*write_word)(unsigned short value, void __iomem *addr); void (*mmcontrol)(struct mtd_info *mtd, int sync_read); + int (*block_markbad)(struct mtd_info *mtd, loff_t ofs); + int (*scan_bbt)(struct mtd_info *mtd); spinlock_t chip_lock; wait_queue_head_t wq; @@ -103,6 +110,8 @@ struct onenand_chip { struct nand_oobinfo *autooob; + void *bbm; + void *priv; }; -- cgit v1.2.3 From fcc31470c49e224ed8115c70541f599fc7568fee Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Sat, 3 Sep 2005 07:20:08 +0100 Subject: [PATCH] OneNAND: Update OMAP OneNAND mapping using device driver model - Update OMAP OneNAND mapping file using device driver model - Remove board specific macro and values. Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/omap-onenand.c | 271 ++++++++++++------------------------- include/linux/mtd/onenand.h | 8 ++ 2 files changed, 97 insertions(+), 182 deletions(-) (limited to 'include/linux') diff --git a/drivers/mtd/onenand/omap-onenand.c b/drivers/mtd/onenand/omap-onenand.c index 7c89549f7f58..57e69f184d33 100644 --- a/drivers/mtd/onenand/omap-onenand.c +++ b/drivers/mtd/onenand/omap-onenand.c @@ -4,236 +4,143 @@ * Copyright (c) 2005 Samsung Electronics * Kyungmin Park * - * Derived from linux/drivers/mtd/nand/omap-nand-flash.c - * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * Overview: - * This is a device driver for the OneNAND flash device for TI OMAP boards. + * This is a device driver for the OneNAND flash for OMAP boards. */ -#include -#include +#include #include +#include #include #include #include #include -#include -#include -#include -#include +#include -#define OMAP_ONENAND_FLASH_START1 OMAP_CS2A_PHYS -#define OMAP_ONENAND_FLASH_START2 omap_cs3_phys() -/* - * MTD structure for OMAP board - */ -static struct mtd_info *omap_onenand_mtd = NULL; +#define DRIVER_NAME "onenand" -/* - * Define partitions for flash devices - */ #ifdef CONFIG_MTD_PARTITIONS -static struct mtd_partition static_partition[] = { - { - .name = "X-Loader + U-Boot", - .offset = 0, - .size = SZ_128K, - .mask_flags = MTD_WRITEABLE /* force read-only */ - }, - { - .name = "U-Boot Environment", - .offset = MTDPART_OFS_APPEND, - .size = SZ_128K, - .mask_flags = MTD_WRITEABLE /* force read-only */ - }, - { - .name = "kernel", - .offset = MTDPART_OFS_APPEND, - .size = 2 * SZ_1M - }, - { - .name = "filesystem0", - .offset = MTDPART_OFS_APPEND, - .size = SZ_16M, - }, - { - .name = "filesystem1", - .offset = MTDPART_OFS_APPEND, - .size = MTDPART_SIZ_FULL, - }, -}; - static const char *part_probes[] = { "cmdlinepart", NULL, }; - #endif -#ifdef CONFIG_MTD_ONENAND_SYNC_READ -static unsigned int omap_emifs_cs; +struct omap_onenand_info { + struct mtd_info mtd; + struct mtd_partition *parts; + struct onenand_chip onenand; +}; -static void omap_find_emifs_cs(unsigned int addr) +static int __devinit omap_onenand_probe(struct device *dev) { - /* Check CS3 */ - if (OMAP_EMIFS_CONFIG_REG & OMAP_EMIFS_CONFIG_BM && addr == 0x0) { - omap_emifs_cs = 3; - } else { - omap_emifs_cs = (addr >> 26); + struct omap_onenand_info *info; + struct platform_device *pdev = to_platform_device(dev); + struct onenand_platform_data *pdata = pdev->dev.platform_data; + struct resource *res = pdev->resource; + unsigned long size = res->end - res->start + 1; + int err; + + info = kmalloc(sizeof(struct omap_onenand_info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + memset(info, 0, sizeof(struct omap_onenand_info)); + + if (!request_mem_region(res->start, size, dev->driver->name)) { + err = -EBUSY; + goto out_free_info; } -} -/** - * omap_onenand_mmcontrol - Control OMAP EMIFS - */ -static void omap_onenand_mmcontrol(struct mtd_info *mtd, int sync_read) -{ - struct onenand_chip *this = mtd->priv; - static unsigned long omap_emifs_ccs, omap_emifs_acs; - static unsigned long onenand_sys_cfg1; - int config, emifs_ccs, emifs_acs; - - if (sync_read) { - /* - * Note: BRL and RDWST is equal - */ - omap_emifs_ccs = EMIFS_CCS(omap_emifs_cs); - omap_emifs_acs = EMIFS_ACS(omap_emifs_cs); - - emifs_ccs = 0x41141; - emifs_acs = 0x1; - - /* OneNAND System Configuration 1 */ - onenand_sys_cfg1 = this->read_word(this->base + ONENAND_REG_SYS_CFG1); - config = (onenand_sys_cfg1 - & ~(0x3f << ONENAND_SYS_CFG1_BL_SHIFT)) - | ONENAND_SYS_CFG1_SYNC_READ - | ONENAND_SYS_CFG1_BRL_4 - | ONENAND_SYS_CFG1_BL_8; - } else { - emifs_ccs = omap_emifs_ccs; - emifs_acs = omap_emifs_acs; - config = onenand_sys_cfg1; + info->onenand.base = ioremap(res->start, size); + if (!info->onenand.base) { + err = -ENOMEM; + goto out_release_mem_region; } - this->write_word(config, this->base + ONENAND_REG_SYS_CFG1); - EMIFS_CCS(omap_emifs_cs) = emifs_ccs; - EMIFS_ACS(omap_emifs_cs) = emifs_acs; -} -#else -#define omap_find_emifs_cs(x) do { } while (0) -#define omap_onenand_mmcontrol NULL -#endif + info->onenand.mmcontrol = pdata->mmcontrol; + info->mtd.name = pdev->dev.bus_id; + info->mtd.priv = &info->onenand; + info->mtd.owner = THIS_MODULE; -/* Scan to find existance of the device at base. - This also allocates oob and data internal buffers */ -static char onenand_name[] = "onenand"; - -/* - * Main initialization routine - */ -static int __init omap_onenand_init (void) -{ - struct onenand_chip *this; - struct mtd_partition *dynamic_partition = 0; - int err = 0; - - /* Allocate memory for MTD device structure and private data */ - omap_onenand_mtd = kmalloc (sizeof(struct mtd_info) + sizeof (struct onenand_chip), - GFP_KERNEL); - if (!omap_onenand_mtd) { - printk (KERN_WARNING "Unable to allocate OneNAND MTD device structure.\n"); - err = -ENOMEM; - goto out; + if (onenand_scan(&info->mtd, 1)) { + err = -ENXIO; + goto out_iounmap; } - /* Get pointer to private data */ - this = (struct onenand_chip *) (&omap_onenand_mtd[1]); +#ifdef CONFIG_MTD_PARTITIONS + err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0); + if (err > 0) + add_mtd_partitions(&info->mtd, info->parts, err); + else if (err < 0 && pdata->parts) + add_mtd_partitions(&info->mtd, pdata->parts, pdata->nr_parts); + else +#endif + err = add_mtd_device(&info->mtd); - /* Initialize structures */ - memset((char *) omap_onenand_mtd, 0, sizeof(struct mtd_info) + sizeof(struct onenand_chip)); + dev_set_drvdata(&pdev->dev, info); - /* Link the private data with the MTD structure */ - omap_onenand_mtd->priv = this; - this->mmcontrol = omap_onenand_mmcontrol; + return 0; - /* try the first address */ - this->base = ioremap(OMAP_ONENAND_FLASH_START1, SZ_128K); - omap_find_emifs_cs(OMAP_ONENAND_FLASH_START1); +out_iounmap: + iounmap(info->onenand.base); +out_release_mem_region: + release_mem_region(res->start, size); +out_free_info: + kfree(info); - omap_onenand_mtd->name = onenand_name; - if (onenand_scan(omap_onenand_mtd, 1)){ - /* try the second address */ - iounmap(this->base); - this->base = ioremap(OMAP_ONENAND_FLASH_START2, SZ_128K); - omap_find_emifs_cs(OMAP_ONENAND_FLASH_START2); + return err; +} - if (onenand_scan(omap_onenand_mtd, 1)) { - iounmap(this->base); - err = -ENXIO; - goto out_mtd; - } - } +static int __devexit omap_onenand_remove(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct omap_onenand_info *info = dev_get_drvdata(&pdev->dev); + struct resource *res = pdev->resource; + unsigned long size = res->end - res->start + 1; - /* Register the partitions */ - switch (omap_onenand_mtd->size) { - case SZ_128M: - case SZ_64M: - case SZ_32M: -#ifdef CONFIG_MTD_PARTITIONS - err = parse_mtd_partitions(omap_onenand_mtd, part_probes, - &dynamic_partition, 0); - if (err > 0) - err = add_mtd_partitions(omap_onenand_mtd, - dynamic_partition, err); - else if (1) - err = add_mtd_partitions(omap_onenand_mtd, - static_partition, - ARRAY_SIZE(static_partition)); + dev_set_drvdata(&pdev->dev, NULL); + + if (info) { + if (info->parts) + del_mtd_partitions(&info->mtd); else -#endif - err = add_mtd_device(omap_onenand_mtd); - if (err) - goto out_buf; - break; + del_mtd_device(&info->mtd); - default: - printk(KERN_WARNING "Unsupported OneNAND device\n"); - err = -ENXIO; - goto out_buf; + onenand_release(&info->mtd); + release_mem_region(res->start, size); + iounmap(info->onenand.base); + kfree(info); } return 0; - -out_buf: - onenand_release(omap_onenand_mtd); - iounmap(this->base); -out_mtd: - kfree(omap_onenand_mtd); -out: - return err; } -/* - * Clean up routine - */ -static void __exit omap_onenand_cleanup (void) +static struct device_driver omap_onenand_driver = { + .name = DRIVER_NAME, + .bus = &platform_bus_type, + .probe = omap_onenand_probe, + .remove = __devexit_p(omap_onenand_remove), +}; + +MODULE_ALIAS(DRIVER_NAME); + +static int __init omap_onenand_init(void) { - struct onenand_chip *this = omap_onenand_mtd->priv; + return driver_register(&omap_onenand_driver); +} - /* onenand_release frees MTD partitions, MTD structure - and onenand internal buffers */ - onenand_release(omap_onenand_mtd); - iounmap(this->base); - kfree(omap_onenand_mtd); +static void __exit omap_onenand_exit(void) +{ + driver_unregister(&omap_onenand_driver); } module_init(omap_onenand_init); -module_exit(omap_onenand_cleanup); +module_exit(omap_onenand_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Kyungmin Park "); diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index 89aaffbc9576..2c29a5ca2c91 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -115,10 +115,18 @@ struct onenand_chip { void *priv; }; +/* + * Helper macros + */ #define ONENAND_CURRENT_BUFFERRAM(this) (this->bufferram_index) #define ONENAND_NEXT_BUFFERRAM(this) (this->bufferram_index ^ 1) #define ONENAND_SET_NEXT_BUFFERRAM(this) (this->bufferram_index ^= 1) +#define ONENAND_GET_SYS_CFG1(this) \ + (this->read_word(this->base + ONENAND_REG_SYS_CFG1)) +#define ONENAND_SET_SYS_CFG1(v, this) \ + (this->write_word(v, this->base + ONENAND_REG_SYS_CFG1)) + /* * Options bits */ -- cgit v1.2.3 From d36d63d404b75ddf231da0dbd3640e6d1722b4ab Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Sat, 3 Sep 2005 07:36:21 +0100 Subject: [PATCH] OneNAND: Fix bug in write verify - Remove unused block, page parameters - Add constant instead of runtime value Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/onenand_base.c | 11 ++++------- include/linux/mtd/onenand.h | 1 + 2 files changed, 5 insertions(+), 7 deletions(-) (limited to 'include/linux') diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index bdeac01e659f..75d757882697 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -719,13 +719,10 @@ out: * onenand_verify_page - [GENERIC] verify the chip contents after a write * @param mtd MTD device structure * @param buf the databuffer to verify - * @param block block address - * @param page page address * * Check DataRAM area directly */ -static int onenand_verify_page(struct mtd_info *mtd, u_char *buf, - loff_t addr, int block, int page) +static int onenand_verify_page(struct mtd_info *mtd, u_char *buf, loff_t addr) { struct onenand_chip *this = mtd->priv; void __iomem *dataram0, *dataram1; @@ -816,7 +813,7 @@ static int onenand_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, written += thislen; /* Only check verify write turn on */ - ret = onenand_verify_page(mtd, (u_char *) buf, to, block, page); + ret = onenand_verify_page(mtd, (u_char *) buf, to); if (ret) { DEBUG(MTD_DEBUG_LEVEL0, "onenand_write_ecc: verify failed %d\n", ret); goto out; @@ -940,7 +937,7 @@ static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, u_char *eccbuf, struct nand_oobinfo *oobsel) { struct onenand_chip *this = mtd->priv; - unsigned char buffer[mtd->oobblock], *pbuf; + unsigned char buffer[MAX_ONENAND_PAGESIZE], *pbuf; size_t total_len, len; int i, written = 0; int ret = 0; @@ -1025,7 +1022,7 @@ static int onenand_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, /* Only check verify write turn on */ - ret = onenand_verify_page(mtd, (u_char *) pbuf, to, block, page); + ret = onenand_verify_page(mtd, (u_char *) pbuf, to); if (ret) { DEBUG(MTD_DEBUG_LEVEL0, "onenand_writev_ecc: verify failed %d\n", ret); goto out; diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index 2c29a5ca2c91..58023082320a 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -17,6 +17,7 @@ #include #define MAX_BUFFERRAM 2 +#define MAX_ONENAND_PAGESIZE (2048 + 64) /* Scan and identify a OneNAND device */ extern int onenand_scan(struct mtd_info *mtd, int max_chips); -- cgit v1.2.3 From e631ddba588783edd521c5a89f7b2902772fb691 Mon Sep 17 00:00:00 2001 From: Ferenc Havasi Date: Wed, 7 Sep 2005 09:35:26 +0100 Subject: [JFFS2] Add erase block summary support (mount time improvement) The goal of summary is to speed up the mount time. Erase block summary (EBS) stores summary information at the end of every (closed) erase block. It is no longer necessary to scan all nodes separetly (and read all pages of them) just read this "small" summary, where every information is stored which is needed at mount time. This summary information is stored in a JFFS2_FEATURE_RWCOMPAT_DELETE. During the mount process if there is no summary info the orignal scan process will be executed. EBS works with NAND and NOR flashes, too. There is a user space tool called sumtool to generate this summary information for a JFFS2 image. Signed-off-by: Ferenc Havasi Signed-off-by: Thomas Gleixner --- fs/Kconfig | 13 + fs/jffs2/Makefile | 3 +- fs/jffs2/build.c | 12 +- fs/jffs2/debug.h | 10 +- fs/jffs2/dir.c | 20 +- fs/jffs2/file.c | 5 +- fs/jffs2/fs.c | 5 +- fs/jffs2/gc.c | 26 +- fs/jffs2/nodelist.h | 13 +- fs/jffs2/nodemgmt.c | 250 ++++++++++----- fs/jffs2/os-linux.h | 19 +- fs/jffs2/scan.c | 198 ++++++++---- fs/jffs2/summary.c | 729 ++++++++++++++++++++++++++++++++++++++++++++ fs/jffs2/summary.h | 183 +++++++++++ fs/jffs2/super.c | 8 +- fs/jffs2/wbuf.c | 12 +- fs/jffs2/write.c | 29 +- fs/jffs2/writev.c | 34 ++- include/linux/jffs2.h | 21 +- include/linux/jffs2_fs_sb.h | 4 +- 20 files changed, 1395 insertions(+), 199 deletions(-) create mode 100644 fs/jffs2/summary.c create mode 100644 fs/jffs2/summary.h (limited to 'include/linux') diff --git a/fs/Kconfig b/fs/Kconfig index 01a295232f75..37d86c5072eb 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -1050,6 +1050,19 @@ config JFFS2_FS_WRITEBUFFER - NOR flash with transparent ECC - DataFlash +config JFFS2_SUMMARY + bool "JFFS2 summary support (EXPERIMENTAL)" + depends on JFFS2_FS && EXPERIMENTAL + default n + help + This feature makes it possible to use summary information + for faster filesystem mount. + + The summary information can be inserted into a filesystem image + by the utility 'sumtool'. + + If unsure, say 'N'. + config JFFS2_COMPRESSION_OPTIONS bool "Advanced compression options for JFFS2" depends on JFFS2_FS diff --git a/fs/jffs2/Makefile b/fs/jffs2/Makefile index e6230f1bba73..77dc5561a04e 100644 --- a/fs/jffs2/Makefile +++ b/fs/jffs2/Makefile @@ -1,7 +1,7 @@ # # Makefile for the Linux Journalling Flash File System v2 (JFFS2) # -# $Id: Makefile.common,v 1.10 2005/07/17 06:56:20 dedekind Exp $ +# $Id: Makefile.common,v 1.11 2005/09/07 08:34:53 havasi Exp $ # obj-$(CONFIG_JFFS2_FS) += jffs2.o @@ -15,3 +15,4 @@ jffs2-$(CONFIG_JFFS2_FS_WRITEBUFFER) += wbuf.o jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rubin.o jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o +jffs2-$(CONFIG_JFFS2_SUMMARY) += summary.o diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index 1522eace932e..f4a47a3b2a01 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: build.c,v 1.77 2005/08/31 13:51:00 havasi Exp $ + * $Id: build.c,v 1.78 2005/09/07 08:34:54 havasi Exp $ * */ @@ -350,6 +350,10 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c) INIT_LIST_HEAD(&c->bad_list); INIT_LIST_HEAD(&c->bad_used_list); c->highest_ino = 1; + c->summary = NULL; + + if (jffs2_sum_init(c)) + return -ENOMEM; if (jffs2_build_filesystem(c)) { D1(printk(KERN_DEBUG "build_fs failed\n")); @@ -357,11 +361,11 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c) jffs2_free_raw_node_refs(c); #ifndef __ECOS if (jffs2_blocks_use_vmalloc(c)) - vfree(c->blocks); + vfree(c->blocks); else #endif - kfree(c->blocks); - + kfree(c->blocks); + return -EIO; } diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index 03d9626ad1ce..60e5dbb3946a 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.h,v 1.14 2005/08/17 13:48:59 dedekind Exp $ + * $Id: debug.h,v 1.15 2005/09/07 08:34:54 havasi Exp $ * */ #ifndef _JFFS2_DEBUG_H_ @@ -28,6 +28,7 @@ #define JFFS2_DBG_DENTLIST_MESSAGES #define JFFS2_DBG_NODEREF_MESSAGES #define JFFS2_DBG_INOCACHE_MESSAGES +#define JFFS2_DBG_SUMMARY_MESSAGES #endif #if CONFIG_JFFS2_FS_DEBUG == 2 @@ -137,6 +138,13 @@ #define JFFS2_DBG_INOCACHE(fmt, ...) #endif +/* Summary debugging messages */ +#ifdef JFFS2_DBG_SUMMARY_MESSAGES +#define JFFS2_DBG_SUMMARY(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#else +#define JFFS2_DBG_SUMMARY(fmt, ...) +#endif + /* Watch the object allocations */ #ifdef JFFS2_DBG_MEMALLOC_MESSAGES #define JFFS2_DBG_MEMALLOC(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 0fd15aaf2458..19bea0f95ac1 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: dir.c,v 1.88 2005/08/17 13:46:22 dedekind Exp $ + * $Id: dir.c,v 1.89 2005/09/07 08:34:54 havasi Exp $ * */ @@ -310,7 +310,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char * Just the node will do for now, though */ namelen = dentry->d_name.len; - ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &phys_ofs, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); if (ret) { jffs2_free_raw_inode(ri); @@ -370,7 +371,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char up(&f->sem); jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); if (ret) { /* Eep. */ jffs2_clear_inode(inode); @@ -455,7 +457,8 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) * Just the node will do for now, though */ namelen = dentry->d_name.len; - ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL, + JFFS2_SUMMARY_INODE_SIZE); if (ret) { jffs2_free_raw_inode(ri); @@ -498,7 +501,8 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) up(&f->sem); jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); if (ret) { /* Eep. */ jffs2_clear_inode(inode); @@ -607,7 +611,8 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de * Just the node will do for now, though */ namelen = dentry->d_name.len; - ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &phys_ofs, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); if (ret) { jffs2_free_raw_inode(ri); @@ -652,7 +657,8 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de up(&f->sem); jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); if (ret) { /* Eep. */ jffs2_clear_inode(inode); diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index 8279bf0133ff..231404a74728 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: file.c,v 1.102 2005/07/06 12:13:09 dwmw2 Exp $ + * $Id: file.c,v 1.103 2005/09/07 08:34:54 havasi Exp $ * */ @@ -134,7 +134,8 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg, D1(printk(KERN_DEBUG "Writing new hole frag 0x%x-0x%x between current EOF and new page\n", (unsigned int)inode->i_size, pageofs)); - ret = jffs2_reserve_space(c, sizeof(ri), &phys_ofs, &alloc_len, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(ri), &phys_ofs, &alloc_len, + ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); if (ret) return ret; diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index c99451ae4b77..c15c30220475 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: fs.c,v 1.64 2005/09/01 08:42:31 havasi Exp $ + * $Id: fs.c,v 1.65 2005/09/07 08:34:54 havasi Exp $ * */ @@ -74,7 +74,8 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) return -ENOMEM; } - ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &phys_ofs, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); if (ret) { jffs2_free_raw_inode(ri); if (S_ISLNK(inode->i_mode & S_IFMT)) diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index def97157ecbd..ee54cdc59e06 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: gc.c,v 1.153 2005/08/17 13:46:22 dedekind Exp $ + * $Id: gc.c,v 1.154 2005/09/07 08:34:54 havasi Exp $ * */ @@ -513,8 +513,11 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, /* Ask for a small amount of space (or the totlen if smaller) because we don't want to force wastage of the end of a block if splitting would work. */ - ret = jffs2_reserve_space_gc(c, min_t(uint32_t, sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN, - rawlen), &phys_ofs, &alloclen); + ret = jffs2_reserve_space_gc(c, min_t(uint32_t, sizeof(struct jffs2_raw_inode) + + JFFS2_MIN_DATA_LEN, rawlen), &phys_ofs, &alloclen, rawlen); + /* this is not the exact summary size of it, + it is only an upper estimation */ + if (ret) return ret; @@ -622,7 +625,9 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, jffs2_dbg_acct_sanity_check(c,jeb); jffs2_dbg_acct_paranoia_check(c, jeb); - ret = jffs2_reserve_space_gc(c, rawlen, &phys_ofs, &dummy); + ret = jffs2_reserve_space_gc(c, rawlen, &phys_ofs, &dummy, rawlen); + /* this is not the exact summary size of it, + it is only an upper estimation */ if (!ret) { D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", phys_ofs)); @@ -701,7 +706,8 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ } - ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &phys_ofs, &alloclen); + ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &phys_ofs, &alloclen, + JFFS2_SUMMARY_INODE_SIZE); if (ret) { printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_metadata failed: %d\n", sizeof(ri)+ mdatalen, ret); @@ -781,7 +787,8 @@ static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_er rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd)-8)); rd.name_crc = cpu_to_je32(crc32(0, fd->name, rd.nsize)); - ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &phys_ofs, &alloclen); + ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &phys_ofs, &alloclen, + JFFS2_SUMMARY_DIRENT_SIZE(rd.nsize)); if (ret) { printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_dirent failed: %d\n", sizeof(rd)+rd.nsize, ret); @@ -994,7 +1001,8 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras ri.data_crc = cpu_to_je32(0); ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); - ret = jffs2_reserve_space_gc(c, sizeof(ri), &phys_ofs, &alloclen); + ret = jffs2_reserve_space_gc(c, sizeof(ri), &phys_ofs, &alloclen, + JFFS2_SUMMARY_INODE_SIZE); if (ret) { printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_hole failed: %d\n", sizeof(ri), ret); @@ -1219,7 +1227,8 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era uint32_t cdatalen; uint16_t comprtype = JFFS2_COMPR_NONE; - ret = jffs2_reserve_space_gc(c, sizeof(ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, &alloclen); + ret = jffs2_reserve_space_gc(c, sizeof(ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, + &alloclen, JFFS2_SUMMARY_INODE_SIZE); if (ret) { printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_dnode failed: %d\n", @@ -1276,4 +1285,3 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era jffs2_gc_release_page(c, pg_ptr, &pg); return ret; } - diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 1533af8b3959..1222372cb290 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.h,v 1.139 2005/08/31 13:51:00 havasi Exp $ + * $Id: nodelist.h,v 1.140 2005/09/07 08:34:54 havasi Exp $ * */ @@ -20,6 +20,7 @@ #include #include #include +#include "summary.h" #ifdef __ECOS #include "os-ecos.h" @@ -326,8 +327,10 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode /* nodemgmt.c */ int jffs2_thread_should_wake(struct jffs2_sb_info *c); -int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, int prio); -int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len); +int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, + uint32_t *len, int prio, uint32_t sumsize); +int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, + uint32_t *len, uint32_t sumsize); int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new); void jffs2_complete_reservation(struct jffs2_sb_info *c); void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw); @@ -386,6 +389,10 @@ char *jffs2_getlink(struct jffs2_sb_info *c, struct jffs2_inode_info *f); /* scan.c */ int jffs2_scan_medium(struct jffs2_sb_info *c); void jffs2_rotate_lists(struct jffs2_sb_info *c); +int jffs2_fill_scan_buf(struct jffs2_sb_info *c, void *buf, + uint32_t ofs, uint32_t len); +struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino); +int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); /* build.c */ int jffs2_do_mount_fs(struct jffs2_sb_info *c); diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index fe7e70a4055b..208b2bdf01e5 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodemgmt.c,v 1.124 2005/07/20 15:32:28 dedekind Exp $ + * $Id: nodemgmt.c,v 1.125 2005/09/07 08:34:54 havasi Exp $ * */ @@ -17,6 +17,7 @@ #include #include /* For cond_resched() */ #include "nodelist.h" +#include "debug.h" /** * jffs2_reserve_space - request physical space to write nodes to flash @@ -38,9 +39,11 @@ * for the requested allocation. */ -static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len); +static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, + uint32_t *ofs, uint32_t *len, uint32_t sumsize); -int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, int prio) +int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, + uint32_t *len, int prio, uint32_t sumsize) { int ret = -EAGAIN; int blocksneeded = c->resv_blocks_write; @@ -129,7 +132,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs spin_lock(&c->erase_completion_lock); } - ret = jffs2_do_reserve_space(c, minsize, ofs, len); + ret = jffs2_do_reserve_space(c, minsize, ofs, len, sumsize); if (ret) { D1(printk(KERN_DEBUG "jffs2_reserve_space: ret is %d\n", ret)); } @@ -140,7 +143,8 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs return ret; } -int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len) +int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, + uint32_t *len, uint32_t sumsize) { int ret = -EAGAIN; minsize = PAD(minsize); @@ -149,7 +153,7 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t * spin_lock(&c->erase_completion_lock); while(ret == -EAGAIN) { - ret = jffs2_do_reserve_space(c, minsize, ofs, len); + ret = jffs2_do_reserve_space(c, minsize, ofs, len, sumsize); if (ret) { D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret)); } @@ -158,105 +162,183 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t * return ret; } -/* Called with alloc sem _and_ erase_completion_lock */ -static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len) + +/* Classify nextblock (clean, dirty of verydirty) and force to select an other one */ + +static void jffs2_close_nextblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) { - struct jffs2_eraseblock *jeb = c->nextblock; + + /* Check, if we have a dirty block now, or if it was dirty already */ + if (ISDIRTY (jeb->wasted_size + jeb->dirty_size)) { + c->dirty_size += jeb->wasted_size; + c->wasted_size -= jeb->wasted_size; + jeb->dirty_size += jeb->wasted_size; + jeb->wasted_size = 0; + if (VERYDIRTY(c, jeb->dirty_size)) { + D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to very_dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", + jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); + list_add_tail(&jeb->list, &c->very_dirty_list); + } else { + D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", + jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); + list_add_tail(&jeb->list, &c->dirty_list); + } + } else { + D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to clean_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", + jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); + list_add_tail(&jeb->list, &c->clean_list); + } + c->nextblock = NULL; + +} + +/* Select a new jeb for nextblock */ + +static int jffs2_find_nextblock(struct jffs2_sb_info *c) +{ + struct list_head *next; - restart: - if (jeb && minsize > jeb->free_size) { - /* Skip the end of this block and file it as having some dirty space */ - /* If there's a pending write to it, flush now */ - if (jffs2_wbuf_dirty(c)) { + /* Take the next block off the 'free' list */ + + if (list_empty(&c->free_list)) { + + if (!c->nr_erasing_blocks && + !list_empty(&c->erasable_list)) { + struct jffs2_eraseblock *ejeb; + + ejeb = list_entry(c->erasable_list.next, struct jffs2_eraseblock, list); + list_del(&ejeb->list); + list_add_tail(&ejeb->list, &c->erase_pending_list); + c->nr_erasing_blocks++; + jffs2_erase_pending_trigger(c); + D1(printk(KERN_DEBUG "jffs2_find_nextblock: Triggering erase of erasable block at 0x%08x\n", + ejeb->offset)); + } + + if (!c->nr_erasing_blocks && + !list_empty(&c->erasable_pending_wbuf_list)) { + D1(printk(KERN_DEBUG "jffs2_find_nextblock: Flushing write buffer\n")); + /* c->nextblock is NULL, no update to c->nextblock allowed */ spin_unlock(&c->erase_completion_lock); - D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Flushing write buffer\n")); jffs2_flush_wbuf_pad(c); spin_lock(&c->erase_completion_lock); - jeb = c->nextblock; - goto restart; + /* Have another go. It'll be on the erasable_list now */ + return -EAGAIN; } - c->wasted_size += jeb->free_size; - c->free_size -= jeb->free_size; - jeb->wasted_size += jeb->free_size; - jeb->free_size = 0; - - /* Check, if we have a dirty block now, or if it was dirty already */ - if (ISDIRTY (jeb->wasted_size + jeb->dirty_size)) { - c->dirty_size += jeb->wasted_size; - c->wasted_size -= jeb->wasted_size; - jeb->dirty_size += jeb->wasted_size; - jeb->wasted_size = 0; - if (VERYDIRTY(c, jeb->dirty_size)) { - D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to very_dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - list_add_tail(&jeb->list, &c->very_dirty_list); - } else { - D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to dirty_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - list_add_tail(&jeb->list, &c->dirty_list); - } - } else { - D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to clean_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - list_add_tail(&jeb->list, &c->clean_list); + + if (!c->nr_erasing_blocks) { + /* Ouch. We're in GC, or we wouldn't have got here. + And there's no space left. At all. */ + printk(KERN_CRIT "Argh. No free space left for GC. nr_erasing_blocks is %d. nr_free_blocks is %d. (erasableempty: %s, erasingempty: %s, erasependingempty: %s)\n", + c->nr_erasing_blocks, c->nr_free_blocks, list_empty(&c->erasable_list)?"yes":"no", + list_empty(&c->erasing_list)?"yes":"no", list_empty(&c->erase_pending_list)?"yes":"no"); + return -ENOSPC; } - c->nextblock = jeb = NULL; + + spin_unlock(&c->erase_completion_lock); + /* Don't wait for it; just erase one right now */ + jffs2_erase_pending_blocks(c, 1); + spin_lock(&c->erase_completion_lock); + + /* An erase may have failed, decreasing the + amount of free space available. So we must + restart from the beginning */ + return -EAGAIN; } + + next = c->free_list.next; + list_del(next); + c->nextblock = list_entry(next, struct jffs2_eraseblock, list); + c->nr_free_blocks--; - if (!jeb) { - struct list_head *next; - /* Take the next block off the 'free' list */ + jffs2_sum_reset_collected(c->summary); /* reset collected summary */ - if (list_empty(&c->free_list)) { + D1(printk(KERN_DEBUG "jffs2_find_nextblock(): new nextblock = 0x%08x\n", c->nextblock->offset)); - if (!c->nr_erasing_blocks && - !list_empty(&c->erasable_list)) { - struct jffs2_eraseblock *ejeb; + return 0; +} - ejeb = list_entry(c->erasable_list.next, struct jffs2_eraseblock, list); - list_del(&ejeb->list); - list_add_tail(&ejeb->list, &c->erase_pending_list); - c->nr_erasing_blocks++; - jffs2_erase_pending_trigger(c); - D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Triggering erase of erasable block at 0x%08x\n", - ejeb->offset)); +/* Called with alloc sem _and_ erase_completion_lock */ +static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, uint32_t sumsize) +{ + struct jffs2_eraseblock *jeb = c->nextblock; + uint32_t reserved_size; /* for summary information at the end of the jeb */ + int ret; + + restart: + reserved_size = 0; + + if (jffs2_sum_active() && (sumsize != JFFS2_SUMMARY_NOSUM_SIZE)) { + /* NOSUM_SIZE means not to generate summary */ + + if (jeb) { + reserved_size = PAD(sumsize + c->summary->sum_size + JFFS2_SUMMARY_FRAME_SIZE); + JFFS2_DBG_SUMMARY("minsize=%d , jeb->free=%d ," + "summary->size=%d , sumsize=%d\n", + minsize, jeb->free_size, + c->summary->sum_size, sumsize); + } + + /* Is there enough space for writing out the current node, or we have to + write out summary information now, close this jeb and select new nextblock? */ + if (jeb && (PAD(minsize) + PAD(c->summary->sum_size + sumsize + + JFFS2_SUMMARY_FRAME_SIZE) > jeb->free_size)) { + + /* Has summary been disabled for this jeb? */ + if (jffs2_sum_is_disabled(c->summary)) { + sumsize = JFFS2_SUMMARY_NOSUM_SIZE; + goto restart; } - if (!c->nr_erasing_blocks && - !list_empty(&c->erasable_pending_wbuf_list)) { - D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Flushing write buffer\n")); - /* c->nextblock is NULL, no update to c->nextblock allowed */ + /* Writing out the collected summary information */ + JFFS2_DBG_SUMMARY("generating summary for 0x%08x.\n", jeb->offset); + ret = jffs2_sum_write_sumnode(c); + + if (ret) + return ret; + + if (jffs2_sum_is_disabled(c->summary)) { + /* jffs2_write_sumnode() couldn't write out the summary information + diabling summary for this jeb and free the collected information + */ + sumsize = JFFS2_SUMMARY_NOSUM_SIZE; + goto restart; + } + + jffs2_close_nextblock(c, jeb); + jeb = NULL; + } + } else { + if (jeb && minsize > jeb->free_size) { + /* Skip the end of this block and file it as having some dirty space */ + /* If there's a pending write to it, flush now */ + + if (jffs2_wbuf_dirty(c)) { spin_unlock(&c->erase_completion_lock); + D1(printk(KERN_DEBUG "jffs2_do_reserve_space: Flushing write buffer\n")); jffs2_flush_wbuf_pad(c); spin_lock(&c->erase_completion_lock); - /* Have another go. It'll be on the erasable_list now */ - return -EAGAIN; - } - - if (!c->nr_erasing_blocks) { - /* Ouch. We're in GC, or we wouldn't have got here. - And there's no space left. At all. */ - printk(KERN_CRIT "Argh. No free space left for GC. nr_erasing_blocks is %d. nr_free_blocks is %d. (erasableempty: %s, erasingempty: %s, erasependingempty: %s)\n", - c->nr_erasing_blocks, c->nr_free_blocks, list_empty(&c->erasable_list)?"yes":"no", - list_empty(&c->erasing_list)?"yes":"no", list_empty(&c->erase_pending_list)?"yes":"no"); - return -ENOSPC; + jeb = c->nextblock; + goto restart; } - spin_unlock(&c->erase_completion_lock); - /* Don't wait for it; just erase one right now */ - jffs2_erase_pending_blocks(c, 1); - spin_lock(&c->erase_completion_lock); + c->wasted_size += jeb->free_size; + c->free_size -= jeb->free_size; + jeb->wasted_size += jeb->free_size; + jeb->free_size = 0; - /* An erase may have failed, decreasing the - amount of free space available. So we must - restart from the beginning */ - return -EAGAIN; + jffs2_close_nextblock(c, jeb); + jeb = NULL; } + } + + if (!jeb) { + + ret = jffs2_find_nextblock(c); + if (ret) + return ret; - next = c->free_list.next; - list_del(next); - c->nextblock = jeb = list_entry(next, struct jffs2_eraseblock, list); - c->nr_free_blocks--; + jeb = c->nextblock; if (jeb->free_size != c->sector_size - c->cleanmarker_size) { printk(KERN_WARNING "Eep. Block 0x%08x taken from free_list had free_size of 0x%08x!!\n", jeb->offset, jeb->free_size); @@ -266,7 +348,7 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, ui /* OK, jeb (==c->nextblock) is now pointing at a block which definitely has enough space */ *ofs = jeb->offset + (c->sector_size - jeb->free_size); - *len = jeb->free_size; + *len = jeb->free_size - reserved_size; if (c->cleanmarker_size && jeb->used_size == c->cleanmarker_size && !jeb->first_node->next_in_ino) { diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index c3c1619fb137..e026888cf1cb 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: os-linux.h,v 1.60 2005/08/06 04:51:30 nico Exp $ + * $Id: os-linux.h,v 1.61 2005/09/07 08:34:54 havasi Exp $ * */ @@ -67,12 +67,18 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) #ifndef CONFIG_JFFS2_FS_WRITEBUFFER #define SECTOR_ADDR(x) ( ((unsigned long)(x) & ~(c->sector_size-1)) ) + +#ifdef CONFIG_JFFS2_SUMMARY +#define jffs2_can_mark_obsolete(c) (0) +#else #define jffs2_can_mark_obsolete(c) (1) +#endif + #define jffs2_is_writebuffered(c) (0) #define jffs2_cleanmarker_oob(c) (0) #define jffs2_write_nand_cleanmarker(c,jeb) (-EIO) -#define jffs2_flash_write(c, ofs, len, retlen, buf) ((c)->mtd->write((c)->mtd, ofs, len, retlen, buf)) +#define jffs2_flash_write(c, ofs, len, retlen, buf) jffs2_flash_direct_write(c, ofs, len, retlen, buf) #define jffs2_flash_read(c, ofs, len, retlen, buf) ((c)->mtd->read((c)->mtd, ofs, len, retlen, buf)) #define jffs2_flush_wbuf_pad(c) ({ (void)(c), 0; }) #define jffs2_flush_wbuf_gc(c, i) ({ (void)(c), (void) i, 0; }) @@ -97,9 +103,15 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) #define jffs2_is_writebuffered(c) (c->wbuf != NULL) #define SECTOR_ADDR(x) ( ((unsigned long)(x) / (unsigned long)(c->sector_size)) * c->sector_size ) + +#ifdef CONFIG_JFFS2_SUMMARY +#define jffs2_can_mark_obsolete(c) (0) +#else #define jffs2_can_mark_obsolete(c) \ ((c->mtd->type == MTD_NORFLASH && !(c->mtd->flags & (MTD_ECC|MTD_PROGRAM_REGIONS))) || \ c->mtd->type == MTD_RAM) +#endif + #define jffs2_cleanmarker_oob(c) (c->mtd->type == MTD_NANDFLASH) #define jffs2_flash_write_oob(c, ofs, len, retlen, buf) ((c)->mtd->write_oob((c)->mtd, ofs, len, retlen, buf)) @@ -192,7 +204,8 @@ void jffs2_flash_cleanup(struct jffs2_sb_info *c); /* writev.c */ int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); - +int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, + size_t *retlen, const u_char *buf); #endif /* __JFFS2_OS_LINUX_H__ */ diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index fcd6314cf179..4e60ba8da197 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: scan.c,v 1.121 2005/07/20 15:32:28 dedekind Exp $ + * $Id: scan.c,v 1.122 2005/09/07 08:34:54 havasi Exp $ * */ #include @@ -18,22 +18,11 @@ #include #include #include "nodelist.h" +#include "summary.h" +#include "debug.h" #define DEFAULT_EMPTY_SCAN_SIZE 1024 -#define DIRTY_SPACE(x) do { typeof(x) _x = (x); \ - c->free_size -= _x; c->dirty_size += _x; \ - jeb->free_size -= _x ; jeb->dirty_size += _x; \ - }while(0) -#define USED_SPACE(x) do { typeof(x) _x = (x); \ - c->free_size -= _x; c->used_size += _x; \ - jeb->free_size -= _x ; jeb->used_size += _x; \ - }while(0) -#define UNCHECKED_SPACE(x) do { typeof(x) _x = (x); \ - c->free_size -= _x; c->unchecked_size += _x; \ - jeb->free_size -= _x ; jeb->unchecked_size += _x; \ - }while(0) - #define noisy_printk(noise, args...) do { \ if (*(noise)) { \ printk(KERN_NOTICE args); \ @@ -47,23 +36,16 @@ static uint32_t pseudo_random; static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - unsigned char *buf, uint32_t buf_size); + unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s); /* These helper functions _must_ increase ofs and also do the dirty/used space accounting. * Returning an error will abort the mount - bad checksums etc. should just mark the space * as dirty. */ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_raw_inode *ri, uint32_t ofs); + struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s); static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_raw_dirent *rd, uint32_t ofs); - -#define BLK_STATE_ALLFF 0 -#define BLK_STATE_CLEAN 1 -#define BLK_STATE_PARTDIRTY 2 -#define BLK_STATE_CLEANMARKER 3 -#define BLK_STATE_ALLDIRTY 4 -#define BLK_STATE_BADBLOCK 5 + struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s); static inline int min_free(struct jffs2_sb_info *c) { @@ -89,6 +71,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) uint32_t empty_blocks = 0, bad_blocks = 0; unsigned char *flashbuf = NULL; uint32_t buf_size = 0; + struct jffs2_summary *s = NULL; /* summary info collected by the scan process */ #ifndef __ECOS size_t pointlen; @@ -122,10 +105,23 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) return -ENOMEM; } + if (jffs2_sum_active()) { + s = kmalloc(sizeof(struct jffs2_summary), GFP_KERNEL); + if (!s) { + JFFS2_WARNING("Can't allocate memory for summary\n"); + return -ENOMEM; + } + memset(s, 0, sizeof(struct jffs2_summary)); + } + for (i=0; inr_blocks; i++) { struct jffs2_eraseblock *jeb = &c->blocks[i]; - ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), buf_size); + /* reset summary info for next eraseblock scan */ + jffs2_sum_reset_collected(s); + + ret = jffs2_scan_eraseblock(c, jeb, buf_size?flashbuf:(flashbuf+jeb->offset), + buf_size, s); if (ret < 0) goto out; @@ -162,18 +158,18 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) break; case BLK_STATE_CLEAN: - /* Full (or almost full) of clean data. Clean list */ - list_add(&jeb->list, &c->clean_list); + /* Full (or almost full) of clean data. Clean list */ + list_add(&jeb->list, &c->clean_list); break; case BLK_STATE_PARTDIRTY: - /* Some data, but not full. Dirty list. */ - /* We want to remember the block with most free space - and stick it in the 'nextblock' position to start writing to it. */ - if (jeb->free_size > min_free(c) && - (!c->nextblock || c->nextblock->free_size < jeb->free_size)) { - /* Better candidate for the next writes to go to */ - if (c->nextblock) { + /* Some data, but not full. Dirty list. */ + /* We want to remember the block with most free space + and stick it in the 'nextblock' position to start writing to it. */ + if (jeb->free_size > min_free(c) && + (!c->nextblock || c->nextblock->free_size < jeb->free_size)) { + /* Better candidate for the next writes to go to */ + if (c->nextblock) { c->nextblock->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size; c->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size; c->free_size -= c->nextblock->free_size; @@ -184,9 +180,14 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) } else { list_add(&c->nextblock->list, &c->dirty_list); } + /* deleting summary information of the old nextblock */ + jffs2_sum_reset_collected(c->summary); } - c->nextblock = jeb; - } else { + /* update collected summary infromation for the current nextblock */ + jffs2_sum_move_collected(c, s); + D1(printk(KERN_DEBUG "jffs2_scan_medium(): new nextblock = 0x%08x\n", jeb->offset)); + c->nextblock = jeb; + } else { jeb->dirty_size += jeb->free_size + jeb->wasted_size; c->dirty_size += jeb->free_size + jeb->wasted_size; c->free_size -= jeb->free_size; @@ -197,30 +198,33 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) } else { list_add(&jeb->list, &c->dirty_list); } - } + } break; case BLK_STATE_ALLDIRTY: /* Nothing valid - not even a clean marker. Needs erasing. */ - /* For now we just put it on the erasing list. We'll start the erases later */ + /* For now we just put it on the erasing list. We'll start the erases later */ D1(printk(KERN_NOTICE "JFFS2: Erase block at 0x%08x is not formatted. It will be erased\n", jeb->offset)); - list_add(&jeb->list, &c->erase_pending_list); + list_add(&jeb->list, &c->erase_pending_list); c->nr_erasing_blocks++; break; - + case BLK_STATE_BADBLOCK: D1(printk(KERN_NOTICE "JFFS2: Block at 0x%08x is bad\n", jeb->offset)); - list_add(&jeb->list, &c->bad_list); + list_add(&jeb->list, &c->bad_list); c->bad_size += c->sector_size; c->free_size -= c->sector_size; bad_blocks++; break; default: printk(KERN_WARNING "jffs2_scan_medium(): unknown block state\n"); - BUG(); + BUG(); } } - + + if (jffs2_sum_active() && s) + kfree(s); + /* Nextblock dirty is always seen as wasted, because we cannot recycle it now */ if (c->nextblock && (c->nextblock->dirty_size)) { c->nextblock->wasted_size += c->nextblock->dirty_size; @@ -265,7 +269,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) return ret; } -static int jffs2_fill_scan_buf (struct jffs2_sb_info *c, unsigned char *buf, +int jffs2_fill_scan_buf (struct jffs2_sb_info *c, void *buf, uint32_t ofs, uint32_t len) { int ret; @@ -286,14 +290,36 @@ static int jffs2_fill_scan_buf (struct jffs2_sb_info *c, unsigned char *buf, return 0; } +int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) +{ + if ((jeb->used_size + jeb->unchecked_size) == PAD(c->cleanmarker_size) && !jeb->dirty_size + && (!jeb->first_node || !jeb->first_node->next_phys) ) + return BLK_STATE_CLEANMARKER; + + /* move blocks with max 4 byte dirty space to cleanlist */ + else if (!ISDIRTY(c->sector_size - (jeb->used_size + jeb->unchecked_size))) { + c->dirty_size -= jeb->dirty_size; + c->wasted_size += jeb->dirty_size; + jeb->wasted_size += jeb->dirty_size; + jeb->dirty_size = 0; + return BLK_STATE_CLEAN; + } else if (jeb->used_size || jeb->unchecked_size) + return BLK_STATE_PARTDIRTY; + else + return BLK_STATE_ALLDIRTY; +} + static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - unsigned char *buf, uint32_t buf_size) { + unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) { struct jffs2_unknown_node *node; struct jffs2_unknown_node crcnode; + struct jffs2_sum_marker *sm; uint32_t ofs, prevofs; uint32_t hdr_crc, buf_ofs, buf_len; int err; int noise = 0; + + #ifdef CONFIG_JFFS2_FS_WRITEBUFFER int cleanmarkerfound = 0; #endif @@ -319,10 +345,46 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo } } #endif + + if (jffs2_sum_active()) { + sm = kmalloc(sizeof(struct jffs2_sum_marker), GFP_KERNEL); + if (!sm) { + return -ENOMEM; + } + + err = jffs2_fill_scan_buf(c, (unsigned char *) sm, jeb->offset + c->sector_size - + sizeof(struct jffs2_sum_marker), sizeof(struct jffs2_sum_marker)); + if (err) { + kfree(sm); + return err; + } + + if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC ) { + err = jffs2_sum_scan_sumnode(c, jeb, je32_to_cpu(sm->offset), &pseudo_random); + if (err) { + kfree(sm); + return err; + } + } + + kfree(sm); + + ofs = jeb->offset; + prevofs = jeb->offset - 1; + } + buf_ofs = jeb->offset; if (!buf_size) { buf_len = c->sector_size; + + if (jffs2_sum_active()) { + /* must reread because of summary test */ + err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len); + if (err) + return err; + } + } else { buf_len = EMPTY_SCAN_SIZE(c->sector_size); err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len); @@ -367,6 +429,8 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo noise = 10; + JFFS2_DBG_SUMMARY("no summary found in jeb 0x%08x. Apply original scan.\n",jeb->offset); + scan_more: while(ofs < jeb->offset + c->sector_size) { @@ -532,7 +596,7 @@ scan_more: buf_ofs = ofs; node = (void *)buf; } - err = jffs2_scan_inode_node(c, jeb, (void *)node, ofs); + err = jffs2_scan_inode_node(c, jeb, (void *)node, ofs, s); if (err) return err; ofs += PAD(je32_to_cpu(node->totlen)); break; @@ -548,7 +612,7 @@ scan_more: buf_ofs = ofs; node = (void *)buf; } - err = jffs2_scan_dirent_node(c, jeb, (void *)node, ofs); + err = jffs2_scan_dirent_node(c, jeb, (void *)node, ofs, s); if (err) return err; ofs += PAD(je32_to_cpu(node->totlen)); break; @@ -582,6 +646,8 @@ scan_more: break; case JFFS2_NODETYPE_PADDING: + if (jffs2_sum_active()) + jffs2_sum_add_padding_mem(s, je32_to_cpu(node->totlen)); DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); ofs += PAD(je32_to_cpu(node->totlen)); break; @@ -616,6 +682,13 @@ scan_more: } } + if (jffs2_sum_active()) { + if (PAD(s->sum_size + JFFS2_SUMMARY_FRAME_SIZE) > jeb->free_size) { + JFFS2_DBG_SUMMARY("There is not enough space for " + "summary information, disabling for this jeb!\n"); + jffs2_sum_disable_collecting(s); + } + } D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x\n", jeb->offset, jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size)); @@ -628,24 +701,10 @@ scan_more: jeb->wasted_size = 0; } - if ((jeb->used_size + jeb->unchecked_size) == PAD(c->cleanmarker_size) && !jeb->dirty_size - && (!jeb->first_node || !jeb->first_node->next_phys) ) - return BLK_STATE_CLEANMARKER; - - /* move blocks with max 4 byte dirty space to cleanlist */ - else if (!ISDIRTY(c->sector_size - (jeb->used_size + jeb->unchecked_size))) { - c->dirty_size -= jeb->dirty_size; - c->wasted_size += jeb->dirty_size; - jeb->wasted_size += jeb->dirty_size; - jeb->dirty_size = 0; - return BLK_STATE_CLEAN; - } else if (jeb->used_size || jeb->unchecked_size) - return BLK_STATE_PARTDIRTY; - else - return BLK_STATE_ALLDIRTY; + return jffs2_scan_classify_jeb(c, jeb); } -static struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino) +struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino) { struct jffs2_inode_cache *ic; @@ -672,7 +731,7 @@ static struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info } static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_raw_inode *ri, uint32_t ofs) + struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s) { struct jffs2_raw_node_ref *raw; struct jffs2_inode_cache *ic; @@ -739,11 +798,16 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc pseudo_random += je32_to_cpu(ri->version); UNCHECKED_SPACE(PAD(je32_to_cpu(ri->totlen))); + + if (jffs2_sum_active()) { + jffs2_sum_add_inode_mem(s, ri, ofs - jeb->offset); + } + return 0; } static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_raw_dirent *rd, uint32_t ofs) + struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s) { struct jffs2_raw_node_ref *raw; struct jffs2_full_dirent *fd; @@ -817,6 +881,10 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo USED_SPACE(PAD(je32_to_cpu(rd->totlen))); jffs2_add_fd_to_list(c, fd, &ic->scan_dents); + if (jffs2_sum_active()) { + jffs2_sum_add_dirent_mem(s, rd, ofs - jeb->offset); + } + return 0; } diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c new file mode 100644 index 000000000000..cb5dd8f11e73 --- /dev/null +++ b/fs/jffs2/summary.c @@ -0,0 +1,729 @@ +/* + * JFFS2 -- Journalling Flash File System, Version 2. + * + * Copyright (C) 2004 Ferenc Havasi , + * Zoltan Sogor , + * Patrik Kluba , + * University of Szeged, Hungary + * + * For licensing information, see the file 'LICENCE' in this directory. + * + * $Id: summary.c,v 1.1 2005/09/07 08:34:54 havasi Exp $ + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "nodelist.h" +#include "debug.h" + +int jffs2_sum_init(struct jffs2_sb_info *c) +{ + c->summary = kmalloc(sizeof(struct jffs2_summary), GFP_KERNEL); + + if (!c->summary) { + JFFS2_WARNING("Can't allocate memory for summary information!\n"); + return -ENOMEM; + } + + memset(c->summary, 0, sizeof(struct jffs2_summary)); + + c->summary->sum_buf = vmalloc(c->sector_size); + + if (!c->summary->sum_buf) { + JFFS2_WARNING("Can't allocate buffer for writing out summary information!\n"); + return -ENOMEM; + } + + JFFS2_DBG_SUMMARY("returned succesfully\n"); + + return 0; +} + +void jffs2_sum_exit(struct jffs2_sb_info *c) +{ + JFFS2_DBG_SUMMARY("called\n"); + + jffs2_sum_disable_collecting(c->summary); + + vfree(c->summary->sum_buf); + c->summary->sum_buf = NULL; + + kfree(c->summary); + c->summary = NULL; +} + +static int jffs2_sum_add_mem(struct jffs2_summary *s, union jffs2_sum_mem *item) +{ + if (!s->sum_list_head) + s->sum_list_head = (union jffs2_sum_mem *) item; + if (s->sum_list_tail) + s->sum_list_tail->u.next = (union jffs2_sum_mem *) item; + s->sum_list_tail = (union jffs2_sum_mem *) item; + + switch (je16_to_cpu(item->u.nodetype)) { + case JFFS2_NODETYPE_INODE: + s->sum_size += JFFS2_SUMMARY_INODE_SIZE; + s->sum_num++; + JFFS2_DBG_SUMMARY("inode (%u) added to summary\n", + je32_to_cpu(item->i.inode)); + break; + case JFFS2_NODETYPE_DIRENT: + s->sum_size += JFFS2_SUMMARY_DIRENT_SIZE(item->d.nsize); + s->sum_num++; + JFFS2_DBG_SUMMARY("dirent (%u) added to summary\n", + je32_to_cpu(item->d.ino)); + break; + default: + JFFS2_WARNING("UNKNOWN node type %u\n", + je16_to_cpu(item->u.nodetype)); + return 1; + } + return 0; +} + + +/* The following 3 functions are called from scan.c to collect summary info for not closed jeb */ + +int jffs2_sum_add_padding_mem(struct jffs2_summary *s, uint32_t size) +{ + JFFS2_DBG_SUMMARY("called with %u\n", size); + s->sum_padded += size; + return 0; +} + +int jffs2_sum_add_inode_mem(struct jffs2_summary *s, struct jffs2_raw_inode *ri, + uint32_t ofs) +{ + struct jffs2_sum_inode_mem *temp = kmalloc(sizeof(struct jffs2_sum_inode_mem), GFP_KERNEL); + + if (!temp) + return -ENOMEM; + + temp->nodetype = ri->nodetype; + temp->inode = ri->ino; + temp->version = ri->version; + temp->offset = cpu_to_je32(ofs); /* relative offset from the begining of the jeb */ + temp->totlen = ri->totlen; + temp->next = NULL; + + return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp); +} + +int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *rd, + uint32_t ofs) +{ + struct jffs2_sum_dirent_mem *temp = + kmalloc(sizeof(struct jffs2_sum_dirent_mem) + rd->nsize, GFP_KERNEL); + + if (!temp) + return -ENOMEM; + + temp->nodetype = rd->nodetype; + temp->totlen = rd->totlen; + temp->offset = cpu_to_je32(ofs); /* relative from the begining of the jeb */ + temp->pino = rd->pino; + temp->version = rd->version; + temp->ino = rd->ino; + temp->nsize = rd->nsize; + temp->type = rd->type; + temp->next = NULL; + + memcpy(temp->name, rd->name, rd->nsize); + + return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp); +} + +/* Cleanup every collected summary information */ + +static void jffs2_sum_clean_collected(struct jffs2_summary *s) +{ + union jffs2_sum_mem *temp; + + if (!s->sum_list_head) { + JFFS2_DBG_SUMMARY("already empty\n"); + } + while (s->sum_list_head) { + temp = s->sum_list_head; + s->sum_list_head = s->sum_list_head->u.next; + kfree(temp); + } + s->sum_list_tail = NULL; + s->sum_padded = 0; + s->sum_num = 0; +} + +void jffs2_sum_reset_collected(struct jffs2_summary *s) +{ + JFFS2_DBG_SUMMARY("called\n"); + jffs2_sum_clean_collected(s); + s->sum_size = 0; +} + +void jffs2_sum_disable_collecting(struct jffs2_summary *s) +{ + JFFS2_DBG_SUMMARY("called\n"); + jffs2_sum_clean_collected(s); + s->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; +} + +int jffs2_sum_is_disabled(struct jffs2_summary *s) +{ + return (s->sum_size == JFFS2_SUMMARY_NOSUM_SIZE); +} + +/* Move the collected summary information into sb (called from scan.c) */ + +void jffs2_sum_move_collected(struct jffs2_sb_info *c, struct jffs2_summary *s) +{ + JFFS2_DBG_SUMMARY("oldsize=0x%x oldnum=%u => newsize=0x%x newnum=%u\n", + c->summary->sum_size, c->summary->sum_num, + s->sum_size, s->sum_num); + + c->summary->sum_size = s->sum_size; + c->summary->sum_num = s->sum_num; + c->summary->sum_padded = s->sum_padded; + c->summary->sum_list_head = s->sum_list_head; + c->summary->sum_list_tail = s->sum_list_tail; + + s->sum_list_head = s->sum_list_tail = NULL; +} + +/* Called from wbuf.c to collect writed node info */ + +int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs, + unsigned long count, uint32_t ofs) +{ + union jffs2_node_union *node; + struct jffs2_eraseblock *jeb; + + node = invecs[0].iov_base; + jeb = &c->blocks[ofs / c->sector_size]; + ofs -= jeb->offset; + + switch (je16_to_cpu(node->u.nodetype)) { + case JFFS2_NODETYPE_INODE: { + struct jffs2_sum_inode_mem *temp = + kmalloc(sizeof(struct jffs2_sum_inode_mem), GFP_KERNEL); + + if (!temp) + goto no_mem; + + temp->nodetype = node->i.nodetype; + temp->inode = node->i.ino; + temp->version = node->i.version; + temp->offset = cpu_to_je32(ofs); + temp->totlen = node->i.totlen; + temp->next = NULL; + + return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp); + } + + case JFFS2_NODETYPE_DIRENT: { + struct jffs2_sum_dirent_mem *temp = + kmalloc(sizeof(struct jffs2_sum_dirent_mem) + node->d.nsize, GFP_KERNEL); + + if (!temp) + goto no_mem; + + temp->nodetype = node->d.nodetype; + temp->totlen = node->d.totlen; + temp->offset = cpu_to_je32(ofs); + temp->pino = node->d.pino; + temp->version = node->d.version; + temp->ino = node->d.ino; + temp->nsize = node->d.nsize; + temp->type = node->d.type; + temp->next = NULL; + + switch (count) { + case 1: + memcpy(temp->name,node->d.name,node->d.nsize); + break; + + case 2: + memcpy(temp->name,invecs[1].iov_base,node->d.nsize); + break; + + default: + BUG(); /* impossible count value */ + break; + } + + return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp); + } + + case JFFS2_NODETYPE_PADDING: + JFFS2_DBG_SUMMARY("node PADDING\n"); + c->summary->sum_padded += je32_to_cpu(node->u.totlen); + break; + + case JFFS2_NODETYPE_CLEANMARKER: + JFFS2_DBG_SUMMARY("node CLEANMARKER\n"); + break; + + case JFFS2_NODETYPE_SUMMARY: + JFFS2_DBG_SUMMARY("node SUMMARY\n"); + break; + + default: + /* If you implement a new node type you should also implement + summary support for it or disable summary. + */ + BUG(); + break; + } + + return 0; + +no_mem: + JFFS2_WARNING("MEMORY ALLOCATION ERROR!"); + return -ENOMEM; +} + + +/* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */ + +static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, + struct jffs2_summary_node *summary, uint32_t *pseudo_random) +{ + struct jffs2_raw_node_ref *raw; + struct jffs2_inode_cache *ic; + struct jffs2_full_dirent *fd; + void *sp; + int i, ino; + + sp = summary->sum; + + for (i=0; isum_num); i++) { + JFFS2_DBG_SUMMARY("processing summary index %d\n", i); + + switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) { + case JFFS2_NODETYPE_INODE: { + struct jffs2_sum_inode_flash *spi; + spi = sp; + + ino = je32_to_cpu(spi->inode); + + JFFS2_DBG_SUMMARY("Inode at 0x%08x\n", + jeb->offset + je32_to_cpu(spi->offset)); + + raw = jffs2_alloc_raw_node_ref(); + if (!raw) { + JFFS2_NOTICE("allocation of node reference failed\n"); + kfree(summary); + return -ENOMEM; + } + + ic = jffs2_scan_make_ino_cache(c, ino); + if (!ic) { + JFFS2_NOTICE("scan_make_ino_cache failed\n"); + jffs2_free_raw_node_ref(raw); + kfree(summary); + return -ENOMEM; + } + + raw->flash_offset = (jeb->offset + je32_to_cpu(spi->offset)) | REF_UNCHECKED; + raw->__totlen = PAD(je32_to_cpu(spi->totlen)); + raw->next_phys = NULL; + raw->next_in_ino = ic->nodes; + + ic->nodes = raw; + if (!jeb->first_node) + jeb->first_node = raw; + if (jeb->last_node) + jeb->last_node->next_phys = raw; + jeb->last_node = raw; + *pseudo_random += je32_to_cpu(spi->version); + + UNCHECKED_SPACE(PAD(je32_to_cpu(spi->totlen))); + + sp += JFFS2_SUMMARY_INODE_SIZE; + + break; + } + + case JFFS2_NODETYPE_DIRENT: { + struct jffs2_sum_dirent_flash *spd; + spd = sp; + + JFFS2_DBG_SUMMARY("Dirent at 0x%08x\n", + jeb->offset + je32_to_cpu(spd->offset)); + + fd = jffs2_alloc_full_dirent(spd->nsize+1); + if (!fd) { + kfree(summary); + return -ENOMEM; + } + + memcpy(&fd->name, spd->name, spd->nsize); + fd->name[spd->nsize] = 0; + + raw = jffs2_alloc_raw_node_ref(); + if (!raw) { + jffs2_free_full_dirent(fd); + JFFS2_NOTICE("allocation of node reference failed\n"); + kfree(summary); + return -ENOMEM; + } + + ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(spd->pino)); + if (!ic) { + jffs2_free_full_dirent(fd); + jffs2_free_raw_node_ref(raw); + kfree(summary); + return -ENOMEM; + } + + raw->__totlen = PAD(je32_to_cpu(spd->totlen)); + raw->flash_offset = (jeb->offset + je32_to_cpu(spd->offset)) | REF_PRISTINE; + raw->next_phys = NULL; + raw->next_in_ino = ic->nodes; + ic->nodes = raw; + if (!jeb->first_node) + jeb->first_node = raw; + if (jeb->last_node) + jeb->last_node->next_phys = raw; + jeb->last_node = raw; + + fd->raw = raw; + fd->next = NULL; + fd->version = je32_to_cpu(spd->version); + fd->ino = je32_to_cpu(spd->ino); + fd->nhash = full_name_hash(fd->name, spd->nsize); + fd->type = spd->type; + USED_SPACE(PAD(je32_to_cpu(spd->totlen))); + jffs2_add_fd_to_list(c, fd, &ic->scan_dents); + + *pseudo_random += je32_to_cpu(spd->version); + + sp += JFFS2_SUMMARY_DIRENT_SIZE(spd->nsize); + + break; + } + + default : { + JFFS2_WARNING("Unsupported node type found in summary! Exiting..."); + kfree(summary); + return -EIO; + } + } + } + + kfree(summary); + return 0; +} + +/* Process the summary node - called from jffs2_scan_eraseblock() */ + +int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, + uint32_t ofs, uint32_t *pseudo_random) +{ + struct jffs2_unknown_node crcnode; + struct jffs2_raw_node_ref *cache_ref; + struct jffs2_summary_node *summary; + int ret, sumsize; + uint32_t crc; + + sumsize = c->sector_size - ofs; + ofs += jeb->offset; + + JFFS2_DBG_SUMMARY("summary found for 0x%08x at 0x%08x (0x%x bytes)\n", + jeb->offset, ofs, sumsize); + + summary = kmalloc(sumsize, GFP_KERNEL); + + if (!summary) { + return -ENOMEM; + } + + ret = jffs2_fill_scan_buf(c, (unsigned char *)summary, ofs, sumsize); + + if (ret) { + kfree(summary); + return ret; + } + + /* OK, now check for node validity and CRC */ + crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + crcnode.nodetype = cpu_to_je16(JFFS2_NODETYPE_SUMMARY); + crcnode.totlen = summary->totlen; + crc = crc32(0, &crcnode, sizeof(crcnode)-4); + + if (je32_to_cpu(summary->hdr_crc) != crc) { + JFFS2_DBG_SUMMARY("Summary node header is corrupt (bad CRC or " + "no summary at all)\n"); + goto crc_err; + } + + if (je32_to_cpu(summary->totlen) != sumsize) { + JFFS2_DBG_SUMMARY("Summary node is corrupt (wrong erasesize?)\n"); + goto crc_err; + } + + crc = crc32(0, summary, sizeof(struct jffs2_summary_node)-8); + + if (je32_to_cpu(summary->node_crc) != crc) { + JFFS2_DBG_SUMMARY("Summary node is corrupt (bad CRC)\n"); + goto crc_err; + } + + crc = crc32(0, summary->sum, sumsize - sizeof(struct jffs2_summary_node)); + + if (je32_to_cpu(summary->sum_crc) != crc) { + JFFS2_DBG_SUMMARY("Summary node data is corrupt (bad CRC)\n"); + goto crc_err; + } + + if ( je32_to_cpu(summary->cln_mkr) ) { + + JFFS2_DBG_SUMMARY("Summary : CLEANMARKER node \n"); + + if (je32_to_cpu(summary->cln_mkr) != c->cleanmarker_size) { + JFFS2_DBG_SUMMARY("CLEANMARKER node has totlen 0x%x != normal 0x%x\n", + je32_to_cpu(summary->cln_mkr), c->cleanmarker_size); + UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr))); + } else if (jeb->first_node) { + JFFS2_DBG_SUMMARY("CLEANMARKER node not first node in block " + "(0x%08x)\n", jeb->offset); + UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr))); + } else { + struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref(); + + if (!marker_ref) { + JFFS2_NOTICE("Failed to allocate node ref for clean marker\n"); + kfree(summary); + return -ENOMEM; + } + + marker_ref->next_in_ino = NULL; + marker_ref->next_phys = NULL; + marker_ref->flash_offset = jeb->offset | REF_NORMAL; + marker_ref->__totlen = je32_to_cpu(summary->cln_mkr); + jeb->first_node = jeb->last_node = marker_ref; + + USED_SPACE( PAD(je32_to_cpu(summary->cln_mkr)) ); + } + } + + if (je32_to_cpu(summary->padded)) { + DIRTY_SPACE(je32_to_cpu(summary->padded)); + } + + ret = jffs2_sum_process_sum_data(c, jeb, summary, pseudo_random); + if (ret) + return ret; + + /* for PARANOIA_CHECK */ + cache_ref = jffs2_alloc_raw_node_ref(); + + if (!cache_ref) { + JFFS2_NOTICE("Failed to allocate node ref for cache\n"); + return -ENOMEM; + } + + cache_ref->next_in_ino = NULL; + cache_ref->next_phys = NULL; + cache_ref->flash_offset = ofs | REF_NORMAL; + cache_ref->__totlen = sumsize; + + if (!jeb->first_node) + jeb->first_node = cache_ref; + if (jeb->last_node) + jeb->last_node->next_phys = cache_ref; + jeb->last_node = cache_ref; + + USED_SPACE(sumsize); + + jeb->wasted_size += jeb->free_size; + c->wasted_size += jeb->free_size; + c->free_size -= jeb->free_size; + jeb->free_size = 0; + + return jffs2_scan_classify_jeb(c, jeb); + +crc_err: + JFFS2_WARNING("Summary node crc error, skipping summary information.\n"); + + return 0; +} + +/* Write summary data to flash - helper function for jffs2_sum_write_sumnode() */ + +static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, + uint32_t infosize, uint32_t datasize, int padsize) +{ + struct jffs2_summary_node isum; + union jffs2_sum_mem *temp; + struct jffs2_sum_marker *sm; + struct kvec vecs[2]; + void *wpage; + int ret; + size_t retlen; + + memset(c->summary->sum_buf, 0xff, datasize); + memset(&isum, 0, sizeof(isum)); + + isum.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); + isum.nodetype = cpu_to_je16(JFFS2_NODETYPE_SUMMARY); + isum.totlen = cpu_to_je32(infosize); + isum.hdr_crc = cpu_to_je32(crc32(0, &isum, sizeof(struct jffs2_unknown_node) - 4)); + isum.padded = cpu_to_je32(c->summary->sum_padded); + isum.cln_mkr = cpu_to_je32(c->cleanmarker_size); + isum.sum_num = cpu_to_je32(c->summary->sum_num); + wpage = c->summary->sum_buf; + + while (c->summary->sum_num) { + + switch (je16_to_cpu(c->summary->sum_list_head->u.nodetype)) { + case JFFS2_NODETYPE_INODE: { + struct jffs2_sum_inode_flash *sino_ptr = wpage; + + sino_ptr->nodetype = c->summary->sum_list_head->i.nodetype; + sino_ptr->inode = c->summary->sum_list_head->i.inode; + sino_ptr->version = c->summary->sum_list_head->i.version; + sino_ptr->offset = c->summary->sum_list_head->i.offset; + sino_ptr->totlen = c->summary->sum_list_head->i.totlen; + + wpage += JFFS2_SUMMARY_INODE_SIZE; + + break; + } + + case JFFS2_NODETYPE_DIRENT: { + struct jffs2_sum_dirent_flash *sdrnt_ptr = wpage; + + sdrnt_ptr->nodetype = c->summary->sum_list_head->d.nodetype; + sdrnt_ptr->totlen = c->summary->sum_list_head->d.totlen; + sdrnt_ptr->offset = c->summary->sum_list_head->d.offset; + sdrnt_ptr->pino = c->summary->sum_list_head->d.pino; + sdrnt_ptr->version = c->summary->sum_list_head->d.version; + sdrnt_ptr->ino = c->summary->sum_list_head->d.ino; + sdrnt_ptr->nsize = c->summary->sum_list_head->d.nsize; + sdrnt_ptr->type = c->summary->sum_list_head->d.type; + + memcpy(sdrnt_ptr->name, c->summary->sum_list_head->d.name, + c->summary->sum_list_head->d.nsize); + + wpage += JFFS2_SUMMARY_DIRENT_SIZE(c->summary->sum_list_head->d.nsize); + + break; + } + + default : { + BUG(); /* unknown node in summary information */ + } + } + + temp = c->summary->sum_list_head; + c->summary->sum_list_head = c->summary->sum_list_head->u.next; + kfree(temp); + + c->summary->sum_num--; + } + + jffs2_sum_reset_collected(c->summary); + + wpage += padsize; + + sm = wpage; + sm->offset = cpu_to_je32(c->sector_size - jeb->free_size); + sm->magic = cpu_to_je32(JFFS2_SUM_MAGIC); + + isum.sum_crc = cpu_to_je32(crc32(0, c->summary->sum_buf, datasize)); + isum.node_crc = cpu_to_je32(crc32(0, &isum, sizeof(isum) - 8)); + + vecs[0].iov_base = &isum; + vecs[0].iov_len = sizeof(isum); + vecs[1].iov_base = c->summary->sum_buf; + vecs[1].iov_len = datasize; + + JFFS2_DBG_SUMMARY("JFFS2: writing out data to flash to pos : 0x%08x\n", + jeb->offset + c->sector_size - jeb->free_size); + + spin_unlock(&c->erase_completion_lock); + ret = jffs2_flash_writev(c, vecs, 2, jeb->offset + c->sector_size - + jeb->free_size, &retlen, 0); + spin_lock(&c->erase_completion_lock); + + + if (ret || (retlen != infosize)) { + JFFS2_WARNING("Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", + infosize, jeb->offset + c->sector_size - jeb->free_size, ret, retlen); + + c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; + WASTED_SPACE(infosize); + + return 1; + } + + return 0; +} + +/* Write out summary information - called from jffs2_do_reserve_space */ + +int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) +{ + struct jffs2_raw_node_ref *summary_ref; + int datasize, infosize, padsize, ret; + struct jffs2_eraseblock *jeb; + + JFFS2_DBG_SUMMARY("called\n"); + + jeb = c->nextblock; + + if (!c->summary->sum_num || !c->summary->sum_list_head) { + JFFS2_WARNING("Empty summary info!!!\n"); + BUG(); + } + + datasize = c->summary->sum_size + sizeof(struct jffs2_sum_marker); + infosize = sizeof(struct jffs2_summary_node) + datasize; + padsize = jeb->free_size - infosize; + infosize += padsize; + datasize += padsize; + + /* Is there enough space for summary? */ + if (padsize < 0) { + /* don't try to write out summary for this jeb */ + jffs2_sum_disable_collecting(c->summary); + + JFFS2_WARNING("Not enough space for summary, padsize = %d\n", padsize); + return 0; + } + + ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize); + if (ret) + return 0; /* can't write out summary, block is marked as NOSUM_SIZE */ + + /* for ACCT_PARANOIA_CHECK */ + spin_unlock(&c->erase_completion_lock); + summary_ref = jffs2_alloc_raw_node_ref(); + spin_lock(&c->erase_completion_lock); + + if (!summary_ref) { + JFFS2_NOTICE("Failed to allocate node ref for summary\n"); + return -ENOMEM; + } + + summary_ref->next_in_ino = NULL; + summary_ref->next_phys = NULL; + summary_ref->flash_offset = (jeb->offset + c->sector_size - jeb->free_size) | REF_NORMAL; + summary_ref->__totlen = infosize; + + if (!jeb->first_node) + jeb->first_node = summary_ref; + if (jeb->last_node) + jeb->last_node->next_phys = summary_ref; + jeb->last_node = summary_ref; + + USED_SPACE(infosize); + + return 0; +} diff --git a/fs/jffs2/summary.h b/fs/jffs2/summary.h new file mode 100644 index 000000000000..e6b0a69acbd4 --- /dev/null +++ b/fs/jffs2/summary.h @@ -0,0 +1,183 @@ +/* + * JFFS2 -- Journalling Flash File System, Version 2. + * + * Copyright (C) 2004 Ferenc Havasi , + * Zoltan Sogor , + * Patrik Kluba , + * University of Szeged, Hungary + * + * For licensing information, see the file 'LICENCE' in this directory. + * + * $Id: summary.h,v 1.1 2005/09/07 08:34:54 havasi Exp $ + * + */ + +#ifndef JFFS2_SUMMARY_H +#define JFFS2_SUMMARY_H + +#include +#include + +#define DIRTY_SPACE(x) do { typeof(x) _x = (x); \ + c->free_size -= _x; c->dirty_size += _x; \ + jeb->free_size -= _x ; jeb->dirty_size += _x; \ + }while(0) +#define USED_SPACE(x) do { typeof(x) _x = (x); \ + c->free_size -= _x; c->used_size += _x; \ + jeb->free_size -= _x ; jeb->used_size += _x; \ + }while(0) +#define WASTED_SPACE(x) do { typeof(x) _x = (x); \ + c->free_size -= _x; c->wasted_size += _x; \ + jeb->free_size -= _x ; jeb->wasted_size += _x; \ + }while(0) +#define UNCHECKED_SPACE(x) do { typeof(x) _x = (x); \ + c->free_size -= _x; c->unchecked_size += _x; \ + jeb->free_size -= _x ; jeb->unchecked_size += _x; \ + }while(0) + +#define BLK_STATE_ALLFF 0 +#define BLK_STATE_CLEAN 1 +#define BLK_STATE_PARTDIRTY 2 +#define BLK_STATE_CLEANMARKER 3 +#define BLK_STATE_ALLDIRTY 4 +#define BLK_STATE_BADBLOCK 5 + +#define JFFS2_SUMMARY_NOSUM_SIZE 0xffffffff +#define JFFS2_SUMMARY_INODE_SIZE (sizeof(struct jffs2_sum_inode_flash)) +#define JFFS2_SUMMARY_DIRENT_SIZE(x) (sizeof(struct jffs2_sum_dirent_flash) + (x)) + +/* Summary structures used on flash */ + +struct jffs2_sum_unknown_flash +{ + jint16_t nodetype; /* node type */ +}; + +struct jffs2_sum_inode_flash +{ + jint16_t nodetype; /* node type */ + jint32_t inode; /* inode number */ + jint32_t version; /* inode version */ + jint32_t offset; /* offset on jeb */ + jint32_t totlen; /* record length */ +} __attribute__((packed)); + +struct jffs2_sum_dirent_flash +{ + jint16_t nodetype; /* == JFFS_NODETYPE_DIRENT */ + jint32_t totlen; /* record length */ + jint32_t offset; /* offset on jeb */ + jint32_t pino; /* parent inode */ + jint32_t version; /* dirent version */ + jint32_t ino; /* == zero for unlink */ + uint8_t nsize; /* dirent name size */ + uint8_t type; /* dirent type */ + uint8_t name[0]; /* dirent name */ +} __attribute__((packed)); + +union jffs2_sum_flash +{ + struct jffs2_sum_unknown_flash u; + struct jffs2_sum_inode_flash i; + struct jffs2_sum_dirent_flash d; +}; + +/* Summary structures used in the memory */ + +struct jffs2_sum_unknown_mem +{ + union jffs2_sum_mem *next; + jint16_t nodetype; /* node type */ +}; + +struct jffs2_sum_inode_mem +{ + union jffs2_sum_mem *next; + jint16_t nodetype; /* node type */ + jint32_t inode; /* inode number */ + jint32_t version; /* inode version */ + jint32_t offset; /* offset on jeb */ + jint32_t totlen; /* record length */ +} __attribute__((packed)); + +struct jffs2_sum_dirent_mem +{ + union jffs2_sum_mem *next; + jint16_t nodetype; /* == JFFS_NODETYPE_DIRENT */ + jint32_t totlen; /* record length */ + jint32_t offset; /* ofset on jeb */ + jint32_t pino; /* parent inode */ + jint32_t version; /* dirent version */ + jint32_t ino; /* == zero for unlink */ + uint8_t nsize; /* dirent name size */ + uint8_t type; /* dirent type */ + uint8_t name[0]; /* dirent name */ +} __attribute__((packed)); + +union jffs2_sum_mem +{ + struct jffs2_sum_unknown_mem u; + struct jffs2_sum_inode_mem i; + struct jffs2_sum_dirent_mem d; +}; + +/* Summary related information stored in superblock */ + +struct jffs2_summary +{ + uint32_t sum_size; /* collected summary information for nextblock */ + uint32_t sum_num; + uint32_t sum_padded; + union jffs2_sum_mem *sum_list_head; + union jffs2_sum_mem *sum_list_tail; + + jint32_t *sum_buf; /* buffer for writing out summary */ +}; + +/* Summary marker is stored at the end of every sumarized erase block */ + +struct jffs2_sum_marker +{ + jint32_t offset; /* offset of the summary node in the jeb */ + jint32_t magic; /* == JFFS2_SUM_MAGIC */ +}; + +#define JFFS2_SUMMARY_FRAME_SIZE (sizeof(struct jffs2_summary_node) + sizeof(struct jffs2_sum_marker)) + +#ifdef CONFIG_JFFS2_SUMMARY /* SUMMARY SUPPORT ENABLED */ + +#define jffs2_sum_active() (1) +int jffs2_sum_init(struct jffs2_sb_info *c); +void jffs2_sum_exit(struct jffs2_sb_info *c); +void jffs2_sum_disable_collecting(struct jffs2_summary *s); +int jffs2_sum_is_disabled(struct jffs2_summary *s); +void jffs2_sum_reset_collected(struct jffs2_summary *s); +void jffs2_sum_move_collected(struct jffs2_sb_info *c, struct jffs2_summary *s); +int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs, + unsigned long count, uint32_t to); +int jffs2_sum_write_sumnode(struct jffs2_sb_info *c); +int jffs2_sum_add_padding_mem(struct jffs2_summary *s, uint32_t size); +int jffs2_sum_add_inode_mem(struct jffs2_summary *s, struct jffs2_raw_inode *ri, uint32_t ofs); +int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *rd, uint32_t ofs); +int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, + uint32_t ofs, uint32_t *pseudo_random); + +#else /* SUMMARY DISABLED */ + +#define jffs2_sum_active() (0) +#define jffs2_sum_init(a) (0) +#define jffs2_sum_exit(a) +#define jffs2_sum_disable_collecting(a) +#define jffs2_sum_is_disabled(a) (0) +#define jffs2_sum_reset_collected(a) +#define jffs2_sum_add_kvec(a,b,c,d) (0) +#define jffs2_sum_move_collected(a,b) +#define jffs2_sum_write_sumnode(a) (0) +#define jffs2_sum_add_padding_mem(a,b) +#define jffs2_sum_add_inode_mem(a,b,c) +#define jffs2_sum_add_dirent_mem(a,b,c) +#define jffs2_sum_scan_sumnode(a,b,c,d) (0) + +#endif /* CONFIG_JFFS2_SUMMARY */ + +#endif /* JFFS2_SUMMARY_H */ diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 58496a03a1d2..99028af3f69e 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: super.c,v 1.108 2005/08/31 13:51:00 havasi Exp $ + * $Id: super.c,v 1.109 2005/09/07 08:34:55 havasi Exp $ * */ @@ -282,6 +282,9 @@ static void jffs2_put_super (struct super_block *sb) down(&c->alloc_sem); jffs2_flush_wbuf_pad(c); up(&c->alloc_sem); + + jffs2_sum_exit(c); + jffs2_free_ino_caches(c); jffs2_free_raw_node_refs(c); if (jffs2_blocks_use_vmalloc(c)) @@ -320,6 +323,9 @@ static int __init init_jffs2_fs(void) printk(KERN_INFO "JFFS2 version 2.2." #ifdef CONFIG_JFFS2_FS_WRITEBUFFER " (NAND)" +#endif +#ifdef CONFIG_JFFS2_SUMMARY + " (SUMMARY) " #endif " (C) 2001-2003 Red Hat, Inc.\n"); diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 8c06d3a2b17d..86860dbc670c 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -9,7 +9,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: wbuf.c,v 1.97 2005/08/06 04:51:30 nico Exp $ + * $Id: wbuf.c,v 1.98 2005/09/07 08:34:55 havasi Exp $ * */ @@ -265,7 +265,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) /* ... and get an allocation of space from a shiny new block instead */ - ret = jffs2_reserve_space_gc(c, end-start, &ofs, &len); + ret = jffs2_reserve_space_gc(c, end-start, &ofs, &len, JFFS2_SUMMARY_NOSUM_SIZE); if (ret) { printk(KERN_WARNING "Failed to allocate space for wbuf recovery. Data loss ensues.\n"); kfree(buf); @@ -836,6 +836,12 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig alldone: *retlen = donelen; + if (jffs2_sum_active()) { + int res = jffs2_sum_add_kvec(c, invecs, count, (uint32_t) to); + if (res) + return res; + } + if (c->wbuf_len && ino) jffs2_wbuf_dirties_inode(c, ino); @@ -855,7 +861,7 @@ int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *r struct kvec vecs[1]; if (!jffs2_is_writebuffered(c)) - return c->mtd->write(c->mtd, ofs, len, retlen, buf); + return jffs2_flash_direct_write(c, ofs, len, retlen, buf); vecs[0].iov_base = (unsigned char *) buf; vecs[0].iov_len = len; diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index 0a194759bbbd..ea411518d801 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: write.c,v 1.95 2005/08/17 13:46:23 dedekind Exp $ + * $Id: write.c,v 1.96 2005/09/07 08:34:55 havasi Exp $ * */ @@ -153,13 +153,15 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 jffs2_dbg_acct_paranoia_check(c, jeb); if (alloc_mode == ALLOC_GC) { - ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &flash_ofs, &dummy); + ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &flash_ofs, + &dummy, JFFS2_SUMMARY_INODE_SIZE); } else { /* Locking pain */ up(&f->sem); jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &flash_ofs, &dummy, alloc_mode); + ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &flash_ofs, + &dummy, alloc_mode, JFFS2_SUMMARY_INODE_SIZE); down(&f->sem); } @@ -299,13 +301,15 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff jffs2_dbg_acct_paranoia_check(c, jeb); if (alloc_mode == ALLOC_GC) { - ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &flash_ofs, &dummy); + ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &flash_ofs, + &dummy, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); } else { /* Locking pain */ up(&f->sem); jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &flash_ofs, &dummy, alloc_mode); + ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &flash_ofs, + &dummy, alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); down(&f->sem); } @@ -362,7 +366,8 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, retry: D2(printk(KERN_DEBUG "jffs2_commit_write() loop: 0x%x to write to 0x%x\n", writelen, offset)); - ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, + &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); if (ret) { D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret)); break; @@ -449,7 +454,8 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str /* Try to reserve enough space for both node and dirent. * Just the node will do for now, though */ - ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL, + JFFS2_SUMMARY_INODE_SIZE); D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen)); if (ret) { up(&f->sem); @@ -478,7 +484,8 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str up(&f->sem); jffs2_complete_reservation(c); - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); if (ret) { /* Eep. */ @@ -549,7 +556,8 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, if (!rd) return -ENOMEM; - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_DELETION); + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, + ALLOC_DELETION, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); if (ret) { jffs2_free_raw_dirent(rd); return ret; @@ -658,7 +666,8 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint if (!rd) return -ENOMEM; - ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL); + ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, + ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); if (ret) { jffs2_free_raw_dirent(rd); return ret; diff --git a/fs/jffs2/writev.c b/fs/jffs2/writev.c index f079f8388566..6d8c27c5e723 100644 --- a/fs/jffs2/writev.c +++ b/fs/jffs2/writev.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: writev.c,v 1.6 2004/11/16 20:36:12 dwmw2 Exp $ + * $Id: writev.c,v 1.7 2005/09/07 08:34:55 havasi Exp $ * */ @@ -44,7 +44,37 @@ int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs, { if (c->mtd->writev) return c->mtd->writev(c->mtd, vecs, count, to, retlen); - else + else { + if (jffs2_sum_active()) { + int res; + + res = jffs2_sum_add_kvec(c, vecs, count, (uint32_t) to); + if (res) { + return res; + } + } + return mtd_fake_writev(c->mtd, vecs, count, to, retlen); + } } +int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, + size_t *retlen, const u_char *buf) +{ + int ret; + ret = c->mtd->write(c->mtd, ofs, len, retlen, buf); + + if (jffs2_sum_active()) { + struct kvec vecs[1]; + int res; + + vecs[0].iov_base = (unsigned char *) buf; + vecs[0].iov_len = len; + + res = jffs2_sum_add_kvec(c, vecs, 1, (uint32_t) ofs); + if (res) { + return res; + } + } + return ret; +} diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h index a66d0a8b70e4..acb51a3669a2 100644 --- a/include/linux/jffs2.h +++ b/include/linux/jffs2.h @@ -8,7 +8,7 @@ * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * - * $Id: jffs2.h,v 1.36 2005/07/26 13:19:36 havasi Exp $ + * $Id: jffs2.h,v 1.37 2005/09/07 08:34:55 havasi Exp $ * */ @@ -28,6 +28,9 @@ #define JFFS2_EMPTY_BITMASK 0xffff #define JFFS2_DIRTY_BITMASK 0x0000 +/* Summary node MAGIC marker */ +#define JFFS2_SUM_MAGIC 0x02851885 + /* We only allow a single char for length, and 0xFF is empty flash so we don't want it confused with a real length. Hence max 254. */ @@ -60,6 +63,8 @@ #define JFFS2_NODETYPE_CLEANMARKER (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3) #define JFFS2_NODETYPE_PADDING (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 4) +#define JFFS2_NODETYPE_SUMMARY (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 6) + // Maybe later... //#define JFFS2_NODETYPE_CHECKPOINT (JFFS2_FEATURE_RWCOMPAT_DELETE | JFFS2_NODE_ACCURATE | 3) //#define JFFS2_NODETYPE_OPTIONS (JFFS2_FEATURE_RWCOMPAT_COPY | JFFS2_NODE_ACCURATE | 4) @@ -146,10 +151,24 @@ struct jffs2_raw_inode uint8_t data[0]; } __attribute__((packed)); +struct jffs2_summary_node{ + jint16_t magic; + jint16_t nodetype; /* = JFFS2_NODETYPE_INODE_SUM */ + jint32_t totlen; + jint32_t hdr_crc; + jint32_t sum_num; /* number of sum entries*/ + jint32_t cln_mkr; /* clean marker size, 0 = no cleanmarker */ + jint32_t padded; /* sum of the size of padding nodes */ + jint32_t sum_crc; /* summary information crc */ + jint32_t node_crc; /* node crc */ + jint32_t sum[0]; /* inode summary info */ +} __attribute__((packed)); + union jffs2_node_union { struct jffs2_raw_inode i; struct jffs2_raw_dirent d; struct jffs2_unknown_node u; + struct jffs2_summary_node s; }; #endif /* __LINUX_JFFS2_H__ */ diff --git a/include/linux/jffs2_fs_sb.h b/include/linux/jffs2_fs_sb.h index 1e21546622de..5087612ed9ac 100644 --- a/include/linux/jffs2_fs_sb.h +++ b/include/linux/jffs2_fs_sb.h @@ -1,4 +1,4 @@ -/* $Id: jffs2_fs_sb.h,v 1.52 2005/05/19 16:12:17 gleixner Exp $ */ +/* $Id: jffs2_fs_sb.h,v 1.53 2005/09/07 08:34:56 havasi Exp $ */ #ifndef _JFFS2_FS_SB #define _JFFS2_FS_SB @@ -112,6 +112,8 @@ struct jffs2_sb_info { uint32_t fsdata_len; #endif + struct jffs2_summary *summary; /* Summary information */ + /* OS-private pointer for getting back to master superblock info */ void *os_priv; }; -- cgit v1.2.3 From 962034f43937d02a1c18e802a6641aed0a266ac5 Mon Sep 17 00:00:00 2001 From: Vitaly Wool Date: Thu, 15 Sep 2005 14:58:53 +0100 Subject: [MTD] NAND: Add suspend/resume functionality The changes introduced allow to suspend/resume NAND flash. A new state (FL_PM_SUSPENDED) is introduced, as well as routines for mtd->suspend and mtd->resume to put the flash in suspended state from software pov. Signed-off-by: Vitaly Wool Signed-off-by: Thomas Gleixner --- drivers/mtd/nand/nand_base.c | 46 ++++++++++++++++++++++++++++++++++++++------ include/linux/mtd/nand.h | 3 ++- 2 files changed, 42 insertions(+), 7 deletions(-) (limited to 'include/linux') diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index cdf108619344..4e22317397e8 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -46,6 +46,8 @@ * perform extra error status checks on erase and write failures. This required * adding a wrapper function for nand_read_ecc. * + * 08-20-2005 vwool: suspend/resume added + * * Credits: * David Woodhouse for adding multichip support * @@ -59,7 +61,7 @@ * The AG-AND chips have nice features for speed improvement, * which are not supported yet. Read / program 4 pages in one go. * - * $Id: nand_base.c,v 1.148 2005/08/04 17:14:48 gleixner Exp $ + * $Id: nand_base.c,v 1.150 2005/09/15 13:58:48 vwool Exp $ * * 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 @@ -153,7 +155,7 @@ static int nand_verify_pages (struct mtd_info *mtd, struct nand_chip *this, int #define nand_verify_pages(...) (0) #endif -static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state); +static int nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state); /** * nand_release_device - [GENERIC] release chip @@ -756,7 +758,7 @@ static void nand_command_lp (struct mtd_info *mtd, unsigned command, int column, * * Get the device and lock it for exclusive access */ -static void nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state) +static int nand_get_device (struct nand_chip *this, struct mtd_info *mtd, int new_state) { struct nand_chip *active; spinlock_t *lock; @@ -779,7 +781,11 @@ retry: if (active == this && this->state == FL_READY) { this->state = new_state; spin_unlock(lock); - return; + return 0; + } + if (new_state == FL_PM_SUSPENDED) { + spin_unlock(lock); + return (this->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN; } set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(wq, &wait); @@ -2284,6 +2290,34 @@ static int nand_block_markbad (struct mtd_info *mtd, loff_t ofs) return this->block_markbad(mtd, ofs); } +/** + * nand_suspend - [MTD Interface] Suspend the NAND flash + * @mtd: MTD device structure + */ +static int nand_suspend(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + + return nand_get_device (this, mtd, FL_PM_SUSPENDED); +} + +/** + * nand_resume - [MTD Interface] Resume the NAND flash + * @mtd: MTD device structure + */ +static void nand_resume(struct mtd_info *mtd) +{ + struct nand_chip *this = mtd->priv; + + if (this->state == FL_PM_SUSPENDED) + nand_release_device(mtd); + else + printk(KERN_ERR "resume() called for the chip which is not " + "in suspended state\n"); + +} + + /** * nand_scan - [NAND Interface] Scan for the NAND device * @mtd: MTD device structure @@ -2643,8 +2677,8 @@ int nand_scan (struct mtd_info *mtd, int maxchips) mtd->sync = nand_sync; mtd->lock = NULL; mtd->unlock = NULL; - mtd->suspend = NULL; - mtd->resume = NULL; + mtd->suspend = nand_suspend; + mtd->resume = nand_resume; mtd->block_isbad = nand_block_isbad; mtd->block_markbad = nand_block_markbad; diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 9b5b76217584..2d36413b2f94 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -5,7 +5,7 @@ * Steven J. Hill * Thomas Gleixner * - * $Id: nand.h,v 1.73 2005/05/31 19:39:17 gleixner Exp $ + * $Id: nand.h,v 1.74 2005/09/15 13:58:50 vwool Exp $ * * 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 @@ -244,6 +244,7 @@ typedef enum { FL_ERASING, FL_SYNCING, FL_CACHEDPRG, + FL_PM_SUSPENDED, } nand_state_t; /* Keep gcc happy */ -- cgit v1.2.3 From 733802d974e5af42acb7cd61b16c0ce6dd03b7ed Mon Sep 17 00:00:00 2001 From: "Artem B. Bityutskiy" Date: Thu, 22 Sep 2005 12:25:00 +0100 Subject: [JFFS2] Debug code simplification, update TODO Simplify the debugging code further. Update the TODO list Signed-off-by: Artem B. Bityutskiy Signed-off-by: Thomas Gleixner --- fs/jffs2/TODO | 38 +++++++-------- fs/jffs2/build.c | 112 +++++++++++++++++++++----------------------- fs/jffs2/debug.c | 3 +- fs/jffs2/debug.h | 50 +++++++++++++------- fs/jffs2/erase.c | 2 +- fs/jffs2/malloc.c | 34 +++++++------- fs/jffs2/nodelist.c | 107 ++++++++++++++++++++++-------------------- fs/jffs2/nodemgmt.c | 6 +-- fs/jffs2/os-linux.h | 6 +-- fs/jffs2/readinode.c | 32 ++++++------- fs/jffs2/scan.c | 48 ++----------------- fs/jffs2/summary.c | 53 +++++++++++---------- fs/jffs2/wbuf.c | 5 +- include/linux/jffs2_fs_sb.h | 5 +- 14 files changed, 235 insertions(+), 266 deletions(-) (limited to 'include/linux') diff --git a/fs/jffs2/TODO b/fs/jffs2/TODO index 2bff82fd221f..d0e23b26fa50 100644 --- a/fs/jffs2/TODO +++ b/fs/jffs2/TODO @@ -1,5 +1,11 @@ -$Id: TODO,v 1.10 2002/09/09 16:31:21 dwmw2 Exp $ +$Id: TODO,v 1.18 2005/09/22 11:24:56 dedekind Exp $ + - support asynchronous operation -- add a per-fs 'reserved_space' count, + let each outstanding write reserve the _maximum_ amount of physical + space it could take. Let GC flush the outstanding writes because the + reservations will necessarily be pessimistic. With this we could even + do shared writable mmap, if we can have a fs hook for do_wp_page() to + make the reservation. - disable compression in commit_write()? - fine-tune the allocation / GC thresholds - chattr support - turning on/off and tuning compression per-inode @@ -11,26 +17,15 @@ $Id: TODO,v 1.10 2002/09/09 16:31:21 dwmw2 Exp $ - test, test, test - NAND flash support: - - flush_wbuf using GC to fill it, don't just pad. - - Deal with write errors. Data don't get lost - we just have to write - the affected node(s) out again somewhere else. - - make fsync flush only if actually required - - make sys_sync() work. - - reboot notifier - - timed flush of old wbuf - - fix magical second arg of jffs2_flush_wbuf(). Split into two or more functions instead. - + - almost done :) + - use bad block check instead of the hardwired byte check - Optimisations: - - Stop GC from decompressing and immediately recompressing nodes which could - just be copied intact. (We now keep track of REF_PRISTINE flag. Easy now.) - - Furthermore, in the case where it could be copied intact we don't even need - to call iget() for it -- if we use (raw_node_raw->flash_offset & 2) as a flag - to show a node can be copied intact and it's _not_ in icache, we could just do - it, fix up the next_in_ino list and move on. We would need a way to find out - _whether_ it's in icache though -- if it's in icache we also need to do the - fragment lists, etc. P'raps a flag or pointer in the jffs2_inode_cache could - help. (We have half of this now.) + - Split writes so they go to two separate blocks rather than just c->nextblock. + By writing _new_ nodes to one block, and garbage-collected REF_PRISTINE + nodes to a different one, we can separate clean nodes from those which + are likely to become dirty, and end up with blocks which are each far + closer to 100% or 0% clean, hence speeding up later GC progress dramatically. - Stop keeping name in-core with struct jffs2_full_dirent. If we keep the hash in the full dirent, we only need to go to the flash in lookup() when we think we've got a match, and in readdir(). @@ -38,3 +33,8 @@ $Id: TODO,v 1.10 2002/09/09 16:31:21 dwmw2 Exp $ - Remove totlen from jffs2_raw_node_ref? Need to have totlen passed into jffs2_mark_node_obsolete(). Can all callers work it out? - Remove size from jffs2_raw_node_frag. + +dedekind: +1. __jffs2_flush_wbuf() has a strange 'pad' parameter. Eliminate. +2. get_sb()->build_fs()->scan() path... Why get_sb() removes scan()'s crap in + case of failure? scan() does not clean everything. Fix. diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index f2cf562ebd2a..ac393b3d6ea3 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: build.c,v 1.79 2005/09/07 11:21:57 havasi Exp $ + * $Id: build.c,v 1.83 2005/09/21 15:52:33 dedekind Exp $ * */ @@ -18,7 +18,8 @@ #include #include "nodelist.h" -static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *, struct jffs2_inode_cache *, struct jffs2_full_dirent **); +static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *, + struct jffs2_inode_cache *, struct jffs2_full_dirent **); static inline struct jffs2_inode_cache * first_inode_chain(int *i, struct jffs2_sb_info *c) @@ -46,11 +47,12 @@ next_inode(int *i, struct jffs2_inode_cache *ic, struct jffs2_sb_info *c) ic = next_inode(&i, ic, (c))) -static inline void jffs2_build_inode_pass1(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) +static inline void jffs2_build_inode_pass1(struct jffs2_sb_info *c, + struct jffs2_inode_cache *ic) { struct jffs2_full_dirent *fd; - D1(printk(KERN_DEBUG "jffs2_build_inode building directory inode #%u\n", ic->ino)); + dbg_fsbuild("building directory inode #%u\n", ic->ino); /* For each child, increase nlink */ for(fd = ic->scan_dents; fd; fd = fd->next) { @@ -58,26 +60,23 @@ static inline void jffs2_build_inode_pass1(struct jffs2_sb_info *c, struct jffs2 if (!fd->ino) continue; - /* XXX: Can get high latency here with huge directories */ + /* we can get high latency here with huge directories */ child_ic = jffs2_get_ino_cache(c, fd->ino); if (!child_ic) { - printk(KERN_NOTICE "Eep. Child \"%s\" (ino #%u) of dir ino #%u doesn't exist!\n", + dbg_fsbuild("child \"%s\" (ino #%u) of dir ino #%u doesn't exist!\n", fd->name, fd->ino, ic->ino); jffs2_mark_node_obsolete(c, fd->raw); continue; } if (child_ic->nlink++ && fd->type == DT_DIR) { - printk(KERN_NOTICE "Child dir \"%s\" (ino #%u) of dir ino #%u appears to be a hard link\n", fd->name, fd->ino, ic->ino); - if (fd->ino == 1 && ic->ino == 1) { - printk(KERN_NOTICE "This is mostly harmless, and probably caused by creating a JFFS2 image\n"); - printk(KERN_NOTICE "using a buggy version of mkfs.jffs2. Use at least v1.17.\n"); - } - /* What do we do about it? */ + JFFS2_ERROR("child dir \"%s\" (ino #%u) of dir ino #%u appears to be a hard link\n", + fd->name, fd->ino, ic->ino); + /* TODO: What do we do about it? */ } - D1(printk(KERN_DEBUG "Increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino)); - /* Can't free them. We might need them in pass 2 */ + dbg_fsbuild("increased nlink for child \"%s\" (ino #%u)\n", fd->name, fd->ino); + /* Can't free scan_dents so far. We might need them in pass 2 */ } } @@ -94,6 +93,8 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) struct jffs2_full_dirent *fd; struct jffs2_full_dirent *dead_fds = NULL; + dbg_fsbuild("build FS data structures\n"); + /* First, scan the medium and build all the inode caches with lists of physical nodes */ @@ -103,33 +104,29 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) if (ret) goto exit; - D1(printk(KERN_DEBUG "Scanned flash completely\n")); + dbg_fsbuild("scanned flash completely\n"); jffs2_dbg_dump_block_lists_nolock(c); + dbg_fsbuild("pass 1 starting\n"); c->flags |= JFFS2_SB_FLAG_BUILDING; /* Now scan the directory tree, increasing nlink according to every dirent found. */ for_each_inode(i, c, ic) { - D1(printk(KERN_DEBUG "Pass 1: ino #%u\n", ic->ino)); - - D1(BUG_ON(ic->ino > c->highest_ino)); - if (ic->scan_dents) { jffs2_build_inode_pass1(c, ic); cond_resched(); } } - D1(printk(KERN_DEBUG "Pass 1 complete\n")); + dbg_fsbuild("pass 1 complete\n"); /* Next, scan for inodes with nlink == 0 and remove them. If they were directories, then decrement the nlink of their children too, and repeat the scan. As that's going to be a fairly uncommon occurrence, it's not so evil to do it this way. Recursion bad. */ - D1(printk(KERN_DEBUG "Pass 2 starting\n")); + dbg_fsbuild("pass 2 starting\n"); for_each_inode(i, c, ic) { - D1(printk(KERN_DEBUG "Pass 2: ino #%u, nlink %d, ic %p, nodes %p\n", ic->ino, ic->nlink, ic, ic->nodes)); if (ic->nlink) continue; @@ -137,26 +134,24 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) cond_resched(); } - D1(printk(KERN_DEBUG "Pass 2a starting\n")); + dbg_fsbuild("pass 2a starting\n"); while (dead_fds) { fd = dead_fds; dead_fds = fd->next; ic = jffs2_get_ino_cache(c, fd->ino); - D1(printk(KERN_DEBUG "Removing dead_fd ino #%u (\"%s\"), ic at %p\n", fd->ino, fd->name, ic)); if (ic) jffs2_build_remove_unlinked_inode(c, ic, &dead_fds); jffs2_free_full_dirent(fd); } - D1(printk(KERN_DEBUG "Pass 2 complete\n")); + dbg_fsbuild("pass 2a complete\n"); + dbg_fsbuild("freeing temporary data structures\n"); /* Finally, we can scan again and free the dirent structs */ for_each_inode(i, c, ic) { - D1(printk(KERN_DEBUG "Pass 3: ino #%u, ic %p, nodes %p\n", ic->ino, ic, ic->nodes)); - while(ic->scan_dents) { fd = ic->scan_dents; ic->scan_dents = fd->next; @@ -167,8 +162,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) } c->flags &= ~JFFS2_SB_FLAG_BUILDING; - D1(printk(KERN_DEBUG "Pass 3 complete\n")); - jffs2_dbg_dump_block_lists_nolock(c); + dbg_fsbuild("FS build complete\n"); /* Rotate the lists by some number to ensure wear levelling */ jffs2_rotate_lists(c); @@ -189,24 +183,26 @@ exit: return ret; } -static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, struct jffs2_full_dirent **dead_fds) +static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, + struct jffs2_inode_cache *ic, + struct jffs2_full_dirent **dead_fds) { struct jffs2_raw_node_ref *raw; struct jffs2_full_dirent *fd; - D1(printk(KERN_DEBUG "JFFS2: Removing ino #%u with nlink == zero.\n", ic->ino)); + dbg_fsbuild("removing ino #%u with nlink == zero.\n", ic->ino); raw = ic->nodes; while (raw != (void *)ic) { struct jffs2_raw_node_ref *next = raw->next_in_ino; - D1(printk(KERN_DEBUG "obsoleting node at 0x%08x\n", ref_offset(raw))); + dbg_fsbuild("obsoleting node at 0x%08x\n", ref_offset(raw)); jffs2_mark_node_obsolete(c, raw); raw = next; } if (ic->scan_dents) { int whinged = 0; - D1(printk(KERN_DEBUG "Inode #%u was a directory which may have children...\n", ic->ino)); + dbg_fsbuild("inode #%u was a directory which may have children...\n", ic->ino); while(ic->scan_dents) { struct jffs2_inode_cache *child_ic; @@ -216,21 +212,19 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jf if (!fd->ino) { /* It's a deletion dirent. Ignore it */ - D1(printk(KERN_DEBUG "Child \"%s\" is a deletion dirent, skipping...\n", fd->name)); + dbg_fsbuild("child \"%s\" is a deletion dirent, skipping...\n", fd->name); jffs2_free_full_dirent(fd); continue; } - if (!whinged) { + if (!whinged) whinged = 1; - printk(KERN_NOTICE "Inode #%u was a directory with children - removing those too...\n", ic->ino); - } - D1(printk(KERN_DEBUG "Removing child \"%s\", ino #%u\n", - fd->name, fd->ino)); + dbg_fsbuild("removing child \"%s\", ino #%u\n", fd->name, fd->ino); child_ic = jffs2_get_ino_cache(c, fd->ino); if (!child_ic) { - printk(KERN_NOTICE "Cannot remove child \"%s\", ino #%u, because it doesn't exist\n", fd->name, fd->ino); + dbg_fsbuild("cannot remove child \"%s\", ino #%u, because it doesn't exist\n", + fd->name, fd->ino); jffs2_free_full_dirent(fd); continue; } @@ -241,13 +235,13 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jf child_ic->nlink--; if (!child_ic->nlink) { - D1(printk(KERN_DEBUG "Inode #%u (\"%s\") has now got zero nlink. Adding to dead_fds list.\n", - fd->ino, fd->name)); + dbg_fsbuild("inode #%u (\"%s\") has now got zero nlink, adding to dead_fds list.\n", + fd->ino, fd->name); fd->next = *dead_fds; *dead_fds = fd; } else { - D1(printk(KERN_DEBUG "Inode #%u (\"%s\") has now got nlink %d. Ignoring.\n", - fd->ino, fd->name, child_ic->nlink)); + dbg_fsbuild("inode #%u (\"%s\") has now got nlink %d. Ignoring.\n", + fd->ino, fd->name, child_ic->nlink); jffs2_free_full_dirent(fd); } } @@ -295,20 +289,20 @@ static void jffs2_calc_trigger_levels(struct jffs2_sb_info *c) trying to GC to make more space. It'll be a fruitless task */ c->nospc_dirty_size = c->sector_size + (c->flash_size / 100); - D1(printk(KERN_DEBUG "JFFS2 trigger levels (size %d KiB, block size %d KiB, %d blocks)\n", - c->flash_size / 1024, c->sector_size / 1024, c->nr_blocks)); - D1(printk(KERN_DEBUG "Blocks required to allow deletion: %d (%d KiB)\n", - c->resv_blocks_deletion, c->resv_blocks_deletion*c->sector_size/1024)); - D1(printk(KERN_DEBUG "Blocks required to allow writes: %d (%d KiB)\n", - c->resv_blocks_write, c->resv_blocks_write*c->sector_size/1024)); - D1(printk(KERN_DEBUG "Blocks required to quiesce GC thread: %d (%d KiB)\n", - c->resv_blocks_gctrigger, c->resv_blocks_gctrigger*c->sector_size/1024)); - D1(printk(KERN_DEBUG "Blocks required to allow GC merges: %d (%d KiB)\n", - c->resv_blocks_gcmerge, c->resv_blocks_gcmerge*c->sector_size/1024)); - D1(printk(KERN_DEBUG "Blocks required to GC bad blocks: %d (%d KiB)\n", - c->resv_blocks_gcbad, c->resv_blocks_gcbad*c->sector_size/1024)); - D1(printk(KERN_DEBUG "Amount of dirty space required to GC: %d bytes\n", - c->nospc_dirty_size)); + dbg_fsbuild("JFFS2 trigger levels (size %d KiB, block size %d KiB, %d blocks)\n", + c->flash_size / 1024, c->sector_size / 1024, c->nr_blocks); + dbg_fsbuild("Blocks required to allow deletion: %d (%d KiB)\n", + c->resv_blocks_deletion, c->resv_blocks_deletion*c->sector_size/1024); + dbg_fsbuild("Blocks required to allow writes: %d (%d KiB)\n", + c->resv_blocks_write, c->resv_blocks_write*c->sector_size/1024); + dbg_fsbuild("Blocks required to quiesce GC thread: %d (%d KiB)\n", + c->resv_blocks_gctrigger, c->resv_blocks_gctrigger*c->sector_size/1024); + dbg_fsbuild("Blocks required to allow GC merges: %d (%d KiB)\n", + c->resv_blocks_gcmerge, c->resv_blocks_gcmerge*c->sector_size/1024); + dbg_fsbuild("Blocks required to GC bad blocks: %d (%d KiB)\n", + c->resv_blocks_gcbad, c->resv_blocks_gcbad*c->sector_size/1024); + dbg_fsbuild("Amount of dirty space required to GC: %d bytes\n", + c->nospc_dirty_size); } int jffs2_do_mount_fs(struct jffs2_sb_info *c) @@ -358,7 +352,7 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c) return ret; if (jffs2_build_filesystem(c)) { - D1(printk(KERN_DEBUG "build_fs failed\n")); + dbg_fsbuild("build_fs failed\n"); jffs2_free_ino_caches(c); jffs2_free_raw_node_refs(c); #ifndef __ECOS diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c index 28983501bcef..0947284f45dd 100644 --- a/fs/jffs2/debug.c +++ b/fs/jffs2/debug.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.c,v 1.10 2005/09/14 16:57:32 dedekind Exp $ + * $Id: debug.c,v 1.11 2005/09/21 13:28:35 dedekind Exp $ * */ #include @@ -15,6 +15,7 @@ #include #include #include +#include #include "nodelist.h" #include "debug.h" diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index 7328e67bebb6..da1417d38914 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.h,v 1.16 2005/09/14 16:57:32 dedekind Exp $ + * $Id: debug.h,v 1.18 2005/09/21 10:26:26 dedekind Exp $ * */ #ifndef _JFFS2_DEBUG_H_ @@ -23,16 +23,23 @@ /* Enable "paranoia" checks and dumps */ #define JFFS2_DBG_PARANOIA_CHECKS #define JFFS2_DBG_DUMPS + +/* + * By defining/undefining the below macros one may select debugging messages + * fro specific JFFS2 subsystems. + */ #define JFFS2_DBG_READINODE_MESSAGES #define JFFS2_DBG_FRAGTREE_MESSAGES #define JFFS2_DBG_DENTLIST_MESSAGES #define JFFS2_DBG_NODEREF_MESSAGES #define JFFS2_DBG_INOCACHE_MESSAGES #define JFFS2_DBG_SUMMARY_MESSAGES +#define JFFS2_DBG_FSBUILD_MESSAGES #endif #if CONFIG_JFFS2_FS_DEBUG == 2 #define JFFS2_DBG_FRAGTREE2_MESSAGES +#define JFFS2_DBG_MEMALLOC_MESSAGES #endif /* Sanity checks are supposed to be light-weight and enabled by default */ @@ -40,7 +47,7 @@ /* * Dx() are mainly used for debugging messages, they must go away and be - * superseded by nicer JFFS2_DBG_XXX() macros... + * superseded by nicer dbg_xxx() macros... */ #if CONFIG_JFFS2_FS_DEBUG > 0 #define D1(x) x @@ -105,56 +112,63 @@ */ /* Read inode debugging messages */ #ifdef JFFS2_DBG_READINODE_MESSAGES -#define JFFS2_DBG_READINODE(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#define dbg_readinode(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else -#define JFFS2_DBG_READINODE(fmt, ...) +#define dbg_readinode(fmt, ...) #endif /* Fragtree build debugging messages */ #ifdef JFFS2_DBG_FRAGTREE_MESSAGES -#define JFFS2_DBG_FRAGTREE(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#define dbg_fragtree(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else -#define JFFS2_DBG_FRAGTREE(fmt, ...) +#define dbg_fragtree(fmt, ...) #endif #ifdef JFFS2_DBG_FRAGTREE2_MESSAGES -#define JFFS2_DBG_FRAGTREE2(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#define dbg_fragtree2(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else -#define JFFS2_DBG_FRAGTREE2(fmt, ...) +#define dbg_fragtree2(fmt, ...) #endif /* Directory entry list manilulation debugging messages */ #ifdef JFFS2_DBG_DENTLIST_MESSAGES -#define JFFS2_DBG_DENTLIST(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#define dbg_dentlist(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else -#define JFFS2_DBG_DENTLIST(fmt, ...) +#define dbg_dentlist(fmt, ...) #endif /* Print the messages about manipulating node_refs */ #ifdef JFFS2_DBG_NODEREF_MESSAGES -#define JFFS2_DBG_NODEREF(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#define dbg_noderef(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else -#define JFFS2_DBG_NODEREF(fmt, ...) +#define dbg_noderef(fmt, ...) #endif /* Manipulations with the list of inodes (JFFS2 inocache) */ #ifdef JFFS2_DBG_INOCACHE_MESSAGES -#define JFFS2_DBG_INOCACHE(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#define dbg_inocache(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else -#define JFFS2_DBG_INOCACHE(fmt, ...) +#define dbg_inocache(fmt, ...) #endif /* Summary debugging messages */ #ifdef JFFS2_DBG_SUMMARY_MESSAGES -#define JFFS2_DBG_SUMMARY(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#define dbg_summary(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#else +#define dbg_summary(fmt, ...) +#endif + +/* File system build messages */ +#ifdef JFFS2_DBG_FSBUILD_MESSAGES +#define dbg_fsbuild(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else -#define JFFS2_DBG_SUMMARY(fmt, ...) +#define dbg_fsbuild(fmt, ...) #endif /* Watch the object allocations */ #ifdef JFFS2_DBG_MEMALLOC_MESSAGES -#define JFFS2_DBG_MEMALLOC(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) +#define dbg_memalloc(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) #else -#define JFFS2_DBG_MEMALLOC(fmt, ...) +#define dbg_memalloc(fmt, ...) #endif diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index a8a0908142d9..347de4efeeeb 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: erase.c,v 1.83 2005/07/22 10:32:08 dedekind Exp $ + * $Id: erase.c,v 1.85 2005/09/20 14:53:15 dedekind Exp $ * */ diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c index 734801145bf8..f27df015f3ec 100644 --- a/fs/jffs2/malloc.c +++ b/fs/jffs2/malloc.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: malloc.c,v 1.29 2005/07/27 14:16:53 dedekind Exp $ + * $Id: malloc.c,v 1.30 2005/09/20 14:27:34 dedekind Exp $ * */ @@ -97,13 +97,13 @@ struct jffs2_full_dirent *jffs2_alloc_full_dirent(int namesize) { struct jffs2_full_dirent *ret; ret = kmalloc(sizeof(struct jffs2_full_dirent) + namesize, GFP_KERNEL); - JFFS2_DBG_MEMALLOC("%p\n", ret); + dbg_memalloc("%p\n", ret); return ret; } void jffs2_free_full_dirent(struct jffs2_full_dirent *x) { - JFFS2_DBG_MEMALLOC("%p\n", x); + dbg_memalloc("%p\n", x); kfree(x); } @@ -111,13 +111,13 @@ struct jffs2_full_dnode *jffs2_alloc_full_dnode(void) { struct jffs2_full_dnode *ret; ret = kmem_cache_alloc(full_dnode_slab, GFP_KERNEL); - JFFS2_DBG_MEMALLOC("%p\n", ret); + dbg_memalloc("%p\n", ret); return ret; } void jffs2_free_full_dnode(struct jffs2_full_dnode *x) { - JFFS2_DBG_MEMALLOC("%p\n", x); + dbg_memalloc("%p\n", x); kmem_cache_free(full_dnode_slab, x); } @@ -125,13 +125,13 @@ struct jffs2_raw_dirent *jffs2_alloc_raw_dirent(void) { struct jffs2_raw_dirent *ret; ret = kmem_cache_alloc(raw_dirent_slab, GFP_KERNEL); - JFFS2_DBG_MEMALLOC("%p\n", ret); + dbg_memalloc("%p\n", ret); return ret; } void jffs2_free_raw_dirent(struct jffs2_raw_dirent *x) { - JFFS2_DBG_MEMALLOC("%p\n", x); + dbg_memalloc("%p\n", x); kmem_cache_free(raw_dirent_slab, x); } @@ -139,13 +139,13 @@ struct jffs2_raw_inode *jffs2_alloc_raw_inode(void) { struct jffs2_raw_inode *ret; ret = kmem_cache_alloc(raw_inode_slab, GFP_KERNEL); - JFFS2_DBG_MEMALLOC("%p\n", ret); + dbg_memalloc("%p\n", ret); return ret; } void jffs2_free_raw_inode(struct jffs2_raw_inode *x) { - JFFS2_DBG_MEMALLOC("%p\n", x); + dbg_memalloc("%p\n", x); kmem_cache_free(raw_inode_slab, x); } @@ -153,14 +153,14 @@ struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void) { struct jffs2_tmp_dnode_info *ret; ret = kmem_cache_alloc(tmp_dnode_info_slab, GFP_KERNEL); - JFFS2_DBG_MEMALLOC("%p\n", + dbg_memalloc("%p\n", ret); return ret; } void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *x) { - JFFS2_DBG_MEMALLOC("%p\n", x); + dbg_memalloc("%p\n", x); kmem_cache_free(tmp_dnode_info_slab, x); } @@ -168,13 +168,13 @@ struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void) { struct jffs2_raw_node_ref *ret; ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL); - JFFS2_DBG_MEMALLOC("%p\n", ret); + dbg_memalloc("%p\n", ret); return ret; } void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x) { - JFFS2_DBG_MEMALLOC("%p\n", x); + dbg_memalloc("%p\n", x); kmem_cache_free(raw_node_ref_slab, x); } @@ -182,13 +182,13 @@ struct jffs2_node_frag *jffs2_alloc_node_frag(void) { struct jffs2_node_frag *ret; ret = kmem_cache_alloc(node_frag_slab, GFP_KERNEL); - JFFS2_DBG_MEMALLOC("%p\n", ret); + dbg_memalloc("%p\n", ret); return ret; } void jffs2_free_node_frag(struct jffs2_node_frag *x) { - JFFS2_DBG_MEMALLOC("%p\n", x); + dbg_memalloc("%p\n", x); kmem_cache_free(node_frag_slab, x); } @@ -196,12 +196,12 @@ struct jffs2_inode_cache *jffs2_alloc_inode_cache(void) { struct jffs2_inode_cache *ret; ret = kmem_cache_alloc(inode_cache_slab, GFP_KERNEL); - JFFS2_DBG_MEMALLOC("%p\n", ret); + dbg_memalloc("%p\n", ret); return ret; } void jffs2_free_inode_cache(struct jffs2_inode_cache *x) { - JFFS2_DBG_MEMALLOC("%p\n", x); + dbg_memalloc("%p\n", x); kmem_cache_free(inode_cache_slab, x); } diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index 9abb5f4cfd75..80fe8feffb4d 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.c,v 1.112 2005/08/22 09:07:09 dedekind Exp $ + * $Id: nodelist.c,v 1.114 2005/09/21 13:28:35 dedekind Exp $ * */ @@ -25,18 +25,18 @@ void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new { struct jffs2_full_dirent **prev = list; - JFFS2_DBG_DENTLIST("add dirent \"%s\", ino #%u\n", new->name, new->ino); + dbg_dentlist("add dirent \"%s\", ino #%u\n", new->name, new->ino); while ((*prev) && (*prev)->nhash <= new->nhash) { if ((*prev)->nhash == new->nhash && !strcmp((*prev)->name, new->name)) { /* Duplicate. Free one */ if (new->version < (*prev)->version) { - JFFS2_DBG_DENTLIST("Eep! Marking new dirent node is obsolete, old is \"%s\", ino #%u\n", + dbg_dentlist("Eep! Marking new dirent node is obsolete, old is \"%s\", ino #%u\n", (*prev)->name, (*prev)->ino); jffs2_mark_node_obsolete(c, new->raw); jffs2_free_full_dirent(new); } else { - JFFS2_DBG_DENTLIST("marking old dirent \"%s\", ino #%u bsolete\n", + dbg_dentlist("marking old dirent \"%s\", ino #%u bsolete\n", (*prev)->name, (*prev)->ino); new->next = (*prev)->next; jffs2_mark_node_obsolete(c, ((*prev)->raw)); @@ -55,7 +55,7 @@ void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint { struct jffs2_node_frag *frag = jffs2_lookup_node_frag(list, size); - JFFS2_DBG_FRAGTREE("truncating fragtree to 0x%08x bytes\n", size); + dbg_fragtree("truncating fragtree to 0x%08x bytes\n", size); /* We know frag->ofs <= size. That's what lookup does for us */ if (frag && frag->ofs != size) { @@ -81,7 +81,7 @@ void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint */ frag = frag_last(list); if (frag->node && (frag->ofs & (PAGE_CACHE_SIZE - 1)) == 0) { - JFFS2_DBG_FRAGTREE2("marking the last fragment 0x%08x-0x%08x REF_PRISTINE.\n", + dbg_fragtree2("marking the last fragment 0x%08x-0x%08x REF_PRISTINE.\n", frag->ofs, frag->ofs + frag->size); frag->node->raw->flash_offset = ref_offset(frag->node->raw) | REF_PRISTINE; } @@ -93,12 +93,12 @@ void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *t this->node->frags--; if (!this->node->frags) { /* The node has no valid frags left. It's totally obsoleted */ - JFFS2_DBG_FRAGTREE2("marking old node @0x%08x (0x%04x-0x%04x) obsolete\n", + dbg_fragtree2("marking old node @0x%08x (0x%04x-0x%04x) obsolete\n", ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size); jffs2_mark_node_obsolete(c, this->node->raw); jffs2_free_full_dnode(this->node); } else { - JFFS2_DBG_FRAGTREE2("marking old node @0x%08x (0x%04x-0x%04x) REF_NORMAL. frags is %d\n", + dbg_fragtree2("marking old node @0x%08x (0x%04x-0x%04x) REF_NORMAL. frags is %d\n", ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size, this->node->frags); mark_ref_normal(this->node->raw); } @@ -112,7 +112,7 @@ static void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_ struct rb_node *parent = &base->rb; struct rb_node **link = &parent; - JFFS2_DBG_FRAGTREE2("insert frag (0x%04x-0x%04x)\n", newfrag->ofs, newfrag->ofs + newfrag->size); + dbg_fragtree2("insert frag (0x%04x-0x%04x)\n", newfrag->ofs, newfrag->ofs + newfrag->size); while (*link) { parent = *link; @@ -172,11 +172,11 @@ static int no_overlapping_node(struct jffs2_sb_info *c, struct rb_root *root, /* By definition, the 'this' node has no right-hand child, because there are no frags with offset greater than it. So that's where we want to put the hole */ - JFFS2_DBG_FRAGTREE2("add hole frag %#04x-%#04x on the right of the new frag.\n", + dbg_fragtree2("add hole frag %#04x-%#04x on the right of the new frag.\n", holefrag->ofs, holefrag->ofs + holefrag->size); rb_link_node(&holefrag->rb, &this->rb, &this->rb.rb_right); } else { - JFFS2_DBG_FRAGTREE2("Add hole frag %#04x-%#04x to the root of the tree.\n", + dbg_fragtree2("Add hole frag %#04x-%#04x to the root of the tree.\n", holefrag->ofs, holefrag->ofs + holefrag->size); rb_link_node(&holefrag->rb, NULL, &root->rb_node); } @@ -188,10 +188,10 @@ static int no_overlapping_node(struct jffs2_sb_info *c, struct rb_root *root, /* By definition, the 'this' node has no right-hand child, because there are no frags with offset greater than it. So that's where we want to put new fragment */ - JFFS2_DBG_FRAGTREE2("add the new node at the right\n"); + dbg_fragtree2("add the new node at the right\n"); rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); } else { - JFFS2_DBG_FRAGTREE2("insert the new node at the root of the tree\n"); + dbg_fragtree2("insert the new node at the root of the tree\n"); rb_link_node(&newfrag->rb, NULL, &root->rb_node); } rb_insert_color(&newfrag->rb, root); @@ -209,11 +209,11 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r this = jffs2_lookup_node_frag(root, newfrag->node->ofs); if (this) { - JFFS2_DBG_FRAGTREE2("lookup gave frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", + dbg_fragtree2("lookup gave frag 0x%04x-0x%04x; phys 0x%08x (*%p)\n", this->ofs, this->ofs+this->size, this->node?(ref_offset(this->node->raw)):0xffffffff, this); lastend = this->ofs + this->size; } else { - JFFS2_DBG_FRAGTREE2("lookup gave no frag\n"); + dbg_fragtree2("lookup gave no frag\n"); lastend = 0; } @@ -235,11 +235,11 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r } if (this->node) - JFFS2_DBG_FRAGTREE2("dealing with frag %u-%u, phys %#08x(%d).\n", + dbg_fragtree2("dealing with frag %u-%u, phys %#08x(%d).\n", this->ofs, this->ofs + this->size, ref_offset(this->node->raw), ref_flags(this->node->raw)); else - JFFS2_DBG_FRAGTREE2("dealing with hole frag %u-%u.\n", + dbg_fragtree2("dealing with hole frag %u-%u.\n", this->ofs, this->ofs + this->size); /* OK. 'this' is pointing at the first frag that newfrag->ofs at least partially obsoletes, @@ -259,10 +259,10 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r struct jffs2_node_frag *newfrag2; if (this->node) - JFFS2_DBG_FRAGTREE2("split old frag 0x%04x-0x%04x, phys 0x%08x\n", + dbg_fragtree2("split old frag 0x%04x-0x%04x, phys 0x%08x\n", this->ofs, this->ofs+this->size, ref_offset(this->node->raw)); else - JFFS2_DBG_FRAGTREE2("split old hole frag 0x%04x-0x%04x\n", + dbg_fragtree2("split old hole frag 0x%04x-0x%04x\n", this->ofs, this->ofs+this->size); /* New second frag pointing to this's node */ @@ -299,13 +299,13 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r } else { /* New frag starts at the same point as 'this' used to. Replace it in the tree without doing a delete and insertion */ - JFFS2_DBG_FRAGTREE2("inserting newfrag (*%p),%d-%d in before 'this' (*%p),%d-%d\n", + dbg_fragtree2("inserting newfrag (*%p),%d-%d in before 'this' (*%p),%d-%d\n", newfrag, newfrag->ofs, newfrag->ofs+newfrag->size, this, this->ofs, this->ofs+this->size); rb_replace_node(&this->rb, &newfrag->rb, root); if (newfrag->ofs + newfrag->size >= this->ofs+this->size) { - JFFS2_DBG_FRAGTREE2("obsoleting node frag %p (%x-%x)\n", this, this->ofs, this->ofs+this->size); + dbg_fragtree2("obsoleting node frag %p (%x-%x)\n", this, this->ofs, this->ofs+this->size); jffs2_obsolete_node_frag(c, this); } else { this->ofs += newfrag->size; @@ -321,7 +321,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r */ while ((this = frag_next(newfrag)) && newfrag->ofs + newfrag->size >= this->ofs + this->size) { /* 'this' frag is obsoleted completely. */ - JFFS2_DBG_FRAGTREE2("obsoleting node frag %p (%x-%x) and removing from tree\n", + dbg_fragtree2("obsoleting node frag %p (%x-%x) and removing from tree\n", this, this->ofs, this->ofs+this->size); rb_erase(&this->rb, root); jffs2_obsolete_node_frag(c, this); @@ -361,7 +361,7 @@ int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_in return -ENOMEM; newfrag->node->frags = 1; - JFFS2_DBG_FRAGTREE("adding node %#04x-%#04x @0x%08x on flash, newfrag *%p\n", + dbg_fragtree("adding node %#04x-%#04x @0x%08x on flash, newfrag *%p\n", fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag); ret = jffs2_add_frag_to_fragtree(c, &f->fragtree, newfrag); @@ -410,14 +410,17 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info BUG_ON(tn->csize == 0); + if (!jffs2_is_writebuffered(c)) + goto adj_acc; + /* Calculate how many bytes were already checked */ ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode); - len = ofs & (c->wbuf_pagesize - 1); + len = ofs % c->wbuf_pagesize; if (likely(len)) len = c->wbuf_pagesize - len; if (len >= tn->csize) { - JFFS2_DBG_READINODE("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.\n", + dbg_readinode("no need to check node at %#08x, data length %u, data starts at %#08x - it has already been checked.\n", ref_offset(ref), tn->csize, ofs); goto adj_acc; } @@ -425,7 +428,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info ofs += len; len = tn->csize - len; - JFFS2_DBG_READINODE("check node at %#08x, data length %u, partial CRC %#08x, correct CRC %#08x, data starts at %#08x, start checking from %#08x - %u bytes.\n", + dbg_readinode("check node at %#08x, data length %u, partial CRC %#08x, correct CRC %#08x, data starts at %#08x, start checking from %#08x - %u bytes.\n", ref_offset(ref), tn->csize, tn->partial_crc, tn->data_crc, ofs - len, ofs, len); #ifndef __ECOS @@ -520,7 +523,7 @@ static inline int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f if (ref_flags(tn->fn->raw) != REF_UNCHECKED) return 0; - JFFS2_DBG_FRAGTREE2("check node %#04x-%#04x, phys offs %#08x.\n", + dbg_fragtree2("check node %#04x-%#04x, phys offs %#08x.\n", tn->fn->ofs, tn->fn->ofs + tn->fn->size, ref_offset(tn->fn->raw)); ret = check_node_data(c, tn); @@ -528,7 +531,7 @@ static inline int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f JFFS2_ERROR("check_node_data() returned error: %d.\n", ret); } else if (unlikely(ret > 0)) { - JFFS2_DBG_FRAGTREE2("CRC error, mark it obsolete.\n"); + dbg_fragtree2("CRC error, mark it obsolete.\n"); jffs2_mark_node_obsolete(c, tn->fn->raw); } @@ -544,7 +547,7 @@ static inline int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f static int split_hole(struct jffs2_sb_info *c, struct rb_root *root, struct jffs2_node_frag *newfrag, struct jffs2_node_frag *hole) { - JFFS2_DBG_FRAGTREE2("fragment %#04x-%#04x splits the hole %#04x-%#04x\n", + dbg_fragtree2("fragment %#04x-%#04x splits the hole %#04x-%#04x\n", newfrag->ofs, newfrag->ofs + newfrag->size, hole->ofs, hole->ofs + hole->size); if (hole->ofs == newfrag->ofs) { @@ -558,7 +561,7 @@ static int split_hole(struct jffs2_sb_info *c, struct rb_root *root, * the new node. */ - JFFS2_DBG_FRAGTREE2("insert fragment %#04x-%#04x and cut the left part of the hole\n", + dbg_fragtree2("insert fragment %#04x-%#04x and cut the left part of the hole\n", newfrag->ofs, newfrag->ofs + newfrag->size); rb_replace_node(&hole->rb, &newfrag->rb, root); @@ -576,7 +579,7 @@ static int split_hole(struct jffs2_sb_info *c, struct rb_root *root, * Ah, the new fragment is of the same size as the hole. * Relace the hole by it. */ - JFFS2_DBG_FRAGTREE2("insert fragment %#04x-%#04x and overwrite hole\n", + dbg_fragtree2("insert fragment %#04x-%#04x and overwrite hole\n", newfrag->ofs, newfrag->ofs + newfrag->size); rb_replace_node(&hole->rb, &newfrag->rb, root); jffs2_free_node_frag(hole); @@ -598,14 +601,14 @@ static int split_hole(struct jffs2_sb_info *c, struct rb_root *root, } hole->size = newfrag->ofs - hole->ofs; - JFFS2_DBG_FRAGTREE2("left the hole %#04x-%#04x at the left and inserd fragment %#04x-%#04x\n", + dbg_fragtree2("left the hole %#04x-%#04x at the left and inserd fragment %#04x-%#04x\n", hole->ofs, hole->ofs + hole->size, newfrag->ofs, newfrag->ofs + newfrag->size); jffs2_fragtree_insert(newfrag, hole); rb_insert_color(&newfrag->rb, root); if (newfrag2) { - JFFS2_DBG_FRAGTREE2("left the hole %#04x-%#04x at the right\n", + dbg_fragtree2("left the hole %#04x-%#04x at the right\n", newfrag2->ofs, newfrag2->ofs + newfrag2->size); jffs2_fragtree_insert(newfrag2, newfrag); rb_insert_color(&newfrag2->rb, root); @@ -640,12 +643,12 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode int err, checked = 0; int ref_flag; - JFFS2_DBG_FRAGTREE("insert fragment %#04x-%#04x, ver %u\n", fn_ofs, fn_ofs + fn_size, tn->version); + dbg_fragtree("insert fragment %#04x-%#04x, ver %u\n", fn_ofs, fn_ofs + fn_size, tn->version); /* Skip all the nodes which are completed before this one starts */ this = jffs2_lookup_node_frag(root, fn_ofs); if (this) - JFFS2_DBG_FRAGTREE2("'this' found %#04x-%#04x (%s)\n", this->ofs, this->ofs + this->size, this->node ? "data" : "hole"); + dbg_fragtree2("'this' found %#04x-%#04x (%s)\n", this->ofs, this->ofs + this->size, this->node ? "data" : "hole"); if (this) lastend = this->ofs + this->size; @@ -745,7 +748,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode * The new node starts at the same offset as * the hole and supersieds the hole. */ - JFFS2_DBG_FRAGTREE2("add the new fragment instead of hole %#04x-%#04x, refcnt %d\n", + dbg_fragtree2("add the new fragment instead of hole %#04x-%#04x, refcnt %d\n", fn_ofs, fn_ofs + this->ofs + this->size - fn_ofs, fn->frags); rb_replace_node(&this->rb, &newfrag->rb, root); @@ -755,10 +758,10 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode * The hole becomes shorter as its right part * is supersieded by the new fragment. */ - JFFS2_DBG_FRAGTREE2("reduce size of hole %#04x-%#04x to %#04x-%#04x\n", + dbg_fragtree2("reduce size of hole %#04x-%#04x to %#04x-%#04x\n", this->ofs, this->ofs + this->size, this->ofs, this->ofs + this->size - newfrag->size); - JFFS2_DBG_FRAGTREE2("add new fragment %#04x-%#04x, refcnt %d\n", fn_ofs, + dbg_fragtree2("add new fragment %#04x-%#04x, refcnt %d\n", fn_ofs, fn_ofs + this->ofs + this->size - fn_ofs, fn->frags); this->size -= newfrag->size; @@ -771,7 +774,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode this = rb_entry(rb_next(&newfrag->rb), struct jffs2_node_frag, rb); - JFFS2_DBG_FRAGTREE2("switch to the next 'this' fragment: %#04x-%#04x %s\n", + dbg_fragtree2("switch to the next 'this' fragment: %#04x-%#04x %s\n", this->ofs, this->ofs + this->size, this->node ? "(data)" : "(hole)"); } @@ -782,7 +785,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode if (this->ofs + this->size >= fn_ofs + fn_size) { /* The new node is obsolete, drop it */ if (fn->frags == 0) { - JFFS2_DBG_FRAGTREE2("%#04x-%#04x is obsolete, mark it obsolete\n", fn_ofs, fn_ofs + fn_size); + dbg_fragtree2("%#04x-%#04x is obsolete, mark it obsolete\n", fn_ofs, fn_ofs + fn_size); ref_flag = REF_OBSOLETE; } goto out_ok; @@ -790,13 +793,13 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode struct jffs2_node_frag *new_this; /* 'This' node obsoletes the beginning of the new node */ - JFFS2_DBG_FRAGTREE2("the beginning %#04x-%#04x is obsolete\n", fn_ofs, this->ofs + this->size); + dbg_fragtree2("the beginning %#04x-%#04x is obsolete\n", fn_ofs, this->ofs + this->size); ref_flag = REF_NORMAL; fn_size -= this->ofs + this->size - fn_ofs; fn_ofs = this->ofs + this->size; - JFFS2_DBG_FRAGTREE2("now considering %#04x-%#04x\n", fn_ofs, fn_ofs + fn_size); + dbg_fragtree2("now considering %#04x-%#04x\n", fn_ofs, fn_ofs + fn_size); new_this = rb_entry(rb_next(&this->rb), struct jffs2_node_frag, rb); if (!new_this) { @@ -816,14 +819,14 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode if (unlikely(!newfrag)) return -ENOMEM; - JFFS2_DBG_FRAGTREE2("there are no more fragments, insert %#04x-%#04x\n", + dbg_fragtree2("there are no more fragments, insert %#04x-%#04x\n", newfrag->ofs, newfrag->ofs + newfrag->size); rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); rb_insert_color(&newfrag->rb, root); goto out_ok; } else { this = new_this; - JFFS2_DBG_FRAGTREE2("switch to the next 'this' fragment: %#04x-%#04x %s\n", + dbg_fragtree2("switch to the next 'this' fragment: %#04x-%#04x %s\n", this->ofs, this->ofs + this->size, this->node ? "(data)" : "(hole)"); } } @@ -833,13 +836,13 @@ out_ok: BUG_ON(fn->size < PAGE_CACHE_SIZE && ref_flag == REF_PRISTINE); if (ref_flag == REF_OBSOLETE) { - JFFS2_DBG_FRAGTREE2("the node is obsolete now\n"); + dbg_fragtree2("the node is obsolete now\n"); /* jffs2_mark_node_obsolete() will adjust space accounting */ jffs2_mark_node_obsolete(c, fn->raw); return 1; } - JFFS2_DBG_FRAGTREE2("the node is \"%s\" now\n", ref_flag == REF_NORMAL ? "REF_NORMAL" : "REF_PRISTINE"); + dbg_fragtree2("the node is \"%s\" now\n", ref_flag == REF_NORMAL ? "REF_NORMAL" : "REF_PRISTINE"); /* Space accounting was adjusted at check_node_data() */ spin_lock(&c->erase_completion_lock); @@ -885,7 +888,7 @@ void jffs2_add_ino_cache (struct jffs2_sb_info *c, struct jffs2_inode_cache *new if (!new->ino) new->ino = ++c->highest_ino; - JFFS2_DBG_INOCACHE("add %p (ino #%u)\n", new, new->ino); + dbg_inocache("add %p (ino #%u)\n", new, new->ino); prev = &c->inocache_list[new->ino % INOCACHE_HASHSIZE]; @@ -902,7 +905,7 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old) { struct jffs2_inode_cache **prev; - JFFS2_DBG_INOCACHE("del %p (ino #%u)\n", old, old->ino); + dbg_inocache("del %p (ino #%u)\n", old, old->ino); spin_lock(&c->inocache_lock); prev = &c->inocache_list[old->ino % INOCACHE_HASHSIZE]; @@ -965,7 +968,7 @@ struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_ struct jffs2_node_frag *prev = NULL; struct jffs2_node_frag *frag = NULL; - JFFS2_DBG_FRAGTREE2("root %p, offset %d\n", fragtree, offset); + dbg_fragtree2("root %p, offset %d\n", fragtree, offset); next = fragtree->rb_node; @@ -988,10 +991,10 @@ struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_ and return the closest smaller one */ if (prev) - JFFS2_DBG_FRAGTREE2("no match. Returning frag %#04x-%#04x, closest previous\n", + dbg_fragtree2("no match. Returning frag %#04x-%#04x, closest previous\n", prev->ofs, prev->ofs+prev->size); else - JFFS2_DBG_FRAGTREE2("returning NULL, empty fragtree\n"); + dbg_fragtree2("returning NULL, empty fragtree\n"); return prev; } @@ -1006,7 +1009,7 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c) if (!root->rb_node) return; - JFFS2_DBG_FRAGTREE("killing\n"); + dbg_fragtree("killing\n"); frag = (rb_entry(root->rb_node, struct jffs2_node_frag, rb)); while(frag) { diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 2cf576ae1120..2c938d1bffb0 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodemgmt.c,v 1.126 2005/09/16 12:58:17 havasi Exp $ + * $Id: nodemgmt.c,v 1.127 2005/09/20 15:49:12 dedekind Exp $ * */ @@ -273,7 +273,7 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin if (jeb) { reserved_size = PAD(sumsize + c->summary->sum_size + JFFS2_SUMMARY_FRAME_SIZE); - JFFS2_DBG_SUMMARY("minsize=%d , jeb->free=%d ," + dbg_summary("minsize=%d , jeb->free=%d ," "summary->size=%d , sumsize=%d\n", minsize, jeb->free_size, c->summary->sum_size, sumsize); @@ -291,7 +291,7 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin } /* Writing out the collected summary information */ - JFFS2_DBG_SUMMARY("generating summary for 0x%08x.\n", jeb->offset); + dbg_summary("generating summary for 0x%08x.\n", jeb->offset); ret = jffs2_sum_write_sumnode(c); if (ret) diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index e026888cf1cb..48ad4202fbb1 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: os-linux.h,v 1.61 2005/09/07 08:34:54 havasi Exp $ + * $Id: os-linux.h,v 1.63 2005/09/21 11:55:21 dedekind Exp $ * */ @@ -80,8 +80,8 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) #define jffs2_flash_write(c, ofs, len, retlen, buf) jffs2_flash_direct_write(c, ofs, len, retlen, buf) #define jffs2_flash_read(c, ofs, len, retlen, buf) ((c)->mtd->read((c)->mtd, ofs, len, retlen, buf)) -#define jffs2_flush_wbuf_pad(c) ({ (void)(c), 0; }) -#define jffs2_flush_wbuf_gc(c, i) ({ (void)(c), (void) i, 0; }) +#define jffs2_flush_wbuf_pad(c) ({ do{} while(0); (void)(c), 0; }) +#define jffs2_flush_wbuf_gc(c, i) ({ do{} while(0); (void)(c), (void) i, 0; }) #define jffs2_write_nand_badblock(c,jeb,bad_offset) (1) #define jffs2_nand_flash_setup(c) (0) #define jffs2_nand_flash_cleanup(c) do {} while(0) diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 6f1e4a7ecd9f..08f8c5ec6118 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.141 2005/08/17 14:57:39 dedekind Exp $ + * $Id: readinode.c,v 1.142 2005/09/20 14:27:34 dedekind Exp $ * */ @@ -97,7 +97,7 @@ static struct jffs2_raw_node_ref *jffs2_first_valid_node(struct jffs2_raw_node_r while (ref && ref->next_in_ino) { if (!ref_obsolete(ref)) return ref; - JFFS2_DBG_NODEREF("node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref)); + dbg_noderef("node at 0x%08x is obsoleted. Ignoring.\n", ref_offset(ref)); ref = ref->next_in_ino; } return NULL; @@ -274,7 +274,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref len = min_t(uint32_t, rdlen - sizeof(*rd), csize); tn->partial_crc = crc32(0, buf, len); - JFFS2_DBG_READINODE("Calculates CRC (%#08x) for %d bytes, csize %d\n", tn->partial_crc, len, csize); + dbg_readinode("Calculates CRC (%#08x) for %d bytes, csize %d\n", tn->partial_crc, len, csize); /* If we actually calculated the whole data CRC * and it is wrong, drop the node. */ @@ -293,7 +293,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref */ struct jffs2_eraseblock *jeb; - JFFS2_DBG_READINODE("the node has no data.\n"); + dbg_readinode("the node has no data.\n"); jeb = &c->blocks[ref->flash_offset / c->sector_size]; len = ref_totlen(c, jeb, ref); @@ -327,7 +327,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref else // normal case... tn->fn->size = je32_to_cpu(rd->dsize); - JFFS2_DBG_READINODE("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n", + dbg_readinode("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n", ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize); jffs2_add_tn_to_tree(tn, tnp); @@ -424,7 +424,7 @@ static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, len = right_size - *rdlen; } - JFFS2_DBG_READINODE("read more %d bytes\n", len); + dbg_readinode("read more %d bytes\n", len); err = jffs2_flash_read(c, offs, len, &retlen, bufstart); if (err) { @@ -461,7 +461,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf *mctime_ver = 0; - JFFS2_DBG_READINODE("ino #%u\n", f->inocache->ino); + dbg_readinode("ino #%u\n", f->inocache->ino); if (jffs2_is_writebuffered(c)) { /* @@ -531,7 +531,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf len = JFFS2_MIN_NODE_HEADER; } - JFFS2_DBG_READINODE("read %d bytes at %#08x(%d).\n", len, ref_offset(ref), ref_flags(ref)); + dbg_readinode("read %d bytes at %#08x(%d).\n", len, ref_offset(ref), ref_flags(ref)); /* FIXME: point() */ err = jffs2_flash_read(c, ref_offset(ref), len, @@ -614,7 +614,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf *fdp = ret_fd; kfree(buf); - JFFS2_DBG_READINODE("nodes of inode #%u were read, the highest version is %u, latest_mctime %u, mctime_ver %u.\n", + dbg_readinode("nodes of inode #%u were read, the highest version is %u, latest_mctime %u, mctime_ver %u.\n", f->inocache->ino, *highest_version, *latest_mctime, *mctime_ver); return 0; @@ -639,7 +639,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, size_t retlen; int ret; - JFFS2_DBG_READINODE("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink); + dbg_readinode("ino #%u nlink is %d\n", f->inocache->ino, f->inocache->nlink); /* Grab all nodes relevant to this ino */ ret = jffs2_get_inode_nodes(c, f, &tn_list, &fd_list, &f->highest_version, &latest_mctime, &mctime_ver); @@ -659,7 +659,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, tn = rb_entry(rb, struct jffs2_tmp_dnode_info, rb); fn = tn->fn; ret = 1; - JFFS2_DBG_READINODE("consider node ver %u, phys offset " + dbg_readinode("consider node ver %u, phys offset " "%#08x(%d), range %u-%u.\n", tn->version, ref_offset(fn->raw), ref_flags(fn->raw), fn->ofs, fn->ofs + fn->size); @@ -703,7 +703,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, jffs2_free_tmp_dnode_info(tn); if (ret) { - JFFS2_DBG_READINODE("delete dnode %u-%u.\n", + dbg_readinode("delete dnode %u-%u.\n", fn->ofs, fn->ofs + fn->size); jffs2_free_full_dnode(fn); } @@ -803,7 +803,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, } f->target[je32_to_cpu(latest_node->csize)] = '\0'; - JFFS2_DBG_READINODE("symlink's target '%s' cached\n", f->target); + dbg_readinode("symlink's target '%s' cached\n", f->target); } /* fall through... */ @@ -851,7 +851,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t ino, struct jffs2_raw_inode *latest_node) { - JFFS2_DBG_READINODE("read inode #%u\n", ino); + dbg_readinode("read inode #%u\n", ino); retry_inocache: spin_lock(&c->inocache_lock); @@ -870,7 +870,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, /* If it's in either of these states, we need to wait for whoever's got it to finish and put it back. */ - JFFS2_DBG_READINODE("waiting for ino #%u in state %d\n", ino, f->inocache->state); + dbg_readinode("waiting for ino #%u in state %d\n", ino, f->inocache->state); sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); goto retry_inocache; @@ -897,7 +897,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, JFFS2_ERROR("cannot allocate inocache for root inode\n"); return -ENOMEM; } - JFFS2_DBG_READINODE("creating inocache for root inode\n"); + dbg_readinode("creating inocache for root inode\n"); memset(f->inocache, 0, sizeof(struct jffs2_inode_cache)); f->inocache->ino = f->inocache->nlink = 1; f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 4e60ba8da197..8df7456472b8 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: scan.c,v 1.122 2005/09/07 08:34:54 havasi Exp $ + * $Id: scan.c,v 1.124 2005/09/21 13:05:22 dedekind Exp $ * */ #include @@ -429,7 +429,7 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo noise = 10; - JFFS2_DBG_SUMMARY("no summary found in jeb 0x%08x. Apply original scan.\n",jeb->offset); + dbg_summary("no summary found in jeb 0x%08x. Apply original scan.\n",jeb->offset); scan_more: while(ofs < jeb->offset + c->sector_size) { @@ -684,7 +684,7 @@ scan_more: if (jffs2_sum_active()) { if (PAD(s->sum_size + JFFS2_SUMMARY_FRAME_SIZE) > jeb->free_size) { - JFFS2_DBG_SUMMARY("There is not enough space for " + dbg_summary("There is not enough space for " "summary information, disabling for this jeb!\n"); jffs2_sum_disable_collecting(s); } @@ -920,76 +920,34 @@ void jffs2_rotate_lists(struct jffs2_sb_info *c) x = count_list(&c->clean_list); if (x) { rotateby = pseudo_random % x; - D1(printk(KERN_DEBUG "Rotating clean_list by %d\n", rotateby)); - rotate_list((&c->clean_list), rotateby); - - D1(printk(KERN_DEBUG "Erase block at front of clean_list is at %08x\n", - list_entry(c->clean_list.next, struct jffs2_eraseblock, list)->offset)); - } else { - D1(printk(KERN_DEBUG "Not rotating empty clean_list\n")); } x = count_list(&c->very_dirty_list); if (x) { rotateby = pseudo_random % x; - D1(printk(KERN_DEBUG "Rotating very_dirty_list by %d\n", rotateby)); - rotate_list((&c->very_dirty_list), rotateby); - - D1(printk(KERN_DEBUG "Erase block at front of very_dirty_list is at %08x\n", - list_entry(c->very_dirty_list.next, struct jffs2_eraseblock, list)->offset)); - } else { - D1(printk(KERN_DEBUG "Not rotating empty very_dirty_list\n")); } x = count_list(&c->dirty_list); if (x) { rotateby = pseudo_random % x; - D1(printk(KERN_DEBUG "Rotating dirty_list by %d\n", rotateby)); - rotate_list((&c->dirty_list), rotateby); - - D1(printk(KERN_DEBUG "Erase block at front of dirty_list is at %08x\n", - list_entry(c->dirty_list.next, struct jffs2_eraseblock, list)->offset)); - } else { - D1(printk(KERN_DEBUG "Not rotating empty dirty_list\n")); } x = count_list(&c->erasable_list); if (x) { rotateby = pseudo_random % x; - D1(printk(KERN_DEBUG "Rotating erasable_list by %d\n", rotateby)); - rotate_list((&c->erasable_list), rotateby); - - D1(printk(KERN_DEBUG "Erase block at front of erasable_list is at %08x\n", - list_entry(c->erasable_list.next, struct jffs2_eraseblock, list)->offset)); - } else { - D1(printk(KERN_DEBUG "Not rotating empty erasable_list\n")); } if (c->nr_erasing_blocks) { rotateby = pseudo_random % c->nr_erasing_blocks; - D1(printk(KERN_DEBUG "Rotating erase_pending_list by %d\n", rotateby)); - rotate_list((&c->erase_pending_list), rotateby); - - D1(printk(KERN_DEBUG "Erase block at front of erase_pending_list is at %08x\n", - list_entry(c->erase_pending_list.next, struct jffs2_eraseblock, list)->offset)); - } else { - D1(printk(KERN_DEBUG "Not rotating empty erase_pending_list\n")); } if (c->nr_free_blocks) { rotateby = pseudo_random % c->nr_free_blocks; - D1(printk(KERN_DEBUG "Rotating free_list by %d\n", rotateby)); - rotate_list((&c->free_list), rotateby); - - D1(printk(KERN_DEBUG "Erase block at front of free_list is at %08x\n", - list_entry(c->free_list.next, struct jffs2_eraseblock, list)->offset)); - } else { - D1(printk(KERN_DEBUG "Not rotating empty free_list\n")); } } diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index cb5dd8f11e73..1ebc81e4477d 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c @@ -8,7 +8,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: summary.c,v 1.1 2005/09/07 08:34:54 havasi Exp $ + * $Id: summary.c,v 1.3 2005/09/21 14:43:07 dedekind Exp $ * */ @@ -38,17 +38,18 @@ int jffs2_sum_init(struct jffs2_sb_info *c) if (!c->summary->sum_buf) { JFFS2_WARNING("Can't allocate buffer for writing out summary information!\n"); + kfree(c->summary); return -ENOMEM; } - JFFS2_DBG_SUMMARY("returned succesfully\n"); + dbg_summary("returned succesfully\n"); return 0; } void jffs2_sum_exit(struct jffs2_sb_info *c) { - JFFS2_DBG_SUMMARY("called\n"); + dbg_summary("called\n"); jffs2_sum_disable_collecting(c->summary); @@ -71,13 +72,13 @@ static int jffs2_sum_add_mem(struct jffs2_summary *s, union jffs2_sum_mem *item) case JFFS2_NODETYPE_INODE: s->sum_size += JFFS2_SUMMARY_INODE_SIZE; s->sum_num++; - JFFS2_DBG_SUMMARY("inode (%u) added to summary\n", + dbg_summary("inode (%u) added to summary\n", je32_to_cpu(item->i.inode)); break; case JFFS2_NODETYPE_DIRENT: s->sum_size += JFFS2_SUMMARY_DIRENT_SIZE(item->d.nsize); s->sum_num++; - JFFS2_DBG_SUMMARY("dirent (%u) added to summary\n", + dbg_summary("dirent (%u) added to summary\n", je32_to_cpu(item->d.ino)); break; default: @@ -93,7 +94,7 @@ static int jffs2_sum_add_mem(struct jffs2_summary *s, union jffs2_sum_mem *item) int jffs2_sum_add_padding_mem(struct jffs2_summary *s, uint32_t size) { - JFFS2_DBG_SUMMARY("called with %u\n", size); + dbg_summary("called with %u\n", size); s->sum_padded += size; return 0; } @@ -147,7 +148,7 @@ static void jffs2_sum_clean_collected(struct jffs2_summary *s) union jffs2_sum_mem *temp; if (!s->sum_list_head) { - JFFS2_DBG_SUMMARY("already empty\n"); + dbg_summary("already empty\n"); } while (s->sum_list_head) { temp = s->sum_list_head; @@ -161,14 +162,14 @@ static void jffs2_sum_clean_collected(struct jffs2_summary *s) void jffs2_sum_reset_collected(struct jffs2_summary *s) { - JFFS2_DBG_SUMMARY("called\n"); + dbg_summary("called\n"); jffs2_sum_clean_collected(s); s->sum_size = 0; } void jffs2_sum_disable_collecting(struct jffs2_summary *s) { - JFFS2_DBG_SUMMARY("called\n"); + dbg_summary("called\n"); jffs2_sum_clean_collected(s); s->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; } @@ -182,7 +183,7 @@ int jffs2_sum_is_disabled(struct jffs2_summary *s) void jffs2_sum_move_collected(struct jffs2_sb_info *c, struct jffs2_summary *s) { - JFFS2_DBG_SUMMARY("oldsize=0x%x oldnum=%u => newsize=0x%x newnum=%u\n", + dbg_summary("oldsize=0x%x oldnum=%u => newsize=0x%x newnum=%u\n", c->summary->sum_size, c->summary->sum_num, s->sum_size, s->sum_num); @@ -260,16 +261,16 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs, } case JFFS2_NODETYPE_PADDING: - JFFS2_DBG_SUMMARY("node PADDING\n"); + dbg_summary("node PADDING\n"); c->summary->sum_padded += je32_to_cpu(node->u.totlen); break; case JFFS2_NODETYPE_CLEANMARKER: - JFFS2_DBG_SUMMARY("node CLEANMARKER\n"); + dbg_summary("node CLEANMARKER\n"); break; case JFFS2_NODETYPE_SUMMARY: - JFFS2_DBG_SUMMARY("node SUMMARY\n"); + dbg_summary("node SUMMARY\n"); break; default: @@ -302,7 +303,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras sp = summary->sum; for (i=0; isum_num); i++) { - JFFS2_DBG_SUMMARY("processing summary index %d\n", i); + dbg_summary("processing summary index %d\n", i); switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) { case JFFS2_NODETYPE_INODE: { @@ -311,7 +312,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras ino = je32_to_cpu(spi->inode); - JFFS2_DBG_SUMMARY("Inode at 0x%08x\n", + dbg_summary("Inode at 0x%08x\n", jeb->offset + je32_to_cpu(spi->offset)); raw = jffs2_alloc_raw_node_ref(); @@ -353,7 +354,7 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras struct jffs2_sum_dirent_flash *spd; spd = sp; - JFFS2_DBG_SUMMARY("Dirent at 0x%08x\n", + dbg_summary("Dirent at 0x%08x\n", jeb->offset + je32_to_cpu(spd->offset)); fd = jffs2_alloc_full_dirent(spd->nsize+1); @@ -434,7 +435,7 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb sumsize = c->sector_size - ofs; ofs += jeb->offset; - JFFS2_DBG_SUMMARY("summary found for 0x%08x at 0x%08x (0x%x bytes)\n", + dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n", jeb->offset, ofs, sumsize); summary = kmalloc(sumsize, GFP_KERNEL); @@ -457,40 +458,40 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb crc = crc32(0, &crcnode, sizeof(crcnode)-4); if (je32_to_cpu(summary->hdr_crc) != crc) { - JFFS2_DBG_SUMMARY("Summary node header is corrupt (bad CRC or " + dbg_summary("Summary node header is corrupt (bad CRC or " "no summary at all)\n"); goto crc_err; } if (je32_to_cpu(summary->totlen) != sumsize) { - JFFS2_DBG_SUMMARY("Summary node is corrupt (wrong erasesize?)\n"); + dbg_summary("Summary node is corrupt (wrong erasesize?)\n"); goto crc_err; } crc = crc32(0, summary, sizeof(struct jffs2_summary_node)-8); if (je32_to_cpu(summary->node_crc) != crc) { - JFFS2_DBG_SUMMARY("Summary node is corrupt (bad CRC)\n"); + dbg_summary("Summary node is corrupt (bad CRC)\n"); goto crc_err; } crc = crc32(0, summary->sum, sumsize - sizeof(struct jffs2_summary_node)); if (je32_to_cpu(summary->sum_crc) != crc) { - JFFS2_DBG_SUMMARY("Summary node data is corrupt (bad CRC)\n"); + dbg_summary("Summary node data is corrupt (bad CRC)\n"); goto crc_err; } if ( je32_to_cpu(summary->cln_mkr) ) { - JFFS2_DBG_SUMMARY("Summary : CLEANMARKER node \n"); + dbg_summary("Summary : CLEANMARKER node \n"); if (je32_to_cpu(summary->cln_mkr) != c->cleanmarker_size) { - JFFS2_DBG_SUMMARY("CLEANMARKER node has totlen 0x%x != normal 0x%x\n", + dbg_summary("CLEANMARKER node has totlen 0x%x != normal 0x%x\n", je32_to_cpu(summary->cln_mkr), c->cleanmarker_size); UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr))); } else if (jeb->first_node) { - JFFS2_DBG_SUMMARY("CLEANMARKER node not first node in block " + dbg_summary("CLEANMARKER node not first node in block " "(0x%08x)\n", jeb->offset); UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr))); } else { @@ -644,7 +645,7 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock vecs[1].iov_base = c->summary->sum_buf; vecs[1].iov_len = datasize; - JFFS2_DBG_SUMMARY("JFFS2: writing out data to flash to pos : 0x%08x\n", + dbg_summary("JFFS2: writing out data to flash to pos : 0x%08x\n", jeb->offset + c->sector_size - jeb->free_size); spin_unlock(&c->erase_completion_lock); @@ -674,7 +675,7 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) int datasize, infosize, padsize, ret; struct jffs2_eraseblock *jeb; - JFFS2_DBG_SUMMARY("called\n"); + dbg_summary("called\n"); jeb = c->nextblock; diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 86860dbc670c..11e05bc014f1 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -9,7 +9,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: wbuf.c,v 1.98 2005/09/07 08:34:55 havasi Exp $ + * $Id: wbuf.c,v 1.99 2005/09/21 16:11:04 dedekind Exp $ * */ @@ -33,9 +33,6 @@ static unsigned char *brokenbuf; /* max. erase failures before we mark a block bad */ #define MAX_ERASE_FAILURES 2 -/* two seconds timeout for timed wbuf-flushing */ -#define WBUF_FLUSH_TIMEOUT 2 * HZ - struct jffs2_inodirty { uint32_t ino; struct jffs2_inodirty *next; diff --git a/include/linux/jffs2_fs_sb.h b/include/linux/jffs2_fs_sb.h index 5087612ed9ac..fdc445b49e19 100644 --- a/include/linux/jffs2_fs_sb.h +++ b/include/linux/jffs2_fs_sb.h @@ -1,4 +1,4 @@ -/* $Id: jffs2_fs_sb.h,v 1.53 2005/09/07 08:34:56 havasi Exp $ */ +/* $Id: jffs2_fs_sb.h,v 1.54 2005/09/21 13:37:34 dedekind Exp $ */ #ifndef _JFFS2_FS_SB #define _JFFS2_FS_SB @@ -95,12 +95,13 @@ struct jffs2_sb_info { to an obsoleted node. I don't like this. Alternatives welcomed. */ struct semaphore erase_free_sem; + uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */ + #ifdef CONFIG_JFFS2_FS_WRITEBUFFER /* Write-behind buffer for NAND flash */ unsigned char *wbuf; uint32_t wbuf_ofs; uint32_t wbuf_len; - uint32_t wbuf_pagesize; struct jffs2_inodirty *wbuf_inodes; struct rw_semaphore wbuf_sem; /* Protects the write buffer */ -- cgit v1.2.3 From 2bc9764c4837c6b7da540b7a2592ec02f9a14e47 Mon Sep 17 00:00:00 2001 From: Ferenc Havasi Date: Mon, 26 Sep 2005 12:37:25 +0100 Subject: [JFFS2] Rename jffs2_summary_node to jffs2_raw_summary Signed-off-by: Ferenc Havasi Signed-off-by: Thomas Gleixner --- fs/jffs2/summary.c | 14 +++++++------- fs/jffs2/summary.h | 4 ++-- include/linux/jffs2.h | 12 +++++++----- 3 files changed, 16 insertions(+), 14 deletions(-) (limited to 'include/linux') diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index 1ebc81e4477d..308251266c6c 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c @@ -8,7 +8,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: summary.c,v 1.3 2005/09/21 14:43:07 dedekind Exp $ + * $Id: summary.c,v 1.4 2005/09/26 11:37:21 havasi Exp $ * */ @@ -292,7 +292,7 @@ no_mem: /* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, - struct jffs2_summary_node *summary, uint32_t *pseudo_random) + struct jffs2_raw_summary *summary, uint32_t *pseudo_random) { struct jffs2_raw_node_ref *raw; struct jffs2_inode_cache *ic; @@ -428,7 +428,7 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb { struct jffs2_unknown_node crcnode; struct jffs2_raw_node_ref *cache_ref; - struct jffs2_summary_node *summary; + struct jffs2_raw_summary *summary; int ret, sumsize; uint32_t crc; @@ -468,14 +468,14 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb goto crc_err; } - crc = crc32(0, summary, sizeof(struct jffs2_summary_node)-8); + crc = crc32(0, summary, sizeof(struct jffs2_raw_summary)-8); if (je32_to_cpu(summary->node_crc) != crc) { dbg_summary("Summary node is corrupt (bad CRC)\n"); goto crc_err; } - crc = crc32(0, summary->sum, sumsize - sizeof(struct jffs2_summary_node)); + crc = crc32(0, summary->sum, sumsize - sizeof(struct jffs2_raw_summary)); if (je32_to_cpu(summary->sum_crc) != crc) { dbg_summary("Summary node data is corrupt (bad CRC)\n"); @@ -560,7 +560,7 @@ crc_err: static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t infosize, uint32_t datasize, int padsize) { - struct jffs2_summary_node isum; + struct jffs2_raw_summary isum; union jffs2_sum_mem *temp; struct jffs2_sum_marker *sm; struct kvec vecs[2]; @@ -685,7 +685,7 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) } datasize = c->summary->sum_size + sizeof(struct jffs2_sum_marker); - infosize = sizeof(struct jffs2_summary_node) + datasize; + infosize = sizeof(struct jffs2_raw_summary) + datasize; padsize = jeb->free_size - infosize; infosize += padsize; datasize += padsize; diff --git a/fs/jffs2/summary.h b/fs/jffs2/summary.h index e6b0a69acbd4..b7a678be1709 100644 --- a/fs/jffs2/summary.h +++ b/fs/jffs2/summary.h @@ -8,7 +8,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: summary.h,v 1.1 2005/09/07 08:34:54 havasi Exp $ + * $Id: summary.h,v 1.2 2005/09/26 11:37:21 havasi Exp $ * */ @@ -142,7 +142,7 @@ struct jffs2_sum_marker jint32_t magic; /* == JFFS2_SUM_MAGIC */ }; -#define JFFS2_SUMMARY_FRAME_SIZE (sizeof(struct jffs2_summary_node) + sizeof(struct jffs2_sum_marker)) +#define JFFS2_SUMMARY_FRAME_SIZE (sizeof(struct jffs2_raw_summary) + sizeof(struct jffs2_sum_marker)) #ifdef CONFIG_JFFS2_SUMMARY /* SUMMARY SUPPORT ENABLED */ diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h index acb51a3669a2..2788880368c4 100644 --- a/include/linux/jffs2.h +++ b/include/linux/jffs2.h @@ -8,7 +8,7 @@ * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * - * $Id: jffs2.h,v 1.37 2005/09/07 08:34:55 havasi Exp $ + * $Id: jffs2.h,v 1.38 2005/09/26 11:37:23 havasi Exp $ * */ @@ -151,9 +151,10 @@ struct jffs2_raw_inode uint8_t data[0]; } __attribute__((packed)); -struct jffs2_summary_node{ +struct jffs2_raw_summary +{ jint16_t magic; - jint16_t nodetype; /* = JFFS2_NODETYPE_INODE_SUM */ + jint16_t nodetype; /* = JFFS2_NODETYPE_SUMMARY */ jint32_t totlen; jint32_t hdr_crc; jint32_t sum_num; /* number of sum entries*/ @@ -164,11 +165,12 @@ struct jffs2_summary_node{ jint32_t sum[0]; /* inode summary info */ } __attribute__((packed)); -union jffs2_node_union { +union jffs2_node_union +{ struct jffs2_raw_inode i; struct jffs2_raw_dirent d; + struct jffs2_raw_summary s; struct jffs2_unknown_node u; - struct jffs2_summary_node s; }; #endif /* __LINUX_JFFS2_H__ */ -- cgit v1.2.3 From 87590e26ff4e7d57dfdaa81780b1b0d9e9970a4c Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Tue, 27 Sep 2005 11:26:39 +0100 Subject: [MTD] OneNAND: Add missing files Simple bad block table source and header files Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/onenand_bbt.c | 246 ++++++++++++++++++++++++++++++++++++++ include/linux/mtd/bbm.h | 122 +++++++++++++++++++ 2 files changed, 368 insertions(+) create mode 100644 drivers/mtd/onenand/onenand_bbt.c create mode 100644 include/linux/mtd/bbm.h (limited to 'include/linux') diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c new file mode 100644 index 000000000000..f40190f499e1 --- /dev/null +++ b/drivers/mtd/onenand/onenand_bbt.c @@ -0,0 +1,246 @@ +/* + * linux/drivers/mtd/onenand/onenand_bbt.c + * + * Bad Block Table support for the OneNAND driver + * + * Copyright(c) 2005 Samsung Electronics + * Kyungmin Park + * + * Derived from nand_bbt.c + * + * TODO: + * Split BBT core and chip specific BBT. + */ + +#include +#include +#include +#include + +/** + * check_short_pattern - [GENERIC] check if a pattern is in the buffer + * @param buf the buffer to search + * @param len the length of buffer to search + * @param paglen the pagelength + * @param td search pattern descriptor + * + * Check for a pattern at the given place. Used to search bad block + * tables and good / bad block identifiers. Same as check_pattern, but + * no optional empty check and the pattern is expected to start + * at offset 0. + * + */ +static int check_short_pattern(uint8_t *buf, int len, int paglen, struct nand_bbt_descr *td) +{ + int i; + uint8_t *p = buf; + + /* Compare the pattern */ + for (i = 0; i < td->len; i++) { + if (p[i] != td->pattern[i]) + return -1; + } + return 0; +} + +/** + * create_bbt - [GENERIC] Create a bad block table by scanning the device + * @param mtd MTD device structure + * @param buf temporary buffer + * @param bd descriptor for the good/bad block search pattern + * @param chip create the table for a specific chip, -1 read all chips. + * Applies only if NAND_BBT_PERCHIP option is set + * + * Create a bad block table by scanning the device + * for the given good/bad block identify pattern + */ +static int create_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr *bd, int chip) +{ + struct onenand_chip *this = mtd->priv; + struct bbm_info *bbm = this->bbm; + int i, j, numblocks, len, scanlen; + int startblock; + loff_t from; + size_t readlen, ooblen; + + printk(KERN_INFO "Scanning device for bad blocks\n"); + + len = 1; + + /* We need only read few bytes from the OOB area */ + scanlen = ooblen = 0; + readlen = bd->len; + + /* chip == -1 case only */ + /* Note that numblocks is 2 * (real numblocks) here; + * see i += 2 below as it makses shifting and masking less painful + */ + numblocks = mtd->size >> (bbm->bbt_erase_shift - 1); + startblock = 0; + from = 0; + + for (i = startblock; i < numblocks; ) { + int ret; + + for (j = 0; j < len; j++) { + size_t retlen; + + /* No need to read pages fully, + * just read required OOB bytes */ + ret = mtd->read_oob(mtd, from + j * mtd->oobblock + bd->offs, + readlen, &retlen, &buf[0]); + + if (ret) + return ret; + + if (check_short_pattern(&buf[j * scanlen], scanlen, mtd->oobblock, bd)) { + bbm->bbt[i >> 3] |= 0x03 << (i & 0x6); + printk(KERN_WARNING "Bad eraseblock %d at 0x%08x\n", + i >> 1, (unsigned int) from); + break; + } + } + i += 2; + from += (1 << bbm->bbt_erase_shift); + } + + return 0; +} + + +/** + * onenand_memory_bbt - [GENERIC] create a memory based bad block table + * @param mtd MTD device structure + * @param bd descriptor for the good/bad block search pattern + * + * The function creates a memory based bbt by scanning the device + * for manufacturer / software marked good / bad blocks + */ +static inline int onenand_memory_bbt (struct mtd_info *mtd, struct nand_bbt_descr *bd) +{ + unsigned char data_buf[MAX_ONENAND_PAGESIZE]; + + bd->options &= ~NAND_BBT_SCANEMPTY; + return create_bbt(mtd, data_buf, bd, -1); +} + +/** + * onenand_isbad_bbt - [OneNAND Interface] Check if a block is bad + * @param mtd MTD device structure + * @param offs offset in the device + * @param allowbbt allow access to bad block table region + */ +static int onenand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt) +{ + struct onenand_chip *this = mtd->priv; + struct bbm_info *bbm = this->bbm; + int block; + uint8_t res; + + /* Get block number * 2 */ + block = (int) (offs >> (bbm->bbt_erase_shift - 1)); + res = (bbm->bbt[block >> 3] >> (block & 0x06)) & 0x03; + + DEBUG(MTD_DEBUG_LEVEL2, "onenand_isbad_bbt: bbt info for offs 0x%08x: (block %d) 0x%02x\n", + (unsigned int) offs, block >> 1, res); + + switch ((int) res) { + case 0x00: return 0; + case 0x01: return 1; + case 0x02: return allowbbt ? 0 : 1; + } + + return 1; +} + +/** + * onenand_scan_bbt - [OneNAND Interface] scan, find, read and maybe create bad block table(s) + * @param mtd MTD device structure + * @param bd descriptor for the good/bad block search pattern + * + * The function checks, if a bad block table(s) is/are already + * available. If not it scans the device for manufacturer + * marked good / bad blocks and writes the bad block table(s) to + * the selected place. + * + * The bad block table memory is allocated here. It must be freed + * by calling the onenand_free_bbt function. + * + */ +int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd) +{ + struct onenand_chip *this = mtd->priv; + struct bbm_info *bbm = this->bbm; + int len, ret = 0; + + len = mtd->size >> (this->erase_shift + 2); + /* Allocate memory (2bit per block) */ + bbm->bbt = kmalloc(len, GFP_KERNEL); + if (!bbm->bbt) { + printk(KERN_ERR "onenand_scan_bbt: Out of memory\n"); + return -ENOMEM; + } + /* Clear the memory bad block table */ + memset(bbm->bbt, 0x00, len); + + /* Set the bad block position */ + bbm->badblockpos = ONENAND_BADBLOCK_POS; + + /* Set erase shift */ + bbm->bbt_erase_shift = this->erase_shift; + + if (!bbm->isbad_bbt) + bbm->isbad_bbt = onenand_isbad_bbt; + + /* Scan the device to build a memory based bad block table */ + if ((ret = onenand_memory_bbt(mtd, bd))) { + printk(KERN_ERR "onenand_scan_bbt: Can't scan flash and build the RAM-based BBT\n"); + kfree(bbm->bbt); + bbm->bbt = NULL; + } + + return ret; +} + +/* + * Define some generic bad / good block scan pattern which are used + * while scanning a device for factory marked good / bad blocks. + */ +static uint8_t scan_ff_pattern[] = { 0xff, 0xff }; + +static struct nand_bbt_descr largepage_memorybased = { + .options = 0, + .offs = 0, + .len = 2, + .pattern = scan_ff_pattern, +}; + +/** + * onenand_default_bbt - [OneNAND Interface] Select a default bad block table for the device + * @param mtd MTD device structure + * + * This function selects the default bad block table + * support for the device and calls the onenand_scan_bbt function + */ +int onenand_default_bbt(struct mtd_info *mtd) +{ + struct onenand_chip *this = mtd->priv; + struct bbm_info *bbm; + + this->bbm = kmalloc(sizeof(struct bbm_info), GFP_KERNEL); + if (!this->bbm) + return -ENOMEM; + + bbm = this->bbm; + + memset(bbm, 0, sizeof(struct bbm_info)); + + /* 1KB page has same configuration as 2KB page */ + if (!bbm->badblock_pattern) + bbm->badblock_pattern = &largepage_memorybased; + + return onenand_scan_bbt(mtd, bbm->badblock_pattern); +} + +EXPORT_SYMBOL(onenand_scan_bbt); +EXPORT_SYMBOL(onenand_default_bbt); diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h new file mode 100644 index 000000000000..92b42cb7ed2e --- /dev/null +++ b/include/linux/mtd/bbm.h @@ -0,0 +1,122 @@ +/* + * linux/include/linux/mtd/bbm.h + * + * NAND family Bad Block Management (BBM) header file + * - Bad Block Table (BBT) implementation + * + * Copyright (c) 2005 Samsung Electronics + * Kyungmin Park + * + * Copyright (c) 2000-2005 + * Thomas Gleixner + * + */ +#ifndef __LINUX_MTD_BBM_H +#define __LINUX_MTD_BBM_H + +/* The maximum number of NAND chips in an array */ +#define NAND_MAX_CHIPS 8 + +/** + * struct nand_bbt_descr - bad block table descriptor + * @param options options for this descriptor + * @param pages the page(s) where we find the bbt, used with + * option BBT_ABSPAGE when bbt is searched, + * then we store the found bbts pages here. + * Its an array and supports up to 8 chips now + * @param offs offset of the pattern in the oob area of the page + * @param veroffs offset of the bbt version counter in the oob are of the page + * @param version version read from the bbt page during scan + * @param len length of the pattern, if 0 no pattern check is performed + * @param maxblocks maximum number of blocks to search for a bbt. This number of + * blocks is reserved at the end of the device + * where the tables are written. + * @param reserved_block_code if non-0, this pattern denotes a reserved + * (rather than bad) block in the stored bbt + * @param pattern pattern to identify bad block table or factory marked + * good / bad blocks, can be NULL, if len = 0 + * + * Descriptor for the bad block table marker and the descriptor for the + * pattern which identifies good and bad blocks. The assumption is made + * that the pattern and the version count are always located in the oob area + * of the first block. + */ +struct nand_bbt_descr { + int options; + int pages[NAND_MAX_CHIPS]; + int offs; + int veroffs; + uint8_t version[NAND_MAX_CHIPS]; + int len; + int maxblocks; + int reserved_block_code; + uint8_t *pattern; +}; + +/* Options for the bad block table descriptors */ + +/* The number of bits used per block in the bbt on the device */ +#define NAND_BBT_NRBITS_MSK 0x0000000F +#define NAND_BBT_1BIT 0x00000001 +#define NAND_BBT_2BIT 0x00000002 +#define NAND_BBT_4BIT 0x00000004 +#define NAND_BBT_8BIT 0x00000008 +/* The bad block table is in the last good block of the device */ +#define NAND_BBT_LASTBLOCK 0x00000010 +/* The bbt is at the given page, else we must scan for the bbt */ +#define NAND_BBT_ABSPAGE 0x00000020 +/* The bbt is at the given page, else we must scan for the bbt */ +#define NAND_BBT_SEARCH 0x00000040 +/* bbt is stored per chip on multichip devices */ +#define NAND_BBT_PERCHIP 0x00000080 +/* bbt has a version counter at offset veroffs */ +#define NAND_BBT_VERSION 0x00000100 +/* Create a bbt if none axists */ +#define NAND_BBT_CREATE 0x00000200 +/* Search good / bad pattern through all pages of a block */ +#define NAND_BBT_SCANALLPAGES 0x00000400 +/* Scan block empty during good / bad block scan */ +#define NAND_BBT_SCANEMPTY 0x00000800 +/* Write bbt if neccecary */ +#define NAND_BBT_WRITE 0x00001000 +/* Read and write back block contents when writing bbt */ +#define NAND_BBT_SAVECONTENT 0x00002000 +/* Search good / bad pattern on the first and the second page */ +#define NAND_BBT_SCAN2NDPAGE 0x00004000 + +/* The maximum number of blocks to scan for a bbt */ +#define NAND_BBT_SCAN_MAXBLOCKS 4 + +/* + * Constants for oob configuration + */ +#define ONENAND_BADBLOCK_POS 0 + +/** + * struct bbt_info - [GENERIC] Bad Block Table data structure + * @param bbt_erase_shift [INTERN] number of address bits in a bbt entry + * @param badblockpos [INTERN] position of the bad block marker in the oob area + * @param bbt [INTERN] bad block table pointer + * @param badblock_pattern [REPLACEABLE] bad block scan pattern used for initial bad block scan + * @param priv [OPTIONAL] pointer to private bbm date + */ +struct bbm_info { + int bbt_erase_shift; + int badblockpos; + int options; + + uint8_t *bbt; + + int (*isbad_bbt)(struct mtd_info *mtd, loff_t ofs, int allowbbt); + + /* TODO Add more NAND specific fileds */ + struct nand_bbt_descr *badblock_pattern; + + void *priv; +}; + +/* OneNAND BBT interface */ +extern int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd); +extern int onenand_default_bbt(struct mtd_info *mtd); + +#endif /* __LINUX_MTD_BBM_H */ -- cgit v1.2.3 From a41371eb6d9b368e53867cd85156f07371e9f72f Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Thu, 29 Sep 2005 03:55:31 +0100 Subject: [MTD] OneNAND: Power Management (PM) support Add suspend/resume Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/onenand_base.c | 36 +++++++++++++++++++++++++++++++++--- include/linux/mtd/onenand.h | 1 + 2 files changed, 34 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 75d757882697..a002d4025b29 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -505,7 +505,7 @@ static int onenand_update_bufferram(struct mtd_info *mtd, loff_t addr, * * Get the device and lock it for exclusive access */ -static void onenand_get_device(struct mtd_info *mtd, int new_state) +static int onenand_get_device(struct mtd_info *mtd, int new_state) { struct onenand_chip *this = mtd->priv; DECLARE_WAITQUEUE(wait, current); @@ -520,12 +520,18 @@ static void onenand_get_device(struct mtd_info *mtd, int new_state) spin_unlock(&this->chip_lock); break; } + if (new_state == FL_PM_SUSPENDED) { + spin_unlock(&this->chip_lock); + return (this->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN; + } set_current_state(TASK_UNINTERRUPTIBLE); add_wait_queue(&this->wq, &wait); spin_unlock(&this->chip_lock); schedule(); remove_wait_queue(&this->wq, &wait); } + + return 0; } /** @@ -1440,6 +1446,30 @@ static int onenand_probe(struct mtd_info *mtd) return 0; } +/** + * onenand_suspend - [MTD Interface] Suspend the OneNAND flash + * @param mtd MTD device structure + */ +static int onenand_suspend(struct mtd_info *mtd) +{ + return onenand_get_device(mtd, FL_PM_SUSPENDED); +} + +/** + * onenand_resume - [MTD Interface] Resume the OneNAND flash + * @param mtd MTD device structure + */ +static void onenand_resume(struct mtd_info *mtd) +{ + struct onenand_chip *this = mtd->priv; + + if (this->state == FL_PM_SUSPENDED) + onenand_release_device(mtd); + else + printk(KERN_ERR "resume() called for the chip which is not" + "in suspended state\n"); +} + /** * onenand_scan - [OneNAND Interface] Scan for the OneNAND device @@ -1527,8 +1557,8 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) mtd->sync = onenand_sync; mtd->lock = NULL; mtd->unlock = onenand_unlock; - mtd->suspend = NULL; - mtd->resume = NULL; + mtd->suspend = onenand_suspend; + mtd->resume = onenand_resume; mtd->block_isbad = onenand_block_isbad; mtd->block_markbad = onenand_block_markbad; mtd->owner = THIS_MODULE; diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index 58023082320a..afaa6342aa7f 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -36,6 +36,7 @@ typedef enum { FL_SYNCING, FL_UNLOCKING, FL_LOCKING, + FL_PM_SUSPENDED, } onenand_state_t; /** -- cgit v1.2.3 From 83a368380e172c1b2e9fd6ec2a62e457684adf0c Mon Sep 17 00:00:00 2001 From: Kyungmin Park Date: Thu, 29 Sep 2005 04:53:16 +0100 Subject: [MTD] OneNAND: Enhanced support for DDP (Dual Densitiy Packages) Add density mask for better support of DDP chips. Signed-off-by: Kyungmin Park Signed-off-by: Thomas Gleixner --- drivers/mtd/onenand/onenand_base.c | 39 ++++++++++++++++++-------------------- include/linux/mtd/onenand.h | 1 + 2 files changed, 19 insertions(+), 21 deletions(-) (limited to 'include/linux') diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index a002d4025b29..99de2f055eb1 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -84,25 +84,23 @@ static void onenand_writew(unsigned short value, void __iomem *addr) /** * onenand_block_address - [DEFAULT] Get block address - * @param device the device id + * @param this onenand chip data structure * @param block the block * @return translated block address if DDP, otherwise same * * Setup Start Address 1 Register (F100h) */ -static int onenand_block_address(int device, int block) +static int onenand_block_address(struct onenand_chip *this, int block) { - if (device & ONENAND_DEVICE_IS_DDP) { + if (this->device_id & ONENAND_DEVICE_IS_DDP) { /* Device Flash Core select, NAND Flash Block Address */ - int dfs = 0, density, mask; + int dfs = 0; - density = device >> ONENAND_DEVICE_DENSITY_SHIFT; - mask = (1 << (density + 6)); - - if (block & mask) + if (block & this->density_mask) dfs = 1; - return (dfs << ONENAND_DDP_SHIFT) | (block & (mask - 1)); + return (dfs << ONENAND_DDP_SHIFT) | + (block & (this->density_mask - 1)); } return block; @@ -110,22 +108,19 @@ static int onenand_block_address(int device, int block) /** * onenand_bufferram_address - [DEFAULT] Get bufferram address - * @param device the device id + * @param this onenand chip data structure * @param block the block * @return set DBS value if DDP, otherwise 0 * * Setup Start Address 2 Register (F101h) for DDP */ -static int onenand_bufferram_address(int device, int block) +static int onenand_bufferram_address(struct onenand_chip *this, int block) { - if (device & ONENAND_DEVICE_IS_DDP) { + if (this->device_id & ONENAND_DEVICE_IS_DDP) { /* Device BufferRAM Select */ - int dbs = 0, density, mask; - - density = device >> ONENAND_DEVICE_DENSITY_SHIFT; - mask = (1 << (density + 6)); + int dbs = 0; - if (block & mask) + if (block & this->density_mask) dbs = 1; return (dbs << ONENAND_DDP_SHIFT); @@ -223,7 +218,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le /* NOTE: The setting order of the registers is very important! */ if (cmd == ONENAND_CMD_BUFFERRAM) { /* Select DataRAM for DDP */ - value = onenand_bufferram_address(this->device_id, block); + value = onenand_bufferram_address(this, block); this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); /* Switch to the next data buffer */ @@ -234,7 +229,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le if (block != -1) { /* Write 'DFS, FBA' of Flash */ - value = onenand_block_address(this->device_id, block); + value = onenand_block_address(this, block); this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); } @@ -263,7 +258,7 @@ static int onenand_command(struct mtd_info *mtd, int cmd, loff_t addr, size_t le if (readcmd) { /* Select DataRAM for DDP */ - value = onenand_bufferram_address(this->device_id, block); + value = onenand_bufferram_address(this, block); this->write_word(value, this->base + ONENAND_REG_START_ADDRESS2); } } @@ -1313,7 +1308,7 @@ static int onenand_unlock(struct mtd_info *mtd, loff_t ofs, size_t len) continue; /* Set block address for read block status */ - value = onenand_block_address(this->device_id, block); + value = onenand_block_address(this, block); this->write_word(value, this->base + ONENAND_REG_START_ADDRESS1); /* Check lock status */ @@ -1415,6 +1410,8 @@ static int onenand_probe(struct mtd_info *mtd) density = dev_id >> ONENAND_DEVICE_DENSITY_SHIFT; this->chipsize = (16 << density) << 20; + /* Set density mask. it is used for DDP */ + this->density_mask = (1 << (density + 6)); /* OneNAND page size & block size */ /* The data buffer size is equal to page size */ diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index afaa6342aa7f..d27fd12d096d 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -84,6 +84,7 @@ struct onenand_chip { void __iomem *base; unsigned int chipsize; unsigned int device_id; + unsigned int density_mask; unsigned int options; unsigned int erase_shift; -- cgit v1.2.3 From fb0258730ad554db531f12fc1c3d5a5234fe52a4 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Mon, 17 Oct 2005 22:03:19 +0100 Subject: [MTD] Don't let gcc inline functions marked __xipram If they get inlined into non __xipram functions we're screwed. Signed-off-by: Nicolas Pitre Signed-off-by: Thomas Gleixner --- include/linux/mtd/xip.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'include/linux') diff --git a/include/linux/mtd/xip.h b/include/linux/mtd/xip.h index 7b7deef6b180..863fa5a1d24e 100644 --- a/include/linux/mtd/xip.h +++ b/include/linux/mtd/xip.h @@ -12,7 +12,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * $Id: xip.h,v 1.2 2004/12/01 15:49:10 nico Exp $ + * $Id: xip.h,v 1.4 2005/10/17 21:03:16 nico Exp $ */ #ifndef __LINUX_MTD_XIP_H__ @@ -22,19 +22,19 @@ #ifdef CONFIG_MTD_XIP -/* - * Function that are modifying the flash state away from array mode must - * obviously not be running from flash. The __xipram is therefore marking - * those functions so they get relocated to ram. - */ -#define __xipram __attribute__ ((__section__ (".data"))) - /* * We really don't want gcc to guess anything. * We absolutely _need_ proper inlining. */ #include +/* + * Function that are modifying the flash state away from array mode must + * obviously not be running from flash. The __xipram is therefore marking + * those functions so they get relocated to ram. + */ +#define __xipram noinline __attribute__ ((__section__ (".data"))) + /* * Each architecture has to provide the following macros. They must access * the hardware directly and not rely on any other (XIP) functions since they -- cgit v1.2.3 From 193515d51ccb363165d6b09e9ba5c21089e34bad Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Mon, 7 Nov 2005 00:59:37 -0500 Subject: [libata] eliminate use of drivers/scsi/scsi.h compatibility header/defines --- drivers/scsi/ahci.c | 4 ++-- drivers/scsi/ata_piix.c | 3 +-- drivers/scsi/libata-core.c | 2 +- drivers/scsi/libata-scsi.c | 2 +- drivers/scsi/pdc_adma.c | 3 +-- drivers/scsi/sata_mv.c | 4 ++-- drivers/scsi/sata_nv.c | 3 +-- drivers/scsi/sata_promise.c | 4 ++-- drivers/scsi/sata_qstor.c | 3 +-- drivers/scsi/sata_sil.c | 3 +-- drivers/scsi/sata_sil24.c | 4 ++-- drivers/scsi/sata_sis.c | 3 +-- drivers/scsi/sata_svw.c | 3 +-- drivers/scsi/sata_sx4.c | 4 ++-- drivers/scsi/sata_uli.c | 3 +-- drivers/scsi/sata_via.c | 3 +-- drivers/scsi/sata_vsc.c | 3 +-- include/linux/libata.h | 6 +++--- 18 files changed, 25 insertions(+), 35 deletions(-) (limited to 'include/linux') diff --git a/drivers/scsi/ahci.c b/drivers/scsi/ahci.c index 4612312c0c2d..10c470e7d316 100644 --- a/drivers/scsi/ahci.c +++ b/drivers/scsi/ahci.c @@ -42,8 +42,8 @@ #include #include #include -#include "scsi.h" #include +#include #include #include @@ -196,7 +196,7 @@ static u8 ahci_check_status(struct ata_port *ap); static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); static void ahci_remove_one (struct pci_dev *pdev); -static Scsi_Host_Template ahci_sht = { +static struct scsi_host_template ahci_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c index 7f8aa1b552ce..a1bd8d95623c 100644 --- a/drivers/scsi/ata_piix.c +++ b/drivers/scsi/ata_piix.c @@ -46,7 +46,6 @@ #include #include #include -#include "scsi.h" #include #include @@ -128,7 +127,7 @@ static struct pci_driver piix_pci_driver = { .remove = ata_pci_remove_one, }; -static Scsi_Host_Template piix_sht = { +static struct scsi_host_template piix_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c index 1c1a7caf785e..98769a3d31ae 100644 --- a/drivers/scsi/libata-core.c +++ b/drivers/scsi/libata-core.c @@ -51,8 +51,8 @@ #include #include #include -#include "scsi.h" #include "scsi_priv.h" +#include #include #include #include diff --git a/drivers/scsi/libata-scsi.c b/drivers/scsi/libata-scsi.c index eb604b0a8990..38a895ebe826 100644 --- a/drivers/scsi/libata-scsi.c +++ b/drivers/scsi/libata-scsi.c @@ -37,9 +37,9 @@ #include #include #include -#include "scsi.h" #include #include +#include #include #include #include diff --git a/drivers/scsi/pdc_adma.c b/drivers/scsi/pdc_adma.c index a50588c60fab..78b4ff117af6 100644 --- a/drivers/scsi/pdc_adma.c +++ b/drivers/scsi/pdc_adma.c @@ -41,7 +41,6 @@ #include #include #include -#include "scsi.h" #include #include #include @@ -139,7 +138,7 @@ static u8 adma_bmdma_status(struct ata_port *ap); static void adma_irq_clear(struct ata_port *ap); static void adma_eng_timeout(struct ata_port *ap); -static Scsi_Host_Template adma_ata_sht = { +static struct scsi_host_template adma_ata_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_mv.c b/drivers/scsi/sata_mv.c index 0f469e3dabe2..93d55233af7b 100644 --- a/drivers/scsi/sata_mv.c +++ b/drivers/scsi/sata_mv.c @@ -30,8 +30,8 @@ #include #include #include -#include "scsi.h" #include +#include #include #include @@ -270,7 +270,7 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance, static void mv_eng_timeout(struct ata_port *ap); static int mv_init_one(struct pci_dev *pdev, const struct pci_device_id *ent); -static Scsi_Host_Template mv_sht = { +static struct scsi_host_template mv_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c index d573888eda76..37a4fae95ed4 100644 --- a/drivers/scsi/sata_nv.c +++ b/drivers/scsi/sata_nv.c @@ -62,7 +62,6 @@ #include #include #include -#include "scsi.h" #include #include @@ -219,7 +218,7 @@ static struct pci_driver nv_pci_driver = { .remove = ata_pci_remove_one, }; -static Scsi_Host_Template nv_sht = { +static struct scsi_host_template nv_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c index b41c977d6fab..9edc9d91efc3 100644 --- a/drivers/scsi/sata_promise.c +++ b/drivers/scsi/sata_promise.c @@ -39,8 +39,8 @@ #include #include #include -#include "scsi.h" #include +#include #include #include #include "sata_promise.h" @@ -94,7 +94,7 @@ static void pdc_irq_clear(struct ata_port *ap); static int pdc_qc_issue_prot(struct ata_queued_cmd *qc); -static Scsi_Host_Template pdc_ata_sht = { +static struct scsi_host_template pdc_ata_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_qstor.c b/drivers/scsi/sata_qstor.c index 65502c157a54..d274ab235781 100644 --- a/drivers/scsi/sata_qstor.c +++ b/drivers/scsi/sata_qstor.c @@ -36,7 +36,6 @@ #include #include #include -#include "scsi.h" #include #include #include @@ -128,7 +127,7 @@ static u8 qs_bmdma_status(struct ata_port *ap); static void qs_irq_clear(struct ata_port *ap); static void qs_eng_timeout(struct ata_port *ap); -static Scsi_Host_Template qs_ata_sht = { +static struct scsi_host_template qs_ata_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c index 435f7e0085ec..d0e3c3c6c25f 100644 --- a/drivers/scsi/sata_sil.c +++ b/drivers/scsi/sata_sil.c @@ -42,7 +42,6 @@ #include #include #include -#include "scsi.h" #include #include @@ -131,7 +130,7 @@ static struct pci_driver sil_pci_driver = { .remove = ata_pci_remove_one, }; -static Scsi_Host_Template sil_sht = { +static struct scsi_host_template sil_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index e6c8e89c226f..4682a50650b4 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c @@ -37,7 +37,7 @@ #include #include #include -#include "scsi.h" +#include #include #include @@ -255,7 +255,7 @@ static struct pci_driver sil24_pci_driver = { .remove = ata_pci_remove_one, /* safe? */ }; -static Scsi_Host_Template sil24_sht = { +static struct scsi_host_template sil24_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c index 42288be0e561..42d7c4e92501 100644 --- a/drivers/scsi/sata_sis.c +++ b/drivers/scsi/sata_sis.c @@ -39,7 +39,6 @@ #include #include #include -#include "scsi.h" #include #include @@ -83,7 +82,7 @@ static struct pci_driver sis_pci_driver = { .remove = ata_pci_remove_one, }; -static Scsi_Host_Template sis_sht = { +static struct scsi_host_template sis_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c index db615ff794d8..9895d1caefcf 100644 --- a/drivers/scsi/sata_svw.c +++ b/drivers/scsi/sata_svw.c @@ -45,7 +45,6 @@ #include #include #include -#include "scsi.h" #include #include @@ -284,7 +283,7 @@ static int k2_sata_proc_info(struct Scsi_Host *shost, char *page, char **start, #endif /* CONFIG_PPC_OF */ -static Scsi_Host_Template k2_sata_sht = { +static struct scsi_host_template k2_sata_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c index f859bbd681ed..d5a38784352b 100644 --- a/drivers/scsi/sata_sx4.c +++ b/drivers/scsi/sata_sx4.c @@ -39,8 +39,8 @@ #include #include #include -#include "scsi.h" #include +#include #include #include #include "sata_promise.h" @@ -177,7 +177,7 @@ static void pdc20621_irq_clear(struct ata_port *ap); static int pdc20621_qc_issue_prot(struct ata_queued_cmd *qc); -static Scsi_Host_Template pdc_sata_sht = { +static struct scsi_host_template pdc_sata_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_uli.c b/drivers/scsi/sata_uli.c index a5e245c098e1..cf0baaa4e045 100644 --- a/drivers/scsi/sata_uli.c +++ b/drivers/scsi/sata_uli.c @@ -33,7 +33,6 @@ #include #include #include -#include "scsi.h" #include #include @@ -71,7 +70,7 @@ static struct pci_driver uli_pci_driver = { .remove = ata_pci_remove_one, }; -static Scsi_Host_Template uli_sht = { +static struct scsi_host_template uli_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c index b3ecdbe400e9..ab19d2ba2a4b 100644 --- a/drivers/scsi/sata_via.c +++ b/drivers/scsi/sata_via.c @@ -42,7 +42,6 @@ #include #include #include -#include "scsi.h" #include #include #include @@ -90,7 +89,7 @@ static struct pci_driver svia_pci_driver = { .remove = ata_pci_remove_one, }; -static Scsi_Host_Template svia_sht = { +static struct scsi_host_template svia_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c index bb84ba0c7e83..ce8a2fd7da84 100644 --- a/drivers/scsi/sata_vsc.c +++ b/drivers/scsi/sata_vsc.c @@ -43,7 +43,6 @@ #include #include #include -#include "scsi.h" #include #include @@ -219,7 +218,7 @@ static irqreturn_t vsc_sata_interrupt (int irq, void *dev_instance, } -static Scsi_Host_Template vsc_sata_sht = { +static struct scsi_host_template vsc_sata_sht = { .module = THIS_MODULE, .name = DRV_NAME, .ioctl = ata_scsi_ioctl, diff --git a/include/linux/libata.h b/include/linux/libata.h index dcd17e7458ab..6f0752219f64 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -214,7 +214,7 @@ struct ata_probe_ent { struct list_head node; struct device *dev; const struct ata_port_operations *port_ops; - Scsi_Host_Template *sht; + struct scsi_host_template *sht; struct ata_ioports port[ATA_MAX_PORTS]; unsigned int n_ports; unsigned int hard_port_no; @@ -398,7 +398,7 @@ struct ata_port_operations { }; struct ata_port_info { - Scsi_Host_Template *sht; + struct scsi_host_template *sht; unsigned long host_flags; unsigned long pio_mask; unsigned long mwdma_mask; @@ -433,7 +433,7 @@ extern void ata_pci_remove_one (struct pci_dev *pdev); #endif /* CONFIG_PCI */ extern int ata_device_add(const struct ata_probe_ent *ent); extern void ata_host_set_remove(struct ata_host_set *host_set); -extern int ata_scsi_detect(Scsi_Host_Template *sht); +extern int ata_scsi_detect(struct scsi_host_template *sht); extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); extern int ata_scsi_error(struct Scsi_Host *host); -- cgit v1.2.3 From 182ec4eee397543101a6db8906ed88727d3f7e53 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Nov 2005 11:16:07 +0000 Subject: [JFFS2] Clean up trailing white spaces Signed-off-by: Thomas Gleixner --- fs/Kconfig | 10 +-- fs/jffs2/background.c | 4 +- fs/jffs2/build.c | 28 ++++---- fs/jffs2/compr.c | 28 ++++---- fs/jffs2/compr.h | 4 +- fs/jffs2/compr_rtime.c | 32 ++++----- fs/jffs2/compr_rubin.c | 37 +++++----- fs/jffs2/compr_rubin.h | 6 +- fs/jffs2/compr_zlib.c | 14 ++-- fs/jffs2/comprtest.c | 30 ++++---- fs/jffs2/debug.c | 30 ++++---- fs/jffs2/debug.h | 10 +-- fs/jffs2/dir.c | 74 +++++++++---------- fs/jffs2/erase.c | 28 ++++---- fs/jffs2/file.c | 20 +++--- fs/jffs2/fs.c | 56 +++++++-------- fs/jffs2/gc.c | 112 ++++++++++++++--------------- fs/jffs2/histo.h | 2 +- fs/jffs2/histo_mips.h | 2 +- fs/jffs2/ioctl.c | 6 +- fs/jffs2/malloc.c | 4 +- fs/jffs2/nodelist.c | 170 ++++++++++++++++++++++---------------------- fs/jffs2/nodelist.h | 26 +++---- fs/jffs2/nodemgmt.c | 58 +++++++-------- fs/jffs2/os-linux.h | 8 +-- fs/jffs2/read.c | 16 ++--- fs/jffs2/readinode.c | 84 +++++++++++----------- fs/jffs2/scan.c | 52 +++++++------- fs/jffs2/summary.c | 8 +-- fs/jffs2/super.c | 16 ++--- fs/jffs2/symlink.c | 8 +-- fs/jffs2/wbuf.c | 128 ++++++++++++++++----------------- fs/jffs2/write.c | 68 +++++++++--------- include/linux/jffs2.h | 12 ++-- include/linux/jffs2_fs_i.h | 4 +- include/linux/jffs2_fs_sb.h | 14 ++-- 36 files changed, 604 insertions(+), 605 deletions(-) (limited to 'include/linux') diff --git a/fs/Kconfig b/fs/Kconfig index 37d86c5072eb..660a0c04d6b9 100644 --- a/fs/Kconfig +++ b/fs/Kconfig @@ -1084,10 +1084,10 @@ config JFFS2_ZLIB default y help Zlib is designed to be a free, general-purpose, legally unencumbered, - lossless data-compression library for use on virtually any computer + lossless data-compression library for use on virtually any computer hardware and operating system. See for further information. - + Say 'Y' if unsure. config JFFS2_RTIME @@ -1109,7 +1109,7 @@ choice default JFFS2_CMODE_PRIORITY depends on JFFS2_FS help - You can set here the default compression mode of JFFS2 from + You can set here the default compression mode of JFFS2 from the available compression modes. Don't touch if unsure. config JFFS2_CMODE_NONE @@ -1120,13 +1120,13 @@ config JFFS2_CMODE_NONE config JFFS2_CMODE_PRIORITY bool "priority" help - Tries the compressors in a predefinied order and chooses the first + Tries the compressors in a predefinied order and chooses the first successful one. config JFFS2_CMODE_SIZE bool "size (EXPERIMENTAL)" help - Tries all compressors and chooses the one which has the smallest + Tries all compressors and chooses the one which has the smallest result. endchoice diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c index 8210ac16a368..7b77a9541125 100644 --- a/fs/jffs2/background.c +++ b/fs/jffs2/background.c @@ -51,7 +51,7 @@ int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c) D1(printk(KERN_DEBUG "JFFS2: Garbage collect thread is pid %d\n", pid)); wait_for_completion(&c->gc_thread_start); } - + return ret; } @@ -101,7 +101,7 @@ static int jffs2_garbage_collect_thread(void *_c) cond_resched(); - /* Put_super will send a SIGKILL and then wait on the sem. + /* Put_super will send a SIGKILL and then wait on the sem. */ while (signal_pending(current)) { siginfo_t info; diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index af6d2ec01366..fff108bb118b 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: build.c,v 1.84 2005/09/27 13:40:49 dedekind Exp $ + * $Id: build.c,v 1.85 2005/11/07 11:14:38 gleixner Exp $ * */ @@ -129,10 +129,10 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) for_each_inode(i, c, ic) { if (ic->nlink) continue; - + jffs2_build_remove_unlinked_inode(c, ic, &dead_fds); cond_resched(); - } + } dbg_fsbuild("pass 2a starting\n"); @@ -149,7 +149,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) dbg_fsbuild("pass 2a complete\n"); dbg_fsbuild("freeing temporary data structures\n"); - + /* Finally, we can scan again and free the dirent structs */ for_each_inode(i, c, ic) { while(ic->scan_dents) { @@ -161,7 +161,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) cond_resched(); } c->flags &= ~JFFS2_SB_FLAG_BUILDING; - + dbg_fsbuild("FS build complete\n"); /* Rotate the lists by some number to ensure wear levelling */ @@ -191,7 +191,7 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, struct jffs2_full_dirent *fd; dbg_fsbuild("removing ino #%u with nlink == zero.\n", ic->ino); - + raw = ic->nodes; while (raw != (void *)ic) { struct jffs2_raw_node_ref *next = raw->next_in_ino; @@ -220,7 +220,7 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, whinged = 1; dbg_fsbuild("removing child \"%s\", ino #%u\n", fd->name, fd->ino); - + child_ic = jffs2_get_ino_cache(c, fd->ino); if (!child_ic) { dbg_fsbuild("cannot remove child \"%s\", ino #%u, because it doesn't exist\n", @@ -229,11 +229,11 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, continue; } - /* Reduce nlink of the child. If it's now zero, stick it on the + /* Reduce nlink of the child. If it's now zero, stick it on the dead_fds list to be cleaned up later. Else just free the fd */ child_ic->nlink--; - + if (!child_ic->nlink) { dbg_fsbuild("inode #%u (\"%s\") has now got zero nlink, adding to dead_fds list.\n", fd->ino, fd->name); @@ -248,7 +248,7 @@ static void jffs2_build_remove_unlinked_inode(struct jffs2_sb_info *c, } /* - We don't delete the inocache from the hash list and free it yet. + We don't delete the inocache from the hash list and free it yet. The erase code will do that, when all the nodes are completely gone. */ } @@ -262,7 +262,7 @@ static void jffs2_calc_trigger_levels(struct jffs2_sb_info *c) because there's not enough free space... */ c->resv_blocks_deletion = 2; - /* Be conservative about how much space we need before we allow writes. + /* Be conservative about how much space we need before we allow writes. On top of that which is required for deletia, require an extra 2% of the medium to be available, for overhead caused by nodes being split across blocks, etc. */ @@ -277,7 +277,7 @@ static void jffs2_calc_trigger_levels(struct jffs2_sb_info *c) c->resv_blocks_gctrigger = c->resv_blocks_write + 1; - /* When do we allow garbage collection to merge nodes to make + /* When do we allow garbage collection to merge nodes to make long-term progress at the expense of short-term space exhaustion? */ c->resv_blocks_gcmerge = c->resv_blocks_deletion + 1; @@ -303,7 +303,7 @@ static void jffs2_calc_trigger_levels(struct jffs2_sb_info *c) c->resv_blocks_gcbad, c->resv_blocks_gcbad*c->sector_size/1024); dbg_fsbuild("Amount of dirty space required to GC: %d bytes\n", c->nospc_dirty_size); -} +} int jffs2_do_mount_fs(struct jffs2_sb_info *c) { @@ -355,7 +355,7 @@ int jffs2_do_mount_fs(struct jffs2_sb_info *c) #ifndef __ECOS if (jffs2_blocks_use_vmalloc(c)) vfree(c->blocks); - else + else #endif kfree(c->blocks); diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c index c9e54b97dba8..e7944e665b9f 100644 --- a/fs/jffs2/compr.c +++ b/fs/jffs2/compr.c @@ -9,7 +9,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: compr.c,v 1.45 2005/07/26 13:24:40 havasi Exp $ + * $Id: compr.c,v 1.46 2005/11/07 11:14:38 gleixner Exp $ * */ @@ -36,16 +36,16 @@ static uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_co * data. * * Returns: Lower byte to be stored with data indicating compression type used. - * Zero is used to show that the data could not be compressed - the + * Zero is used to show that the data could not be compressed - the * compressed version was actually larger than the original. * Upper byte will be used later. (soon) * * If the cdata buffer isn't large enough to hold all the uncompressed data, - * jffs2_compress should compress as much as will fit, and should set + * jffs2_compress should compress as much as will fit, and should set * *datalen accordingly to show the amount of data which were compressed. */ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - unsigned char *data_in, unsigned char **cpage_out, + unsigned char *data_in, unsigned char **cpage_out, uint32_t *datalen, uint32_t *cdatalen) { int ret = JFFS2_COMPR_NONE; @@ -164,7 +164,7 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, } int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - uint16_t comprtype, unsigned char *cdata_in, + uint16_t comprtype, unsigned char *cdata_in, unsigned char *data_out, uint32_t cdatalen, uint32_t datalen) { struct jffs2_compressor *this; @@ -298,7 +298,7 @@ char *jffs2_stats(void) act_buf += sprintf(act_buf,"JFFS2 compressor statistics:\n"); act_buf += sprintf(act_buf,"%10s ","none"); - act_buf += sprintf(act_buf,"compr: %d blocks (%d) decompr: %d blocks\n", none_stat_compr_blocks, + act_buf += sprintf(act_buf,"compr: %d blocks (%d) decompr: %d blocks\n", none_stat_compr_blocks, none_stat_compr_size, none_stat_decompr_blocks); spin_lock(&jffs2_compressor_list_lock); list_for_each_entry(this, &jffs2_compressor_list, list) { @@ -307,8 +307,8 @@ char *jffs2_stats(void) act_buf += sprintf(act_buf,"- "); else act_buf += sprintf(act_buf,"+ "); - act_buf += sprintf(act_buf,"compr: %d blocks (%d/%d) decompr: %d blocks ", this->stat_compr_blocks, - this->stat_compr_new_size, this->stat_compr_orig_size, + act_buf += sprintf(act_buf,"compr: %d blocks (%d/%d) decompr: %d blocks ", this->stat_compr_blocks, + this->stat_compr_new_size, this->stat_compr_orig_size, this->stat_decompr_blocks); act_buf += sprintf(act_buf,"\n"); } @@ -317,7 +317,7 @@ char *jffs2_stats(void) return buf; } -char *jffs2_get_compression_mode_name(void) +char *jffs2_get_compression_mode_name(void) { switch (jffs2_compression_mode) { case JFFS2_COMPR_MODE_NONE: @@ -330,7 +330,7 @@ char *jffs2_get_compression_mode_name(void) return "unkown"; } -int jffs2_set_compression_mode_name(const char *name) +int jffs2_set_compression_mode_name(const char *name) { if (!strcmp("none",name)) { jffs2_compression_mode = JFFS2_COMPR_MODE_NONE; @@ -355,7 +355,7 @@ static int jffs2_compressor_Xable(const char *name, int disabled) if (!strcmp(this->name, name)) { this->disabled = disabled; spin_unlock(&jffs2_compressor_list_lock); - return 0; + return 0; } } spin_unlock(&jffs2_compressor_list_lock); @@ -385,7 +385,7 @@ int jffs2_set_compressor_priority(const char *name, int priority) } } spin_unlock(&jffs2_compressor_list_lock); - printk(KERN_WARNING "JFFS2: compressor %s not found.\n",name); + printk(KERN_WARNING "JFFS2: compressor %s not found.\n",name); return 1; reinsert: /* list is sorted in the order of priority, so if @@ -412,7 +412,7 @@ void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig) kfree(comprbuf); } -int jffs2_compressors_init(void) +int jffs2_compressors_init(void) { /* Registering compressors */ #ifdef CONFIG_JFFS2_ZLIB @@ -440,7 +440,7 @@ int jffs2_compressors_init(void) return 0; } -int jffs2_compressors_exit(void) +int jffs2_compressors_exit(void) { /* Unregistering compressors */ #ifdef CONFIG_JFFS2_RUBIN diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h index 9ec6e37d3833..a77e830d85c5 100644 --- a/fs/jffs2/compr.h +++ b/fs/jffs2/compr.h @@ -4,10 +4,10 @@ * Copyright (C) 2004 Ferenc Havasi , * University of Szeged, Hungary * - * For licensing information, see the file 'LICENCE' in the + * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * - * $Id: compr.h,v 1.8 2005/07/26 13:24:40 havasi Exp $ + * $Id: compr.h,v 1.9 2005/11/07 11:14:38 gleixner Exp $ * */ diff --git a/fs/jffs2/compr_rtime.c b/fs/jffs2/compr_rtime.c index 393129418666..2eb1b7428d16 100644 --- a/fs/jffs2/compr_rtime.c +++ b/fs/jffs2/compr_rtime.c @@ -24,8 +24,8 @@ #include #include #include -#include -#include +#include +#include #include "compr.h" /* _compress returns the compressed size, -1 if bigger */ @@ -38,19 +38,19 @@ static int jffs2_rtime_compress(unsigned char *data_in, int outpos = 0; int pos=0; - memset(positions,0,sizeof(positions)); - + memset(positions,0,sizeof(positions)); + while (pos < (*sourcelen) && outpos <= (*dstlen)-2) { int backpos, runlen=0; unsigned char value; - + value = data_in[pos]; cpage_out[outpos++] = data_in[pos++]; - + backpos = positions[value]; positions[value]=pos; - + while ((backpos < pos) && (pos < (*sourcelen)) && (data_in[pos]==data_in[backpos++]) && (runlen<255)) { pos++; @@ -63,12 +63,12 @@ static int jffs2_rtime_compress(unsigned char *data_in, /* We failed */ return -1; } - + /* Tell the caller how much we managed to compress, and how much space it took */ *sourcelen = pos; *dstlen = outpos; return 0; -} +} static int jffs2_rtime_decompress(unsigned char *data_in, @@ -79,19 +79,19 @@ static int jffs2_rtime_decompress(unsigned char *data_in, short positions[256]; int outpos = 0; int pos=0; - - memset(positions,0,sizeof(positions)); - + + memset(positions,0,sizeof(positions)); + while (outpos= outpos) { @@ -101,12 +101,12 @@ static int jffs2_rtime_decompress(unsigned char *data_in, } } else { memcpy(&cpage_out[outpos],&cpage_out[backoffs],repeat); - outpos+=repeat; + outpos+=repeat; } } } return 0; -} +} static struct jffs2_compressor jffs2_rtime_comp = { .priority = JFFS2_RTIME_PRIORITY, diff --git a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c index 09422388fb96..e792e675d624 100644 --- a/fs/jffs2/compr_rubin.c +++ b/fs/jffs2/compr_rubin.c @@ -11,7 +11,6 @@ * */ - #include #include #include @@ -20,7 +19,7 @@ #include "compr.h" static void init_rubin(struct rubin_state *rs, int div, int *bits) -{ +{ int c; rs->q = 0; @@ -40,7 +39,7 @@ static int encode(struct rubin_state *rs, long A, long B, int symbol) while ((rs->q >= UPPER_BIT_RUBIN) || ((rs->p + rs->q) <= UPPER_BIT_RUBIN)) { rs->bit_number++; - + ret = pushbit(&rs->pp, (rs->q & UPPER_BIT_RUBIN) ? 1 : 0, 0); if (ret) return ret; @@ -68,7 +67,7 @@ static int encode(struct rubin_state *rs, long A, long B, int symbol) static void end_rubin(struct rubin_state *rs) -{ +{ int i; @@ -82,7 +81,7 @@ static void end_rubin(struct rubin_state *rs) static void init_decode(struct rubin_state *rs, int div, int *bits) { - init_rubin(rs, div, bits); + init_rubin(rs, div, bits); /* behalve lower */ rs->rec_q = 0; @@ -188,7 +187,7 @@ static int in_byte(struct rubin_state *rs) -static int rubin_do_compress(int bit_divider, int *bits, unsigned char *data_in, +static int rubin_do_compress(int bit_divider, int *bits, unsigned char *data_in, unsigned char *cpage_out, uint32_t *sourcelen, uint32_t *dstlen) { int outpos = 0; @@ -198,31 +197,31 @@ static int rubin_do_compress(int bit_divider, int *bits, unsigned char *data_in, init_pushpull(&rs.pp, cpage_out, *dstlen * 8, 0, 32); init_rubin(&rs, bit_divider, bits); - + while (pos < (*sourcelen) && !out_byte(&rs, data_in[pos])) pos++; - + end_rubin(&rs); if (outpos > pos) { /* We failed */ return -1; } - - /* Tell the caller how much we managed to compress, + + /* Tell the caller how much we managed to compress, * and how much space it took */ - + outpos = (pushedbits(&rs.pp)+7)/8; - + if (outpos >= pos) return -1; /* We didn't actually compress */ *sourcelen = pos; *dstlen = outpos; return 0; -} +} #if 0 /* _compress returns the compressed size, -1 if bigger */ -int jffs2_rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out, +int jffs2_rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out, uint32_t *sourcelen, uint32_t *dstlen, void *model) { return rubin_do_compress(BIT_DIVIDER_MIPS, bits_mips, data_in, cpage_out, sourcelen, dstlen); @@ -277,7 +276,7 @@ static int jffs2_dynrubin_compress(unsigned char *data_in, } ret = rubin_do_compress(256, bits, data_in, cpage_out+8, &mysrclen, &mydstlen); - if (ret) + if (ret) return ret; /* Add back the 8 bytes we took for the probabilities */ @@ -293,19 +292,19 @@ static int jffs2_dynrubin_compress(unsigned char *data_in, return 0; } -static void rubin_do_decompress(int bit_divider, int *bits, unsigned char *cdata_in, +static void rubin_do_decompress(int bit_divider, int *bits, unsigned char *cdata_in, unsigned char *page_out, uint32_t srclen, uint32_t destlen) { int outpos = 0; struct rubin_state rs; - + init_pushpull(&rs.pp, cdata_in, srclen, 0, 0); init_decode(&rs, bit_divider, bits); - + while (outpos < destlen) { page_out[outpos++] = in_byte(&rs); } -} +} static int jffs2_rubinmips_decompress(unsigned char *data_in, diff --git a/fs/jffs2/compr_rubin.h b/fs/jffs2/compr_rubin.h index cf51e34f6574..bf1a93451621 100644 --- a/fs/jffs2/compr_rubin.h +++ b/fs/jffs2/compr_rubin.h @@ -1,7 +1,7 @@ /* Rubin encoder/decoder header */ /* work started at : aug 3, 1994 */ /* last modification : aug 15, 1994 */ -/* $Id: compr_rubin.h,v 1.6 2002/01/25 01:49:26 dwmw2 Exp $ */ +/* $Id: compr_rubin.h,v 1.7 2005/11/07 11:14:38 gleixner Exp $ */ #include "pushpull.h" @@ -11,8 +11,8 @@ struct rubin_state { - unsigned long p; - unsigned long q; + unsigned long p; + unsigned long q; unsigned long rec_q; long bit_number; struct pushpull pp; diff --git a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c index 83f7e0788fd0..4db8be8e90cc 100644 --- a/fs/jffs2/compr_zlib.c +++ b/fs/jffs2/compr_zlib.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: compr_zlib.c,v 1.31 2005/05/20 19:30:06 gleixner Exp $ + * $Id: compr_zlib.c,v 1.32 2005/11/07 11:14:38 gleixner Exp $ * */ @@ -24,11 +24,11 @@ #include "nodelist.h" #include "compr.h" - /* Plan: call deflate() with avail_in == *sourcelen, - avail_out = *dstlen - 12 and flush == Z_FINISH. + /* Plan: call deflate() with avail_in == *sourcelen, + avail_out = *dstlen - 12 and flush == Z_FINISH. If it doesn't manage to finish, call it again with avail_in == 0 and avail_out set to the remaining 12 - bytes for it to clean up. + bytes for it to clean up. Q: Is 12 bytes sufficient? */ #define STREAM_END_SPACE 12 @@ -89,7 +89,7 @@ static int jffs2_zlib_compress(unsigned char *data_in, def_strm.next_in = data_in; def_strm.total_in = 0; - + def_strm.next_out = cpage_out; def_strm.total_out = 0; @@ -99,7 +99,7 @@ static int jffs2_zlib_compress(unsigned char *data_in, D1(printk(KERN_DEBUG "calling deflate with avail_in %d, avail_out %d\n", def_strm.avail_in, def_strm.avail_out)); ret = zlib_deflate(&def_strm, Z_PARTIAL_FLUSH); - D1(printk(KERN_DEBUG "deflate returned with avail_in %d, avail_out %d, total_in %ld, total_out %ld\n", + D1(printk(KERN_DEBUG "deflate returned with avail_in %d, avail_out %d, total_in %ld, total_out %ld\n", def_strm.avail_in, def_strm.avail_out, def_strm.total_in, def_strm.total_out)); if (ret != Z_OK) { D1(printk(KERN_DEBUG "deflate in loop returned %d\n", ret)); @@ -150,7 +150,7 @@ static int jffs2_zlib_decompress(unsigned char *data_in, inf_strm.next_in = data_in; inf_strm.avail_in = srclen; inf_strm.total_in = 0; - + inf_strm.next_out = cpage_out; inf_strm.avail_out = destlen; inf_strm.total_out = 0; diff --git a/fs/jffs2/comprtest.c b/fs/jffs2/comprtest.c index cf51f091d0e7..f0fb8be7740c 100644 --- a/fs/jffs2/comprtest.c +++ b/fs/jffs2/comprtest.c @@ -1,4 +1,4 @@ -/* $Id: comprtest.c,v 1.5 2002/01/03 15:20:44 dwmw2 Exp $ */ +/* $Id: comprtest.c,v 1.6 2005/11/07 11:14:38 gleixner Exp $ */ #include #include @@ -265,9 +265,9 @@ static unsigned char testdata[TESTDATA_LEN] = { static unsigned char comprbuf[TESTDATA_LEN]; static unsigned char decomprbuf[TESTDATA_LEN]; -int jffs2_decompress(unsigned char comprtype, unsigned char *cdata_in, +int jffs2_decompress(unsigned char comprtype, unsigned char *cdata_in, unsigned char *data_out, uint32_t cdatalen, uint32_t datalen); -unsigned char jffs2_compress(unsigned char *data_in, unsigned char *cpage_out, +unsigned char jffs2_compress(unsigned char *data_in, unsigned char *cpage_out, uint32_t *datalen, uint32_t *cdatalen); int init_module(void ) { @@ -276,10 +276,10 @@ int init_module(void ) { int ret; printk("Original data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - testdata[0],testdata[1],testdata[2],testdata[3], - testdata[4],testdata[5],testdata[6],testdata[7], - testdata[8],testdata[9],testdata[10],testdata[11], - testdata[12],testdata[13],testdata[14],testdata[15]); + testdata[0],testdata[1],testdata[2],testdata[3], + testdata[4],testdata[5],testdata[6],testdata[7], + testdata[8],testdata[9],testdata[10],testdata[11], + testdata[12],testdata[13],testdata[14],testdata[15]); d = TESTDATA_LEN; c = TESTDATA_LEN; comprtype = jffs2_compress(testdata, comprbuf, &d, &c); @@ -287,18 +287,18 @@ int init_module(void ) { printk("jffs2_compress used compression type %d. Compressed size %d, uncompressed size %d\n", comprtype, c, d); printk("Compressed data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - comprbuf[0],comprbuf[1],comprbuf[2],comprbuf[3], - comprbuf[4],comprbuf[5],comprbuf[6],comprbuf[7], - comprbuf[8],comprbuf[9],comprbuf[10],comprbuf[11], - comprbuf[12],comprbuf[13],comprbuf[14],comprbuf[15]); + comprbuf[0],comprbuf[1],comprbuf[2],comprbuf[3], + comprbuf[4],comprbuf[5],comprbuf[6],comprbuf[7], + comprbuf[8],comprbuf[9],comprbuf[10],comprbuf[11], + comprbuf[12],comprbuf[13],comprbuf[14],comprbuf[15]); ret = jffs2_decompress(comprtype, comprbuf, decomprbuf, c, d); printk("jffs2_decompress returned %d\n", ret); printk("Decompressed data: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", - decomprbuf[0],decomprbuf[1],decomprbuf[2],decomprbuf[3], - decomprbuf[4],decomprbuf[5],decomprbuf[6],decomprbuf[7], - decomprbuf[8],decomprbuf[9],decomprbuf[10],decomprbuf[11], - decomprbuf[12],decomprbuf[13],decomprbuf[14],decomprbuf[15]); + decomprbuf[0],decomprbuf[1],decomprbuf[2],decomprbuf[3], + decomprbuf[4],decomprbuf[5],decomprbuf[6],decomprbuf[7], + decomprbuf[8],decomprbuf[9],decomprbuf[10],decomprbuf[11], + decomprbuf[12],decomprbuf[13],decomprbuf[14],decomprbuf[15]); if (memcmp(decomprbuf, testdata, d)) printk("Compression and decompression corrupted data\n"); else diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c index 0947284f45dd..1fe17de713e8 100644 --- a/fs/jffs2/debug.c +++ b/fs/jffs2/debug.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.c,v 1.11 2005/09/21 13:28:35 dedekind Exp $ + * $Id: debug.c,v 1.12 2005/11/07 11:14:39 gleixner Exp $ * */ #include @@ -67,7 +67,7 @@ __jffs2_dbg_fragtree_paranoia_check(struct jffs2_inode_info *f) __jffs2_dbg_fragtree_paranoia_check_nolock(f); up(&f->sem); } - + void __jffs2_dbg_fragtree_paranoia_check_nolock(struct jffs2_inode_info *f) { @@ -165,7 +165,7 @@ __jffs2_dbg_acct_paranoia_check(struct jffs2_sb_info *c, __jffs2_dbg_acct_paranoia_check_nolock(c, jeb); spin_unlock(&c->erase_completion_lock); } - + void __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) @@ -237,7 +237,7 @@ error: __jffs2_dbg_dump_jeb_nolock(jeb); __jffs2_dbg_dump_block_lists_nolock(c); BUG(); - + } #endif /* JFFS2_DBG_PARANOIA_CHECKS */ @@ -321,7 +321,7 @@ void __jffs2_dbg_dump_block_lists_nolock(struct jffs2_sb_info *c) { printk(JFFS2_DBG_MSG_PREFIX " dump JFFS2 blocks lists:\n"); - + printk(JFFS2_DBG "flash_size: %#08x\n", c->flash_size); printk(JFFS2_DBG "used_size: %#08x\n", c->used_size); printk(JFFS2_DBG "dirty_size: %#08x\n", c->dirty_size); @@ -577,15 +577,15 @@ __jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs) { int skip; int i; - + printk(JFFS2_DBG_MSG_PREFIX " dump from offset %#08x to offset %#08x (%x bytes).\n", offs, offs + len, len); i = skip = offs % JFFS2_BUFDUMP_BYTES_PER_LINE; offs = offs & ~(JFFS2_BUFDUMP_BYTES_PER_LINE - 1); - + if (skip != 0) printk(JFFS2_DBG "%#08x: ", offs); - + while (skip--) printk(" "); @@ -598,7 +598,7 @@ __jffs2_dbg_dump_buffer(unsigned char *buf, int len, uint32_t offs) } printk("%02x ", buf[i]); - + i += 1; } @@ -616,7 +616,7 @@ __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs) size_t retlen; uint32_t crc; int ret; - + printk(JFFS2_DBG_MSG_PREFIX " dump node at offset %#08x.\n", ofs); ret = jffs2_flash_read(c, ofs, len, &retlen, (unsigned char *)&node); @@ -630,13 +630,13 @@ __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs) printk(JFFS2_DBG "nodetype:\t%#04x\n", je16_to_cpu(node.u.nodetype)); printk(JFFS2_DBG "totlen:\t%#08x\n", je32_to_cpu(node.u.totlen)); printk(JFFS2_DBG "hdr_crc:\t%#08x\n", je32_to_cpu(node.u.hdr_crc)); - + crc = crc32(0, &node.u, sizeof(node.u) - 4); if (crc != je32_to_cpu(node.u.hdr_crc)) { JFFS2_ERROR("wrong common header CRC.\n"); return; } - + if (je16_to_cpu(node.u.magic) != JFFS2_MAGIC_BITMASK && je16_to_cpu(node.u.magic) != JFFS2_OLD_MAGIC_BITMASK) { @@ -668,7 +668,7 @@ __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs) printk(JFFS2_DBG "data_crc:\t%#08x\n", je32_to_cpu(node.i.data_crc)); printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.i.node_crc)); - crc = crc32(0, &node.i, sizeof(node.i) - 8); + crc = crc32(0, &node.i, sizeof(node.i) - 8); if (crc != je32_to_cpu(node.i.node_crc)) { JFFS2_ERROR("wrong node header CRC.\n"); return; @@ -686,11 +686,11 @@ __jffs2_dbg_dump_node(struct jffs2_sb_info *c, uint32_t ofs) printk(JFFS2_DBG "type:\t%#02x\n", node.d.type); printk(JFFS2_DBG "node_crc:\t%#08x\n", je32_to_cpu(node.d.node_crc)); printk(JFFS2_DBG "name_crc:\t%#08x\n", je32_to_cpu(node.d.name_crc)); - + node.d.name[node.d.nsize] = '\0'; printk(JFFS2_DBG "name:\t\"%s\"\n", node.d.name); - crc = crc32(0, &node.d, sizeof(node.d) - 8); + crc = crc32(0, &node.d, sizeof(node.d) - 8); if (crc != je32_to_cpu(node.d.node_crc)) { JFFS2_ERROR("wrong node header CRC.\n"); return; diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index b47ba9f1d606..f193d43a8a59 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: debug.h,v 1.20 2005/10/24 16:22:34 dedekind Exp $ + * $Id: debug.h,v 1.21 2005/11/07 11:14:39 gleixner Exp $ * */ #ifndef _JFFS2_DEBUG_H_ @@ -24,7 +24,7 @@ #define JFFS2_DBG_PARANOIA_CHECKS #define JFFS2_DBG_DUMPS -/* +/* * By defining/undefining the below macros one may select debugging messages * fro specific JFFS2 subsystems. */ @@ -45,7 +45,7 @@ /* Sanity checks are supposed to be light-weight and enabled by default */ #define JFFS2_DBG_SANITY_CHECKS -/* +/* * Dx() are mainly used for debugging messages, they must go away and be * superseded by nicer dbg_xxx() macros... */ @@ -91,7 +91,7 @@ " (%d) %s: " fmt, current->pid, \ __FUNCTION__, ##__VA_ARGS__); \ } while(0) - + #define JFFS2_NOTICE(fmt, ...) \ do { \ printk(JFFS2_NOTICE_MSG_PREFIX \ @@ -106,7 +106,7 @@ __FUNCTION__, ##__VA_ARGS__); \ } while(0) -/* +/* * We split our debugging messages on several parts, depending on the JFFS2 * subsystem the message belongs to. */ diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 19bea0f95ac1..a7bf9cb2567f 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: dir.c,v 1.89 2005/09/07 08:34:54 havasi Exp $ + * $Id: dir.c,v 1.90 2005/11/07 11:14:39 gleixner Exp $ * */ @@ -64,7 +64,7 @@ struct inode_operations jffs2_dir_inode_operations = /* We keep the dirent list sorted in increasing order of name hash, - and we use the same hash function as the dentries. Makes this + and we use the same hash function as the dentries. Makes this nice and simple */ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target, @@ -85,7 +85,7 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target, /* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */ for (fd_list = dir_f->dents; fd_list && fd_list->nhash <= target->d_name.hash; fd_list = fd_list->next) { - if (fd_list->nhash == target->d_name.hash && + if (fd_list->nhash == target->d_name.hash && (!fd || fd_list->version > fd->version) && strlen(fd_list->name) == target->d_name.len && !strncmp(fd_list->name, target->d_name.name, target->d_name.len)) { @@ -147,7 +147,7 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir) curofs++; /* First loop: curofs = 2; offset = 2 */ if (curofs < offset) { - D2(printk(KERN_DEBUG "Skipping dirent: \"%s\", ino #%u, type %d, because curofs %ld < offset %ld\n", + D2(printk(KERN_DEBUG "Skipping dirent: \"%s\", ino #%u, type %d, because curofs %ld < offset %ld\n", fd->name, fd->ino, fd->type, curofs, offset)); continue; } @@ -182,7 +182,7 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode, ri = jffs2_alloc_raw_inode(); if (!ri) return -ENOMEM; - + c = JFFS2_SB_INFO(dir_i->i_sb); D1(printk(KERN_DEBUG "jffs2_create()\n")); @@ -203,7 +203,7 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode, f = JFFS2_INODE_INFO(inode); dir_f = JFFS2_INODE_INFO(dir_i); - ret = jffs2_do_create(c, dir_f, f, ri, + ret = jffs2_do_create(c, dir_f, f, ri, dentry->d_name.name, dentry->d_name.len); if (ret) { @@ -234,7 +234,7 @@ static int jffs2_unlink(struct inode *dir_i, struct dentry *dentry) int ret; uint32_t now = get_seconds(); - ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, + ret = jffs2_do_unlink(c, dir_f, dentry->d_name.name, dentry->d_name.len, dead_f, now); if (dead_f->inocache) dentry->d_inode->i_nlink = dead_f->inocache->nlink; @@ -303,11 +303,11 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char if (!ri) return -ENOMEM; - + c = JFFS2_SB_INFO(dir_i->i_sb); - - /* Try to reserve enough space for both node and dirent. - * Just the node will do for now, though + + /* Try to reserve enough space for both node and dirent. + * Just the node will do for now, though */ namelen = dentry->d_name.len; ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &phys_ofs, &alloclen, @@ -338,7 +338,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char ri->compr = JFFS2_COMPR_NONE; ri->data_crc = cpu_to_je32(crc32(0, target, targetlen)); ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - + fn = jffs2_write_dnode(c, f, ri, target, targetlen, phys_ofs, ALLOC_NORMAL); jffs2_free_raw_inode(ri); @@ -364,7 +364,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char memcpy(f->target, target, targetlen + 1); D1(printk(KERN_DEBUG "jffs2_symlink: symlink's target '%s' cached\n", (char *)f->target)); - /* No data here. Only a metadata node, which will be + /* No data here. Only a metadata node, which will be obsoleted by the first data write */ f->metadata = fn; @@ -407,7 +407,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL); if (IS_ERR(fd)) { - /* dirent failed to write. Delete the inode normally + /* dirent failed to write. Delete the inode normally as if it were the final unlink() */ jffs2_complete_reservation(c); jffs2_free_raw_dirent(rd); @@ -450,11 +450,11 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) ri = jffs2_alloc_raw_inode(); if (!ri) return -ENOMEM; - + c = JFFS2_SB_INFO(dir_i->i_sb); - /* Try to reserve enough space for both node and dirent. - * Just the node will do for now, though + /* Try to reserve enough space for both node and dirent. + * Just the node will do for now, though */ namelen = dentry->d_name.len; ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL, @@ -482,7 +482,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) ri->data_crc = cpu_to_je32(0); ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - + fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL); jffs2_free_raw_inode(ri); @@ -494,7 +494,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) jffs2_clear_inode(inode); return PTR_ERR(fn); } - /* No data here. Only a metadata node, which will be + /* No data here. Only a metadata node, which will be obsoleted by the first data write */ f->metadata = fn; @@ -508,7 +508,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) jffs2_clear_inode(inode); return ret; } - + rd = jffs2_alloc_raw_dirent(); if (!rd) { /* Argh. Now we treat it like a normal delete */ @@ -535,9 +535,9 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL); - + if (IS_ERR(fd)) { - /* dirent failed to write. Delete the inode normally + /* dirent failed to write. Delete the inode normally as if it were the final unlink() */ jffs2_complete_reservation(c); jffs2_free_raw_dirent(rd); @@ -599,16 +599,16 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de ri = jffs2_alloc_raw_inode(); if (!ri) return -ENOMEM; - + c = JFFS2_SB_INFO(dir_i->i_sb); - + if (S_ISBLK(mode) || S_ISCHR(mode)) { dev = cpu_to_je16(old_encode_dev(rdev)); devlen = sizeof(dev); } - - /* Try to reserve enough space for both node and dirent. - * Just the node will do for now, though + + /* Try to reserve enough space for both node and dirent. + * Just the node will do for now, though */ namelen = dentry->d_name.len; ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &phys_ofs, &alloclen, @@ -638,7 +638,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de ri->compr = JFFS2_COMPR_NONE; ri->data_crc = cpu_to_je32(crc32(0, &dev, devlen)); ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); - + fn = jffs2_write_dnode(c, f, ri, (char *)&dev, devlen, phys_ofs, ALLOC_NORMAL); jffs2_free_raw_inode(ri); @@ -650,7 +650,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de jffs2_clear_inode(inode); return PTR_ERR(fn); } - /* No data here. Only a metadata node, which will be + /* No data here. Only a metadata node, which will be obsoleted by the first data write */ f->metadata = fn; @@ -694,9 +694,9 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL); - + if (IS_ERR(fd)) { - /* dirent failed to write. Delete the inode normally + /* dirent failed to write. Delete the inode normally as if it were the final unlink() */ jffs2_complete_reservation(c); jffs2_free_raw_dirent(rd); @@ -730,7 +730,7 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, uint8_t type; uint32_t now; - /* The VFS will check for us and prevent trying to rename a + /* The VFS will check for us and prevent trying to rename a * file over a directory and vice versa, but if it's a directory, * the VFS can't check whether the victim is empty. The filesystem * needs to do that for itself. @@ -752,18 +752,18 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, } /* XXX: We probably ought to alloc enough space for - both nodes at the same time. Writing the new link, + both nodes at the same time. Writing the new link, then getting -ENOSPC, is quite bad :) */ /* Make a hard link */ - + /* XXX: This is ugly */ type = (old_dentry->d_inode->i_mode & S_IFMT) >> 12; if (!type) type = DT_REG; now = get_seconds(); - ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i), + ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i), old_dentry->d_inode->i_ino, type, new_dentry->d_name.name, new_dentry->d_name.len, now); @@ -782,13 +782,13 @@ static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, } } - /* If it was a directory we moved, and there was no victim, + /* If it was a directory we moved, and there was no victim, increase i_nlink on its new parent */ if (S_ISDIR(old_dentry->d_inode->i_mode) && !victim_f) new_dir_i->i_nlink++; /* Unlink the original */ - ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), + ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i), old_dentry->d_name.name, old_dentry->d_name.len, NULL, now); /* We don't touch inode->i_nlink */ diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index 347de4efeeeb..dad68fdffe9e 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c @@ -24,7 +24,7 @@ struct erase_priv_struct { struct jffs2_eraseblock *jeb; struct jffs2_sb_info *c; }; - + #ifndef __ECOS static void jffs2_erase_callback(struct erase_info *); #endif @@ -71,7 +71,7 @@ static void jffs2_erase_block(struct jffs2_sb_info *c, instr->callback = jffs2_erase_callback; instr->priv = (unsigned long)(&instr[1]); instr->fail_addr = 0xffffffff; - + ((struct erase_priv_struct *)instr->priv)->jeb = jeb; ((struct erase_priv_struct *)instr->priv)->c = c; @@ -96,7 +96,7 @@ static void jffs2_erase_block(struct jffs2_sb_info *c, return; } - if (ret == -EROFS) + if (ret == -EROFS) printk(KERN_WARNING "Erase at 0x%08x failed immediately: -EROFS. Is the sector locked?\n", jeb->offset); else printk(KERN_WARNING "Erase at 0x%08x failed immediately: errno %d\n", jeb->offset, ret); @@ -197,7 +197,7 @@ static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock c->nr_erasing_blocks--; spin_unlock(&c->erase_completion_lock); wake_up(&c->erase_wait); -} +} #ifndef __ECOS static void jffs2_erase_callback(struct erase_info *instr) @@ -209,7 +209,7 @@ static void jffs2_erase_callback(struct erase_info *instr) jffs2_erase_failed(priv->c, priv->jeb, instr->fail_addr); } else { jffs2_erase_succeeded(priv->c, priv->jeb); - } + } kfree(instr); } #endif /* !__ECOS */ @@ -227,13 +227,13 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c, /* Walk the inode's list once, removing any nodes from this eraseblock */ while (1) { if (!(*prev)->next_in_ino) { - /* We're looking at the jffs2_inode_cache, which is + /* We're looking at the jffs2_inode_cache, which is at the end of the linked list. Stash it and continue from the beginning of the list */ ic = (struct jffs2_inode_cache *)(*prev); prev = &ic->nodes; continue; - } + } if (SECTOR_ADDR((*prev)->flash_offset) == jeb->offset) { /* It's in the block we're erasing */ @@ -267,7 +267,7 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c, printk(KERN_DEBUG "After remove_node_refs_from_ino_list: \n" KERN_DEBUG); this = ic->nodes; - + while(this) { printk( "0x%08x(%d)->", ref_offset(this), ref_flags(this)); if (++i == 5) { @@ -290,7 +290,7 @@ static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_erase while(jeb->first_node) { ref = jeb->first_node; jeb->first_node = ref->next_phys; - + /* Remove from the inode-list */ if (ref->next_in_ino) jffs2_remove_node_refs_from_ino_list(c, ref, jeb); @@ -307,7 +307,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl uint32_t ofs; size_t retlen; int ret = -EIO; - + ebuf = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!ebuf) { printk(KERN_WARNING "Failed to allocate page buffer for verifying erase at 0x%08x. Refiling\n", jeb->offset); @@ -361,7 +361,7 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb case -EIO: goto filebad; } - /* Write the erase complete marker */ + /* Write the erase complete marker */ D1(printk(KERN_DEBUG "Writing erased marker to block at 0x%08x\n", jeb->offset)); bad_offset = jeb->offset; @@ -399,7 +399,7 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb vecs[0].iov_base = (unsigned char *) ▮ vecs[0].iov_len = sizeof(marker); ret = jffs2_flash_direct_writev(c, vecs, 1, jeb->offset, &retlen); - + if (ret || retlen != sizeof(marker)) { if (ret) printk(KERN_WARNING "Write clean marker to block at 0x%08x failed: %d\n", @@ -416,9 +416,9 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb marker_ref->next_phys = NULL; marker_ref->flash_offset = jeb->offset | REF_NORMAL; marker_ref->__totlen = c->cleanmarker_size; - + jeb->first_node = jeb->last_node = marker_ref; - + jeb->free_size = c->sector_size - c->cleanmarker_size; jeb->used_size = c->cleanmarker_size; jeb->dirty_size = 0; diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index 605ea6b0b473..935f273dc57b 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c @@ -34,8 +34,8 @@ int jffs2_fsync(struct file *filp, struct dentry *dentry, int datasync) /* Trigger GC to flush any pending writes for this inode */ jffs2_flush_wbuf_gc(c, inode->i_ino); - - return 0; + + return 0; } struct file_operations jffs2_file_operations = @@ -107,7 +107,7 @@ static int jffs2_readpage (struct file *filp, struct page *pg) { struct jffs2_inode_info *f = JFFS2_INODE_INFO(pg->mapping->host); int ret; - + down(&f->sem); ret = jffs2_do_readpage_unlock(pg->mapping->host, pg); up(&f->sem); @@ -130,7 +130,7 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg, struct jffs2_raw_inode ri; struct jffs2_full_dnode *fn; uint32_t phys_ofs, alloc_len; - + D1(printk(KERN_DEBUG "Writing new hole frag 0x%x-0x%x between current EOF and new page\n", (unsigned int)inode->i_size, pageofs)); @@ -160,7 +160,7 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg, ri.compr = JFFS2_COMPR_ZERO; ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); ri.data_crc = cpu_to_je32(0); - + fn = jffs2_write_dnode(c, f, &ri, NULL, 0, phys_ofs, ALLOC_NORMAL); if (IS_ERR(fn)) { @@ -187,7 +187,7 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg, inode->i_size = pageofs; up(&f->sem); } - + /* Read in the page if it wasn't already present, unless it's a whole page */ if (!PageUptodate(pg) && (start || end < PAGE_CACHE_SIZE)) { down(&f->sem); @@ -218,7 +218,7 @@ static int jffs2_commit_write (struct file *filp, struct page *pg, if (!start && end == PAGE_CACHE_SIZE) { /* We need to avoid deadlock with page_cache_read() in jffs2_garbage_collect_pass(). So we have to mark the - page up to date, to prevent page_cache_read() from + page up to date, to prevent page_cache_read() from trying to re-lock it. */ SetPageUptodate(pg); } @@ -252,7 +252,7 @@ static int jffs2_commit_write (struct file *filp, struct page *pg, /* There was an error writing. */ SetPageError(pg); } - + /* Adjust writtenlen for the padding we did, so we don't confuse our caller */ if (writtenlen < (start&3)) writtenlen = 0; @@ -263,7 +263,7 @@ static int jffs2_commit_write (struct file *filp, struct page *pg, if (inode->i_size < (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen) { inode->i_size = (pg->index << PAGE_CACHE_SHIFT) + start + writtenlen; inode->i_blocks = (inode->i_size + 511) >> 9; - + inode->i_ctime = inode->i_mtime = ITIME(je32_to_cpu(ri->ctime)); } } @@ -272,7 +272,7 @@ static int jffs2_commit_write (struct file *filp, struct page *pg, if (start+writtenlen < end) { /* generic_file_write has written more to the page cache than we've - actually written to the medium. Mark the page !Uptodate so that + actually written to the medium. Mark the page !Uptodate so that it gets reread */ D1(printk(KERN_DEBUG "jffs2_commit_write(): Not all bytes written. Marking page !uptodate\n")); SetPageError(pg); diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index b0b96d7272d8..543420665c5b 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -40,7 +40,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) int ret; D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino)); ret = inode_change_ok(inode, iattr); - if (ret) + if (ret) return ret; /* Special cases - we don't want more than one data node @@ -73,7 +73,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) kfree(mdata); return -ENOMEM; } - + ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &phys_ofs, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); if (ret) { @@ -84,7 +84,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) } down(&f->sem); ivalid = iattr->ia_valid; - + ri->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); ri->nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); ri->totlen = cpu_to_je32(sizeof(*ri) + mdatalen); @@ -100,7 +100,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) if (iattr->ia_mode & S_ISGID && !in_group_p(je16_to_cpu(ri->gid)) && !capable(CAP_FSETID)) ri->mode = cpu_to_jemode(iattr->ia_mode & ~S_ISGID); - else + else ri->mode = cpu_to_jemode(iattr->ia_mode); else ri->mode = cpu_to_jemode(inode->i_mode); @@ -129,7 +129,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, phys_ofs, ALLOC_NORMAL); if (S_ISLNK(inode->i_mode)) kfree(mdata); - + if (IS_ERR(new_metadata)) { jffs2_complete_reservation(c); jffs2_free_raw_inode(ri); @@ -167,7 +167,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) jffs2_complete_reservation(c); /* We have to do the vmtruncate() without f->sem held, since - some pages may be locked and waiting for it in readpage(). + some pages may be locked and waiting for it in readpage(). We are protected from a simultaneous write() extending i_size back past iattr->ia_size, because do_truncate() holds the generic inode semaphore. */ @@ -210,12 +210,12 @@ int jffs2_statfs(struct super_block *sb, struct kstatfs *buf) void jffs2_clear_inode (struct inode *inode) { - /* We can forget about this inode for now - drop all + /* We can forget about this inode for now - drop all * the nodelists associated with it, etc. */ struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); - + D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode)); jffs2_do_clear_inode(c, f); @@ -234,7 +234,7 @@ void jffs2_read_inode (struct inode *inode) c = JFFS2_SB_INFO(inode->i_sb); jffs2_init_inode_info(f); - + ret = jffs2_do_read_inode(c, f, inode->i_ino, &latest_node); if (ret) { @@ -254,14 +254,14 @@ void jffs2_read_inode (struct inode *inode) inode->i_blksize = PAGE_SIZE; inode->i_blocks = (inode->i_size + 511) >> 9; - + switch (inode->i_mode & S_IFMT) { jint16_t rdev; case S_IFLNK: inode->i_op = &jffs2_symlink_inode_operations; break; - + case S_IFDIR: { struct jffs2_full_dirent *fd; @@ -298,7 +298,7 @@ void jffs2_read_inode (struct inode *inode) jffs2_do_clear_inode(c, f); make_bad_inode(inode); return; - } + } case S_IFSOCK: case S_IFIFO: @@ -354,11 +354,11 @@ int jffs2_remount_fs (struct super_block *sb, int *flags, char *data) down(&c->alloc_sem); jffs2_flush_wbuf_pad(c); up(&c->alloc_sem); - } + } if (!(*flags & MS_RDONLY)) jffs2_start_garbage_collect_thread(c); - + *flags |= MS_NOATIME; return 0; @@ -392,9 +392,9 @@ struct inode *jffs2_new_inode (struct inode *dir_i, int mode, struct jffs2_raw_i D1(printk(KERN_DEBUG "jffs2_new_inode(): dir_i %ld, mode 0x%x\n", dir_i->i_ino, mode)); c = JFFS2_SB_INFO(sb); - + inode = new_inode(sb); - + if (!inode) return ERR_PTR(-ENOMEM); @@ -458,14 +458,14 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) #endif c->flash_size = c->mtd->size; - c->sector_size = c->mtd->erasesize; + c->sector_size = c->mtd->erasesize; blocks = c->flash_size / c->sector_size; /* * Size alignment check */ if ((c->sector_size * blocks) != c->flash_size) { - c->flash_size = c->sector_size * blocks; + c->flash_size = c->sector_size * blocks; printk(KERN_INFO "jffs2: Flash size not aligned to erasesize, reducing to %dKiB\n", c->flash_size / 1024); } @@ -543,16 +543,16 @@ struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic; if (!nlink) { /* The inode has zero nlink but its nodes weren't yet marked - obsolete. This has to be because we're still waiting for + obsolete. This has to be because we're still waiting for the final (close() and) iput() to happen. - There's a possibility that the final iput() could have + There's a possibility that the final iput() could have happened while we were contemplating. In order to ensure that we don't cause a new read_inode() (which would fail) for the inode in question, we use ilookup() in this case instead of iget(). - The nlink can't _become_ zero at this point because we're + The nlink can't _become_ zero at this point because we're holding the alloc_sem, and jffs2_do_unlink() would also need that while decrementing nlink on any inode. */ @@ -599,19 +599,19 @@ struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, return JFFS2_INODE_INFO(inode); } -unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, - struct jffs2_inode_info *f, +unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, + struct jffs2_inode_info *f, unsigned long offset, unsigned long *priv) { struct inode *inode = OFNI_EDONI_2SFFJ(f); struct page *pg; - pg = read_cache_page(inode->i_mapping, offset >> PAGE_CACHE_SHIFT, + pg = read_cache_page(inode->i_mapping, offset >> PAGE_CACHE_SHIFT, (void *)jffs2_do_readpage_unlock, inode); if (IS_ERR(pg)) return (void *)pg; - + *priv = (unsigned long)pg; return kmap(pg); } @@ -628,7 +628,7 @@ void jffs2_gc_release_page(struct jffs2_sb_info *c, static int jffs2_flash_setup(struct jffs2_sb_info *c) { int ret = 0; - + if (jffs2_cleanmarker_oob(c)) { /* NAND flash... do setup accordingly */ ret = jffs2_nand_flash_setup(c); @@ -642,7 +642,7 @@ static int jffs2_flash_setup(struct jffs2_sb_info *c) { if (ret) return ret; } - + /* and Dataflash */ if (jffs2_dataflash(c)) { ret = jffs2_dataflash_setup(c); @@ -670,7 +670,7 @@ void jffs2_flash_cleanup(struct jffs2_sb_info *c) { if (jffs2_nor_ecc(c)) { jffs2_nor_ecc_flash_cleanup(c); } - + /* and DataFlash */ if (jffs2_dataflash(c)) { jffs2_dataflash_cleanup(c); diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index ee54cdc59e06..f9ffece453a3 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: gc.c,v 1.154 2005/09/07 08:34:54 havasi Exp $ + * $Id: gc.c,v 1.155 2005/11/07 11:14:39 gleixner Exp $ * */ @@ -21,14 +21,14 @@ #include "nodelist.h" #include "compr.h" -static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, +static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, struct jffs2_raw_node_ref *raw); -static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_inode_info *f, struct jffs2_full_dnode *fd); -static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_inode_info *f, struct jffs2_full_dirent *fd); -static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_inode_info *f, struct jffs2_full_dirent *fd); static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn, @@ -55,7 +55,7 @@ again: D1(printk(KERN_DEBUG "Picking block from bad_used_list to GC next\n")); nextlist = &c->bad_used_list; } else if (n < 50 && !list_empty(&c->erasable_list)) { - /* Note that most of them will have gone directly to be erased. + /* Note that most of them will have gone directly to be erased. So don't favour the erasable_list _too_ much. */ D1(printk(KERN_DEBUG "Picking block from erasable_list to GC next\n")); nextlist = &c->erasable_list; @@ -101,7 +101,7 @@ again: printk(KERN_WARNING "Eep. ret->gc_node for block at 0x%08x is NULL\n", ret->offset); BUG(); } - + /* Have we accidentally picked a clean block with wasted space ? */ if (ret->wasted_size) { D1(printk(KERN_DEBUG "Converting wasted_size %08x to dirty_size\n", ret->wasted_size)); @@ -136,7 +136,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) /* We can't start doing GC yet. We haven't finished checking the node CRCs etc. Do it now. */ - + /* checked_ino is protected by the alloc_sem */ if (c->checked_ino > c->highest_ino) { printk(KERN_CRIT "Checked all inodes but still 0x%x bytes of unchecked space?\n", @@ -178,7 +178,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) case INO_STATE_READING: /* We need to wait for it to finish, lest we move on - and trigger the BUG() above while we haven't yet + and trigger the BUG() above while we haven't yet finished checking all its nodes */ D1(printk(KERN_DEBUG "Waiting for ino #%u to finish reading\n", ic->ino)); up(&c->alloc_sem); @@ -228,13 +228,13 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) } raw = jeb->gc_node; - + while(ref_obsolete(raw)) { D1(printk(KERN_DEBUG "Node at 0x%08x is obsolete... skipping\n", ref_offset(raw))); raw = raw->next_phys; if (unlikely(!raw)) { printk(KERN_WARNING "eep. End of raw list while still supposedly nodes to GC\n"); - printk(KERN_WARNING "erase block at 0x%08x. free_size 0x%08x, dirty_size 0x%08x, used_size 0x%08x\n", + printk(KERN_WARNING "erase block at 0x%08x. free_size 0x%08x, dirty_size 0x%08x, used_size 0x%08x\n", jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size); jeb->gc_node = raw; spin_unlock(&c->erase_completion_lock); @@ -259,7 +259,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) ic = jffs2_raw_ref_to_ic(raw); /* We need to hold the inocache. Either the erase_completion_lock or - the inocache_lock are sufficient; we trade down since the inocache_lock + the inocache_lock are sufficient; we trade down since the inocache_lock causes less contention. */ spin_lock(&c->inocache_lock); @@ -278,14 +278,14 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) switch(ic->state) { case INO_STATE_CHECKEDABSENT: - /* It's been checked, but it's not currently in-core. + /* It's been checked, but it's not currently in-core. We can just copy any pristine nodes, but have to prevent anyone else from doing read_inode() while we're at it, so we set the state accordingly */ if (ref_flags(raw) == REF_PRISTINE) ic->state = INO_STATE_GC; else { - D1(printk(KERN_DEBUG "Ino #%u is absent but node not REF_PRISTINE. Reading.\n", + D1(printk(KERN_DEBUG "Ino #%u is absent but node not REF_PRISTINE. Reading.\n", ic->ino)); } break; @@ -298,8 +298,8 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) case INO_STATE_CHECKING: case INO_STATE_GC: /* Should never happen. We should have finished checking - by the time we actually start doing any GC, and since - we're holding the alloc_sem, no other garbage collection + by the time we actually start doing any GC, and since + we're holding the alloc_sem, no other garbage collection can happen. */ printk(KERN_CRIT "Inode #%u already in state %d in jffs2_garbage_collect_pass()!\n", @@ -319,21 +319,21 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() waiting for ino #%u in state %d\n", ic->ino, ic->state)); sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); - /* And because we dropped the alloc_sem we must start again from the + /* And because we dropped the alloc_sem we must start again from the beginning. Ponder chance of livelock here -- we're returning success without actually making any progress. - Q: What are the chances that the inode is back in INO_STATE_READING + Q: What are the chances that the inode is back in INO_STATE_READING again by the time we next enter this function? And that this happens enough times to cause a real delay? - A: Small enough that I don't care :) + A: Small enough that I don't care :) */ return 0; } /* OK. Now if the inode is in state INO_STATE_GC, we are going to copy the - node intact, and we don't have to muck about with the fragtree etc. + node intact, and we don't have to muck about with the fragtree etc. because we know it's not in-core. If it _was_ in-core, we go through all the iget() crap anyway */ @@ -453,7 +453,7 @@ static int jffs2_garbage_collect_live(struct jffs2_sb_info *c, struct jffs2_era if (!ret) { /* Urgh. Return it sensibly. */ frag->node->raw = f->inocache->nodes; - } + } if (ret != -EBADFD) goto upnout; } @@ -467,7 +467,7 @@ static int jffs2_garbage_collect_live(struct jffs2_sb_info *c, struct jffs2_era } goto upnout; } - + /* Wasn't a dnode. Try dirent */ for (fd = f->dents; fd; fd=fd->next) { if (fd->raw == raw) @@ -494,7 +494,7 @@ static int jffs2_garbage_collect_live(struct jffs2_sb_info *c, struct jffs2_era return ret; } -static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, +static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, struct jffs2_raw_node_ref *raw) { @@ -580,7 +580,7 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, } break; default: - printk(KERN_WARNING "Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n", + printk(KERN_WARNING "Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n", ref_offset(raw), je16_to_cpu(node->u.nodetype)); goto bail; } @@ -621,7 +621,7 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, retried = 1; D1(printk(KERN_DEBUG "Retrying failed write of REF_PRISTINE node.\n")); - + jffs2_dbg_acct_sanity_check(c,jeb); jffs2_dbg_acct_paranoia_check(c, jeb); @@ -669,7 +669,7 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, goto out_node; } -static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn) { struct jffs2_full_dnode *new_fn; @@ -684,7 +684,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ S_ISCHR(JFFS2_F_I_MODE(f)) ) { /* For these, we don't actually need to read the old node */ /* FIXME: for minor or major > 255. */ - dev = cpu_to_je16(((JFFS2_F_I_RDEV_MAJ(f) << 8) | + dev = cpu_to_je16(((JFFS2_F_I_RDEV_MAJ(f) << 8) | JFFS2_F_I_RDEV_MIN(f))); mdata = (char *)&dev; mdatalen = sizeof(dev); @@ -705,7 +705,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bites of symlink target\n", mdatalen)); } - + ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &phys_ofs, &alloclen, JFFS2_SUMMARY_INODE_SIZE); if (ret) { @@ -713,7 +713,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ sizeof(ri)+ mdatalen, ret); goto out; } - + last_frag = frag_last(&f->fragtree); if (last_frag) /* Fetch the inode length from the fragtree rather then @@ -721,7 +721,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ ilen = last_frag->ofs + last_frag->size; else ilen = JFFS2_F_I_SIZE(f); - + memset(&ri, 0, sizeof(ri)); ri.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); ri.nodetype = cpu_to_je16(JFFS2_NODETYPE_INODE); @@ -760,7 +760,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ return ret; } -static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_inode_info *f, struct jffs2_full_dirent *fd) { struct jffs2_full_dirent *new_fd; @@ -781,12 +781,12 @@ static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_er so refrain from splatting them. */ if (JFFS2_F_I_MTIME(f) == JFFS2_F_I_CTIME(f)) rd.mctime = cpu_to_je32(JFFS2_F_I_MTIME(f)); - else + else rd.mctime = cpu_to_je32(0); rd.type = fd->type; rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd)-8)); rd.name_crc = cpu_to_je32(crc32(0, fd->name, rd.nsize)); - + ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &phys_ofs, &alloclen, JFFS2_SUMMARY_DIRENT_SIZE(rd.nsize)); if (ret) { @@ -804,7 +804,7 @@ static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_er return 0; } -static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_inode_info *f, struct jffs2_full_dirent *fd) { struct jffs2_full_dirent **fdp = &f->dents; @@ -843,7 +843,7 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct if (ref_totlen(c, NULL, raw) != rawlen) continue; - /* Doesn't matter if there's one in the same erase block. We're going to + /* Doesn't matter if there's one in the same erase block. We're going to delete it too at the same time. */ if (SECTOR_ADDR(raw->flash_offset) == SECTOR_ADDR(fd->raw->flash_offset)) continue; @@ -895,7 +895,7 @@ static int jffs2_garbage_collect_deletion_dirent(struct jffs2_sb_info *c, struct kfree(rd); } - /* FIXME: If we're deleting a dirent which contains the current mtime and ctime, + /* FIXME: If we're deleting a dirent which contains the current mtime and ctime, we should update the metadata node with those times accordingly */ /* No need for it any more. Just mark it obsolete and remove it from the list */ @@ -927,13 +927,13 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras D1(printk(KERN_DEBUG "Writing replacement hole node for ino #%u from offset 0x%x to 0x%x\n", f->inocache->ino, start, end)); - + memset(&ri, 0, sizeof(ri)); if(fn->frags > 1) { size_t readlen; uint32_t crc; - /* It's partially obsoleted by a later write. So we have to + /* It's partially obsoleted by a later write. So we have to write it out again with the _same_ version as before */ ret = jffs2_flash_read(c, ref_offset(fn->raw), sizeof(ri), &readlen, (char *)&ri); if (readlen != sizeof(ri) || ret) { @@ -955,16 +955,16 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras crc = crc32(0, &ri, sizeof(ri)-8); if (crc != je32_to_cpu(ri.node_crc)) { printk(KERN_WARNING "jffs2_garbage_collect_hole: Node at 0x%08x had CRC 0x%08x which doesn't match calculated CRC 0x%08x\n", - ref_offset(fn->raw), + ref_offset(fn->raw), je32_to_cpu(ri.node_crc), crc); /* FIXME: We could possibly deal with this by writing new holes for each frag */ - printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%u will be lost\n", + printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%u will be lost\n", start, end, f->inocache->ino); goto fill; } if (ri.compr != JFFS2_COMPR_ZERO) { printk(KERN_WARNING "jffs2_garbage_collect_hole: Node 0x%08x wasn't a hole node!\n", ref_offset(fn->raw)); - printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%u will be lost\n", + printk(KERN_WARNING "Data in the range 0x%08x to 0x%08x of inode #%u will be lost\n", start, end, f->inocache->ino); goto fill; } @@ -982,7 +982,7 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras ri.csize = cpu_to_je32(0); ri.compr = JFFS2_COMPR_ZERO; } - + frag = frag_last(&f->fragtree); if (frag) /* Fetch the inode length from the fragtree rather then @@ -1024,10 +1024,10 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras return 0; } - /* + /* * We should only get here in the case where the node we are * replacing had more than one frag, so we kept the same version - * number as before. (Except in case of error -- see 'goto fill;' + * number as before. (Except in case of error -- see 'goto fill;' * above.) */ D1(if(unlikely(fn->frags <= 1)) { @@ -1039,7 +1039,7 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras /* This is a partially-overlapped hole node. Mark it REF_NORMAL not REF_PRISTINE */ mark_ref_normal(new_fn->raw); - for (frag = jffs2_lookup_node_frag(&f->fragtree, fn->ofs); + for (frag = jffs2_lookup_node_frag(&f->fragtree, fn->ofs); frag; frag = frag_next(frag)) { if (frag->ofs > fn->size + fn->ofs) break; @@ -1057,10 +1057,10 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras printk(KERN_WARNING "jffs2_garbage_collect_hole: New node has no frags!\n"); BUG(); } - + jffs2_mark_node_obsolete(c, fn->raw); jffs2_free_full_dnode(fn); - + return 0; } @@ -1070,12 +1070,12 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era { struct jffs2_full_dnode *new_fn; struct jffs2_raw_inode ri; - uint32_t alloclen, phys_ofs, offset, orig_end, orig_start; + uint32_t alloclen, phys_ofs, offset, orig_end, orig_start; int ret = 0; unsigned char *comprbuf = NULL, *writebuf; unsigned long pg; unsigned char *pg_ptr; - + memset(&ri, 0, sizeof(ri)); D1(printk(KERN_DEBUG "Writing replacement dnode for ino #%u from offset 0x%x to 0x%x\n", @@ -1087,8 +1087,8 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era if (c->nr_free_blocks + c->nr_erasing_blocks > c->resv_blocks_gcmerge) { /* Attempt to do some merging. But only expand to cover logically adjacent frags if the block containing them is already considered - to be dirty. Otherwise we end up with GC just going round in - circles dirtying the nodes it already wrote out, especially + to be dirty. Otherwise we end up with GC just going round in + circles dirtying the nodes it already wrote out, especially on NAND where we have small eraseblocks and hence a much higher chance of nodes having to be split to cross boundaries. */ @@ -1122,7 +1122,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era break; } else { - /* OK, it's a frag which extends to the beginning of the page. Does it live + /* OK, it's a frag which extends to the beginning of the page. Does it live in a block which is still considered clean? If so, don't obsolete it. If not, cover it anyway. */ @@ -1172,7 +1172,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era break; } else { - /* OK, it's a frag which extends to the beginning of the page. Does it live + /* OK, it's a frag which extends to the beginning of the page. Does it live in a block which is still considered clean? If so, don't obsolete it. If not, cover it anyway. */ @@ -1199,14 +1199,14 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era break; } } - D1(printk(KERN_DEBUG "Expanded dnode to write from (0x%x-0x%x) to (0x%x-0x%x)\n", + D1(printk(KERN_DEBUG "Expanded dnode to write from (0x%x-0x%x) to (0x%x-0x%x)\n", orig_start, orig_end, start, end)); D1(BUG_ON(end > frag_last(&f->fragtree)->ofs + frag_last(&f->fragtree)->size)); BUG_ON(end < orig_end); BUG_ON(start > orig_start); } - + /* First, use readpage() to read the appropriate page into the page cache */ /* Q: What happens if we actually try to GC the _same_ page for which commit_write() * triggered garbage collection in the first place? @@ -1263,7 +1263,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era ri.usercompr = (comprtype >> 8) & 0xff; ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); ri.data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen)); - + new_fn = jffs2_write_dnode(c, f, &ri, comprbuf, cdatalen, phys_ofs, ALLOC_GC); jffs2_free_comprbuf(comprbuf, writebuf); diff --git a/fs/jffs2/histo.h b/fs/jffs2/histo.h index 84f184f0836f..22a93a08210c 100644 --- a/fs/jffs2/histo.h +++ b/fs/jffs2/histo.h @@ -1,3 +1,3 @@ /* This file provides the bit-probabilities for the input file */ -#define BIT_DIVIDER 629 +#define BIT_DIVIDER 629 static int bits[9] = { 179,167,183,165,159,198,178,119,}; /* ia32 .so files */ diff --git a/fs/jffs2/histo_mips.h b/fs/jffs2/histo_mips.h index 9a443268d885..fa3dac19a109 100644 --- a/fs/jffs2/histo_mips.h +++ b/fs/jffs2/histo_mips.h @@ -1,2 +1,2 @@ -#define BIT_DIVIDER_MIPS 1043 +#define BIT_DIVIDER_MIPS 1043 static int bits_mips[8] = { 277,249,290,267,229,341,212,241}; /* mips32 */ diff --git a/fs/jffs2/ioctl.c b/fs/jffs2/ioctl.c index 238c7992064c..69099835de1c 100644 --- a/fs/jffs2/ioctl.c +++ b/fs/jffs2/ioctl.c @@ -7,17 +7,17 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: ioctl.c,v 1.9 2004/11/16 20:36:11 dwmw2 Exp $ + * $Id: ioctl.c,v 1.10 2005/11/07 11:14:40 gleixner Exp $ * */ #include -int jffs2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, +int jffs2_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { /* Later, this will provide for lsattr.jffs2 and chattr.jffs2, which will include compression support etc. */ return -ENOTTY; } - + diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c index f27df015f3ec..036cbd11c004 100644 --- a/fs/jffs2/malloc.c +++ b/fs/jffs2/malloc.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: malloc.c,v 1.30 2005/09/20 14:27:34 dedekind Exp $ + * $Id: malloc.c,v 1.31 2005/11/07 11:14:40 gleixner Exp $ * */ @@ -29,7 +29,7 @@ static kmem_cache_t *inode_cache_slab; int __init jffs2_create_slab_caches(void) { - full_dnode_slab = kmem_cache_create("jffs2_full_dnode", + full_dnode_slab = kmem_cache_create("jffs2_full_dnode", sizeof(struct jffs2_full_dnode), 0, 0, NULL, NULL); if (!full_dnode_slab) diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index 80fe8feffb4d..c79eebb8ab32 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.c,v 1.114 2005/09/21 13:28:35 dedekind Exp $ + * $Id: nodelist.c,v 1.115 2005/11/07 11:14:40 gleixner Exp $ * */ @@ -24,7 +24,7 @@ void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list) { struct jffs2_full_dirent **prev = list; - + dbg_dentlist("add dirent \"%s\", ino #%u\n", new->name, new->ino); while ((*prev) && (*prev)->nhash <= new->nhash) { @@ -75,14 +75,14 @@ void jffs2_truncate_fragtree(struct jffs2_sb_info *c, struct rb_root *list, uint if (size == 0) return; - /* + /* * If the last fragment starts at the RAM page boundary, it is * REF_PRISTINE irrespective of its size. */ frag = frag_last(list); if (frag->node && (frag->ofs & (PAGE_CACHE_SIZE - 1)) == 0) { dbg_fragtree2("marking the last fragment 0x%08x-0x%08x REF_PRISTINE.\n", - frag->ofs, frag->ofs + frag->size); + frag->ofs, frag->ofs + frag->size); frag->node->raw->flash_offset = ref_offset(frag->node->raw) | REF_PRISTINE; } } @@ -102,7 +102,7 @@ void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *t ref_offset(this->node->raw), this->node->ofs, this->node->ofs+this->node->size, this->node->frags); mark_ref_normal(this->node->raw); } - + } jffs2_free_node_frag(this); } @@ -117,7 +117,7 @@ static void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_ while (*link) { parent = *link; base = rb_entry(parent, struct jffs2_node_frag, rb); - + if (newfrag->ofs > base->ofs) link = &base->rb.rb_right; else if (newfrag->ofs < base->ofs) @@ -137,7 +137,7 @@ static void jffs2_fragtree_insert(struct jffs2_node_frag *newfrag, struct jffs2_ static inline struct jffs2_node_frag * new_fragment(struct jffs2_full_dnode *fn, uint32_t ofs, uint32_t size) { struct jffs2_node_frag *newfrag; - + newfrag = jffs2_alloc_node_frag(); if (likely(newfrag)) { newfrag->ofs = ofs; @@ -169,7 +169,7 @@ static int no_overlapping_node(struct jffs2_sb_info *c, struct rb_root *root, } if (this) { - /* By definition, the 'this' node has no right-hand child, + /* By definition, the 'this' node has no right-hand child, because there are no frags with offset greater than it. So that's where we want to put the hole */ dbg_fragtree2("add hole frag %#04x-%#04x on the right of the new frag.\n", @@ -183,13 +183,13 @@ static int no_overlapping_node(struct jffs2_sb_info *c, struct rb_root *root, rb_insert_color(&holefrag->rb, root); this = holefrag; } - + if (this) { - /* By definition, the 'this' node has no right-hand child, + /* By definition, the 'this' node has no right-hand child, because there are no frags with offset greater than it. So that's where we want to put new fragment */ dbg_fragtree2("add the new node at the right\n"); - rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); + rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); } else { dbg_fragtree2("insert the new node at the root of the tree\n"); rb_link_node(&newfrag->rb, NULL, &root->rb_node); @@ -216,7 +216,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r dbg_fragtree2("lookup gave no frag\n"); lastend = 0; } - + /* See if we ran off the end of the fragtree */ if (lastend <= newfrag->ofs) { /* We did */ @@ -243,7 +243,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r this->ofs, this->ofs + this->size); /* OK. 'this' is pointing at the first frag that newfrag->ofs at least partially obsoletes, - * - i.e. newfrag->ofs < this->ofs+this->size && newfrag->ofs >= this->ofs + * - i.e. newfrag->ofs < this->ofs+this->size && newfrag->ofs >= this->ofs */ if (newfrag->ofs > this->ofs) { /* This node isn't completely obsoleted. The start of it remains valid */ @@ -261,10 +261,10 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r if (this->node) dbg_fragtree2("split old frag 0x%04x-0x%04x, phys 0x%08x\n", this->ofs, this->ofs+this->size, ref_offset(this->node->raw)); - else + else dbg_fragtree2("split old hole frag 0x%04x-0x%04x\n", this->ofs, this->ofs+this->size); - + /* New second frag pointing to this's node */ newfrag2 = new_fragment(this->node, newfrag->ofs + newfrag->size, this->ofs + this->size - newfrag->ofs - newfrag->size); @@ -284,10 +284,10 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r from newfrag to insert newfrag2. */ jffs2_fragtree_insert(newfrag, this); rb_insert_color(&newfrag->rb, root); - + jffs2_fragtree_insert(newfrag2, newfrag); rb_insert_color(&newfrag2->rb, root); - + return 0; } /* New node just reduces 'this' frag in size, doesn't split it */ @@ -297,13 +297,13 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r jffs2_fragtree_insert(newfrag, this); rb_insert_color(&newfrag->rb, root); } else { - /* New frag starts at the same point as 'this' used to. Replace + /* New frag starts at the same point as 'this' used to. Replace it in the tree without doing a delete and insertion */ dbg_fragtree2("inserting newfrag (*%p),%d-%d in before 'this' (*%p),%d-%d\n", newfrag, newfrag->ofs, newfrag->ofs+newfrag->size, this, this->ofs, this->ofs+this->size); - + rb_replace_node(&this->rb, &newfrag->rb, root); - + if (newfrag->ofs + newfrag->size >= this->ofs+this->size) { dbg_fragtree2("obsoleting node frag %p (%x-%x)\n", this, this->ofs, this->ofs+this->size); jffs2_obsolete_node_frag(c, this); @@ -317,7 +317,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r } } /* OK, now we have newfrag added in the correct place in the tree, but - frag_next(newfrag) may be a fragment which is overlapped by it + frag_next(newfrag) may be a fragment which is overlapped by it */ while ((this = frag_next(newfrag)) && newfrag->ofs + newfrag->size >= this->ofs + this->size) { /* 'this' frag is obsoleted completely. */ @@ -326,7 +326,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r rb_erase(&this->rb, root); jffs2_obsolete_node_frag(c, this); } - /* Now we're pointing at the first frag which isn't totally obsoleted by + /* Now we're pointing at the first frag which isn't totally obsoleted by the new frag */ if (!this || newfrag->ofs + newfrag->size == this->ofs) @@ -344,7 +344,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *r return 0; } -/* +/* * Given an inode, probably with existing tree of fragments, add the new node * to the fragment tree. */ @@ -363,7 +363,7 @@ int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_in dbg_fragtree("adding node %#04x-%#04x @0x%08x on flash, newfrag *%p\n", fn->ofs, fn->ofs+fn->size, ref_offset(fn->raw), newfrag); - + ret = jffs2_add_frag_to_fragtree(c, &f->fragtree, newfrag); if (unlikely(ret)) return ret; @@ -374,14 +374,14 @@ int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_in struct jffs2_node_frag *prev = frag_prev(newfrag); mark_ref_normal(fn->raw); - /* If we don't start at zero there's _always_ a previous */ + /* If we don't start at zero there's _always_ a previous */ if (prev->node) mark_ref_normal(prev->node->raw); } if ((newfrag->ofs+newfrag->size) & (PAGE_CACHE_SIZE-1)) { struct jffs2_node_frag *next = frag_next(newfrag); - + if (next) { mark_ref_normal(fn->raw); if (next->node) @@ -412,7 +412,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info if (!jffs2_is_writebuffered(c)) goto adj_acc; - + /* Calculate how many bytes were already checked */ ofs = ref_offset(ref) + sizeof(struct jffs2_raw_inode); len = ofs % c->wbuf_pagesize; @@ -424,13 +424,13 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info ref_offset(ref), tn->csize, ofs); goto adj_acc; } - + ofs += len; len = tn->csize - len; - + dbg_readinode("check node at %#08x, data length %u, partial CRC %#08x, correct CRC %#08x, data starts at %#08x, start checking from %#08x - %u bytes.\n", ref_offset(ref), tn->csize, tn->partial_crc, tn->data_crc, ofs - len, ofs, len); - + #ifndef __ECOS /* TODO: instead, incapsulate point() stuff to jffs2_flash_read(), * adding and jffs2_flash_read_end() interface. */ @@ -445,12 +445,12 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info pointed = 1; /* succefully pointed to device */ } #endif - + if (!pointed) { buffer = kmalloc(len, GFP_KERNEL); if (unlikely(!buffer)) return -ENOMEM; - + /* TODO: this is very frequent pattern, make it a separate * routine */ err = jffs2_flash_read(c, ofs, len, &retlen, buffer); @@ -458,7 +458,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info JFFS2_ERROR("can not read %d bytes from 0x%08x, error code: %d.\n", len, ofs, err); goto free_out; } - + if (retlen != len) { JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", ofs, retlen, len); err = -EIO; @@ -485,7 +485,7 @@ adj_acc: jeb = &c->blocks[ref->flash_offset / c->sector_size]; len = ref_totlen(c, jeb, ref); - /* + /* * Mark the node as having been checked and fix the * accounting accordingly. */ @@ -516,13 +516,13 @@ free_out: static inline int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn) { int ret; - + BUG_ON(ref_obsolete(tn->fn->raw)); /* We only check the data CRC of unchecked nodes */ if (ref_flags(tn->fn->raw) != REF_UNCHECKED) return 0; - + dbg_fragtree2("check node %#04x-%#04x, phys offs %#08x.\n", tn->fn->ofs, tn->fn->ofs + tn->fn->size, ref_offset(tn->fn->raw)); @@ -538,7 +538,7 @@ static inline int check_node(struct jffs2_sb_info *c, struct jffs2_inode_info *f return ret; } -/* +/* * Helper function for jffs2_add_older_frag_to_fragtree(). * * Called when the new fragment that is being inserted @@ -551,31 +551,31 @@ static int split_hole(struct jffs2_sb_info *c, struct rb_root *root, newfrag->ofs, newfrag->ofs + newfrag->size, hole->ofs, hole->ofs + hole->size); if (hole->ofs == newfrag->ofs) { - /* + /* * Well, the new fragment actually starts at the same offset as * the hole. */ if (hole->ofs + hole->size > newfrag->ofs + newfrag->size) { - /* + /* * We replace the overlapped left part of the hole by * the new node. */ - + dbg_fragtree2("insert fragment %#04x-%#04x and cut the left part of the hole\n", newfrag->ofs, newfrag->ofs + newfrag->size); rb_replace_node(&hole->rb, &newfrag->rb, root); - + hole->ofs += newfrag->size; hole->size -= newfrag->size; - - /* + + /* * We know that 'hole' should be the right hand * fragment. */ jffs2_fragtree_insert(hole, newfrag); rb_insert_color(&hole->rb, root); } else { - /* + /* * Ah, the new fragment is of the same size as the hole. * Relace the hole by it. */ @@ -586,7 +586,7 @@ static int split_hole(struct jffs2_sb_info *c, struct rb_root *root, } } else { /* The new fragment lefts some hole space at the left */ - + struct jffs2_node_frag * newfrag2 = NULL; if (hole->ofs + hole->size > newfrag->ofs + newfrag->size) { @@ -606,7 +606,7 @@ static int split_hole(struct jffs2_sb_info *c, struct rb_root *root, jffs2_fragtree_insert(newfrag, hole); rb_insert_color(&newfrag->rb, root); - + if (newfrag2) { dbg_fragtree2("left the hole %#04x-%#04x at the right\n", newfrag2->ofs, newfrag2->ofs + newfrag2->size); @@ -654,18 +654,18 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode lastend = this->ofs + this->size; else lastend = 0; - + /* Detect the preliminary type of node */ if (fn->size >= PAGE_CACHE_SIZE) ref_flag = REF_PRISTINE; else ref_flag = REF_NORMAL; - + /* See if we ran off the end of the root */ if (lastend <= fn_ofs) { /* We did */ - - /* + + /* * We are going to insert the new node into the * fragment tree, so check it. */ @@ -691,21 +691,21 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode fn->frags = 0; while (1) { - /* + /* * Here we have: * fn_ofs < this->ofs + this->size && fn_ofs >= this->ofs. - * + * * Remember, 'this' has higher version, any non-hole node * which is already in the fragtree is newer then the newly * inserted. */ if (!this->node) { - /* + /* * 'this' is the hole fragment, so at least the * beginning of the new fragment is valid. */ - - /* + + /* * We are going to insert the new node into the * fragment tree, so check it. */ @@ -715,7 +715,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode return err; checked = 1; } - + if (this->ofs + this->size >= fn_ofs + fn_size) { /* We split the hole on two parts */ @@ -730,7 +730,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode goto out_ok; } - /* + /* * The beginning of the new fragment is valid since it * overlaps the hole node. */ @@ -742,9 +742,9 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode this->ofs + this->size - fn_ofs); if (unlikely(!newfrag)) return -ENOMEM; - + if (fn_ofs == this->ofs) { - /* + /* * The new node starts at the same offset as * the hole and supersieds the hole. */ @@ -754,21 +754,21 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode rb_replace_node(&this->rb, &newfrag->rb, root); jffs2_free_node_frag(this); } else { - /* + /* * The hole becomes shorter as its right part * is supersieded by the new fragment. */ dbg_fragtree2("reduce size of hole %#04x-%#04x to %#04x-%#04x\n", this->ofs, this->ofs + this->size, this->ofs, this->ofs + this->size - newfrag->size); - + dbg_fragtree2("add new fragment %#04x-%#04x, refcnt %d\n", fn_ofs, fn_ofs + this->ofs + this->size - fn_ofs, fn->frags); - + this->size -= newfrag->size; jffs2_fragtree_insert(newfrag, this); rb_insert_color(&newfrag->rb, root); } - + fn_ofs += newfrag->size; fn_size -= newfrag->size; this = rb_entry(rb_next(&newfrag->rb), @@ -778,7 +778,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode this->ofs, this->ofs + this->size, this->node ? "(data)" : "(hole)"); } - /* + /* * 'This' node is not the hole so it obsoletes the new fragment * either fully or partially. */ @@ -791,19 +791,19 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode goto out_ok; } else { struct jffs2_node_frag *new_this; - + /* 'This' node obsoletes the beginning of the new node */ dbg_fragtree2("the beginning %#04x-%#04x is obsolete\n", fn_ofs, this->ofs + this->size); ref_flag = REF_NORMAL; - + fn_size -= this->ofs + this->size - fn_ofs; fn_ofs = this->ofs + this->size; dbg_fragtree2("now considering %#04x-%#04x\n", fn_ofs, fn_ofs + fn_size); - + new_this = rb_entry(rb_next(&this->rb), struct jffs2_node_frag, rb); if (!new_this) { - /* + /* * There is no next fragment. Add the rest of * the new node as the right-hand child. */ @@ -813,7 +813,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode return err; checked = 1; } - + fn->frags += 1; newfrag = new_fragment(fn, fn_ofs, fn_size); if (unlikely(!newfrag)) @@ -821,7 +821,7 @@ int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode dbg_fragtree2("there are no more fragments, insert %#04x-%#04x\n", newfrag->ofs, newfrag->ofs + newfrag->size); - rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); + rb_link_node(&newfrag->rb, &this->rb, &this->rb.rb_right); rb_insert_color(&newfrag->rb, root); goto out_ok; } else { @@ -862,9 +862,9 @@ void jffs2_set_inocache_state(struct jffs2_sb_info *c, struct jffs2_inode_cache /* During mount, this needs no locking. During normal operation, its callers want to do other stuff while still holding the inocache_lock. - Rather than introducing special case get_ino_cache functions or + Rather than introducing special case get_ino_cache functions or callbacks, we just let the caller do the locking itself. */ - + struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, uint32_t ino) { struct jffs2_inode_cache *ret; @@ -873,7 +873,7 @@ struct jffs2_inode_cache *jffs2_get_ino_cache(struct jffs2_sb_info *c, uint32_t while (ret && ret->ino < ino) { ret = ret->next; } - + if (ret && ret->ino != ino) ret = NULL; @@ -907,9 +907,9 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old) dbg_inocache("del %p (ino #%u)\n", old, old->ino); spin_lock(&c->inocache_lock); - + prev = &c->inocache_list[old->ino % INOCACHE_HASHSIZE]; - + while ((*prev) && (*prev)->ino < old->ino) { prev = &(*prev)->next; } @@ -919,7 +919,7 @@ void jffs2_del_ino_cache(struct jffs2_sb_info *c, struct jffs2_inode_cache *old) /* Free it now unless it's in READING or CLEARING state, which are the transitions upon read_inode() and clear_inode(). The - rest of the time we know nobody else is looking at it, and + rest of the time we know nobody else is looking at it, and if it's held by read_inode() or clear_inode() they'll free it for themselves. */ if (old->state != INO_STATE_READING && old->state != INO_STATE_CLEARING) @@ -932,7 +932,7 @@ void jffs2_free_ino_caches(struct jffs2_sb_info *c) { int i; struct jffs2_inode_cache *this, *next; - + for (i=0; iinocache_list[i]; while (this) { @@ -959,10 +959,10 @@ void jffs2_free_raw_node_refs(struct jffs2_sb_info *c) c->blocks[i].first_node = c->blocks[i].last_node = NULL; } } - + struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_t offset) { - /* The common case in lookup is that there will be a node + /* The common case in lookup is that there will be a node which precisely matches. So we go looking for that first */ struct rb_node *next; struct jffs2_node_frag *prev = NULL; @@ -993,9 +993,9 @@ struct jffs2_node_frag *jffs2_lookup_node_frag(struct rb_root *fragtree, uint32_ if (prev) dbg_fragtree2("no match. Returning frag %#04x-%#04x, closest previous\n", prev->ofs, prev->ofs+prev->size); - else + else dbg_fragtree2("returning NULL, empty fragtree\n"); - + return prev; } @@ -1010,7 +1010,7 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c) return; dbg_fragtree("killing\n"); - + frag = (rb_entry(root->rb_node, struct jffs2_node_frag, rb)); while(frag) { if (frag->rb.rb_left) { @@ -1023,18 +1023,18 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c) } if (frag->node && !(--frag->node->frags)) { - /* Not a hole, and it's the final remaining frag + /* Not a hole, and it's the final remaining frag of this node. Free the node */ if (c) jffs2_mark_node_obsolete(c, frag->node->raw); - + jffs2_free_full_dnode(frag->node); } parent = frag_parent(frag); if (parent) { if (frag_left(parent) == frag) parent->rb.rb_left = NULL; - else + else parent->rb.rb_right = NULL; } diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 1222372cb290..23a67bb3052f 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -58,7 +58,7 @@ #define je16_to_cpu(x) (le16_to_cpu(x.v16)) #define je32_to_cpu(x) (le32_to_cpu(x.v32)) #define jemode_to_cpu(x) (le32_to_cpu(jffs2_to_os_mode((x).m))) -#else +#else #error wibble #endif @@ -68,7 +68,7 @@ /* This is all we need to keep in-core for each raw node during normal operation. As and when we do read_inode on a particular inode, we can - scan the nodes which are listed for it and build up a proper map of + scan the nodes which are listed for it and build up a proper map of which nodes are currently valid. JFFSv1 always used to keep that whole map in core for each inode. */ @@ -85,7 +85,7 @@ struct jffs2_raw_node_ref /* flash_offset & 3 always has to be zero, because nodes are always aligned at 4 bytes. So we have a couple of extra bits - to play with, which indicate the node's status; see below: */ + to play with, which indicate the node's status; see below: */ #define REF_UNCHECKED 0 /* We haven't yet checked the CRC or built its inode */ #define REF_OBSOLETE 1 /* Obsolete, can be completely ignored */ #define REF_PRISTINE 2 /* Completely clean. GC without looking */ @@ -98,7 +98,7 @@ struct jffs2_raw_node_ref /* For each inode in the filesystem, we need to keep a record of nlink, because it would be a PITA to scan the whole directory tree at read_inode() time to calculate it, and to keep sufficient information - in the raw_node_ref (basically both parent and child inode number for + in the raw_node_ref (basically both parent and child inode number for dirent nodes) would take more space than this does. We also keep a pointer to the first physical node which is part of this inode, too. */ @@ -128,7 +128,7 @@ struct jffs2_inode_cache { #define INOCACHE_HASHSIZE 128 /* - Larger representation of a raw node, kept in-core only when the + Larger representation of a raw node, kept in-core only when the struct inode for this particular ino is instantiated. */ @@ -138,11 +138,11 @@ struct jffs2_full_dnode uint32_t ofs; /* The offset to which the data of this node belongs */ uint32_t size; uint32_t frags; /* Number of fragments which currently refer - to this node. When this reaches zero, + to this node. When this reaches zero, the node is obsolete. */ }; -/* +/* Even larger representation of a raw node, kept in-core only while we're actually building up the original map of which nodes go where, in read_inode() @@ -155,7 +155,7 @@ struct jffs2_tmp_dnode_info uint32_t data_crc; uint32_t partial_crc; uint32_t csize; -}; +}; struct jffs2_full_dirent { @@ -169,7 +169,7 @@ struct jffs2_full_dirent }; /* - Fragments - used to build a map of which raw node to obtain + Fragments - used to build a map of which raw node to obtain data from for each part of the ino */ struct jffs2_node_frag @@ -209,7 +209,7 @@ static inline uint32_t __ref_totlen(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref) { uint32_t ref_end; - + if (ref->next_phys) ref_end = ref_offset(ref->next_phys); else { @@ -264,7 +264,7 @@ static inline uint32_t ref_totlen(struct jffs2_sb_info *c, #define VERYDIRTY(c, size) ((size) >= ((c)->sector_size / 2)) /* check if dirty space is more than 255 Byte */ -#define ISDIRTY(size) ((size) > sizeof (struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN) +#define ISDIRTY(size) ((size) > sizeof (struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN) #define PAD(x) (((x)+3)&~3) @@ -341,7 +341,7 @@ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode); struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, uint32_t flash_ofs, int alloc_mode); int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - struct jffs2_raw_inode *ri, unsigned char *buf, + struct jffs2_raw_inode *ri, unsigned char *buf, uint32_t offset, uint32_t writelen, uint32_t *retlen); int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const char *name, int namelen); int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, int namelen, struct jffs2_inode_info *dead_f, uint32_t time); @@ -349,7 +349,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint /* readinode.c */ -int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, +int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t ino, struct jffs2_raw_inode *latest_node); int jffs2_do_crccheck_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f); diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 2c938d1bffb0..49127a1f0458 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c @@ -88,12 +88,12 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs up(&c->alloc_sem); return -ENOSPC; } - + /* Calc possibly available space. Possibly available means that we * don't know, if unchecked size contains obsoleted nodes, which could give us some * more usable space. This will affect the sum only once, as gc first finishes checking * of nodes. - + Return -ENOSPC, if the maximum possibly available space is less or equal than + + Return -ENOSPC, if the maximum possibly available space is less or equal than * blocksneeded * sector_size. * This blocks endless gc looping on a filesystem, which is nearly full, even if * the check above passes. @@ -118,7 +118,7 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs c->nr_free_blocks, c->nr_erasing_blocks, c->free_size, c->dirty_size, c->wasted_size, c->used_size, c->erasing_size, c->bad_size, c->free_size + c->dirty_size + c->wasted_size + c->used_size + c->erasing_size + c->bad_size, c->flash_size)); spin_unlock(&c->erase_completion_lock); - + ret = jffs2_garbage_collect_pass(c); if (ret) return ret; @@ -183,7 +183,7 @@ static void jffs2_close_nextblock(struct jffs2_sb_info *c, struct jffs2_eraseblo jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); list_add_tail(&jeb->list, &c->dirty_list); } - } else { + } else { D1(printk(KERN_DEBUG "Adding full erase block at 0x%08x to clean_list (free 0x%08x, dirty 0x%08x, used 0x%08x\n", jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); list_add_tail(&jeb->list, &c->clean_list); @@ -197,7 +197,7 @@ static void jffs2_close_nextblock(struct jffs2_sb_info *c, struct jffs2_eraseblo static int jffs2_find_nextblock(struct jffs2_sb_info *c) { struct list_head *next; - + /* Take the next block off the 'free' list */ if (list_empty(&c->free_list)) { @@ -229,8 +229,8 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c) if (!c->nr_erasing_blocks) { /* Ouch. We're in GC, or we wouldn't have got here. And there's no space left. At all. */ - printk(KERN_CRIT "Argh. No free space left for GC. nr_erasing_blocks is %d. nr_free_blocks is %d. (erasableempty: %s, erasingempty: %s, erasependingempty: %s)\n", - c->nr_erasing_blocks, c->nr_free_blocks, list_empty(&c->erasable_list)?"yes":"no", + printk(KERN_CRIT "Argh. No free space left for GC. nr_erasing_blocks is %d. nr_free_blocks is %d. (erasableempty: %s, erasingempty: %s, erasependingempty: %s)\n", + c->nr_erasing_blocks, c->nr_free_blocks, list_empty(&c->erasable_list)?"yes":"no", list_empty(&c->erasing_list)?"yes":"no", list_empty(&c->erase_pending_list)?"yes":"no"); return -ENOSPC; } @@ -250,7 +250,7 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c) list_del(next); c->nextblock = list_entry(next, struct jffs2_eraseblock, list); c->nr_free_blocks--; - + jffs2_sum_reset_collected(c->summary); /* reset collected summary */ D1(printk(KERN_DEBUG "jffs2_find_nextblock(): new nextblock = 0x%08x\n", c->nextblock->offset)); @@ -354,9 +354,9 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin if (c->cleanmarker_size && jeb->used_size == c->cleanmarker_size && !jeb->first_node->next_in_ino) { - /* Only node in it beforehand was a CLEANMARKER node (we think). + /* Only node in it beforehand was a CLEANMARKER node (we think). So mark it obsolete now that there's going to be another node - in the block. This will reduce used_size to zero but We've + in the block. This will reduce used_size to zero but We've already set c->nextblock so that jffs2_mark_node_obsolete() won't try to refile it to the dirty_list. */ @@ -376,12 +376,12 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin * @len: length of this physical node * @dirty: dirty flag for new node * - * Should only be used to report nodes for which space has been allocated + * Should only be used to report nodes for which space has been allocated * by jffs2_reserve_space. * * Must be called with the alloc_sem held. */ - + int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new) { struct jffs2_eraseblock *jeb; @@ -488,8 +488,8 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref if (jffs2_can_mark_obsolete(c) && !jffs2_is_readonly(c) && !(c->flags & (JFFS2_SB_FLAG_SCANNING | JFFS2_SB_FLAG_BUILDING))) { - /* Hm. This may confuse static lock analysis. If any of the above - three conditions is false, we're going to return from this + /* Hm. This may confuse static lock analysis. If any of the above + three conditions is false, we're going to return from this function without actually obliterating any nodes or freeing any jffs2_raw_node_refs. So we don't need to stop erases from happening, or protect against people holding an obsolete @@ -546,17 +546,17 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref D1(printk(KERN_DEBUG "Wasting\n")); addedsize = 0; jeb->wasted_size += ref_totlen(c, jeb, ref); - c->wasted_size += ref_totlen(c, jeb, ref); + c->wasted_size += ref_totlen(c, jeb, ref); } ref->flash_offset = ref_offset(ref) | REF_OBSOLETE; - + jffs2_dbg_acct_sanity_check_nolock(c, jeb); jffs2_dbg_acct_paranoia_check_nolock(c, jeb); if (c->flags & JFFS2_SB_FLAG_SCANNING) { /* Flash scanning is in progress. Don't muck about with the block lists because they're not ready yet, and don't actually - obliterate nodes that look obsolete. If they weren't + obliterate nodes that look obsolete. If they weren't marked obsolete on the flash at the time they _became_ obsolete, there was probably a reason for that. */ spin_unlock(&c->erase_completion_lock); @@ -590,7 +590,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref immediately reused, and we spread the load a bit. */ D1(printk(KERN_DEBUG "...and adding to erasable_list\n")); list_add_tail(&jeb->list, &c->erasable_list); - } + } } D1(printk(KERN_DEBUG "Done OK\n")); } else if (jeb == c->gcblock) { @@ -608,8 +608,8 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref list_add_tail(&jeb->list, &c->very_dirty_list); } else { D1(printk(KERN_DEBUG "Eraseblock at 0x%08x not moved anywhere. (free 0x%08x, dirty 0x%08x, used 0x%08x)\n", - jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); - } + jeb->offset, jeb->free_size, jeb->dirty_size, jeb->used_size)); + } spin_unlock(&c->erase_completion_lock); @@ -656,11 +656,11 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref /* Nodes which have been marked obsolete no longer need to be associated with any inode. Remove them from the per-inode list. - - Note we can't do this for NAND at the moment because we need + + Note we can't do this for NAND at the moment because we need obsolete dirent nodes to stay on the lists, because of the horridness in jffs2_garbage_collect_deletion_dirent(). Also - because we delete the inocache, and on NAND we need that to + because we delete the inocache, and on NAND we need that to stay around until all the nodes are actually erased, in order to stop us from giving the same inode number to another newly created inode. */ @@ -689,7 +689,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref if (ref->next_phys && ref_obsolete(ref->next_phys) && !ref->next_phys->next_in_ino) { struct jffs2_raw_node_ref *n = ref->next_phys; - + spin_lock(&c->erase_completion_lock); ref->__totlen += n->__totlen; @@ -703,7 +703,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref jffs2_free_raw_node_ref(n); } - + /* Also merge with the previous node in the list, if there is one and that one is obsolete */ if (ref != jeb->first_node ) { @@ -713,7 +713,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref while (p->next_phys != ref) p = p->next_phys; - + if (ref_obsolete(p) && !ref->next_in_ino) { p->__totlen += ref->__totlen; if (jeb->last_node == ref) { @@ -753,11 +753,11 @@ int jffs2_thread_should_wake(struct jffs2_sb_info *c) */ dirty = c->dirty_size + c->erasing_size - c->nr_erasing_blocks * c->sector_size; - if (c->nr_free_blocks + c->nr_erasing_blocks < c->resv_blocks_gctrigger && - (dirty > c->nospc_dirty_size)) + if (c->nr_free_blocks + c->nr_erasing_blocks < c->resv_blocks_gctrigger && + (dirty > c->nospc_dirty_size)) ret = 1; - D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x: %s\n", + D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x: %s\n", c->nr_free_blocks, c->nr_erasing_blocks, c->dirty_size, ret?"yes":"no")); return ret; diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index 04d4167ab252..59e7a393200c 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -191,18 +191,18 @@ void jffs2_gc_release_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *jffs2_gc_fetch_inode(struct jffs2_sb_info *c, int inum, int nlink); -unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, - struct jffs2_inode_info *f, +unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, + struct jffs2_inode_info *f, unsigned long offset, unsigned long *priv); void jffs2_gc_release_page(struct jffs2_sb_info *c, unsigned char *pg, unsigned long *priv); void jffs2_flash_cleanup(struct jffs2_sb_info *c); - + /* writev.c */ -int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs, +int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); int jffs2_flash_direct_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, const u_char *buf); diff --git a/fs/jffs2/read.c b/fs/jffs2/read.c index e38e6c5f143a..f3b86da833ba 100644 --- a/fs/jffs2/read.c +++ b/fs/jffs2/read.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: read.c,v 1.41 2005/07/22 10:32:08 dedekind Exp $ + * $Id: read.c,v 1.42 2005/11/07 11:14:41 gleixner Exp $ * */ @@ -43,7 +43,7 @@ int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, } if (readlen != sizeof(*ri)) { jffs2_free_raw_inode(ri); - printk(KERN_WARNING "Short read from 0x%08x: wanted 0x%zx bytes, got 0x%zx\n", + printk(KERN_WARNING "Short read from 0x%08x: wanted 0x%zx bytes, got 0x%zx\n", ref_offset(fd->raw), sizeof(*ri), readlen); return -EIO; } @@ -61,7 +61,7 @@ int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, } /* There was a bug where we wrote hole nodes out with csize/dsize swapped. Deal with it */ - if (ri->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(ri->dsize) && + if (ri->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(ri->dsize) && je32_to_cpu(ri->csize)) { ri->dsize = ri->csize; ri->csize = cpu_to_je32(0); @@ -74,7 +74,7 @@ int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, goto out_ri; }); - + if (ri->compr == JFFS2_COMPR_ZERO) { memset(buf, 0, len); goto out_ri; @@ -82,8 +82,8 @@ int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, /* Cases: Reading whole node and it's uncompressed - read directly to buffer provided, check CRC. - Reading whole node and it's compressed - read into comprbuf, check CRC and decompress to buffer provided - Reading partial node and it's uncompressed - read into readbuf, check CRC, and copy + Reading whole node and it's compressed - read into comprbuf, check CRC and decompress to buffer provided + Reading partial node and it's uncompressed - read into readbuf, check CRC, and copy Reading partial node and it's compressed - read into readbuf, check checksum, decompress to decomprbuf and copy */ if (ri->compr == JFFS2_COMPR_NONE && len == je32_to_cpu(ri->dsize)) { @@ -129,7 +129,7 @@ int jffs2_read_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, D2(printk(KERN_DEBUG "Data CRC matches calculated CRC %08x\n", crc)); if (ri->compr != JFFS2_COMPR_NONE) { D2(printk(KERN_DEBUG "Decompress %d bytes from %p to %d bytes at %p\n", - je32_to_cpu(ri->csize), readbuf, je32_to_cpu(ri->dsize), decomprbuf)); + je32_to_cpu(ri->csize), readbuf, je32_to_cpu(ri->dsize), decomprbuf)); ret = jffs2_decompress(c, f, ri->compr | (ri->usercompr << 8), readbuf, decomprbuf, je32_to_cpu(ri->csize), je32_to_cpu(ri->dsize)); if (ret) { printk(KERN_WARNING "Error: jffs2_decompress returned %d\n", ret); @@ -191,7 +191,7 @@ int jffs2_read_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, } else { uint32_t readlen; uint32_t fragofs; /* offset within the frag to start reading */ - + fragofs = offset - frag->ofs; readlen = min(frag->size - fragofs, end - offset); D1(printk(KERN_DEBUG "Reading %d-%d from node at 0x%08x (%d)\n", diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index 08f8c5ec6118..5f0652df5d47 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.142 2005/09/20 14:27:34 dedekind Exp $ + * $Id: readinode.c,v 1.143 2005/11/07 11:14:41 gleixner Exp $ * */ @@ -116,19 +116,19 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r uint32_t *latest_mctime, uint32_t *mctime_ver) { struct jffs2_full_dirent *fd; - + /* The direntry nodes are checked during the flash scanning */ BUG_ON(ref_flags(ref) == REF_UNCHECKED); /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ BUG_ON(ref_obsolete(ref)); - + /* Sanity check */ if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) { JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n", ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen)); return 1; } - + fd = jffs2_alloc_full_dirent(rd->nsize + 1); if (unlikely(!fd)) return -ENOMEM; @@ -144,39 +144,39 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r *latest_mctime = je32_to_cpu(rd->mctime); } - /* + /* * Copy as much of the name as possible from the raw * dirent we've already read from the flash. */ if (read > sizeof(*rd)) memcpy(&fd->name[0], &rd->name[0], min_t(uint32_t, rd->nsize, (read - sizeof(*rd)) )); - + /* Do we need to copy any more of the name directly from the flash? */ if (rd->nsize + sizeof(*rd) > read) { /* FIXME: point() */ int err; int already = read - sizeof(*rd); - - err = jffs2_flash_read(c, (ref_offset(ref)) + read, + + err = jffs2_flash_read(c, (ref_offset(ref)) + read, rd->nsize - already, &read, &fd->name[already]); if (unlikely(read != rd->nsize - already) && likely(!err)) return -EIO; - + if (unlikely(err)) { JFFS2_ERROR("read remainder of name: error %d\n", err); jffs2_free_full_dirent(fd); return -EIO; } } - + fd->nhash = full_name_hash(fd->name, rd->nsize); fd->next = NULL; fd->name[rd->nsize] = '\0'; - + /* * Wheee. We now have a complete jffs2_full_dirent structure, with - * the name in it and everything. Link it into the list + * the name in it and everything. Link it into the list */ jffs2_add_fd_to_list(c, fd, fdp); @@ -198,7 +198,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref struct jffs2_tmp_dnode_info *tn; uint32_t len, csize; int ret = 1; - + /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ BUG_ON(ref_obsolete(ref)); @@ -210,7 +210,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref tn->partial_crc = 0; csize = je32_to_cpu(rd->csize); - + /* If we've never checked the CRCs on this node, check them now */ if (ref_flags(ref) == REF_UNCHECKED) { uint32_t crc; @@ -221,7 +221,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref ref_offset(ref), je32_to_cpu(rd->node_crc), crc); goto free_out; } - + /* Sanity checks */ if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) || unlikely(PAD(je32_to_cpu(rd->csize) + sizeof(*rd)) != PAD(je32_to_cpu(rd->totlen)))) { @@ -313,13 +313,13 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref ret = -ENOMEM; goto free_out; } - + tn->version = je32_to_cpu(rd->version); tn->fn->ofs = je32_to_cpu(rd->offset); tn->data_crc = je32_to_cpu(rd->data_crc); tn->csize = csize; tn->fn->raw = ref; - + /* There was a bug where we wrote hole nodes out with csize/dsize swapped. Deal with it */ if (rd->compr == JFFS2_COMPR_ZERO && !je32_to_cpu(rd->dsize) && csize) @@ -329,7 +329,7 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref dbg_readinode("dnode @%08x: ver %u, offset %#04x, dsize %#04x, csize %#04x\n", ref_offset(ref), je32_to_cpu(rd->version), je32_to_cpu(rd->offset), je32_to_cpu(rd->dsize), csize); - + jffs2_add_tn_to_tree(tn, tnp); return 0; @@ -351,7 +351,7 @@ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_re { /* We don't mark unknown nodes as REF_UNCHECKED */ BUG_ON(ref_flags(ref) == REF_UNCHECKED); - + un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype)); if (crc32(0, un, sizeof(struct jffs2_unknown_node) - 4) != je32_to_cpu(un->hdr_crc)) { @@ -423,7 +423,7 @@ static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, bufstart = buf + *rdlen; len = right_size - *rdlen; } - + dbg_readinode("read more %d bytes\n", len); err = jffs2_flash_read(c, offs, len, &retlen, bufstart); @@ -432,7 +432,7 @@ static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, "error code: %d.\n", len, offs, err); return err; } - + if (retlen < len) { JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", offs, retlen, len); @@ -460,7 +460,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf int len, err; *mctime_ver = 0; - + dbg_readinode("ino #%u\n", f->inocache->ino); if (jffs2_is_writebuffered(c)) { @@ -487,7 +487,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf buf = kmalloc(len, GFP_KERNEL); if (!buf) return -ENOMEM; - + spin_lock(&c->erase_completion_lock); valid_ref = jffs2_first_valid_node(f->inocache->nodes); if (!valid_ref && f->inocache->ino != 1) @@ -514,7 +514,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf * size = JFFS2_MIN_NODE_HEADER. */ if (jffs2_is_writebuffered(c)) { - /* + /* * We treat 'buf' as 2 adjacent wbufs. We want to * adjust bufstart such as it points to the * beginning of the node within this wbuf. @@ -540,17 +540,17 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf JFFS2_ERROR("can not read %d bytes from 0x%08x, " "error code: %d.\n", len, ref_offset(ref), err); goto free_out; } - + if (retlen < len) { JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", ref_offset(ref), retlen, len); err = -EIO; goto free_out; } - + node = (union jffs2_node_union *)bufstart; - + switch (je16_to_cpu(node->u.nodetype)) { - + case JFFS2_NODETYPE_DIRENT: if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_dirent)) { @@ -558,21 +558,21 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf if (unlikely(err)) goto free_out; } - + err = read_direntry(c, ref, &node->d, retlen, &ret_fd, latest_mctime, mctime_ver); if (err == 1) { jffs2_mark_node_obsolete(c, ref); break; } else if (unlikely(err)) goto free_out; - + if (je32_to_cpu(node->d.version) > *highest_version) *highest_version = je32_to_cpu(node->d.version); break; case JFFS2_NODETYPE_INODE: - + if (JFFS2_MIN_NODE_HEADER < sizeof(struct jffs2_raw_inode)) { err = read_more(c, ref, sizeof(struct jffs2_raw_inode), &len, buf, bufstart); if (unlikely(err)) @@ -588,7 +588,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf if (je32_to_cpu(node->i.version) > *highest_version) *highest_version = je32_to_cpu(node->i.version); - + break; default: @@ -597,7 +597,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf if (unlikely(err)) goto free_out; } - + err = read_unknown(c, ref, &node->u); if (err == 1) { jffs2_mark_node_obsolete(c, ref); @@ -625,7 +625,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf return err; } -static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, +static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *latest_node) { @@ -677,7 +677,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, ret = 0; /* Prevent freeing the metadata update node */ } else jffs2_mark_node_obsolete(c, fn->raw); - + BUG_ON(rb->rb_left); if (rb->rb_parent && rb->rb_parent->rb_left == rb) { /* We were then left-hand child of our parent. We need @@ -763,7 +763,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, } break; - + case S_IFREG: /* If it was a regular file, truncate it to the latest node's isize */ jffs2_truncate_fragtree(c, &f->fragtree, je32_to_cpu(latest_node->isize)); @@ -788,10 +788,10 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, jffs2_do_clear_inode(c, f); return -ENOMEM; } - + ret = jffs2_flash_read(c, ref_offset(fn->raw) + sizeof(*latest_node), je32_to_cpu(latest_node->csize), &retlen, (char *)f->target); - + if (ret || retlen != je32_to_cpu(latest_node->csize)) { if (retlen != je32_to_cpu(latest_node->csize)) ret = -EIO; @@ -805,7 +805,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, f->target[je32_to_cpu(latest_node->csize)] = '\0'; dbg_readinode("symlink's target '%s' cached\n", f->target); } - + /* fall through... */ case S_IFBLK: @@ -848,7 +848,7 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, } /* Scan the list of all nodes present for this ino, build map of versions, etc. */ -int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, +int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t ino, struct jffs2_raw_inode *latest_node) { dbg_readinode("read inode #%u\n", ino); @@ -864,7 +864,7 @@ int jffs2_do_read_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, case INO_STATE_CHECKEDABSENT: f->inocache->state = INO_STATE_READING; break; - + case INO_STATE_CHECKING: case INO_STATE_GC: /* If it's in either of these states, we need @@ -957,7 +957,7 @@ void jffs2_do_clear_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f) kfree(f->target); f->target = NULL; } - + fds = f->dents; while(fds) { fd = fds; diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 805a166469d2..0e7456ec99fd 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -38,11 +38,11 @@ static uint32_t pseudo_random; static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s); -/* These helper functions _must_ increase ofs and also do the dirty/used space accounting. +/* These helper functions _must_ increase ofs and also do the dirty/used space accounting. * Returning an error will abort the mount - bad checksums etc. should just mark the space * as dirty. */ -static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s); static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s); @@ -131,8 +131,8 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) /* Now decide which list to put it on */ switch(ret) { case BLK_STATE_ALLFF: - /* - * Empty block. Since we can't be sure it + /* + * Empty block. Since we can't be sure it * was entirely erased, we just queue it for erase * again. It will be marked as such when the erase * is complete. Meanwhile we still count it as empty @@ -234,7 +234,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) } #ifdef CONFIG_JFFS2_FS_WRITEBUFFER if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size % c->wbuf_pagesize)) { - /* If we're going to start writing into a block which already + /* If we're going to start writing into a block which already contains data, and the end of the data isn't page-aligned, skip a little and align it. */ @@ -250,7 +250,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) } #endif if (c->nr_erasing_blocks) { - if ( !c->used_size && ((c->nr_free_blocks+empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) { + if ( !c->used_size && ((c->nr_free_blocks+empty_blocks+bad_blocks)!= c->nr_blocks || bad_blocks == c->nr_blocks) ) { printk(KERN_NOTICE "Cowardly refusing to erase blocks on filesystem with no valid JFFS2 nodes\n"); printk(KERN_NOTICE "empty_blocks %d, bad_blocks %d, c->nr_blocks %d\n",empty_blocks,bad_blocks,c->nr_blocks); ret = -EIO; @@ -263,7 +263,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) if (buf_size) kfree(flashbuf); #ifndef __ECOS - else + else c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size); #endif return ret; @@ -391,7 +391,7 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo if (err) return err; } - + /* We temporarily use 'ofs' as a pointer into the buffer/jeb */ ofs = 0; @@ -431,7 +431,7 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo dbg_summary("no summary found in jeb 0x%08x. Apply original scan.\n",jeb->offset); -scan_more: +scan_more: while(ofs < jeb->offset + c->sector_size) { jffs2_dbg_acct_paranoia_check_nolock(c, jeb); @@ -496,7 +496,7 @@ scan_more: /* If we're only checking the beginning of a block with a cleanmarker, bail now */ - if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) && + if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) && c->cleanmarker_size && !jeb->dirty_size && !jeb->first_node->next_phys) { D1(printk(KERN_DEBUG "%d bytes at start of block seems clean... assuming all clean\n", EMPTY_SCAN_SIZE(c->sector_size))); return BLK_STATE_CLEANMARKER; @@ -505,7 +505,7 @@ scan_more: /* See how much more there is to read in this eraseblock... */ buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); if (!buf_len) { - /* No more to read. Break out of main loop without marking + /* No more to read. Break out of main loop without marking this range of empty space as dirty (because it's not) */ D1(printk(KERN_DEBUG "Empty flash at %08x runs to end of block. Treating as free_space\n", empty_start)); @@ -540,8 +540,8 @@ scan_more: } if (je16_to_cpu(node->magic) != JFFS2_MAGIC_BITMASK) { /* OK. We're out of possibilities. Whinge and move on */ - noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n", - JFFS2_MAGIC_BITMASK, ofs, + noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n", + JFFS2_MAGIC_BITMASK, ofs, je16_to_cpu(node->magic)); DIRTY_SPACE(4); ofs += 4; @@ -556,7 +556,7 @@ scan_more: if (hdr_crc != je32_to_cpu(node->hdr_crc)) { noisy_printk(&noise, "jffs2_scan_eraseblock(): Node at 0x%08x {0x%04x, 0x%04x, 0x%08x) has invalid CRC 0x%08x (calculated 0x%08x)\n", ofs, je16_to_cpu(node->magic), - je16_to_cpu(node->nodetype), + je16_to_cpu(node->nodetype), je32_to_cpu(node->totlen), je32_to_cpu(node->hdr_crc), hdr_crc); @@ -565,7 +565,7 @@ scan_more: continue; } - if (ofs + je32_to_cpu(node->totlen) > + if (ofs + je32_to_cpu(node->totlen) > jeb->offset + c->sector_size) { /* Eep. Node goes over the end of the erase block. */ printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n", @@ -600,7 +600,7 @@ scan_more: if (err) return err; ofs += PAD(je32_to_cpu(node->totlen)); break; - + case JFFS2_NODETYPE_DIRENT: if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) { buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); @@ -620,7 +620,7 @@ scan_more: case JFFS2_NODETYPE_CLEANMARKER: D1(printk(KERN_DEBUG "CLEANMARKER node found at 0x%08x\n", ofs)); if (je32_to_cpu(node->totlen) != c->cleanmarker_size) { - printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n", + printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n", ofs, je32_to_cpu(node->totlen), c->cleanmarker_size); DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node))); ofs += PAD(sizeof(struct jffs2_unknown_node)); @@ -639,7 +639,7 @@ scan_more: marker_ref->flash_offset = ofs | REF_NORMAL; marker_ref->__totlen = c->cleanmarker_size; jeb->first_node = jeb->last_node = marker_ref; - + USED_SPACE(PAD(c->cleanmarker_size)); ofs += PAD(c->cleanmarker_size); } @@ -690,7 +690,7 @@ scan_more: } } - D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x\n", jeb->offset, + D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x\n", jeb->offset, jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size)); /* mark_node_obsolete can add to wasted !! */ @@ -730,7 +730,7 @@ struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uin return ic; } -static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s) { struct jffs2_raw_node_ref *raw; @@ -740,11 +740,11 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", ofs)); /* We do very little here now. Just check the ino# to which we should attribute - this node; we can do all the CRC checking etc. later. There's a tradeoff here -- + this node; we can do all the CRC checking etc. later. There's a tradeoff here -- we used to scan the flash once only, reading everything we want from it into memory, then building all our in-core data structures and freeing the extra information. Now we allow the first part of the mount to complete a lot quicker, - but we have to go _back_ to the flash in order to finish the CRC checking, etc. + but we have to go _back_ to the flash in order to finish the CRC checking, etc. Which means that the _full_ amount of time to get to proper write mode with GC operational may actually be _longer_ than before. Sucks to be me. */ @@ -790,7 +790,7 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc jeb->last_node->next_phys = raw; jeb->last_node = raw; - D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n", + D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n", je32_to_cpu(ri->ino), je32_to_cpu(ri->version), je32_to_cpu(ri->offset), je32_to_cpu(ri->offset)+je32_to_cpu(ri->dsize))); @@ -806,7 +806,7 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc return 0; } -static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, +static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s) { struct jffs2_raw_node_ref *raw; @@ -840,7 +840,7 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo crc = crc32(0, fd->name, rd->nsize); if (crc != je32_to_cpu(rd->name_crc)) { printk(KERN_NOTICE "jffs2_scan_dirent_node(): Name CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", - ofs, je32_to_cpu(rd->name_crc), crc); + ofs, je32_to_cpu(rd->name_crc), crc); D1(printk(KERN_NOTICE "Name for which CRC failed is (now) '%s', ino #%d\n", fd->name, je32_to_cpu(rd->ino))); jffs2_free_full_dirent(fd); /* FIXME: Why do we believe totlen? */ @@ -860,7 +860,7 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo jffs2_free_raw_node_ref(raw); return -ENOMEM; } - + raw->__totlen = PAD(je32_to_cpu(rd->totlen)); raw->flash_offset = ofs | REF_PRISTINE; raw->next_phys = NULL; diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index 308251266c6c..fb9cec61fcf2 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c @@ -82,7 +82,7 @@ static int jffs2_sum_add_mem(struct jffs2_summary *s, union jffs2_sum_mem *item) je32_to_cpu(item->d.ino)); break; default: - JFFS2_WARNING("UNKNOWN node type %u\n", + JFFS2_WARNING("UNKNOWN node type %u\n", je16_to_cpu(item->u.nodetype)); return 1; } @@ -174,7 +174,7 @@ void jffs2_sum_disable_collecting(struct jffs2_summary *s) s->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; } -int jffs2_sum_is_disabled(struct jffs2_summary *s) +int jffs2_sum_is_disabled(struct jffs2_summary *s) { return (s->sum_size == JFFS2_SUMMARY_NOSUM_SIZE); } @@ -609,7 +609,7 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock sdrnt_ptr->nsize = c->summary->sum_list_head->d.nsize; sdrnt_ptr->type = c->summary->sum_list_head->d.type; - memcpy(sdrnt_ptr->name, c->summary->sum_list_head->d.name, + memcpy(sdrnt_ptr->name, c->summary->sum_list_head->d.name, c->summary->sum_list_head->d.nsize); wpage += JFFS2_SUMMARY_DIRENT_SIZE(c->summary->sum_list_head->d.nsize); @@ -687,7 +687,7 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) datasize = c->summary->sum_size + sizeof(struct jffs2_sum_marker); infosize = sizeof(struct jffs2_raw_summary) + datasize; padsize = jeb->free_size - infosize; - infosize += padsize; + infosize += padsize; datasize += padsize; /* Is there enough space for summary? */ diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 99028af3f69e..9e0b5458d9c0 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: super.c,v 1.109 2005/09/07 08:34:55 havasi Exp $ + * $Id: super.c,v 1.110 2005/11/07 11:14:42 gleixner Exp $ * */ @@ -62,7 +62,7 @@ static int jffs2_sync_fs(struct super_block *sb, int wait) down(&c->alloc_sem); jffs2_flush_wbuf_pad(c); - up(&c->alloc_sem); + up(&c->alloc_sem); return 0; } @@ -112,7 +112,7 @@ static int jffs2_sb_set(struct super_block *sb, void *data) } static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type, - int flags, const char *dev_name, + int flags, const char *dev_name, void *data, struct mtd_info *mtd) { struct super_block *sb; @@ -172,7 +172,7 @@ static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type, } static struct super_block *jffs2_get_sb_mtdnr(struct file_system_type *fs_type, - int flags, const char *dev_name, + int flags, const char *dev_name, void *data, int mtdnr) { struct mtd_info *mtd; @@ -201,7 +201,7 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, /* The preferred way of mounting in future; especially when CONFIG_BLK_DEV is implemented - we specify the underlying - MTD device by number or by name, so that we don't require + MTD device by number or by name, so that we don't require block device support to be present in the kernel. */ /* FIXME: How to do the root fs this way? */ @@ -225,7 +225,7 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, } else if (isdigit(dev_name[3])) { /* Mount by MTD device number name */ char *endptr; - + mtdnr = simple_strtoul(dev_name+3, &endptr, 0); if (!*endptr) { /* It was a valid number */ @@ -235,7 +235,7 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, } } - /* Try the old way - the hack where we allowed users to mount + /* Try the old way - the hack where we allowed users to mount /dev/mtdblock$(n) but didn't actually _use_ the blkdev */ err = path_lookup(dev_name, LOOKUP_FOLLOW, &nd); @@ -376,5 +376,5 @@ module_exit(exit_jffs2_fs); MODULE_DESCRIPTION("The Journalling Flash File System, v2"); MODULE_AUTHOR("Red Hat, Inc."); -MODULE_LICENSE("GPL"); // Actually dual-licensed, but it doesn't matter for +MODULE_LICENSE("GPL"); // Actually dual-licensed, but it doesn't matter for // the sake of this tag. It's Free Software. diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c index 6fd5ee4f90b7..d55754fe8925 100644 --- a/fs/jffs2/symlink.c +++ b/fs/jffs2/symlink.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: symlink.c,v 1.18 2005/11/06 11:03:27 gleixner Exp $ + * $Id: symlink.c,v 1.19 2005/11/07 11:14:42 gleixner Exp $ * */ @@ -21,7 +21,7 @@ static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd); struct inode_operations jffs2_symlink_inode_operations = -{ +{ .readlink = generic_readlink, .follow_link = jffs2_follow_link, .setattr = jffs2_setattr @@ -44,7 +44,7 @@ static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) * stopped using our f->target string which we provide by means of * nd_set_link() call. */ - + if (!p) { printk(KERN_ERR "jffs2_follow_link(): can't find symlink taerget\n"); p = ERR_PTR(-EIO); @@ -52,7 +52,7 @@ static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) D1(printk(KERN_DEBUG "jffs2_follow_link(): target path is '%s'\n", (char *) f->target)); nd_set_link(nd, p); - + /* * We will unlock the f->sem mutex but VFS will use the f->target string. This is safe * since the only way that may cause f->target to be changed is iput() operation. diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 44d8a894a41b..242cd53a970c 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -188,7 +188,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) /* Find the first node to be recovered, by skipping over every node which ends before the wbuf starts, or which is obsolete. */ first_raw = &jeb->first_node; - while (*first_raw && + while (*first_raw && (ref_obsolete(*first_raw) || (ref_offset(*first_raw)+ref_totlen(c, jeb, *first_raw)) < c->wbuf_ofs)) { D1(printk(KERN_DEBUG "Skipping node at 0x%08x(%d)-0x%08x which is either before 0x%08x or obsolete\n", @@ -237,7 +237,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) ret = c->mtd->read_ecc(c->mtd, start, c->wbuf_ofs - start, &retlen, buf, NULL, c->oobinfo); else ret = c->mtd->read(c->mtd, start, c->wbuf_ofs - start, &retlen, buf); - + if (ret == -EBADMSG && retlen == c->wbuf_ofs - start) { /* ECC recovered */ ret = 0; @@ -274,15 +274,15 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) if (end-start >= c->wbuf_pagesize) { /* Need to do another write immediately, but it's possible that this is just because the wbuf itself is completely - full, and there's nothing earlier read back from the - flash. Hence 'buf' isn't necessarily what we're writing + full, and there's nothing earlier read back from the + flash. Hence 'buf' isn't necessarily what we're writing from. */ unsigned char *rewrite_buf = buf?:c->wbuf; uint32_t towrite = (end-start) - ((end-start)%c->wbuf_pagesize); D1(printk(KERN_DEBUG "Write 0x%x bytes at 0x%08x in wbuf recover\n", towrite, ofs)); - + #ifdef BREAKMEHEADER static int breakme; if (breakme++ == 20) { @@ -434,7 +434,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) this happens, if we have a change to a new block, or if fsync forces us to flush the writebuffer. if we have a switch to next page, we will not have - enough remaining space for this. + enough remaining space for this. */ if (pad ) { c->wbuf_len = PAD(c->wbuf_len); @@ -442,7 +442,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) /* Pad with JFFS2_DIRTY_BITMASK initially. this helps out ECC'd NOR with 8 byte page size */ memset(c->wbuf + c->wbuf_len, 0, c->wbuf_pagesize - c->wbuf_len); - + if ( c->wbuf_len + sizeof(struct jffs2_unknown_node) < c->wbuf_pagesize) { struct jffs2_unknown_node *padnode = (void *)(c->wbuf + c->wbuf_len); padnode->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); @@ -453,7 +453,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) } /* else jffs2_flash_writev has actually filled in the rest of the buffer for us, and will deal with the node refs etc. later. */ - + #ifdef BREAKME static int breakme; if (breakme++ == 20) { @@ -462,9 +462,9 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, brokenbuf, NULL, c->oobinfo); ret = -EIO; - } else + } else #endif - + if (jffs2_cleanmarker_oob(c)) ret = c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf, NULL, c->oobinfo); else @@ -485,7 +485,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) } spin_lock(&c->erase_completion_lock); - + /* Adjust free size of the block if we padded. */ if (pad) { struct jffs2_eraseblock *jeb; @@ -495,7 +495,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) D1(printk(KERN_DEBUG "jffs2_flush_wbuf() adjusting free_size of %sblock at %08x\n", (jeb==c->nextblock)?"next":"", jeb->offset)); - /* wbuf_pagesize - wbuf_len is the amount of space that's to be + /* wbuf_pagesize - wbuf_len is the amount of space that's to be padded. If there is less free space in the block than that, something screwed up */ if (jeb->free_size < (c->wbuf_pagesize - c->wbuf_len)) { @@ -523,9 +523,9 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) return 0; } -/* Trigger garbage collection to flush the write-buffer. +/* Trigger garbage collection to flush the write-buffer. If ino arg is zero, do it if _any_ real (i.e. not GC) writes are - outstanding. If ino arg non-zero, do it only if a write for the + outstanding. If ino arg non-zero, do it only if a write for the given inode is outstanding. */ int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino) { @@ -620,13 +620,13 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig /* If not NAND flash, don't bother */ if (!jffs2_is_writebuffered(c)) return jffs2_flash_direct_writev(c, invecs, count, to, retlen); - + down_write(&c->wbuf_sem); /* If wbuf_ofs is not initialized, set it to target address */ if (c->wbuf_ofs == 0xFFFFFFFF) { c->wbuf_ofs = PAGE_DIV(to); - c->wbuf_len = PAGE_MOD(to); + c->wbuf_len = PAGE_MOD(to); memset(c->wbuf,0xff,c->wbuf_pagesize); } @@ -640,10 +640,10 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig memset(c->wbuf,0xff,c->wbuf_pagesize); } } - - /* Sanity checks on target address. - It's permitted to write at PAD(c->wbuf_len+c->wbuf_ofs), - and it's permitted to write at the beginning of a new + + /* Sanity checks on target address. + It's permitted to write at PAD(c->wbuf_len+c->wbuf_ofs), + and it's permitted to write at the beginning of a new erase block. Anything else, and you die. New block starts at xxx000c (0-b = block header) */ @@ -661,8 +661,8 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig } /* set pointer to new block */ c->wbuf_ofs = PAGE_DIV(to); - c->wbuf_len = PAGE_MOD(to); - } + c->wbuf_len = PAGE_MOD(to); + } if (to != PAD(c->wbuf_ofs + c->wbuf_len)) { /* We're not writing immediately after the writebuffer. Bad. */ @@ -682,21 +682,21 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig invec = 0; outvec = 0; - /* Fill writebuffer first, if already in use */ + /* Fill writebuffer first, if already in use */ if (c->wbuf_len) { uint32_t invec_ofs = 0; - /* adjust alignment offset */ + /* adjust alignment offset */ if (c->wbuf_len != PAGE_MOD(to)) { c->wbuf_len = PAGE_MOD(to); /* take care of alignment to next page */ if (!c->wbuf_len) c->wbuf_len = c->wbuf_pagesize; } - + while(c->wbuf_len < c->wbuf_pagesize) { uint32_t thislen; - + if (invec == count) goto alldone; @@ -704,17 +704,17 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig if (thislen >= invecs[invec].iov_len) thislen = invecs[invec].iov_len; - + invec_ofs = thislen; memcpy(c->wbuf + c->wbuf_len, invecs[invec].iov_base, thislen); c->wbuf_len += thislen; donelen += thislen; /* Get next invec, if actual did not fill the buffer */ - if (c->wbuf_len < c->wbuf_pagesize) + if (c->wbuf_len < c->wbuf_pagesize) invec++; - } - + } + /* write buffer is full, flush buffer */ ret = __jffs2_flush_wbuf(c, NOPAD); if (ret) { @@ -773,10 +773,10 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig /* We did cross a page boundary, so we write some now */ if (jffs2_cleanmarker_oob(c)) - ret = c->mtd->writev_ecc(c->mtd, outvecs, splitvec+1, outvec_to, &wbuf_retlen, NULL, c->oobinfo); + ret = c->mtd->writev_ecc(c->mtd, outvecs, splitvec+1, outvec_to, &wbuf_retlen, NULL, c->oobinfo); else ret = jffs2_flash_direct_writev(c, outvecs, splitvec+1, outvec_to, &wbuf_retlen); - + if (ret < 0 || wbuf_retlen != PAGE_DIV(totlen)) { /* At this point we have no problem, c->wbuf is empty. However refile nextblock to avoid @@ -793,7 +793,7 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig spin_unlock(&c->erase_completion_lock); goto exit; } - + donelen += wbuf_retlen; c->wbuf_ofs = PAGE_DIV(outvec_to) + PAGE_DIV(totlen); @@ -837,7 +837,7 @@ alldone: jffs2_wbuf_dirties_inode(c, ino); ret = 0; - + exit: up_write(&c->wbuf_sem); return ret; @@ -880,18 +880,18 @@ int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *re if ( (ret == -EBADMSG) && (*retlen == len) ) { printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx) returned ECC error\n", len, ofs); - /* - * We have the raw data without ECC correction in the buffer, maybe + /* + * We have the raw data without ECC correction in the buffer, maybe * we are lucky and all data or parts are correct. We check the node. * If data are corrupted node check will sort it out. * We keep this block, it will fail on write or erase and the we * mark it bad. Or should we do that now? But we should give him a chance. - * Maybe we had a system crash or power loss before the ecc write or + * Maybe we had a system crash or power loss before the ecc write or * a erase was completed. * So we return success. :) */ ret = 0; - } + } /* if no writebuffer available or write buffer empty, return */ if (!c->wbuf_pagesize || !c->wbuf_len) @@ -906,16 +906,16 @@ int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *re if (owbf > c->wbuf_len) /* is read beyond write buffer ? */ goto exit; lwbf = c->wbuf_len - owbf; /* number of bytes to copy */ - if (lwbf > len) + if (lwbf > len) lwbf = len; - } else { + } else { orbf = (c->wbuf_ofs - ofs); /* offset in read buffer */ if (orbf > len) /* is write beyond write buffer ? */ goto exit; lwbf = len - orbf; /* number of bytes to copy */ - if (lwbf > c->wbuf_len) + if (lwbf > c->wbuf_len) lwbf = c->wbuf_len; - } + } if (lwbf > 0) memcpy(buf+orbf,c->wbuf+owbf,lwbf); @@ -943,7 +943,7 @@ int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb printk(KERN_NOTICE "jffs2_check_oob_empty(): allocation of temporary data buffer for oob check failed\n"); return -ENOMEM; } - /* + /* * if mode = 0, we scan for a total empty oob area, else we have * to take care of the cleanmarker in the first page of the block */ @@ -952,41 +952,41 @@ int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB failed %d for block at %08x\n", ret, jeb->offset)); goto out; } - + if (retlen < len) { D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB return short read " "(%zd bytes not %d) for block at %08x\n", retlen, len, jeb->offset)); ret = -EIO; goto out; } - + /* Special check for first page */ for(i = 0; i < oob_size ; i++) { /* Yeah, we know about the cleanmarker. */ - if (mode && i >= c->fsdata_pos && + if (mode && i >= c->fsdata_pos && i < c->fsdata_pos + c->fsdata_len) continue; if (buf[i] != 0xFF) { D2(printk(KERN_DEBUG "Found %02x at %x in OOB for %08x\n", buf[i], i, jeb->offset)); - ret = 1; + ret = 1; goto out; } } - /* we know, we are aligned :) */ + /* we know, we are aligned :) */ for (page = oob_size; page < len; page += sizeof(long)) { unsigned long dat = *(unsigned long *)(&buf[page]); if(dat != -1) { - ret = 1; + ret = 1; goto out; } } out: - kfree(buf); - + kfree(buf); + return ret; } @@ -1068,7 +1068,7 @@ int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_erasebloc n.totlen = cpu_to_je32(8); ret = jffs2_flash_write_oob(c, jeb->offset + c->fsdata_pos, c->fsdata_len, &retlen, (unsigned char *)&n); - + if (ret) { D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Write failed for block at %08x: error %d\n", jeb->offset, ret)); return ret; @@ -1080,7 +1080,7 @@ int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_erasebloc return 0; } -/* +/* * On NAND we try to mark this block bad. If the block was erased more * than MAX_ERASE_FAILURES we mark it finaly bad. * Don't care about failures. This block remains on the erase-pending @@ -1101,7 +1101,7 @@ int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock * D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Marking bad block at %08x\n", bad_offset)); ret = c->mtd->block_markbad(c->mtd, bad_offset); - + if (ret) { D1(printk(KERN_WARNING "jffs2_write_nand_badblock(): Write failed for block at %08x: error %d\n", jeb->offset, ret)); return ret; @@ -1125,7 +1125,7 @@ static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c) /* Do this only, if we have an oob buffer */ if (!c->mtd->oobsize) return 0; - + /* Cleanmarker is out-of-band, so inline size zero */ c->cleanmarker_size = 0; @@ -1151,7 +1151,7 @@ static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c) c->fsdata_len = NAND_JFFS2_OOB16_FSDALEN; c->badblock_pos = 15; break; - + default: D1(printk(KERN_DEBUG "JFFS2 on NAND. No autoplacment info found\n")); return -EINVAL; @@ -1168,7 +1168,7 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c) init_rwsem(&c->wbuf_sem); c->wbuf_pagesize = c->mtd->oobblock; c->wbuf_ofs = 0xFFFFFFFF; - + c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); if (!c->wbuf) return -ENOMEM; @@ -1194,13 +1194,13 @@ void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c) int jffs2_dataflash_setup(struct jffs2_sb_info *c) { c->cleanmarker_size = 0; /* No cleanmarkers needed */ - + /* Initialize write buffer */ init_rwsem(&c->wbuf_sem); - - + + c->wbuf_pagesize = c->mtd->erasesize; - + /* Find a suitable c->sector_size * - Not too much sectors * - Sectors have to be at least 4 K + some bytes @@ -1210,11 +1210,11 @@ int jffs2_dataflash_setup(struct jffs2_sb_info *c) { */ c->sector_size = 8 * c->mtd->erasesize; - + while (c->sector_size < 8192) { c->sector_size *= 2; } - + /* It may be necessary to adjust the flash size */ c->flash_size = c->mtd->size; @@ -1222,7 +1222,7 @@ int jffs2_dataflash_setup(struct jffs2_sb_info *c) { c->flash_size = (c->flash_size / c->sector_size) * c->sector_size; printk(KERN_WARNING "JFFS2 flash size adjusted to %dKiB\n", c->flash_size); }; - + c->wbuf_ofs = 0xFFFFFFFF; c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); if (!c->wbuf) diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index ea411518d801..1342f0158e9b 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c @@ -7,7 +7,7 @@ * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: write.c,v 1.96 2005/09/07 08:34:55 havasi Exp $ + * $Id: write.c,v 1.97 2005/11/07 11:14:42 gleixner Exp $ * */ @@ -54,7 +54,7 @@ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint return 0; } -/* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it, +/* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it, write it to the flash, link it into the existing inode/fragment list */ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode) @@ -86,7 +86,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 raw = jffs2_alloc_raw_node_ref(); if (!raw) return ERR_PTR(-ENOMEM); - + fn = jffs2_alloc_full_dnode(); if (!fn) { jffs2_free_raw_node_ref(raw); @@ -110,7 +110,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(ri->version) < f->highest_version)) { BUG_ON(!retried); D1(printk(KERN_DEBUG "jffs2_write_dnode : dnode_version %d, " - "highest version %d -> updating dnode\n", + "highest version %d -> updating dnode\n", je32_to_cpu(ri->version), f->highest_version)); ri->version = cpu_to_je32(++f->highest_version); ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); @@ -120,7 +120,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 (alloc_mode==ALLOC_GC)?0:f->inocache->ino); if (ret || (retlen != sizeof(*ri) + datalen)) { - printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", + printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", sizeof(*ri)+datalen, flash_ofs, ret, retlen); /* Mark the space as dirtied */ @@ -128,10 +128,10 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 /* Doesn't belong to any inode */ raw->next_in_ino = NULL; - /* Don't change raw->size to match retlen. We may have + /* Don't change raw->size to match retlen. We may have written the node header already, and only the data will seem corrupted, in which case the scan would skip over - any node we write before the original intended end of + any node we write before the original intended end of this node */ raw->flash_offset |= REF_OBSOLETE; jffs2_add_physical_node_ref(c, raw); @@ -148,7 +148,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 retried = 1; D1(printk(KERN_DEBUG "Retrying failed write.\n")); - + jffs2_dbg_acct_sanity_check(c,jeb); jffs2_dbg_acct_paranoia_check(c, jeb); @@ -159,7 +159,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 /* Locking pain */ up(&f->sem); jffs2_complete_reservation(c); - + ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &flash_ofs, &dummy, alloc_mode, JFFS2_SUMMARY_INODE_SIZE); down(&f->sem); @@ -181,9 +181,9 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 return ERR_PTR(ret?ret:-EIO); } /* Mark the space used */ - /* If node covers at least a whole page, or if it starts at the - beginning of a page and runs to the end of the file, or if - it's a hole node, mark it REF_PRISTINE, else REF_NORMAL. + /* If node covers at least a whole page, or if it starts at the + beginning of a page and runs to the end of the file, or if + it's a hole node, mark it REF_PRISTINE, else REF_NORMAL. */ if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) || ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) && @@ -201,7 +201,7 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 spin_unlock(&c->erase_completion_lock); D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n", - flash_ofs, ref_flags(raw), je32_to_cpu(ri->dsize), + flash_ofs, ref_flags(raw), je32_to_cpu(ri->dsize), je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc), je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen))); @@ -221,7 +221,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff int retried = 0; int ret; - D1(printk(KERN_DEBUG "jffs2_write_dirent(ino #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x)\n", + D1(printk(KERN_DEBUG "jffs2_write_dirent(ino #%u, name at *0x%p \"%s\"->ino #%u, name_crc 0x%08x)\n", je32_to_cpu(rd->pino), name, name, je32_to_cpu(rd->ino), je32_to_cpu(rd->name_crc))); @@ -235,7 +235,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff vecs[0].iov_len = sizeof(*rd); vecs[1].iov_base = (unsigned char *)name; vecs[1].iov_len = namelen; - + jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); raw = jffs2_alloc_raw_node_ref(); @@ -276,7 +276,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff ret = jffs2_flash_writev(c, vecs, 2, flash_ofs, &retlen, (alloc_mode==ALLOC_GC)?0:je32_to_cpu(rd->pino)); if (ret || (retlen != sizeof(*rd) + namelen)) { - printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", + printk(KERN_NOTICE "Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", sizeof(*rd)+namelen, flash_ofs, ret, retlen); /* Mark the space as dirtied */ if (retlen) { @@ -307,7 +307,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff /* Locking pain */ up(&f->sem); jffs2_complete_reservation(c); - + ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &flash_ofs, &dummy, alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); down(&f->sem); @@ -346,7 +346,7 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff we don't have to go digging in struct inode or its equivalent. It should set: mode, uid, gid, (starting)isize, atime, ctime, mtime */ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, - struct jffs2_raw_inode *ri, unsigned char *buf, + struct jffs2_raw_inode *ri, unsigned char *buf, uint32_t offset, uint32_t writelen, uint32_t *retlen) { int ret = 0; @@ -354,7 +354,7 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, D1(printk(KERN_DEBUG "jffs2_write_inode_range(): Ino #%u, ofs 0x%x, len 0x%x\n", f->inocache->ino, offset, writelen)); - + while(writelen) { struct jffs2_full_dnode *fn; unsigned char *comprbuf = NULL; @@ -451,8 +451,8 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str uint32_t alloclen, phys_ofs; int ret; - /* Try to reserve enough space for both node and dirent. - * Just the node will do for now, though + /* Try to reserve enough space for both node and dirent. + * Just the node will do for now, though */ ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); @@ -477,7 +477,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str jffs2_complete_reservation(c); return PTR_ERR(fn); } - /* No data here. Only a metadata node, which will be + /* No data here. Only a metadata node, which will be obsoleted by the first data write */ f->metadata = fn; @@ -486,7 +486,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str jffs2_complete_reservation(c); ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); - + if (ret) { /* Eep. */ D1(printk(KERN_DEBUG "jffs2_reserve_space() for dirent failed\n")); @@ -519,9 +519,9 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL); jffs2_free_raw_dirent(rd); - + if (IS_ERR(fd)) { - /* dirent failed to write. Delete the inode normally + /* dirent failed to write. Delete the inode normally as if it were the final unlink() */ jffs2_complete_reservation(c); up(&dir_f->sem); @@ -548,7 +548,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t alloclen, phys_ofs; int ret; - if (1 /* alternative branch needs testing */ || + if (1 /* alternative branch needs testing */ || !jffs2_can_mark_obsolete(c)) { /* We can't mark stuff obsolete on the medium. We need to write a deletion dirent */ @@ -570,7 +570,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT); rd->totlen = cpu_to_je32(sizeof(*rd) + namelen); rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)); - + rd->pino = cpu_to_je32(dir_f->inocache->ino); rd->version = cpu_to_je32(++dir_f->highest_version); rd->ino = cpu_to_je32(0); @@ -581,7 +581,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_DELETION); - + jffs2_free_raw_dirent(rd); if (IS_ERR(fd)) { @@ -600,7 +600,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, down(&dir_f->sem); while ((*prev) && (*prev)->nhash <= nhash) { - if ((*prev)->nhash == nhash && + if ((*prev)->nhash == nhash && !memcmp((*prev)->name, name, namelen) && !(*prev)->name[namelen]) { struct jffs2_full_dirent *this = *prev; @@ -621,7 +621,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, /* dead_f is NULL if this was a rename not a real unlink */ /* Also catch the !f->inocache case, where there was a dirent pointing to an inode which didn't exist. */ - if (dead_f && dead_f->inocache) { + if (dead_f && dead_f->inocache) { down(&dead_f->sem); @@ -629,9 +629,9 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, while (dead_f->dents) { /* There can be only deleted ones */ fd = dead_f->dents; - + dead_f->dents = fd->next; - + if (fd->ino) { printk(KERN_WARNING "Deleting inode #%u with active dentry \"%s\"->ino #%u\n", dead_f->inocache->ino, fd->name, fd->ino); @@ -672,7 +672,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint jffs2_free_raw_dirent(rd); return ret; } - + down(&dir_f->sem); /* Build a deletion node */ @@ -693,7 +693,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL); - + jffs2_free_raw_dirent(rd); if (IS_ERR(fd)) { diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h index 2788880368c4..cf792bb3c726 100644 --- a/include/linux/jffs2.h +++ b/include/linux/jffs2.h @@ -5,7 +5,7 @@ * * Created by David Woodhouse * - * For licensing information, see the file 'LICENCE' in the + * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * * $Id: jffs2.h,v 1.38 2005/09/26 11:37:23 havasi Exp $ @@ -70,10 +70,10 @@ //#define JFFS2_NODETYPE_OPTIONS (JFFS2_FEATURE_RWCOMPAT_COPY | JFFS2_NODE_ACCURATE | 4) -#define JFFS2_INO_FLAG_PREREAD 1 /* Do read_inode() for this one at - mount time, don't wait for it to +#define JFFS2_INO_FLAG_PREREAD 1 /* Do read_inode() for this one at + mount time, don't wait for it to happen later */ -#define JFFS2_INO_FLAG_USERCOMPR 2 /* User has requested a specific +#define JFFS2_INO_FLAG_USERCOMPR 2 /* User has requested a specific compression type */ @@ -120,7 +120,7 @@ struct jffs2_raw_dirent } __attribute__((packed)); /* The JFFS2 raw inode structure: Used for storage on physical media. */ -/* The uid, gid, atime, mtime and ctime members could be longer, but +/* The uid, gid, atime, mtime and ctime members could be longer, but are left like this for space efficiency. If and when people decide they really need them extended, it's simple enough to add support for a new type of raw node. @@ -165,7 +165,7 @@ struct jffs2_raw_summary jint32_t sum[0]; /* inode summary info */ } __attribute__((packed)); -union jffs2_node_union +union jffs2_node_union { struct jffs2_raw_inode i; struct jffs2_raw_dirent d; diff --git a/include/linux/jffs2_fs_i.h b/include/linux/jffs2_fs_i.h index a5db884ec607..ef85ab56302b 100644 --- a/include/linux/jffs2_fs_i.h +++ b/include/linux/jffs2_fs_i.h @@ -1,4 +1,4 @@ -/* $Id: jffs2_fs_i.h,v 1.18 2005/07/17 11:13:48 dedekind Exp $ */ +/* $Id: jffs2_fs_i.h,v 1.19 2005/11/07 11:14:52 gleixner Exp $ */ #ifndef _JFFS2_FS_I #define _JFFS2_FS_I @@ -25,7 +25,7 @@ struct jffs2_inode_info { /* There may be one datanode which isn't referenced by any of the above fragments, if it contains a metadata update but no actual data - or if this is a directory inode */ - /* This also holds the _only_ dnode for symlinks/device nodes, + /* This also holds the _only_ dnode for symlinks/device nodes, etc. */ struct jffs2_full_dnode *metadata; diff --git a/include/linux/jffs2_fs_sb.h b/include/linux/jffs2_fs_sb.h index fdc445b49e19..4bcfb5570221 100644 --- a/include/linux/jffs2_fs_sb.h +++ b/include/linux/jffs2_fs_sb.h @@ -20,7 +20,7 @@ struct jffs2_inodirty; /* A struct for the overall file system control. Pointers to - jffs2_sb_info structs are named `c' in the source code. + jffs2_sb_info structs are named `c' in the source code. Nee jffs_control */ struct jffs2_sb_info { @@ -35,7 +35,7 @@ struct jffs2_sb_info { struct completion gc_thread_start; /* GC thread start completion */ struct completion gc_thread_exit; /* GC thread exit completion port */ - struct semaphore alloc_sem; /* Used to protect all the following + struct semaphore alloc_sem; /* Used to protect all the following fields, and also to protect against out-of-order writing of nodes. And GC. */ uint32_t cleanmarker_size; /* Size of an _inline_ CLEANMARKER @@ -64,7 +64,7 @@ struct jffs2_sb_info { uint32_t nospc_dirty_size; uint32_t nr_blocks; - struct jffs2_eraseblock *blocks; /* The whole array of blocks. Used for getting blocks + struct jffs2_eraseblock *blocks; /* The whole array of blocks. Used for getting blocks * from the offset (blocks[ofs / sector_size]) */ struct jffs2_eraseblock *nextblock; /* The block we're currently filling */ @@ -82,21 +82,21 @@ struct jffs2_sb_info { struct list_head bad_list; /* Bad blocks. */ struct list_head bad_used_list; /* Bad blocks with valid data in. */ - spinlock_t erase_completion_lock; /* Protect free_list and erasing_list + spinlock_t erase_completion_lock; /* Protect free_list and erasing_list against erase completion handler */ wait_queue_head_t erase_wait; /* For waiting for erases to complete */ wait_queue_head_t inocache_wq; struct jffs2_inode_cache **inocache_list; spinlock_t inocache_lock; - + /* Sem to allow jffs2_garbage_collect_deletion_dirent to - drop the erase_completion_lock while it's holding a pointer + drop the erase_completion_lock while it's holding a pointer to an obsoleted node. I don't like this. Alternatives welcomed. */ struct semaphore erase_free_sem; uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */ - + #ifdef CONFIG_JFFS2_FS_WRITEBUFFER /* Write-behind buffer for NAND flash */ unsigned char *wbuf; -- cgit v1.2.3 From 03ead8427d65f6986a8bf5fd3f29a879348780ad Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Nov 2005 11:15:37 +0000 Subject: [LIB] reed_solomon: Clean up trailing white spaces --- include/linux/rslib.h | 28 +++++++++--------- lib/reed_solomon/Makefile | 2 +- lib/reed_solomon/decode_rs.c | 36 +++++++++++------------ lib/reed_solomon/encode_rs.c | 14 ++++----- lib/reed_solomon/reed_solomon.c | 64 ++++++++++++++++++++--------------------- 5 files changed, 72 insertions(+), 72 deletions(-) (limited to 'include/linux') diff --git a/include/linux/rslib.h b/include/linux/rslib.h index 980c8f74d8dc..ace25acfdc97 100644 --- a/include/linux/rslib.h +++ b/include/linux/rslib.h @@ -1,15 +1,15 @@ -/* +/* * include/linux/rslib.h * * Overview: * Generic Reed Solomon encoder / decoder library - * + * * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de) * * RS code lifted from reed solomon library written by Phil Karn * Copyright 2002 Phil Karn, KA9Q * - * $Id: rslib.h,v 1.3 2004/10/05 22:08:22 gleixner Exp $ + * $Id: rslib.h,v 1.4 2005/11/07 11:14:52 gleixner Exp $ * * 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 @@ -21,20 +21,20 @@ #include -/** +/** * struct rs_control - rs control structure - * + * * @mm: Bits per symbol * @nn: Symbols per block (= (1<mm = number of bits per symbol + * rs->mm = number of bits per symbol * rs->nn = (2^rs->mm) - 1 - * + * * Simple arithmetic modulo would return a wrong result for values * >= 3 * rs->nn */ diff --git a/lib/reed_solomon/Makefile b/lib/reed_solomon/Makefile index 747a2de29346..c3d7136827ed 100644 --- a/lib/reed_solomon/Makefile +++ b/lib/reed_solomon/Makefile @@ -1,5 +1,5 @@ # -# This is a modified version of reed solomon lib, +# This is a modified version of reed solomon lib, # obj-$(CONFIG_REED_SOLOMON) += reed_solomon.o diff --git a/lib/reed_solomon/decode_rs.c b/lib/reed_solomon/decode_rs.c index d401decd6289..a58df56f09b6 100644 --- a/lib/reed_solomon/decode_rs.c +++ b/lib/reed_solomon/decode_rs.c @@ -1,22 +1,22 @@ -/* +/* * lib/reed_solomon/decode_rs.c * * Overview: * Generic Reed Solomon encoder / decoder library - * + * * Copyright 2002, Phil Karn, KA9Q * May be used under the terms of the GNU General Public License (GPL) * * Adaption to the kernel by Thomas Gleixner (tglx@linutronix.de) * - * $Id: decode_rs.c,v 1.6 2004/10/22 15:41:47 gleixner Exp $ + * $Id: decode_rs.c,v 1.7 2005/11/07 11:14:59 gleixner Exp $ * */ -/* Generic data width independent code which is included by the +/* Generic data width independent code which is included by the * wrappers. */ -{ +{ int deg_lambda, el, deg_omega; int i, j, r, k, pad; int nn = rs->nn; @@ -41,9 +41,9 @@ pad = nn - nroots - len; if (pad < 0 || pad >= nn) return -ERANGE; - + /* Does the caller provide the syndrome ? */ - if (s != NULL) + if (s != NULL) goto decode; /* form the syndromes; i.e., evaluate data(x) at roots of @@ -54,11 +54,11 @@ for (j = 1; j < len; j++) { for (i = 0; i < nroots; i++) { if (syn[i] == 0) { - syn[i] = (((uint16_t) data[j]) ^ + syn[i] = (((uint16_t) data[j]) ^ invmsk) & msk; } else { syn[i] = ((((uint16_t) data[j]) ^ - invmsk) & msk) ^ + invmsk) & msk) ^ alpha_to[rs_modnn(rs, index_of[syn[i]] + (fcr + i) * prim)]; } @@ -70,7 +70,7 @@ if (syn[i] == 0) { syn[i] = ((uint16_t) par[j]) & msk; } else { - syn[i] = (((uint16_t) par[j]) & msk) ^ + syn[i] = (((uint16_t) par[j]) & msk) ^ alpha_to[rs_modnn(rs, index_of[syn[i]] + (fcr+i)*prim)]; } @@ -99,14 +99,14 @@ if (no_eras > 0) { /* Init lambda to be the erasure locator polynomial */ - lambda[1] = alpha_to[rs_modnn(rs, + lambda[1] = alpha_to[rs_modnn(rs, prim * (nn - 1 - eras_pos[0]))]; for (i = 1; i < no_eras; i++) { u = rs_modnn(rs, prim * (nn - 1 - eras_pos[i])); for (j = i + 1; j > 0; j--) { tmp = index_of[lambda[j - 1]]; if (tmp != nn) { - lambda[j] ^= + lambda[j] ^= alpha_to[rs_modnn(rs, u + tmp)]; } } @@ -127,8 +127,8 @@ discr_r = 0; for (i = 0; i < r; i++) { if ((lambda[i] != 0) && (s[r - i - 1] != nn)) { - discr_r ^= - alpha_to[rs_modnn(rs, + discr_r ^= + alpha_to[rs_modnn(rs, index_of[lambda[i]] + s[r - i - 1])]; } @@ -143,7 +143,7 @@ t[0] = lambda[0]; for (i = 0; i < nroots; i++) { if (b[i] != nn) { - t[i + 1] = lambda[i + 1] ^ + t[i + 1] = lambda[i + 1] ^ alpha_to[rs_modnn(rs, discr_r + b[i])]; } else @@ -229,7 +229,7 @@ num1 = 0; for (i = deg_omega; i >= 0; i--) { if (omega[i] != nn) - num1 ^= alpha_to[rs_modnn(rs, omega[i] + + num1 ^= alpha_to[rs_modnn(rs, omega[i] + i * root[j])]; } num2 = alpha_to[rs_modnn(rs, root[j] * (fcr - 1) + nn)]; @@ -239,13 +239,13 @@ * lambda_pr of lambda[i] */ for (i = min(deg_lambda, nroots - 1) & ~1; i >= 0; i -= 2) { if (lambda[i + 1] != nn) { - den ^= alpha_to[rs_modnn(rs, lambda[i + 1] + + den ^= alpha_to[rs_modnn(rs, lambda[i + 1] + i * root[j])]; } } /* Apply error to data */ if (num1 != 0 && loc[j] >= pad) { - uint16_t cor = alpha_to[rs_modnn(rs,index_of[num1] + + uint16_t cor = alpha_to[rs_modnn(rs,index_of[num1] + index_of[num2] + nn - index_of[den])]; /* Store the error correction pattern, if a diff --git a/lib/reed_solomon/encode_rs.c b/lib/reed_solomon/encode_rs.c index 237bf65ae886..0b5b1a6728ec 100644 --- a/lib/reed_solomon/encode_rs.c +++ b/lib/reed_solomon/encode_rs.c @@ -1,19 +1,19 @@ -/* +/* * lib/reed_solomon/encode_rs.c * * Overview: * Generic Reed Solomon encoder / decoder library - * + * * Copyright 2002, Phil Karn, KA9Q * May be used under the terms of the GNU General Public License (GPL) * * Adaption to the kernel by Thomas Gleixner (tglx@linutronix.de) * - * $Id: encode_rs.c,v 1.4 2004/10/22 15:41:47 gleixner Exp $ + * $Id: encode_rs.c,v 1.5 2005/11/07 11:14:59 gleixner Exp $ * */ -/* Generic data width independent code which is included by the +/* Generic data width independent code which is included by the * wrappers. * int encode_rsX (struct rs_control *rs, uintX_t *data, int len, uintY_t *par) */ @@ -35,16 +35,16 @@ for (i = 0; i < len; i++) { fb = index_of[((((uint16_t) data[i])^invmsk) & msk) ^ par[0]]; /* feedback term is non-zero */ - if (fb != nn) { + if (fb != nn) { for (j = 1; j < nroots; j++) { - par[j] ^= alpha_to[rs_modnn(rs, fb + + par[j] ^= alpha_to[rs_modnn(rs, fb + genpoly[nroots - j])]; } } /* Shift */ memmove(&par[0], &par[1], sizeof(uint16_t) * (nroots - 1)); if (fb != nn) { - par[nroots - 1] = alpha_to[rs_modnn(rs, + par[nroots - 1] = alpha_to[rs_modnn(rs, fb + genpoly[0])]; } else { par[nroots - 1] = 0; diff --git a/lib/reed_solomon/reed_solomon.c b/lib/reed_solomon/reed_solomon.c index 6604e3b1940c..f5fef948a415 100644 --- a/lib/reed_solomon/reed_solomon.c +++ b/lib/reed_solomon/reed_solomon.c @@ -1,22 +1,22 @@ -/* +/* * lib/reed_solomon/rslib.c * * Overview: * Generic Reed Solomon encoder / decoder library - * + * * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de) * * Reed Solomon code lifted from reed solomon library written by Phil Karn * Copyright 2002 Phil Karn, KA9Q * - * $Id: rslib.c,v 1.5 2004/10/22 15:41:47 gleixner Exp $ + * $Id: rslib.c,v 1.7 2005/11/07 11:14:59 gleixner Exp $ * * 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. * * Description: - * + * * The generic Reed Solomon library provides runtime configurable * encoding / decoding of RS codes. * Each user must call init_rs to get a pointer to a rs_control @@ -25,11 +25,11 @@ * If a structure is generated then the polynomial arrays for * fast encoding / decoding are built. This can take some time so * make sure not to call this function from a time critical path. - * Usually a module / driver should initialize the necessary + * Usually a module / driver should initialize the necessary * rs_control structure on module / driver init and release it * on exit. - * The encoding puts the calculated syndrome into a given syndrome - * buffer. + * The encoding puts the calculated syndrome into a given syndrome + * buffer. * The decoding is a two step process. The first step calculates * the syndrome over the received (data + syndrome) and calls the * second stage, which does the decoding / error correction itself. @@ -51,7 +51,7 @@ static LIST_HEAD (rslist); /* Protection for the list */ static DECLARE_MUTEX(rslistlock); -/** +/** * rs_init - Initialize a Reed-Solomon codec * * @symsize: symbol size, bits (1-8) @@ -63,7 +63,7 @@ static DECLARE_MUTEX(rslistlock); * Allocate a control structure and the polynom arrays for faster * en/decoding. Fill the arrays according to the given parameters */ -static struct rs_control *rs_init(int symsize, int gfpoly, int fcr, +static struct rs_control *rs_init(int symsize, int gfpoly, int fcr, int prim, int nroots) { struct rs_control *rs; @@ -124,15 +124,15 @@ static struct rs_control *rs_init(int symsize, int gfpoly, int fcr, /* Multiply rs->genpoly[] by @**(root + x) */ for (j = i; j > 0; j--) { if (rs->genpoly[j] != 0) { - rs->genpoly[j] = rs->genpoly[j -1] ^ - rs->alpha_to[rs_modnn(rs, + rs->genpoly[j] = rs->genpoly[j -1] ^ + rs->alpha_to[rs_modnn(rs, rs->index_of[rs->genpoly[j]] + root)]; } else rs->genpoly[j] = rs->genpoly[j - 1]; } /* rs->genpoly[0] can never be zero */ - rs->genpoly[0] = - rs->alpha_to[rs_modnn(rs, + rs->genpoly[0] = + rs->alpha_to[rs_modnn(rs, rs->index_of[rs->genpoly[0]] + root)]; } /* convert rs->genpoly[] to index form for quicker encoding */ @@ -153,7 +153,7 @@ errrs: } -/** +/** * free_rs - Free the rs control structure, if its not longer used * * @rs: the control structure which is not longer used by the @@ -173,19 +173,19 @@ void free_rs(struct rs_control *rs) up(&rslistlock); } -/** +/** * init_rs - Find a matching or allocate a new rs control structure * * @symsize: the symbol size (number of bits) * @gfpoly: the extended Galois field generator polynomial coefficients, * with the 0th coefficient in the low order bit. The polynomial * must be primitive; - * @fcr: the first consecutive root of the rs code generator polynomial + * @fcr: the first consecutive root of the rs code generator polynomial * in index form * @prim: primitive element to generate polynomial roots * @nroots: RS code generator polynomial degree (number of roots) */ -struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim, +struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim, int nroots) { struct list_head *tmp; @@ -198,9 +198,9 @@ struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim, return NULL; if (prim <= 0 || prim >= (1<= (1< 8) + if (nroots < 0 || nroots >= (1<gfpoly) continue; if (fcr != rs->fcr) - continue; + continue; if (prim != rs->prim) - continue; + continue; if (nroots != rs->nroots) continue; /* We have a matching one already */ @@ -227,18 +227,18 @@ struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim, rs->users = 1; list_add(&rs->list, &rslist); } -out: +out: up(&rslistlock); return rs; } #ifdef CONFIG_REED_SOLOMON_ENC8 -/** +/** * encode_rs8 - Calculate the parity for data values (8bit data width) * * @rs: the rs control structure * @data: data field of a given type - * @len: data length + * @len: data length * @par: parity data, must be initialized by caller (usually all 0) * @invmsk: invert data mask (will be xored on data) * @@ -246,7 +246,7 @@ out: * symbol size > 8. The calling code must take care of encoding of the * syndrome result for storage itself. */ -int encode_rs8(struct rs_control *rs, uint8_t *data, int len, uint16_t *par, +int encode_rs8(struct rs_control *rs, uint8_t *data, int len, uint16_t *par, uint16_t invmsk) { #include "encode_rs.c" @@ -255,7 +255,7 @@ EXPORT_SYMBOL_GPL(encode_rs8); #endif #ifdef CONFIG_REED_SOLOMON_DEC8 -/** +/** * decode_rs8 - Decode codeword (8bit data width) * * @rs: the rs control structure @@ -273,7 +273,7 @@ EXPORT_SYMBOL_GPL(encode_rs8); * syndrome result and the received parity before calling this code. */ int decode_rs8(struct rs_control *rs, uint8_t *data, uint16_t *par, int len, - uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk, + uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk, uint16_t *corr) { #include "decode_rs.c" @@ -287,13 +287,13 @@ EXPORT_SYMBOL_GPL(decode_rs8); * * @rs: the rs control structure * @data: data field of a given type - * @len: data length + * @len: data length * @par: parity data, must be initialized by caller (usually all 0) * @invmsk: invert data mask (will be xored on data, not on parity!) * * Each field in the data array contains up to symbol size bits of valid data. */ -int encode_rs16(struct rs_control *rs, uint16_t *data, int len, uint16_t *par, +int encode_rs16(struct rs_control *rs, uint16_t *data, int len, uint16_t *par, uint16_t invmsk) { #include "encode_rs.c" @@ -302,7 +302,7 @@ EXPORT_SYMBOL_GPL(encode_rs16); #endif #ifdef CONFIG_REED_SOLOMON_DEC16 -/** +/** * decode_rs16 - Decode codeword (16bit data width) * * @rs: the rs control structure @@ -312,13 +312,13 @@ EXPORT_SYMBOL_GPL(encode_rs16); * @s: syndrome data field (if NULL, syndrome is calculated) * @no_eras: number of erasures * @eras_pos: position of erasures, can be NULL - * @invmsk: invert data mask (will be xored on data, not on parity!) + * @invmsk: invert data mask (will be xored on data, not on parity!) * @corr: buffer to store correction bitmask on eras_pos * * Each field in the data array contains up to symbol size bits of valid data. */ int decode_rs16(struct rs_control *rs, uint16_t *data, uint16_t *par, int len, - uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk, + uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk, uint16_t *corr) { #include "decode_rs.c" -- cgit v1.2.3 From 61ecfa8777d0bc8e33dc0e5c2cca9b3247da2d37 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 7 Nov 2005 11:15:31 +0000 Subject: [MTD] includes: Clean up trailing white spaces Signed-off-by: Thomas Gleixner --- include/linux/mtd/bbm.h | 2 +- include/linux/mtd/blktrans.h | 4 ++-- include/linux/mtd/cfi.h | 24 +++++++++---------- include/linux/mtd/doc2000.h | 18 +++++++------- include/linux/mtd/flashchip.h | 14 +++++------ include/linux/mtd/ftl.h | 6 ++--- include/linux/mtd/gen_probe.h | 4 ++-- include/linux/mtd/jedec.h | 20 ++++++++-------- include/linux/mtd/map.h | 14 +++++------ include/linux/mtd/mtd.h | 24 +++++++++---------- include/linux/mtd/nand.h | 54 +++++++++++++++++++++--------------------- include/linux/mtd/onenand.h | 2 +- include/linux/mtd/partitions.h | 20 ++++++++-------- include/linux/mtd/physmap.h | 12 +++++----- include/linux/mtd/pmc551.h | 12 +++++----- include/linux/mtd/xip.h | 6 ++--- 16 files changed, 118 insertions(+), 118 deletions(-) (limited to 'include/linux') diff --git a/include/linux/mtd/bbm.h b/include/linux/mtd/bbm.h index 92b42cb7ed2e..7a7fbe87fef0 100644 --- a/include/linux/mtd/bbm.h +++ b/include/linux/mtd/bbm.h @@ -29,7 +29,7 @@ * @param version version read from the bbt page during scan * @param len length of the pattern, if 0 no pattern check is performed * @param maxblocks maximum number of blocks to search for a bbt. This number of - * blocks is reserved at the end of the device + * blocks is reserved at the end of the device * where the tables are written. * @param reserved_block_code if non-0, this pattern denotes a reserved * (rather than bad) block in the stored bbt diff --git a/include/linux/mtd/blktrans.h b/include/linux/mtd/blktrans.h index 4ebc2e5a16e2..f46afec6fbf8 100644 --- a/include/linux/mtd/blktrans.h +++ b/include/linux/mtd/blktrans.h @@ -1,5 +1,5 @@ /* - * $Id: blktrans.h,v 1.5 2003/06/23 12:00:08 dwmw2 Exp $ + * $Id: blktrans.h,v 1.6 2005/11/07 11:14:54 gleixner Exp $ * * (C) 2003 David Woodhouse * @@ -67,6 +67,6 @@ extern int register_mtd_blktrans(struct mtd_blktrans_ops *tr); extern int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr); extern int add_mtd_blktrans_dev(struct mtd_blktrans_dev *dev); extern int del_mtd_blktrans_dev(struct mtd_blktrans_dev *dev); - + #endif /* __MTD_TRANS_H__ */ diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index 360cf626c288..39f1430bd6d5 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h @@ -1,7 +1,7 @@ -/* Common Flash Interface structures +/* Common Flash Interface structures * See http://support.intel.com/design/flash/technote/index.htm - * $Id: cfi.h,v 1.55 2005/08/06 04:40:42 nico Exp $ + * $Id: cfi.h,v 1.56 2005/11/07 11:14:54 gleixner Exp $ */ #ifndef __MTD_CFI_H__ @@ -82,8 +82,8 @@ static inline int cfi_interleave_supported(int i) } -/* NB: these values must represents the number of bytes needed to meet the - * device type (x8, x16, x32). Eg. a 32 bit device is 4 x 8 bytes. +/* NB: these values must represents the number of bytes needed to meet the + * device type (x8, x16, x32). Eg. a 32 bit device is 4 x 8 bytes. * These numbers are used in calculations. */ #define CFI_DEVICETYPE_X8 (8 / 8) @@ -259,7 +259,7 @@ static inline uint32_t cfi_build_cmd_addr(uint32_t cmd_ofs, int interleave, int /* * Transforms the CFI command for the given geometry (bus width & interleave). * It looks too long to be inline, but in the common case it should almost all - * get optimised away. + * get optimised away. */ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cfi_private *cfi) { @@ -268,7 +268,7 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf unsigned long onecmd; int i; - /* We do it this way to give the compiler a fighting chance + /* We do it this way to give the compiler a fighting chance of optimising away all the crap for 'bankwidth' larger than an unsigned long, in the common case where that support is disabled */ @@ -279,7 +279,7 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf wordwidth = map_bankwidth(map); words_per_bus = 1; } - + chip_mode = map_bankwidth(map) / cfi_interleave(cfi); chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map); @@ -298,7 +298,7 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf break; } - /* Now replicate it across the size of an unsigned long, or + /* Now replicate it across the size of an unsigned long, or just to the bus width as appropriate */ switch (chips_per_word) { default: BUG(); @@ -314,7 +314,7 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf ; } - /* And finally, for the multi-word case, replicate it + /* And finally, for the multi-word case, replicate it in all words in the structure */ for (i=0; i < words_per_bus; i++) { val.x[i] = onecmd; @@ -325,14 +325,14 @@ static inline map_word cfi_build_cmd(u_long cmd, struct map_info *map, struct cf #define CMD(x) cfi_build_cmd((x), map, cfi) -static inline unsigned long cfi_merge_status(map_word val, struct map_info *map, +static inline unsigned long cfi_merge_status(map_word val, struct map_info *map, struct cfi_private *cfi) { int wordwidth, words_per_bus, chip_mode, chips_per_word; unsigned long onestat, res = 0; int i; - /* We do it this way to give the compiler a fighting chance + /* We do it this way to give the compiler a fighting chance of optimising away all the crap for 'bankwidth' larger than an unsigned long, in the common case where that support is disabled */ @@ -343,7 +343,7 @@ static inline unsigned long cfi_merge_status(map_word val, struct map_info *map, wordwidth = map_bankwidth(map); words_per_bus = 1; } - + chip_mode = map_bankwidth(map) / cfi_interleave(cfi); chips_per_word = wordwidth * cfi_interleave(cfi) / map_bankwidth(map); diff --git a/include/linux/mtd/doc2000.h b/include/linux/mtd/doc2000.h index 953e64fb8ac5..386a52cf8b1b 100644 --- a/include/linux/mtd/doc2000.h +++ b/include/linux/mtd/doc2000.h @@ -1,12 +1,12 @@ -/* +/* * Linux driver for Disk-On-Chip devices * - * Copyright (C) 1999 Machine Vision Holdings, Inc. + * Copyright (C) 1999 Machine Vision Holdings, Inc. * Copyright (C) 2001-2003 David Woodhouse * Copyright (C) 2002-2003 Greg Ungerer * Copyright (C) 2002-2003 SnapGear Inc * - * $Id: doc2000.h,v 1.24 2005/01/05 12:40:38 dwmw2 Exp $ + * $Id: doc2000.h,v 1.25 2005/11/07 11:14:54 gleixner Exp $ * * Released under GPL */ @@ -75,10 +75,10 @@ #define DoC_Mplus_CtrlConfirm 0x1076 #define DoC_Mplus_Power 0x1fff -/* How to access the device? - * On ARM, it'll be mmap'd directly with 32-bit wide accesses. +/* How to access the device? + * On ARM, it'll be mmap'd directly with 32-bit wide accesses. * On PPC, it's mmap'd and 16-bit wide. - * Others use readb/writeb + * Others use readb/writeb */ #if defined(__arm__) #define ReadDOC_(adr, reg) ((unsigned char)(*(volatile __u32 *)(((unsigned long)adr)+((reg)<<2)))) @@ -172,7 +172,7 @@ struct DiskOnChip { unsigned long totlen; unsigned char ChipID; /* Type of DiskOnChip */ int ioreg; - + unsigned long mfr; /* Flash IDs - only one type of flash per device */ unsigned long id; int chipshift; @@ -180,10 +180,10 @@ struct DiskOnChip { char pageadrlen; char interleave; /* Internal interleaving - Millennium Plus style */ unsigned long erasesize; - + int curfloor; int curchip; - + int numchips; struct Nand *chips; struct mtd_info *nextdoc; diff --git a/include/linux/mtd/flashchip.h b/include/linux/mtd/flashchip.h index 675776fa3e27..a293a3b78e05 100644 --- a/include/linux/mtd/flashchip.h +++ b/include/linux/mtd/flashchip.h @@ -1,12 +1,12 @@ -/* +/* * struct flchip definition - * - * Contains information about the location and state of a given flash device + * + * Contains information about the location and state of a given flash device * * (C) 2000 Red Hat. GPLd. * - * $Id: flashchip.h,v 1.17 2005/03/14 18:27:15 bjd Exp $ + * $Id: flashchip.h,v 1.18 2005/11/07 11:14:54 gleixner Exp $ * */ @@ -15,11 +15,11 @@ /* For spinlocks. sched.h includes spinlock.h from whichever directory it * happens to be in - so we don't have to care whether we're on 2.2, which - * has asm/spinlock.h, or 2.4, which has linux/spinlock.h + * has asm/spinlock.h, or 2.4, which has linux/spinlock.h */ #include -typedef enum { +typedef enum { FL_READY, FL_STATUS, FL_CFI_QUERY, @@ -45,7 +45,7 @@ typedef enum { -/* NOTE: confusingly, this can be used to refer to more than one chip at a time, +/* NOTE: confusingly, this can be used to refer to more than one chip at a time, if they're interleaved. This can even refer to individual partitions on the same physical chip when present. */ diff --git a/include/linux/mtd/ftl.h b/include/linux/mtd/ftl.h index 3678459b4535..d99609113307 100644 --- a/include/linux/mtd/ftl.h +++ b/include/linux/mtd/ftl.h @@ -1,6 +1,6 @@ /* - * $Id: ftl.h,v 1.6 2003/01/24 13:20:04 dwmw2 Exp $ - * + * $Id: ftl.h,v 1.7 2005/11/07 11:14:54 gleixner Exp $ + * * Derived from (and probably identical to): * ftl.h 1.7 1999/10/25 20:23:17 * @@ -12,7 +12,7 @@ * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and - * limitations under the License. + * limitations under the License. * * The initial developer of the original code is David A. Hinds * . Portions created by David A. Hinds diff --git a/include/linux/mtd/gen_probe.h b/include/linux/mtd/gen_probe.h index 3d7bdec14f97..256e7342ed1e 100644 --- a/include/linux/mtd/gen_probe.h +++ b/include/linux/mtd/gen_probe.h @@ -1,14 +1,14 @@ /* * (C) 2001, 2001 Red Hat, Inc. * GPL'd - * $Id: gen_probe.h,v 1.3 2004/10/20 22:10:33 dwmw2 Exp $ + * $Id: gen_probe.h,v 1.4 2005/11/07 11:14:54 gleixner Exp $ */ #ifndef __LINUX_MTD_GEN_PROBE_H__ #define __LINUX_MTD_GEN_PROBE_H__ #include -#include +#include #include #include diff --git a/include/linux/mtd/jedec.h b/include/linux/mtd/jedec.h index 2ba0f700ddbc..9006feb218b9 100644 --- a/include/linux/mtd/jedec.h +++ b/include/linux/mtd/jedec.h @@ -1,13 +1,13 @@ /* JEDEC Flash Interface. - * This is an older type of interface for self programming flash. It is + * This is an older type of interface for self programming flash. It is * commonly use in older AMD chips and is obsolete compared with CFI. * It is called JEDEC because the JEDEC association distributes the ID codes * for the chips. * * See the AMD flash databook for information on how to operate the interface. * - * $Id: jedec.h,v 1.3 2003/05/21 11:51:01 dwmw2 Exp $ + * $Id: jedec.h,v 1.4 2005/11/07 11:14:54 gleixner Exp $ */ #ifndef __LINUX_MTD_JEDEC_H__ @@ -33,16 +33,16 @@ struct jedec_flash_chip __u16 jedec; unsigned long size; unsigned long sectorsize; - + // *(__u8*)(base + (adder << addrshift)) = data << datashift // Address size = size << addrshift unsigned long base; // Byte 0 of the flash, will be unaligned unsigned int datashift; // Useful for 32bit/16bit accesses unsigned int addrshift; unsigned long offset; // linerized start. base==offset for unbanked, uninterleaved flash - + __u32 capabilities; - + // These markers are filled in by the flash_chip_scan function unsigned long start; unsigned long length; @@ -51,16 +51,16 @@ struct jedec_flash_chip struct jedec_private { unsigned long size; // Total size of all the devices - + /* Bank handling. If sum(bank_fill) == size then this is linear flash. Otherwise the mapping has holes in it. bank_fill may be used to - find the holes, but in the common symetric case - bank_fill[0] == bank_fill[*], thus addresses may be computed + find the holes, but in the common symetric case + bank_fill[0] == bank_fill[*], thus addresses may be computed mathmatically. bank_fill must be powers of two */ unsigned is_banked; unsigned long bank_fill[MAX_JEDEC_CHIPS]; - - struct jedec_flash_chip chips[MAX_JEDEC_CHIPS]; + + struct jedec_flash_chip chips[MAX_JEDEC_CHIPS]; }; #endif diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h index fc28841f3409..fedfbc8a287f 100644 --- a/include/linux/mtd/map.h +++ b/include/linux/mtd/map.h @@ -1,6 +1,6 @@ /* Overhauled routines for dealing with different mmap regions of flash */ -/* $Id: map.h,v 1.52 2005/05/25 10:29:41 gleixner Exp $ */ +/* $Id: map.h,v 1.54 2005/11/07 11:14:54 gleixner Exp $ */ #ifndef __LINUX_MTD_MAP_H__ #define __LINUX_MTD_MAP_H__ @@ -170,14 +170,14 @@ typedef union { to a chip probe routine -- either JEDEC or CFI probe or both -- via do_map_probe(). If a chip is recognised, the probe code will invoke the appropriate chip driver (if present) and return a struct mtd_info. - At which point, you fill in the mtd->module with your own module + At which point, you fill in the mtd->module with your own module address, and register it with the MTD core code. Or you could partition it and register the partitions instead, or keep it for your own private use; whatever. - + The mtd->priv field will point to the struct map_info, and any further - private data required by the chip driver is linked from the - mtd->priv->fldrv_priv field. This allows the map driver to get at + private data required by the chip driver is linked from the + mtd->priv->fldrv_priv field. This allows the map driver to get at the destructor function map->fldrv_destroy() when it's tired of living. */ @@ -214,7 +214,7 @@ struct map_info { If there is no cache to care about this can be set to NULL. */ void (*inval_cache)(struct map_info *, unsigned long, ssize_t); - /* set_vpp() must handle being reentered -- enable, enable, disable + /* set_vpp() must handle being reentered -- enable, enable, disable must leave it enabled. */ void (*set_vpp)(struct map_info *, int); @@ -353,7 +353,7 @@ static inline map_word map_word_ff(struct map_info *map) { map_word r; int i; - + if (map_bankwidth(map) < MAP_FF_LIMIT) { int bw = 8 * map_bankwidth(map); r.x[0] = (1 << bw) - 1; diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index ab5804183916..e95d0463a3e5 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -1,5 +1,5 @@ -/* - * $Id: mtd.h,v 1.60 2005/08/06 04:40:42 nico Exp $ +/* + * $Id: mtd.h,v 1.61 2005/11/07 11:14:54 gleixner Exp $ * * Copyright (C) 1999-2003 David Woodhouse et al. * @@ -90,13 +90,13 @@ struct mtd_info { // oobinfo is a nand_oobinfo structure, which can be set by iotcl (MEMSETOOBINFO) struct nand_oobinfo oobinfo; - u_int32_t oobavail; // Number of bytes in OOB area available for fs + u_int32_t oobavail; // Number of bytes in OOB area available for fs /* Data for variable erase regions. If numeraseregions is zero, - * it means that the whole device has erasesize as given above. + * it means that the whole device has erasesize as given above. */ int numeraseregions; - struct mtd_erase_region_info *eraseregions; + struct mtd_erase_region_info *eraseregions; /* This really shouldn't be here. It can go away in 2.5 */ u_int32_t bank_size; @@ -119,10 +119,10 @@ struct mtd_info { int (*read_oob) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); int (*write_oob) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); - /* - * Methods to access the protection register area, present in some + /* + * Methods to access the protection register area, present in some * flash devices. The user data is one time programmable but the - * factory data is read only. + * factory data is read only. */ int (*get_fact_prot_info) (struct mtd_info *mtd, struct otp_info *buf, size_t len); int (*read_fact_prot_reg) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); @@ -133,14 +133,14 @@ struct mtd_info { /* kvec-based read/write methods. We need these especially for NAND flash, with its limited number of write cycles per erase. - NB: The 'count' parameter is the number of _vectors_, each of + NB: The 'count' parameter is the number of _vectors_, each of which contains an (ofs, len) tuple. */ int (*readv) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, size_t *retlen); - int (*readv_ecc) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, + int (*readv_ecc) (struct mtd_info *mtd, struct kvec *vecs, unsigned long count, loff_t from, size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel); int (*writev) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen); - int (*writev_ecc) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, + int (*writev_ecc) (struct mtd_info *mtd, const struct kvec *vecs, unsigned long count, loff_t to, size_t *retlen, u_char *eccbuf, struct nand_oobinfo *oobsel); /* Sync */ @@ -204,7 +204,7 @@ int default_mtd_readv(struct mtd_info *mtd, struct kvec *vecs, #define MTD_WRITEECC(mtd, args...) (*(mtd->write_ecc))(mtd, args) #define MTD_READOOB(mtd, args...) (*(mtd->read_oob))(mtd, args) #define MTD_WRITEOOB(mtd, args...) (*(mtd->write_oob))(mtd, args) -#define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd); } while (0) +#define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd); } while (0) #ifdef CONFIG_MTD_PARTITIONS diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 2d36413b2f94..da5e67b3fc70 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -24,7 +24,7 @@ * bat later if I did something naughty. * 10-11-2000 SJH Added private NAND flash structure for driver * 10-24-2000 SJH Added prototype for 'nand_scan' function - * 10-29-2001 TG changed nand_chip structure to support + * 10-29-2001 TG changed nand_chip structure to support * hardwarespecific function for accessing control lines * 02-21-2002 TG added support for different read/write adress and * ready/busy line access function @@ -36,21 +36,21 @@ * CONFIG_MTD_NAND_ECC_JFFS2 is not set * 08-10-2002 TG extensions to nand_chip structure to support HW-ECC * - * 08-29-2002 tglx nand_chip structure: data_poi for selecting + * 08-29-2002 tglx nand_chip structure: data_poi for selecting * internal / fs-driver buffer * support for 6byte/512byte hardware ECC * read_ecc, write_ecc extended for different oob-layout * oob layout selections: NAND_NONE_OOB, NAND_JFFS2_OOB, * NAND_YAFFS_OOB * 11-25-2002 tglx Added Manufacturer code FUJITSU, NATIONAL - * Split manufacturer and device ID structures + * Split manufacturer and device ID structures * * 02-08-2004 tglx added option field to nand structure for chip anomalities * 05-25-2004 tglx added bad block table support, ST-MICRO manufacturer id * update of nand_chip structure description - * 01-17-2005 dmarlin added extended commands for AG-AND device and added option + * 01-17-2005 dmarlin added extended commands for AG-AND device and added option * for BBT_AUTO_REFRESH. - * 01-20-2005 dmarlin added optional pointer to hardware specific callback for + * 01-20-2005 dmarlin added optional pointer to hardware specific callback for * extra error status checks. */ #ifndef __LINUX_MTD_NAND_H @@ -120,8 +120,8 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_ #define NAND_CMD_CACHEDPROG 0x15 /* Extended commands for AG-AND device */ -/* - * Note: the command for NAND_CMD_DEPLETE1 is really 0x00 but +/* + * Note: the command for NAND_CMD_DEPLETE1 is really 0x00 but * there is no way to distinguish that from NAND_CMD_READ0 * until the remaining sequence of commands has been completed * so add a high order bit and mask it off in the command. @@ -145,7 +145,7 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_ #define NAND_STATUS_READY 0x40 #define NAND_STATUS_WP 0x80 -/* +/* * Constants for ECC_MODES */ @@ -191,12 +191,12 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_ #define NAND_CACHEPRG 0x00000008 /* Chip has copy back function */ #define NAND_COPYBACK 0x00000010 -/* AND Chip which has 4 banks and a confusing page / block +/* AND Chip which has 4 banks and a confusing page / block * assignment. See Renesas datasheet for further information */ #define NAND_IS_AND 0x00000020 /* Chip has a array of 4 pages which can be read without * additional ready /busy waits */ -#define NAND_4PAGE_ARRAY 0x00000040 +#define NAND_4PAGE_ARRAY 0x00000040 /* Chip requires that BBT is periodically rewritten to prevent * bits from adjacent blocks from 'leaking' in altering data. * This happens with the Renesas AG-AND chips, possibly others. */ @@ -219,8 +219,8 @@ extern int nand_read_raw (struct mtd_info *mtd, uint8_t *buf, loff_t from, size_ /* Use a flash based bad block table. This option is passed to the * default bad block table function. */ #define NAND_USE_FLASH_BBT 0x00010000 -/* The hw ecc generator provides a syndrome instead a ecc value on read - * This can only work if we have the ecc bytes directly behind the +/* The hw ecc generator provides a syndrome instead a ecc value on read + * This can only work if we have the ecc bytes directly behind the * data bytes. Applies for DOC and AG-AND Renesas HW Reed Solomon generators */ #define NAND_HWECC_SYNDROME 0x00020000 /* This option skips the bbt scan during initialization. */ @@ -252,7 +252,7 @@ struct nand_chip; /** * struct nand_hw_control - Control structure for hardware controller (e.g ECC generator) shared among independend devices - * @lock: protection lock + * @lock: protection lock * @active: the mtd device which holds the controller currently * @wq: wait queue to sleep on if a NAND operation is in progress * used instead of the per chip wait queue when a hw controller is available @@ -265,8 +265,8 @@ struct nand_hw_control { /** * struct nand_chip - NAND Private Flash Chip Data - * @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the flash device - * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the flash device + * @IO_ADDR_R: [BOARDSPECIFIC] address to read the 8 I/O lines of the flash device + * @IO_ADDR_W: [BOARDSPECIFIC] address to write the 8 I/O lines of the flash device * @read_byte: [REPLACEABLE] read one byte from the chip * @write_byte: [REPLACEABLE] write one byte to the chip * @read_word: [REPLACEABLE] read one word from the chip @@ -289,7 +289,7 @@ struct nand_hw_control { * be provided if a hardware ECC is available * @erase_cmd: [INTERN] erase command write function, selectable due to AND support * @scan_bbt: [REPLACEABLE] function to scan bad block table - * @eccmode: [BOARDSPECIFIC] mode of ecc, see defines + * @eccmode: [BOARDSPECIFIC] mode of ecc, see defines * @eccsize: [INTERN] databytes used per ecc-calculation * @eccbytes: [INTERN] number of ecc bytes per ecc-calculation step * @eccsteps: [INTERN] number of ecc calculation steps per page @@ -301,7 +301,7 @@ struct nand_hw_control { * @phys_erase_shift: [INTERN] number of address bits in a physical eraseblock * @bbt_erase_shift: [INTERN] number of address bits in a bbt entry * @chip_shift: [INTERN] number of address bits in one chip - * @data_buf: [INTERN] internal buffer for one page + oob + * @data_buf: [INTERN] internal buffer for one page + oob * @oob_buf: [INTERN] oob buffer for one eraseblock * @oobdirty: [INTERN] indicates that oob_buf must be reinitialized * @data_poi: [INTERN] pointer to a data buffer @@ -316,22 +316,22 @@ struct nand_hw_control { * @bbt: [INTERN] bad block table pointer * @bbt_td: [REPLACEABLE] bad block table descriptor for flash lookup * @bbt_md: [REPLACEABLE] bad block table mirror descriptor - * @badblock_pattern: [REPLACEABLE] bad block scan pattern used for initial bad block scan + * @badblock_pattern: [REPLACEABLE] bad block scan pattern used for initial bad block scan * @controller: [OPTIONAL] a pointer to a hardware controller structure which is shared among multiple independend devices * @priv: [OPTIONAL] pointer to private chip date - * @errstat: [OPTIONAL] hardware specific function to perform additional error status checks + * @errstat: [OPTIONAL] hardware specific function to perform additional error status checks * (determine if errors are correctable) */ - + struct nand_chip { void __iomem *IO_ADDR_R; void __iomem *IO_ADDR_W; - + u_char (*read_byte)(struct mtd_info *mtd); void (*write_byte)(struct mtd_info *mtd, u_char byte); u16 (*read_word)(struct mtd_info *mtd); void (*write_word)(struct mtd_info *mtd, u16 word); - + void (*write_buf)(struct mtd_info *mtd, const u_char *buf, int len); void (*read_buf)(struct mtd_info *mtd, u_char *buf, int len); int (*verify_buf)(struct mtd_info *mtd, const u_char *buf, int len); @@ -396,7 +396,7 @@ struct nand_chip { * @name: Identify the device type * @id: device ID code * @pagesize: Pagesize in bytes. Either 256 or 512 or 0 - * If the pagesize is 0, then the real pagesize + * If the pagesize is 0, then the real pagesize * and the eraseize are determined from the * extended id bytes in the chip * @erasesize: Size of an erase block in the flash device. @@ -425,7 +425,7 @@ struct nand_manufacturers { extern struct nand_flash_dev nand_flash_ids[]; extern struct nand_manufacturers nand_manuf_ids[]; -/** +/** * struct nand_bbt_descr - bad block table descriptor * @options: options for this descriptor * @pages: the page(s) where we find the bbt, used with option BBT_ABSPAGE @@ -436,14 +436,14 @@ extern struct nand_manufacturers nand_manuf_ids[]; * @version: version read from the bbt page during scan * @len: length of the pattern, if 0 no pattern check is performed * @maxblocks: maximum number of blocks to search for a bbt. This number of - * blocks is reserved at the end of the device where the tables are + * blocks is reserved at the end of the device where the tables are * written. * @reserved_block_code: if non-0, this pattern denotes a reserved (rather than * bad) block in the stored bbt - * @pattern: pattern to identify bad block table or factory marked good / + * @pattern: pattern to identify bad block table or factory marked good / * bad blocks, can be NULL, if len = 0 * - * Descriptor for the bad block table marker and the descriptor for the + * Descriptor for the bad block table marker and the descriptor for the * pattern which identifies good and bad blocks. The assumption is made * that the pattern and the version count are always located in the oob area * of the first block. diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index d27fd12d096d..f1fd4215686a 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -77,7 +77,7 @@ struct onenand_bufferram { * @param wq [INTERN] wait queue to sleep on if a OneNAND operation is in progress * @param state [INTERN] the current state of the OneNAND device * @param autooob [REPLACEABLE] the default (auto)placement scheme - * @param bbm [REPLACEABLE] pointer to Bad Block Management + * @param bbm [REPLACEABLE] pointer to Bad Block Management * @param priv [OPTIONAL] pointer to private chip date */ struct onenand_chip { diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h index 50b2edfc8f11..b03f512d51b9 100644 --- a/include/linux/mtd/partitions.h +++ b/include/linux/mtd/partitions.h @@ -5,7 +5,7 @@ * * This code is GPL * - * $Id: partitions.h,v 1.16 2004/11/16 18:34:40 dwmw2 Exp $ + * $Id: partitions.h,v 1.17 2005/11/07 11:14:55 gleixner Exp $ */ #ifndef MTD_PARTITIONS_H @@ -16,25 +16,25 @@ /* * Partition definition structure: - * + * * An array of struct partition is passed along with a MTD object to * add_mtd_partitions() to create them. * * For each partition, these fields are available: * name: string that will be used to label the partition's MTD device. - * size: the partition size; if defined as MTDPART_SIZ_FULL, the partition + * size: the partition size; if defined as MTDPART_SIZ_FULL, the partition * will extend to the end of the master MTD device. - * offset: absolute starting position within the master MTD device; if - * defined as MTDPART_OFS_APPEND, the partition will start where the + * offset: absolute starting position within the master MTD device; if + * defined as MTDPART_OFS_APPEND, the partition will start where the * previous one ended; if MTDPART_OFS_NXTBLK, at the next erase block. - * mask_flags: contains flags that have to be masked (removed) from the + * mask_flags: contains flags that have to be masked (removed) from the * master MTD flag set for the corresponding MTD partition. - * For example, to force a read-only partition, simply adding + * For example, to force a read-only partition, simply adding * MTD_WRITEABLE to the mask_flags will do the trick. * - * Note: writeable partitions require their size and offset be + * Note: writeable partitions require their size and offset be * erasesize aligned (e.g. use MTDPART_OFS_NEXTBLK). - */ + */ struct mtd_partition { char *name; /* identifier string */ @@ -66,7 +66,7 @@ struct mtd_part_parser { extern int register_mtd_parser(struct mtd_part_parser *parser); extern int deregister_mtd_parser(struct mtd_part_parser *parser); -extern int parse_mtd_partitions(struct mtd_info *master, const char **types, +extern int parse_mtd_partitions(struct mtd_info *master, const char **types, struct mtd_partition **pparts, unsigned long origin); #define put_partition_parser(p) do { module_put((p)->owner); } while(0) diff --git a/include/linux/mtd/physmap.h b/include/linux/mtd/physmap.h index 05aa4970677f..c7b8bcdef013 100644 --- a/include/linux/mtd/physmap.h +++ b/include/linux/mtd/physmap.h @@ -1,8 +1,8 @@ /* - * For boards with physically mapped flash and using + * For boards with physically mapped flash and using * drivers/mtd/maps/physmap.c mapping driver. * - * $Id: physmap.h,v 1.3 2004/07/21 00:16:15 jwboyer Exp $ + * $Id: physmap.h,v 1.4 2005/11/07 11:14:55 gleixner Exp $ * * Copyright (C) 2003 MontaVista Software Inc. * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net @@ -18,7 +18,7 @@ #include -#if defined(CONFIG_MTD_PHYSMAP) +#if defined(CONFIG_MTD_PHYSMAP) #include #include @@ -44,12 +44,12 @@ static inline void physmap_configure(unsigned long addr, unsigned long size, int #if defined(CONFIG_MTD_PARTITIONS) /* - * Machines that wish to do flash partition may want to call this function in - * their setup routine. + * Machines that wish to do flash partition may want to call this function in + * their setup routine. * * physmap_set_partitions(mypartitions, num_parts); * - * Note that one can always override this hard-coded partition with + * Note that one can always override this hard-coded partition with * command line partition (you need to enable CONFIG_MTD_CMDLINE_PARTS). */ void physmap_set_partitions(struct mtd_partition *parts, int num_parts); diff --git a/include/linux/mtd/pmc551.h b/include/linux/mtd/pmc551.h index 113e3087f68a..a7f6d20ad407 100644 --- a/include/linux/mtd/pmc551.h +++ b/include/linux/mtd/pmc551.h @@ -1,5 +1,5 @@ /* - * $Id: pmc551.h,v 1.5 2003/01/24 16:49:53 dwmw2 Exp $ + * $Id: pmc551.h,v 1.6 2005/11/07 11:14:55 gleixner Exp $ * * PMC551 PCI Mezzanine Ram Device * @@ -7,7 +7,7 @@ * Mark Ferrell * Copyright 1999,2000 Nortel Networks * - * License: + * License: * As part of this driver was derrived from the slram.c driver it falls * under the same license, which is GNU General Public License v2 */ @@ -17,7 +17,7 @@ #include -#define PMC551_VERSION "$Id: pmc551.h,v 1.5 2003/01/24 16:49:53 dwmw2 Exp $\n"\ +#define PMC551_VERSION "$Id: pmc551.h,v 1.6 2005/11/07 11:14:55 gleixner Exp $\n"\ "Ramix PMC551 PCI Mezzanine Ram Driver. (C) 1999,2000 Nortel Networks.\n" /* @@ -30,7 +30,7 @@ struct mypriv { u32 curr_map0; u32 asize; struct mtd_info *nextpmc551; -}; +}; /* * Function Prototypes @@ -39,7 +39,7 @@ static int pmc551_erase(struct mtd_info *, struct erase_info *); static void pmc551_unpoint(struct mtd_info *, u_char *, loff_t, size_t); static int pmc551_point (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char **mtdbuf); static int pmc551_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *); -static int pmc551_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); +static int pmc551_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); /* @@ -50,7 +50,7 @@ static int pmc551_write(struct mtd_info *, loff_t, size_t, size_t *, const u_cha #endif #ifndef PCI_DEVICE_ID_V3_SEMI_V370PDC -#define PCI_DEVICE_ID_V3_SEMI_V370PDC 0x0200 +#define PCI_DEVICE_ID_V3_SEMI_V370PDC 0x0200 #endif diff --git a/include/linux/mtd/xip.h b/include/linux/mtd/xip.h index 863fa5a1d24e..220d50bb71cd 100644 --- a/include/linux/mtd/xip.h +++ b/include/linux/mtd/xip.h @@ -12,7 +12,7 @@ * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * - * $Id: xip.h,v 1.4 2005/10/17 21:03:16 nico Exp $ + * $Id: xip.h,v 1.5 2005/11/07 11:14:55 gleixner Exp $ */ #ifndef __LINUX_MTD_XIP_H__ @@ -60,9 +60,9 @@ * overflowing. * * xip_iprefetch() - * + * * Macro to fill instruction prefetch - * e.g. a series of nops: asm volatile (".rep 8; nop; .endr"); + * e.g. a series of nops: asm volatile (".rep 8; nop; .endr"); */ #include -- cgit v1.2.3 From 2109a2d1b175dfcffbfdac693bdbe4c4ab62f11f Mon Sep 17 00:00:00 2001 From: Pekka J Enberg Date: Mon, 7 Nov 2005 00:58:01 -0800 Subject: [PATCH] mm: rename kmem_cache_s to kmem_cache This patch renames struct kmem_cache_s to kmem_cache so we can start using it instead of kmem_cache_t typedef. Signed-off-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/magic-number.txt | 2 +- fs/file_table.c | 4 ++-- fs/freevxfs/vxfs_extern.h | 4 ++-- fs/xfs/linux-2.6/kmem.h | 4 ++-- include/linux/file.h | 6 +++--- include/linux/slab.h | 2 +- mm/slab.c | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) (limited to 'include/linux') diff --git a/Documentation/magic-number.txt b/Documentation/magic-number.txt index bd8eefa17587..af67faccf4de 100644 --- a/Documentation/magic-number.txt +++ b/Documentation/magic-number.txt @@ -120,7 +120,7 @@ ISDN_NET_MAGIC 0x49344C02 isdn_net_local_s drivers/isdn/i4l/isdn_net_li SAVEKMSG_MAGIC2 0x4B4D5347 savekmsg arch/*/amiga/config.c STLI_BOARDMAGIC 0x4bc6c825 stlibrd include/linux/istallion.h CS_STATE_MAGIC 0x4c4f4749 cs_state sound/oss/cs46xx.c -SLAB_C_MAGIC 0x4f17a36d kmem_cache_s mm/slab.c +SLAB_C_MAGIC 0x4f17a36d kmem_cache mm/slab.c COW_MAGIC 0x4f4f4f4d cow_header_v1 arch/um/drivers/ubd_user.c I810_CARD_MAGIC 0x5072696E i810_card sound/oss/i810_audio.c TRIDENT_CARD_MAGIC 0x5072696E trident_card sound/oss/trident.c diff --git a/fs/file_table.c b/fs/file_table.c index 4dc205546547..c3a5e2fd663b 100644 --- a/fs/file_table.c +++ b/fs/file_table.c @@ -35,7 +35,7 @@ static DEFINE_SPINLOCK(filp_count_lock); * context and must be fully threaded - use a local spinlock * to protect files_stat.nr_files */ -void filp_ctor(void * objp, struct kmem_cache_s *cachep, unsigned long cflags) +void filp_ctor(void *objp, struct kmem_cache *cachep, unsigned long cflags) { if ((cflags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) { @@ -46,7 +46,7 @@ void filp_ctor(void * objp, struct kmem_cache_s *cachep, unsigned long cflags) } } -void filp_dtor(void * objp, struct kmem_cache_s *cachep, unsigned long dflags) +void filp_dtor(void *objp, struct kmem_cache *cachep, unsigned long dflags) { unsigned long flags; spin_lock_irqsave(&filp_count_lock, flags); diff --git a/fs/freevxfs/vxfs_extern.h b/fs/freevxfs/vxfs_extern.h index d8be917f9797..927acf70c591 100644 --- a/fs/freevxfs/vxfs_extern.h +++ b/fs/freevxfs/vxfs_extern.h @@ -38,7 +38,7 @@ */ -struct kmem_cache_s; +struct kmem_cache; struct super_block; struct vxfs_inode_info; struct inode; @@ -51,7 +51,7 @@ extern daddr_t vxfs_bmap1(struct inode *, long); extern int vxfs_read_fshead(struct super_block *); /* vxfs_inode.c */ -extern struct kmem_cache_s *vxfs_inode_cachep; +extern struct kmem_cache *vxfs_inode_cachep; extern void vxfs_dumpi(struct vxfs_inode_info *, ino_t); extern struct inode * vxfs_get_fake_inode(struct super_block *, struct vxfs_inode_info *); diff --git a/fs/xfs/linux-2.6/kmem.h b/fs/xfs/linux-2.6/kmem.h index 8f82c1a20dc5..c64a29cdfff3 100644 --- a/fs/xfs/linux-2.6/kmem.h +++ b/fs/xfs/linux-2.6/kmem.h @@ -30,8 +30,8 @@ #define KM_NOFS 0x0004u #define KM_MAYFAIL 0x0008u -#define kmem_zone kmem_cache_s -#define kmem_zone_t kmem_cache_t +#define kmem_zone kmem_cache +#define kmem_zone_t struct kmem_cache typedef unsigned long xfs_pflags_t; diff --git a/include/linux/file.h b/include/linux/file.h index f5bbd4c508b3..d3b1a15d5f21 100644 --- a/include/linux/file.h +++ b/include/linux/file.h @@ -59,9 +59,9 @@ extern void FASTCALL(set_close_on_exec(unsigned int fd, int flag)); extern void put_filp(struct file *); extern int get_unused_fd(void); extern void FASTCALL(put_unused_fd(unsigned int fd)); -struct kmem_cache_s; -extern void filp_ctor(void * objp, struct kmem_cache_s *cachep, unsigned long cflags); -extern void filp_dtor(void * objp, struct kmem_cache_s *cachep, unsigned long dflags); +struct kmem_cache; +extern void filp_ctor(void * objp, struct kmem_cache *cachep, unsigned long cflags); +extern void filp_dtor(void * objp, struct kmem_cache *cachep, unsigned long dflags); extern struct file ** alloc_fd_array(int); extern void free_fd_array(struct file **, int); diff --git a/include/linux/slab.h b/include/linux/slab.h index 09b9aa60063d..d1ea4051b996 100644 --- a/include/linux/slab.h +++ b/include/linux/slab.h @@ -9,7 +9,7 @@ #if defined(__KERNEL__) -typedef struct kmem_cache_s kmem_cache_t; +typedef struct kmem_cache kmem_cache_t; #include /* kmalloc_sizes.h needs CONFIG_ options */ #include diff --git a/mm/slab.c b/mm/slab.c index 41e91794aa50..d77e5f50fba9 100644 --- a/mm/slab.c +++ b/mm/slab.c @@ -368,7 +368,7 @@ static inline void kmem_list3_init(struct kmem_list3 *parent) * manages a cache. */ -struct kmem_cache_s { +struct kmem_cache { /* 1) per-cpu data, touched during every alloc/free */ struct array_cache *array[NR_CPUS]; unsigned int batchcount; -- cgit v1.2.3 From 055a2512144cd7e60dcaae7a13e460df43b98787 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 7 Nov 2005 00:58:21 -0800 Subject: [PATCH] superhyway: multiple block support and VCR rework This extends the API somewhat to allow for platform-specific VCR reading and writing. Some platforms (like SH4-202) implement the VCR in a split VCRL and VCRH, but end up being in reverse order or have other quirks that need to be dealt with, so we add a set of superhyway_ops per-bus to accomodate this. We also have to extend the per-device resources somewhat, as some devices now conveniently split control and data blocks. So we allow a platform to register its set of SuperHyway devices via superhyway_add_devices() with the control block always ordered as the first resource (as this is the one that userspace cares about). Signed-off-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/sh/superhyway/superhyway-sysfs.c | 2 +- drivers/sh/superhyway/superhyway.c | 75 +++++++++++++++++++++++--------- include/linux/superhyway.h | 38 +++++++++++++--- 3 files changed, 89 insertions(+), 26 deletions(-) (limited to 'include/linux') diff --git a/drivers/sh/superhyway/superhyway-sysfs.c b/drivers/sh/superhyway/superhyway-sysfs.c index dc119ce68e3e..55434330867b 100644 --- a/drivers/sh/superhyway/superhyway-sysfs.c +++ b/drivers/sh/superhyway/superhyway-sysfs.c @@ -30,7 +30,7 @@ superhyway_ro_attr(bot_mb, "0x%02x\n", vcr.bot_mb); superhyway_ro_attr(top_mb, "0x%02x\n", vcr.top_mb); /* Misc */ -superhyway_ro_attr(resource, "0x%08lx\n", resource.start); +superhyway_ro_attr(resource, "0x%08lx\n", resource[0].start); struct device_attribute superhyway_dev_attrs[] = { __ATTR_RO(perr_flags), diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c index 28757cb9d246..7bdab2a7f59c 100644 --- a/drivers/sh/superhyway/superhyway.c +++ b/drivers/sh/superhyway/superhyway.c @@ -27,19 +27,20 @@ static struct device superhyway_bus_device = { static void superhyway_device_release(struct device *dev) { - kfree(to_superhyway_device(dev)); + struct superhyway_device *sdev = to_superhyway_device(dev); + + kfree(sdev->resource); + kfree(sdev); } /** * superhyway_add_device - Add a SuperHyway module - * @mod_id: Module ID (taken from MODULE.VCR.MOD_ID). * @base: Physical address where module is mapped. - * @vcr: VCR value. + * @sdev: SuperHyway device to add, or NULL to allocate a new one. + * @bus: Bus where SuperHyway module resides. * * This is responsible for adding a new SuperHyway module. This sets up a new - * struct superhyway_device for the module being added. Each one of @mod_id, - * @base, and @vcr are registered with the new device for further use - * elsewhere. + * struct superhyway_device for the module being added if @sdev == NULL. * * Devices are initially added in the order that they are scanned (from the * top-down of the memory map), and are assigned an ID based on the order that @@ -49,28 +50,40 @@ static void superhyway_device_release(struct device *dev) * Further work can and should be done in superhyway_scan_bus(), to be sure * that any new modules are properly discovered and subsequently registered. */ -int superhyway_add_device(unsigned int mod_id, unsigned long base, - unsigned long long vcr) +int superhyway_add_device(unsigned long base, struct superhyway_device *sdev, + struct superhyway_bus *bus) { - struct superhyway_device *dev; + struct superhyway_device *dev = sdev; + + if (!dev) { + dev = kmalloc(sizeof(struct superhyway_device), GFP_KERNEL); + if (!dev) + return -ENOMEM; - dev = kmalloc(sizeof(struct superhyway_device), GFP_KERNEL); - if (!dev) - return -ENOMEM; + memset(dev, 0, sizeof(struct superhyway_device)); + } - memset(dev, 0, sizeof(struct superhyway_device)); + dev->bus = bus; + superhyway_read_vcr(dev, base, &dev->vcr); - dev->id.id = mod_id; - sprintf(dev->name, "SuperHyway device %04x", dev->id.id); + if (!dev->resource) { + dev->resource = kmalloc(sizeof(struct resource), GFP_KERNEL); + if (!dev->resource) { + kfree(dev); + return -ENOMEM; + } + + dev->resource->name = dev->name; + dev->resource->start = base; + dev->resource->end = dev->resource->start + 0x01000000; + } - dev->vcr = *((struct vcr_info *)(&vcr)); - dev->resource.name = dev->name; - dev->resource.start = base; - dev->resource.end = dev->resource.start + 0x01000000; dev->dev.parent = &superhyway_bus_device; dev->dev.bus = &superhyway_bus_type; dev->dev.release = superhyway_device_release; + dev->id.id = dev->vcr.mod_id; + sprintf(dev->name, "SuperHyway device %04x", dev->id.id); sprintf(dev->dev.bus_id, "%02x", superhyway_devices); superhyway_devices++; @@ -78,10 +91,31 @@ int superhyway_add_device(unsigned int mod_id, unsigned long base, return device_register(&dev->dev); } +int superhyway_add_devices(struct superhyway_bus *bus, + struct superhyway_device **devices, + int nr_devices) +{ + int i, ret = 0; + + for (i = 0; i < nr_devices; i++) { + struct superhyway_device *dev = devices[i]; + ret |= superhyway_add_device(dev->resource[0].start, dev, bus); + } + + return ret; +} + static int __init superhyway_init(void) { + struct superhyway_bus *bus; + int ret = 0; + device_register(&superhyway_bus_device); - return superhyway_scan_bus(); + + for (bus = superhyway_channels; bus->ops; bus++) + ret |= superhyway_scan_bus(bus); + + return ret; } postcore_initcall(superhyway_init); @@ -197,6 +231,7 @@ module_exit(superhyway_bus_exit); EXPORT_SYMBOL(superhyway_bus_type); EXPORT_SYMBOL(superhyway_add_device); +EXPORT_SYMBOL(superhyway_add_devices); EXPORT_SYMBOL(superhyway_register_driver); EXPORT_SYMBOL(superhyway_unregister_driver); diff --git a/include/linux/superhyway.h b/include/linux/superhyway.h index c906c5a0aaef..17ea468fa362 100644 --- a/include/linux/superhyway.h +++ b/include/linux/superhyway.h @@ -19,7 +19,7 @@ */ #define SUPERHYWAY_DEVICE_ID_SH5_DMAC 0x0183 -struct vcr_info { +struct superhyway_vcr_info { u8 perr_flags; /* P-port Error flags */ u8 merr_flags; /* Module Error flags */ u16 mod_vers; /* Module Version */ @@ -28,6 +28,17 @@ struct vcr_info { u8 top_mb; /* Top Memory block */ }; +struct superhyway_ops { + int (*read_vcr)(unsigned long base, struct superhyway_vcr_info *vcr); + int (*write_vcr)(unsigned long base, struct superhyway_vcr_info vcr); +}; + +struct superhyway_bus { + struct superhyway_ops *ops; +}; + +extern struct superhyway_bus superhyway_channels[]; + struct superhyway_device_id { unsigned int id; unsigned long driver_data; @@ -55,9 +66,11 @@ struct superhyway_device { struct superhyway_device_id id; struct superhyway_driver *drv; + struct superhyway_bus *bus; - struct resource resource; - struct vcr_info vcr; + int num_resources; + struct resource *resource; + struct superhyway_vcr_info vcr; }; #define to_superhyway_device(d) container_of((d), struct superhyway_device, dev) @@ -65,12 +78,27 @@ struct superhyway_device { #define superhyway_get_drvdata(d) dev_get_drvdata(&(d)->dev) #define superhyway_set_drvdata(d,p) dev_set_drvdata(&(d)->dev, (p)) -extern int superhyway_scan_bus(void); +static inline int +superhyway_read_vcr(struct superhyway_device *dev, unsigned long base, + struct superhyway_vcr_info *vcr) +{ + return dev->bus->ops->read_vcr(base, vcr); +} + +static inline int +superhyway_write_vcr(struct superhyway_device *dev, unsigned long base, + struct superhyway_vcr_info vcr) +{ + return dev->bus->ops->write_vcr(base, vcr); +} + +extern int superhyway_scan_bus(struct superhyway_bus *); /* drivers/sh/superhyway/superhyway.c */ int superhyway_register_driver(struct superhyway_driver *); void superhyway_unregister_driver(struct superhyway_driver *); -int superhyway_add_device(unsigned int, unsigned long, unsigned long long); +int superhyway_add_device(unsigned long base, struct superhyway_device *, struct superhyway_bus *); +int superhyway_add_devices(struct superhyway_bus *bus, struct superhyway_device **devices, int nr_devices); /* drivers/sh/superhyway/superhyway-sysfs.c */ extern struct device_attribute superhyway_dev_attrs[]; -- cgit v1.2.3 From 9f46080c41d5f3f7c00b4e169ba4b0b2865258bf Mon Sep 17 00:00:00 2001 From: Matt Helsley Date: Mon, 7 Nov 2005 00:59:16 -0800 Subject: [PATCH] Process Events Connector This patch adds a connector that reports fork, exec, id change, and exit events for all processes to userspace. It replaces the fork_advisor patch that ELSA is currently using. Applications that may find these events useful include accounting/auditing (e.g. ELSA), system activity monitoring (e.g. top), security, and resource management (e.g. CKRM). Signed-off-by: Matt Helsley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/connector/Kconfig | 8 ++ drivers/connector/Makefile | 1 + drivers/connector/cn_proc.c | 222 ++++++++++++++++++++++++++++++++++++++++++++ fs/exec.c | 2 + include/linux/cn_proc.h | 127 +++++++++++++++++++++++++ include/linux/connector.h | 6 ++ kernel/exit.c | 2 + kernel/fork.c | 2 + kernel/sys.c | 9 ++ 9 files changed, 379 insertions(+) create mode 100644 drivers/connector/cn_proc.c create mode 100644 include/linux/cn_proc.h (limited to 'include/linux') diff --git a/drivers/connector/Kconfig b/drivers/connector/Kconfig index 0bc2059c1e08..e0bdc0db9640 100644 --- a/drivers/connector/Kconfig +++ b/drivers/connector/Kconfig @@ -10,4 +10,12 @@ config CONNECTOR Connector support can also be built as a module. If so, the module will be called cn.ko. +config PROC_EVENTS + boolean "Report process events to userspace" + depends on CONNECTOR=y + default y + ---help--- + Provide a connector that reports process events to userspace. Send + events such as fork, exec, id change (uid, gid, suid, etc), and exit. + endmenu diff --git a/drivers/connector/Makefile b/drivers/connector/Makefile index 12ca79e8234d..1f255e46e916 100644 --- a/drivers/connector/Makefile +++ b/drivers/connector/Makefile @@ -1,3 +1,4 @@ obj-$(CONFIG_CONNECTOR) += cn.o +obj-$(CONFIG_PROC_EVENTS) += cn_proc.o cn-y += cn_queue.o connector.o diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c new file mode 100644 index 000000000000..fcdf0fff13a6 --- /dev/null +++ b/drivers/connector/cn_proc.c @@ -0,0 +1,222 @@ +/* + * cn_proc.c - process events connector + * + * Copyright (C) Matt Helsley, IBM Corp. 2005 + * Based on cn_fork.c by Guillaume Thouvenin + * Original copyright notice follows: + * Copyright (C) 2005 BULL SA. + * + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include + +#define CN_PROC_MSG_SIZE (sizeof(struct cn_msg) + sizeof(struct proc_event)) + +static atomic_t proc_event_num_listeners = ATOMIC_INIT(0); +static struct cb_id cn_proc_event_id = { CN_IDX_PROC, CN_VAL_PROC }; + +/* proc_counts is used as the sequence number of the netlink message */ +static DEFINE_PER_CPU(__u32, proc_event_counts) = { 0 }; + +static inline void get_seq(__u32 *ts, int *cpu) +{ + *ts = get_cpu_var(proc_event_counts)++; + *cpu = smp_processor_id(); + put_cpu_var(proc_counts); +} + +void proc_fork_connector(struct task_struct *task) +{ + struct cn_msg *msg; + struct proc_event *ev; + __u8 buffer[CN_PROC_MSG_SIZE]; + + if (atomic_read(&proc_event_num_listeners) < 1) + return; + + msg = (struct cn_msg*)buffer; + ev = (struct proc_event*)msg->data; + get_seq(&msg->seq, &ev->cpu); + ev->what = PROC_EVENT_FORK; + ev->event_data.fork.parent_pid = task->real_parent->pid; + ev->event_data.fork.parent_tgid = task->real_parent->tgid; + ev->event_data.fork.child_pid = task->pid; + ev->event_data.fork.child_tgid = task->tgid; + + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = 0; /* not used */ + msg->len = sizeof(*ev); + /* If cn_netlink_send() failed, the data is not sent */ + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); +} + +void proc_exec_connector(struct task_struct *task) +{ + struct cn_msg *msg; + struct proc_event *ev; + __u8 buffer[CN_PROC_MSG_SIZE]; + + if (atomic_read(&proc_event_num_listeners) < 1) + return; + + msg = (struct cn_msg*)buffer; + ev = (struct proc_event*)msg->data; + get_seq(&msg->seq, &ev->cpu); + ev->what = PROC_EVENT_EXEC; + ev->event_data.exec.process_pid = task->pid; + ev->event_data.exec.process_tgid = task->tgid; + + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = 0; /* not used */ + msg->len = sizeof(*ev); + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); +} + +void proc_id_connector(struct task_struct *task, int which_id) +{ + struct cn_msg *msg; + struct proc_event *ev; + __u8 buffer[CN_PROC_MSG_SIZE]; + + if (atomic_read(&proc_event_num_listeners) < 1) + return; + + msg = (struct cn_msg*)buffer; + ev = (struct proc_event*)msg->data; + ev->what = which_id; + ev->event_data.id.process_pid = task->pid; + ev->event_data.id.process_tgid = task->tgid; + if (which_id == PROC_EVENT_UID) { + ev->event_data.id.r.ruid = task->uid; + ev->event_data.id.e.euid = task->euid; + } else if (which_id == PROC_EVENT_GID) { + ev->event_data.id.r.rgid = task->gid; + ev->event_data.id.e.egid = task->egid; + } else + return; + get_seq(&msg->seq, &ev->cpu); + + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = 0; /* not used */ + msg->len = sizeof(*ev); + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); +} + +void proc_exit_connector(struct task_struct *task) +{ + struct cn_msg *msg; + struct proc_event *ev; + __u8 buffer[CN_PROC_MSG_SIZE]; + + if (atomic_read(&proc_event_num_listeners) < 1) + return; + + msg = (struct cn_msg*)buffer; + ev = (struct proc_event*)msg->data; + get_seq(&msg->seq, &ev->cpu); + ev->what = PROC_EVENT_EXIT; + ev->event_data.exit.process_pid = task->pid; + ev->event_data.exit.process_tgid = task->tgid; + ev->event_data.exit.exit_code = task->exit_code; + ev->event_data.exit.exit_signal = task->exit_signal; + + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = 0; /* not used */ + msg->len = sizeof(*ev); + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); +} + +/* + * Send an acknowledgement message to userspace + * + * Use 0 for success, EFOO otherwise. + * Note: this is the negative of conventional kernel error + * values because it's not being returned via syscall return + * mechanisms. + */ +static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack) +{ + struct cn_msg *msg; + struct proc_event *ev; + __u8 buffer[CN_PROC_MSG_SIZE]; + + if (atomic_read(&proc_event_num_listeners) < 1) + return; + + msg = (struct cn_msg*)buffer; + ev = (struct proc_event*)msg->data; + msg->seq = rcvd_seq; + ev->cpu = -1; + ev->what = PROC_EVENT_NONE; + ev->event_data.ack.err = err; + memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); + msg->ack = rcvd_ack + 1; + msg->len = sizeof(*ev); + cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); +} + +/** + * cn_proc_mcast_ctl + * @data: message sent from userspace via the connector + */ +static void cn_proc_mcast_ctl(void *data) +{ + struct cn_msg *msg = data; + enum proc_cn_mcast_op *mc_op = NULL; + int err = 0; + + if (msg->len != sizeof(*mc_op)) + return; + + mc_op = (enum proc_cn_mcast_op*)msg->data; + switch (*mc_op) { + case PROC_CN_MCAST_LISTEN: + atomic_inc(&proc_event_num_listeners); + break; + case PROC_CN_MCAST_IGNORE: + atomic_dec(&proc_event_num_listeners); + break; + default: + err = EINVAL; + break; + } + cn_proc_ack(err, msg->seq, msg->ack); +} + +/* + * cn_proc_init - initialization entry point + * + * Adds the connector callback to the connector driver. + */ +static int __init cn_proc_init(void) +{ + int err; + + if ((err = cn_add_callback(&cn_proc_event_id, "cn_proc", + &cn_proc_mcast_ctl))) { + printk(KERN_WARNING "cn_proc failed to register\n"); + return err; + } + return 0; +} + +module_init(cn_proc_init); diff --git a/fs/exec.c b/fs/exec.c index 10d493fea7ce..ce76b33f25ac 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include @@ -1096,6 +1097,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) fput(bprm->file); bprm->file = NULL; current->did_exec = 1; + proc_exec_connector(current); return retval; } read_lock(&binfmt_lock); diff --git a/include/linux/cn_proc.h b/include/linux/cn_proc.h new file mode 100644 index 000000000000..70ab56317380 --- /dev/null +++ b/include/linux/cn_proc.h @@ -0,0 +1,127 @@ +/* + * cn_proc.h - process events connector + * + * Copyright (C) Matt Helsley, IBM Corp. 2005 + * Based on cn_fork.h by Nguyen Anh Quynh and Guillaume Thouvenin + * Original copyright notice follows: + * Copyright (C) 2005 Nguyen Anh Quynh + * Copyright (C) 2005 Guillaume Thouvenin + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef CN_PROC_H +#define CN_PROC_H + +#include +#include + +/* + * Userspace sends this enum to register with the kernel that it is listening + * for events on the connector. + */ +enum proc_cn_mcast_op { + PROC_CN_MCAST_LISTEN = 1, + PROC_CN_MCAST_IGNORE = 2 +}; + +/* + * From the user's point of view, the process + * ID is the thread group ID and thread ID is the internal + * kernel "pid". So, fields are assigned as follow: + * + * In user space - In kernel space + * + * parent process ID = parent->tgid + * parent thread ID = parent->pid + * child process ID = child->tgid + * child thread ID = child->pid + */ + +struct proc_event { + enum what { + /* Use successive bits so the enums can be used to record + * sets of events as well + */ + PROC_EVENT_NONE = 0x00000000, + PROC_EVENT_FORK = 0x00000001, + PROC_EVENT_EXEC = 0x00000002, + PROC_EVENT_UID = 0x00000004, + PROC_EVENT_GID = 0x00000040, + /* "next" should be 0x00000400 */ + /* "last" is the last process event: exit */ + PROC_EVENT_EXIT = 0x80000000 + } what; + __u32 cpu; + union { /* must be last field of proc_event struct */ + struct { + __u32 err; + } ack; + + struct fork_proc_event { + pid_t parent_pid; + pid_t parent_tgid; + pid_t child_pid; + pid_t child_tgid; + } fork; + + struct exec_proc_event { + pid_t process_pid; + pid_t process_tgid; + } exec; + + struct id_proc_event { + pid_t process_pid; + pid_t process_tgid; + union { + uid_t ruid; /* current->uid */ + gid_t rgid; /* current->gid */ + } r; + union { + uid_t euid; + gid_t egid; + } e; + } id; + + struct exit_proc_event { + pid_t process_pid; + pid_t process_tgid; + __u32 exit_code, exit_signal; + } exit; + } event_data; +}; + +#ifdef __KERNEL__ +#ifdef CONFIG_PROC_EVENTS +void proc_fork_connector(struct task_struct *task); +void proc_exec_connector(struct task_struct *task); +void proc_id_connector(struct task_struct *task, int which_id); +void proc_exit_connector(struct task_struct *task); +#else +static inline void proc_fork_connector(struct task_struct *task) +{} + +static inline void proc_exec_connector(struct task_struct *task) +{} + +static inline void proc_id_connector(struct task_struct *task, + int which_id) +{} + +static inline void proc_exit_connector(struct task_struct *task) +{} +#endif /* CONFIG_PROC_EVENTS */ +#endif /* __KERNEL__ */ +#endif /* CN_PROC_H */ diff --git a/include/linux/connector.h b/include/linux/connector.h index 95952cc1f525..c5769c6585f4 100644 --- a/include/linux/connector.h +++ b/include/linux/connector.h @@ -27,6 +27,12 @@ #define CN_IDX_CONNECTOR 0xffffffff #define CN_VAL_CONNECTOR 0xffffffff +/* + * Process Events connector unique ids -- used for message routing + */ +#define CN_IDX_PROC 0x1 +#define CN_VAL_PROC 0x1 + #define CN_NETLINK_USERS 1 /* diff --git a/kernel/exit.c b/kernel/exit.c index 537394b25e8d..452a1d116178 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -863,6 +864,7 @@ fastcall NORET_TYPE void do_exit(long code) module_put(tsk->binfmt->module); tsk->exit_code = code; + proc_exit_connector(tsk); exit_notify(tsk); #ifdef CONFIG_NUMA mpol_free(tsk->mempolicy); diff --git a/kernel/fork.c b/kernel/fork.c index 8a069612eac3..efac2c58ec7d 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include @@ -1143,6 +1144,7 @@ static task_t *copy_process(unsigned long clone_flags, __get_cpu_var(process_counts)++; } + proc_fork_connector(p); if (!current->signal->tty && p->signal->tty) p->signal->tty = NULL; diff --git a/kernel/sys.c b/kernel/sys.c index 2fa1ed18123c..1e1f41b3fdf6 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -623,6 +624,7 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid) current->egid = new_egid; current->gid = new_rgid; key_fsgid_changed(current); + proc_id_connector(current, PROC_EVENT_GID); return 0; } @@ -662,6 +664,7 @@ asmlinkage long sys_setgid(gid_t gid) return -EPERM; key_fsgid_changed(current); + proc_id_connector(current, PROC_EVENT_GID); return 0; } @@ -751,6 +754,7 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid) current->fsuid = current->euid; key_fsuid_changed(current); + proc_id_connector(current, PROC_EVENT_UID); return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RE); } @@ -798,6 +802,7 @@ asmlinkage long sys_setuid(uid_t uid) current->suid = new_suid; key_fsuid_changed(current); + proc_id_connector(current, PROC_EVENT_UID); return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_ID); } @@ -846,6 +851,7 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid) current->suid = suid; key_fsuid_changed(current); + proc_id_connector(current, PROC_EVENT_UID); return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RES); } @@ -898,6 +904,7 @@ asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid) current->sgid = sgid; key_fsgid_changed(current); + proc_id_connector(current, PROC_EVENT_GID); return 0; } @@ -940,6 +947,7 @@ asmlinkage long sys_setfsuid(uid_t uid) } key_fsuid_changed(current); + proc_id_connector(current, PROC_EVENT_UID); security_task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS); @@ -968,6 +976,7 @@ asmlinkage long sys_setfsgid(gid_t gid) } current->fsgid = gid; key_fsgid_changed(current); + proc_id_connector(current, PROC_EVENT_GID); } return old_fsgid; } -- cgit v1.2.3 From 665a7583f32ab5b3bfe7a4d88da506542f7cdd75 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 7 Nov 2005 00:59:17 -0800 Subject: [PATCH] Remove hlist_for_each_rcu() API, convert existing use to hlist_for_each_entry_rcu Remove the hlist_for_each_rcu() API, which is used only in one place, and is trivially converted to hlist_for_each_entry_rcu(), making the code shorter and more readable. Any out-of-tree uses may be similarly converted. Signed-off-by: "Paul E. McKenney" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/RCU/whatisRCU.txt | 2 -- fs/dcache.c | 10 ++++------ include/linux/list.h | 13 ++++--------- 3 files changed, 8 insertions(+), 17 deletions(-) (limited to 'include/linux') diff --git a/Documentation/RCU/whatisRCU.txt b/Documentation/RCU/whatisRCU.txt index 354d89c78377..15da16861fa3 100644 --- a/Documentation/RCU/whatisRCU.txt +++ b/Documentation/RCU/whatisRCU.txt @@ -772,8 +772,6 @@ RCU pointer/list traversal: list_for_each_entry_rcu list_for_each_continue_rcu (to be deprecated in favor of new list_for_each_entry_continue_rcu) - hlist_for_each_rcu (to be deprecated in favor of - hlist_for_each_entry_rcu) hlist_for_each_entry_rcu RCU pointer update: diff --git a/fs/dcache.c b/fs/dcache.c index e90512ed35a4..17e439138681 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -644,7 +644,7 @@ void shrink_dcache_parent(struct dentry * parent) * * Prune the dentries that are anonymous * - * parsing d_hash list does not hlist_for_each_rcu() as it + * parsing d_hash list does not hlist_for_each_entry_rcu() as it * done under dcache_lock. * */ @@ -1043,15 +1043,13 @@ struct dentry * __d_lookup(struct dentry * parent, struct qstr * name) struct hlist_head *head = d_hash(parent,hash); struct dentry *found = NULL; struct hlist_node *node; + struct dentry *dentry; rcu_read_lock(); - hlist_for_each_rcu(node, head) { - struct dentry *dentry; + hlist_for_each_entry_rcu(dentry, node, head, d_hash) { struct qstr *qstr; - dentry = hlist_entry(node, struct dentry, d_hash); - if (dentry->d_name.hash != hash) continue; if (dentry->d_parent != parent) @@ -1123,7 +1121,7 @@ int d_validate(struct dentry *dentry, struct dentry *dparent) spin_lock(&dcache_lock); base = d_hash(dparent, dentry->d_name.hash); hlist_for_each(lhp,base) { - /* hlist_for_each_rcu() not required for d_hash list + /* hlist_for_each_entry_rcu() not required for d_hash list * as it is parsed under dcache_lock */ if (dentry == hlist_entry(lhp, struct dentry, d_hash)) { diff --git a/include/linux/list.h b/include/linux/list.h index 084971f333fe..fbfca73355a3 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -601,7 +601,7 @@ static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) * or hlist_del_rcu(), running on this same list. * However, it is perfectly legal to run concurrently with * the _rcu list-traversal primitives, such as - * hlist_for_each_rcu(), used to prevent memory-consistency + * hlist_for_each_entry_rcu(), used to prevent memory-consistency * problems on Alpha CPUs. Regardless of the type of CPU, the * list-traversal primitive must be guarded by rcu_read_lock(). */ @@ -650,7 +650,7 @@ static inline void hlist_add_after(struct hlist_node *n, * or hlist_del_rcu(), running on this same list. * However, it is perfectly legal to run concurrently with * the _rcu list-traversal primitives, such as - * hlist_for_each_rcu(), used to prevent memory-consistency + * hlist_for_each_entry_rcu(), used to prevent memory-consistency * problems on Alpha CPUs. */ static inline void hlist_add_before_rcu(struct hlist_node *n, @@ -675,7 +675,7 @@ static inline void hlist_add_before_rcu(struct hlist_node *n, * or hlist_del_rcu(), running on this same list. * However, it is perfectly legal to run concurrently with * the _rcu list-traversal primitives, such as - * hlist_for_each_rcu(), used to prevent memory-consistency + * hlist_for_each_entry_rcu(), used to prevent memory-consistency * problems on Alpha CPUs. */ static inline void hlist_add_after_rcu(struct hlist_node *prev, @@ -699,11 +699,6 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev, for (pos = (head)->first; pos && ({ n = pos->next; 1; }); \ pos = n) -#define hlist_for_each_rcu(pos, head) \ - for ((pos) = (head)->first; \ - rcu_dereference((pos)) && ({ prefetch((pos)->next); 1; }); \ - (pos) = (pos)->next) - /** * hlist_for_each_entry - iterate over list of given type * @tpos: the type * to use as a loop counter. @@ -756,7 +751,7 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev, /** * hlist_for_each_entry_rcu - iterate over rcu list of given type - * @pos: the type * to use as a loop counter. + * @tpos: the type * to use as a loop counter. * @pos: the &struct hlist_node to use as a loop counter. * @head: the head for your list. * @member: the name of the hlist_node within the struct. -- cgit v1.2.3 From bf8f972d3a1daf969cf44f64cc36d53bfd76441f Mon Sep 17 00:00:00 2001 From: Badari Pulavarty Date: Mon, 7 Nov 2005 00:59:27 -0800 Subject: [PATCH] SHM_NORESERVE flags for shmget() Add SHM_NORESERVE functionality similar to MAP_NORESERVE for shared memory segments. This is mainly to avoid abuse of OVERCOMMIT_ALWAYS and this flag is ignored for OVERCOMMIT_NEVER. Signed-off-by: Badari Pulavarty Cc: Hugh Dickins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/shm.h | 1 + ipc/shm.c | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/shm.h b/include/linux/shm.h index 80113a1f60bc..a2c896ad0bef 100644 --- a/include/linux/shm.h +++ b/include/linux/shm.h @@ -92,6 +92,7 @@ struct shmid_kernel /* private to the kernel */ #define SHM_DEST 01000 /* segment will be destroyed on last detach */ #define SHM_LOCKED 02000 /* segment will not be swapped */ #define SHM_HUGETLB 04000 /* segment will use huge TLB pages */ +#define SHM_NORESERVE 010000 /* don't check for reservations */ #ifdef CONFIG_SYSVIPC long do_shmat(int shmid, char __user *shmaddr, int shmflg, unsigned long *addr); diff --git a/ipc/shm.c b/ipc/shm.c index b58c651d31ae..587d836d80d9 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -212,8 +212,16 @@ static int newseg (key_t key, int shmflg, size_t size) file = hugetlb_zero_setup(size); shp->mlock_user = current->user; } else { + int acctflag = VM_ACCOUNT; + /* + * Do not allow no accounting for OVERCOMMIT_NEVER, even + * if it's asked for. + */ + if ((shmflg & SHM_NORESERVE) && + sysctl_overcommit_memory != OVERCOMMIT_NEVER) + acctflag = 0; sprintf (name, "SYSV%08x", key); - file = shmem_file_setup(name, size, VM_ACCOUNT); + file = shmem_file_setup(name, size, acctflag); } error = PTR_ERR(file); if (IS_ERR(file)) -- cgit v1.2.3 From 7361f4d8ca65d23a18ba009b4484612183332c2f Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 7 Nov 2005 00:59:28 -0800 Subject: [PATCH] readahead commentary Add a few comments surrounding the generic readahead API. Also convert some ulongs into pgoff_t: the identifier for PAGE_CACHE_SIZE offsets into pagecache. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mm.h | 8 ++++---- mm/readahead.c | 31 ++++++++++++++++++++++--------- 2 files changed, 26 insertions(+), 13 deletions(-) (limited to 'include/linux') diff --git a/include/linux/mm.h b/include/linux/mm.h index 5c1fb0a2e806..7b115feca4df 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -932,13 +932,13 @@ int write_one_page(struct page *page, int wait); * turning readahead off */ int do_page_cache_readahead(struct address_space *mapping, struct file *filp, - unsigned long offset, unsigned long nr_to_read); + pgoff_t offset, unsigned long nr_to_read); int force_page_cache_readahead(struct address_space *mapping, struct file *filp, - unsigned long offset, unsigned long nr_to_read); -unsigned long page_cache_readahead(struct address_space *mapping, + pgoff_t offset, unsigned long nr_to_read); +unsigned long page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra, struct file *filp, - unsigned long offset, + pgoff_t offset, unsigned long size); void handle_ra_miss(struct address_space *mapping, struct file_ra_state *ra, pgoff_t offset); diff --git a/mm/readahead.c b/mm/readahead.c index d0b50034e245..72e7adbb87c7 100644 --- a/mm/readahead.c +++ b/mm/readahead.c @@ -254,7 +254,7 @@ out: */ static int __do_page_cache_readahead(struct address_space *mapping, struct file *filp, - unsigned long offset, unsigned long nr_to_read) + pgoff_t offset, unsigned long nr_to_read) { struct inode *inode = mapping->host; struct page *page; @@ -274,7 +274,7 @@ __do_page_cache_readahead(struct address_space *mapping, struct file *filp, */ read_lock_irq(&mapping->tree_lock); for (page_idx = 0; page_idx < nr_to_read; page_idx++) { - unsigned long page_offset = offset + page_idx; + pgoff_t page_offset = offset + page_idx; if (page_offset > end_index) break; @@ -311,7 +311,7 @@ out: * memory at once. */ int force_page_cache_readahead(struct address_space *mapping, struct file *filp, - unsigned long offset, unsigned long nr_to_read) + pgoff_t offset, unsigned long nr_to_read) { int ret = 0; @@ -368,7 +368,7 @@ static inline int check_ra_success(struct file_ra_state *ra, * request queues. */ int do_page_cache_readahead(struct address_space *mapping, struct file *filp, - unsigned long offset, unsigned long nr_to_read) + pgoff_t offset, unsigned long nr_to_read) { if (bdi_read_congested(mapping->backing_dev_info)) return -1; @@ -385,7 +385,7 @@ int do_page_cache_readahead(struct address_space *mapping, struct file *filp, */ static int blockable_page_cache_readahead(struct address_space *mapping, struct file *filp, - unsigned long offset, unsigned long nr_to_read, + pgoff_t offset, unsigned long nr_to_read, struct file_ra_state *ra, int block) { int actual; @@ -430,14 +430,27 @@ static int make_ahead_window(struct address_space *mapping, struct file *filp, return ret; } -/* - * page_cache_readahead is the main function. If performs the adaptive +/** + * page_cache_readahead - generic adaptive readahead + * @mapping: address_space which holds the pagecache and I/O vectors + * @ra: file_ra_state which holds the readahead state + * @filp: passed on to ->readpage() and ->readpages() + * @offset: start offset into @mapping, in PAGE_CACHE_SIZE units + * @req_size: hint: total size of the read which the caller is performing in + * PAGE_CACHE_SIZE units + * + * page_cache_readahead() is the main function. If performs the adaptive * readahead window size management and submits the readahead I/O. + * + * Note that @filp is purely used for passing on to the ->readpage[s]() + * handler: it may refer to a different file from @mapping (so we may not use + * @filp->f_mapping or @filp->f_dentry->d_inode here). + * Also, @ra may not be equal to &@filp->f_ra. + * */ unsigned long page_cache_readahead(struct address_space *mapping, struct file_ra_state *ra, - struct file *filp, unsigned long offset, - unsigned long req_size) + struct file *filp, pgoff_t offset, unsigned long req_size) { unsigned long max, newsize; int sequential; -- cgit v1.2.3 From a43313668f62a06e14c915b8c8994fc8a1257394 Mon Sep 17 00:00:00 2001 From: Hans Reiser Date: Mon, 7 Nov 2005 00:59:29 -0800 Subject: [PATCH] reiser4: add radix_tree_lookup_slot() Reiser4 uses radix trees to solve a trouble reiser4_readdir has serving nfs requests. Unfortunately, radix tree api lacks an operation suitable for modifying existing entry. This patch adds radix_tree_lookup_slot which returns pointer to found item within the tree. That location can be then updated. Both Nick and Christoph Lameter have patches which need this as well. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/radix-tree.h | 1 + lib/radix-tree.c | 51 ++++++++++++++++++++++++++++++++++------------ 2 files changed, 39 insertions(+), 13 deletions(-) (limited to 'include/linux') diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h index 9f0f9281f42a..36e5d269612f 100644 --- a/include/linux/radix-tree.h +++ b/include/linux/radix-tree.h @@ -46,6 +46,7 @@ do { \ int radix_tree_insert(struct radix_tree_root *, unsigned long, void *); void *radix_tree_lookup(struct radix_tree_root *, unsigned long); +void **radix_tree_lookup_slot(struct radix_tree_root *, unsigned long); void *radix_tree_delete(struct radix_tree_root *, unsigned long); unsigned int radix_tree_gang_lookup(struct radix_tree_root *root, void **results, diff --git a/lib/radix-tree.c b/lib/radix-tree.c index d1c057e71b68..88511c3805ad 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -281,35 +281,60 @@ int radix_tree_insert(struct radix_tree_root *root, } EXPORT_SYMBOL(radix_tree_insert); -/** - * radix_tree_lookup - perform lookup operation on a radix tree - * @root: radix tree root - * @index: index key - * - * Lookup the item at the position @index in the radix tree @root. - */ -void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index) +static inline void **__lookup_slot(struct radix_tree_root *root, + unsigned long index) { unsigned int height, shift; - struct radix_tree_node *slot; + struct radix_tree_node **slot; height = root->height; if (index > radix_tree_maxindex(height)) return NULL; shift = (height-1) * RADIX_TREE_MAP_SHIFT; - slot = root->rnode; + slot = &root->rnode; while (height > 0) { - if (slot == NULL) + if (*slot == NULL) return NULL; - slot = slot->slots[(index >> shift) & RADIX_TREE_MAP_MASK]; + slot = (struct radix_tree_node **) + ((*slot)->slots + + ((index >> shift) & RADIX_TREE_MAP_MASK)); shift -= RADIX_TREE_MAP_SHIFT; height--; } - return slot; + return (void **)slot; +} + +/** + * radix_tree_lookup_slot - lookup a slot in a radix tree + * @root: radix tree root + * @index: index key + * + * Lookup the slot corresponding to the position @index in the radix tree + * @root. This is useful for update-if-exists operations. + */ +void **radix_tree_lookup_slot(struct radix_tree_root *root, unsigned long index) +{ + return __lookup_slot(root, index); +} +EXPORT_SYMBOL(radix_tree_lookup_slot); + +/** + * radix_tree_lookup - perform lookup operation on a radix tree + * @root: radix tree root + * @index: index key + * + * Lookup the item at the position @index in the radix tree @root. + */ +void *radix_tree_lookup(struct radix_tree_root *root, unsigned long index) +{ + void **slot; + + slot = __lookup_slot(root, index); + return slot != NULL ? *slot : NULL; } EXPORT_SYMBOL(radix_tree_lookup); -- cgit v1.2.3 From 28ef35845f2c8da8e1bed068277d2fab1e8c8979 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Mon, 7 Nov 2005 00:59:29 -0800 Subject: [PATCH] small kernel_stat.h cleanup cleanup: use for_each_cpu() instead of an open-coded NR_CPUS loop. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/kernel_stat.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h index dba27749b428..a484572c302e 100644 --- a/include/linux/kernel_stat.h +++ b/include/linux/kernel_stat.h @@ -6,6 +6,7 @@ #include #include #include +#include #include /* @@ -43,11 +44,10 @@ extern unsigned long long nr_context_switches(void); */ static inline int kstat_irqs(int irq) { - int i, sum=0; + int cpu, sum = 0; - for (i = 0; i < NR_CPUS; i++) - if (cpu_possible(i)) - sum += kstat_cpu(i).irqs[irq]; + for_each_cpu(cpu) + sum += kstat_cpu(cpu).irqs[irq]; return sum; } -- cgit v1.2.3 From d55b5fdaf40846221d543937b786956e27837fda Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Mon, 7 Nov 2005 00:59:31 -0800 Subject: [PATCH] aio: remove aio_max_nr accounting race AIO was adding a new context's max requests to the global total before testing if that resulting total was over the global limit. This let innocent tasks get their new limit tested along with a racing guilty task that was crossing the limit. This serializes the _nr accounting with a spinlock It also switches to using unsigned long for the global totals. Individual contexts are still limited to an unsigned int's worth of requests by the syscall interface. The problem and fix were verified with a simple program that spun creating and destroying a context while holding on to another long lived context. Before the patch a task creating a tiny context could get a spurious EAGAIN if it raced with a task creating a very large context that overran the limit. Signed-off-by: Zach Brown Cc: Benjamin LaHaise Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/aio.c | 31 +++++++++++++++++++++---------- include/linux/aio.h | 5 +++-- kernel/sysctl.c | 4 ++-- 3 files changed, 26 insertions(+), 14 deletions(-) (limited to 'include/linux') diff --git a/fs/aio.c b/fs/aio.c index edfca5b75535..20bb919eb195 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -42,8 +42,9 @@ #endif /*------ sysctl variables----*/ -atomic_t aio_nr = ATOMIC_INIT(0); /* current system wide number of aio requests */ -unsigned aio_max_nr = 0x10000; /* system wide maximum number of aio requests */ +static DEFINE_SPINLOCK(aio_nr_lock); +unsigned long aio_nr; /* current system wide number of aio requests */ +unsigned long aio_max_nr = 0x10000; /* system wide maximum number of aio requests */ /*----end sysctl variables---*/ static kmem_cache_t *kiocb_cachep; @@ -208,7 +209,7 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) return ERR_PTR(-EINVAL); } - if (nr_events > aio_max_nr) + if ((unsigned long)nr_events > aio_max_nr) return ERR_PTR(-EAGAIN); ctx = kmem_cache_alloc(kioctx_cachep, GFP_KERNEL); @@ -233,8 +234,14 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) goto out_freectx; /* limit the number of system wide aios */ - atomic_add(ctx->max_reqs, &aio_nr); /* undone by __put_ioctx */ - if (unlikely(atomic_read(&aio_nr) > aio_max_nr)) + spin_lock(&aio_nr_lock); + if (aio_nr + ctx->max_reqs > aio_max_nr || + aio_nr + ctx->max_reqs < aio_nr) + ctx->max_reqs = 0; + else + aio_nr += ctx->max_reqs; + spin_unlock(&aio_nr_lock); + if (ctx->max_reqs == 0) goto out_cleanup; /* now link into global list. kludge. FIXME */ @@ -248,8 +255,6 @@ static struct kioctx *ioctx_alloc(unsigned nr_events) return ctx; out_cleanup: - atomic_sub(ctx->max_reqs, &aio_nr); - ctx->max_reqs = 0; /* prevent __put_ioctx from sub'ing aio_nr */ __put_ioctx(ctx); return ERR_PTR(-EAGAIN); @@ -374,7 +379,12 @@ void fastcall __put_ioctx(struct kioctx *ctx) pr_debug("__put_ioctx: freeing %p\n", ctx); kmem_cache_free(kioctx_cachep, ctx); - atomic_sub(nr_events, &aio_nr); + if (nr_events) { + spin_lock(&aio_nr_lock); + BUG_ON(aio_nr - nr_events > aio_nr); + aio_nr -= nr_events; + spin_unlock(&aio_nr_lock); + } } /* aio_get_req @@ -1258,8 +1268,9 @@ asmlinkage long sys_io_setup(unsigned nr_events, aio_context_t __user *ctxp) goto out; ret = -EINVAL; - if (unlikely(ctx || (int)nr_events <= 0)) { - pr_debug("EINVAL: io_setup: ctx or nr_events > max\n"); + if (unlikely(ctx || nr_events == 0)) { + pr_debug("EINVAL: io_setup: ctx %lu nr_events %u\n", + ctx, nr_events); goto out; } diff --git a/include/linux/aio.h b/include/linux/aio.h index 0decf66117c1..403d71dcb7c8 100644 --- a/include/linux/aio.h +++ b/include/linux/aio.h @@ -183,6 +183,7 @@ struct kioctx { struct list_head active_reqs; /* used for cancellation */ struct list_head run_list; /* used for kicked reqs */ + /* sys_io_setup currently limits this to an unsigned int */ unsigned max_reqs; struct aio_ring_info ring_info; @@ -234,7 +235,7 @@ static inline struct kiocb *list_kiocb(struct list_head *h) } /* for sysctl: */ -extern atomic_t aio_nr; -extern unsigned aio_max_nr; +extern unsigned long aio_nr; +extern unsigned long aio_max_nr; #endif /* __LINUX__AIO_H */ diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 8e56e2495542..e1351200ce85 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -952,7 +952,7 @@ static ctl_table fs_table[] = { .data = &aio_nr, .maxlen = sizeof(aio_nr), .mode = 0444, - .proc_handler = &proc_dointvec, + .proc_handler = &proc_doulongvec_minmax, }, { .ctl_name = FS_AIO_MAX_NR, @@ -960,7 +960,7 @@ static ctl_table fs_table[] = { .data = &aio_max_nr, .maxlen = sizeof(aio_max_nr), .mode = 0644, - .proc_handler = &proc_dointvec, + .proc_handler = &proc_doulongvec_minmax, }, #ifdef CONFIG_INOTIFY { -- cgit v1.2.3 From be586bab8bfbf5d429bdfcb6136bdde89583c5c4 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 00:59:35 -0800 Subject: [PATCH] quota: small cleanups - "extern inline" -> "static inline" - every file should #include the headers containing the prototypes for it's global functions Signed-off-by: Adrian Bunk Signed-off-by: Jan Kara Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/dquot.c | 1 + fs/quota.c | 1 + include/linux/quotaops.h | 12 ++++++------ 3 files changed, 8 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/fs/dquot.c b/fs/dquot.c index ea7644227a65..afa06a893468 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -77,6 +77,7 @@ #include #include #include +#include #include diff --git a/fs/quota.c b/fs/quota.c index 1df7832b4e08..612e04db4b93 100644 --- a/fs/quota.c +++ b/fs/quota.c @@ -15,6 +15,7 @@ #include #include #include +#include /* Check validity of generic quotactl commands */ static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id) diff --git a/include/linux/quotaops.h b/include/linux/quotaops.h index d211507ab246..4f34d3d60f2e 100644 --- a/include/linux/quotaops.h +++ b/include/linux/quotaops.h @@ -198,38 +198,38 @@ static __inline__ int DQUOT_OFF(struct super_block *sb) #define DQUOT_SYNC(sb) do { } while(0) #define DQUOT_OFF(sb) do { } while(0) #define DQUOT_TRANSFER(inode, iattr) (0) -extern __inline__ int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) +static inline int DQUOT_PREALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) { inode_add_bytes(inode, nr); return 0; } -extern __inline__ int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr) +static inline int DQUOT_PREALLOC_SPACE(struct inode *inode, qsize_t nr) { DQUOT_PREALLOC_SPACE_NODIRTY(inode, nr); mark_inode_dirty(inode); return 0; } -extern __inline__ int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) +static inline int DQUOT_ALLOC_SPACE_NODIRTY(struct inode *inode, qsize_t nr) { inode_add_bytes(inode, nr); return 0; } -extern __inline__ int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr) +static inline int DQUOT_ALLOC_SPACE(struct inode *inode, qsize_t nr) { DQUOT_ALLOC_SPACE_NODIRTY(inode, nr); mark_inode_dirty(inode); return 0; } -extern __inline__ void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr) +static inline void DQUOT_FREE_SPACE_NODIRTY(struct inode *inode, qsize_t nr) { inode_sub_bytes(inode, nr); } -extern __inline__ void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr) +static inline void DQUOT_FREE_SPACE(struct inode *inode, qsize_t nr) { DQUOT_FREE_SPACE_NODIRTY(inode, nr); mark_inode_dirty(inode); -- cgit v1.2.3 From 8c65b4a60450590e79a28e9717ceffa9e4debb3f Mon Sep 17 00:00:00 2001 From: Tim Schmielau Date: Mon, 7 Nov 2005 00:59:43 -0800 Subject: [PATCH] fix remaining missing includes Fix more include file problems that surfaced since I submitted the previous fix-missing-includes.patch. This should now allow not to include sched.h from module.h, which is done by a followup patch. Signed-off-by: Tim Schmielau Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/mach-aaec2000/clock.c | 1 + arch/arm/mach-epxa10db/mm.c | 1 + arch/arm/mach-pxa/corgi_lcd.c | 1 + arch/ppc/syslib/ppc_sys.c | 1 + drivers/base/power/sysfs.c | 1 + drivers/char/agp/amd64-agp.c | 1 + drivers/hwmon/hwmon.c | 1 + drivers/infiniband/core/agent.c | 3 +++ drivers/infiniband/core/packer.c | 2 ++ drivers/infiniband/core/sysfs.c | 3 +++ drivers/infiniband/core/ud_header.c | 1 + drivers/infiniband/core/verbs.c | 1 + drivers/infiniband/hw/mthca/mthca_catas.c | 3 +++ drivers/infiniband/hw/mthca/mthca_srq.c | 3 +++ drivers/media/dvb/frontends/cx24110.c | 1 + drivers/message/i2o/exec-osm.c | 1 + drivers/mfd/mcp-core.c | 2 ++ drivers/pci/hotplug/pciehprm_nonacpi.c | 1 + drivers/pci/pci-driver.c | 1 + drivers/scsi/atari_dma_emul.c | 2 ++ drivers/scsi/raid_class.c | 2 ++ drivers/scsi/scsi_transport_sas.c | 2 ++ drivers/scsi/sym53c8xx_2/sym_hipd.c | 1 + fs/9p/error.c | 1 + include/asm-alpha/pgtable.h | 3 +++ include/asm-cris/processor.h | 2 ++ include/asm-frv/pgtable.h | 2 ++ include/asm-generic/pgtable.h | 1 + include/asm-i386/elf.h | 2 ++ include/asm-i386/pgtable.h | 3 +++ include/asm-ia64/pgtable.h | 1 + include/asm-m32r/pgtable.h | 3 +++ include/asm-mips/elf.h | 2 ++ include/asm-mips/pgtable.h | 3 +++ include/asm-parisc/pgtable.h | 3 ++- include/asm-powerpc/elf.h | 2 ++ include/asm-ppc/pgtable.h | 1 + include/asm-ppc64/pgtable.h | 1 + include/asm-s390/elf.h | 1 + include/asm-s390/pgtable.h | 1 + include/asm-sh/elf.h | 1 + include/asm-sh/pgtable.h | 2 ++ include/asm-sh64/pgtable.h | 2 ++ include/asm-x86_64/elf.h | 2 ++ include/asm-x86_64/pgtable.h | 2 ++ include/asm-xtensa/elf.h | 2 ++ include/asm-xtensa/pgtable.h | 3 +++ include/linux/irq.h | 1 + include/linux/memory.h | 3 +++ include/linux/sem.h | 2 ++ include/linux/wait.h | 1 + kernel/module.c | 1 + 52 files changed, 89 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/arch/arm/mach-aaec2000/clock.c b/arch/arm/mach-aaec2000/clock.c index 99e019169dda..0340ddc4824e 100644 --- a/arch/arm/mach-aaec2000/clock.c +++ b/arch/arm/mach-aaec2000/clock.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include diff --git a/arch/arm/mach-epxa10db/mm.c b/arch/arm/mach-epxa10db/mm.c index e8832d0910ee..cfd0d2182d44 100644 --- a/arch/arm/mach-epxa10db/mm.c +++ b/arch/arm/mach-epxa10db/mm.c @@ -25,6 +25,7 @@ #include #include #include +#include #include diff --git a/arch/arm/mach-pxa/corgi_lcd.c b/arch/arm/mach-pxa/corgi_lcd.c index 54162ba95414..698eb06545c4 100644 --- a/arch/arm/mach-pxa/corgi_lcd.c +++ b/arch/arm/mach-pxa/corgi_lcd.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include diff --git a/arch/ppc/syslib/ppc_sys.c b/arch/ppc/syslib/ppc_sys.c index 62ee86e80711..603f01190816 100644 --- a/arch/ppc/syslib/ppc_sys.c +++ b/arch/ppc/syslib/ppc_sys.c @@ -14,6 +14,7 @@ * option) any later version. */ +#include #include int (*ppc_sys_device_fixup) (struct platform_device * pdev); diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index 89c57875f3e5..f3a0c562bcb5 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c @@ -3,6 +3,7 @@ */ #include +#include #include "power.h" diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 0e6c3a31d344..78ce98a69f37 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -13,6 +13,7 @@ #include #include #include +#include #include /* PAGE_SIZE */ #include "agp.h" diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c index 6f48579799b5..dddd3eb9b387 100644 --- a/drivers/hwmon/hwmon.c +++ b/drivers/hwmon/hwmon.c @@ -16,6 +16,7 @@ #include #include #include +#include #define HWMON_ID_PREFIX "hwmon" #define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d" diff --git a/drivers/infiniband/core/agent.c b/drivers/infiniband/core/agent.c index 7545775d38ef..34b724afd28d 100644 --- a/drivers/infiniband/core/agent.c +++ b/drivers/infiniband/core/agent.c @@ -37,6 +37,9 @@ * $Id: agent.c 1389 2004-12-27 22:56:47Z roland $ */ +#include +#include + #include "agent.h" #include "smi.h" diff --git a/drivers/infiniband/core/packer.c b/drivers/infiniband/core/packer.c index 35df5010e723..c972d7235764 100644 --- a/drivers/infiniband/core/packer.c +++ b/drivers/infiniband/core/packer.c @@ -33,6 +33,8 @@ * $Id: packer.c 1349 2004-12-16 21:09:43Z roland $ */ +#include + #include static u64 value_read(int offset, int size, void *structure) diff --git a/drivers/infiniband/core/sysfs.c b/drivers/infiniband/core/sysfs.c index b8120650e711..08648b1a387e 100644 --- a/drivers/infiniband/core/sysfs.c +++ b/drivers/infiniband/core/sysfs.c @@ -36,6 +36,9 @@ #include "core_priv.h" +#include +#include + #include struct ib_port { diff --git a/drivers/infiniband/core/ud_header.c b/drivers/infiniband/core/ud_header.c index 527b23450ab3..997c07db6d8f 100644 --- a/drivers/infiniband/core/ud_header.c +++ b/drivers/infiniband/core/ud_header.c @@ -34,6 +34,7 @@ */ #include +#include #include diff --git a/drivers/infiniband/core/verbs.c b/drivers/infiniband/core/verbs.c index 72d3ef786db5..4186cc888ea5 100644 --- a/drivers/infiniband/core/verbs.c +++ b/drivers/infiniband/core/verbs.c @@ -40,6 +40,7 @@ #include #include +#include #include #include diff --git a/drivers/infiniband/hw/mthca/mthca_catas.c b/drivers/infiniband/hw/mthca/mthca_catas.c index 7ac52af43b99..25ebab64bc42 100644 --- a/drivers/infiniband/hw/mthca/mthca_catas.c +++ b/drivers/infiniband/hw/mthca/mthca_catas.c @@ -32,6 +32,9 @@ * $Id$ */ +#include +#include + #include "mthca_dev.h" enum { diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index 292f55be8cbd..26d5161fde07 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -32,6 +32,9 @@ * $Id: mthca_srq.c 3047 2005-08-10 03:59:35Z roland $ */ +#include +#include + #include "mthca_dev.h" #include "mthca_cmd.h" #include "mthca_memfree.h" diff --git a/drivers/media/dvb/frontends/cx24110.c b/drivers/media/dvb/frontends/cx24110.c index d4b97989e3ed..654d7dc879d9 100644 --- a/drivers/media/dvb/frontends/cx24110.c +++ b/drivers/media/dvb/frontends/cx24110.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "dvb_frontend.h" #include "cx24110.h" diff --git a/drivers/message/i2o/exec-osm.c b/drivers/message/i2o/exec-osm.c index b675b4ebbebd..9c339a2505b0 100644 --- a/drivers/message/i2o/exec-osm.c +++ b/drivers/message/i2o/exec-osm.c @@ -33,6 +33,7 @@ #include #include #include +#include /* wait_event_interruptible_timeout() needs this */ #include /* HZ */ #include "core.h" diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c index c75d713c01e4..55ba23075c90 100644 --- a/drivers/mfd/mcp-core.c +++ b/drivers/mfd/mcp-core.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include #include diff --git a/drivers/pci/hotplug/pciehprm_nonacpi.c b/drivers/pci/hotplug/pciehprm_nonacpi.c index 33b2c69a0829..76c727c74cc0 100644 --- a/drivers/pci/hotplug/pciehprm_nonacpi.c +++ b/drivers/pci/hotplug/pciehprm_nonacpi.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c index ae986e590b48..94e68c54d273 100644 --- a/drivers/pci/pci-driver.c +++ b/drivers/pci/pci-driver.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "pci.h" /* diff --git a/drivers/scsi/atari_dma_emul.c b/drivers/scsi/atari_dma_emul.c index 7026045527fd..8d5d2a5da961 100644 --- a/drivers/scsi/atari_dma_emul.c +++ b/drivers/scsi/atari_dma_emul.c @@ -19,6 +19,8 @@ * this code. */ +#include +#include #include #define hades_dma_ctrl (*(unsigned char *) 0xffff8717) diff --git a/drivers/scsi/raid_class.c b/drivers/scsi/raid_class.c index f1ea5027865f..caa0c3629626 100644 --- a/drivers/scsi/raid_class.c +++ b/drivers/scsi/raid_class.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 0cc766a9aa65..edabbd05d258 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c index a1a58e1d5ad3..a7420cad4547 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.c +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c @@ -39,6 +39,7 @@ */ #include +#include /* for timeouts in units of HZ */ #include "sym_glue.h" #include "sym_nvram.h" diff --git a/fs/9p/error.c b/fs/9p/error.c index fee5d19179c5..834cb179e388 100644 --- a/fs/9p/error.c +++ b/fs/9p/error.c @@ -33,6 +33,7 @@ #include #include +#include #include "debug.h" #include "error.h" diff --git a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h index 8393bf374b2b..a985cd29b6db 100644 --- a/include/asm-alpha/pgtable.h +++ b/include/asm-alpha/pgtable.h @@ -17,6 +17,9 @@ #include /* For TASK_SIZE */ #include +struct mm_struct; +struct vm_area_struct; + /* Certain architectures need to do special things when PTEs * within a page table are directly modified. Thus, the following * hook is made available. diff --git a/include/asm-cris/processor.h b/include/asm-cris/processor.h index e8b2abb2ae59..dce41009eeb0 100644 --- a/include/asm-cris/processor.h +++ b/include/asm-cris/processor.h @@ -16,6 +16,8 @@ #include #include +struct task_struct; + /* This decides where the kernel will search for a free chunk of vm * space during mmap's. */ diff --git a/include/asm-frv/pgtable.h b/include/asm-frv/pgtable.h index b247e99dff49..844666377dcb 100644 --- a/include/asm-frv/pgtable.h +++ b/include/asm-frv/pgtable.h @@ -26,6 +26,8 @@ #include #include #include +struct mm_struct; +struct vm_area_struct; #endif #ifndef __ASSEMBLY__ diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h index 7dca30a26c53..358e4d309ceb 100644 --- a/include/asm-generic/pgtable.h +++ b/include/asm-generic/pgtable.h @@ -128,6 +128,7 @@ do { \ #endif #ifndef __HAVE_ARCH_PTEP_SET_WRPROTECT +struct mm_struct; static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long address, pte_t *ptep) { pte_t old_pte = *ptep; diff --git a/include/asm-i386/elf.h b/include/asm-i386/elf.h index fa11117d3cfa..4153d80e4d2b 100644 --- a/include/asm-i386/elf.h +++ b/include/asm-i386/elf.h @@ -119,6 +119,8 @@ typedef struct user_fxsr_struct elf_fpxregset_t; */ #define elf_read_implies_exec(ex, executable_stack) (executable_stack != EXSTACK_DISABLE_X) +struct task_struct; + extern int dump_task_regs (struct task_struct *, elf_gregset_t *); extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *); extern int dump_task_extended_fpu (struct task_struct *, struct user_fxsr_struct *); diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h index 03f3c8ac6383..088a945bf26b 100644 --- a/include/asm-i386/pgtable.h +++ b/include/asm-i386/pgtable.h @@ -25,6 +25,9 @@ #include #include +struct mm_struct; +struct vm_area_struct; + /* * ZERO_PAGE is a global shared page that is always zero: used * for zero-mapped memory areas etc.. diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h index 21e32a06bc82..c34ba80c1c31 100644 --- a/include/asm-ia64/pgtable.h +++ b/include/asm-ia64/pgtable.h @@ -127,6 +127,7 @@ # ifndef __ASSEMBLY__ +#include /* for mm_struct */ #include #include #include diff --git a/include/asm-m32r/pgtable.h b/include/asm-m32r/pgtable.h index 1cd5fd4a5b2c..75740debcd01 100644 --- a/include/asm-m32r/pgtable.h +++ b/include/asm-m32r/pgtable.h @@ -27,6 +27,9 @@ #include #include +struct mm_struct; +struct vm_area_struct; + extern pgd_t swapper_pg_dir[1024]; extern void paging_init(void); diff --git a/include/asm-mips/elf.h b/include/asm-mips/elf.h index 7420f12742bb..d2c9a25f8459 100644 --- a/include/asm-mips/elf.h +++ b/include/asm-mips/elf.h @@ -275,6 +275,8 @@ do { \ #endif /* CONFIG_64BIT */ +struct task_struct; + extern void dump_regs(elf_greg_t *, struct pt_regs *regs); extern int dump_task_regs (struct task_struct *, elf_gregset_t *); extern int dump_task_fpu(struct task_struct *, elf_fpregset_t *); diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h index 34facd996503..702a28fa7a34 100644 --- a/include/asm-mips/pgtable.h +++ b/include/asm-mips/pgtable.h @@ -19,6 +19,9 @@ #include #include +struct mm_struct; +struct vm_area_struct; + #define PAGE_NONE __pgprot(_PAGE_PRESENT | _CACHE_CACHABLE_NONCOHERENT) #define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_READ | _PAGE_WRITE | \ PAGE_CACHABLE_DEFAULT) diff --git a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h index c28fb6f48c6c..b4554711c3e7 100644 --- a/include/asm-parisc/pgtable.h +++ b/include/asm-parisc/pgtable.h @@ -12,6 +12,7 @@ */ #include +#include /* for vm_area_struct */ #include #include #include @@ -418,7 +419,6 @@ extern void paging_init (void); #define PG_dcache_dirty PG_arch_1 -struct vm_area_struct; /* forward declaration (include/linux/mm.h) */ extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); /* Encode and de-code a swap entry */ @@ -464,6 +464,7 @@ static inline int ptep_test_and_clear_dirty(struct vm_area_struct *vma, unsigned extern spinlock_t pa_dbit_lock; +struct mm_struct; static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) { pte_t old_pte; diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h index d140577d0a05..feac3458d71f 100644 --- a/include/asm-powerpc/elf.h +++ b/include/asm-powerpc/elf.h @@ -1,11 +1,13 @@ #ifndef _ASM_POWERPC_ELF_H #define _ASM_POWERPC_ELF_H +#include /* for task_struct */ #include #include #include #include #include +#include /* PowerPC relocations defined by the ABIs */ #define R_PPC_NONE 0 diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h index b28a713ba862..6d1c39e8a6af 100644 --- a/include/asm-ppc/pgtable.h +++ b/include/asm-ppc/pgtable.h @@ -12,6 +12,7 @@ #include /* For TASK_SIZE */ #include #include +struct mm_struct; extern unsigned long va_to_phys(unsigned long address); extern pte_t *va_to_pte(unsigned long address); diff --git a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h index fde93ec36abc..a9783ba7fe98 100644 --- a/include/asm-ppc64/pgtable.h +++ b/include/asm-ppc64/pgtable.h @@ -13,6 +13,7 @@ #include #include #include +struct mm_struct; #endif /* __ASSEMBLY__ */ #ifdef CONFIG_PPC_64K_PAGES diff --git a/include/asm-s390/elf.h b/include/asm-s390/elf.h index 3b8bd46832a1..372d51cccd53 100644 --- a/include/asm-s390/elf.h +++ b/include/asm-s390/elf.h @@ -96,6 +96,7 @@ * ELF register definitions.. */ +#include /* for task_struct */ #include #include #include /* for save_access_regs */ diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h index df94f89038cc..9be741bb1496 100644 --- a/include/asm-s390/pgtable.h +++ b/include/asm-s390/pgtable.h @@ -36,6 +36,7 @@ #include struct vm_area_struct; /* forward declaration (include/linux/mm.h) */ +struct mm_struct; extern pgd_t swapper_pg_dir[] __attribute__ ((aligned (4096))); extern void paging_init(void); diff --git a/include/asm-sh/elf.h b/include/asm-sh/elf.h index 8fe00a1981ce..1b63dfeea4f2 100644 --- a/include/asm-sh/elf.h +++ b/include/asm-sh/elf.h @@ -111,6 +111,7 @@ typedef struct user_fpu_struct elf_fpregset_t; #ifdef __KERNEL__ #define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT) +struct task_struct; extern int dump_task_regs (struct task_struct *, elf_gregset_t *); extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *); diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h index dee36bcbcf98..bb0efb31a8cb 100644 --- a/include/asm-sh/pgtable.h +++ b/include/asm-sh/pgtable.h @@ -284,6 +284,8 @@ typedef pte_t *pte_addr_t; #define GET_IOSPACE(pfn) 0 #define GET_PFN(pfn) (pfn) +struct mm_struct; + /* * No page table caches to initialise */ diff --git a/include/asm-sh64/pgtable.h b/include/asm-sh64/pgtable.h index 51b05818e4eb..a1906a772df9 100644 --- a/include/asm-sh64/pgtable.h +++ b/include/asm-sh64/pgtable.h @@ -24,6 +24,8 @@ #include #include +struct vm_area_struct; + extern void paging_init(void); /* We provide our own get_unmapped_area to avoid cache synonym issue */ diff --git a/include/asm-x86_64/elf.h b/include/asm-x86_64/elf.h index a60a35e79222..43862cd6a569 100644 --- a/include/asm-x86_64/elf.h +++ b/include/asm-x86_64/elf.h @@ -149,6 +149,8 @@ extern void set_personality_64bit(void); */ #define elf_read_implies_exec(ex, executable_stack) (executable_stack != EXSTACK_DISABLE_X) +struct task_struct; + extern int dump_task_regs (struct task_struct *, elf_gregset_t *); extern int dump_task_fpu (struct task_struct *, elf_fpregset_t *); diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h index 7a07196a7202..7309fffeec9a 100644 --- a/include/asm-x86_64/pgtable.h +++ b/include/asm-x86_64/pgtable.h @@ -105,6 +105,8 @@ static inline void pgd_clear (pgd_t * pgd) #define ptep_get_and_clear(mm,addr,xp) __pte(xchg(&(xp)->pte, 0)) +struct mm_struct; + static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long addr, pte_t *ptep, int full) { pte_t pte; diff --git a/include/asm-xtensa/elf.h b/include/asm-xtensa/elf.h index 64f1f53874fe..de0667453b2e 100644 --- a/include/asm-xtensa/elf.h +++ b/include/asm-xtensa/elf.h @@ -209,6 +209,8 @@ extern void xtensa_elf_core_copy_regs (xtensa_gregset_t *, struct pt_regs *); #define SET_PERSONALITY(ex, ibcs2) set_personality(PER_LINUX_32BIT) +struct task_struct; + extern void do_copy_regs (xtensa_gregset_t*, struct pt_regs*, struct task_struct*); extern void do_restore_regs (xtensa_gregset_t*, struct pt_regs*, diff --git a/include/asm-xtensa/pgtable.h b/include/asm-xtensa/pgtable.h index 987e3b802313..7b15afb70c56 100644 --- a/include/asm-xtensa/pgtable.h +++ b/include/asm-xtensa/pgtable.h @@ -278,6 +278,8 @@ static inline void update_pte(pte_t *ptep, pte_t pteval) #endif } +struct mm_struct; + static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pteval) { @@ -294,6 +296,7 @@ set_pmd(pmd_t *pmdp, pmd_t pmdval) #endif } +struct vm_area_struct; static inline int ptep_test_and_clear_young(struct vm_area_struct *vma, unsigned long addr, diff --git a/include/linux/irq.h b/include/linux/irq.h index 69681c3b1f05..c516382fbec2 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h @@ -10,6 +10,7 @@ */ #include +#include /* cpu_online_map */ #if !defined(CONFIG_ARCH_S390) diff --git a/include/linux/memory.h b/include/linux/memory.h index 0def328ab5cf..9a424383e6c6 100644 --- a/include/linux/memory.h +++ b/include/linux/memory.h @@ -54,6 +54,9 @@ struct memory_block { */ #define MEM_MAPPING_INVALID (1<<3) +struct notifier_block; +struct mem_section; + #ifndef CONFIG_MEMORY_HOTPLUG static inline int memory_dev_init(void) { diff --git a/include/linux/sem.h b/include/linux/sem.h index 106f9757339a..3c1f1120fe88 100644 --- a/include/linux/sem.h +++ b/include/linux/sem.h @@ -79,6 +79,8 @@ struct seminfo { #ifdef __KERNEL__ +struct task_struct; + /* One semaphore structure for each semaphore in the system. */ struct sem { int semval; /* current value */ diff --git a/include/linux/wait.h b/include/linux/wait.h index d38c9fecdc36..d28518236b62 100644 --- a/include/linux/wait.h +++ b/include/linux/wait.h @@ -54,6 +54,7 @@ struct __wait_queue_head { }; typedef struct __wait_queue_head wait_queue_head_t; +struct task_struct; /* * Macros for declaration and initialisaton of the datatypes diff --git a/kernel/module.c b/kernel/module.c index ff5c500ab625..2ea929d51ad0 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 481bed454247538e9f57d4ea37b153ccba24ba7b Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Mon, 7 Nov 2005 00:59:47 -0800 Subject: [PATCH] consolidate sys_ptrace() The sys_ptrace boilerplate code (everything outside the big switch statement for the arch-specific requests) is shared by most architectures. This patch moves it to kernel/ptrace.c and leaves the arch-specific code as arch_ptrace. Some architectures have a too different ptrace so we have to exclude them. They continue to keep their implementations. For sh64 I had to add a sh64_ptrace wrapper because it does some initialization on the first call. For um I removed an ifdefed SUBARCH_PTRACE_SPECIAL block, but SUBARCH_PTRACE_SPECIAL isn't defined anywhere in the tree. Signed-off-by: Christoph Hellwig Acked-by: Paul Mackerras Acked-by: Ralf Baechle Acked-By: David Howells Acked-by: Russell King Acked-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/kernel/ptrace.c | 49 +--------------------- arch/arm26/kernel/ptrace.c | 49 +--------------------- arch/cris/arch-v10/kernel/ptrace.c | 51 +---------------------- arch/cris/arch-v32/kernel/ptrace.c | 51 +---------------------- arch/frv/kernel/ptrace.c | 43 +------------------- arch/h8300/kernel/ptrace.c | 39 +----------------- arch/i386/kernel/ptrace.c | 44 +------------------- arch/m68k/kernel/ptrace.c | 47 ++------------------- arch/m68knommu/kernel/ptrace.c | 39 +----------------- arch/mips/kernel/ptrace.c | 55 +++---------------------- arch/parisc/kernel/ptrace.c | 50 ++--------------------- arch/powerpc/kernel/ptrace.c | 43 +------------------- arch/sh/kernel/ptrace.c | 44 +------------------- arch/sh64/kernel/ptrace.c | 83 +++++++++++++------------------------- arch/sh64/kernel/syscalls.S | 2 +- arch/um/kernel/ptrace.c | 50 +---------------------- arch/v850/kernel/ptrace.c | 43 +------------------- arch/x86_64/kernel/ptrace.c | 43 +------------------- arch/xtensa/kernel/ptrace.c | 55 +------------------------ include/asm-alpha/ptrace.h | 3 ++ include/asm-ia64/ptrace.h | 3 ++ include/asm-m32r/ptrace.h | 3 ++ include/asm-s390/ptrace.h | 2 + include/asm-sparc/ptrace.h | 3 ++ include/asm-sparc64/ptrace.h | 3 ++ include/linux/ptrace.h | 2 + kernel/ptrace.c | 82 +++++++++++++++++++++++++++++++++++++ 27 files changed, 163 insertions(+), 818 deletions(-) (limited to 'include/linux') diff --git a/arch/arm/kernel/ptrace.c b/arch/arm/kernel/ptrace.c index 9bd8609a2926..9a340e790da5 100644 --- a/arch/arm/kernel/ptrace.c +++ b/arch/arm/kernel/ptrace.c @@ -648,7 +648,7 @@ static int ptrace_setwmmxregs(struct task_struct *tsk, void __user *ufp) #endif -static int do_ptrace(int request, struct task_struct *child, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { unsigned long tmp; int ret; @@ -782,53 +782,6 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat return ret; } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) -{ - struct task_struct *child; - int ret; - - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret == 0) - ret = do_ptrace(request, child, addr, data); - -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); - return ret; -} - asmlinkage void syscall_trace(int why, struct pt_regs *regs) { unsigned long ip; diff --git a/arch/arm26/kernel/ptrace.c b/arch/arm26/kernel/ptrace.c index cf7e977d18c8..4e6b7356a722 100644 --- a/arch/arm26/kernel/ptrace.c +++ b/arch/arm26/kernel/ptrace.c @@ -546,7 +546,7 @@ static int ptrace_setfpregs(struct task_struct *tsk, void *ufp) sizeof(struct user_fp)) ? -EFAULT : 0; } -static int do_ptrace(int request, struct task_struct *child, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { unsigned long tmp; int ret; @@ -665,53 +665,6 @@ static int do_ptrace(int request, struct task_struct *child, long addr, long dat return ret; } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) -{ - struct task_struct *child; - int ret; - - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret == 0) - ret = do_ptrace(request, child, addr, data); - -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); - return ret; -} - asmlinkage void syscall_trace(int why, struct pt_regs *regs) { unsigned long ip; diff --git a/arch/cris/arch-v10/kernel/ptrace.c b/arch/cris/arch-v10/kernel/ptrace.c index 130dd214e41d..6cbd34a27b90 100644 --- a/arch/cris/arch-v10/kernel/ptrace.c +++ b/arch/cris/arch-v10/kernel/ptrace.c @@ -76,55 +76,11 @@ ptrace_disable(struct task_struct *child) * (in user space) where the result of the ptrace call is written (instead of * being returned). */ -asmlinkage int -sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int ret; unsigned long __user *datap = (unsigned long __user *)data; - lock_kernel(); - ret = -EPERM; - - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - - if (child) - get_task_struct(child); - - read_unlock(&tasklist_lock); - - if (!child) - goto out; - - ret = -EPERM; - - if (pid == 1) /* Leave the init process alone! */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* Read word at location address. */ case PTRACE_PEEKTEXT: @@ -289,10 +245,7 @@ sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + return ret; } diff --git a/arch/cris/arch-v32/kernel/ptrace.c b/arch/cris/arch-v32/kernel/ptrace.c index 208489da2a87..5528b83a622b 100644 --- a/arch/cris/arch-v32/kernel/ptrace.c +++ b/arch/cris/arch-v32/kernel/ptrace.c @@ -99,55 +99,11 @@ ptrace_disable(struct task_struct *child) } -asmlinkage int -sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int ret; unsigned long __user *datap = (unsigned long __user *)data; - lock_kernel(); - ret = -EPERM; - - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - - if (child) - get_task_struct(child); - - read_unlock(&tasklist_lock); - - if (!child) - goto out; - - ret = -EPERM; - - if (pid == 1) /* Leave the init process alone! */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* Read word at location address. */ case PTRACE_PEEKTEXT: @@ -347,10 +303,7 @@ sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + return ret; } diff --git a/arch/frv/kernel/ptrace.c b/arch/frv/kernel/ptrace.c index cb335a14a315..f953484e7d59 100644 --- a/arch/frv/kernel/ptrace.c +++ b/arch/frv/kernel/ptrace.c @@ -106,48 +106,11 @@ void ptrace_enable(struct task_struct *child) child->thread.frame0->__status |= REG__STATUS_STEP; } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; unsigned long tmp; int ret; - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -351,10 +314,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ret = -EIO; break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); return ret; } diff --git a/arch/h8300/kernel/ptrace.c b/arch/h8300/kernel/ptrace.c index a569fe4aa284..0ff6f79b0fed 100644 --- a/arch/h8300/kernel/ptrace.c +++ b/arch/h8300/kernel/ptrace.c @@ -57,43 +57,10 @@ void ptrace_disable(struct task_struct *child) h8300_disable_trace(child); } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int ret; - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: { @@ -251,10 +218,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ret = -EIO; break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); return ret; } diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index efd11f09c996..5ffbb4b7ad05 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c @@ -354,49 +354,12 @@ ptrace_set_thread_area(struct task_struct *child, return 0; } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; struct user * dummy = NULL; int i, ret; unsigned long __user *datap = (unsigned long __user *)data; - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -663,10 +626,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + out_tsk: return ret; } diff --git a/arch/m68k/kernel/ptrace.c b/arch/m68k/kernel/ptrace.c index f7f1d2e5b90b..7e54422685cf 100644 --- a/arch/m68k/kernel/ptrace.c +++ b/arch/m68k/kernel/ptrace.c @@ -121,48 +121,11 @@ void ptrace_disable(struct task_struct *child) child->thread.work.syscall_trace = 0; } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; unsigned long tmp; int i, ret = 0; - lock_kernel(); - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) { - ret = -EPERM; - goto out; - } - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - goto out; - } - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (unlikely(!child)) { - ret = -ESRCH; - goto out; - } - - /* you may not mess with init */ - if (unlikely(pid == 1)) { - ret = -EPERM; - goto out_tsk; - } - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -317,14 +280,10 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + return ret; out_eio: - ret = -EIO; - goto out_tsk; + return -EIO; } asmlinkage void syscall_trace(void) diff --git a/arch/m68knommu/kernel/ptrace.c b/arch/m68knommu/kernel/ptrace.c index 621d7b91ccfe..262ab8c72e5f 100644 --- a/arch/m68knommu/kernel/ptrace.c +++ b/arch/m68knommu/kernel/ptrace.c @@ -101,43 +101,10 @@ void ptrace_disable(struct task_struct *child) put_reg(child, PT_SR, tmp); } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(truct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int ret; - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -357,10 +324,6 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ret = -EIO; break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); return ret; } diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c index f1b0f3e1f95b..510da5fda567 100644 --- a/arch/mips/kernel/ptrace.c +++ b/arch/mips/kernel/ptrace.c @@ -174,51 +174,10 @@ int ptrace_setfpregs (struct task_struct *child, __u32 __user *data) return 0; } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int ret; -#if 0 - printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n", - (int) request, (int) pid, (unsigned long) addr, - (unsigned long) data); -#endif - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - if ((ret = security_ptrace(current->parent, current))) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -319,7 +278,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) if (!cpu_has_dsp) { tmp = 0; ret = -EIO; - goto out_tsk; + goto out; } if (child->thread.dsp.used_dsp) { dregs = __get_dsp_regs(child); @@ -333,14 +292,14 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) if (!cpu_has_dsp) { tmp = 0; ret = -EIO; - goto out_tsk; + goto out; } tmp = child->thread.dsp.dspcontrol; break; default: tmp = 0; ret = -EIO; - goto out_tsk; + goto out; } ret = put_user(tmp, (unsigned long __user *) data); break; @@ -495,11 +454,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } - -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + out: return ret; } diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c index 18130c3748f3..b6fe202a620d 100644 --- a/arch/parisc/kernel/ptrace.c +++ b/arch/parisc/kernel/ptrace.c @@ -78,52 +78,13 @@ void ptrace_disable(struct task_struct *child) pa_psw(child)->l = 0; } -long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; long ret; #ifdef DEBUG_PTRACE long oaddr=addr, odata=data; #endif - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - ret = -EPERM; - if (pid == 1) /* no messing around with init! */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: { @@ -383,11 +344,11 @@ long sys_ptrace(long request, long pid, long addr, long data) case PTRACE_GETEVENTMSG: ret = put_user(child->ptrace_message, (unsigned int __user *) data); - goto out_tsk; + goto out; default: ret = ptrace_request(child, request, addr, data); - goto out_tsk; + goto out; } out_wake_notrap: @@ -396,10 +357,7 @@ out_wake: wake_up_process(child); ret = 0; out_tsk: - put_task_struct(child); -out: - unlock_kernel(); - DBG("sys_ptrace(%ld, %d, %lx, %lx) returning %ld\n", + DBG("arch_ptrace(%ld, %d, %lx, %lx) returning %ld\n", request, pid, oaddr, odata, ret); return ret; } diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 568ea335d616..3d2abd95c7ae 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c @@ -248,46 +248,10 @@ void ptrace_disable(struct task_struct *child) clear_single_step(child); } -long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int ret = -EPERM; - lock_kernel(); - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -540,10 +504,7 @@ long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + return ret; } diff --git a/arch/sh/kernel/ptrace.c b/arch/sh/kernel/ptrace.c index 1fbe5a428e31..1a8be06519ec 100644 --- a/arch/sh/kernel/ptrace.c +++ b/arch/sh/kernel/ptrace.c @@ -80,48 +80,11 @@ void ptrace_disable(struct task_struct *child) /* nothing to do.. */ } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; struct user * dummy = NULL; int ret; - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -289,10 +252,7 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + return ret; } diff --git a/arch/sh64/kernel/ptrace.c b/arch/sh64/kernel/ptrace.c index 71f2eec00b99..cd22e9471316 100644 --- a/arch/sh64/kernel/ptrace.c +++ b/arch/sh64/kernel/ptrace.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -121,61 +122,11 @@ put_fpu_long(struct task_struct *task, unsigned long addr, unsigned long data) return 0; } -asmlinkage long sys_ptrace(long request, long pid, long addr, long data) + +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; - extern void poke_real_address_q(unsigned long long addr, unsigned long long data); -#define WPC_DBRMODE 0x0d104008 - static int first_call = 1; int ret; - lock_kernel(); - - if (first_call) { - /* Set WPC.DBRMODE to 0. This makes all debug events get - * delivered through RESVEC, i.e. into the handlers in entry.S. - * (If the kernel was downloaded using a remote gdb, WPC.DBRMODE - * would normally be left set to 1, which makes debug events get - * delivered through DBRVEC, i.e. into the remote gdb's - * handlers. This prevents ptrace getting them, and confuses - * the remote gdb.) */ - printk("DBRMODE set to 0 to permit native debugging\n"); - poke_real_address_q(WPC_DBRMODE, 0); - first_call = 0; - } - - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -313,13 +264,33 @@ asmlinkage long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); return ret; } +asmlinkage int sh64_ptrace(long request, long pid, long addr, long data) +{ + extern void poke_real_address_q(unsigned long long addr, unsigned long long data); +#define WPC_DBRMODE 0x0d104008 + static int first_call = 1; + + lock_kernel(); + if (first_call) { + /* Set WPC.DBRMODE to 0. This makes all debug events get + * delivered through RESVEC, i.e. into the handlers in entry.S. + * (If the kernel was downloaded using a remote gdb, WPC.DBRMODE + * would normally be left set to 1, which makes debug events get + * delivered through DBRVEC, i.e. into the remote gdb's + * handlers. This prevents ptrace getting them, and confuses + * the remote gdb.) */ + printk("DBRMODE set to 0 to permit native debugging\n"); + poke_real_address_q(WPC_DBRMODE, 0); + first_call = 0; + } + unlock_kernel(); + + return sys_ptrace(request, pid, addr, data); +} + asmlinkage void syscall_trace(void) { struct task_struct *tsk = current; diff --git a/arch/sh64/kernel/syscalls.S b/arch/sh64/kernel/syscalls.S index a3d037805f1c..c0079d54c850 100644 --- a/arch/sh64/kernel/syscalls.S +++ b/arch/sh64/kernel/syscalls.S @@ -46,7 +46,7 @@ sys_call_table: .long sys_setuid16 .long sys_getuid16 .long sys_stime /* 25 */ - .long sys_ptrace + .long sh64_ptrace .long sys_alarm .long sys_fstat .long sys_pause diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 71af4d503899..98e09395c093 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -43,53 +43,10 @@ void ptrace_disable(struct task_struct *child) extern int peek_user(struct task_struct * child, long addr, long data); extern int poke_user(struct task_struct * child, long addr, long data); -long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int i, ret; - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - -#ifdef SUBACH_PTRACE_SPECIAL - SUBARCH_PTRACE_SPECIAL(child,request,addr,data); -#endif - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -282,10 +239,7 @@ long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } - out_tsk: - put_task_struct(child); - out: - unlock_kernel(); + return ret; } diff --git a/arch/v850/kernel/ptrace.c b/arch/v850/kernel/ptrace.c index d6077ff47d22..18492d02aaf6 100644 --- a/arch/v850/kernel/ptrace.c +++ b/arch/v850/kernel/ptrace.c @@ -113,45 +113,10 @@ static int set_single_step (struct task_struct *t, int val) return 1; } -long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int rval; - lock_kernel(); - - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) { - rval = -EPERM; - goto out; - } - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - rval = 0; - goto out; - } - rval = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - rval = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - rval = ptrace_attach(child); - goto out_tsk; - } - rval = ptrace_check_attach(child, request == PTRACE_KILL); - if (rval < 0) - goto out_tsk; - switch (request) { unsigned long val, copied; @@ -248,11 +213,7 @@ long sys_ptrace(long request, long pid, long addr, long data) rval = -EIO; goto out; } - -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + out: return rval; } diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c index bbf64b59a21e..a87b6cebe80f 100644 --- a/arch/x86_64/kernel/ptrace.c +++ b/arch/x86_64/kernel/ptrace.c @@ -313,48 +313,11 @@ static unsigned long getreg(struct task_struct *child, unsigned long regno) } -asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; long i, ret; unsigned ui; - /* This lock_kernel fixes a subtle race with suid exec */ - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -608,10 +571,6 @@ asmlinkage long sys_ptrace(long request, long pid, unsigned long addr, long data ret = ptrace_request(child, request, addr, data); break; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); return ret; } diff --git a/arch/xtensa/kernel/ptrace.c b/arch/xtensa/kernel/ptrace.c index 14460743de07..ab5c4c65b5c4 100644 --- a/arch/xtensa/kernel/ptrace.c +++ b/arch/xtensa/kernel/ptrace.c @@ -45,58 +45,10 @@ void ptrace_disable(struct task_struct *child) /* Nothing to do.. */ } -long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int ret = -EPERM; - lock_kernel(); - -#if 0 - if ((int)request != 1) - printk("ptrace(r=%d,pid=%d,addr=%08lx,data=%08lx)\n", - (int) request, (int) pid, (unsigned long) addr, - (unsigned long) data); -#endif - - if (request == PTRACE_TRACEME) { - - /* Are we already being traced? */ - - if (current->ptrace & PT_PTRACED) - goto out; - - if ((ret = security_ptrace(current->parent, current))) - goto out; - - /* Set the ptrace bit in the process flags. */ - - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - - if ((ret = ptrace_check_attach(child, request == PTRACE_KILL)) < 0) - goto out_tsk; - switch (request) { case PTRACE_PEEKTEXT: /* read word at location addr. */ case PTRACE_PEEKDATA: @@ -375,10 +327,7 @@ long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); goto out; } -out_tsk: - put_task_struct(child); -out: - unlock_kernel(); + out: return ret; } diff --git a/include/asm-alpha/ptrace.h b/include/asm-alpha/ptrace.h index d462c5e14c13..072375c135b4 100644 --- a/include/asm-alpha/ptrace.h +++ b/include/asm-alpha/ptrace.h @@ -67,6 +67,9 @@ struct switch_stack { }; #ifdef __KERNEL__ + +#define __ARCH_SYS_PTRACE 1 + #define user_mode(regs) (((regs)->ps & 8) != 0) #define instruction_pointer(regs) ((regs)->pc) #define profile_pc(regs) instruction_pointer(regs) diff --git a/include/asm-ia64/ptrace.h b/include/asm-ia64/ptrace.h index a79d1a7ecc77..2c703d6e0c86 100644 --- a/include/asm-ia64/ptrace.h +++ b/include/asm-ia64/ptrace.h @@ -229,6 +229,9 @@ struct switch_stack { }; #ifdef __KERNEL__ + +#define __ARCH_SYS_PTRACE 1 + /* * We use the ia64_psr(regs)->ri to determine which of the three * instructions in bundle (16 bytes) took the sample. Generate diff --git a/include/asm-m32r/ptrace.h b/include/asm-m32r/ptrace.h index 976417126b2d..55cd7ecfde43 100644 --- a/include/asm-m32r/ptrace.h +++ b/include/asm-m32r/ptrace.h @@ -145,6 +145,9 @@ struct pt_regs { #define PTRACE_O_TRACESYSGOOD 0x00000001 #ifdef __KERNEL__ + +#define __ARCH_SYS_PTRACE 1 + #if defined(CONFIG_ISA_M32R2) || defined(CONFIG_CHIP_VDEC2) #define user_mode(regs) ((M32R_PSW_BPM & (regs)->psw) != 0) #elif defined(CONFIG_ISA_M32R) diff --git a/include/asm-s390/ptrace.h b/include/asm-s390/ptrace.h index fc7c96edc697..a949cc077cc7 100644 --- a/include/asm-s390/ptrace.h +++ b/include/asm-s390/ptrace.h @@ -468,6 +468,8 @@ struct user_regs_struct }; #ifdef __KERNEL__ +#define __ARCH_SYS_PTRACE 1 + #define user_mode(regs) (((regs)->psw.mask & PSW_MASK_PSTATE) != 0) #define instruction_pointer(regs) ((regs)->psw.addr & PSW_ADDR_INSN) #define profile_pc(regs) instruction_pointer(regs) diff --git a/include/asm-sparc/ptrace.h b/include/asm-sparc/ptrace.h index a8ecb2d6977a..714497099a42 100644 --- a/include/asm-sparc/ptrace.h +++ b/include/asm-sparc/ptrace.h @@ -60,6 +60,9 @@ struct sparc_stackf { #define STACKFRAME_SZ sizeof(struct sparc_stackf) #ifdef __KERNEL__ + +#define __ARCH_SYS_PTRACE 1 + #define user_mode(regs) (!((regs)->psr & PSR_PS)) #define instruction_pointer(regs) ((regs)->pc) unsigned long profile_pc(struct pt_regs *); diff --git a/include/asm-sparc64/ptrace.h b/include/asm-sparc64/ptrace.h index 6194f771e9fc..7eba90c6c753 100644 --- a/include/asm-sparc64/ptrace.h +++ b/include/asm-sparc64/ptrace.h @@ -94,6 +94,9 @@ struct sparc_trapf { #define STACKFRAME32_SZ sizeof(struct sparc_stackf32) #ifdef __KERNEL__ + +#define __ARCH_SYS_PTRACE 1 + #define force_successful_syscall_return() \ do { current_thread_info()->syscall_noerror = 1; \ } while (0) diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index dc6f3647bfbc..b2b3dba1298d 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h @@ -78,6 +78,8 @@ #include /* For unlikely. */ #include /* For struct task_struct. */ + +extern long arch_ptrace(struct task_struct *child, long request, long addr, long data); extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len); extern int ptrace_attach(struct task_struct *tsk); diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 863eee8bff47..5b8dd98a230e 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -406,3 +406,85 @@ int ptrace_request(struct task_struct *child, long request, return ret; } + +#ifndef __ARCH_SYS_PTRACE +static int ptrace_get_task_struct(long request, long pid, + struct task_struct **childp) +{ + struct task_struct *child; + int ret; + + /* + * Callers use child == NULL as an indication to exit early even + * when the return value is 0, so make sure it is non-NULL here. + */ + *childp = NULL; + + if (request == PTRACE_TRACEME) { + /* + * Are we already being traced? + */ + if (current->ptrace & PT_PTRACED) + return -EPERM; + ret = security_ptrace(current->parent, current); + if (ret) + return -EPERM; + /* + * Set the ptrace bit in the process ptrace flags. + */ + current->ptrace |= PT_PTRACED; + return 0; + } + + /* + * You may not mess with init + */ + if (pid == 1) + return -EPERM; + + ret = -ESRCH; + read_lock(&tasklist_lock); + child = find_task_by_pid(pid); + if (child) + get_task_struct(child); + read_unlock(&tasklist_lock); + if (!child) + return -ESRCH; + + *childp = child; + return 0; +} + +asmlinkage long sys_ptrace(long request, long pid, long addr, long data) +{ + struct task_struct *child; + long ret; + + /* + * This lock_kernel fixes a subtle race with suid exec + */ + lock_kernel(); + ret = ptrace_get_task_struct(request, pid, &child); + if (!child) + goto out; + + if (request == PTRACE_ATTACH) { + ret = ptrace_attach(child); + goto out; + } + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (ret < 0) + goto out_put_task_struct; + + ret = arch_ptrace(child, request, addr, data); + if (ret < 0) + goto out_put_task_struct; + + out_put_task_struct: + put_task_struct(child); + out: + unlock_kernel(); + return ret; +} +#endif /* __ARCH_SYS_PTRACE */ -- cgit v1.2.3 From cc4e69dee4a080f6eae3f410daec2593f4fa6f00 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 7 Nov 2005 00:59:49 -0800 Subject: [PATCH] VFS: pass file pointer to filesystem from ftruncate() This patch extends the iattr structure with a file pointer memeber, and adds an ATTR_FILE validity flag for this member. This is set if do_truncate() is invoked from ftruncate() or from do_coredump(). The change is source and binary compatible. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/exec.c | 2 +- fs/namei.c | 2 +- fs/open.c | 10 +++++++--- include/linux/fs.h | 10 +++++++++- 4 files changed, 18 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/fs/exec.c b/fs/exec.c index ce76b33f25ac..cd6c574557dc 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -1511,7 +1511,7 @@ int do_coredump(long signr, int exit_code, struct pt_regs * regs) goto close_fail; if (!file->f_op->write) goto close_fail; - if (do_truncate(file->f_dentry, 0) != 0) + if (do_truncate(file->f_dentry, 0, file) != 0) goto close_fail; retval = binfmt->core_dump(signr, regs, file); diff --git a/fs/namei.c b/fs/namei.c index c5769c4fcab1..b3f8a1966c9c 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1459,7 +1459,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) if (!error) { DQUOT_INIT(inode); - error = do_truncate(dentry, 0); + error = do_truncate(dentry, 0, NULL); } put_write_access(inode); if (error) diff --git a/fs/open.c b/fs/open.c index 2835f096c683..6e8136751e9a 100644 --- a/fs/open.c +++ b/fs/open.c @@ -194,7 +194,7 @@ out: return error; } -int do_truncate(struct dentry *dentry, loff_t length) +int do_truncate(struct dentry *dentry, loff_t length, struct file *filp) { int err; struct iattr newattrs; @@ -205,6 +205,10 @@ int do_truncate(struct dentry *dentry, loff_t length) newattrs.ia_size = length; newattrs.ia_valid = ATTR_SIZE | ATTR_CTIME; + if (filp) { + newattrs.ia_file = filp; + newattrs.ia_valid |= ATTR_FILE; + } down(&dentry->d_inode->i_sem); err = notify_change(dentry, &newattrs); @@ -262,7 +266,7 @@ static inline long do_sys_truncate(const char __user * path, loff_t length) error = locks_verify_truncate(inode, NULL, length); if (!error) { DQUOT_INIT(inode); - error = do_truncate(nd.dentry, length); + error = do_truncate(nd.dentry, length, NULL); } put_write_access(inode); @@ -314,7 +318,7 @@ static inline long do_sys_ftruncate(unsigned int fd, loff_t length, int small) error = locks_verify_truncate(inode, file, length); if (!error) - error = do_truncate(dentry, length); + error = do_truncate(dentry, length, file); out_putf: fput(file); out: diff --git a/include/linux/fs.h b/include/linux/fs.h index 6d6226732c93..0c89fc9481a8 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -264,6 +264,7 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset, #define ATTR_ATTR_FLAG 1024 #define ATTR_KILL_SUID 2048 #define ATTR_KILL_SGID 4096 +#define ATTR_FILE 8192 /* * This is the Inode Attributes structure, used for notify_change(). It @@ -283,6 +284,13 @@ struct iattr { struct timespec ia_atime; struct timespec ia_mtime; struct timespec ia_ctime; + + /* + * Not an attribute, but an auxilary info for filesystems wanting to + * implement an ftruncate() like method. NOTE: filesystem should + * check for (ia_valid & ATTR_FILE), and not for (ia_file != NULL). + */ + struct file *ia_file; }; /* @@ -1288,7 +1296,7 @@ static inline int break_lease(struct inode *inode, unsigned int mode) /* fs/open.c */ -extern int do_truncate(struct dentry *, loff_t start); +extern int do_truncate(struct dentry *, loff_t start, struct file *filp); extern long do_sys_open(const char __user *filename, int flags, int mode); extern struct file *filp_open(const char *, int, int); extern struct file * dentry_open(struct dentry *, struct vfsmount *, int); -- cgit v1.2.3 From 5b62073d502a88fedc5c369f8a004bda7c9d1999 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 7 Nov 2005 00:59:49 -0800 Subject: [PATCH] FUSE: bump interface minor version Though the following changes are all backward compatible (from the kernel's as well as the library's POV) change the minor version, so interested applications can detect new features. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/fuse.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/fuse.h b/include/linux/fuse.h index f98854c2abd7..6e91c9a3a0b6 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -14,7 +14,7 @@ #define FUSE_KERNEL_VERSION 7 /** Minor version number of this interface */ -#define FUSE_KERNEL_MINOR_VERSION 2 +#define FUSE_KERNEL_MINOR_VERSION 3 /** The node ID of the root inode */ #define FUSE_ROOT_ID 1 -- cgit v1.2.3 From 31d40d74b402a6fa18a006fb3745f64609f35b77 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 7 Nov 2005 00:59:50 -0800 Subject: [PATCH] FUSE: add access call Add a new access call, which will only be called if ->permission is invoked from sys_access(). In all other cases permission checking is delayed until the actual filesystem operation. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dir.c | 35 +++++++++++++++++++++++++++++++++++ fs/fuse/fuse_i.h | 3 +++ include/linux/fuse.h | 8 +++++++- 3 files changed, 45 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 61b58fdd973e..4bc1afcc476d 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -461,6 +461,38 @@ static int fuse_revalidate(struct dentry *entry) return fuse_do_getattr(inode); } +static int fuse_access(struct inode *inode, int mask) +{ + struct fuse_conn *fc = get_fuse_conn(inode); + struct fuse_req *req; + struct fuse_access_in inarg; + int err; + + if (fc->no_access) + return 0; + + req = fuse_get_request(fc); + if (!req) + return -EINTR; + + memset(&inarg, 0, sizeof(inarg)); + inarg.mask = mask; + req->in.h.opcode = FUSE_ACCESS; + req->in.h.nodeid = get_node_id(inode); + req->inode = inode; + req->in.numargs = 1; + req->in.args[0].size = sizeof(inarg); + req->in.args[0].value = &inarg; + request_send(fc, req); + err = req->out.h.error; + fuse_put_request(fc, req); + if (err == -ENOSYS) { + fc->no_access = 1; + err = 0; + } + return err; +} + static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) { struct fuse_conn *fc = get_fuse_conn(inode); @@ -493,6 +525,9 @@ static int fuse_permission(struct inode *inode, int mask, struct nameidata *nd) int mode = inode->i_mode; if ((mask & MAY_EXEC) && !S_ISDIR(mode) && !(mode & S_IXUGO)) return -EACCES; + + if (nd && (nd->flags & LOOKUP_ACCESS)) + return fuse_access(inode, mask); return 0; } } diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 5cb456f572c1..c4e8c3b47982 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -266,6 +266,9 @@ struct fuse_conn { /** Is removexattr not implemented by fs? */ unsigned no_removexattr : 1; + /** Is access not implemented by fs? */ + unsigned no_access : 1; + /** Backing dev info */ struct backing_dev_info bdi; }; diff --git a/include/linux/fuse.h b/include/linux/fuse.h index 6e91c9a3a0b6..507913b65af0 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -99,7 +99,8 @@ enum fuse_opcode { FUSE_OPENDIR = 27, FUSE_READDIR = 28, FUSE_RELEASEDIR = 29, - FUSE_FSYNCDIR = 30 + FUSE_FSYNCDIR = 30, + FUSE_ACCESS = 34 }; /* Conservative buffer size for the client */ @@ -222,6 +223,11 @@ struct fuse_getxattr_out { __u32 padding; }; +struct fuse_access_in { + __u32 mask; + __u32 padding; +}; + struct fuse_init_in_out { __u32 major; __u32 minor; -- cgit v1.2.3 From fd72faac95d7e47610e981d7ed7b3c1529e55c88 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 7 Nov 2005 00:59:51 -0800 Subject: [PATCH] FUSE: atomic create+open This patch adds an atomic create+open operation. This does not yet work if the file type changes between lookup and create+open, but solves the permission checking problems for the separte create and open methods. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dev.c | 7 +++ fs/fuse/dir.c | 106 ++++++++++++++++++++++++++++++++++++++++- fs/fuse/file.c | 132 +++++++++++++++++++++++++++++++++------------------ fs/fuse/fuse_i.h | 14 ++++++ include/linux/fuse.h | 5 +- 5 files changed, 214 insertions(+), 50 deletions(-) (limited to 'include/linux') diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index a6f90a6c754a..8f873e621f41 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -184,6 +184,13 @@ static void request_end(struct fuse_conn *fc, struct fuse_req *req) fuse_putback_request() */ for (i = 1; i < FUSE_MAX_OUTSTANDING; i++) up(&fc->outstanding_sem); + } else if (req->in.h.opcode == FUSE_RELEASE && req->inode == NULL) { + /* Special case for failed iget in CREATE */ + u64 nodeid = req->in.h.nodeid; + __fuse_get_request(req); + fuse_reset_request(req); + fuse_send_forget(fc, req, nodeid, 1); + putback = 0; } if (putback) fuse_putback_request(fc, req); diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 4bc1afcc476d..83be119ef067 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -13,6 +13,7 @@ #include #include #include +#include static inline unsigned long time_to_jiffies(unsigned long sec, unsigned long nsec) @@ -134,6 +135,101 @@ static void fuse_invalidate_entry(struct dentry *entry) entry->d_time = jiffies - 1; } +static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode, + struct nameidata *nd) +{ + int err; + struct inode *inode; + struct fuse_conn *fc = get_fuse_conn(dir); + struct fuse_req *req; + struct fuse_open_in inarg; + struct fuse_open_out outopen; + struct fuse_entry_out outentry; + struct fuse_inode *fi; + struct fuse_file *ff; + struct file *file; + int flags = nd->intent.open.flags - 1; + + err = -ENOSYS; + if (fc->no_create) + goto out; + + err = -ENAMETOOLONG; + if (entry->d_name.len > FUSE_NAME_MAX) + goto out; + + err = -EINTR; + req = fuse_get_request(fc); + if (!req) + goto out; + + ff = fuse_file_alloc(); + if (!ff) + goto out_put_request; + + flags &= ~O_NOCTTY; + memset(&inarg, 0, sizeof(inarg)); + inarg.flags = flags; + inarg.mode = mode; + req->in.h.opcode = FUSE_CREATE; + req->in.h.nodeid = get_node_id(dir); + req->inode = dir; + req->in.numargs = 2; + req->in.args[0].size = sizeof(inarg); + req->in.args[0].value = &inarg; + req->in.args[1].size = entry->d_name.len + 1; + req->in.args[1].value = entry->d_name.name; + req->out.numargs = 2; + req->out.args[0].size = sizeof(outentry); + req->out.args[0].value = &outentry; + req->out.args[1].size = sizeof(outopen); + req->out.args[1].value = &outopen; + request_send(fc, req); + err = req->out.h.error; + if (err) { + if (err == -ENOSYS) + fc->no_create = 1; + goto out_free_ff; + } + + err = -EIO; + if (!S_ISREG(outentry.attr.mode)) + goto out_free_ff; + + inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation, + &outentry.attr); + err = -ENOMEM; + if (!inode) { + flags &= ~(O_CREAT | O_EXCL | O_TRUNC); + ff->fh = outopen.fh; + fuse_send_release(fc, ff, outentry.nodeid, NULL, flags, 0); + goto out_put_request; + } + fuse_put_request(fc, req); + entry->d_time = time_to_jiffies(outentry.entry_valid, + outentry.entry_valid_nsec); + fi = get_fuse_inode(inode); + fi->i_time = time_to_jiffies(outentry.attr_valid, + outentry.attr_valid_nsec); + + d_instantiate(entry, inode); + file = lookup_instantiate_filp(nd, entry, generic_file_open); + if (IS_ERR(file)) { + ff->fh = outopen.fh; + fuse_send_release(fc, ff, outentry.nodeid, inode, flags, 0); + return PTR_ERR(file); + } + fuse_finish_open(inode, file, ff, &outopen); + return 0; + + out_free_ff: + fuse_file_free(ff); + out_put_request: + fuse_put_request(fc, req); + out: + return err; +} + static int create_new_entry(struct fuse_conn *fc, struct fuse_req *req, struct inode *dir, struct dentry *entry, int mode) @@ -208,6 +304,12 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode, static int fuse_create(struct inode *dir, struct dentry *entry, int mode, struct nameidata *nd) { + if (nd && (nd->flags & LOOKUP_CREATE)) { + int err = fuse_create_open(dir, entry, mode, nd); + if (err != -ENOSYS) + return err; + /* Fall back on mknod */ + } return fuse_mknod(dir, entry, mode, 0); } @@ -767,7 +869,9 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry, struct nameidata *nd) { struct inode *inode; - int err = fuse_lookup_iget(dir, entry, &inode); + int err; + + err = fuse_lookup_iget(dir, entry, &inode); if (err) return ERR_PTR(err); if (inode && S_ISDIR(inode->i_mode)) { diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 657ab11c173b..2ca86141d13a 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -14,11 +14,69 @@ static struct file_operations fuse_direct_io_file_operations; -int fuse_open_common(struct inode *inode, struct file *file, int isdir) +static int fuse_send_open(struct inode *inode, struct file *file, int isdir, + struct fuse_open_out *outargp) { struct fuse_conn *fc = get_fuse_conn(inode); - struct fuse_req *req; struct fuse_open_in inarg; + struct fuse_req *req; + int err; + + req = fuse_get_request(fc); + if (!req) + return -EINTR; + + memset(&inarg, 0, sizeof(inarg)); + inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); + req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; + req->in.h.nodeid = get_node_id(inode); + req->inode = inode; + req->in.numargs = 1; + req->in.args[0].size = sizeof(inarg); + req->in.args[0].value = &inarg; + req->out.numargs = 1; + req->out.args[0].size = sizeof(*outargp); + req->out.args[0].value = outargp; + request_send(fc, req); + err = req->out.h.error; + fuse_put_request(fc, req); + + return err; +} + +struct fuse_file *fuse_file_alloc(void) +{ + struct fuse_file *ff; + ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL); + if (ff) { + ff->release_req = fuse_request_alloc(); + if (!ff->release_req) { + kfree(ff); + ff = NULL; + } + } + return ff; +} + +void fuse_file_free(struct fuse_file *ff) +{ + fuse_request_free(ff->release_req); + kfree(ff); +} + +void fuse_finish_open(struct inode *inode, struct file *file, + struct fuse_file *ff, struct fuse_open_out *outarg) +{ + if (outarg->open_flags & FOPEN_DIRECT_IO) + file->f_op = &fuse_direct_io_file_operations; + if (!(outarg->open_flags & FOPEN_KEEP_CACHE)) + invalidate_inode_pages(inode->i_mapping); + ff->fh = outarg->fh; + file->private_data = ff; +} + +int fuse_open_common(struct inode *inode, struct file *file, int isdir) +{ struct fuse_open_out outarg; struct fuse_file *ff; int err; @@ -34,73 +92,53 @@ int fuse_open_common(struct inode *inode, struct file *file, int isdir) /* If opening the root node, no lookup has been performed on it, so the attributes must be refreshed */ if (get_node_id(inode) == FUSE_ROOT_ID) { - int err = fuse_do_getattr(inode); + err = fuse_do_getattr(inode); if (err) return err; } - req = fuse_get_request(fc); - if (!req) - return -EINTR; - - err = -ENOMEM; - ff = kmalloc(sizeof(struct fuse_file), GFP_KERNEL); + ff = fuse_file_alloc(); if (!ff) - goto out_put_request; + return -ENOMEM; - ff->release_req = fuse_request_alloc(); - if (!ff->release_req) { - kfree(ff); - goto out_put_request; - } - - memset(&inarg, 0, sizeof(inarg)); - inarg.flags = file->f_flags & ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC); - req->in.h.opcode = isdir ? FUSE_OPENDIR : FUSE_OPEN; - req->in.h.nodeid = get_node_id(inode); - req->inode = inode; - req->in.numargs = 1; - req->in.args[0].size = sizeof(inarg); - req->in.args[0].value = &inarg; - req->out.numargs = 1; - req->out.args[0].size = sizeof(outarg); - req->out.args[0].value = &outarg; - request_send(fc, req); - err = req->out.h.error; - if (err) { - fuse_request_free(ff->release_req); - kfree(ff); - } else { - if (!isdir && (outarg.open_flags & FOPEN_DIRECT_IO)) - file->f_op = &fuse_direct_io_file_operations; - if (!(outarg.open_flags & FOPEN_KEEP_CACHE)) - invalidate_inode_pages(inode->i_mapping); - ff->fh = outarg.fh; - file->private_data = ff; + err = fuse_send_open(inode, file, isdir, &outarg); + if (err) + fuse_file_free(ff); + else { + if (isdir) + outarg.open_flags &= ~FOPEN_DIRECT_IO; + fuse_finish_open(inode, file, ff, &outarg); } - out_put_request: - fuse_put_request(fc, req); return err; } -int fuse_release_common(struct inode *inode, struct file *file, int isdir) +void fuse_send_release(struct fuse_conn *fc, struct fuse_file *ff, + u64 nodeid, struct inode *inode, int flags, int isdir) { - struct fuse_conn *fc = get_fuse_conn(inode); - struct fuse_file *ff = file->private_data; - struct fuse_req *req = ff->release_req; + struct fuse_req * req = ff->release_req; struct fuse_release_in *inarg = &req->misc.release_in; inarg->fh = ff->fh; - inarg->flags = file->f_flags & ~O_EXCL; + inarg->flags = flags; req->in.h.opcode = isdir ? FUSE_RELEASEDIR : FUSE_RELEASE; - req->in.h.nodeid = get_node_id(inode); + req->in.h.nodeid = nodeid; req->inode = inode; req->in.numargs = 1; req->in.args[0].size = sizeof(struct fuse_release_in); req->in.args[0].value = inarg; request_send_background(fc, req); kfree(ff); +} + +int fuse_release_common(struct inode *inode, struct file *file, int isdir) +{ + struct fuse_file *ff = file->private_data; + if (ff) { + struct fuse_conn *fc = get_fuse_conn(inode); + u64 nodeid = get_node_id(inode); + fuse_send_release(fc, ff, nodeid, inode, file->f_flags, isdir); + } /* Return value is ignored by VFS */ return 0; diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index c4e8c3b47982..0ea5301f86be 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -269,6 +269,9 @@ struct fuse_conn { /** Is access not implemented by fs? */ unsigned no_access : 1; + /** Is create not implemented by fs? */ + unsigned no_create : 1; + /** Backing dev info */ struct backing_dev_info bdi; }; @@ -340,6 +343,17 @@ size_t fuse_send_read_common(struct fuse_req *req, struct file *file, */ int fuse_open_common(struct inode *inode, struct file *file, int isdir); +struct fuse_file *fuse_file_alloc(void); +void fuse_file_free(struct fuse_file *ff); +void fuse_finish_open(struct inode *inode, struct file *file, + struct fuse_file *ff, struct fuse_open_out *outarg); + +/** + * Send a RELEASE request + */ +void fuse_send_release(struct fuse_conn *fc, struct fuse_file *ff, + u64 nodeid, struct inode *inode, int flags, int isdir); + /** * Send RELEASE or RELEASEDIR request */ diff --git a/include/linux/fuse.h b/include/linux/fuse.h index 507913b65af0..45c398f08247 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -100,7 +100,8 @@ enum fuse_opcode { FUSE_READDIR = 28, FUSE_RELEASEDIR = 29, FUSE_FSYNCDIR = 30, - FUSE_ACCESS = 34 + FUSE_ACCESS = 34, + FUSE_CREATE = 35 }; /* Conservative buffer size for the client */ @@ -158,7 +159,7 @@ struct fuse_setattr_in { struct fuse_open_in { __u32 flags; - __u32 padding; + __u32 mode; }; struct fuse_open_out { -- cgit v1.2.3 From befc649c2274a1c35f0cd1e888dd83652cbb0422 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Mon, 7 Nov 2005 00:59:52 -0800 Subject: [PATCH] FUSE: pass file handle in setattr This patch passes the file handle supplied in iattr to userspace, in case the ->setattr() was invoked from sys_ftruncate(). This solves the permission checking (or lack thereof) in ftruncate() for the class of filesystems served by an unprivileged userspace process. Signed-off-by: Miklos Szeredi Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/fuse/dir.c | 28 ++++++++++++++-------------- include/linux/fuse.h | 16 +++++++++++++++- 2 files changed, 29 insertions(+), 15 deletions(-) (limited to 'include/linux') diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index 83be119ef067..c045cc70c749 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -763,29 +763,29 @@ static int fuse_dir_fsync(struct file *file, struct dentry *de, int datasync) return file ? fuse_fsync_common(file, de, datasync, 1) : 0; } -static unsigned iattr_to_fattr(struct iattr *iattr, struct fuse_attr *fattr) +static void iattr_to_fattr(struct iattr *iattr, struct fuse_setattr_in *arg) { unsigned ivalid = iattr->ia_valid; - unsigned fvalid = 0; - - memset(fattr, 0, sizeof(*fattr)); if (ivalid & ATTR_MODE) - fvalid |= FATTR_MODE, fattr->mode = iattr->ia_mode; + arg->valid |= FATTR_MODE, arg->mode = iattr->ia_mode; if (ivalid & ATTR_UID) - fvalid |= FATTR_UID, fattr->uid = iattr->ia_uid; + arg->valid |= FATTR_UID, arg->uid = iattr->ia_uid; if (ivalid & ATTR_GID) - fvalid |= FATTR_GID, fattr->gid = iattr->ia_gid; + arg->valid |= FATTR_GID, arg->gid = iattr->ia_gid; if (ivalid & ATTR_SIZE) - fvalid |= FATTR_SIZE, fattr->size = iattr->ia_size; + arg->valid |= FATTR_SIZE, arg->size = iattr->ia_size; /* You can only _set_ these together (they may change by themselves) */ if ((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) { - fvalid |= FATTR_ATIME | FATTR_MTIME; - fattr->atime = iattr->ia_atime.tv_sec; - fattr->mtime = iattr->ia_mtime.tv_sec; + arg->valid |= FATTR_ATIME | FATTR_MTIME; + arg->atime = iattr->ia_atime.tv_sec; + arg->mtime = iattr->ia_mtime.tv_sec; + } + if (ivalid & ATTR_FILE) { + struct fuse_file *ff = iattr->ia_file->private_data; + arg->valid |= FATTR_FH; + arg->fh = ff->fh; } - - return fvalid; } static int fuse_setattr(struct dentry *entry, struct iattr *attr) @@ -820,7 +820,7 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr) return -EINTR; memset(&inarg, 0, sizeof(inarg)); - inarg.valid = iattr_to_fattr(attr, &inarg.attr); + iattr_to_fattr(attr, &inarg); req->in.h.opcode = FUSE_SETATTR; req->in.h.nodeid = get_node_id(inode); req->inode = inode; diff --git a/include/linux/fuse.h b/include/linux/fuse.h index 45c398f08247..b76b558b03d4 100644 --- a/include/linux/fuse.h +++ b/include/linux/fuse.h @@ -61,6 +61,7 @@ struct fuse_kstatfs { #define FATTR_SIZE (1 << 3) #define FATTR_ATIME (1 << 4) #define FATTR_MTIME (1 << 5) +#define FATTR_FH (1 << 6) /** * Flags returned by the OPEN request @@ -154,7 +155,20 @@ struct fuse_link_in { struct fuse_setattr_in { __u32 valid; __u32 padding; - struct fuse_attr attr; + __u64 fh; + __u64 size; + __u64 unused1; + __u64 atime; + __u64 mtime; + __u64 unused2; + __u32 atimensec; + __u32 mtimensec; + __u32 unused3; + __u32 mode; + __u32 unused4; + __u32 uid; + __u32 gid; + __u32 unused5; }; struct fuse_open_in { -- cgit v1.2.3 From 393d2cc354d150b8b4bb888a9da7db4c935e12bd Mon Sep 17 00:00:00 2001 From: Corey Minyard Date: Mon, 7 Nov 2005 00:59:54 -0800 Subject: [PATCH] ipmi: use refcount in message handler This patch is rather large, but it really can't be done in smaller chunks easily and I believe it is an important change. This has been out and tested for a while in the latest IPMI driver release. There are no functional changes, just changes as necessary to convert the locking over (and a few minor style updates). The IPMI driver uses read/write locks to ensure that things exist while they are in use. This is bad from a number of points of view. This patch removes the rwlocks and uses refcounts and RCU lists to manage what the locks did. Signed-off-by: Corey Minyard Cc: Matt Domsch Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_msghandler.c | 953 +++++++++++++++++++----------------- include/linux/ipmi.h | 5 +- 2 files changed, 499 insertions(+), 459 deletions(-) (limited to 'include/linux') diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 32fa82c78c73..320d7f035bf9 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -38,13 +38,13 @@ #include #include #include -#include #include #include #include #include #include #include +#include #define PFX "IPMI message handler: " @@ -65,10 +65,19 @@ struct proc_dir_entry *proc_ipmi_root = NULL; the max message timer. This is in milliseconds. */ #define MAX_MSG_TIMEOUT 60000 + +/* + * The main "user" data structure. + */ struct ipmi_user { struct list_head link; + /* Set to "0" when the user is destroyed. */ + int valid; + + struct kref refcount; + /* The upper layer that handles receive messages. */ struct ipmi_user_hndl *handler; void *handler_data; @@ -87,6 +96,15 @@ struct cmd_rcvr ipmi_user_t user; unsigned char netfn; unsigned char cmd; + + /* + * This is used to form a linked lised during mass deletion. + * Since this is in an RCU list, we cannot use the link above + * or change any data until the RCU period completes. So we + * use this next variable during mass deletion so we can have + * a list and don't have to wait and restart the search on + * every individual deletion of a command. */ + struct cmd_rcvr *next; }; struct seq_table @@ -150,13 +168,11 @@ struct ipmi_smi /* What interface number are we? */ int intf_num; - /* The list of upper layers that are using me. We read-lock - this when delivering messages to the upper layer to keep - the user from going away while we are processing the - message. This means that you cannot add or delete a user - from the receive callback. */ - rwlock_t users_lock; - struct list_head users; + struct kref refcount; + + /* The list of upper layers that are using me. seq_lock + * protects this. */ + struct list_head users; /* Used for wake ups at startup. */ wait_queue_head_t waitq; @@ -193,7 +209,7 @@ struct ipmi_smi /* The list of command receivers that are registered for commands on this interface. */ - rwlock_t cmd_rcvr_lock; + spinlock_t cmd_rcvrs_lock; struct list_head cmd_rcvrs; /* Events that were queues because no one was there to receive @@ -296,16 +312,17 @@ struct ipmi_smi unsigned int events; }; +/* Used to mark an interface entry that cannot be used but is not a + * free entry, either, primarily used at creation and deletion time so + * a slot doesn't get reused too quickly. */ +#define IPMI_INVALID_INTERFACE_ENTRY ((ipmi_smi_t) ((long) 1)) +#define IPMI_INVALID_INTERFACE(i) (((i) == NULL) \ + || (i == IPMI_INVALID_INTERFACE_ENTRY)) + #define MAX_IPMI_INTERFACES 4 static ipmi_smi_t ipmi_interfaces[MAX_IPMI_INTERFACES]; -/* Used to keep interfaces from going away while operations are - operating on interfaces. Grab read if you are not modifying the - interfaces, write if you are. */ -static DECLARE_RWSEM(interfaces_sem); - -/* Directly protects the ipmi_interfaces data structure. This is - claimed in the timer interrupt. */ +/* Directly protects the ipmi_interfaces data structure. */ static DEFINE_SPINLOCK(interfaces_lock); /* List of watchers that want to know when smi's are added and @@ -313,20 +330,73 @@ static DEFINE_SPINLOCK(interfaces_lock); static struct list_head smi_watchers = LIST_HEAD_INIT(smi_watchers); static DECLARE_RWSEM(smi_watchers_sem); + +static void free_recv_msg_list(struct list_head *q) +{ + struct ipmi_recv_msg *msg, *msg2; + + list_for_each_entry_safe(msg, msg2, q, link) { + list_del(&msg->link); + ipmi_free_recv_msg(msg); + } +} + +static void clean_up_interface_data(ipmi_smi_t intf) +{ + int i; + struct cmd_rcvr *rcvr, *rcvr2; + unsigned long flags; + struct list_head list; + + free_recv_msg_list(&intf->waiting_msgs); + free_recv_msg_list(&intf->waiting_events); + + /* Wholesale remove all the entries from the list in the + * interface and wait for RCU to know that none are in use. */ + spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags); + list_add_rcu(&list, &intf->cmd_rcvrs); + list_del_rcu(&intf->cmd_rcvrs); + spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags); + synchronize_rcu(); + + list_for_each_entry_safe(rcvr, rcvr2, &list, link) + kfree(rcvr); + + for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) { + if ((intf->seq_table[i].inuse) + && (intf->seq_table[i].recv_msg)) + { + ipmi_free_recv_msg(intf->seq_table[i].recv_msg); + } + } +} + +static void intf_free(struct kref *ref) +{ + ipmi_smi_t intf = container_of(ref, struct ipmi_smi, refcount); + + clean_up_interface_data(intf); + kfree(intf); +} + int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher) { - int i; + int i; + unsigned long flags; - down_read(&interfaces_sem); down_write(&smi_watchers_sem); list_add(&(watcher->link), &smi_watchers); + up_write(&smi_watchers_sem); + spin_lock_irqsave(&interfaces_lock, flags); for (i = 0; i < MAX_IPMI_INTERFACES; i++) { - if (ipmi_interfaces[i] != NULL) { - watcher->new_smi(i); - } + ipmi_smi_t intf = ipmi_interfaces[i]; + if (IPMI_INVALID_INTERFACE(intf)) + continue; + spin_unlock_irqrestore(&interfaces_lock, flags); + watcher->new_smi(i); + spin_lock_irqsave(&interfaces_lock, flags); } - up_write(&smi_watchers_sem); - up_read(&interfaces_sem); + spin_unlock_irqrestore(&interfaces_lock, flags); return 0; } @@ -471,8 +541,8 @@ static void deliver_response(struct ipmi_recv_msg *msg) } ipmi_free_recv_msg(msg); } else { - msg->user->handler->ipmi_recv_hndl(msg, - msg->user->handler_data); + ipmi_user_t user = msg->user; + user->handler->ipmi_recv_hndl(msg, user->handler_data); } } @@ -662,15 +732,18 @@ int ipmi_create_user(unsigned int if_num, if (! new_user) return -ENOMEM; - down_read(&interfaces_sem); - if ((if_num >= MAX_IPMI_INTERFACES) || ipmi_interfaces[if_num] == NULL) - { - rv = -EINVAL; - goto out_unlock; + spin_lock_irqsave(&interfaces_lock, flags); + intf = ipmi_interfaces[if_num]; + if ((if_num >= MAX_IPMI_INTERFACES) || IPMI_INVALID_INTERFACE(intf)) { + spin_unlock_irqrestore(&interfaces_lock, flags); + return -EINVAL; } - intf = ipmi_interfaces[if_num]; + /* Note that each existing user holds a refcount to the interface. */ + kref_get(&intf->refcount); + spin_unlock_irqrestore(&interfaces_lock, flags); + kref_init(&new_user->refcount); new_user->handler = handler; new_user->handler_data = handler_data; new_user->intf = intf; @@ -678,98 +751,92 @@ int ipmi_create_user(unsigned int if_num, if (!try_module_get(intf->handlers->owner)) { rv = -ENODEV; - goto out_unlock; + goto out_err; } if (intf->handlers->inc_usecount) { rv = intf->handlers->inc_usecount(intf->send_info); if (rv) { module_put(intf->handlers->owner); - goto out_unlock; + goto out_err; } } - write_lock_irqsave(&intf->users_lock, flags); - list_add_tail(&new_user->link, &intf->users); - write_unlock_irqrestore(&intf->users_lock, flags); - - out_unlock: - if (rv) { - kfree(new_user); - } else { - *user = new_user; - } + new_user->valid = 1; + spin_lock_irqsave(&intf->seq_lock, flags); + list_add_rcu(&new_user->link, &intf->users); + spin_unlock_irqrestore(&intf->seq_lock, flags); + *user = new_user; + return 0; - up_read(&interfaces_sem); + out_err: + kfree(new_user); + kref_put(&intf->refcount, intf_free); return rv; } -static int ipmi_destroy_user_nolock(ipmi_user_t user) +static void free_user(struct kref *ref) +{ + ipmi_user_t user = container_of(ref, struct ipmi_user, refcount); + kfree(user); +} + +int ipmi_destroy_user(ipmi_user_t user) { int rv = -ENODEV; - ipmi_user_t t_user; - struct cmd_rcvr *rcvr, *rcvr2; + ipmi_smi_t intf = user->intf; int i; unsigned long flags; + struct cmd_rcvr *rcvr; + struct list_head *entry1, *entry2; + struct cmd_rcvr *rcvrs = NULL; - /* Find the user and delete them from the list. */ - list_for_each_entry(t_user, &(user->intf->users), link) { - if (t_user == user) { - list_del(&t_user->link); - rv = 0; - break; - } - } + user->valid = 1; - if (rv) { - goto out_unlock; - } + /* Remove the user from the interface's sequence table. */ + spin_lock_irqsave(&intf->seq_lock, flags); + list_del_rcu(&user->link); - /* Remove the user from the interfaces sequence table. */ - spin_lock_irqsave(&(user->intf->seq_lock), flags); for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) { - if (user->intf->seq_table[i].inuse - && (user->intf->seq_table[i].recv_msg->user == user)) + if (intf->seq_table[i].inuse + && (intf->seq_table[i].recv_msg->user == user)) { - user->intf->seq_table[i].inuse = 0; + intf->seq_table[i].inuse = 0; } } - spin_unlock_irqrestore(&(user->intf->seq_lock), flags); - - /* Remove the user from the command receiver's table. */ - write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags); - list_for_each_entry_safe(rcvr, rcvr2, &(user->intf->cmd_rcvrs), link) { + spin_unlock_irqrestore(&intf->seq_lock, flags); + + /* + * Remove the user from the command receiver's table. First + * we build a list of everything (not using the standard link, + * since other things may be using it till we do + * synchronize_rcu()) then free everything in that list. + */ + spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags); + list_for_each_safe_rcu(entry1, entry2, &intf->cmd_rcvrs) { + rcvr = list_entry(entry1, struct cmd_rcvr, link); if (rcvr->user == user) { - list_del(&rcvr->link); - kfree(rcvr); + list_del_rcu(&rcvr->link); + rcvr->next = rcvrs; + rcvrs = rcvr; } } - write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags); + spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags); + synchronize_rcu(); + while (rcvrs) { + rcvr = rcvrs; + rcvrs = rcvr->next; + kfree(rcvr); + } - kfree(user); + module_put(intf->handlers->owner); + if (intf->handlers->dec_usecount) + intf->handlers->dec_usecount(intf->send_info); - out_unlock: + kref_put(&intf->refcount, intf_free); - return rv; -} - -int ipmi_destroy_user(ipmi_user_t user) -{ - int rv; - ipmi_smi_t intf = user->intf; - unsigned long flags; + kref_put(&user->refcount, free_user); - down_read(&interfaces_sem); - write_lock_irqsave(&intf->users_lock, flags); - rv = ipmi_destroy_user_nolock(user); - if (!rv) { - module_put(intf->handlers->owner); - if (intf->handlers->dec_usecount) - intf->handlers->dec_usecount(intf->send_info); - } - - write_unlock_irqrestore(&intf->users_lock, flags); - up_read(&interfaces_sem); return rv; } @@ -823,62 +890,78 @@ int ipmi_get_my_LUN(ipmi_user_t user, int ipmi_set_gets_events(ipmi_user_t user, int val) { - unsigned long flags; - struct ipmi_recv_msg *msg, *msg2; + unsigned long flags; + ipmi_smi_t intf = user->intf; + struct ipmi_recv_msg *msg, *msg2; + struct list_head msgs; - read_lock(&(user->intf->users_lock)); - spin_lock_irqsave(&(user->intf->events_lock), flags); + INIT_LIST_HEAD(&msgs); + + spin_lock_irqsave(&intf->events_lock, flags); user->gets_events = val; if (val) { /* Deliver any queued events. */ - list_for_each_entry_safe(msg, msg2, &(user->intf->waiting_events), link) { + list_for_each_entry_safe(msg, msg2, &intf->waiting_events, link) { list_del(&msg->link); - msg->user = user; - deliver_response(msg); + list_add_tail(&msg->link, &msgs); } } - - spin_unlock_irqrestore(&(user->intf->events_lock), flags); - read_unlock(&(user->intf->users_lock)); + + /* Hold the events lock while doing this to preserve order. */ + list_for_each_entry_safe(msg, msg2, &msgs, link) { + msg->user = user; + kref_get(&user->refcount); + deliver_response(msg); + } + + spin_unlock_irqrestore(&intf->events_lock, flags); return 0; } +static struct cmd_rcvr *find_cmd_rcvr(ipmi_smi_t intf, + unsigned char netfn, + unsigned char cmd) +{ + struct cmd_rcvr *rcvr; + + list_for_each_entry_rcu(rcvr, &intf->cmd_rcvrs, link) { + if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) + return rcvr; + } + return NULL; +} + int ipmi_register_for_cmd(ipmi_user_t user, unsigned char netfn, unsigned char cmd) { - struct cmd_rcvr *cmp; - unsigned long flags; - struct cmd_rcvr *rcvr; - int rv = 0; + ipmi_smi_t intf = user->intf; + struct cmd_rcvr *rcvr; + struct cmd_rcvr *entry; + int rv = 0; rcvr = kmalloc(sizeof(*rcvr), GFP_KERNEL); if (! rcvr) return -ENOMEM; + rcvr->cmd = cmd; + rcvr->netfn = netfn; + rcvr->user = user; - read_lock(&(user->intf->users_lock)); - write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags); + spin_lock_irq(&intf->cmd_rcvrs_lock); /* Make sure the command/netfn is not already registered. */ - list_for_each_entry(cmp, &(user->intf->cmd_rcvrs), link) { - if ((cmp->netfn == netfn) && (cmp->cmd == cmd)) { - rv = -EBUSY; - break; - } - } - - if (! rv) { - rcvr->cmd = cmd; - rcvr->netfn = netfn; - rcvr->user = user; - list_add_tail(&(rcvr->link), &(user->intf->cmd_rcvrs)); + entry = find_cmd_rcvr(intf, netfn, cmd); + if (entry) { + rv = -EBUSY; + goto out_unlock; } - write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags); - read_unlock(&(user->intf->users_lock)); + list_add_rcu(&rcvr->link, &intf->cmd_rcvrs); + out_unlock: + spin_unlock_irq(&intf->cmd_rcvrs_lock); if (rv) kfree(rcvr); @@ -889,31 +972,28 @@ int ipmi_unregister_for_cmd(ipmi_user_t user, unsigned char netfn, unsigned char cmd) { - unsigned long flags; - struct cmd_rcvr *rcvr; - int rv = -ENOENT; + ipmi_smi_t intf = user->intf; + struct cmd_rcvr *rcvr; - read_lock(&(user->intf->users_lock)); - write_lock_irqsave(&(user->intf->cmd_rcvr_lock), flags); + spin_lock_irq(&intf->cmd_rcvrs_lock); /* Make sure the command/netfn is not already registered. */ - list_for_each_entry(rcvr, &(user->intf->cmd_rcvrs), link) { - if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) { - rv = 0; - list_del(&rcvr->link); - kfree(rcvr); - break; - } + rcvr = find_cmd_rcvr(intf, netfn, cmd); + if ((rcvr) && (rcvr->user == user)) { + list_del_rcu(&rcvr->link); + spin_unlock_irq(&intf->cmd_rcvrs_lock); + synchronize_rcu(); + kfree(rcvr); + return 0; + } else { + spin_unlock_irq(&intf->cmd_rcvrs_lock); + return -ENOENT; } - write_unlock_irqrestore(&(user->intf->cmd_rcvr_lock), flags); - read_unlock(&(user->intf->users_lock)); - - return rv; } void ipmi_user_set_run_to_completion(ipmi_user_t user, int val) { - user->intf->handlers->set_run_to_completion(user->intf->send_info, - val); + ipmi_smi_t intf = user->intf; + intf->handlers->set_run_to_completion(intf->send_info, val); } static unsigned char @@ -1010,19 +1090,19 @@ static inline void format_lan_msg(struct ipmi_smi_msg *smi_msg, supplied in certain circumstances (mainly at panic time). If messages are supplied, they will be freed, even if an error occurs. */ -static inline int i_ipmi_request(ipmi_user_t user, - ipmi_smi_t intf, - struct ipmi_addr *addr, - long msgid, - struct kernel_ipmi_msg *msg, - void *user_msg_data, - void *supplied_smi, - struct ipmi_recv_msg *supplied_recv, - int priority, - unsigned char source_address, - unsigned char source_lun, - int retries, - unsigned int retry_time_ms) +static int i_ipmi_request(ipmi_user_t user, + ipmi_smi_t intf, + struct ipmi_addr *addr, + long msgid, + struct kernel_ipmi_msg *msg, + void *user_msg_data, + void *supplied_smi, + struct ipmi_recv_msg *supplied_recv, + int priority, + unsigned char source_address, + unsigned char source_lun, + int retries, + unsigned int retry_time_ms) { int rv = 0; struct ipmi_smi_msg *smi_msg; @@ -1051,6 +1131,8 @@ static inline int i_ipmi_request(ipmi_user_t user, } recv_msg->user = user; + if (user) + kref_get(&user->refcount); recv_msg->msgid = msgid; /* Store the message to send in the receive message so timeout responses can get the proper response data. */ @@ -1725,11 +1807,11 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, unsigned char version_major, unsigned char version_minor, unsigned char slave_addr, - ipmi_smi_t *intf) + ipmi_smi_t *new_intf) { int i, j; int rv; - ipmi_smi_t new_intf; + ipmi_smi_t intf; unsigned long flags; @@ -1745,189 +1827,142 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, return -ENODEV; } - new_intf = kmalloc(sizeof(*new_intf), GFP_KERNEL); - if (!new_intf) + intf = kmalloc(sizeof(*intf), GFP_KERNEL); + if (!intf) return -ENOMEM; - memset(new_intf, 0, sizeof(*new_intf)); - - new_intf->proc_dir = NULL; + memset(intf, 0, sizeof(*intf)); + intf->intf_num = -1; + kref_init(&intf->refcount); + intf->version_major = version_major; + intf->version_minor = version_minor; + for (j = 0; j < IPMI_MAX_CHANNELS; j++) { + intf->channels[j].address = IPMI_BMC_SLAVE_ADDR; + intf->channels[j].lun = 2; + } + if (slave_addr != 0) + intf->channels[0].address = slave_addr; + INIT_LIST_HEAD(&intf->users); + intf->handlers = handlers; + intf->send_info = send_info; + spin_lock_init(&intf->seq_lock); + for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) { + intf->seq_table[j].inuse = 0; + intf->seq_table[j].seqid = 0; + } + intf->curr_seq = 0; +#ifdef CONFIG_PROC_FS + spin_lock_init(&intf->proc_entry_lock); +#endif + spin_lock_init(&intf->waiting_msgs_lock); + INIT_LIST_HEAD(&intf->waiting_msgs); + spin_lock_init(&intf->events_lock); + INIT_LIST_HEAD(&intf->waiting_events); + intf->waiting_events_count = 0; + spin_lock_init(&intf->cmd_rcvrs_lock); + INIT_LIST_HEAD(&intf->cmd_rcvrs); + init_waitqueue_head(&intf->waitq); + + spin_lock_init(&intf->counter_lock); + intf->proc_dir = NULL; rv = -ENOMEM; - - down_write(&interfaces_sem); + spin_lock_irqsave(&interfaces_lock, flags); for (i = 0; i < MAX_IPMI_INTERFACES; i++) { if (ipmi_interfaces[i] == NULL) { - new_intf->intf_num = i; - new_intf->version_major = version_major; - new_intf->version_minor = version_minor; - for (j = 0; j < IPMI_MAX_CHANNELS; j++) { - new_intf->channels[j].address - = IPMI_BMC_SLAVE_ADDR; - new_intf->channels[j].lun = 2; - } - if (slave_addr != 0) - new_intf->channels[0].address = slave_addr; - rwlock_init(&(new_intf->users_lock)); - INIT_LIST_HEAD(&(new_intf->users)); - new_intf->handlers = handlers; - new_intf->send_info = send_info; - spin_lock_init(&(new_intf->seq_lock)); - for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) { - new_intf->seq_table[j].inuse = 0; - new_intf->seq_table[j].seqid = 0; - } - new_intf->curr_seq = 0; -#ifdef CONFIG_PROC_FS - spin_lock_init(&(new_intf->proc_entry_lock)); -#endif - spin_lock_init(&(new_intf->waiting_msgs_lock)); - INIT_LIST_HEAD(&(new_intf->waiting_msgs)); - spin_lock_init(&(new_intf->events_lock)); - INIT_LIST_HEAD(&(new_intf->waiting_events)); - new_intf->waiting_events_count = 0; - rwlock_init(&(new_intf->cmd_rcvr_lock)); - init_waitqueue_head(&new_intf->waitq); - INIT_LIST_HEAD(&(new_intf->cmd_rcvrs)); - - spin_lock_init(&(new_intf->counter_lock)); - - spin_lock_irqsave(&interfaces_lock, flags); - ipmi_interfaces[i] = new_intf; - spin_unlock_irqrestore(&interfaces_lock, flags); - + intf->intf_num = i; + /* Reserve the entry till we are done. */ + ipmi_interfaces[i] = IPMI_INVALID_INTERFACE_ENTRY; rv = 0; - *intf = new_intf; break; } } + spin_unlock_irqrestore(&interfaces_lock, flags); + if (rv) + goto out; - downgrade_write(&interfaces_sem); - - if (rv == 0) - rv = add_proc_entries(*intf, i); - - if (rv == 0) { - if ((version_major > 1) - || ((version_major == 1) && (version_minor >= 5))) - { - /* Start scanning the channels to see what is - available. */ - (*intf)->null_user_handler = channel_handler; - (*intf)->curr_channel = 0; - rv = send_channel_info_cmd(*intf, 0); - if (rv) - goto out; + /* FIXME - this is an ugly kludge, this sets the intf for the + caller before sending any messages with it. */ + *new_intf = intf; - /* Wait for the channel info to be read. */ - up_read(&interfaces_sem); - wait_event((*intf)->waitq, - ((*intf)->curr_channel>=IPMI_MAX_CHANNELS)); - down_read(&interfaces_sem); + if ((version_major > 1) + || ((version_major == 1) && (version_minor >= 5))) + { + /* Start scanning the channels to see what is + available. */ + intf->null_user_handler = channel_handler; + intf->curr_channel = 0; + rv = send_channel_info_cmd(intf, 0); + if (rv) + goto out; - if (ipmi_interfaces[i] != new_intf) - /* Well, it went away. Just return. */ - goto out; - } else { - /* Assume a single IPMB channel at zero. */ - (*intf)->channels[0].medium = IPMI_CHANNEL_MEDIUM_IPMB; - (*intf)->channels[0].protocol - = IPMI_CHANNEL_PROTOCOL_IPMB; - } - - /* Call all the watcher interfaces to tell - them that a new interface is available. */ - call_smi_watchers(i); + /* Wait for the channel info to be read. */ + wait_event(intf->waitq, + intf->curr_channel >= IPMI_MAX_CHANNELS); + } else { + /* Assume a single IPMB channel at zero. */ + intf->channels[0].medium = IPMI_CHANNEL_MEDIUM_IPMB; + intf->channels[0].protocol = IPMI_CHANNEL_PROTOCOL_IPMB; } - out: - up_read(&interfaces_sem); + if (rv == 0) + rv = add_proc_entries(intf, i); + out: if (rv) { - if (new_intf->proc_dir) - remove_proc_entries(new_intf); - kfree(new_intf); + if (intf->proc_dir) + remove_proc_entries(intf); + kref_put(&intf->refcount, intf_free); + if (i < MAX_IPMI_INTERFACES) { + spin_lock_irqsave(&interfaces_lock, flags); + ipmi_interfaces[i] = NULL; + spin_unlock_irqrestore(&interfaces_lock, flags); + } + } else { + spin_lock_irqsave(&interfaces_lock, flags); + ipmi_interfaces[i] = intf; + spin_unlock_irqrestore(&interfaces_lock, flags); + call_smi_watchers(i); } return rv; } -static void free_recv_msg_list(struct list_head *q) -{ - struct ipmi_recv_msg *msg, *msg2; - - list_for_each_entry_safe(msg, msg2, q, link) { - list_del(&msg->link); - ipmi_free_recv_msg(msg); - } -} - -static void free_cmd_rcvr_list(struct list_head *q) -{ - struct cmd_rcvr *rcvr, *rcvr2; - - list_for_each_entry_safe(rcvr, rcvr2, q, link) { - list_del(&rcvr->link); - kfree(rcvr); - } -} - -static void clean_up_interface_data(ipmi_smi_t intf) -{ - int i; - - free_recv_msg_list(&(intf->waiting_msgs)); - free_recv_msg_list(&(intf->waiting_events)); - free_cmd_rcvr_list(&(intf->cmd_rcvrs)); - - for (i = 0; i < IPMI_IPMB_NUM_SEQ; i++) { - if ((intf->seq_table[i].inuse) - && (intf->seq_table[i].recv_msg)) - { - ipmi_free_recv_msg(intf->seq_table[i].recv_msg); - } - } -} - int ipmi_unregister_smi(ipmi_smi_t intf) { - int rv = -ENODEV; int i; struct ipmi_smi_watcher *w; unsigned long flags; - down_write(&interfaces_sem); - if (list_empty(&(intf->users))) - { - for (i = 0; i < MAX_IPMI_INTERFACES; i++) { - if (ipmi_interfaces[i] == intf) { - remove_proc_entries(intf); - spin_lock_irqsave(&interfaces_lock, flags); - ipmi_interfaces[i] = NULL; - clean_up_interface_data(intf); - spin_unlock_irqrestore(&interfaces_lock,flags); - kfree(intf); - rv = 0; - goto out_call_watcher; - } + spin_lock_irqsave(&interfaces_lock, flags); + for (i = 0; i < MAX_IPMI_INTERFACES; i++) { + if (ipmi_interfaces[i] == intf) { + /* Set the interface number reserved until we + * are done. */ + ipmi_interfaces[i] = IPMI_INVALID_INTERFACE_ENTRY; + intf->intf_num = -1; + break; } - } else { - rv = -EBUSY; } - up_write(&interfaces_sem); + spin_unlock_irqrestore(&interfaces_lock,flags); - return rv; + if (i == MAX_IPMI_INTERFACES) + return -ENODEV; - out_call_watcher: - downgrade_write(&interfaces_sem); + remove_proc_entries(intf); /* Call all the watcher interfaces to tell them that an interface is gone. */ down_read(&smi_watchers_sem); - list_for_each_entry(w, &smi_watchers, link) { + list_for_each_entry(w, &smi_watchers, link) w->smi_gone(i); - } up_read(&smi_watchers_sem); - up_read(&interfaces_sem); + + /* Allow the entry to be reused now. */ + spin_lock_irqsave(&interfaces_lock, flags); + ipmi_interfaces[i] = NULL; + spin_unlock_irqrestore(&interfaces_lock,flags); + + kref_put(&intf->refcount, intf_free); return 0; } @@ -1998,14 +2033,14 @@ static int handle_ipmb_get_msg_rsp(ipmi_smi_t intf, static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, struct ipmi_smi_msg *msg) { - struct cmd_rcvr *rcvr; - int rv = 0; - unsigned char netfn; - unsigned char cmd; - ipmi_user_t user = NULL; - struct ipmi_ipmb_addr *ipmb_addr; - struct ipmi_recv_msg *recv_msg; - unsigned long flags; + struct cmd_rcvr *rcvr; + int rv = 0; + unsigned char netfn; + unsigned char cmd; + ipmi_user_t user = NULL; + struct ipmi_ipmb_addr *ipmb_addr; + struct ipmi_recv_msg *recv_msg; + unsigned long flags; if (msg->rsp_size < 10) { /* Message not big enough, just ignore it. */ @@ -2023,16 +2058,14 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, netfn = msg->rsp[4] >> 2; cmd = msg->rsp[8]; - read_lock(&(intf->cmd_rcvr_lock)); - - /* Find the command/netfn. */ - list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) { - if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) { - user = rcvr->user; - break; - } - } - read_unlock(&(intf->cmd_rcvr_lock)); + spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags); + rcvr = find_cmd_rcvr(intf, netfn, cmd); + if (rcvr) { + user = rcvr->user; + kref_get(&user->refcount); + } else + user = NULL; + spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags); if (user == NULL) { /* We didn't find a user, deliver an error response. */ @@ -2079,6 +2112,7 @@ static int handle_ipmb_get_msg_cmd(ipmi_smi_t intf, message, so requeue it for handling later. */ rv = 1; + kref_put(&user->refcount, free_user); } else { /* Extract the source address from the data. */ ipmb_addr = (struct ipmi_ipmb_addr *) &recv_msg->addr; @@ -2179,14 +2213,14 @@ static int handle_lan_get_msg_rsp(ipmi_smi_t intf, static int handle_lan_get_msg_cmd(ipmi_smi_t intf, struct ipmi_smi_msg *msg) { - struct cmd_rcvr *rcvr; - int rv = 0; - unsigned char netfn; - unsigned char cmd; - ipmi_user_t user = NULL; - struct ipmi_lan_addr *lan_addr; - struct ipmi_recv_msg *recv_msg; - unsigned long flags; + struct cmd_rcvr *rcvr; + int rv = 0; + unsigned char netfn; + unsigned char cmd; + ipmi_user_t user = NULL; + struct ipmi_lan_addr *lan_addr; + struct ipmi_recv_msg *recv_msg; + unsigned long flags; if (msg->rsp_size < 12) { /* Message not big enough, just ignore it. */ @@ -2204,19 +2238,17 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf, netfn = msg->rsp[6] >> 2; cmd = msg->rsp[10]; - read_lock(&(intf->cmd_rcvr_lock)); - - /* Find the command/netfn. */ - list_for_each_entry(rcvr, &(intf->cmd_rcvrs), link) { - if ((rcvr->netfn == netfn) && (rcvr->cmd == cmd)) { - user = rcvr->user; - break; - } - } - read_unlock(&(intf->cmd_rcvr_lock)); + spin_lock_irqsave(&intf->cmd_rcvrs_lock, flags); + rcvr = find_cmd_rcvr(intf, netfn, cmd); + if (rcvr) { + user = rcvr->user; + kref_get(&user->refcount); + } else + user = NULL; + spin_unlock_irqrestore(&intf->cmd_rcvrs_lock, flags); if (user == NULL) { - /* We didn't find a user, deliver an error response. */ + /* We didn't find a user, just give up. */ spin_lock_irqsave(&intf->counter_lock, flags); intf->unhandled_commands++; spin_unlock_irqrestore(&intf->counter_lock, flags); @@ -2235,6 +2267,7 @@ static int handle_lan_get_msg_cmd(ipmi_smi_t intf, message, so requeue it for handling later. */ rv = 1; + kref_put(&user->refcount, free_user); } else { /* Extract the source address from the data. */ lan_addr = (struct ipmi_lan_addr *) &recv_msg->addr; @@ -2286,8 +2319,6 @@ static void copy_event_into_recv_msg(struct ipmi_recv_msg *recv_msg, recv_msg->msg.data_len = msg->rsp_size - 3; } -/* This will be called with the intf->users_lock read-locked, so no need - to do that here. */ static int handle_read_event_rsp(ipmi_smi_t intf, struct ipmi_smi_msg *msg) { @@ -2313,7 +2344,7 @@ static int handle_read_event_rsp(ipmi_smi_t intf, INIT_LIST_HEAD(&msgs); - spin_lock_irqsave(&(intf->events_lock), flags); + spin_lock_irqsave(&intf->events_lock, flags); spin_lock(&intf->counter_lock); intf->events++; @@ -2321,12 +2352,14 @@ static int handle_read_event_rsp(ipmi_smi_t intf, /* Allocate and fill in one message for every user that is getting events. */ - list_for_each_entry(user, &(intf->users), link) { + rcu_read_lock(); + list_for_each_entry_rcu(user, &intf->users, link) { if (! user->gets_events) continue; recv_msg = ipmi_alloc_recv_msg(); if (! recv_msg) { + rcu_read_unlock(); list_for_each_entry_safe(recv_msg, recv_msg2, &msgs, link) { list_del(&recv_msg->link); ipmi_free_recv_msg(recv_msg); @@ -2342,8 +2375,10 @@ static int handle_read_event_rsp(ipmi_smi_t intf, copy_event_into_recv_msg(recv_msg, msg); recv_msg->user = user; + kref_get(&user->refcount); list_add_tail(&(recv_msg->link), &msgs); } + rcu_read_unlock(); if (deliver_count) { /* Now deliver all the messages. */ @@ -2382,9 +2417,8 @@ static int handle_bmc_rsp(ipmi_smi_t intf, struct ipmi_smi_msg *msg) { struct ipmi_recv_msg *recv_msg; - int found = 0; - struct ipmi_user *user; unsigned long flags; + struct ipmi_user *user; recv_msg = (struct ipmi_recv_msg *) msg->user_data; if (recv_msg == NULL) @@ -2396,16 +2430,9 @@ static int handle_bmc_rsp(ipmi_smi_t intf, return 0; } + user = recv_msg->user; /* Make sure the user still exists. */ - list_for_each_entry(user, &(intf->users), link) { - if (user == recv_msg->user) { - /* Found it, so we can deliver it */ - found = 1; - break; - } - } - - if ((! found) && recv_msg->user) { + if (user && !user->valid) { /* The user for the message went away, so give up. */ spin_lock_irqsave(&intf->counter_lock, flags); intf->unhandled_local_responses++; @@ -2486,7 +2513,7 @@ static int handle_new_recv_msg(ipmi_smi_t intf, { /* It's a response to a response we sent. For this we deliver a send message response to the user. */ - struct ipmi_recv_msg *recv_msg = msg->user_data; + struct ipmi_recv_msg *recv_msg = msg->user_data; requeue = 0; if (msg->rsp_size < 2) @@ -2498,13 +2525,18 @@ static int handle_new_recv_msg(ipmi_smi_t intf, /* Invalid channel number */ goto out; - if (recv_msg) { - recv_msg->recv_type = IPMI_RESPONSE_RESPONSE_TYPE; - recv_msg->msg.data = recv_msg->msg_data; - recv_msg->msg.data_len = 1; - recv_msg->msg_data[0] = msg->rsp[2]; - deliver_response(recv_msg); - } + if (!recv_msg) + goto out; + + /* Make sure the user still exists. */ + if (!recv_msg->user || !recv_msg->user->valid) + goto out; + + recv_msg->recv_type = IPMI_RESPONSE_RESPONSE_TYPE; + recv_msg->msg.data = recv_msg->msg_data; + recv_msg->msg.data_len = 1; + recv_msg->msg_data[0] = msg->rsp[2]; + deliver_response(recv_msg); } else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2)) && (msg->rsp[1] == IPMI_GET_MSG_CMD)) { @@ -2570,14 +2602,11 @@ void ipmi_smi_msg_received(ipmi_smi_t intf, int rv; - /* Lock the user lock so the user can't go away while we are - working on it. */ - read_lock(&(intf->users_lock)); - if ((msg->data_size >= 2) && (msg->data[0] == (IPMI_NETFN_APP_REQUEST << 2)) && (msg->data[1] == IPMI_SEND_MSG_CMD) - && (msg->user_data == NULL)) { + && (msg->user_data == NULL)) + { /* This is the local response to a command send, start the timer for these. The user_data will not be NULL if this is a response send, and we will let @@ -2612,46 +2641,46 @@ void ipmi_smi_msg_received(ipmi_smi_t intf, } ipmi_free_smi_msg(msg); - goto out_unlock; + goto out; } /* To preserve message order, if the list is not empty, we tack this message onto the end of the list. */ - spin_lock_irqsave(&(intf->waiting_msgs_lock), flags); - if (!list_empty(&(intf->waiting_msgs))) { - list_add_tail(&(msg->link), &(intf->waiting_msgs)); - spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags); - goto out_unlock; + spin_lock_irqsave(&intf->waiting_msgs_lock, flags); + if (!list_empty(&intf->waiting_msgs)) { + list_add_tail(&msg->link, &intf->waiting_msgs); + spin_unlock(&intf->waiting_msgs_lock); + goto out; } - spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags); + spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags); rv = handle_new_recv_msg(intf, msg); if (rv > 0) { /* Could not handle the message now, just add it to a list to handle later. */ - spin_lock_irqsave(&(intf->waiting_msgs_lock), flags); - list_add_tail(&(msg->link), &(intf->waiting_msgs)); - spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags); + spin_lock(&intf->waiting_msgs_lock); + list_add_tail(&msg->link, &intf->waiting_msgs); + spin_unlock(&intf->waiting_msgs_lock); } else if (rv == 0) { ipmi_free_smi_msg(msg); } - out_unlock: - read_unlock(&(intf->users_lock)); + out: + return; } void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf) { ipmi_user_t user; - read_lock(&(intf->users_lock)); - list_for_each_entry(user, &(intf->users), link) { + rcu_read_lock(); + list_for_each_entry_rcu(user, &intf->users, link) { if (! user->handler->ipmi_watchdog_pretimeout) continue; user->handler->ipmi_watchdog_pretimeout(user->handler_data); } - read_unlock(&(intf->users_lock)); + rcu_read_unlock(); } static void @@ -2691,8 +2720,65 @@ smi_from_recv_msg(ipmi_smi_t intf, struct ipmi_recv_msg *recv_msg, return smi_msg; } -static void -ipmi_timeout_handler(long timeout_period) +static void check_msg_timeout(ipmi_smi_t intf, struct seq_table *ent, + struct list_head *timeouts, long timeout_period, + int slot, unsigned long *flags) +{ + struct ipmi_recv_msg *msg; + + if (!ent->inuse) + return; + + ent->timeout -= timeout_period; + if (ent->timeout > 0) + return; + + if (ent->retries_left == 0) { + /* The message has used all its retries. */ + ent->inuse = 0; + msg = ent->recv_msg; + list_add_tail(&msg->link, timeouts); + spin_lock(&intf->counter_lock); + if (ent->broadcast) + intf->timed_out_ipmb_broadcasts++; + else if (ent->recv_msg->addr.addr_type == IPMI_LAN_ADDR_TYPE) + intf->timed_out_lan_commands++; + else + intf->timed_out_ipmb_commands++; + spin_unlock(&intf->counter_lock); + } else { + struct ipmi_smi_msg *smi_msg; + /* More retries, send again. */ + + /* Start with the max timer, set to normal + timer after the message is sent. */ + ent->timeout = MAX_MSG_TIMEOUT; + ent->retries_left--; + spin_lock(&intf->counter_lock); + if (ent->recv_msg->addr.addr_type == IPMI_LAN_ADDR_TYPE) + intf->retransmitted_lan_commands++; + else + intf->retransmitted_ipmb_commands++; + spin_unlock(&intf->counter_lock); + + smi_msg = smi_from_recv_msg(intf, ent->recv_msg, slot, + ent->seqid); + if (! smi_msg) + return; + + spin_unlock_irqrestore(&intf->seq_lock, *flags); + /* Send the new message. We send with a zero + * priority. It timed out, I doubt time is + * that critical now, and high priority + * messages are really only for messages to the + * local MC, which don't get resent. */ + intf->handlers->sender(intf->send_info, + smi_msg, 0); + spin_lock_irqsave(&intf->seq_lock, *flags); + } +} + +static void ipmi_timeout_handler(long timeout_period) { ipmi_smi_t intf; struct list_head timeouts; @@ -2706,14 +2792,14 @@ ipmi_timeout_handler(long timeout_period) spin_lock(&interfaces_lock); for (i = 0; i < MAX_IPMI_INTERFACES; i++) { intf = ipmi_interfaces[i]; - if (intf == NULL) + if (IPMI_INVALID_INTERFACE(intf)) continue; - - read_lock(&(intf->users_lock)); + kref_get(&intf->refcount); + spin_unlock(&interfaces_lock); /* See if any waiting messages need to be processed. */ - spin_lock_irqsave(&(intf->waiting_msgs_lock), flags); - list_for_each_entry_safe(smi_msg, smi_msg2, &(intf->waiting_msgs), link) { + spin_lock_irqsave(&intf->waiting_msgs_lock, flags); + list_for_each_entry_safe(smi_msg, smi_msg2, &intf->waiting_msgs, link) { if (! handle_new_recv_msg(intf, smi_msg)) { list_del(&smi_msg->link); ipmi_free_smi_msg(smi_msg); @@ -2723,73 +2809,23 @@ ipmi_timeout_handler(long timeout_period) break; } } - spin_unlock_irqrestore(&(intf->waiting_msgs_lock), flags); + spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags); /* Go through the seq table and find any messages that have timed out, putting them in the timeouts list. */ - spin_lock_irqsave(&(intf->seq_lock), flags); - for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) { - struct seq_table *ent = &(intf->seq_table[j]); - if (!ent->inuse) - continue; - - ent->timeout -= timeout_period; - if (ent->timeout > 0) - continue; - - if (ent->retries_left == 0) { - /* The message has used all its retries. */ - ent->inuse = 0; - msg = ent->recv_msg; - list_add_tail(&(msg->link), &timeouts); - spin_lock(&intf->counter_lock); - if (ent->broadcast) - intf->timed_out_ipmb_broadcasts++; - else if (ent->recv_msg->addr.addr_type - == IPMI_LAN_ADDR_TYPE) - intf->timed_out_lan_commands++; - else - intf->timed_out_ipmb_commands++; - spin_unlock(&intf->counter_lock); - } else { - struct ipmi_smi_msg *smi_msg; - /* More retries, send again. */ - - /* Start with the max timer, set to normal - timer after the message is sent. */ - ent->timeout = MAX_MSG_TIMEOUT; - ent->retries_left--; - spin_lock(&intf->counter_lock); - if (ent->recv_msg->addr.addr_type - == IPMI_LAN_ADDR_TYPE) - intf->retransmitted_lan_commands++; - else - intf->retransmitted_ipmb_commands++; - spin_unlock(&intf->counter_lock); - smi_msg = smi_from_recv_msg(intf, - ent->recv_msg, j, ent->seqid); - if (! smi_msg) - continue; - - spin_unlock_irqrestore(&(intf->seq_lock),flags); - /* Send the new message. We send with a zero - * priority. It timed out, I doubt time is - * that critical now, and high priority - * messages are really only for messages to the - * local MC, which don't get resent. */ - intf->handlers->sender(intf->send_info, - smi_msg, 0); - spin_lock_irqsave(&(intf->seq_lock), flags); - } - } - spin_unlock_irqrestore(&(intf->seq_lock), flags); - - list_for_each_entry_safe(msg, msg2, &timeouts, link) { + spin_lock_irqsave(&intf->seq_lock, flags); + for (j = 0; j < IPMI_IPMB_NUM_SEQ; j++) + check_msg_timeout(intf, &(intf->seq_table[j]), + &timeouts, timeout_period, j, + &flags); + spin_unlock_irqrestore(&intf->seq_lock, flags); + + list_for_each_entry_safe(msg, msg2, &timeouts, link) handle_msg_timeout(msg); - } - read_unlock(&(intf->users_lock)); + kref_put(&intf->refcount, intf_free); + spin_lock(&interfaces_lock); } spin_unlock(&interfaces_lock); } @@ -2802,7 +2838,7 @@ static void ipmi_request_event(void) spin_lock(&interfaces_lock); for (i = 0; i < MAX_IPMI_INTERFACES; i++) { intf = ipmi_interfaces[i]; - if (intf == NULL) + if (IPMI_INVALID_INTERFACE(intf)) continue; intf->handlers->request_events(intf->send_info); @@ -2884,6 +2920,13 @@ struct ipmi_recv_msg *ipmi_alloc_recv_msg(void) return rv; } +void ipmi_free_recv_msg(struct ipmi_recv_msg *msg) +{ + if (msg->user) + kref_put(&msg->user->refcount, free_user); + msg->done(msg); +} + #ifdef CONFIG_IPMI_PANIC_EVENT static void dummy_smi_done_handler(struct ipmi_smi_msg *msg) @@ -2964,7 +3007,7 @@ static void send_panic_events(char *str) /* For every registered interface, send the event. */ for (i = 0; i < MAX_IPMI_INTERFACES; i++) { intf = ipmi_interfaces[i]; - if (intf == NULL) + if (IPMI_INVALID_INTERFACE(intf)) continue; /* Send the event announcing the panic. */ @@ -2995,7 +3038,7 @@ static void send_panic_events(char *str) int j; intf = ipmi_interfaces[i]; - if (intf == NULL) + if (IPMI_INVALID_INTERFACE(intf)) continue; /* First job here is to figure out where to send the @@ -3131,7 +3174,7 @@ static int panic_event(struct notifier_block *this, /* For every registered interface, set it to run to completion. */ for (i = 0; i < MAX_IPMI_INTERFACES; i++) { intf = ipmi_interfaces[i]; - if (intf == NULL) + if (IPMI_INVALID_INTERFACE(intf)) continue; intf->handlers->set_run_to_completion(intf->send_info, 1); @@ -3160,9 +3203,8 @@ static int ipmi_init_msghandler(void) printk(KERN_INFO "ipmi message handler version " IPMI_DRIVER_VERSION "\n"); - for (i = 0; i < MAX_IPMI_INTERFACES; i++) { + for (i = 0; i < MAX_IPMI_INTERFACES; i++) ipmi_interfaces[i] = NULL; - } #ifdef CONFIG_PROC_FS proc_ipmi_root = proc_mkdir("ipmi", NULL); @@ -3258,3 +3300,4 @@ EXPORT_SYMBOL(ipmi_get_my_LUN); EXPORT_SYMBOL(ipmi_smi_add_proc_entry); EXPORT_SYMBOL(proc_ipmi_root); EXPORT_SYMBOL(ipmi_user_set_run_to_completion); +EXPORT_SYMBOL(ipmi_free_recv_msg); diff --git a/include/linux/ipmi.h b/include/linux/ipmi.h index 938d55b813a5..d6276e60b3bf 100644 --- a/include/linux/ipmi.h +++ b/include/linux/ipmi.h @@ -256,10 +256,7 @@ struct ipmi_recv_msg }; /* Allocate and free the receive message. */ -static inline void ipmi_free_recv_msg(struct ipmi_recv_msg *msg) -{ - msg->done(msg); -} +void ipmi_free_recv_msg(struct ipmi_recv_msg *msg); struct ipmi_user_hndl { -- cgit v1.2.3 From e65845235c8120be63001fc1a4ac00c819194bbe Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Mon, 7 Nov 2005 01:00:07 -0800 Subject: [PATCH] Kprobes: Track kprobe on a per_cpu basis - base changes Changes to the base kprobe infrastructure to track kprobe execution on a per-cpu basis. Signed-off-by: Ananth N Mavinakayanahalli Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/kprobes.h | 31 ++++++++++++++++++++++--------- kernel/kprobes.c | 43 ++++++++++++++++++++++++++++--------------- 2 files changed, 50 insertions(+), 24 deletions(-) (limited to 'include/linux') diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index e30afdca7917..6720305a31e8 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -33,6 +33,7 @@ #include #include #include +#include #include @@ -106,6 +107,9 @@ struct jprobe { kprobe_opcode_t *entry; /* probe handling code to jump to */ }; +DECLARE_PER_CPU(struct kprobe *, current_kprobe); +DECLARE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); + #ifdef ARCH_SUPPORTS_KRETPROBES extern void arch_prepare_kretprobe(struct kretprobe *rp, struct pt_regs *regs); #else /* ARCH_SUPPORTS_KRETPROBES */ @@ -146,13 +150,6 @@ struct kretprobe_instance { void lock_kprobes(void); void unlock_kprobes(void); -/* kprobe running now on this CPU? */ -static inline int kprobe_running(void) -{ - extern unsigned int kprobe_cpu; - return kprobe_cpu == smp_processor_id(); -} - extern int arch_prepare_kprobe(struct kprobe *p); extern void arch_copy_kprobe(struct kprobe *p); extern void arch_arm_kprobe(struct kprobe *p); @@ -167,6 +164,22 @@ extern void free_insn_slot(kprobe_opcode_t *slot); struct kprobe *get_kprobe(void *addr); struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk); +/* kprobe_running() will just return the current_kprobe on this CPU */ +static inline struct kprobe *kprobe_running(void) +{ + return (__get_cpu_var(current_kprobe)); +} + +static inline void reset_current_kprobe(void) +{ + __get_cpu_var(current_kprobe) = NULL; +} + +static inline struct kprobe_ctlblk *get_kprobe_ctlblk(void) +{ + return (&__get_cpu_var(kprobe_ctlblk)); +} + int register_kprobe(struct kprobe *p); void unregister_kprobe(struct kprobe *p); int setjmp_pre_handler(struct kprobe *, struct pt_regs *); @@ -183,9 +196,9 @@ void add_rp_inst(struct kretprobe_instance *ri); void kprobe_flush_task(struct task_struct *tk); void recycle_rp_inst(struct kretprobe_instance *ri); #else /* CONFIG_KPROBES */ -static inline int kprobe_running(void) +static inline struct kprobe *kprobe_running(void) { - return 0; + return NULL; } static inline int register_kprobe(struct kprobe *p) { diff --git a/kernel/kprobes.c b/kernel/kprobes.c index ce4915dd683a..6da8f9b33d1e 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -51,7 +51,7 @@ static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE]; unsigned int kprobe_cpu = NR_CPUS; static DEFINE_SPINLOCK(kprobe_lock); -static struct kprobe *curr_kprobe; +static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL; /* * kprobe->ainsn.insn points to the copy of the instruction to be @@ -188,6 +188,17 @@ void __kprobes unlock_kprobes(void) local_irq_restore(flags); } +/* We have preemption disabled.. so it is safe to use __ versions */ +static inline void set_kprobe_instance(struct kprobe *kp) +{ + __get_cpu_var(kprobe_instance) = kp; +} + +static inline void reset_kprobe_instance(void) +{ + __get_cpu_var(kprobe_instance) = NULL; +} + /* You have to be holding the kprobe_lock */ struct kprobe __kprobes *get_kprobe(void *addr) { @@ -213,11 +224,11 @@ static int __kprobes aggr_pre_handler(struct kprobe *p, struct pt_regs *regs) list_for_each_entry(kp, &p->list, list) { if (kp->pre_handler) { - curr_kprobe = kp; + set_kprobe_instance(kp); if (kp->pre_handler(kp, regs)) return 1; } - curr_kprobe = NULL; + reset_kprobe_instance(); } return 0; } @@ -229,9 +240,9 @@ static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs, list_for_each_entry(kp, &p->list, list) { if (kp->post_handler) { - curr_kprobe = kp; + set_kprobe_instance(kp); kp->post_handler(kp, regs, flags); - curr_kprobe = NULL; + reset_kprobe_instance(); } } return; @@ -240,12 +251,14 @@ static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs, static int __kprobes aggr_fault_handler(struct kprobe *p, struct pt_regs *regs, int trapnr) { + struct kprobe *cur = __get_cpu_var(kprobe_instance); + /* * if we faulted "during" the execution of a user specified * probe handler, invoke just that probe's fault handler */ - if (curr_kprobe && curr_kprobe->fault_handler) { - if (curr_kprobe->fault_handler(curr_kprobe, regs, trapnr)) + if (cur && cur->fault_handler) { + if (cur->fault_handler(cur, regs, trapnr)) return 1; } return 0; @@ -253,15 +266,15 @@ static int __kprobes aggr_fault_handler(struct kprobe *p, struct pt_regs *regs, static int __kprobes aggr_break_handler(struct kprobe *p, struct pt_regs *regs) { - struct kprobe *kp = curr_kprobe; - if (curr_kprobe && kp->break_handler) { - if (kp->break_handler(kp, regs)) { - curr_kprobe = NULL; - return 1; - } + struct kprobe *cur = __get_cpu_var(kprobe_instance); + int ret = 0; + + if (cur && cur->break_handler) { + if (cur->break_handler(cur, regs)) + ret = 1; } - curr_kprobe = NULL; - return 0; + reset_kprobe_instance(); + return ret; } struct kretprobe_instance __kprobes *get_free_rp_inst(struct kretprobe *rp) -- cgit v1.2.3 From 3516a46042508a495fac13c2e73530d936ebe015 Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Mon, 7 Nov 2005 01:00:13 -0800 Subject: [PATCH] Kprobes: Use RCU for (un)register synchronization - base changes Changes to the base kprobes infrastructure to use RCU for synchronization during kprobe registration and unregistration. These changes coupled with the arch kprobe changes (next in series): a. serialize registration and unregistration of kprobes. b. enable lockless execution of handlers. Handlers can now run in parallel. Signed-off-by: Ananth N Mavinakayanahalli Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/kprobes.h | 9 ++--- kernel/kprobes.c | 103 ++++++++++++++++++++---------------------------- 2 files changed, 46 insertions(+), 66 deletions(-) (limited to 'include/linux') diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index 6720305a31e8..cff281cf70cf 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -34,6 +34,8 @@ #include #include #include +#include +#include #include @@ -146,10 +148,7 @@ struct kretprobe_instance { }; #ifdef CONFIG_KPROBES -/* Locks kprobe: irq must be disabled */ -void lock_kprobes(void); -void unlock_kprobes(void); - +extern spinlock_t kretprobe_lock; extern int arch_prepare_kprobe(struct kprobe *p); extern void arch_copy_kprobe(struct kprobe *p); extern void arch_arm_kprobe(struct kprobe *p); @@ -160,7 +159,7 @@ extern void show_registers(struct pt_regs *regs); extern kprobe_opcode_t *get_insn_slot(void); extern void free_insn_slot(kprobe_opcode_t *slot); -/* Get the kprobe at this addr (if any). Must have called lock_kprobes */ +/* Get the kprobe at this addr (if any) - called under a rcu_read_lock() */ struct kprobe *get_kprobe(void *addr); struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk); diff --git a/kernel/kprobes.c b/kernel/kprobes.c index 6da8f9b33d1e..cfef426e4cdc 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -32,7 +32,6 @@ * added function-return probes. */ #include -#include #include #include #include @@ -49,8 +48,8 @@ static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE]; static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE]; -unsigned int kprobe_cpu = NR_CPUS; -static DEFINE_SPINLOCK(kprobe_lock); +static DEFINE_SPINLOCK(kprobe_lock); /* Protects kprobe_table */ +DEFINE_SPINLOCK(kretprobe_lock); /* Protects kretprobe_inst_table */ static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL; /* @@ -153,41 +152,6 @@ void __kprobes free_insn_slot(kprobe_opcode_t *slot) } } -/* Locks kprobe: irqs must be disabled */ -void __kprobes lock_kprobes(void) -{ - unsigned long flags = 0; - - /* Avoiding local interrupts to happen right after we take the kprobe_lock - * and before we get a chance to update kprobe_cpu, this to prevent - * deadlock when we have a kprobe on ISR routine and a kprobe on task - * routine - */ - local_irq_save(flags); - - spin_lock(&kprobe_lock); - kprobe_cpu = smp_processor_id(); - - local_irq_restore(flags); -} - -void __kprobes unlock_kprobes(void) -{ - unsigned long flags = 0; - - /* Avoiding local interrupts to happen right after we update - * kprobe_cpu and before we get a a chance to release kprobe_lock, - * this to prevent deadlock when we have a kprobe on ISR routine and - * a kprobe on task routine - */ - local_irq_save(flags); - - kprobe_cpu = NR_CPUS; - spin_unlock(&kprobe_lock); - - local_irq_restore(flags); -} - /* We have preemption disabled.. so it is safe to use __ versions */ static inline void set_kprobe_instance(struct kprobe *kp) { @@ -199,15 +163,20 @@ static inline void reset_kprobe_instance(void) __get_cpu_var(kprobe_instance) = NULL; } -/* You have to be holding the kprobe_lock */ +/* + * This routine is called either: + * - under the kprobe_lock spinlock - during kprobe_[un]register() + * OR + * - under an rcu_read_lock() - from arch/xxx/kernel/kprobes.c + */ struct kprobe __kprobes *get_kprobe(void *addr) { struct hlist_head *head; struct hlist_node *node; + struct kprobe *p; head = &kprobe_table[hash_ptr(addr, KPROBE_HASH_BITS)]; - hlist_for_each(node, head) { - struct kprobe *p = hlist_entry(node, struct kprobe, hlist); + hlist_for_each_entry_rcu(p, node, head, hlist) { if (p->addr == addr) return p; } @@ -222,7 +191,7 @@ static int __kprobes aggr_pre_handler(struct kprobe *p, struct pt_regs *regs) { struct kprobe *kp; - list_for_each_entry(kp, &p->list, list) { + list_for_each_entry_rcu(kp, &p->list, list) { if (kp->pre_handler) { set_kprobe_instance(kp); if (kp->pre_handler(kp, regs)) @@ -238,7 +207,7 @@ static void __kprobes aggr_post_handler(struct kprobe *p, struct pt_regs *regs, { struct kprobe *kp; - list_for_each_entry(kp, &p->list, list) { + list_for_each_entry_rcu(kp, &p->list, list) { if (kp->post_handler) { set_kprobe_instance(kp); kp->post_handler(kp, regs, flags); @@ -277,6 +246,7 @@ static int __kprobes aggr_break_handler(struct kprobe *p, struct pt_regs *regs) return ret; } +/* Called with kretprobe_lock held */ struct kretprobe_instance __kprobes *get_free_rp_inst(struct kretprobe *rp) { struct hlist_node *node; @@ -286,6 +256,7 @@ struct kretprobe_instance __kprobes *get_free_rp_inst(struct kretprobe *rp) return NULL; } +/* Called with kretprobe_lock held */ static struct kretprobe_instance __kprobes *get_used_rp_inst(struct kretprobe *rp) { @@ -296,6 +267,7 @@ static struct kretprobe_instance __kprobes *get_used_rp_inst(struct kretprobe return NULL; } +/* Called with kretprobe_lock held */ void __kprobes add_rp_inst(struct kretprobe_instance *ri) { /* @@ -314,6 +286,7 @@ void __kprobes add_rp_inst(struct kretprobe_instance *ri) hlist_add_head(&ri->uflist, &ri->rp->used_instances); } +/* Called with kretprobe_lock held */ void __kprobes recycle_rp_inst(struct kretprobe_instance *ri) { /* remove rp inst off the rprobe_inst_table */ @@ -347,13 +320,13 @@ void __kprobes kprobe_flush_task(struct task_struct *tk) struct hlist_node *node, *tmp; unsigned long flags = 0; - spin_lock_irqsave(&kprobe_lock, flags); + spin_lock_irqsave(&kretprobe_lock, flags); head = kretprobe_inst_table_head(current); hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { if (ri->task == tk) recycle_rp_inst(ri); } - spin_unlock_irqrestore(&kprobe_lock, flags); + spin_unlock_irqrestore(&kretprobe_lock, flags); } /* @@ -364,9 +337,12 @@ static int __kprobes pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs) { struct kretprobe *rp = container_of(p, struct kretprobe, kp); + unsigned long flags = 0; /*TODO: consider to only swap the RA after the last pre_handler fired */ + spin_lock_irqsave(&kretprobe_lock, flags); arch_prepare_kretprobe(rp, regs); + spin_unlock_irqrestore(&kretprobe_lock, flags); return 0; } @@ -397,13 +373,13 @@ static int __kprobes add_new_kprobe(struct kprobe *old_p, struct kprobe *p) struct kprobe *kp; if (p->break_handler) { - list_for_each_entry(kp, &old_p->list, list) { + list_for_each_entry_rcu(kp, &old_p->list, list) { if (kp->break_handler) return -EEXIST; } - list_add_tail(&p->list, &old_p->list); + list_add_tail_rcu(&p->list, &old_p->list); } else - list_add(&p->list, &old_p->list); + list_add_rcu(&p->list, &old_p->list); return 0; } @@ -421,18 +397,18 @@ static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p) ap->break_handler = aggr_break_handler; INIT_LIST_HEAD(&ap->list); - list_add(&p->list, &ap->list); + list_add_rcu(&p->list, &ap->list); INIT_HLIST_NODE(&ap->hlist); - hlist_del(&p->hlist); - hlist_add_head(&ap->hlist, + hlist_del_rcu(&p->hlist); + hlist_add_head_rcu(&ap->hlist, &kprobe_table[hash_ptr(ap->addr, KPROBE_HASH_BITS)]); } /* * This is the second or subsequent kprobe at the address - handle * the intricacies - * TODO: Move kcalloc outside the spinlock + * TODO: Move kcalloc outside the spin_lock */ static int __kprobes register_aggr_kprobe(struct kprobe *old_p, struct kprobe *p) @@ -458,7 +434,7 @@ static int __kprobes register_aggr_kprobe(struct kprobe *old_p, static inline void cleanup_kprobe(struct kprobe *p, unsigned long flags) { arch_disarm_kprobe(p); - hlist_del(&p->hlist); + hlist_del_rcu(&p->hlist); spin_unlock_irqrestore(&kprobe_lock, flags); arch_remove_kprobe(p); } @@ -466,11 +442,10 @@ static inline void cleanup_kprobe(struct kprobe *p, unsigned long flags) static inline void cleanup_aggr_kprobe(struct kprobe *old_p, struct kprobe *p, unsigned long flags) { - list_del(&p->list); - if (list_empty(&old_p->list)) { + list_del_rcu(&p->list); + if (list_empty(&old_p->list)) cleanup_kprobe(old_p, flags); - kfree(old_p); - } else + else spin_unlock_irqrestore(&kprobe_lock, flags); } @@ -493,9 +468,9 @@ int __kprobes register_kprobe(struct kprobe *p) if ((ret = arch_prepare_kprobe(p)) != 0) goto rm_kprobe; + p->nmissed = 0; spin_lock_irqsave(&kprobe_lock, flags); old_p = get_kprobe(p->addr); - p->nmissed = 0; if (old_p) { ret = register_aggr_kprobe(old_p, p); goto out; @@ -503,7 +478,7 @@ int __kprobes register_kprobe(struct kprobe *p) arch_copy_kprobe(p); INIT_HLIST_NODE(&p->hlist); - hlist_add_head(&p->hlist, + hlist_add_head_rcu(&p->hlist, &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]); arch_arm_kprobe(p); @@ -524,10 +499,16 @@ void __kprobes unregister_kprobe(struct kprobe *p) spin_lock_irqsave(&kprobe_lock, flags); old_p = get_kprobe(p->addr); if (old_p) { + /* cleanup_*_kprobe() does the spin_unlock_irqrestore */ if (old_p->pre_handler == aggr_pre_handler) cleanup_aggr_kprobe(old_p, p, flags); else cleanup_kprobe(p, flags); + + synchronize_sched(); + if (old_p->pre_handler == aggr_pre_handler && + list_empty(&old_p->list)) + kfree(old_p); } else spin_unlock_irqrestore(&kprobe_lock, flags); } @@ -604,13 +585,13 @@ void __kprobes unregister_kretprobe(struct kretprobe *rp) unregister_kprobe(&rp->kp); /* No race here */ - spin_lock_irqsave(&kprobe_lock, flags); + spin_lock_irqsave(&kretprobe_lock, flags); free_rp_inst(rp); while ((ri = get_used_rp_inst(rp)) != NULL) { ri->rp = NULL; hlist_del(&ri->uflist); } - spin_unlock_irqrestore(&kprobe_lock, flags); + spin_unlock_irqrestore(&kretprobe_lock, flags); } static int __init init_kprobes(void) -- cgit v1.2.3 From d217d5450f11d8c907c0458d175b0dc999b4d06d Mon Sep 17 00:00:00 2001 From: Ananth N Mavinakayanahalli Date: Mon, 7 Nov 2005 01:00:14 -0800 Subject: [PATCH] Kprobes: preempt_disable/enable() simplification Reorganize the preempt_disable/enable calls to eliminate the extra preempt depth. Changes based on Paul McKenney's review suggestions for the kprobes RCU changeset. Signed-off-by: Ananth N Mavinakayanahalli Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/kprobes.c | 25 +++++++++++++++---------- arch/ia64/kernel/kprobes.c | 37 ++++++++++++++++++++----------------- arch/ppc64/kernel/kprobes.c | 25 +++++++++++++++---------- arch/sparc64/kernel/kprobes.c | 21 +++++++++++++-------- arch/x86_64/kernel/kprobes.c | 29 +++++++++++++++-------------- include/linux/kprobes.h | 2 +- kernel/kprobes.c | 2 +- 7 files changed, 80 insertions(+), 61 deletions(-) (limited to 'include/linux') diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c index ad469299267a..32b0c24ab9a6 100644 --- a/arch/i386/kernel/kprobes.c +++ b/arch/i386/kernel/kprobes.c @@ -153,7 +153,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) int ret = 0; kprobe_opcode_t *addr = NULL; unsigned long *lp; - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + struct kprobe_ctlblk *kcb; + + /* + * We don't want to be preempted for the entire + * duration of kprobe processing + */ + preempt_disable(); + kcb = get_kprobe_ctlblk(); /* Check if the application is using LDT entry for its code segment and * calculate the address by reading the base address from the LDT entry. @@ -221,11 +228,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) goto no_kprobe; } - /* - * This preempt_disable() matches the preempt_enable_no_resched() - * in post_kprobe_handler() - */ - preempt_disable(); set_current_kprobe(p, regs, kcb); kcb->kprobe_status = KPROBE_HIT_ACTIVE; @@ -239,6 +241,7 @@ ss_probe: return 1; no_kprobe: + preempt_enable_no_resched(); return ret; } @@ -310,8 +313,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) /* * By returning a non-zero value, we are telling - * kprobe_handler() that we have handled unlocking - * and re-enabling preemption + * kprobe_handler() that we don't want the post_handler + * to run (and have re-enabled preemption) */ return 1; } @@ -455,7 +458,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; - rcu_read_lock(); switch (val) { case DIE_INT3: if (kprobe_handler(args->regs)) @@ -467,14 +469,16 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, break; case DIE_GPF: case DIE_PAGE_FAULT: + /* kprobe_running() needs smp_processor_id() */ + preempt_disable(); if (kprobe_running() && kprobe_fault_handler(args->regs, args->trapnr)) ret = NOTIFY_STOP; + preempt_enable(); break; default: break; } - rcu_read_unlock(); return ret; } @@ -537,6 +541,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) *regs = kcb->jprobe_saved_regs; memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack, MIN_STACK_SIZE(stack_addr)); + preempt_enable_no_resched(); return 1; } return 0; diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index fddbac32d44a..96736a119c91 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c @@ -389,11 +389,11 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) spin_unlock_irqrestore(&kretprobe_lock, flags); preempt_enable_no_resched(); - /* - * By returning a non-zero value, we are telling - * kprobe_handler() that we have handled unlocking - * and re-enabling preemption - */ + /* + * By returning a non-zero value, we are telling + * kprobe_handler() that we don't want the post_handler + * to run (and have re-enabled preemption) + */ return 1; } @@ -604,7 +604,14 @@ static int __kprobes pre_kprobes_handler(struct die_args *args) int ret = 0; struct pt_regs *regs = args->regs; kprobe_opcode_t *addr = (kprobe_opcode_t *)instruction_pointer(regs); - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + struct kprobe_ctlblk *kcb; + + /* + * We don't want to be preempted for the entire + * duration of kprobe processing + */ + preempt_disable(); + kcb = get_kprobe_ctlblk(); /* Handle recursion cases */ if (kprobe_running()) { @@ -659,11 +666,6 @@ static int __kprobes pre_kprobes_handler(struct die_args *args) goto no_kprobe; } - /* - * This preempt_disable() matches the preempt_enable_no_resched() - * in post_kprobes_handler() - */ - preempt_disable(); set_current_kprobe(p, kcb); kcb->kprobe_status = KPROBE_HIT_ACTIVE; @@ -681,6 +683,7 @@ ss_probe: return 1; no_kprobe: + preempt_enable_no_resched(); return ret; } @@ -716,9 +719,6 @@ static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr) struct kprobe *cur = kprobe_running(); struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); - if (!cur) - return 0; - if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) return 1; @@ -737,7 +737,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; - rcu_read_lock(); switch(val) { case DIE_BREAK: if (pre_kprobes_handler(args)) @@ -748,12 +747,15 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, ret = NOTIFY_STOP; break; case DIE_PAGE_FAULT: - if (kprobes_fault_handler(args->regs, args->trapnr)) + /* kprobe_running() needs smp_processor_id() */ + preempt_disable(); + if (kprobe_running() && + kprobes_fault_handler(args->regs, args->trapnr)) ret = NOTIFY_STOP; + preempt_enable(); default: break; } - rcu_read_unlock(); return ret; } @@ -785,6 +787,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); *regs = kcb->jprobe_saved_regs; + preempt_enable_no_resched(); return 1; } diff --git a/arch/ppc64/kernel/kprobes.c b/arch/ppc64/kernel/kprobes.c index e0a25b35437f..511af54e6230 100644 --- a/arch/ppc64/kernel/kprobes.c +++ b/arch/ppc64/kernel/kprobes.c @@ -148,7 +148,14 @@ static inline int kprobe_handler(struct pt_regs *regs) struct kprobe *p; int ret = 0; unsigned int *addr = (unsigned int *)regs->nip; - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + struct kprobe_ctlblk *kcb; + + /* + * We don't want to be preempted for the entire + * duration of kprobe processing + */ + preempt_disable(); + kcb = get_kprobe_ctlblk(); /* Check we're not actually recursing */ if (kprobe_running()) { @@ -207,11 +214,6 @@ static inline int kprobe_handler(struct pt_regs *regs) goto no_kprobe; } - /* - * This preempt_disable() matches the preempt_enable_no_resched() - * in post_kprobe_handler(). - */ - preempt_disable(); kcb->kprobe_status = KPROBE_HIT_ACTIVE; set_current_kprobe(p, regs, kcb); if (p->pre_handler && p->pre_handler(p, regs)) @@ -224,6 +226,7 @@ ss_probe: return 1; no_kprobe: + preempt_enable_no_resched(); return ret; } @@ -296,8 +299,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) /* * By returning a non-zero value, we are telling - * kprobe_handler() that we have handled unlocking - * and re-enabling preemption. + * kprobe_handler() that we don't want the post_handler + * to run (and have re-enabled preemption) */ return 1; } @@ -385,7 +388,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; - rcu_read_lock(); switch (val) { case DIE_BPT: if (kprobe_handler(args->regs)) @@ -396,14 +398,16 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, ret = NOTIFY_STOP; break; case DIE_PAGE_FAULT: + /* kprobe_running() needs smp_processor_id() */ + preempt_disable(); if (kprobe_running() && kprobe_fault_handler(args->regs, args->trapnr)) ret = NOTIFY_STOP; + preempt_enable(); break; default: break; } - rcu_read_unlock(); return ret; } @@ -440,6 +444,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) * saved regs... */ memcpy(regs, &kcb->jprobe_saved_regs, sizeof(struct pt_regs)); + preempt_enable_no_resched(); return 1; } diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c index 58a815e90373..96bd09b098f4 100644 --- a/arch/sparc64/kernel/kprobes.c +++ b/arch/sparc64/kernel/kprobes.c @@ -113,7 +113,14 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) struct kprobe *p; void *addr = (void *) regs->tpc; int ret = 0; - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + struct kprobe_ctlblk *kcb; + + /* + * We don't want to be preempted for the entire + * duration of kprobe processing + */ + preempt_disable(); + kcb = get_kprobe_ctlblk(); if (kprobe_running()) { p = get_kprobe(addr); @@ -159,11 +166,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) goto no_kprobe; } - /* - * This preempt_disable() matches the preempt_enable_no_resched() - * in post_kprobes_handler() - */ - preempt_disable(); set_current_kprobe(p, regs, kcb); kcb->kprobe_status = KPROBE_HIT_ACTIVE; if (p->pre_handler && p->pre_handler(p, regs)) @@ -175,6 +177,7 @@ ss_probe: return 1; no_kprobe: + preempt_enable_no_resched(); return ret; } @@ -321,7 +324,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; - rcu_read_lock(); switch (val) { case DIE_DEBUG: if (kprobe_handler(args->regs)) @@ -333,14 +335,16 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, break; case DIE_GPF: case DIE_PAGE_FAULT: + /* kprobe_running() needs smp_processor_id() */ + preempt_disable(); if (kprobe_running() && kprobe_fault_handler(args->regs, args->trapnr)) ret = NOTIFY_STOP; + preempt_enable(); break; default: break; } - rcu_read_unlock(); return ret; } @@ -426,6 +430,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) &(kcb->jprobe_saved_stack), sizeof(kcb->jprobe_saved_stack)); + preempt_enable_no_resched(); return 1; } return 0; diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c index 9bef2c8dc12c..dddeb678b440 100644 --- a/arch/x86_64/kernel/kprobes.c +++ b/arch/x86_64/kernel/kprobes.c @@ -286,16 +286,19 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe *rp, } } -/* - * Interrupts are disabled on entry as trap3 is an interrupt gate and they - * remain disabled thorough out this function. - */ int __kprobes kprobe_handler(struct pt_regs *regs) { struct kprobe *p; int ret = 0; kprobe_opcode_t *addr = (kprobe_opcode_t *)(regs->rip - sizeof(kprobe_opcode_t)); - struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); + struct kprobe_ctlblk *kcb; + + /* + * We don't want to be preempted for the entire + * duration of kprobe processing + */ + preempt_disable(); + kcb = get_kprobe_ctlblk(); /* Check we're not actually recursing */ if (kprobe_running()) { @@ -359,11 +362,6 @@ int __kprobes kprobe_handler(struct pt_regs *regs) goto no_kprobe; } - /* - * This preempt_disable() matches the preempt_enable_no_resched() - * in post_kprobe_handler() - */ - preempt_disable(); set_current_kprobe(p, regs, kcb); kcb->kprobe_status = KPROBE_HIT_ACTIVE; @@ -377,6 +375,7 @@ ss_probe: return 1; no_kprobe: + preempt_enable_no_resched(); return ret; } @@ -448,8 +447,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) /* * By returning a non-zero value, we are telling - * kprobe_handler() that we have handled unlocking - * and re-enabling preemption + * kprobe_handler() that we don't want the post_handler + * to run (and have re-enabled preemption) */ return 1; } @@ -594,7 +593,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, struct die_args *args = (struct die_args *)data; int ret = NOTIFY_DONE; - rcu_read_lock(); switch (val) { case DIE_INT3: if (kprobe_handler(args->regs)) @@ -606,14 +604,16 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self, break; case DIE_GPF: case DIE_PAGE_FAULT: + /* kprobe_running() needs smp_processor_id() */ + preempt_disable(); if (kprobe_running() && kprobe_fault_handler(args->regs, args->trapnr)) ret = NOTIFY_STOP; + preempt_enable(); break; default: break; } - rcu_read_unlock(); return ret; } @@ -675,6 +675,7 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) *regs = kcb->jprobe_saved_regs; memcpy((kprobe_opcode_t *) stack_addr, kcb->jprobes_stack, MIN_STACK_SIZE(stack_addr)); + preempt_enable_no_resched(); return 1; } return 0; diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index cff281cf70cf..e373c4a9de53 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h @@ -159,7 +159,7 @@ extern void show_registers(struct pt_regs *regs); extern kprobe_opcode_t *get_insn_slot(void); extern void free_insn_slot(kprobe_opcode_t *slot); -/* Get the kprobe at this addr (if any) - called under a rcu_read_lock() */ +/* Get the kprobe at this addr (if any) - called with preemption disabled */ struct kprobe *get_kprobe(void *addr); struct hlist_head * kretprobe_inst_table_head(struct task_struct *tsk); diff --git a/kernel/kprobes.c b/kernel/kprobes.c index cfef426e4cdc..5beda378cc75 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -167,7 +167,7 @@ static inline void reset_kprobe_instance(void) * This routine is called either: * - under the kprobe_lock spinlock - during kprobe_[un]register() * OR - * - under an rcu_read_lock() - from arch/xxx/kernel/kprobes.c + * - with preemption disabled - from arch/xxx/kernel/kprobes.c */ struct kprobe __kprobes *get_kprobe(void *addr) { -- cgit v1.2.3 From 70a50ebd9a94533964c19f918dbbd66763e3f9e5 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 7 Nov 2005 01:00:16 -0800 Subject: [PATCH] RapidIO support: core includes Add RapidIO core include files. The core code implements enumeration/discovery, management of devices/resources, and interfaces for RIO drivers. Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/rio.h | 321 ++++++++++++++++++++++++++++++++ include/linux/rio_drv.h | 469 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/rio_ids.h | 24 +++ include/linux/rio_regs.h | 202 ++++++++++++++++++++ 4 files changed, 1016 insertions(+) create mode 100644 include/linux/rio.h create mode 100644 include/linux/rio_drv.h create mode 100644 include/linux/rio_ids.h create mode 100644 include/linux/rio_regs.h (limited to 'include/linux') diff --git a/include/linux/rio.h b/include/linux/rio.h new file mode 100644 index 000000000000..930bbb7c3802 --- /dev/null +++ b/include/linux/rio.h @@ -0,0 +1,321 @@ +/* + * RapidIO interconnect services + * (RapidIO Interconnect Specification, http://www.rapidio.org) + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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. + */ + +#ifndef LINUX_RIO_H +#define LINUX_RIO_H + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include +#include +#include + +#define RIO_ANY_DESTID 0xff +#define RIO_NO_HOPCOUNT -1 + +#define RIO_MAX_MPORT_RESOURCES 16 +#define RIO_MAX_DEV_RESOURCES 16 + +#define RIO_GLOBAL_TABLE 0xff /* Indicates access of a switch's + global routing table if it + has multiple (or per port) + tables */ + +#define RIO_INVALID_ROUTE 0xff /* Indicates that a route table + entry is invalid (no route + exists for the device ID) */ + +#ifdef CONFIG_RAPIDIO_8_BIT_TRANSPORT +#define RIO_MAX_ROUTE_ENTRIES (1 << 8) +#else +#define RIO_MAX_ROUTE_ENTRIES (1 << 16) +#endif + +#define RIO_MAX_MBOX 4 +#define RIO_MAX_MSG_SIZE 0x1000 + +/* + * Error values that may be returned by RIO functions. + */ +#define RIO_SUCCESSFUL 0x00 +#define RIO_BAD_SIZE 0x81 + +/* + * For RIO devices, the region numbers are assigned this way: + * + * 0 RapidIO outbound doorbells + * 1-15 RapidIO memory regions + * + * For RIO master ports, the region number are assigned this way: + * + * 0 RapidIO inbound doorbells + * 1 RapidIO inbound mailboxes + * 1 RapidIO outbound mailboxes + */ +#define RIO_DOORBELL_RESOURCE 0 +#define RIO_INB_MBOX_RESOURCE 1 +#define RIO_OUTB_MBOX_RESOURCE 2 + +extern struct bus_type rio_bus_type; +extern struct list_head rio_devices; /* list of all devices */ + +struct rio_mport; + +/** + * struct rio_dev - RIO device info + * @global_list: Node in list of all RIO devices + * @net_list: Node in list of RIO devices in a network + * @net: Network this device is a part of + * @did: Device ID + * @vid: Vendor ID + * @device_rev: Device revision + * @asm_did: Assembly device ID + * @asm_vid: Assembly vendor ID + * @asm_rev: Assembly revision + * @efptr: Extended feature pointer + * @pef: Processing element features + * @swpinfo: Switch port info + * @src_ops: Source operation capabilities + * @dst_ops: Destination operation capabilities + * @rswitch: Pointer to &struct rio_switch if valid for this device + * @driver: Driver claiming this device + * @dev: Device model device + * @riores: RIO resources this device owns + * @destid: Network destination ID + */ +struct rio_dev { + struct list_head global_list; /* node in list of all RIO devices */ + struct list_head net_list; /* node in per net list */ + struct rio_net *net; /* RIO net this device resides in */ + u16 did; + u16 vid; + u32 device_rev; + u16 asm_did; + u16 asm_vid; + u16 asm_rev; + u16 efptr; + u32 pef; + u32 swpinfo; /* Only used for switches */ + u32 src_ops; + u32 dst_ops; + struct rio_switch *rswitch; /* RIO switch info */ + struct rio_driver *driver; /* RIO driver claiming this device */ + struct device dev; /* LDM device structure */ + struct resource riores[RIO_MAX_DEV_RESOURCES]; + u16 destid; +}; + +#define rio_dev_g(n) list_entry(n, struct rio_dev, global_list) +#define rio_dev_f(n) list_entry(n, struct rio_dev, net_list) +#define to_rio_dev(n) container_of(n, struct rio_dev, dev) + +/** + * struct rio_msg - RIO message event + * @res: Mailbox resource + * @mcback: Message event callback + */ +struct rio_msg { + struct resource *res; + void (*mcback) (struct rio_mport * mport, int mbox, int slot); +}; + +/** + * struct rio_dbell - RIO doorbell event + * @node: Node in list of doorbell events + * @res: Doorbell resource + * @dinb: Doorbell event callback + */ +struct rio_dbell { + struct list_head node; + struct resource *res; + void (*dinb) (struct rio_mport * mport, u16 src, u16 dst, u16 info); +}; + +/** + * struct rio_mport - RIO master port info + * @dbells: List of doorbell events + * @node: Node in global list of master ports + * @nnode: Node in network list of master ports + * @iores: I/O mem resource that this master port interface owns + * @riores: RIO resources that this master port interfaces owns + * @inb_msg: RIO inbound message event descriptors + * @outb_msg: RIO outbound message event descriptors + * @host_deviceid: Host device ID associated with this master port + * @ops: configuration space functions + * @id: Port ID, unique among all ports + * @index: Port index, unique among all port interfaces of the same type + * @name: Port name string + */ +struct rio_mport { + struct list_head dbells; /* list of doorbell events */ + struct list_head node; /* node in global list of ports */ + struct list_head nnode; /* node in net list of ports */ + struct resource iores; + struct resource riores[RIO_MAX_MPORT_RESOURCES]; + struct rio_msg inb_msg[RIO_MAX_MBOX]; + struct rio_msg outb_msg[RIO_MAX_MBOX]; + int host_deviceid; /* Host device ID */ + struct rio_ops *ops; /* maintenance transaction functions */ + unsigned char id; /* port ID, unique among all ports */ + unsigned char index; /* port index, unique among all port + interfaces of the same type */ + unsigned char name[40]; +}; + +/** + * struct rio_net - RIO network info + * @node: Node in global list of RIO networks + * @devices: List of devices in this network + * @mports: List of master ports accessing this network + * @hport: Default port for accessing this network + * @id: RIO network ID + */ +struct rio_net { + struct list_head node; /* node in list of networks */ + struct list_head devices; /* list of devices in this net */ + struct list_head mports; /* list of ports accessing net */ + struct rio_mport *hport; /* primary port for accessing net */ + unsigned char id; /* RIO network ID */ +}; + +/** + * struct rio_switch - RIO switch info + * @node: Node in global list of switches + * @switchid: Switch ID that is unique across a network + * @hopcount: Hopcount to this switch + * @destid: Associated destid in the path + * @route_table: Copy of switch routing table + * @add_entry: Callback for switch-specific route add function + * @get_entry: Callback for switch-specific route get function + */ +struct rio_switch { + struct list_head node; + u16 switchid; + u16 hopcount; + u16 destid; + u8 route_table[RIO_MAX_ROUTE_ENTRIES]; + int (*add_entry) (struct rio_mport * mport, u16 destid, u8 hopcount, + u16 table, u16 route_destid, u8 route_port); + int (*get_entry) (struct rio_mport * mport, u16 destid, u8 hopcount, + u16 table, u16 route_destid, u8 * route_port); +}; + +/* Low-level architecture-dependent routines */ + +/** + * struct rio_ops - Low-level RIO configuration space operations + * @lcread: Callback to perform local (master port) read of config space. + * @lcwrite: Callback to perform local (master port) write of config space. + * @cread: Callback to perform network read of config space. + * @cwrite: Callback to perform network write of config space. + * @dsend: Callback to send a doorbell message. + */ +struct rio_ops { + int (*lcread) (int index, u32 offset, int len, u32 * data); + int (*lcwrite) (int index, u32 offset, int len, u32 data); + int (*cread) (int index, u16 destid, u8 hopcount, u32 offset, int len, + u32 * data); + int (*cwrite) (int index, u16 destid, u8 hopcount, u32 offset, int len, + u32 data); + int (*dsend) (int index, u16 destid, u16 data); +}; + +#define RIO_RESOURCE_MEM 0x00000100 +#define RIO_RESOURCE_DOORBELL 0x00000200 +#define RIO_RESOURCE_MAILBOX 0x00000400 + +#define RIO_RESOURCE_CACHEABLE 0x00010000 +#define RIO_RESOURCE_PCI 0x00020000 + +#define RIO_RESOURCE_BUSY 0x80000000 + +/** + * struct rio_driver - RIO driver info + * @node: Node in list of drivers + * @name: RIO driver name + * @id_table: RIO device ids to be associated with this driver + * @probe: RIO device inserted + * @remove: RIO device removed + * @suspend: RIO device suspended + * @resume: RIO device awakened + * @enable_wake: RIO device enable wake event + * @driver: LDM driver struct + * + * Provides info on a RIO device driver for insertion/removal and + * power management purposes. + */ +struct rio_driver { + struct list_head node; + char *name; + const struct rio_device_id *id_table; + int (*probe) (struct rio_dev * dev, const struct rio_device_id * id); + void (*remove) (struct rio_dev * dev); + int (*suspend) (struct rio_dev * dev, u32 state); + int (*resume) (struct rio_dev * dev); + int (*enable_wake) (struct rio_dev * dev, u32 state, int enable); + struct device_driver driver; +}; + +#define to_rio_driver(drv) container_of(drv,struct rio_driver, driver) + +/** + * struct rio_device_id - RIO device identifier + * @did: RIO device ID + * @vid: RIO vendor ID + * @asm_did: RIO assembly device ID + * @asm_vid: RIO assembly vendor ID + * + * Identifies a RIO device based on both the device/vendor IDs and + * the assembly device/vendor IDs. + */ +struct rio_device_id { + u16 did, vid; + u16 asm_did, asm_vid; +}; + +/** + * struct rio_route_ops - Per-switch route operations + * @vid: RIO vendor ID + * @did: RIO device ID + * @add_hook: Callback that adds a route entry + * @get_hook: Callback that gets a route entry + * + * Defines the operations that are necessary to manipulate the route + * tables for a particular RIO switch device. + */ +struct rio_route_ops { + u16 vid, did; + int (*add_hook) (struct rio_mport * mport, u16 destid, u8 hopcount, + u16 table, u16 route_destid, u8 route_port); + int (*get_hook) (struct rio_mport * mport, u16 destid, u8 hopcount, + u16 table, u16 route_destid, u8 * route_port); +}; + +/* Architecture and hardware-specific functions */ +extern int rio_init_mports(void); +extern void rio_register_mport(struct rio_mport *); +extern int rio_hw_add_outb_message(struct rio_mport *, struct rio_dev *, int, + void *, size_t); +extern int rio_hw_add_inb_buffer(struct rio_mport *, int, void *); +extern void *rio_hw_get_inb_message(struct rio_mport *, int); +extern int rio_open_inb_mbox(struct rio_mport *, int, int); +extern void rio_close_inb_mbox(struct rio_mport *, int); +extern int rio_open_outb_mbox(struct rio_mport *, int, int); +extern void rio_close_outb_mbox(struct rio_mport *, int); + +#endif /* __KERNEL__ */ +#endif /* LINUX_RIO_H */ diff --git a/include/linux/rio_drv.h b/include/linux/rio_drv.h new file mode 100644 index 000000000000..7483dfc0dfa3 --- /dev/null +++ b/include/linux/rio_drv.h @@ -0,0 +1,469 @@ +/* + * RapidIO driver services + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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. + */ + +#ifndef LINUX_RIO_DRV_H +#define LINUX_RIO_DRV_H + +#ifdef __KERNEL__ + +#include +#include +#include +#include +#include +#include +#include + +extern int __rio_local_read_config_32(struct rio_mport *port, u32 offset, + u32 * data); +extern int __rio_local_write_config_32(struct rio_mport *port, u32 offset, + u32 data); +extern int __rio_local_read_config_16(struct rio_mport *port, u32 offset, + u16 * data); +extern int __rio_local_write_config_16(struct rio_mport *port, u32 offset, + u16 data); +extern int __rio_local_read_config_8(struct rio_mport *port, u32 offset, + u8 * data); +extern int __rio_local_write_config_8(struct rio_mport *port, u32 offset, + u8 data); + +extern int rio_mport_read_config_32(struct rio_mport *port, u16 destid, + u8 hopcount, u32 offset, u32 * data); +extern int rio_mport_write_config_32(struct rio_mport *port, u16 destid, + u8 hopcount, u32 offset, u32 data); +extern int rio_mport_read_config_16(struct rio_mport *port, u16 destid, + u8 hopcount, u32 offset, u16 * data); +extern int rio_mport_write_config_16(struct rio_mport *port, u16 destid, + u8 hopcount, u32 offset, u16 data); +extern int rio_mport_read_config_8(struct rio_mport *port, u16 destid, + u8 hopcount, u32 offset, u8 * data); +extern int rio_mport_write_config_8(struct rio_mport *port, u16 destid, + u8 hopcount, u32 offset, u8 data); + +/** + * rio_local_read_config_32 - Read 32 bits from local configuration space + * @port: Master port + * @offset: Offset into local configuration space + * @data: Pointer to read data into + * + * Reads 32 bits of data from the specified offset within the local + * device's configuration space. + */ +static inline int rio_local_read_config_32(struct rio_mport *port, u32 offset, + u32 * data) +{ + return __rio_local_read_config_32(port, offset, data); +} + +/** + * rio_local_write_config_32 - Write 32 bits to local configuration space + * @port: Master port + * @offset: Offset into local configuration space + * @data: Data to be written + * + * Writes 32 bits of data to the specified offset within the local + * device's configuration space. + */ +static inline int rio_local_write_config_32(struct rio_mport *port, u32 offset, + u32 data) +{ + return __rio_local_write_config_32(port, offset, data); +} + +/** + * rio_local_read_config_16 - Read 16 bits from local configuration space + * @port: Master port + * @offset: Offset into local configuration space + * @data: Pointer to read data into + * + * Reads 16 bits of data from the specified offset within the local + * device's configuration space. + */ +static inline int rio_local_read_config_16(struct rio_mport *port, u32 offset, + u16 * data) +{ + return __rio_local_read_config_16(port, offset, data); +} + +/** + * rio_local_write_config_16 - Write 16 bits to local configuration space + * @port: Master port + * @offset: Offset into local configuration space + * @data: Data to be written + * + * Writes 16 bits of data to the specified offset within the local + * device's configuration space. + */ + +static inline int rio_local_write_config_16(struct rio_mport *port, u32 offset, + u16 data) +{ + return __rio_local_write_config_16(port, offset, data); +} + +/** + * rio_local_read_config_8 - Read 8 bits from local configuration space + * @port: Master port + * @offset: Offset into local configuration space + * @data: Pointer to read data into + * + * Reads 8 bits of data from the specified offset within the local + * device's configuration space. + */ +static inline int rio_local_read_config_8(struct rio_mport *port, u32 offset, + u8 * data) +{ + return __rio_local_read_config_8(port, offset, data); +} + +/** + * rio_local_write_config_8 - Write 8 bits to local configuration space + * @port: Master port + * @offset: Offset into local configuration space + * @data: Data to be written + * + * Writes 8 bits of data to the specified offset within the local + * device's configuration space. + */ +static inline int rio_local_write_config_8(struct rio_mport *port, u32 offset, + u8 data) +{ + return __rio_local_write_config_8(port, offset, data); +} + +/** + * rio_read_config_32 - Read 32 bits from configuration space + * @rdev: RIO device + * @offset: Offset into device configuration space + * @data: Pointer to read data into + * + * Reads 32 bits of data from the specified offset within the + * RIO device's configuration space. + */ +static inline int rio_read_config_32(struct rio_dev *rdev, u32 offset, + u32 * data) +{ + u8 hopcount = 0xff; + u16 destid = rdev->destid; + + if (rdev->rswitch) { + destid = rdev->rswitch->destid; + hopcount = rdev->rswitch->hopcount; + } + + return rio_mport_read_config_32(rdev->net->hport, destid, hopcount, + offset, data); +}; + +/** + * rio_write_config_32 - Write 32 bits to configuration space + * @rdev: RIO device + * @offset: Offset into device configuration space + * @data: Data to be written + * + * Writes 32 bits of data to the specified offset within the + * RIO device's configuration space. + */ +static inline int rio_write_config_32(struct rio_dev *rdev, u32 offset, + u32 data) +{ + u8 hopcount = 0xff; + u16 destid = rdev->destid; + + if (rdev->rswitch) { + destid = rdev->rswitch->destid; + hopcount = rdev->rswitch->hopcount; + } + + return rio_mport_write_config_32(rdev->net->hport, destid, hopcount, + offset, data); +}; + +/** + * rio_read_config_16 - Read 16 bits from configuration space + * @rdev: RIO device + * @offset: Offset into device configuration space + * @data: Pointer to read data into + * + * Reads 16 bits of data from the specified offset within the + * RIO device's configuration space. + */ +static inline int rio_read_config_16(struct rio_dev *rdev, u32 offset, + u16 * data) +{ + u8 hopcount = 0xff; + u16 destid = rdev->destid; + + if (rdev->rswitch) { + destid = rdev->rswitch->destid; + hopcount = rdev->rswitch->hopcount; + } + + return rio_mport_read_config_16(rdev->net->hport, destid, hopcount, + offset, data); +}; + +/** + * rio_write_config_16 - Write 16 bits to configuration space + * @rdev: RIO device + * @offset: Offset into device configuration space + * @data: Data to be written + * + * Writes 16 bits of data to the specified offset within the + * RIO device's configuration space. + */ +static inline int rio_write_config_16(struct rio_dev *rdev, u32 offset, + u16 data) +{ + u8 hopcount = 0xff; + u16 destid = rdev->destid; + + if (rdev->rswitch) { + destid = rdev->rswitch->destid; + hopcount = rdev->rswitch->hopcount; + } + + return rio_mport_write_config_16(rdev->net->hport, destid, hopcount, + offset, data); +}; + +/** + * rio_read_config_8 - Read 8 bits from configuration space + * @rdev: RIO device + * @offset: Offset into device configuration space + * @data: Pointer to read data into + * + * Reads 8 bits of data from the specified offset within the + * RIO device's configuration space. + */ +static inline int rio_read_config_8(struct rio_dev *rdev, u32 offset, u8 * data) +{ + u8 hopcount = 0xff; + u16 destid = rdev->destid; + + if (rdev->rswitch) { + destid = rdev->rswitch->destid; + hopcount = rdev->rswitch->hopcount; + } + + return rio_mport_read_config_8(rdev->net->hport, destid, hopcount, + offset, data); +}; + +/** + * rio_write_config_8 - Write 8 bits to configuration space + * @rdev: RIO device + * @offset: Offset into device configuration space + * @data: Data to be written + * + * Writes 8 bits of data to the specified offset within the + * RIO device's configuration space. + */ +static inline int rio_write_config_8(struct rio_dev *rdev, u32 offset, u8 data) +{ + u8 hopcount = 0xff; + u16 destid = rdev->destid; + + if (rdev->rswitch) { + destid = rdev->rswitch->destid; + hopcount = rdev->rswitch->hopcount; + } + + return rio_mport_write_config_8(rdev->net->hport, destid, hopcount, + offset, data); +}; + +extern int rio_mport_send_doorbell(struct rio_mport *mport, u16 destid, + u16 data); + +/** + * rio_send_doorbell - Send a doorbell message to a device + * @rdev: RIO device + * @data: Doorbell message data + * + * Send a doorbell message to a RIO device. The doorbell message + * has a 16-bit info field provided by the @data argument. + */ +static inline int rio_send_doorbell(struct rio_dev *rdev, u16 data) +{ + return rio_mport_send_doorbell(rdev->net->hport, rdev->destid, data); +}; + +/** + * rio_init_mbox_res - Initialize a RIO mailbox resource + * @res: resource struct + * @start: start of mailbox range + * @end: end of mailbox range + * + * This function is used to initialize the fields of a resource + * for use as a mailbox resource. It initializes a range of + * mailboxes using the start and end arguments. + */ +static inline void rio_init_mbox_res(struct resource *res, int start, int end) +{ + memset(res, 0, sizeof(struct resource)); + res->start = start; + res->end = end; + res->flags = RIO_RESOURCE_MAILBOX; +} + +/** + * rio_init_dbell_res - Initialize a RIO doorbell resource + * @res: resource struct + * @start: start of doorbell range + * @end: end of doorbell range + * + * This function is used to initialize the fields of a resource + * for use as a doorbell resource. It initializes a range of + * doorbell messages using the start and end arguments. + */ +static inline void rio_init_dbell_res(struct resource *res, u16 start, u16 end) +{ + memset(res, 0, sizeof(struct resource)); + res->start = start; + res->end = end; + res->flags = RIO_RESOURCE_DOORBELL; +} + +/** + * RIO_DEVICE - macro used to describe a specific RIO device + * @vid: the 16 bit RIO vendor ID + * @did: the 16 bit RIO device ID + * + * This macro is used to create a struct rio_device_id that matches a + * specific device. The assembly vendor and assembly device fields + * will be set to %RIO_ANY_ID. + */ +#define RIO_DEVICE(dev,ven) \ + .did = (dev), .vid = (ven), \ + .asm_did = RIO_ANY_ID, .asm_vid = RIO_ANY_ID + +/* Mailbox management */ +extern int rio_request_outb_mbox(struct rio_mport *, int, int, + void (*)(struct rio_mport *, int, int)); +extern int rio_release_outb_mbox(struct rio_mport *, int); + +/** + * rio_add_outb_message - Add RIO message to an outbound mailbox queue + * @mport: RIO master port containing the outbound queue + * @rdev: RIO device the message is be sent to + * @mbox: The outbound mailbox queue + * @buffer: Pointer to the message buffer + * @len: Length of the message buffer + * + * Adds a RIO message buffer to an outbound mailbox queue for + * transmission. Returns 0 on success. + */ +static inline int rio_add_outb_message(struct rio_mport *mport, + struct rio_dev *rdev, int mbox, + void *buffer, size_t len) +{ + return rio_hw_add_outb_message(mport, rdev, mbox, buffer, len); +} + +extern int rio_request_inb_mbox(struct rio_mport *, int, int, + void (*)(struct rio_mport *, int, int)); +extern int rio_release_inb_mbox(struct rio_mport *, int); + +/** + * rio_add_inb_buffer - Add buffer to an inbound mailbox queue + * @mport: Master port containing the inbound mailbox + * @mbox: The inbound mailbox number + * @buffer: Pointer to the message buffer + * + * Adds a buffer to an inbound mailbox queue for reception. Returns + * 0 on success. + */ +static inline int rio_add_inb_buffer(struct rio_mport *mport, int mbox, + void *buffer) +{ + return rio_hw_add_inb_buffer(mport, mbox, buffer); +} + +/** + * rio_get_inb_message - Get A RIO message from an inbound mailbox queue + * @mport: Master port containing the inbound mailbox + * @mbox: The inbound mailbox number + * @buffer: Pointer to the message buffer + * + * Get a RIO message from an inbound mailbox queue. Returns 0 on success. + */ +static inline void *rio_get_inb_message(struct rio_mport *mport, int mbox) +{ + return rio_hw_get_inb_message(mport, mbox); +} + +/* Doorbell management */ +extern int rio_request_inb_dbell(struct rio_mport *, u16, u16, + void (*)(struct rio_mport *, u16, u16, u16)); +extern int rio_release_inb_dbell(struct rio_mport *, u16, u16); +extern struct resource *rio_request_outb_dbell(struct rio_dev *, u16, u16); +extern int rio_release_outb_dbell(struct rio_dev *, struct resource *); + +/* Memory region management */ +int rio_claim_resource(struct rio_dev *, int); +int rio_request_regions(struct rio_dev *, char *); +void rio_release_regions(struct rio_dev *); +int rio_request_region(struct rio_dev *, int, char *); +void rio_release_region(struct rio_dev *, int); + +/* LDM support */ +int rio_register_driver(struct rio_driver *); +void rio_unregister_driver(struct rio_driver *); +struct rio_dev *rio_dev_get(struct rio_dev *); +void rio_dev_put(struct rio_dev *); + +/** + * rio_name - Get the unique RIO device identifier + * @rdev: RIO device + * + * Get the unique RIO device identifier. Returns the device + * identifier string. + */ +static inline char *rio_name(struct rio_dev *rdev) +{ + return rdev->dev.bus_id; +} + +/** + * rio_get_drvdata - Get RIO driver specific data + * @rdev: RIO device + * + * Get RIO driver specific data. Returns a pointer to the + * driver specific data. + */ +static inline void *rio_get_drvdata(struct rio_dev *rdev) +{ + return dev_get_drvdata(&rdev->dev); +} + +/** + * rio_set_drvdata - Set RIO driver specific data + * @rdev: RIO device + * @data: Pointer to driver specific data + * + * Set RIO driver specific data. device struct driver data pointer + * is set to the @data argument. + */ +static inline void rio_set_drvdata(struct rio_dev *rdev, void *data) +{ + dev_set_drvdata(&rdev->dev, data); +} + +/* Misc driver helpers */ +extern u16 rio_local_get_device_id(struct rio_mport *port); +extern struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *from); +extern struct rio_dev *rio_get_asm(u16 vid, u16 did, u16 asm_vid, u16 asm_did, + struct rio_dev *from); + +#endif /* __KERNEL__ */ +#endif /* LINUX_RIO_DRV_H */ diff --git a/include/linux/rio_ids.h b/include/linux/rio_ids.h new file mode 100644 index 000000000000..919d4e07d54e --- /dev/null +++ b/include/linux/rio_ids.h @@ -0,0 +1,24 @@ +/* + * RapidIO devices + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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. + */ + +#ifndef LINUX_RIO_IDS_H +#define LINUX_RIO_IDS_H + +#define RIO_ANY_ID 0xffff + +#define RIO_VID_FREESCALE 0x0002 +#define RIO_DID_MPC8560 0x0003 + +#define RIO_VID_TUNDRA 0x000d +#define RIO_DID_TSI500 0x0500 + +#endif /* LINUX_RIO_IDS_H */ diff --git a/include/linux/rio_regs.h b/include/linux/rio_regs.h new file mode 100644 index 000000000000..f419be3be491 --- /dev/null +++ b/include/linux/rio_regs.h @@ -0,0 +1,202 @@ +/* + * RapidIO register definitions + * + * Copyright 2005 MontaVista Software, Inc. + * Matt Porter + * + * 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. + */ + +#ifndef LINUX_RIO_REGS_H +#define LINUX_RIO_REGS_H + +/* + * In RapidIO, each device has a 2MB configuration space that is + * accessed via maintenance transactions. Portions of configuration + * space are standardized and/or reserved. + */ +#define RIO_DEV_ID_CAR 0x00 /* [I] Device Identity CAR */ +#define RIO_DEV_INFO_CAR 0x04 /* [I] Device Information CAR */ +#define RIO_ASM_ID_CAR 0x08 /* [I] Assembly Identity CAR */ +#define RIO_ASM_ID_MASK 0xffff0000 /* [I] Asm ID Mask */ +#define RIO_ASM_VEN_ID_MASK 0x0000ffff /* [I] Asm Vend Mask */ + +#define RIO_ASM_INFO_CAR 0x0c /* [I] Assembly Information CAR */ +#define RIO_ASM_REV_MASK 0xffff0000 /* [I] Asm Rev Mask */ +#define RIO_EXT_FTR_PTR_MASK 0x0000ffff /* [I] EF_PTR Mask */ + +#define RIO_PEF_CAR 0x10 /* [I] Processing Element Features CAR */ +#define RIO_PEF_BRIDGE 0x80000000 /* [I] Bridge */ +#define RIO_PEF_MEMORY 0x40000000 /* [I] MMIO */ +#define RIO_PEF_PROCESSOR 0x20000000 /* [I] Processor */ +#define RIO_PEF_SWITCH 0x10000000 /* [I] Switch */ +#define RIO_PEF_INB_MBOX 0x00f00000 /* [II] Mailboxes */ +#define RIO_PEF_INB_MBOX0 0x00800000 /* [II] Mailbox 0 */ +#define RIO_PEF_INB_MBOX1 0x00400000 /* [II] Mailbox 1 */ +#define RIO_PEF_INB_MBOX2 0x00200000 /* [II] Mailbox 2 */ +#define RIO_PEF_INB_MBOX3 0x00100000 /* [II] Mailbox 3 */ +#define RIO_PEF_INB_DOORBELL 0x00080000 /* [II] Doorbells */ +#define RIO_PEF_CTLS 0x00000010 /* [III] CTLS */ +#define RIO_PEF_EXT_FEATURES 0x00000008 /* [I] EFT_PTR valid */ +#define RIO_PEF_ADDR_66 0x00000004 /* [I] 66 bits */ +#define RIO_PEF_ADDR_50 0x00000002 /* [I] 50 bits */ +#define RIO_PEF_ADDR_34 0x00000001 /* [I] 34 bits */ + +#define RIO_SWP_INFO_CAR 0x14 /* [I] Switch Port Information CAR */ +#define RIO_SWP_INFO_PORT_TOTAL_MASK 0x0000ff00 /* [I] Total number of ports */ +#define RIO_SWP_INFO_PORT_NUM_MASK 0x000000ff /* [I] Maintenance transaction port number */ +#define RIO_GET_TOTAL_PORTS(x) ((x & RIO_SWP_INFO_PORT_TOTAL_MASK) >> 8) + +#define RIO_SRC_OPS_CAR 0x18 /* [I] Source Operations CAR */ +#define RIO_SRC_OPS_READ 0x00008000 /* [I] Read op */ +#define RIO_SRC_OPS_WRITE 0x00004000 /* [I] Write op */ +#define RIO_SRC_OPS_STREAM_WRITE 0x00002000 /* [I] Str-write op */ +#define RIO_SRC_OPS_WRITE_RESPONSE 0x00001000 /* [I] Write/resp op */ +#define RIO_SRC_OPS_DATA_MSG 0x00000800 /* [II] Data msg op */ +#define RIO_SRC_OPS_DOORBELL 0x00000400 /* [II] Doorbell op */ +#define RIO_SRC_OPS_ATOMIC_TST_SWP 0x00000100 /* [I] Atomic TAS op */ +#define RIO_SRC_OPS_ATOMIC_INC 0x00000080 /* [I] Atomic inc op */ +#define RIO_SRC_OPS_ATOMIC_DEC 0x00000040 /* [I] Atomic dec op */ +#define RIO_SRC_OPS_ATOMIC_SET 0x00000020 /* [I] Atomic set op */ +#define RIO_SRC_OPS_ATOMIC_CLR 0x00000010 /* [I] Atomic clr op */ +#define RIO_SRC_OPS_PORT_WRITE 0x00000004 /* [I] Port-write op */ + +#define RIO_DST_OPS_CAR 0x1c /* Destination Operations CAR */ +#define RIO_DST_OPS_READ 0x00008000 /* [I] Read op */ +#define RIO_DST_OPS_WRITE 0x00004000 /* [I] Write op */ +#define RIO_DST_OPS_STREAM_WRITE 0x00002000 /* [I] Str-write op */ +#define RIO_DST_OPS_WRITE_RESPONSE 0x00001000 /* [I] Write/resp op */ +#define RIO_DST_OPS_DATA_MSG 0x00000800 /* [II] Data msg op */ +#define RIO_DST_OPS_DOORBELL 0x00000400 /* [II] Doorbell op */ +#define RIO_DST_OPS_ATOMIC_TST_SWP 0x00000100 /* [I] Atomic TAS op */ +#define RIO_DST_OPS_ATOMIC_INC 0x00000080 /* [I] Atomic inc op */ +#define RIO_DST_OPS_ATOMIC_DEC 0x00000040 /* [I] Atomic dec op */ +#define RIO_DST_OPS_ATOMIC_SET 0x00000020 /* [I] Atomic set op */ +#define RIO_DST_OPS_ATOMIC_CLR 0x00000010 /* [I] Atomic clr op */ +#define RIO_DST_OPS_PORT_WRITE 0x00000004 /* [I] Port-write op */ + + /* 0x20-0x3c *//* Reserved */ + +#define RIO_MBOX_CSR 0x40 /* [II] Mailbox CSR */ +#define RIO_MBOX0_AVAIL 0x80000000 /* [II] Mbox 0 avail */ +#define RIO_MBOX0_FULL 0x40000000 /* [II] Mbox 0 full */ +#define RIO_MBOX0_EMPTY 0x20000000 /* [II] Mbox 0 empty */ +#define RIO_MBOX0_BUSY 0x10000000 /* [II] Mbox 0 busy */ +#define RIO_MBOX0_FAIL 0x08000000 /* [II] Mbox 0 fail */ +#define RIO_MBOX0_ERROR 0x04000000 /* [II] Mbox 0 error */ +#define RIO_MBOX1_AVAIL 0x00800000 /* [II] Mbox 1 avail */ +#define RIO_MBOX1_FULL 0x00200000 /* [II] Mbox 1 full */ +#define RIO_MBOX1_EMPTY 0x00200000 /* [II] Mbox 1 empty */ +#define RIO_MBOX1_BUSY 0x00100000 /* [II] Mbox 1 busy */ +#define RIO_MBOX1_FAIL 0x00080000 /* [II] Mbox 1 fail */ +#define RIO_MBOX1_ERROR 0x00040000 /* [II] Mbox 1 error */ +#define RIO_MBOX2_AVAIL 0x00008000 /* [II] Mbox 2 avail */ +#define RIO_MBOX2_FULL 0x00004000 /* [II] Mbox 2 full */ +#define RIO_MBOX2_EMPTY 0x00002000 /* [II] Mbox 2 empty */ +#define RIO_MBOX2_BUSY 0x00001000 /* [II] Mbox 2 busy */ +#define RIO_MBOX2_FAIL 0x00000800 /* [II] Mbox 2 fail */ +#define RIO_MBOX2_ERROR 0x00000400 /* [II] Mbox 2 error */ +#define RIO_MBOX3_AVAIL 0x00000080 /* [II] Mbox 3 avail */ +#define RIO_MBOX3_FULL 0x00000040 /* [II] Mbox 3 full */ +#define RIO_MBOX3_EMPTY 0x00000020 /* [II] Mbox 3 empty */ +#define RIO_MBOX3_BUSY 0x00000010 /* [II] Mbox 3 busy */ +#define RIO_MBOX3_FAIL 0x00000008 /* [II] Mbox 3 fail */ +#define RIO_MBOX3_ERROR 0x00000004 /* [II] Mbox 3 error */ + +#define RIO_WRITE_PORT_CSR 0x44 /* [I] Write Port CSR */ +#define RIO_DOORBELL_CSR 0x44 /* [II] Doorbell CSR */ +#define RIO_DOORBELL_AVAIL 0x80000000 /* [II] Doorbell avail */ +#define RIO_DOORBELL_FULL 0x40000000 /* [II] Doorbell full */ +#define RIO_DOORBELL_EMPTY 0x20000000 /* [II] Doorbell empty */ +#define RIO_DOORBELL_BUSY 0x10000000 /* [II] Doorbell busy */ +#define RIO_DOORBELL_FAILED 0x08000000 /* [II] Doorbell failed */ +#define RIO_DOORBELL_ERROR 0x04000000 /* [II] Doorbell error */ +#define RIO_WRITE_PORT_AVAILABLE 0x00000080 /* [I] Write Port Available */ +#define RIO_WRITE_PORT_FULL 0x00000040 /* [I] Write Port Full */ +#define RIO_WRITE_PORT_EMPTY 0x00000020 /* [I] Write Port Empty */ +#define RIO_WRITE_PORT_BUSY 0x00000010 /* [I] Write Port Busy */ +#define RIO_WRITE_PORT_FAILED 0x00000008 /* [I] Write Port Failed */ +#define RIO_WRITE_PORT_ERROR 0x00000004 /* [I] Write Port Error */ + + /* 0x48 *//* Reserved */ + +#define RIO_PELL_CTRL_CSR 0x4c /* [I] PE Logical Layer Control CSR */ +#define RIO_PELL_ADDR_66 0x00000004 /* [I] 66-bit addr */ +#define RIO_PELL_ADDR_50 0x00000002 /* [I] 50-bit addr */ +#define RIO_PELL_ADDR_34 0x00000001 /* [I] 34-bit addr */ + + /* 0x50-0x54 *//* Reserved */ + +#define RIO_LCSH_BA 0x58 /* [I] LCS High Base Address */ +#define RIO_LCSL_BA 0x5c /* [I] LCS Base Address */ + +#define RIO_DID_CSR 0x60 /* [III] Base Device ID CSR */ + + /* 0x64 *//* Reserved */ + +#define RIO_HOST_DID_LOCK_CSR 0x68 /* [III] Host Base Device ID Lock CSR */ +#define RIO_COMPONENT_TAG_CSR 0x6c /* [III] Component Tag CSR */ + + /* 0x70-0xf8 *//* Reserved */ + /* 0x100-0xfff8 *//* [I] Extended Features Space */ + /* 0x10000-0xfffff8 *//* [I] Implementation-defined Space */ + +/* + * Extended Features Space is a configuration space area where + * functionality is mapped into extended feature blocks via a + * singly linked list of extended feature pointers (EFT_PTR). + * + * Each extended feature block can be identified/located in + * Extended Features Space by walking the extended feature + * list starting with the Extended Feature Pointer located + * in the Assembly Information CAR. + * + * Extended Feature Blocks (EFBs) are identified with an assigned + * EFB ID. Extended feature block offsets in the definitions are + * relative to the offset of the EFB within the Extended Features + * Space. + */ + +/* Helper macros to parse the Extended Feature Block header */ +#define RIO_EFB_PTR_MASK 0xffff0000 +#define RIO_EFB_ID_MASK 0x0000ffff +#define RIO_GET_BLOCK_PTR(x) ((x & RIO_EFB_PTR_MASK) >> 16) +#define RIO_GET_BLOCK_ID(x) (x & RIO_EFB_ID_MASK) + +/* Extended Feature Block IDs */ +#define RIO_EFB_PAR_EP_ID 0x0001 /* [IV] LP/LVDS EP Devices */ +#define RIO_EFB_PAR_EP_REC_ID 0x0002 /* [IV] LP/LVDS EP Recovery Devices */ +#define RIO_EFB_PAR_EP_FREE_ID 0x0003 /* [IV] LP/LVDS EP Free Devices */ +#define RIO_EFB_SER_EP_ID 0x0004 /* [VI] LP/Serial EP Devices */ +#define RIO_EFB_SER_EP_REC_ID 0x0005 /* [VI] LP/Serial EP Recovery Devices */ +#define RIO_EFB_SER_EP_FREE_ID 0x0006 /* [VI] LP/Serial EP Free Devices */ + +/* + * Physical 8/16 LP-LVDS + * ID=0x0001, Generic End Point Devices + * ID=0x0002, Generic End Point Devices, software assisted recovery option + * ID=0x0003, Generic End Point Free Devices + * + * Physical LP-Serial + * ID=0x0004, Generic End Point Devices + * ID=0x0005, Generic End Point Devices, software assisted recovery option + * ID=0x0006, Generic End Point Free Devices + */ +#define RIO_PORT_MNT_HEADER 0x0000 +#define RIO_PORT_REQ_CTL_CSR 0x0020 +#define RIO_PORT_RSP_CTL_CSR 0x0024 /* 0x0001/0x0002 */ +#define RIO_PORT_GEN_CTL_CSR 0x003c +#define RIO_PORT_GEN_HOST 0x80000000 +#define RIO_PORT_GEN_MASTER 0x40000000 +#define RIO_PORT_GEN_DISCOVERED 0x20000000 +#define RIO_PORT_N_MNT_REQ_CSR(x) (0x0040 + x*0x20) /* 0x0002 */ +#define RIO_PORT_N_MNT_RSP_CSR(x) (0x0044 + x*0x20) /* 0x0002 */ +#define RIO_PORT_N_ACK_STS_CSR(x) (0x0048 + x*0x20) /* 0x0002 */ +#define RIO_PORT_N_ERR_STS_CSR(x) (0x58 + x*0x20) +#define PORT_N_ERR_STS_PORT_OK 0x00000002 +#define RIO_PORT_N_CTL_CSR(x) (0x5c + x*0x20) + +#endif /* LINUX_RIO_REGS_H */ -- cgit v1.2.3 From fa78cc51794912b7e6ee98cd823fcc84cf79d04a Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 7 Nov 2005 01:00:18 -0800 Subject: [PATCH] rapidio: core updates Addresses issues raised with the 2.6.12-rc6-mm1 RIO support. Fix dma_mask init, shrink some code, general cleanup. Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rapidio/rio-scan.c | 35 ++++++++++------------------------- drivers/rapidio/rio.h | 3 +++ include/linux/rio.h | 2 ++ include/linux/rio_regs.h | 13 +++++++++++++ 4 files changed, 28 insertions(+), 25 deletions(-) (limited to 'include/linux') diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c index 20e1d8f74597..4f7ed4bd3be9 100644 --- a/drivers/rapidio/rio-scan.c +++ b/drivers/rapidio/rio-scan.c @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -33,7 +34,8 @@ static LIST_HEAD(rio_switches); static void rio_enum_timeout(unsigned long); -spinlock_t rio_global_list_lock = SPIN_LOCK_UNLOCKED; +DEFINE_SPINLOCK(rio_global_list_lock); + static int next_destid = 0; static int next_switchid = 0; static int next_net = 0; @@ -55,9 +57,6 @@ static int rio_sport_phys_table[] = { -1, }; -extern struct rio_route_ops __start_rio_route_ops[]; -extern struct rio_route_ops __end_rio_route_ops[]; - /** * rio_get_device_id - Get the base/extended device id for a device * @port: RIO master port @@ -85,8 +84,7 @@ static u16 rio_get_device_id(struct rio_mport *port, u16 destid, u8 hopcount) * * Writes the base/extended device id from a device. */ -static void -rio_set_device_id(struct rio_mport *port, u16 destid, u8 hopcount, u16 did) +static void rio_set_device_id(struct rio_mport *port, u16 destid, u8 hopcount, u16 did) { rio_mport_write_config_32(port, destid, hopcount, RIO_DID_CSR, RIO_SET_DID(did)); @@ -192,23 +190,9 @@ static int rio_enum_host(struct rio_mport *port) static int rio_device_has_destid(struct rio_mport *port, int src_ops, int dst_ops) { - if (((src_ops & RIO_SRC_OPS_READ) || - (src_ops & RIO_SRC_OPS_WRITE) || - (src_ops & RIO_SRC_OPS_ATOMIC_TST_SWP) || - (src_ops & RIO_SRC_OPS_ATOMIC_INC) || - (src_ops & RIO_SRC_OPS_ATOMIC_DEC) || - (src_ops & RIO_SRC_OPS_ATOMIC_SET) || - (src_ops & RIO_SRC_OPS_ATOMIC_CLR)) && - ((dst_ops & RIO_DST_OPS_READ) || - (dst_ops & RIO_DST_OPS_WRITE) || - (dst_ops & RIO_DST_OPS_ATOMIC_TST_SWP) || - (dst_ops & RIO_DST_OPS_ATOMIC_INC) || - (dst_ops & RIO_DST_OPS_ATOMIC_DEC) || - (dst_ops & RIO_DST_OPS_ATOMIC_SET) || - (dst_ops & RIO_DST_OPS_ATOMIC_CLR))) { - return 1; - } else - return 0; + u32 mask = RIO_OPS_READ | RIO_OPS_WRITE | RIO_OPS_ATOMIC_TST_SWP | RIO_OPS_ATOMIC_INC | RIO_OPS_ATOMIC_DEC | RIO_OPS_ATOMIC_SET | RIO_OPS_ATOMIC_CLR; + + return !!((src_ops | dst_ops) & mask); } /** @@ -383,8 +367,9 @@ static struct rio_dev *rio_setup_device(struct rio_net *net, rdev->dev.release = rio_release_dev; rio_dev_get(rdev); - rdev->dev.dma_mask = (u64 *) 0xffffffff; - rdev->dev.coherent_dma_mask = 0xffffffffULL; + rdev->dma_mask = DMA_32BIT_MASK; + rdev->dev.dma_mask = &rdev->dma_mask; + rdev->dev.coherent_dma_mask = DMA_32BIT_MASK; if ((rdev->pef & RIO_PEF_INB_DOORBELL) && (rdev->dst_ops & RIO_DST_OPS_DOORBELL)) diff --git a/drivers/rapidio/rio.h b/drivers/rapidio/rio.h index f865a68cd3d5..b242cee656e7 100644 --- a/drivers/rapidio/rio.h +++ b/drivers/rapidio/rio.h @@ -26,6 +26,9 @@ extern int rio_disc_mport(struct rio_mport *mport); extern struct device_attribute rio_dev_attrs[]; extern spinlock_t rio_global_list_lock; +extern struct rio_route_ops __start_rio_route_ops[]; +extern struct rio_route_ops __end_rio_route_ops[]; + /* Helpers internal to the RIO core code */ #define DECLARE_RIO_ROUTE_SECTION(section, vid, did, add_hook, get_hook) \ static struct rio_route_ops __rio_route_ops __attribute_used__ \ diff --git a/include/linux/rio.h b/include/linux/rio.h index 930bbb7c3802..5c29f2f477c2 100644 --- a/include/linux/rio.h +++ b/include/linux/rio.h @@ -91,6 +91,7 @@ struct rio_mport; * @swpinfo: Switch port info * @src_ops: Source operation capabilities * @dst_ops: Destination operation capabilities + * @dma_mask: Mask of bits of RIO address this device implements * @rswitch: Pointer to &struct rio_switch if valid for this device * @driver: Driver claiming this device * @dev: Device model device @@ -112,6 +113,7 @@ struct rio_dev { u32 swpinfo; /* Only used for switches */ u32 src_ops; u32 dst_ops; + u64 dma_mask; struct rio_switch *rswitch; /* RIO switch info */ struct rio_driver *driver; /* RIO driver claiming this device */ struct device dev; /* LDM device structure */ diff --git a/include/linux/rio_regs.h b/include/linux/rio_regs.h index f419be3be491..326540f9b54e 100644 --- a/include/linux/rio_regs.h +++ b/include/linux/rio_regs.h @@ -78,6 +78,19 @@ #define RIO_DST_OPS_ATOMIC_CLR 0x00000010 /* [I] Atomic clr op */ #define RIO_DST_OPS_PORT_WRITE 0x00000004 /* [I] Port-write op */ +#define RIO_OPS_READ 0x00008000 /* [I] Read op */ +#define RIO_OPS_WRITE 0x00004000 /* [I] Write op */ +#define RIO_OPS_STREAM_WRITE 0x00002000 /* [I] Str-write op */ +#define RIO_OPS_WRITE_RESPONSE 0x00001000 /* [I] Write/resp op */ +#define RIO_OPS_DATA_MSG 0x00000800 /* [II] Data msg op */ +#define RIO_OPS_DOORBELL 0x00000400 /* [II] Doorbell op */ +#define RIO_OPS_ATOMIC_TST_SWP 0x00000100 /* [I] Atomic TAS op */ +#define RIO_OPS_ATOMIC_INC 0x00000080 /* [I] Atomic inc op */ +#define RIO_OPS_ATOMIC_DEC 0x00000040 /* [I] Atomic dec op */ +#define RIO_OPS_ATOMIC_SET 0x00000020 /* [I] Atomic set op */ +#define RIO_OPS_ATOMIC_CLR 0x00000010 /* [I] Atomic clr op */ +#define RIO_OPS_PORT_WRITE 0x00000004 /* [I] Port-write op */ + /* 0x20-0x3c *//* Reserved */ #define RIO_MBOX_CSR 0x40 /* [II] Mailbox CSR */ -- cgit v1.2.3 From 6978bbc097c2f665c336927a9d56ae39ef75fa56 Mon Sep 17 00:00:00 2001 From: Matt Porter Date: Mon, 7 Nov 2005 01:00:20 -0800 Subject: [PATCH] rapidio: message interface updates Updates the RIO messaging interface to pass a device instance into the event registeration and callbacks. Signed-off-by: Matt Porter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ppc/syslib/ppc85xx_rio.c | 16 +++++++++++----- drivers/rapidio/rio-sysfs.c | 4 ++-- drivers/rapidio/rio.c | 25 ++++++++++++++++--------- include/linux/rio.h | 10 ++++++---- include/linux/rio_drv.h | 12 ++++++------ 5 files changed, 41 insertions(+), 26 deletions(-) (limited to 'include/linux') diff --git a/arch/ppc/syslib/ppc85xx_rio.c b/arch/ppc/syslib/ppc85xx_rio.c index 9d09c2715e0a..297f3b549177 100644 --- a/arch/ppc/syslib/ppc85xx_rio.c +++ b/arch/ppc/syslib/ppc85xx_rio.c @@ -135,6 +135,7 @@ static struct rio_msg_tx_ring { dma_addr_t phys_buffer[RIO_MAX_TX_RING_SIZE]; int tx_slot; int size; + void *dev_id; } msg_tx_ring; static struct rio_msg_rx_ring { @@ -143,6 +144,7 @@ static struct rio_msg_rx_ring { void *virt_buffer[RIO_MAX_RX_RING_SIZE]; int rx_slot; int size; + void *dev_id; } msg_rx_ring; /** @@ -376,7 +378,7 @@ mpc85xx_rio_tx_handler(int irq, void *dev_instance, struct pt_regs *regs) if (osr & RIO_MSG_OSR_EOMI) { u32 dqp = in_be32((void *)&msg_regs->odqdpar); int slot = (dqp - msg_tx_ring.phys) >> 5; - port->outb_msg[0].mcback(port, -1, slot); + port->outb_msg[0].mcback(port, msg_tx_ring.dev_id, -1, slot); /* Ack the end-of-message interrupt */ out_be32((void *)&msg_regs->osr, RIO_MSG_OSR_EOMI); @@ -389,6 +391,7 @@ mpc85xx_rio_tx_handler(int irq, void *dev_instance, struct pt_regs *regs) /** * rio_open_outb_mbox - Initialize MPC85xx outbound mailbox * @mport: Master port implementing the outbound message unit + * @dev_id: Device specific pointer to pass on event * @mbox: Mailbox to open * @entries: Number of entries in the outbound mailbox ring * @@ -396,7 +399,7 @@ mpc85xx_rio_tx_handler(int irq, void *dev_instance, struct pt_regs *regs) * and enables the outbound message unit. Returns %0 on success and * %-EINVAL or %-ENOMEM on failure. */ -int rio_open_outb_mbox(struct rio_mport *mport, int mbox, int entries) +int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) { int i, j, rc = 0; @@ -407,6 +410,7 @@ int rio_open_outb_mbox(struct rio_mport *mport, int mbox, int entries) } /* Initialize shadow copy ring */ + msg_tx_ring.dev_id = dev_id; msg_tx_ring.size = entries; for (i = 0; i < msg_tx_ring.size; i++) { @@ -541,7 +545,7 @@ mpc85xx_rio_rx_handler(int irq, void *dev_instance, struct pt_regs *regs) * make the callback with an unknown/invalid mailbox number * argument. */ - port->inb_msg[0].mcback(port, -1, -1); + port->inb_msg[0].mcback(port, msg_rx_ring.dev_id, -1, -1); /* Ack the queueing interrupt */ out_be32((void *)&msg_regs->isr, RIO_MSG_ISR_DIQI); @@ -554,6 +558,7 @@ mpc85xx_rio_rx_handler(int irq, void *dev_instance, struct pt_regs *regs) /** * rio_open_inb_mbox - Initialize MPC85xx inbound mailbox * @mport: Master port implementing the inbound message unit + * @dev_id: Device specific pointer to pass on event * @mbox: Mailbox to open * @entries: Number of entries in the inbound mailbox ring * @@ -561,7 +566,7 @@ mpc85xx_rio_rx_handler(int irq, void *dev_instance, struct pt_regs *regs) * and enables the inbound message unit. Returns %0 on success * and %-EINVAL or %-ENOMEM on failure. */ -int rio_open_inb_mbox(struct rio_mport *mport, int mbox, int entries) +int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries) { int i, rc = 0; @@ -572,6 +577,7 @@ int rio_open_inb_mbox(struct rio_mport *mport, int mbox, int entries) } /* Initialize client buffer ring */ + msg_rx_ring.dev_id = dev_id; msg_rx_ring.size = entries; msg_rx_ring.rx_slot = 0; for (i = 0; i < msg_rx_ring.size; i++) @@ -777,7 +783,7 @@ mpc85xx_rio_dbell_handler(int irq, void *dev_instance, struct pt_regs *regs) } } if (found) { - dbell->dinb(port, DBELL_SID(dmsg), DBELL_TID(dmsg), + dbell->dinb(port, dbell->dev_id, DBELL_SID(dmsg), DBELL_TID(dmsg), DBELL_INF(dmsg)); } else { pr_debug diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c index 73218a37506d..30a11436e241 100644 --- a/drivers/rapidio/rio-sysfs.c +++ b/drivers/rapidio/rio-sysfs.c @@ -21,7 +21,7 @@ /* Sysfs support */ #define rio_config_attr(field, format_string) \ static ssize_t \ - field##_show(struct device *dev, char *buf) \ +field##_show(struct device *dev, struct device_attribute *attr, char *buf) \ { \ struct rio_dev *rdev = to_rio_dev(dev); \ \ @@ -35,7 +35,7 @@ rio_config_attr(asm_did, "0x%04x\n"); rio_config_attr(asm_vid, "0x%04x\n"); rio_config_attr(asm_rev, "0x%04x\n"); -static ssize_t routes_show(struct device *dev, char *buf) +static ssize_t routes_show(struct device *dev, struct device_attribute *attr, char *buf) { struct rio_dev *rdev = to_rio_dev(dev); char *str = buf; diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c index adc299e2b07e..3ca1011ceaac 100644 --- a/drivers/rapidio/rio.c +++ b/drivers/rapidio/rio.c @@ -48,6 +48,7 @@ u16 rio_local_get_device_id(struct rio_mport *port) /** * rio_request_inb_mbox - request inbound mailbox service * @mport: RIO master port from which to allocate the mailbox resource + * @dev_id: Device specific pointer to pass on event * @mbox: Mailbox number to claim * @entries: Number of entries in inbound mailbox queue * @minb: Callback to execute when inbound message is received @@ -56,9 +57,10 @@ u16 rio_local_get_device_id(struct rio_mport *port) * a callback function to the resource. Returns %0 on success. */ int rio_request_inb_mbox(struct rio_mport *mport, + void *dev_id, int mbox, int entries, - void (*minb) (struct rio_mport * mport, int mbox, + void (*minb) (struct rio_mport * mport, void *dev_id, int mbox, int slot)) { int rc = 0; @@ -81,7 +83,7 @@ int rio_request_inb_mbox(struct rio_mport *mport, /* Hook the inbound message callback */ mport->inb_msg[mbox].mcback = minb; - rc = rio_open_inb_mbox(mport, mbox, entries); + rc = rio_open_inb_mbox(mport, dev_id, mbox, entries); } else rc = -ENOMEM; @@ -108,6 +110,7 @@ int rio_release_inb_mbox(struct rio_mport *mport, int mbox) /** * rio_request_outb_mbox - request outbound mailbox service * @mport: RIO master port from which to allocate the mailbox resource + * @dev_id: Device specific pointer to pass on event * @mbox: Mailbox number to claim * @entries: Number of entries in outbound mailbox queue * @moutb: Callback to execute when outbound message is sent @@ -116,10 +119,10 @@ int rio_release_inb_mbox(struct rio_mport *mport, int mbox) * a callback function to the resource. Returns 0 on success. */ int rio_request_outb_mbox(struct rio_mport *mport, + void *dev_id, int mbox, int entries, - void (*moutb) (struct rio_mport * mport, int mbox, - int slot)) + void (*moutb) (struct rio_mport * mport, void *dev_id, int mbox, int slot)) { int rc = 0; @@ -141,7 +144,7 @@ int rio_request_outb_mbox(struct rio_mport *mport, /* Hook the inbound message callback */ mport->outb_msg[mbox].mcback = moutb; - rc = rio_open_outb_mbox(mport, mbox, entries); + rc = rio_open_outb_mbox(mport, dev_id, mbox, entries); } else rc = -ENOMEM; @@ -168,6 +171,7 @@ int rio_release_outb_mbox(struct rio_mport *mport, int mbox) /** * rio_setup_inb_dbell - bind inbound doorbell callback * @mport: RIO master port to bind the doorbell callback + * @dev_id: Device specific pointer to pass on event * @res: Doorbell message resource * @dinb: Callback to execute when doorbell is received * @@ -176,8 +180,8 @@ int rio_release_outb_mbox(struct rio_mport *mport, int mbox) * satisfied. */ static int -rio_setup_inb_dbell(struct rio_mport *mport, struct resource *res, - void (*dinb) (struct rio_mport * mport, u16 src, u16 dst, +rio_setup_inb_dbell(struct rio_mport *mport, void *dev_id, struct resource *res, + void (*dinb) (struct rio_mport * mport, void *dev_id, u16 src, u16 dst, u16 info)) { int rc = 0; @@ -190,6 +194,7 @@ rio_setup_inb_dbell(struct rio_mport *mport, struct resource *res, dbell->res = res; dbell->dinb = dinb; + dbell->dev_id = dev_id; list_add_tail(&dbell->node, &mport->dbells); @@ -200,6 +205,7 @@ rio_setup_inb_dbell(struct rio_mport *mport, struct resource *res, /** * rio_request_inb_dbell - request inbound doorbell message service * @mport: RIO master port from which to allocate the doorbell resource + * @dev_id: Device specific pointer to pass on event * @start: Doorbell info range start * @end: Doorbell info range end * @dinb: Callback to execute when doorbell is received @@ -209,9 +215,10 @@ rio_setup_inb_dbell(struct rio_mport *mport, struct resource *res, * has been satisfied. */ int rio_request_inb_dbell(struct rio_mport *mport, + void *dev_id, u16 start, u16 end, - void (*dinb) (struct rio_mport * mport, u16 src, + void (*dinb) (struct rio_mport * mport, void *dev_id, u16 src, u16 dst, u16 info)) { int rc = 0; @@ -230,7 +237,7 @@ int rio_request_inb_dbell(struct rio_mport *mport, } /* Hook the doorbell callback */ - rc = rio_setup_inb_dbell(mport, res, dinb); + rc = rio_setup_inb_dbell(mport, dev_id, res, dinb); } else rc = -ENOMEM; diff --git a/include/linux/rio.h b/include/linux/rio.h index 5c29f2f477c2..c7e907faae9c 100644 --- a/include/linux/rio.h +++ b/include/linux/rio.h @@ -132,7 +132,7 @@ struct rio_dev { */ struct rio_msg { struct resource *res; - void (*mcback) (struct rio_mport * mport, int mbox, int slot); + void (*mcback) (struct rio_mport * mport, void *dev_id, int mbox, int slot); }; /** @@ -140,11 +140,13 @@ struct rio_msg { * @node: Node in list of doorbell events * @res: Doorbell resource * @dinb: Doorbell event callback + * @dev_id: Device specific pointer to pass on event */ struct rio_dbell { struct list_head node; struct resource *res; - void (*dinb) (struct rio_mport * mport, u16 src, u16 dst, u16 info); + void (*dinb) (struct rio_mport *mport, void *dev_id, u16 src, u16 dst, u16 info); + void *dev_id; }; /** @@ -314,9 +316,9 @@ extern int rio_hw_add_outb_message(struct rio_mport *, struct rio_dev *, int, void *, size_t); extern int rio_hw_add_inb_buffer(struct rio_mport *, int, void *); extern void *rio_hw_get_inb_message(struct rio_mport *, int); -extern int rio_open_inb_mbox(struct rio_mport *, int, int); +extern int rio_open_inb_mbox(struct rio_mport *, void *, int, int); extern void rio_close_inb_mbox(struct rio_mport *, int); -extern int rio_open_outb_mbox(struct rio_mport *, int, int); +extern int rio_open_outb_mbox(struct rio_mport *, void *, int, int); extern void rio_close_outb_mbox(struct rio_mport *, int); #endif /* __KERNEL__ */ diff --git a/include/linux/rio_drv.h b/include/linux/rio_drv.h index 7483dfc0dfa3..3bd7cce19e26 100644 --- a/include/linux/rio_drv.h +++ b/include/linux/rio_drv.h @@ -348,8 +348,8 @@ static inline void rio_init_dbell_res(struct resource *res, u16 start, u16 end) .asm_did = RIO_ANY_ID, .asm_vid = RIO_ANY_ID /* Mailbox management */ -extern int rio_request_outb_mbox(struct rio_mport *, int, int, - void (*)(struct rio_mport *, int, int)); +extern int rio_request_outb_mbox(struct rio_mport *, void *, int, int, + void (*)(struct rio_mport *, void *,int, int)); extern int rio_release_outb_mbox(struct rio_mport *, int); /** @@ -370,8 +370,8 @@ static inline int rio_add_outb_message(struct rio_mport *mport, return rio_hw_add_outb_message(mport, rdev, mbox, buffer, len); } -extern int rio_request_inb_mbox(struct rio_mport *, int, int, - void (*)(struct rio_mport *, int, int)); +extern int rio_request_inb_mbox(struct rio_mport *, void *, int, int, + void (*)(struct rio_mport *, void *, int, int)); extern int rio_release_inb_mbox(struct rio_mport *, int); /** @@ -403,8 +403,8 @@ static inline void *rio_get_inb_message(struct rio_mport *mport, int mbox) } /* Doorbell management */ -extern int rio_request_inb_dbell(struct rio_mport *, u16, u16, - void (*)(struct rio_mport *, u16, u16, u16)); +extern int rio_request_inb_dbell(struct rio_mport *, void *, u16, u16, + void (*)(struct rio_mport *, void *, u16, u16, u16)); extern int rio_release_inb_dbell(struct rio_mport *, u16, u16); extern struct resource *rio_request_outb_dbell(struct rio_dev *, u16, u16); extern int rio_release_outb_dbell(struct rio_dev *, struct resource *); -- cgit v1.2.3 From 70c3b76c28b012452d63bb27f6d0517afb05d86f Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 7 Nov 2005 01:00:25 -0800 Subject: [PATCH] knfsd: Allow run-time selection of NFS versions to export Provide a file in the NFSD filesystem that allows setting and querying of which version of NFS are being exported. Changes are only allowed while no server is running. Signed-off-by: Steve Dickson Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfsd/nfsctl.c | 82 ++++++++++++++++++++++++++++++++++++++++++++ fs/nfsd/nfssvc.c | 79 +++++++++++++++++++++++++++--------------- include/linux/nfsd/nfsd.h | 2 +- include/linux/nfsd/syscall.h | 17 +++++++++ 4 files changed, 151 insertions(+), 29 deletions(-) (limited to 'include/linux') diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 2a99a0bf54f6..a0871b3efeb7 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -35,6 +36,8 @@ #include +unsigned int nfsd_versbits = ~0; + /* * We have a single directory with 9 nodes in it. */ @@ -50,8 +53,15 @@ enum { NFSD_List, NFSD_Fh, NFSD_Threads, + NFSD_Versions, + /* + * The below MUST come last. Otherwise we leave a hole in nfsd_files[] + * with !CONFIG_NFSD_V4 and simple_fill_super() goes oops + */ +#ifdef CONFIG_NFSD_V4 NFSD_Leasetime, NFSD_RecoveryDir, +#endif }; /* @@ -66,8 +76,11 @@ static ssize_t write_getfd(struct file *file, char *buf, size_t size); static ssize_t write_getfs(struct file *file, char *buf, size_t size); static ssize_t write_filehandle(struct file *file, char *buf, size_t size); static ssize_t write_threads(struct file *file, char *buf, size_t size); +static ssize_t write_versions(struct file *file, char *buf, size_t size); +#ifdef CONFIG_NFSD_V4 static ssize_t write_leasetime(struct file *file, char *buf, size_t size); static ssize_t write_recoverydir(struct file *file, char *buf, size_t size); +#endif static ssize_t (*write_op[])(struct file *, char *, size_t) = { [NFSD_Svc] = write_svc, @@ -79,8 +92,11 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = { [NFSD_Getfs] = write_getfs, [NFSD_Fh] = write_filehandle, [NFSD_Threads] = write_threads, + [NFSD_Versions] = write_versions, +#ifdef CONFIG_NFSD_V4 [NFSD_Leasetime] = write_leasetime, [NFSD_RecoveryDir] = write_recoverydir, +#endif }; static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) @@ -343,6 +359,70 @@ static ssize_t write_threads(struct file *file, char *buf, size_t size) return strlen(buf); } +static ssize_t write_versions(struct file *file, char *buf, size_t size) +{ + /* + * Format: + * [-/+]vers [-/+]vers ... + */ + char *mesg = buf; + char *vers, sign; + int len, num; + ssize_t tlen = 0; + char *sep; + + if (size>0) { + if (nfsd_serv) + return -EBUSY; + if (buf[size-1] != '\n') + return -EINVAL; + buf[size-1] = 0; + + vers = mesg; + len = qword_get(&mesg, vers, size); + if (len <= 0) return -EINVAL; + do { + sign = *vers; + if (sign == '+' || sign == '-') + num = simple_strtol((vers+1), NULL, 0); + else + num = simple_strtol(vers, NULL, 0); + switch(num) { + case 2: + case 3: + case 4: + if (sign != '-') + NFSCTL_VERSET(nfsd_versbits, num); + else + NFSCTL_VERUNSET(nfsd_versbits, num); + break; + default: + return -EINVAL; + } + vers += len + 1; + tlen += len; + } while ((len = qword_get(&mesg, vers, size)) > 0); + /* If all get turned off, turn them back on, as + * having no versions is BAD + */ + if ((nfsd_versbits & NFSCTL_VERALL)==0) + nfsd_versbits = NFSCTL_VERALL; + } + /* Now write current state into reply buffer */ + len = 0; + sep = ""; + for (num=2 ; num <= 4 ; num++) + if (NFSCTL_VERISSET(NFSCTL_VERALL, num)) { + len += sprintf(buf+len, "%s%c%d", sep, + NFSCTL_VERISSET(nfsd_versbits, num)?'+':'-', + num); + sep = " "; + } + len += sprintf(buf+len, "\n"); + return len; +} + +#ifdef CONFIG_NFSD_V4 extern time_t nfs4_leasetime(void); static ssize_t write_leasetime(struct file *file, char *buf, size_t size) @@ -384,6 +464,7 @@ static ssize_t write_recoverydir(struct file *file, char *buf, size_t size) status = nfs4_reset_recoverydir(recdir); return strlen(buf); } +#endif /*----------------------------------------------------------------------------*/ /* @@ -403,6 +484,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent) [NFSD_List] = {"exports", &exports_operations, S_IRUGO}, [NFSD_Fh] = {"filehandle", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR}, + [NFSD_Versions] = {"versions", &transaction_ops, S_IWUSR|S_IRUSR}, #ifdef CONFIG_NFSD_V4 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR}, diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index 1697539a7171..0568ff8565b1 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -52,7 +53,7 @@ extern struct svc_program nfsd_program; static void nfsd(struct svc_rqst *rqstp); struct timeval nfssvc_boot; -static struct svc_serv *nfsd_serv; + struct svc_serv *nfsd_serv; static atomic_t nfsd_busy; static unsigned long nfsd_last_call; static DEFINE_SPINLOCK(nfsd_call_lock); @@ -63,6 +64,31 @@ struct nfsd_list { }; static struct list_head nfsd_list = LIST_HEAD_INIT(nfsd_list); +static struct svc_version * nfsd_version[] = { + [2] = &nfsd_version2, +#if defined(CONFIG_NFSD_V3) + [3] = &nfsd_version3, +#endif +#if defined(CONFIG_NFSD_V4) + [4] = &nfsd_version4, +#endif +}; + +#define NFSD_MINVERS 2 +#define NFSD_NRVERS (sizeof(nfsd_version)/sizeof(nfsd_version[0])) +static struct svc_version *nfsd_versions[NFSD_NRVERS]; + +struct svc_program nfsd_program = { + .pg_prog = NFS_PROGRAM, /* program number */ + .pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */ + .pg_vers = nfsd_versions, /* version table */ + .pg_name = "nfsd", /* program name */ + .pg_class = "nfsd", /* authentication class */ + .pg_stats = &nfsd_svcstats, /* version table */ + .pg_authenticate = &svc_set_client, /* export authentication */ + +}; + /* * Maximum number of nfsd processes */ @@ -80,11 +106,12 @@ int nfsd_svc(unsigned short port, int nrservs) { int error; - int none_left; + int none_left, found_one, i; struct list_head *victim; lock_kernel(); - dprintk("nfsd: creating service\n"); + dprintk("nfsd: creating service: vers 0x%x\n", + nfsd_versbits); error = -EINVAL; if (nrservs <= 0) nrservs = 0; @@ -99,6 +126,27 @@ nfsd_svc(unsigned short port, int nrservs) if (error<0) goto out; if (!nfsd_serv) { + /* + * Use the nfsd_ctlbits to define which + * versions that will be advertised. + * If nfsd_ctlbits doesn't list any version, + * export them all. + */ + found_one = 0; + + for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) { + if (NFSCTL_VERISSET(nfsd_versbits, i)) { + nfsd_program.pg_vers[i] = nfsd_version[i]; + found_one = 1; + } else + nfsd_program.pg_vers[i] = NULL; + } + + if (!found_one) { + for (i = NFSD_MINVERS; i < NFSD_NRVERS; i++) + nfsd_program.pg_vers[i] = nfsd_version[i]; + } + atomic_set(&nfsd_busy, 0); error = -ENOMEM; nfsd_serv = svc_create(&nfsd_program, NFSD_BUFSIZE); @@ -389,28 +437,3 @@ static struct svc_stat nfsd_acl_svcstats = { #else #define nfsd_acl_program_p NULL #endif /* defined(CONFIG_NFSD_V2_ACL) || defined(CONFIG_NFSD_V3_ACL) */ - -extern struct svc_version nfsd_version2, nfsd_version3, nfsd_version4; - -static struct svc_version * nfsd_version[] = { - [2] = &nfsd_version2, -#if defined(CONFIG_NFSD_V3) - [3] = &nfsd_version3, -#endif -#if defined(CONFIG_NFSD_V4) - [4] = &nfsd_version4, -#endif -}; - -#define NFSD_NRVERS (sizeof(nfsd_version)/sizeof(nfsd_version[0])) -struct svc_program nfsd_program = { - .pg_next = nfsd_acl_program_p, - .pg_prog = NFS_PROGRAM, /* program number */ - .pg_nvers = NFSD_NRVERS, /* nr of entries in nfsd_version */ - .pg_vers = nfsd_version, /* version table */ - .pg_name = "nfsd", /* program name */ - .pg_class = "nfsd", /* authentication class */ - .pg_stats = &nfsd_svcstats, /* version table */ - .pg_authenticate = &svc_set_client, /* export authentication */ - -}; diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h index 6d5a24f3fc6d..51c231a1e5a6 100644 --- a/include/linux/nfsd/nfsd.h +++ b/include/linux/nfsd/nfsd.h @@ -60,7 +60,7 @@ typedef int (*nfsd_dirop_t)(struct inode *, struct dentry *, int, int); extern struct svc_program nfsd_program; extern struct svc_version nfsd_version2, nfsd_version3, nfsd_version4; - +extern struct svc_serv *nfsd_serv; /* * Function prototypes. */ diff --git a/include/linux/nfsd/syscall.h b/include/linux/nfsd/syscall.h index e65c9db6d13f..781efbf94ed3 100644 --- a/include/linux/nfsd/syscall.h +++ b/include/linux/nfsd/syscall.h @@ -39,6 +39,21 @@ #define NFSCTL_GETFD 7 /* get an fh by path (used by mountd) */ #define NFSCTL_GETFS 8 /* get an fh by path with max FH len */ +/* + * Macros used to set version + */ +#define NFSCTL_VERSET(_cltbits, _v) ((_cltbits) |= (1 << (_v))) +#define NFSCTL_VERUNSET(_cltbits, _v) ((_cltbits) &= ~(1 << (_v))) +#define NFSCTL_VERISSET(_cltbits, _v) ((_cltbits) & (1 << (_v))) + +#if defined(CONFIG_NFSD_V4) +#define NFSCTL_VERALL (0x1c /* 0b011100 */) +#elif defined(CONFIG_NFSD_V3) +#define NFSCTL_VERALL (0x0c /* 0b001100 */) +#else +#define NFSCTL_VERALL (0x04 /* 0b000100 */) +#endif + /* SVC */ struct nfsctl_svc { unsigned short svc_port; @@ -120,6 +135,8 @@ extern int exp_delclient(struct nfsctl_client *ncp); extern int exp_export(struct nfsctl_export *nxp); extern int exp_unexport(struct nfsctl_export *nxp); +extern unsigned int nfsd_versbits; + #endif /* __KERNEL__ */ #endif /* NFSD_SYSCALL_H */ -- cgit v1.2.3 From 0ba7536d5d47e4ecf2259a80b207158dc4e711eb Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 7 Nov 2005 01:00:26 -0800 Subject: [PATCH] knfsd: Fix some minor sign problems in nfsd/xdr There are a couple of tests which could possibly be confused by extremely large numbers appearing in 'xdr' packets. I think the closest to an exploit you could get would be writing random data from a free page into a file - i.e. leak data out of kernel space. I'm fairly sure they cannot be used for remote compromise. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfsd/nfs3xdr.c | 3 ++- include/linux/nfsd/xdr3.h | 2 +- include/linux/sunrpc/svc.h | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index e0e134d6baba..9147b8524d05 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c @@ -366,7 +366,8 @@ nfs3svc_decode_writeargs(struct svc_rqst *rqstp, u32 *p, len = args->len = ntohl(*p++); hdr = (void*)p - rqstp->rq_arg.head[0].iov_base; - if (rqstp->rq_arg.len < len + hdr) + if (rqstp->rq_arg.len < hdr || + rqstp->rq_arg.len - hdr < len) return 0; args->vec[0].iov_base = (void*)p; diff --git a/include/linux/nfsd/xdr3.h b/include/linux/nfsd/xdr3.h index 21e18ce7ca63..3c2a71b43bac 100644 --- a/include/linux/nfsd/xdr3.h +++ b/include/linux/nfsd/xdr3.h @@ -42,7 +42,7 @@ struct nfsd3_writeargs { __u64 offset; __u32 count; int stable; - int len; + __u32 len; struct kvec vec[RPCSVC_MAXPAGES]; int vlen; }; diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 5af8800e0ce3..e4086ec8b952 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -171,7 +171,8 @@ xdr_argsize_check(struct svc_rqst *rqstp, u32 *p) { char *cp = (char *)p; struct kvec *vec = &rqstp->rq_arg.head[0]; - return cp - (char*)vec->iov_base <= vec->iov_len; + return cp >= (char*)vec->iov_base + && cp <= (char*)vec->iov_base + vec->iov_len; } static inline int -- cgit v1.2.3 From c465e05a03209651078b95686158648fd7ed84c5 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 7 Nov 2005 01:00:35 -0800 Subject: [PATCH] fbcon/fbdev: Move softcursor out of fbdev to fbcon According to Jon Smirl, filling in the field fb_cursor with soft_cursor for drivers that do not support hardware cursors is redundant. The soft_cursor function is usable by all drivers because it is just a wrapper around fb_imageblit. And because soft_cursor is an fbcon-specific hook, the file is moved to the console directory. Thus, drivers that do not support hardware cursors can leave the fb_cursor field blank. For drivers that do, they can fill up this field with their own version. The end result is a smaller code size. And if the framebuffer console is not loaded, module/kernel size is also reduced because the soft_cursor module will also not be loaded. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/68328fb.c | 1 - drivers/video/Kconfig | 79 ---------------------------------- drivers/video/Makefile | 1 - drivers/video/acornfb.c | 1 - drivers/video/amba-clcd.c | 1 - drivers/video/amifb.c | 1 - drivers/video/arcfb.c | 1 - drivers/video/asiliantfb.c | 1 - drivers/video/aty/aty128fb.c | 1 - drivers/video/aty/atyfb_base.c | 1 - drivers/video/aty/radeon_base.c | 1 - drivers/video/bw2.c | 1 - drivers/video/cg14.c | 1 - drivers/video/cg3.c | 1 - drivers/video/cg6.c | 1 - drivers/video/chipsfb.c | 1 - drivers/video/cirrusfb.c | 1 - drivers/video/clps711xfb.c | 1 - drivers/video/console/Makefile | 2 +- drivers/video/console/bitblit.c | 7 ++- drivers/video/console/fbcon.h | 2 +- drivers/video/console/softcursor.c | 72 +++++++++++++++++++++++++++++++ drivers/video/controlfb.c | 1 - drivers/video/cyber2000fb.c | 1 - drivers/video/cyblafb.c | 1 - drivers/video/dnfb.c | 1 - drivers/video/epson1355fb.c | 1 - drivers/video/ffb.c | 3 -- drivers/video/fm2fb.c | 1 - drivers/video/gbefb.c | 1 - drivers/video/geode/Kconfig | 1 - drivers/video/geode/gx1fb_core.c | 1 - drivers/video/hitfb.c | 1 - drivers/video/hpfb.c | 1 - drivers/video/imsttfb.c | 1 - drivers/video/imxfb.c | 1 - drivers/video/intelfb/intelfbdrv.c | 2 +- drivers/video/kyro/fbdev.c | 1 - drivers/video/leo.c | 1 - drivers/video/macfb.c | 1 - drivers/video/matrox/matroxfb_accel.c | 2 +- drivers/video/matrox/matroxfb_crtc2.c | 1 - drivers/video/maxinefb.c | 1 - drivers/video/neofb.c | 1 - drivers/video/nvidia/nvidia.c | 2 +- drivers/video/offb.c | 1 - drivers/video/p9100.c | 1 - drivers/video/platinumfb.c | 1 - drivers/video/pm2fb.c | 1 - drivers/video/pmag-ba-fb.c | 1 - drivers/video/pmagb-b-fb.c | 1 - drivers/video/pvr2fb.c | 1 - drivers/video/pxafb.c | 1 - drivers/video/q40fb.c | 1 - drivers/video/radeonfb.c | 1 - drivers/video/s1d13xxxfb.c | 1 - drivers/video/s3c2410fb.c | 1 - drivers/video/sa1100fb.c | 1 - drivers/video/savage/savagefb_driver.c | 1 - drivers/video/sgivwfb.c | 1 - drivers/video/sis/sis_main.c | 2 + drivers/video/skeletonfb.c | 9 ++-- drivers/video/softcursor.c | 72 ------------------------------- drivers/video/sstfb.c | 1 - drivers/video/stifb.c | 1 - drivers/video/tcx.c | 1 - drivers/video/tdfxfb.c | 1 - drivers/video/tgafb.c | 1 - drivers/video/tridentfb.c | 1 - drivers/video/tx3912fb.c | 1 - drivers/video/valkyriefb.c | 1 - drivers/video/vesafb.c | 1 - drivers/video/vfb.c | 1 - drivers/video/vga16fb.c | 1 - drivers/video/w100fb.c | 1 - include/linux/fb.h | 1 - 76 files changed, 88 insertions(+), 230 deletions(-) create mode 100644 drivers/video/console/softcursor.c delete mode 100644 drivers/video/softcursor.c (limited to 'include/linux') diff --git a/drivers/video/68328fb.c b/drivers/video/68328fb.c index 6a3cfbdc6dc9..3b0ddc55236b 100644 --- a/drivers/video/68328fb.c +++ b/drivers/video/68328fb.c @@ -113,7 +113,6 @@ static struct fb_ops mc68x328fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_mmap = mc68x328fb_mmap, }; diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 9c54695911c1..44b6ca290ce3 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -65,15 +65,6 @@ config FB_CFB_IMAGEBLIT blitting. This is used by drivers that don't provide their own (accelerated) version. -config FB_SOFT_CURSOR - tristate - depends on FB - default n - ---help--- - Include the soft_cursor function for generic software cursor support. - This is used by drivers that don't provide their own (accelerated) - version. - config FB_MACMODES tristate depends on FB @@ -114,7 +105,6 @@ config FB_CIRRUS select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- This enables support for Cirrus Logic GD542x/543x based boards on Amiga: SD64, Piccolo, Picasso II/II+, Picasso IV, or EGS Spectrum. @@ -133,7 +123,6 @@ config FB_PM2 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the Permedia2 AGP frame buffer card from ASK, aka `Graphic Blaster Exxtreme'. There is a @@ -152,7 +141,6 @@ config FB_ARMCLCD select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This framebuffer device driver is for the ARM PrimeCell PL110 Colour LCD controller. ARM PrimeCells provide the building @@ -169,7 +157,6 @@ config FB_ACORN select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the Acorn VIDC graphics hardware found in Acorn RISC PCs and other ARM-based machines. If @@ -181,7 +168,6 @@ config FB_CLPS711X select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Say Y to enable the Framebuffer driver for the CLPS7111 and EP7212 processors. @@ -192,7 +178,6 @@ config FB_SA1100 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is a framebuffer device for the SA-1100 LCD Controller. See for information on framebuffer @@ -207,7 +192,6 @@ config FB_IMX select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR config FB_CYBER2000 tristate "CyberPro 2000/2010/5000 support" @@ -215,7 +199,6 @@ config FB_CYBER2000 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This enables support for the Integraphics CyberPro 20x0 and 5000 VGA chips used in the Rebel.com Netwinder and other machines. @@ -228,7 +211,6 @@ config FB_APOLLO default y select FB_CFB_FILLRECT select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR config FB_Q40 bool @@ -237,12 +219,10 @@ config FB_Q40 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR config FB_AMIGA tristate "Amiga native chipset support" depends on FB && AMIGA - select FB_SOFT_CURSOR help This is the frame buffer device driver for the builtin graphics chipset found in Amigas. @@ -282,7 +262,6 @@ config FB_CYBER select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This enables support for the Cybervision 64 graphics card from Phase5. Please note that its use is not all that intuitive (i.e. if @@ -297,7 +276,6 @@ config FB_VIRGE select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This enables support for the Cybervision 64/3D graphics card from Phase5. Please note that its use is not all that intuitive (i.e. if @@ -320,7 +298,6 @@ config FB_FM2 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the Amiga FrameMaster card from BSC (exhibited 1992 but not shipped as a CBM product). @@ -331,7 +308,6 @@ config FB_ARC select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This enables support for the Arc Monochrome LCD board. The board is based on the KS-108 lcd controller and is typically a matrix @@ -354,7 +330,6 @@ config FB_OF select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES help Say Y if you want support with Open Firmware for your graphics @@ -366,7 +341,6 @@ config FB_CONTROL select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES help This driver supports a frame buffer for the graphics adapter in the @@ -378,7 +352,6 @@ config FB_PLATINUM select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES help This driver supports a frame buffer for the "platinum" graphics @@ -390,7 +363,6 @@ config FB_VALKYRIE select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES help This driver supports a frame buffer for the "valkyrie" graphics @@ -402,7 +374,6 @@ config FB_CT65550 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the Chips & Technologies 65550 graphics chip in PowerBooks. @@ -413,13 +384,11 @@ config FB_ASILIANT select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR config FB_IMSTT bool "IMS Twin Turbo display support" depends on (FB = y) && PCI select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES if PPC help The IMS Twin Turbo is a PCI-based frame buffer card bundled with @@ -431,7 +400,6 @@ config FB_VGA16 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for VGA 16 color graphic cards. Say Y if you have such a card. @@ -445,7 +413,6 @@ config FB_STI select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR default y ---help--- STI refers to the HP "Standard Text Interface" which is a set of @@ -466,7 +433,6 @@ config FB_MAC select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES # bool ' Apple DAFB display support' CONFIG_FB_DAFB @@ -475,7 +441,6 @@ config FB_HP300 depends on (FB = y) && HP300 select FB_CFB_FILLRECT select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR default y config FB_TGA @@ -484,7 +449,6 @@ config FB_TGA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for generic TGA graphic cards. Say Y if you have one of those. @@ -495,7 +459,6 @@ config FB_VESA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for generic VESA 2.0 compliant graphic cards. The older VESA 1.2 cards are not supported. @@ -513,7 +476,6 @@ config FB_HGA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Say Y here if you have a Hercules mono graphics card. @@ -542,7 +504,6 @@ config FB_SGIVW select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help SGI Visual Workstation support for framebuffer graphics. @@ -552,7 +513,6 @@ config FB_GBE select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for SGI Graphics Backend. This chip is used in SGI O2 and Visual Workstation 320/540. @@ -580,7 +540,6 @@ config FB_BW2 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the BWtwo frame buffer. @@ -589,7 +548,6 @@ config FB_CG3 depends on (FB = y) && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3) select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the CGthree frame buffer. @@ -598,7 +556,6 @@ config FB_CG6 depends on (FB = y) && ((SPARC32 || SPARC64) && FB_SBUS || (SUN3 || SUN3X) && FB_SUN3) select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the CGsix (GX, TurboGX) frame buffer. @@ -609,7 +566,6 @@ config FB_PVR2 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- Say Y here if you have a PowerVR 2 card in your box. If you plan to run linux on your Dreamcast, you will have to say Y here. @@ -631,7 +587,6 @@ config FB_EPSON1355 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Build in support for the SED1355 Epson Research Embedded RAMDAC LCD/CRT Controller (since redesignated as the S1D13505) as a @@ -676,7 +631,6 @@ config FB_S1D13XXX select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Support for S1D13XXX framebuffer device family (currently only working with S1D13806). Product specs at @@ -691,7 +645,6 @@ config FB_NVIDIA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This driver supports graphics boards with the nVidia chips, TNT and newer. For very old chipsets, such as the RIVA128, then use @@ -809,7 +762,6 @@ config FB_INTEL select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This driver supports the on-board graphics built in to the Intel 830M/845G/852GM/855GM/865G chipsets. @@ -832,7 +784,6 @@ config FB_MATROX select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_TILEBLITTING select FB_MACMODES if PPC_PMAC ---help--- @@ -973,7 +924,6 @@ config FB_RADEON_OLD select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES if PPC help Choose this option if you want to use an ATI Radeon graphics card as @@ -991,7 +941,6 @@ config FB_RADEON select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES if PPC_OF help Choose this option if you want to use an ATI Radeon graphics card as @@ -1029,7 +978,6 @@ config FB_ATY128 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES if PPC_PMAC help This driver supports graphics boards with the ATI Rage128 chips. @@ -1045,7 +993,6 @@ config FB_ATY select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select FB_MACMODES if PPC help This driver supports graphics boards with the ATI Mach64 chips. @@ -1103,7 +1050,6 @@ config FB_SAVAGE select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This driver supports notebooks and computers with S3 Savage PCI/AGP chips. @@ -1140,7 +1086,6 @@ config FB_SIS select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the SiS 300, 315, 330 and 340 series as well as XGI V3XT, V5, V8, Z7 graphics chipsets. @@ -1170,7 +1115,6 @@ config FB_NEOMAGIC select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This driver supports notebooks with NeoMagic PCI chips. Say Y if you have such a graphics card. @@ -1184,7 +1128,6 @@ config FB_KYRO select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Say Y here if you have a STG4000 / Kyro / PowerVR 3 based graphics board. @@ -1198,7 +1141,6 @@ config FB_3DFX select FB_CFB_IMAGEBLIT select FB_CFB_FILLRECT select FB_CFB_COPYAREA - select FB_SOFT_CURSOR help This driver supports graphics boards with the 3Dfx Banshee/Voodoo3 chips. Say Y if you have such a graphics board. @@ -1220,7 +1162,6 @@ config FB_VOODOO1 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- Say Y here if you have a 3Dfx Voodoo Graphics (Voodoo1/sst1) or Voodoo2 (cvg) based graphics card. @@ -1237,7 +1178,6 @@ config FB_CYBLA tristate "Cyberblade/i1 support" depends on FB && PCI select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR select VIDEO_SELECT ---help--- This driver is supposed to support the Trident Cyberblade/i1 @@ -1265,7 +1205,6 @@ config FB_TRIDENT select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- This driver is supposed to support graphics boards with the Trident CyberXXXX/Image/CyberBlade chips mostly found in laptops @@ -1314,7 +1253,6 @@ config FB_FFB depends on FB_SBUS && SPARC64 select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the Creator, Creator3D, and Elite3D graphics boards. @@ -1325,7 +1263,6 @@ config FB_TCX select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the TCX 24/8bit frame buffer. @@ -1336,7 +1273,6 @@ config FB_CG14 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the CGfourteen frame buffer on Desktop SPARCsystems with the SX graphics option. @@ -1347,7 +1283,6 @@ config FB_P9100 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the P9100 card supported on Sparcbook 3 machines. @@ -1358,7 +1293,6 @@ config FB_LEO select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the SBUS-based Sun ZX (leo) frame buffer cards. @@ -1373,7 +1307,6 @@ config FB_IGA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the framebuffer device for the INTERGRAPHICS 1680 and successor frame buffer cards. @@ -1384,7 +1317,6 @@ config FB_HIT select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help This is the frame buffer device driver for the Hitachi HD64461 LCD frame buffer card. @@ -1395,7 +1327,6 @@ config FB_PMAG_AA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Support for the PMAG-AA TURBOchannel framebuffer card (1280x1024x1) used mainly in the MIPS-based DECstation series. @@ -1406,7 +1337,6 @@ config FB_PMAG_BA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Support for the PMAG-BA TURBOchannel framebuffer card (1024x864x8) used mainly in the MIPS-based DECstation series. @@ -1417,7 +1347,6 @@ config FB_PMAGB_B select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Support for the PMAGB-B TURBOchannel framebuffer card used mainly in the MIPS-based DECstation series. The card is currently only @@ -1429,7 +1358,6 @@ config FB_MAXINE select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Support for the onboard framebuffer (1024x768x8) in the Personal DECstation series (Personal DECstation 5000/20, /25, /33, /50, @@ -1441,7 +1369,6 @@ config FB_TX3912 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help The TX3912 is a Toshiba RISC processor based on the MIPS 3900 core see . @@ -1454,7 +1381,6 @@ config FB_G364 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help The G364 driver is the framebuffer used in MIPS Magnum 4000 and Olivetti M700-10 systems. @@ -1465,7 +1391,6 @@ config FB_68328 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR help Say Y here if you want to support the built-in frame buffer of the Motorola 68328 CPU family. @@ -1476,7 +1401,6 @@ config FB_PXA select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- Frame buffer driver for the built-in LCD controller in the Intel PXA2x0 processor. @@ -1511,7 +1435,6 @@ config FB_W100 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- Frame buffer driver for the w100 as found on the Sharp SL-Cxx series. @@ -1528,7 +1451,6 @@ config FB_S3C2410 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- Frame buffer driver for the built-in LCD controller in the Samsung S3C2410 processor. @@ -1552,7 +1474,6 @@ config FB_VIRTUAL select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- This is a `virtual' frame buffer device. It operates on a chunk of unswappable kernel memory instead of on the memory of a graphics diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 97c5d03ac8d9..aa434e725c0d 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -16,7 +16,6 @@ fb-objs := $(fb-y) obj-$(CONFIG_FB_CFB_FILLRECT) += cfbfillrect.o obj-$(CONFIG_FB_CFB_COPYAREA) += cfbcopyarea.o obj-$(CONFIG_FB_CFB_IMAGEBLIT) += cfbimgblt.o -obj-$(CONFIG_FB_SOFT_CURSOR) += softcursor.o obj-$(CONFIG_FB_MACMODES) += macmodes.o # Hardware specific drivers go first diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index 9b6a39348f81..193b482570c7 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c @@ -926,7 +926,6 @@ static struct fb_ops acornfb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_mmap = acornfb_mmap, - .fb_cursor = soft_cursor, }; /* diff --git a/drivers/video/amba-clcd.c b/drivers/video/amba-clcd.c index 4fc93dc2b4d3..467a1d7ebbde 100644 --- a/drivers/video/amba-clcd.c +++ b/drivers/video/amba-clcd.c @@ -333,7 +333,6 @@ static struct fb_ops clcdfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_mmap = clcdfb_mmap, }; diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index cf8bb67462dc..d549e215f3c5 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -1185,7 +1185,6 @@ static struct fb_ops amifb_ops = { .fb_fillrect = amifb_fillrect, .fb_copyarea = amifb_copyarea, .fb_imageblit = amifb_imageblit, - .fb_cursor = soft_cursor, .fb_ioctl = amifb_ioctl, }; diff --git a/drivers/video/arcfb.c b/drivers/video/arcfb.c index 6aa9f824c185..a1fc8bbb1090 100644 --- a/drivers/video/arcfb.c +++ b/drivers/video/arcfb.c @@ -511,7 +511,6 @@ static struct fb_ops arcfb_ops = { .fb_fillrect = arcfb_fillrect, .fb_copyarea = arcfb_copyarea, .fb_imageblit = arcfb_imageblit, - .fb_cursor = soft_cursor, .fb_ioctl = arcfb_ioctl, }; diff --git a/drivers/video/asiliantfb.c b/drivers/video/asiliantfb.c index f4729f4df8ce..c64de59398f4 100644 --- a/drivers/video/asiliantfb.c +++ b/drivers/video/asiliantfb.c @@ -106,7 +106,6 @@ static struct fb_ops asiliantfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* Calculate the ratios for the dot clocks without using a single long long diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index e380ee8b0247..e686185a076d 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -478,7 +478,6 @@ static struct fb_ops aty128fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; #ifdef CONFIG_PMAC_BACKLIGHT diff --git a/drivers/video/aty/atyfb_base.c b/drivers/video/aty/atyfb_base.c index 037fe9d32fe3..5e4523ae85b1 100644 --- a/drivers/video/aty/atyfb_base.c +++ b/drivers/video/aty/atyfb_base.c @@ -292,7 +292,6 @@ static struct fb_ops atyfb_ops = { .fb_fillrect = atyfb_fillrect, .fb_copyarea = atyfb_copyarea, .fb_imageblit = atyfb_imageblit, - .fb_cursor = soft_cursor, #ifdef __sparc__ .fb_mmap = atyfb_mmap, #endif diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 7ef4b901b93e..29f5b2cdbb7a 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -1873,7 +1873,6 @@ static struct fb_ops radeonfb_ops = { .fb_fillrect = radeonfb_fillrect, .fb_copyarea = radeonfb_copyarea, .fb_imageblit = radeonfb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c index 3d20b2d47d46..f53bf3ba1278 100644 --- a/drivers/video/bw2.c +++ b/drivers/video/bw2.c @@ -51,7 +51,6 @@ static struct fb_ops bw2_ops = { .fb_imageblit = cfb_imageblit, .fb_mmap = bw2_mmap, .fb_ioctl = bw2_ioctl, - .fb_cursor = soft_cursor, }; /* OBio addresses for the bwtwo registers */ diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c index 18e60b941e21..030d4b13b1c2 100644 --- a/drivers/video/cg14.c +++ b/drivers/video/cg14.c @@ -49,7 +49,6 @@ static struct fb_ops cg14_ops = { .fb_imageblit = cfb_imageblit, .fb_mmap = cg14_mmap, .fb_ioctl = cg14_ioctl, - .fb_cursor = soft_cursor, }; #define CG14_MCR_INTENABLE_SHIFT 7 diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c index 6e7d8d45dc68..b94eee8c42d5 100644 --- a/drivers/video/cg3.c +++ b/drivers/video/cg3.c @@ -50,7 +50,6 @@ static struct fb_ops cg3_ops = { .fb_imageblit = cfb_imageblit, .fb_mmap = cg3_mmap, .fb_ioctl = cg3_ioctl, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c index 49a2545671d9..3280bb9560e2 100644 --- a/drivers/video/cg6.c +++ b/drivers/video/cg6.c @@ -54,7 +54,6 @@ static struct fb_ops cg6_ops = { .fb_sync = cg6_sync, .fb_mmap = cg6_mmap, .fb_ioctl = cg6_ioctl, - .fb_cursor = soft_cursor, }; /* Offset of interesting structures in the OBIO space */ diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c index 4131243cfdf8..bc061d4ec786 100644 --- a/drivers/video/chipsfb.c +++ b/drivers/video/chipsfb.c @@ -91,7 +91,6 @@ static struct fb_ops chipsfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static int chipsfb_check_var(struct fb_var_screeninfo *var, diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 3a26f9cc8585..2858c5c8ba3c 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -548,7 +548,6 @@ static struct fb_ops cirrusfb_ops = { .fb_fillrect = cirrusfb_fillrect, .fb_copyarea = cirrusfb_copyarea, .fb_imageblit = cirrusfb_imageblit, - .fb_cursor = soft_cursor, }; /*--- Hardware Specific Routines -------------------------------------------*/ diff --git a/drivers/video/clps711xfb.c b/drivers/video/clps711xfb.c index 8692e002986b..50b78af0fa24 100644 --- a/drivers/video/clps711xfb.c +++ b/drivers/video/clps711xfb.c @@ -219,7 +219,6 @@ static struct fb_ops clps7111fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static int diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile index 42c7b8dcd220..71b4b626e328 100644 --- a/drivers/video/console/Makefile +++ b/drivers/video/console/Makefile @@ -26,7 +26,7 @@ obj-$(CONFIG_PROM_CONSOLE) += promcon.o promcon_tbl.o obj-$(CONFIG_STI_CONSOLE) += sticon.o sticore.o font.o obj-$(CONFIG_VGA_CONSOLE) += vgacon.o obj-$(CONFIG_MDA_CONSOLE) += mdacon.o -obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o bitblit.o font.o +obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += fbcon.o bitblit.o font.o softcursor.o ifeq ($(CONFIG_FB_TILEBLITTING),y) obj-$(CONFIG_FRAMEBUFFER_CONSOLE) += tileblit.o endif diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c index 9f70e512b88b..67857b3cfc8b 100644 --- a/drivers/video/console/bitblit.c +++ b/drivers/video/console/bitblit.c @@ -272,6 +272,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int w = (vc->vc_font.width + 7) >> 3, c; int y = real_y(p, vc->vc_y); int attribute, use_sw = (vc->vc_cursor_type & 0x10); + int err = 1; char *src; cursor.set = 0; @@ -408,7 +409,11 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, cursor.image.depth = 1; cursor.rop = ROP_XOR; - info->fbops->fb_cursor(info, &cursor); + if (info->fbops->fb_cursor) + err = info->fbops->fb_cursor(info, &cursor); + + if (err) + soft_cursor(info, &cursor); ops->cursor_reset = 0; } diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h index 0738cd62def2..b68e0e2c2d16 100644 --- a/drivers/video/console/fbcon.h +++ b/drivers/video/console/fbcon.h @@ -167,5 +167,5 @@ extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info, struct display *p, struct fbcon_ops *ops); #endif extern void fbcon_set_bitops(struct fbcon_ops *ops); - +extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor); #endif /* _VIDEO_FBCON_H */ diff --git a/drivers/video/console/softcursor.c b/drivers/video/console/softcursor.c new file mode 100644 index 000000000000..8529bf08db28 --- /dev/null +++ b/drivers/video/console/softcursor.c @@ -0,0 +1,72 @@ +/* + * linux/drivers/video/softcursor.c -- Generic software cursor for frame buffer devices + * + * Created 14 Nov 2002 by James Simmons + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include + +#include +#include + +int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) +{ + unsigned int scan_align = info->pixmap.scan_align - 1; + unsigned int buf_align = info->pixmap.buf_align - 1; + unsigned int i, size, dsize, s_pitch, d_pitch; + struct fb_image *image; + u8 *dst, *src; + + if (info->state != FBINFO_STATE_RUNNING) + return 0; + + s_pitch = (cursor->image.width + 7) >> 3; + dsize = s_pitch * cursor->image.height; + + src = kmalloc(dsize + sizeof(struct fb_image), GFP_ATOMIC); + if (!src) + return -ENOMEM; + + image = (struct fb_image *) (src + dsize); + *image = cursor->image; + d_pitch = (s_pitch + scan_align) & ~scan_align; + + size = d_pitch * image->height + buf_align; + size &= ~buf_align; + dst = fb_get_buffer_offset(info, &info->pixmap, size); + + if (cursor->enable) { + switch (cursor->rop) { + case ROP_XOR: + for (i = 0; i < dsize; i++) + src[i] = image->data[i] ^ cursor->mask[i]; + break; + case ROP_COPY: + default: + for (i = 0; i < dsize; i++) + src[i] = image->data[i] & cursor->mask[i]; + break; + } + } else + memcpy(src, image->data, dsize); + + fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, image->height); + image->data = dst; + info->fbops->fb_imageblit(info, image); + kfree(src); + return 0; +} + +EXPORT_SYMBOL(soft_cursor); + +MODULE_AUTHOR("James Simmons "); +MODULE_DESCRIPTION("Generic software cursor"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/controlfb.c b/drivers/video/controlfb.c index 989e700159e0..403d17377f8d 100644 --- a/drivers/video/controlfb.c +++ b/drivers/video/controlfb.c @@ -176,7 +176,6 @@ static struct fb_ops controlfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index 3894b2a501d6..c589d23e7f91 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c @@ -1064,7 +1064,6 @@ static struct fb_ops cyber2000fb_ops = { .fb_fillrect = cyber2000fb_fillrect, .fb_copyarea = cyber2000fb_copyarea, .fb_imageblit = cyber2000fb_imageblit, - .fb_cursor = soft_cursor, .fb_sync = cyber2000fb_sync, }; diff --git a/drivers/video/cyblafb.c b/drivers/video/cyblafb.c index 6992100a508c..03fbe83d71a8 100644 --- a/drivers/video/cyblafb.c +++ b/drivers/video/cyblafb.c @@ -968,7 +968,6 @@ static struct fb_ops cyblafb_ops __devinitdata = { .fb_fillrect = cyblafb_fillrect, .fb_copyarea= cyblafb_copyarea, .fb_imageblit = cyblafb_imageblit, - .fb_cursor = soft_cursor, }; //========================================================================== diff --git a/drivers/video/dnfb.c b/drivers/video/dnfb.c index 1785686a7f11..957a3ada2b75 100644 --- a/drivers/video/dnfb.c +++ b/drivers/video/dnfb.c @@ -116,7 +116,6 @@ static struct fb_ops dn_fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = dnfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; struct fb_var_screeninfo dnfb_var __devinitdata = { diff --git a/drivers/video/epson1355fb.c b/drivers/video/epson1355fb.c index 7363d0b25fdf..6a81a1dd8f3d 100644 --- a/drivers/video/epson1355fb.c +++ b/drivers/video/epson1355fb.c @@ -484,7 +484,6 @@ static struct fb_ops epson1355fb_fbops = { .fb_imageblit = cfb_imageblit, .fb_read = epson1355fb_read, .fb_write = epson1355fb_write, - .fb_cursor = soft_cursor, }; /* ------------------------------------------------------------------------- */ diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index 10cd05059fe9..04417dc16c2e 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c @@ -57,9 +57,6 @@ static struct fb_ops ffb_ops = { .fb_sync = ffb_sync, .fb_mmap = ffb_mmap, .fb_ioctl = ffb_ioctl, - - /* XXX Use FFB hw cursor once fb cursor API is better understood... */ - .fb_cursor = soft_cursor, }; /* Register layout and definitions */ diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c index a0763283d776..998374cfae6d 100644 --- a/drivers/video/fm2fb.c +++ b/drivers/video/fm2fb.c @@ -172,7 +172,6 @@ static struct fb_ops fm2fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* diff --git a/drivers/video/gbefb.c b/drivers/video/gbefb.c index ed853bef19e9..9d5e4f342110 100644 --- a/drivers/video/gbefb.c +++ b/drivers/video/gbefb.c @@ -1038,7 +1038,6 @@ static struct fb_ops gbefb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* diff --git a/drivers/video/geode/Kconfig b/drivers/video/geode/Kconfig index 5a9b89c3831b..42fb9a89a792 100644 --- a/drivers/video/geode/Kconfig +++ b/drivers/video/geode/Kconfig @@ -14,7 +14,6 @@ config FB_GEODE_GX1 select FB_CFB_FILLRECT select FB_CFB_COPYAREA select FB_CFB_IMAGEBLIT - select FB_SOFT_CURSOR ---help--- Framebuffer driver for the display controller integrated into the AMD Geode GX1 processor. diff --git a/drivers/video/geode/gx1fb_core.c b/drivers/video/geode/gx1fb_core.c index 74a5fca86b8a..8e8da7433994 100644 --- a/drivers/video/geode/gx1fb_core.c +++ b/drivers/video/geode/gx1fb_core.c @@ -275,7 +275,6 @@ static struct fb_ops gx1fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static struct fb_info * __init gx1fb_init_fbinfo(struct device *dev) diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c index 0d376ba54814..f04ca721f94c 100644 --- a/drivers/video/hitfb.c +++ b/drivers/video/hitfb.c @@ -262,7 +262,6 @@ static struct fb_ops hitfb_ops = { .fb_fillrect = hitfb_fillrect, .fb_copyarea = hitfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; int __init hitfb_init(void) diff --git a/drivers/video/hpfb.c b/drivers/video/hpfb.c index e97fe8481d59..bebdac59d231 100644 --- a/drivers/video/hpfb.c +++ b/drivers/video/hpfb.c @@ -193,7 +193,6 @@ static struct fb_ops hpfb_ops = { .fb_fillrect = hpfb_fillrect, .fb_copyarea = hpfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_sync = hpfb_sync, }; diff --git a/drivers/video/imsttfb.c b/drivers/video/imsttfb.c index 7b9bf45ab6fe..7fbe24206b19 100644 --- a/drivers/video/imsttfb.c +++ b/drivers/video/imsttfb.c @@ -1344,7 +1344,6 @@ static struct fb_ops imsttfb_ops = { .fb_fillrect = imsttfb_fillrect, .fb_copyarea = imsttfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_ioctl = imsttfb_ioctl, }; diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 64d9bcc38da3..e20b9f3a255f 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c @@ -298,7 +298,6 @@ static struct fb_ops imxfb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_blank = imxfb_blank, - .fb_cursor = soft_cursor, /* FIXME: i.MX can do hardware cursor */ }; /* diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index e6d75b926dc8..0799b999b314 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c @@ -1485,7 +1485,7 @@ intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor) #endif if (!dinfo->hwcursor) - return soft_cursor(info, cursor); + return -ENODEV; intelfbhw_cursor_hide(dinfo); diff --git a/drivers/video/kyro/fbdev.c b/drivers/video/kyro/fbdev.c index d8bac9e97842..5eb4d5c177bd 100644 --- a/drivers/video/kyro/fbdev.c +++ b/drivers/video/kyro/fbdev.c @@ -669,7 +669,6 @@ static struct fb_ops kyrofb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static int __devinit kyrofb_probe(struct pci_dev *pdev, diff --git a/drivers/video/leo.c b/drivers/video/leo.c index 7e1e7fb168bd..84a7fe435bb8 100644 --- a/drivers/video/leo.c +++ b/drivers/video/leo.c @@ -51,7 +51,6 @@ static struct fb_ops leo_ops = { .fb_imageblit = cfb_imageblit, .fb_mmap = leo_mmap, .fb_ioctl = leo_ioctl, - .fb_cursor = soft_cursor, }; #define LEO_OFF_LC_SS0_KRN 0x00200000UL diff --git a/drivers/video/macfb.c b/drivers/video/macfb.c index 4945a4c02209..cfc748e94272 100644 --- a/drivers/video/macfb.c +++ b/drivers/video/macfb.c @@ -589,7 +589,6 @@ static struct fb_ops macfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; void __init macfb_setup(char *options) diff --git a/drivers/video/matrox/matroxfb_accel.c b/drivers/video/matrox/matroxfb_accel.c index c7f3e1321224..a5c825d99466 100644 --- a/drivers/video/matrox/matroxfb_accel.c +++ b/drivers/video/matrox/matroxfb_accel.c @@ -122,7 +122,7 @@ void matrox_cfbX_init(WPMINFO2) { ACCESS_FBINFO(fbops).fb_copyarea = cfb_copyarea; ACCESS_FBINFO(fbops).fb_fillrect = cfb_fillrect; ACCESS_FBINFO(fbops).fb_imageblit = cfb_imageblit; - ACCESS_FBINFO(fbops).fb_cursor = soft_cursor; + ACCESS_FBINFO(fbops).fb_cursor = NULL; accel = (ACCESS_FBINFO(fbcon).var.accel_flags & FB_ACCELF_TEXT) == FB_ACCELF_TEXT; diff --git a/drivers/video/matrox/matroxfb_crtc2.c b/drivers/video/matrox/matroxfb_crtc2.c index 429047ac615a..d52d7d825c41 100644 --- a/drivers/video/matrox/matroxfb_crtc2.c +++ b/drivers/video/matrox/matroxfb_crtc2.c @@ -576,7 +576,6 @@ static struct fb_ops matroxfb_dh_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static struct fb_var_screeninfo matroxfb_dh_defined = { diff --git a/drivers/video/maxinefb.c b/drivers/video/maxinefb.c index f192d995d030..743e7ad26acc 100644 --- a/drivers/video/maxinefb.c +++ b/drivers/video/maxinefb.c @@ -113,7 +113,6 @@ static struct fb_ops maxinefb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; int __init maxinefb_init(void) diff --git a/drivers/video/neofb.c b/drivers/video/neofb.c index 5d424a30270a..8486e77872dc 100644 --- a/drivers/video/neofb.c +++ b/drivers/video/neofb.c @@ -1665,7 +1665,6 @@ static struct fb_ops neofb_ops = { .fb_fillrect = neofb_fillrect, .fb_copyarea = neofb_copyarea, .fb_imageblit = neofb_imageblit, - .fb_cursor = soft_cursor, }; /* --------------------------------------------------------------------- */ diff --git a/drivers/video/nvidia/nvidia.c b/drivers/video/nvidia/nvidia.c index 691151e2bce3..cbe165bb181d 100644 --- a/drivers/video/nvidia/nvidia.c +++ b/drivers/video/nvidia/nvidia.c @@ -1433,7 +1433,7 @@ static int __devinit nvidia_set_fbinfo(struct fb_info *info) info->pixmap.flags = FB_PIXMAP_SYSTEM; if (!hwcur) - info->fbops->fb_cursor = soft_cursor; + info->fbops->fb_cursor = NULL; info->var.accel_flags = (!noaccel); diff --git a/drivers/video/offb.c b/drivers/video/offb.c index 611922c0b22f..2c856838694e 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -85,7 +85,6 @@ static struct fb_ops offb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c index b76a5a9a125b..9aaf65fb623a 100644 --- a/drivers/video/p9100.c +++ b/drivers/video/p9100.c @@ -48,7 +48,6 @@ static struct fb_ops p9100_ops = { .fb_imageblit = cfb_imageblit, .fb_mmap = p9100_mmap, .fb_ioctl = p9100_ioctl, - .fb_cursor = soft_cursor, }; /* P9100 control registers */ diff --git a/drivers/video/platinumfb.c b/drivers/video/platinumfb.c index b00887e9851c..ca4082ae5a18 100644 --- a/drivers/video/platinumfb.c +++ b/drivers/video/platinumfb.c @@ -109,7 +109,6 @@ static struct fb_ops platinumfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index 42c17efa9fb0..f4188fe6dd9a 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c @@ -1034,7 +1034,6 @@ static struct fb_ops pm2fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c index c98f1c8d7dc2..f3927b6cda9d 100644 --- a/drivers/video/pmag-ba-fb.c +++ b/drivers/video/pmag-ba-fb.c @@ -128,7 +128,6 @@ static struct fb_ops pmagbafb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c index a483b13e117b..25148de5fe67 100644 --- a/drivers/video/pmagb-b-fb.c +++ b/drivers/video/pmagb-b-fb.c @@ -132,7 +132,6 @@ static struct fb_ops pmagbbfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c index 31c547fd383b..ec4bacf9dd2e 100644 --- a/drivers/video/pvr2fb.c +++ b/drivers/video/pvr2fb.c @@ -230,7 +230,6 @@ static struct fb_ops pvr2fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static struct fb_videomode pvr2_modedb[] __initdata = { diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index efd9333b05c2..f305a5b77b23 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -418,7 +418,6 @@ static struct fb_ops pxafb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_blank = pxafb_blank, - .fb_cursor = soft_cursor, .fb_mmap = pxafb_mmap, }; diff --git a/drivers/video/q40fb.c b/drivers/video/q40fb.c index 8416b2e2b501..bfc41f2c902a 100644 --- a/drivers/video/q40fb.c +++ b/drivers/video/q40fb.c @@ -84,7 +84,6 @@ static struct fb_ops q40fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static int __init q40fb_probe(struct device *device) diff --git a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c index a78b9bd8f897..600318f708f2 100644 --- a/drivers/video/radeonfb.c +++ b/drivers/video/radeonfb.c @@ -2218,7 +2218,6 @@ static struct fb_ops radeonfb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, #endif - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/s1d13xxxfb.c b/drivers/video/s1d13xxxfb.c index f4437430dc5f..3edbd14c5c46 100644 --- a/drivers/video/s1d13xxxfb.c +++ b/drivers/video/s1d13xxxfb.c @@ -388,7 +388,6 @@ static struct fb_ops s1d13xxxfb_fbops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor }; static int s1d13xxxfb_width_tab[2][4] __devinitdata = { diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index 3cef90456a4b..bf679312be06 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c @@ -495,7 +495,6 @@ static struct fb_ops s3c2410fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/sa1100fb.c b/drivers/video/sa1100fb.c index 3d35b28aaac7..a5184575cfae 100644 --- a/drivers/video/sa1100fb.c +++ b/drivers/video/sa1100fb.c @@ -853,7 +853,6 @@ static struct fb_ops sa1100fb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, .fb_blank = sa1100fb_blank, - .fb_cursor = soft_cursor, .fb_mmap = sa1100fb_mmap, }; diff --git a/drivers/video/savage/savagefb_driver.c b/drivers/video/savage/savagefb_driver.c index 7c285455c924..378ea1e34de7 100644 --- a/drivers/video/savage/savagefb_driver.c +++ b/drivers/video/savage/savagefb_driver.c @@ -1470,7 +1470,6 @@ static struct fb_ops savagefb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, #endif - .fb_cursor = soft_cursor, }; /* --------------------------------------------------------------------- */ diff --git a/drivers/video/sgivwfb.c b/drivers/video/sgivwfb.c index 5ce81f44c769..2e8769dd345a 100644 --- a/drivers/video/sgivwfb.c +++ b/drivers/video/sgivwfb.c @@ -126,7 +126,6 @@ static struct fb_ops sgivwfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_mmap = sgivwfb_mmap, }; diff --git a/drivers/video/sis/sis_main.c b/drivers/video/sis/sis_main.c index 42c54b69726e..dea1a46c67c4 100644 --- a/drivers/video/sis/sis_main.c +++ b/drivers/video/sis/sis_main.c @@ -2002,7 +2002,9 @@ static struct fb_ops sisfb_ops = { .fb_fillrect = fbcon_sis_fillrect, .fb_copyarea = fbcon_sis_copyarea, .fb_imageblit = cfb_imageblit, +#ifdef CONFIG_FB_SOFT_CURSOR .fb_cursor = soft_cursor, +#endif .fb_sync = fbcon_sis_sync, #ifdef SIS_NEW_CONFIG_COMPAT .fb_compat_ioctl= sisfb_compat_ioctl, diff --git a/drivers/video/skeletonfb.c b/drivers/video/skeletonfb.c index 7b43716ab665..a01e7ecc15ed 100644 --- a/drivers/video/skeletonfb.c +++ b/drivers/video/skeletonfb.c @@ -457,11 +457,8 @@ void xxxfb_imageblit(struct fb_info *p, const struct fb_image *image) } /** - * xxxfb_cursor - REQUIRED function. If your hardware lacks support - * for a cursor you can use the default cursor whose - * function is called soft_cursor. It will always - * work since it uses xxxfb_imageblit function which - * is required. + * xxxfb_cursor - OPTIONAL. If your hardware lacks support + * for a cursor, leave this field NULL. * * @info: frame buffer structure that represents a single frame buffer * @cursor: structure defining the cursor to draw. @@ -663,7 +660,7 @@ static struct fb_ops xxxfb_ops = { .fb_fillrect = xxxfb_fillrect, /* Needed !!! */ .fb_copyarea = xxxfb_copyarea, /* Needed !!! */ .fb_imageblit = xxxfb_imageblit, /* Needed !!! */ - .fb_cursor = xxxfb_cursor, /* Needed !!! */ + .fb_cursor = xxxfb_cursor, /* Optional !!! */ .fb_rotate = xxxfb_rotate, .fb_poll = xxxfb_poll, .fb_sync = xxxfb_sync, diff --git a/drivers/video/softcursor.c b/drivers/video/softcursor.c deleted file mode 100644 index 229c4bc35079..000000000000 --- a/drivers/video/softcursor.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * linux/drivers/video/softcursor.c -- Generic software cursor for frame buffer devices - * - * Created 14 Nov 2002 by James Simmons - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive - * for more details. - */ - -#include -#include -#include -#include -#include - -#include -#include - -int soft_cursor(struct fb_info *info, struct fb_cursor *cursor) -{ - unsigned int scan_align = info->pixmap.scan_align - 1; - unsigned int buf_align = info->pixmap.buf_align - 1; - unsigned int i, size, dsize, s_pitch, d_pitch; - struct fb_image *image; - u8 *dst, *src; - - if (info->state != FBINFO_STATE_RUNNING) - return 0; - - s_pitch = (cursor->image.width + 7) >> 3; - dsize = s_pitch * cursor->image.height; - - src = kmalloc(dsize + sizeof(struct fb_image), GFP_ATOMIC); - if (!src) - return -ENOMEM; - - image = (struct fb_image *) (src + dsize); - *image = cursor->image; - d_pitch = (s_pitch + scan_align) & ~scan_align; - - size = d_pitch * image->height + buf_align; - size &= ~buf_align; - dst = fb_get_buffer_offset(info, &info->pixmap, size); - - if (cursor->enable) { - switch (cursor->rop) { - case ROP_XOR: - for (i = 0; i < dsize; i++) - src[i] = image->data[i] ^ cursor->mask[i]; - break; - case ROP_COPY: - default: - for (i = 0; i < dsize; i++) - src[i] = image->data[i] & cursor->mask[i]; - break; - } - } else - memcpy(src, image->data, dsize); - - fb_pad_aligned_buffer(dst, d_pitch, src, s_pitch, image->height); - image->data = dst; - info->fbops->fb_imageblit(info, image); - kfree(src); - return 0; -} - -EXPORT_SYMBOL(soft_cursor); - -MODULE_AUTHOR("James Simmons "); -MODULE_DESCRIPTION("Generic software cursor"); -MODULE_LICENSE("GPL"); diff --git a/drivers/video/sstfb.c b/drivers/video/sstfb.c index 663d53657fa4..e0f14df840d9 100644 --- a/drivers/video/sstfb.c +++ b/drivers/video/sstfb.c @@ -1382,7 +1382,6 @@ static struct fb_ops sstfb_ops = { .fb_fillrect = cfb_fillrect, /* sstfb_fillrect */ .fb_copyarea = cfb_copyarea, /* sstfb_copyarea */ .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_ioctl = sstfb_ioctl, }; diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index 9e52794768e6..fbb17332afd7 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c @@ -1147,7 +1147,6 @@ static struct fb_ops stifb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c index 1986a8b3833c..59fff29bc02e 100644 --- a/drivers/video/tcx.c +++ b/drivers/video/tcx.c @@ -52,7 +52,6 @@ static struct fb_ops tcx_ops = { .fb_imageblit = cfb_imageblit, .fb_mmap = tcx_mmap, .fb_ioctl = tcx_ioctl, - .fb_cursor = soft_cursor, }; /* THC definitions */ diff --git a/drivers/video/tdfxfb.c b/drivers/video/tdfxfb.c index 7044226c5d4c..9d53387e6a66 100644 --- a/drivers/video/tdfxfb.c +++ b/drivers/video/tdfxfb.c @@ -184,7 +184,6 @@ static struct fb_ops tdfxfb_ops = { .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, #endif - .fb_cursor = soft_cursor, }; /* diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c index 9d9d2009ad8c..7398bd48ba6c 100644 --- a/drivers/video/tgafb.c +++ b/drivers/video/tgafb.c @@ -63,7 +63,6 @@ static struct fb_ops tgafb_ops = { .fb_fillrect = tgafb_fillrect, .fb_copyarea = tgafb_copyarea, .fb_imageblit = tgafb_imageblit, - .fb_cursor = soft_cursor, }; diff --git a/drivers/video/tridentfb.c b/drivers/video/tridentfb.c index 81a6d9f188cf..9ac2d3171187 100644 --- a/drivers/video/tridentfb.c +++ b/drivers/video/tridentfb.c @@ -1293,7 +1293,6 @@ static struct fb_ops tridentfb_ops = { .fb_fillrect = tridentfb_fillrect, .fb_copyarea= tridentfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; module_init(tridentfb_init); diff --git a/drivers/video/tx3912fb.c b/drivers/video/tx3912fb.c index 39d9ca71856b..d904da44e1aa 100644 --- a/drivers/video/tx3912fb.c +++ b/drivers/video/tx3912fb.c @@ -89,7 +89,6 @@ static struct fb_ops tx3912fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static int tx3912fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) diff --git a/drivers/video/valkyriefb.c b/drivers/video/valkyriefb.c index 31a2bbc53974..ce97ec8eae97 100644 --- a/drivers/video/valkyriefb.c +++ b/drivers/video/valkyriefb.c @@ -135,7 +135,6 @@ static struct fb_ops valkyriefb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; /* Sets the video mode according to info->var */ diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index 3cc23106641d..4f02615225ac 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -215,7 +215,6 @@ static struct fb_ops vesafb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; static int __init vesafb_setup(char *options) diff --git a/drivers/video/vfb.c b/drivers/video/vfb.c index 92d46555dd86..8794dc5d2466 100644 --- a/drivers/video/vfb.c +++ b/drivers/video/vfb.c @@ -92,7 +92,6 @@ static struct fb_ops vfb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, .fb_mmap = vfb_mmap, }; diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index b46454c55c91..690bb6fe8281 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c @@ -1326,7 +1326,6 @@ static struct fb_ops vga16fb_ops = { .fb_fillrect = vga16fb_fillrect, .fb_copyarea = vga16fb_copyarea, .fb_imageblit = vga16fb_imageblit, - .fb_cursor = soft_cursor, }; #ifndef MODULE diff --git a/drivers/video/w100fb.c b/drivers/video/w100fb.c index cf8cdb108fd9..48e70f153c4b 100644 --- a/drivers/video/w100fb.c +++ b/drivers/video/w100fb.c @@ -397,7 +397,6 @@ static struct fb_ops w100fb_ops = { .fb_fillrect = cfb_fillrect, .fb_copyarea = cfb_copyarea, .fb_imageblit = cfb_imageblit, - .fb_cursor = soft_cursor, }; #ifdef CONFIG_PM diff --git a/include/linux/fb.h b/include/linux/fb.h index c698055266d0..008ea71f4d7f 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -810,7 +810,6 @@ struct fb_info { extern int fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var); extern int fb_pan_display(struct fb_info *info, struct fb_var_screeninfo *var); extern int fb_blank(struct fb_info *info, int blank); -extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor); extern void cfb_fillrect(struct fb_info *info, const struct fb_fillrect *rect); extern void cfb_copyarea(struct fb_info *info, const struct fb_copyarea *area); extern void cfb_imageblit(struct fb_info *info, const struct fb_image *image); -- cgit v1.2.3 From 8fb6567e347a04d44b57e2b223cc5845859dfc6a Mon Sep 17 00:00:00 2001 From: Michal Januszewski Date: Mon, 7 Nov 2005 01:00:47 -0800 Subject: [PATCH] fbdev: fix the fb_find_nearest_mode() function Currently the fb_find_nearest_mode() function finds a mode with screen resolution closest to that described by the 'var' argument and with some arbitrary refresh rate (eg. in the following sequence of refresh rates: 70 60 53 85 75, 53 is selected). This patch fixes the function so that it looks for the closest mode as far as both resolution and refresh rate are concerned. The function's first argument is changed to fb_videomode so that the refresh rate can be specified by the caller, as fb_var_screeninfo doesn't have any fields that could directly hold this data. Signed-off-by: Michal Januszewski Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/fbcon.c | 3 ++- drivers/video/modedb.c | 24 +++++++++++++----------- include/linux/fb.h | 2 +- 3 files changed, 16 insertions(+), 13 deletions(-) (limited to 'include/linux') diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 5ff51cd0a2a9..3cf1b61ff1f8 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -2715,7 +2715,8 @@ static void fbcon_new_modelist(struct fb_info *info) continue; vc = vc_cons[i].d; display_to_var(&var, &fb_display[i]); - mode = fb_find_nearest_mode(&var, &info->modelist); + mode = fb_find_nearest_mode(fb_display[i].mode, + &info->modelist); fb_videomode_to_var(&var, mode); if (vc) diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index 47516c44a390..aadef046ce7b 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c @@ -676,6 +676,8 @@ void fb_var_to_videomode(struct fb_videomode *mode, mode->sync = var->sync; mode->vmode = var->vmode & FB_VMODE_MASK; mode->flag = FB_MODE_IS_FROM_VAR; + mode->refresh = 0; + if (!var->pixclock) return; @@ -785,39 +787,39 @@ struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var, } /** - * fb_find_nearest_mode - find mode closest video mode + * fb_find_nearest_mode - find closest videomode * - * @var: pointer to struct fb_var_screeninfo + * @mode: pointer to struct fb_videomode * @head: pointer to modelist * * Finds best matching videomode, smaller or greater in dimension. * If more than 1 videomode is found, will return the videomode with - * the closest refresh rate + * the closest refresh rate. */ -struct fb_videomode *fb_find_nearest_mode(struct fb_var_screeninfo *var, +struct fb_videomode *fb_find_nearest_mode(struct fb_videomode *mode, struct list_head *head) { struct list_head *pos; struct fb_modelist *modelist; - struct fb_videomode *mode, *best = NULL; + struct fb_videomode *cmode, *best = NULL; u32 diff = -1, diff_refresh = -1; list_for_each(pos, head) { u32 d; modelist = list_entry(pos, struct fb_modelist, list); - mode = &modelist->mode; + cmode = &modelist->mode; - d = abs(mode->xres - var->xres) + - abs(mode->yres - var->yres); + d = abs(cmode->xres - mode->xres) + + abs(cmode->yres - mode->yres); if (diff > d) { diff = d; - best = mode; + best = cmode; } else if (diff == d) { - d = abs(mode->refresh - best->refresh); + d = abs(cmode->refresh - mode->refresh); if (diff_refresh > d) { diff_refresh = d; - best = mode; + best = cmode; } } } diff --git a/include/linux/fb.h b/include/linux/fb.h index 008ea71f4d7f..68a787914d85 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -897,7 +897,7 @@ extern struct fb_videomode *fb_match_mode(struct fb_var_screeninfo *var, struct list_head *head); extern struct fb_videomode *fb_find_best_mode(struct fb_var_screeninfo *var, struct list_head *head); -extern struct fb_videomode *fb_find_nearest_mode(struct fb_var_screeninfo *var, +extern struct fb_videomode *fb_find_nearest_mode(struct fb_videomode *mode, struct list_head *head); extern void fb_destroy_modelist(struct list_head *head); extern void fb_videomode_to_modelist(struct fb_videomode *modedb, int num, -- cgit v1.2.3 From e07dea98761270249f33e733ff86420bc52ccab6 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 7 Nov 2005 01:00:51 -0800 Subject: [PATCH] console: Fix compile error Fix following compile error (From Kernel Bugzilla Bug 5427): include/linux/console_struct.h:53: error: field `vt_mode' has incomplete type Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/console_struct.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include/linux') diff --git a/include/linux/console_struct.h b/include/linux/console_struct.h index 725be90ef55e..f8e5587a0f92 100644 --- a/include/linux/console_struct.h +++ b/include/linux/console_struct.h @@ -9,6 +9,8 @@ * to achieve effects such as fast scrolling by changing the origin. */ +#include + struct vt_struct; #define NPAR 16 -- cgit v1.2.3 From 998e6d51162707685336ff99c029c8911b270d32 Mon Sep 17 00:00:00 2001 From: Zach Smith Date: Mon, 7 Nov 2005 01:00:52 -0800 Subject: [PATCH] fbcon: Add rl (Roman Large) font I converted the "rl" console font from the kbd utility to be a built-in font for the framebuffer console, and I was wondering if you would be OK with including it. I've generated a font_rl.c file and related minor modifications. I find it's the most visually appealing of the kbd fonts which is why I use it and selected it for conversion. I believe the font is GPL'd. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/Kconfig | 7 + drivers/video/console/Makefile | 1 + drivers/video/console/font_rl.c | 4374 +++++++++++++++++++++++++++++++++++++++ drivers/video/console/fonts.c | 4 + include/linux/font.h | 2 + 5 files changed, 4388 insertions(+) create mode 100644 drivers/video/console/font_rl.c (limited to 'include/linux') diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index 81d44995f9eb..fadf7c5d216e 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -205,5 +205,12 @@ config FONT_10x18 big letters. It fits between the sun 12x22 and the normal 8x16 font. If other fonts are too big or too small for you, say Y, otherwise say N. +config FONT_RL + bool "console Roman Large 8x16 font" if FONTS + depends on FRAMEBUFFER_CONSOLE + help + This is the visually-appealing "RL" console font that is + included with the kbd package. + endmenu diff --git a/drivers/video/console/Makefile b/drivers/video/console/Makefile index 71b4b626e328..5222628accce 100644 --- a/drivers/video/console/Makefile +++ b/drivers/video/console/Makefile @@ -15,6 +15,7 @@ font-objs-$(CONFIG_FONT_10x18) += font_10x18.o font-objs-$(CONFIG_FONT_PEARL_8x8) += font_pearl_8x8.o font-objs-$(CONFIG_FONT_ACORN_8x8) += font_acorn_8x8.o font-objs-$(CONFIG_FONT_MINI_4x6) += font_mini_4x6.o +font-objs-$(CONFIG_FONT_RL) += font_rl.o font-objs += $(font-objs-y) diff --git a/drivers/video/console/font_rl.c b/drivers/video/console/font_rl.c new file mode 100644 index 000000000000..dfecc27d8ded --- /dev/null +++ b/drivers/video/console/font_rl.c @@ -0,0 +1,4374 @@ + +/* This font is simply the "rl.fnt" console font from the kbd utility. + * Converted by Zack T Smith, fbui@comcast.net. + * The original binary file is covered under the GNU Public License. + */ + +#include + +#define FONTDATAMAX 4096 + +static unsigned char patterns[4096] = { +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x3c, +0x42, +0x81, +0xe7, +0xa5, +0x99, +0x81, +0x81, +0x99, +0x42, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x3c, +0x7e, +0xff, +0x99, +0xdb, +0xe7, +0xff, +0xff, +0xe7, +0x7e, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x6c, +0xfe, +0xfe, +0xfe, +0xfe, +0xfe, +0x7c, +0x38, +0x10, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x10, +0x38, +0x7c, +0xfe, +0x7c, +0x38, +0x10, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x38, +0x38, +0x10, +0xd6, +0xfe, +0xd6, +0x10, +0x10, +0x38, +0x7c, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x10, +0x38, +0x7c, +0xfe, +0xfe, +0x54, +0x10, +0x10, +0x38, +0x7c, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x18, +0x3c, +0x3c, +0x18, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xe7, +0xc3, +0xc3, +0xe7, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x3c, +0x66, +0x42, +0x42, +0x66, +0x3c, +0x00, +0x00, +0x00, +0x00, +0x00, + +0xff, +0xff, +0xff, +0xff, +0xff, +0xc3, +0x99, +0xbd, +0xbd, +0x99, +0xc3, +0xff, +0xff, +0xff, +0xff, +0xff, + +0x00, +0x00, +0x0f, +0x07, +0x0d, +0x18, +0x78, +0xcc, +0xcc, +0xcc, +0xcc, +0x78, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x3c, +0x66, +0x66, +0x66, +0x3c, +0x18, +0x7e, +0x18, +0x18, +0x18, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x08, +0x0c, +0x0a, +0x0a, +0x0a, +0x08, +0x08, +0x08, +0x38, +0x78, +0x30, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x10, +0x18, +0x1c, +0x1e, +0x1e, +0x16, +0x12, +0x72, +0xf2, +0x62, +0x0e, +0x1e, +0x0c, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x10, +0x92, +0x54, +0x38, +0xfe, +0x38, +0x54, +0x92, +0x10, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x80, +0xc0, +0xe0, +0xb8, +0x8e, +0xb8, +0xe0, +0xc0, +0x80, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x02, +0x06, +0x0e, +0x3a, +0xe2, +0x3a, +0x0e, +0x06, +0x02, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x10, +0x38, +0x7c, +0xd6, +0x10, +0x10, +0x10, +0x10, +0xd6, +0x7c, +0x38, +0x10, +0x00, +0x00, + +0x00, +0x42, +0xe7, +0xe7, +0xe7, +0xe7, +0x42, +0x42, +0x42, +0x00, +0x66, +0x66, +0x66, +0x00, +0x00, +0x00, + +0x00, +0x7f, +0xca, +0xca, +0xca, +0xca, +0x7a, +0x0a, +0x0a, +0x0a, +0x0a, +0x0a, +0x1b, +0x00, +0x00, +0x00, + +0x00, +0x1e, +0x31, +0x78, +0xcc, +0xc6, +0xc3, +0x63, +0x33, +0x1e, +0x8c, +0x78, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xfe, +0xfe, +0xfe, +0xfe, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x10, +0x38, +0x7c, +0xd6, +0x10, +0x10, +0x10, +0x10, +0xd6, +0x7c, +0x38, +0x10, +0xfe, +0x00, + +0x00, +0x00, +0x10, +0x38, +0x7c, +0xd6, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x00, +0x00, + +0x00, +0x00, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0x10, +0xd6, +0x7c, +0x38, +0x10, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x08, +0x0c, +0x06, +0xff, +0x06, +0x0c, +0x08, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x10, +0x30, +0x60, +0xff, +0x60, +0x30, +0x10, +0x00, +0x00, +0x00, +0x00, + +0x22, +0x44, +0x88, +0xcc, +0xee, +0x44, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x24, +0x42, +0xff, +0x42, +0x24, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x10, +0x38, +0x38, +0x6c, +0x6c, +0xc6, +0xfe, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0xfe, +0xc6, +0x6c, +0x6c, +0x38, +0x38, +0x10, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x18, +0x3c, +0x3c, +0x3c, +0x3c, +0x18, +0x18, +0x18, +0x10, +0x00, +0x18, +0x18, +0x00, +0x00, +0x00, + +0x22, +0x77, +0x33, +0x11, +0x22, +0x44, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x12, +0x12, +0x12, +0x7f, +0x24, +0x24, +0x24, +0xfe, +0x48, +0x48, +0x48, +0x00, +0x00, +0x00, + +0x10, +0x10, +0x7c, +0xd2, +0xd0, +0xd0, +0xd0, +0x7c, +0x16, +0x16, +0x16, +0x96, +0x7c, +0x10, +0x10, +0x00, + +0x00, +0x42, +0xbe, +0x44, +0x0c, +0x08, +0x18, +0x10, +0x30, +0x20, +0x64, +0x4a, +0xc4, +0x00, +0x00, +0x00, + +0x00, +0x38, +0x6c, +0x6c, +0x6c, +0x38, +0x37, +0x72, +0xdc, +0xcc, +0xcc, +0xcc, +0x77, +0x00, +0x00, +0x00, + +0x10, +0x38, +0x18, +0x08, +0x10, +0x20, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x04, +0x08, +0x10, +0x10, +0x30, +0x30, +0x30, +0x30, +0x30, +0x10, +0x10, +0x08, +0x04, +0x00, +0x00, + +0x00, +0x20, +0x10, +0x08, +0x08, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x08, +0x08, +0x10, +0x20, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x44, +0x28, +0x38, +0xfe, +0x38, +0x28, +0x44, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x18, +0x18, +0x7e, +0x18, +0x18, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x10, +0x38, +0x18, +0x08, +0x10, +0x20, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x7e, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x10, +0x38, +0x10, +0x00, +0x00, +0x00, + +0x00, +0x06, +0x06, +0x0c, +0x0c, +0x18, +0x18, +0x30, +0x30, +0x60, +0x60, +0xc0, +0xc0, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x3c, +0x46, +0xc6, +0xc6, +0xc6, +0xc6, +0xc6, +0xc4, +0x78, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x08, +0x18, +0x78, +0x18, +0x18, +0x18, +0x18, +0x18, +0x7e, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x7c, +0x86, +0x06, +0x0c, +0x18, +0x20, +0x40, +0xc1, +0xfe, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x3c, +0x46, +0x04, +0x08, +0x1c, +0x06, +0x06, +0x06, +0x06, +0x0c, +0x70, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x04, +0x08, +0x10, +0x2c, +0x4c, +0x8c, +0x8c, +0xfe, +0x0c, +0x0c, +0x0c, +0x00, + +0x00, +0x00, +0x00, +0x02, +0x3c, +0x20, +0x20, +0x70, +0x0c, +0x06, +0x06, +0x06, +0x06, +0x0c, +0x70, +0x00, + +0x00, +0x00, +0x18, +0x20, +0x40, +0xc0, +0xdc, +0xc6, +0xc6, +0xc6, +0xc6, +0x44, +0x38, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x40, +0x7e, +0x82, +0x06, +0x04, +0x0c, +0x18, +0x18, +0x30, +0x30, +0x30, +0x30, +0x00, + +0x00, +0x00, +0x7c, +0xc6, +0xc6, +0x64, +0x38, +0x4c, +0xc6, +0xc6, +0xc6, +0xc6, +0x7c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x38, +0x44, +0xc6, +0xc6, +0x76, +0x06, +0x06, +0x06, +0x04, +0x08, +0x30, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x10, +0x38, +0x10, +0x00, +0x00, +0x00, +0x10, +0x38, +0x10, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x10, +0x38, +0x10, +0x00, +0x00, +0x00, +0x10, +0x38, +0x18, +0x08, +0x10, +0x20, + +0x00, +0x06, +0x0c, +0x18, +0x30, +0x60, +0xa0, +0xa0, +0x60, +0x30, +0x18, +0x0c, +0x06, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x7e, +0x00, +0x00, +0x7e, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x60, +0x30, +0x18, +0x0c, +0x06, +0x05, +0x05, +0x06, +0x0c, +0x18, +0x30, +0x60, +0x00, +0x00, +0x00, + +0x00, +0x7c, +0x86, +0xc6, +0x06, +0x04, +0x08, +0x10, +0x10, +0x18, +0x00, +0x18, +0x18, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x3c, +0x46, +0xc6, +0xce, +0xd6, +0xd6, +0xd6, +0xdc, +0xc0, +0xc4, +0x78, +0x00, +0x00, +0x00, + +0x00, +0x18, +0x18, +0x18, +0x3c, +0x2c, +0x2c, +0x2c, +0x7e, +0x46, +0x46, +0x46, +0xef, +0x00, +0x00, +0x00, + +0x00, +0xfc, +0x66, +0x66, +0x66, +0x66, +0x7c, +0x66, +0x66, +0x66, +0x66, +0x66, +0xfc, +0x00, +0x00, +0x00, + +0x00, +0x3a, +0x66, +0xc2, +0xc0, +0xc0, +0xc0, +0xc0, +0xc0, +0xc0, +0xc0, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0xfc, +0x66, +0x63, +0x63, +0x63, +0x63, +0x63, +0x63, +0x63, +0x63, +0x66, +0xfc, +0x00, +0x00, +0x00, + +0x00, +0xff, +0x61, +0x60, +0x60, +0x64, +0x7c, +0x64, +0x60, +0x60, +0x60, +0x61, +0xfe, +0x00, +0x00, +0x00, + +0x00, +0xff, +0x61, +0x61, +0x60, +0x64, +0x7c, +0x64, +0x60, +0x60, +0x60, +0x60, +0xf0, +0x00, +0x00, +0x00, + +0x00, +0x3a, +0x66, +0xc2, +0xc0, +0xc0, +0xc0, +0xcf, +0xc6, +0xc6, +0xc6, +0x66, +0x38, +0x00, +0x00, +0x00, + +0x00, +0xf7, +0x62, +0x62, +0x62, +0x62, +0x7e, +0x62, +0x62, +0x62, +0x62, +0x62, +0xf7, +0x00, +0x00, +0x00, + +0x00, +0x3c, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x1e, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x08, +0xf0, + +0x00, +0xf7, +0x64, +0x6c, +0x68, +0x68, +0x78, +0x6c, +0x6c, +0x6c, +0x66, +0x66, +0xf7, +0x00, +0x00, +0x00, + +0x00, +0xf8, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x61, +0xfe, +0x00, +0x00, +0x00, + +0x00, +0xc3, +0x66, +0x76, +0x7e, +0x56, +0x56, +0x46, +0x46, +0x46, +0x46, +0x46, +0xef, +0x00, +0x00, +0x00, + +0x00, +0xe7, +0x62, +0x62, +0x72, +0x52, +0x5a, +0x4a, +0x4e, +0x46, +0x46, +0x42, +0xe2, +0x00, +0x00, +0x00, + +0x00, +0x3c, +0x66, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0x66, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0xfc, +0x66, +0x66, +0x66, +0x66, +0x6c, +0x60, +0x60, +0x60, +0x60, +0x60, +0xf0, +0x00, +0x00, +0x00, + +0x00, +0x3c, +0x66, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0x66, +0x3c, +0x10, +0x39, +0x0e, + +0x00, +0xfc, +0x66, +0x66, +0x66, +0x66, +0x7c, +0x6c, +0x66, +0x66, +0x66, +0x66, +0xf3, +0x00, +0x00, +0x00, + +0x00, +0x7a, +0xc6, +0xc2, +0xc0, +0x70, +0x3c, +0x0e, +0x06, +0x06, +0x86, +0xc6, +0xbc, +0x00, +0x00, +0x00, + +0x00, +0xff, +0x99, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0xf7, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0xf7, +0x62, +0x62, +0x62, +0x76, +0x34, +0x34, +0x34, +0x3c, +0x18, +0x18, +0x18, +0x00, +0x00, +0x00, + +0x00, +0xf7, +0x62, +0x62, +0x62, +0x62, +0x6a, +0x6a, +0x6a, +0x6a, +0x7e, +0x7e, +0x34, +0x00, +0x00, +0x00, + +0x00, +0xf7, +0x62, +0x62, +0x34, +0x34, +0x18, +0x18, +0x2c, +0x2c, +0x46, +0x46, +0xef, +0x00, +0x00, +0x00, + +0x00, +0xf7, +0x62, +0x62, +0x62, +0x34, +0x34, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x7f, +0x46, +0x86, +0x0c, +0x0c, +0x18, +0x18, +0x30, +0x30, +0x61, +0x62, +0xfe, +0x00, +0x00, +0x00, + +0x00, +0x3c, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x30, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0xc0, +0xc0, +0x60, +0x60, +0x30, +0x30, +0x18, +0x18, +0x0c, +0x0c, +0x06, +0x06, +0x00, +0x00, +0x00, + +0x00, +0x3c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x10, +0x38, +0x4c, +0x86, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xff, +0x00, +0x00, + +0x00, +0x18, +0x20, +0x30, +0x38, +0x10, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x78, +0x8c, +0x0c, +0x3c, +0xcc, +0xcc, +0xcd, +0x76, +0x00, +0x00, +0x00, + +0x00, +0x20, +0xe0, +0x60, +0x60, +0x6c, +0x76, +0x66, +0x66, +0x66, +0x66, +0x76, +0x6c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x3c, +0x66, +0x60, +0x60, +0x60, +0x60, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x04, +0x1c, +0x0c, +0x0c, +0x6c, +0xdc, +0xcc, +0xcc, +0xcc, +0xcc, +0xdc, +0x66, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x3c, +0x66, +0x7e, +0x60, +0x60, +0x60, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x1e, +0x31, +0x33, +0x30, +0x30, +0x78, +0x30, +0x30, +0x30, +0x30, +0x30, +0x78, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x7b, +0xce, +0xcc, +0xcc, +0xcc, +0x78, +0x60, +0x7c, +0x86, +0xc6, +0x7c, + +0x00, +0x20, +0xe0, +0x60, +0x60, +0x6c, +0x76, +0x66, +0x66, +0x66, +0x66, +0x66, +0xf7, +0x00, +0x00, +0x00, + +0x00, +0x10, +0x38, +0x10, +0x00, +0x18, +0x38, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x08, +0x1c, +0x08, +0x00, +0x0c, +0x1c, +0x0c, +0x0c, +0x0c, +0x0c, +0x0c, +0x6c, +0x4c, +0x38, +0x00, + +0x00, +0x20, +0xe0, +0x60, +0x60, +0x67, +0x66, +0x6c, +0x78, +0x6c, +0x6c, +0x66, +0xe7, +0x00, +0x00, +0x00, + +0x00, +0x08, +0x38, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x6a, +0xfe, +0x6a, +0x6a, +0x6a, +0x62, +0x62, +0xf7, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x5c, +0xf6, +0x66, +0x66, +0x66, +0x66, +0x66, +0xf7, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x3c, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x5c, +0xe6, +0x66, +0x66, +0x66, +0x66, +0x66, +0x7c, +0x60, +0x60, +0xf0, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x76, +0xcc, +0xcc, +0xcc, +0xcc, +0xcc, +0xcc, +0x7c, +0x0c, +0x0c, +0x1e, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x5e, +0xf6, +0x60, +0x60, +0x60, +0x60, +0x60, +0xf0, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x7a, +0xc6, +0x72, +0x1c, +0x06, +0x86, +0xc6, +0xbc, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x10, +0x30, +0x7c, +0x30, +0x30, +0x30, +0x30, +0x30, +0x34, +0x18, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0xee, +0x66, +0x66, +0x66, +0x66, +0x66, +0x67, +0x3a, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0xf7, +0x62, +0x76, +0x34, +0x34, +0x3c, +0x18, +0x18, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0xf7, +0x62, +0x6a, +0x6a, +0x6a, +0x6a, +0x7e, +0x24, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0xf7, +0x62, +0x34, +0x18, +0x2c, +0x46, +0x46, +0xef, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0xf7, +0x62, +0x62, +0x34, +0x34, +0x18, +0x18, +0x18, +0x10, +0xb0, +0xe0, + +0x00, +0x00, +0x00, +0x00, +0x00, +0xfe, +0x8c, +0x18, +0x30, +0x30, +0x60, +0xc2, +0xfe, +0x00, +0x00, +0x00, + +0x00, +0x0e, +0x18, +0x10, +0x10, +0x08, +0x70, +0x70, +0x08, +0x10, +0x10, +0x18, +0x0e, +0x00, +0x00, +0x00, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x00, +0x00, + +0x00, +0x70, +0x18, +0x08, +0x08, +0x10, +0x0e, +0x0e, +0x10, +0x08, +0x08, +0x18, +0x70, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x76, +0xdc, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x10, +0x38, +0x6c, +0xc6, +0xc6, +0xc6, +0xfe, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x3a, +0x66, +0xc2, +0xc0, +0xc0, +0xc0, +0xc0, +0xc0, +0x62, +0x3c, +0x18, +0x0c, +0x24, +0x18, + +0x00, +0x00, +0x66, +0x00, +0x00, +0xee, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x3b, +0x00, +0x00, +0x00, + +0x00, +0x0c, +0x18, +0x20, +0x00, +0x3c, +0x66, +0x7e, +0x60, +0x60, +0x60, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x30, +0x58, +0x8c, +0x00, +0x78, +0x8c, +0x0c, +0x3c, +0xcc, +0xcc, +0xcd, +0x76, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x66, +0x00, +0x00, +0x78, +0x8c, +0x0c, +0x3c, +0xcc, +0xcc, +0xcd, +0x76, +0x00, +0x00, +0x00, + +0x00, +0x30, +0x18, +0x04, +0x00, +0x78, +0x8c, +0x0c, +0x3c, +0xcc, +0xcc, +0xcd, +0x76, +0x00, +0x00, +0x00, + +0x38, +0x44, +0x44, +0x38, +0x00, +0x78, +0x8c, +0x0c, +0x3c, +0xcc, +0xcc, +0xcd, +0x76, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x3c, +0x66, +0x60, +0x60, +0x60, +0x60, +0x62, +0x3c, +0x08, +0x24, +0x18, + +0x00, +0x18, +0x2c, +0x46, +0x00, +0x3c, +0x66, +0x7e, +0x60, +0x60, +0x60, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x66, +0x00, +0x00, +0x3c, +0x66, +0x7e, +0x60, +0x60, +0x60, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x30, +0x18, +0x04, +0x00, +0x3c, +0x66, +0x7e, +0x60, +0x60, +0x60, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x66, +0x00, +0x00, +0x38, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x18, +0x2c, +0x46, +0x00, +0x38, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x60, +0x30, +0x08, +0x00, +0x38, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x66, +0x18, +0x18, +0x18, +0x3c, +0x2c, +0x2c, +0x2c, +0x7e, +0x46, +0x46, +0x46, +0xef, +0x00, +0x00, +0x00, + +0x18, +0x24, +0x18, +0x18, +0x3c, +0x2c, +0x2c, +0x2c, +0x7e, +0x46, +0x46, +0x46, +0xef, +0x00, +0x00, +0x00, + +0x0c, +0x18, +0xff, +0x61, +0x60, +0x60, +0x64, +0x7c, +0x64, +0x60, +0x60, +0x61, +0xfe, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x76, +0x9b, +0x1b, +0x3f, +0xd8, +0xd8, +0xd9, +0x6e, +0x00, +0x00, +0x00, + +0x00, +0x1f, +0x1d, +0x1d, +0x3c, +0x2c, +0x2e, +0x2c, +0x7c, +0x4c, +0x4c, +0x4d, +0xef, +0x00, +0x00, +0x00, + +0x00, +0x18, +0x2c, +0x46, +0x00, +0x3c, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x66, +0x00, +0x00, +0x3c, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x30, +0x18, +0x04, +0x00, +0x3c, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x18, +0x2c, +0x46, +0x00, +0xee, +0x66, +0x66, +0x66, +0x66, +0x66, +0x67, +0x3a, +0x00, +0x00, +0x00, + +0x00, +0x30, +0x18, +0x04, +0x00, +0xee, +0x66, +0x66, +0x66, +0x66, +0x66, +0x67, +0x3a, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x66, +0x00, +0x00, +0xf7, +0x62, +0x62, +0x34, +0x34, +0x18, +0x18, +0x18, +0x10, +0xb0, +0xe0, + +0x66, +0x00, +0x3c, +0x66, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0x66, +0x3c, +0x00, +0x00, +0x00, + +0x66, +0x00, +0xf7, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x62, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x10, +0x10, +0x10, +0x7c, +0xc6, +0xc0, +0xc0, +0xc0, +0xc0, +0xc2, +0x7c, +0x10, +0x10, +0x00, + +0x00, +0x38, +0x64, +0x6c, +0x60, +0x60, +0xf0, +0x60, +0x60, +0x60, +0x60, +0x66, +0xfc, +0x00, +0x00, +0x00, + +0x00, +0x81, +0xc3, +0x66, +0x3c, +0x18, +0xff, +0x18, +0x18, +0xff, +0x18, +0x18, +0x18, +0x00, +0x00, +0x00, + +0x00, +0xfe, +0x63, +0x63, +0x63, +0x63, +0x6e, +0x60, +0x64, +0x6e, +0x64, +0x64, +0xf5, +0x06, +0x00, +0x00, + +0x00, +0x0e, +0x19, +0x1b, +0x18, +0x18, +0x3c, +0x18, +0x18, +0x18, +0x18, +0xd8, +0x98, +0x70, +0x00, +0x00, + +0x00, +0x0c, +0x18, +0x20, +0x00, +0x78, +0x8c, +0x0c, +0x3c, +0xcc, +0xcc, +0xcd, +0x76, +0x00, +0x00, +0x00, + +0x00, +0x06, +0x0c, +0x10, +0x00, +0x38, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x0c, +0x18, +0x20, +0x00, +0x3c, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x0c, +0x18, +0x20, +0x00, +0xee, +0x66, +0x66, +0x66, +0x66, +0x66, +0x67, +0x3a, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x32, +0x4c, +0x00, +0x5c, +0xf6, +0x66, +0x66, +0x66, +0x66, +0x66, +0xf7, +0x00, +0x00, +0x00, + +0x32, +0x4c, +0x00, +0xe7, +0x72, +0x52, +0x5a, +0x4a, +0x4e, +0x46, +0x46, +0x42, +0xe2, +0x00, +0x00, +0x00, + +0x00, +0x78, +0x8c, +0x0c, +0x3c, +0xcc, +0xcc, +0xcd, +0x76, +0x00, +0xfe, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x3c, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x3c, +0x00, +0x7e, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x30, +0x30, +0x00, +0x30, +0x10, +0x10, +0x20, +0x40, +0xc0, +0xc6, +0xc2, +0x7c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xfe, +0xc0, +0xc0, +0xc0, +0xc0, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xfe, +0x06, +0x06, +0x06, +0x06, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x20, +0xe0, +0x63, +0x66, +0xfc, +0x18, +0x30, +0x60, +0xce, +0x93, +0x06, +0x0c, +0x1f, +0x00, +0x00, + +0x00, +0x20, +0xe0, +0x63, +0x66, +0xfc, +0x18, +0x30, +0x64, +0xc8, +0x96, +0x3f, +0x06, +0x06, +0x00, +0x00, + +0x00, +0x18, +0x18, +0x00, +0x08, +0x18, +0x18, +0x18, +0x3c, +0x3c, +0x3c, +0x3c, +0x18, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x36, +0x6c, +0xd8, +0xd8, +0x6c, +0x36, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0xd8, +0x6c, +0x36, +0x36, +0x6c, +0xd8, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x82, +0x10, +0x82, +0x10, +0x82, +0x10, +0x82, +0x10, +0x82, +0x10, +0x82, +0x10, +0x82, +0x10, +0x82, +0x10, + +0x00, +0x95, +0x00, +0xa9, +0x00, +0x95, +0x00, +0xa9, +0x00, +0x95, +0x00, +0xa9, +0x00, +0x95, +0x00, +0xa9, + +0x92, +0x49, +0x92, +0x49, +0x92, +0x49, +0x92, +0x49, +0x92, +0x49, +0x92, +0x49, +0x92, +0x49, +0x92, +0x49, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xf8, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xf8, +0x18, +0x18, +0xf8, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0xe6, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xfe, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xf8, +0x18, +0x18, +0xf8, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0xe6, +0x06, +0x06, +0xe6, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xfe, +0x06, +0x06, +0xe6, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0xe6, +0x06, +0x06, +0xfe, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0xfe, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xf8, +0x18, +0x18, +0xf8, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xf8, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x1f, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xff, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xff, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x1f, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xff, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xff, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x1f, +0x18, +0x18, +0x1f, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x67, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x67, +0x60, +0x60, +0x7f, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x7f, +0x60, +0x60, +0x67, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0xe7, +0x00, +0x00, +0xff, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xff, +0x00, +0x00, +0xe7, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x67, +0x60, +0x60, +0x67, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xff, +0x00, +0x00, +0xff, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0xe7, +0x00, +0x00, +0xe7, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xff, +0x00, +0x00, +0xff, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0xff, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xff, +0x00, +0x00, +0xff, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xff, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x7f, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x1f, +0x18, +0x18, +0x1f, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x1f, +0x18, +0x18, +0x1f, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x7f, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0xff, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, +0x66, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xff, +0x00, +0x00, +0xff, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xf8, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x1f, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, + +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, +0xf0, + +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, +0x0f, + +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0xff, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x77, +0xcc, +0xcc, +0xcc, +0xcc, +0xde, +0x73, +0x00, +0x00, +0x00, + +0x00, +0x7c, +0xc6, +0xc6, +0xc6, +0xc4, +0xc8, +0xc4, +0xc6, +0xc6, +0xc6, +0xc6, +0xdc, +0xc0, +0xc0, +0x00, + +0x00, +0xff, +0x61, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0x60, +0xf0, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x01, +0x7e, +0xa4, +0x24, +0x2c, +0x6c, +0x6c, +0x6c, +0x48, +0x00, +0x00, +0x00, + +0x00, +0xff, +0xc1, +0x60, +0x30, +0x18, +0x0c, +0x18, +0x30, +0x60, +0xc0, +0xc1, +0xfe, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x7f, +0xc8, +0xc8, +0xc8, +0xc8, +0xc8, +0xc8, +0x70, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x22, +0x66, +0x66, +0x66, +0x66, +0x66, +0x7c, +0x60, +0x60, +0x60, +0xc0, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x76, +0xdc, +0x18, +0x18, +0x18, +0x18, +0x18, +0x10, +0x00, +0x00, +0x00, + +0x00, +0x38, +0x10, +0x7c, +0xd6, +0xd6, +0xd6, +0xd6, +0xd6, +0xd6, +0x7c, +0x10, +0x38, +0x00, +0x00, +0x00, + +0x00, +0x38, +0x6c, +0xc6, +0xc6, +0xc6, +0xfe, +0xc6, +0xc6, +0xc6, +0xc6, +0x6c, +0x38, +0x00, +0x00, +0x00, + +0x00, +0x3c, +0x66, +0xc3, +0xc3, +0xc3, +0xc3, +0xc3, +0x66, +0x24, +0x24, +0xa5, +0xe7, +0x00, +0x00, +0x00, + +0x00, +0x1e, +0x31, +0x30, +0x18, +0x0c, +0x3e, +0x66, +0x66, +0x66, +0x66, +0x66, +0x3c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x6e, +0xff, +0x99, +0x99, +0x99, +0x99, +0xff, +0x76, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x02, +0x04, +0x7c, +0xca, +0x92, +0xa6, +0x7c, +0x40, +0x80, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x1c, +0x30, +0x60, +0x60, +0x60, +0x7c, +0x60, +0x60, +0x60, +0x60, +0x30, +0x1c, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x7c, +0xc6, +0xc6, +0xc6, +0xc6, +0xc6, +0xc6, +0xc6, +0xc6, +0xc6, +0xc6, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0xfe, +0x00, +0x00, +0x00, +0x7c, +0x00, +0x00, +0x00, +0xfe, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x18, +0x18, +0x7e, +0x18, +0x18, +0x00, +0x00, +0x7e, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x30, +0x18, +0x0c, +0x06, +0x0c, +0x18, +0x30, +0x00, +0x7e, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x0c, +0x18, +0x30, +0x60, +0x30, +0x18, +0x0c, +0x00, +0x7e, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x0e, +0x19, +0x1b, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, + +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0x18, +0xd8, +0x98, +0x70, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x18, +0x18, +0x00, +0x7e, +0x00, +0x18, +0x18, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x76, +0xdc, +0x00, +0x00, +0x76, +0xdc, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x38, +0x44, +0x44, +0x44, +0x38, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x18, +0x18, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x18, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x07, +0x06, +0x06, +0x0c, +0x0c, +0x08, +0x98, +0xd0, +0xf0, +0x60, +0x20, +0x00, +0x00, +0x00, + +0x00, +0xcc, +0x76, +0x66, +0x66, +0x66, +0x66, +0xf7, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x70, +0x98, +0x18, +0x30, +0x60, +0x88, +0xf8, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x7c, +0x64, +0x64, +0x64, +0x64, +0x64, +0x7c, +0x00, +0x00, +0x00, +0x00, + +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, +0x00, + +}; + + +const struct font_desc font_rl = { + RL_IDX, + "RomanLarge", + 8, + 16, + patterns, + -1 +}; diff --git a/drivers/video/console/fonts.c b/drivers/video/console/fonts.c index 4fd07d9eca03..9be83bed1959 100644 --- a/drivers/video/console/fonts.c +++ b/drivers/video/console/fonts.c @@ -64,6 +64,10 @@ static const struct font_desc *fonts[] = { #undef NO_FONTS &font_mini_4x6, #endif +#ifdef CONFIG_FONT_RL +#undef NO_FONTS + &font_rl, +#endif }; #define num_fonts (sizeof(fonts)/sizeof(*fonts)) diff --git a/include/linux/font.h b/include/linux/font.h index 53b129f07f6f..8aac48c37f3d 100644 --- a/include/linux/font.h +++ b/include/linux/font.h @@ -31,6 +31,7 @@ struct font_desc { #define SUN12x22_IDX 7 #define ACORN8x8_IDX 8 #define MINI4x6_IDX 9 +#define RL_IDX 10 extern const struct font_desc font_vga_8x8, font_vga_8x16, @@ -41,6 +42,7 @@ extern const struct font_desc font_vga_8x8, font_sun_8x16, font_sun_12x22, font_acorn_8x8, + font_rl, font_mini_4x6; /* Find a font with a specific name */ -- cgit v1.2.3 From 003cfc0c56977f1c3ce48ddfd2073b7c6d75a5d8 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Mon, 7 Nov 2005 01:00:54 -0800 Subject: [PATCH] fbdev: Add helper to get an appropriate initial mode Add new helper, fb_find_best_display(), which will search the modelist for the best mode for the attached display. This requires an EDID block that is converted to struct fb_monspecs and a private modelist. The search will be done in this manner: - if 1st detailed timing is preferred, use that - else if dimensions of the display are known, use that to estimate xres and - else if modelist has detailed timings, use the first detailed timing - else, use the very first entry from the modelist Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/modedb.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/fb.h | 2 ++ 2 files changed, 62 insertions(+) (limited to 'include/linux') diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c index aadef046ce7b..1789a52d776a 100644 --- a/drivers/video/modedb.c +++ b/drivers/video/modedb.c @@ -944,6 +944,66 @@ void fb_videomode_to_modelist(struct fb_videomode *modedb, int num, } } +struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs, + struct list_head *head) +{ + struct list_head *pos; + struct fb_modelist *modelist; + struct fb_videomode *m, *m1 = NULL, *md = NULL, *best = NULL; + int first = 0; + + if (!head->prev || !head->next || list_empty(head)) + goto finished; + + /* get the first detailed mode and the very first mode */ + list_for_each(pos, head) { + modelist = list_entry(pos, struct fb_modelist, list); + m = &modelist->mode; + + if (!first) { + m1 = m; + first = 1; + } + + if (m->flag & FB_MODE_IS_FIRST) { + md = m; + break; + } + } + + /* first detailed timing is preferred */ + if (specs->misc & FB_MISC_1ST_DETAIL) { + best = md; + goto finished; + } + + /* find best mode based on display width and height */ + if (specs->max_x && specs->max_y) { + struct fb_var_screeninfo var; + + memset(&var, 0, sizeof(struct fb_var_screeninfo)); + var.xres = (specs->max_x * 7200)/254; + var.yres = (specs->max_y * 7200)/254; + m = fb_find_best_mode(&var, head); + if (m) { + best = m; + goto finished; + } + } + + /* use first detailed mode */ + if (md) { + best = md; + goto finished; + } + + /* last resort, use the very first mode */ + best = m1; +finished: + return best; +} +EXPORT_SYMBOL(fb_find_best_display); + EXPORT_SYMBOL(fb_videomode_to_var); EXPORT_SYMBOL(fb_var_to_videomode); EXPORT_SYMBOL(fb_mode_is_equal); diff --git a/include/linux/fb.h b/include/linux/fb.h index 68a787914d85..e7ff98e395f6 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -902,6 +902,8 @@ extern struct fb_videomode *fb_find_nearest_mode(struct fb_videomode *mode, extern void fb_destroy_modelist(struct list_head *head); extern void fb_videomode_to_modelist(struct fb_videomode *modedb, int num, struct list_head *head); +extern struct fb_videomode *fb_find_best_display(struct fb_monspecs *specs, + struct list_head *head); /* drivers/video/fbcmap.c */ extern int fb_alloc_cmap(struct fb_cmap *cmap, int len, int transp); -- cgit v1.2.3 From 63921fbfbd87ec745e65d2e9aecdfdc9a4ce73f2 Mon Sep 17 00:00:00 2001 From: Ville Syrjälä Date: Mon, 7 Nov 2005 01:00:57 -0800 Subject: [PATCH] matroxfb: Add support for Mystique AGP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add new entries for Mystique AGP with the PCI ID 0x051e. I don't actually have such boards but according to google they do exist. Curiosly X.Org doesn't recognize that PCI ID. And what's even more interesting is that Matrox's own Windows drivers don't recognize it either. After going through about a dozen different versions I did find one older driver that does list this particular ID. It is also listed in the pci.ids file. I'm not sure if non-220 AGP chips exist. I left the chip revision check intact for AGP chips nonetheless. Signed-off-by: Ville Syrjälä Signed-off-by: Petr Vandrovec Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/matrox/matroxfb_base.c | 14 ++++++++++++++ include/linux/pci_ids.h | 1 + 2 files changed, 15 insertions(+) (limited to 'include/linux') diff --git a/drivers/video/matrox/matroxfb_base.c b/drivers/video/matrox/matroxfb_base.c index 5f2df1725e6e..1734438f7d7c 100644 --- a/drivers/video/matrox/matroxfb_base.c +++ b/drivers/video/matrox/matroxfb_base.c @@ -1428,6 +1428,20 @@ static struct board { MGA_1164, &vbMystique, "Mystique 220 (PCI)"}, + {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS_AGP, 0x02, + 0, 0, + DEVF_VIDEO64BIT | DEVF_CROSS4MB, + 180000, + MGA_1064, + &vbMystique, + "Mystique (AGP)"}, + {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_MYS_AGP, 0xFF, + 0, 0, + DEVF_VIDEO64BIT | DEVF_SWAPS | DEVF_CROSS4MB, + 220000, + MGA_1164, + &vbMystique, + "Mystique 220 (AGP)"}, #endif #ifdef CONFIG_FB_MATROX_G {PCI_VENDOR_ID_MATROX, PCI_DEVICE_ID_MATROX_G100_MM, 0xFF, diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 88de3f8ce1a2..cd62a39ce068 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -519,6 +519,7 @@ #define PCI_DEVICE_ID_MATROX_MIL 0x0519 #define PCI_DEVICE_ID_MATROX_MYS 0x051A #define PCI_DEVICE_ID_MATROX_MIL_2 0x051b +#define PCI_DEVICE_ID_MATROX_MYS_AGP 0x051e #define PCI_DEVICE_ID_MATROX_MIL_2_AGP 0x051f #define PCI_DEVICE_ID_MATROX_MGA_IMP 0x0d10 #define PCI_DEVICE_ID_MATROX_G100_MM 0x1000 -- cgit v1.2.3 From 6c8bec6d5f24b01c53b792b06a645e78d482020d Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 7 Nov 2005 01:01:04 -0800 Subject: [PATCH] jbd doc: fix some kernel-doc warnings Add structure fields kernel-doc for 2 fields in struct journal_s. Warning(/var/linsrc/linux-2614-rc4//include/linux/jbd.h:808): No description found for parameter 'j_wbuf' Warning(/var/linsrc/linux-2614-rc4//include/linux/jbd.h:808): No description found for parameter 'j_wbufsize' Convert fs/jbd/recovery.c non-static functions to kernel-doc format. fs/jbd/recovery.c doesn't export any symbols, so it should use !I instead of !E to eliminate this warning message: Warning(/var/linsrc/linux-2614-rc4//fs/jbd/recovery.c): no structured comments found Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/DocBook/journal-api.tmpl | 2 +- fs/jbd/recovery.c | 4 ++-- include/linux/jbd.h | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/Documentation/DocBook/journal-api.tmpl b/Documentation/DocBook/journal-api.tmpl index 341aaa4ce481..2077f9a28c19 100644 --- a/Documentation/DocBook/journal-api.tmpl +++ b/Documentation/DocBook/journal-api.tmpl @@ -306,7 +306,7 @@ an example. Journal Level !Efs/jbd/journal.c -!Efs/jbd/recovery.c +!Ifs/jbd/recovery.c Transasction Level !Efs/jbd/transaction.c diff --git a/fs/jbd/recovery.c b/fs/jbd/recovery.c index 103c34e4fb28..80d7f53fd0a7 100644 --- a/fs/jbd/recovery.c +++ b/fs/jbd/recovery.c @@ -210,7 +210,7 @@ do { \ } while (0) /** - * int journal_recover(journal_t *journal) - recovers a on-disk journal + * journal_recover - recovers a on-disk journal * @journal: the journal to recover * * The primary function for recovering the log contents when mounting a @@ -266,7 +266,7 @@ int journal_recover(journal_t *journal) } /** - * int journal_skip_recovery() - Start journal and wipe exiting records + * journal_skip_recovery - Start journal and wipe exiting records * @journal: journal to startup * * Locate any valid recovery information from the journal and set up the diff --git a/include/linux/jbd.h b/include/linux/jbd.h index be197eb90077..aa56172c6fed 100644 --- a/include/linux/jbd.h +++ b/include/linux/jbd.h @@ -611,6 +611,9 @@ struct transaction_s * @j_revoke: The revoke table - maintains the list of revoked blocks in the * current transaction. * @j_revoke_table: alternate revoke tables for j_revoke + * @j_wbuf: array of buffer_heads for journal_commit_transaction + * @j_wbufsize: maximum number of buffer_heads allowed in j_wbuf, the + * number that will fit in j_blocksize * @j_private: An opaque pointer to fs-private information. */ -- cgit v1.2.3 From 8f2709b542c96a2b1910ca5f2fe27dc9023b1225 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 7 Nov 2005 01:01:05 -0800 Subject: [PATCH] kernel-doc: fix some kernel-api warnings Fix various warnings in kernel-doc: Warning(linux-2614-rc4//include/linux/net.h:89): Enum value 'SOCK_DCCP' not described in enum 'sock_type' usercopy.c: should use !E instead of !I for exported symbols: Warning(linux-2614-rc4//arch/i386/lib/usercopy.c): no structured comments found fs.h does not need to use !E since it has no exported symbols: Warning(linux-2614-rc4//include/linux/fs.h:1182): No description found for parameter 'find_exported_dentry' Warning(linux-2614-rc4//include/linux/fs.h): no structured comments found irq/manage.c should use !E for its exported symbols: Warning(linux-2614-rc4//kernel/irq/manage.c): no structured comments found macmodes.c should use !E for its exported symbols: Warning(linux-2614-rc4//drivers/video/macmodes.c): no structured comments found Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/DocBook/kernel-api.tmpl | 7 +++---- include/linux/fs.h | 2 ++ include/linux/net.h | 1 + 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index ec474e5a25ed..a8316b1a3e3d 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl @@ -118,7 +118,7 @@ X!Ilib/string.c User Space Memory Access !Iinclude/asm-i386/uaccess.h -!Iarch/i386/lib/usercopy.c +!Earch/i386/lib/usercopy.c More Memory Management Functions !Iinclude/linux/rmap.h @@ -174,7 +174,6 @@ X!Ilib/string.c The Linux VFS The Filesystem types !Iinclude/linux/fs.h -!Einclude/linux/fs.h The Directory Cache !Efs/dcache.c @@ -266,7 +265,7 @@ X!Ekernel/module.c Hardware Interfaces Interrupt Handling -!Ikernel/irq/manage.c +!Ekernel/irq/manage.c Resources Management @@ -501,7 +500,7 @@ KAO --> !Edrivers/video/modedb.c Frame Buffer Macintosh Video Mode Database -!Idrivers/video/macmodes.c +!Edrivers/video/macmodes.c Frame Buffer Fonts diff --git a/include/linux/fs.h b/include/linux/fs.h index 0c89fc9481a8..9a593ef262ef 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1096,6 +1096,8 @@ int sync_inode(struct inode *inode, struct writeback_control *wbc); * @get_name: find the name for a given inode in a given directory * @get_parent: find the parent of a given directory * @get_dentry: find a dentry for the inode given a file handle sub-fragment + * @find_exported_dentry: + * set by the exporting module to a standard helper function. * * Description: * The export_operations structure provides a means for nfsd to communicate diff --git a/include/linux/net.h b/include/linux/net.h index 4e981585a89a..d6a41e6577f6 100644 --- a/include/linux/net.h +++ b/include/linux/net.h @@ -71,6 +71,7 @@ typedef enum { * @SOCK_RAW: raw socket * @SOCK_RDM: reliably-delivered message * @SOCK_SEQPACKET: sequential packet socket + * @SOCK_DCCP: Datagram Congestion Control Protocol socket * @SOCK_PACKET: linux specific way of getting packets at the dev level. * For writing rarp and other similar things on the user level. * -- cgit v1.2.3 From b8887e6e8c04bcefb512cdb08fc7e9c310ac847e Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 7 Nov 2005 01:01:07 -0800 Subject: [PATCH] kernel-docs: fix kernel-doc format problems Convert to proper kernel-doc format. Some have extra blank lines (not allowed immed. after the function name) or need blank lines (after all parameters). Function summary must be only one line. Colon (":") in a function description does weird things (causes kernel-doc to think that it's a new section head sadly). Signed-off-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/ll_rw_blk.c | 1 - fs/fs-writeback.c | 5 +++-- include/linux/kernel.h | 1 - kernel/sys.c | 2 +- 4 files changed, 4 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 2747741677fb..5f52e30b43f8 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -706,7 +706,6 @@ EXPORT_SYMBOL(blk_queue_dma_alignment); /** * blk_queue_find_tag - find a request by its tag and queue - * * @q: The request queue for the device * @tag: The tag of the request * diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 1361a4a64157..785c7213a54f 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -606,7 +606,7 @@ EXPORT_SYMBOL(sync_inode); * O_SYNC flag set, to flush dirty writes to disk. * * @what is a bitmask, specifying which part of the inode's data should be - * written and waited upon: + * written and waited upon. * * OSYNC_DATA: i_mapping's dirty data * OSYNC_METADATA: the buffers at i_mapping->private_list @@ -672,8 +672,9 @@ int writeback_acquire(struct backing_dev_info *bdi) /** * writeback_in_progress: determine whether there is writeback in progress - * against a backing device. * @bdi: the device's backing_dev_info structure. + * + * Determine whether there is writeback in progress against a backing device. */ int writeback_in_progress(struct backing_dev_info *bdi) { diff --git a/include/linux/kernel.h b/include/linux/kernel.h index f1925ccc9fe1..b6419489b27b 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -266,7 +266,6 @@ extern void dump_stack(void); /** * container_of - cast a member of a structure out to the containing structure - * * @ptr: the pointer to the member. * @type: the type of the container struct this is embedded in. * @member: the name of the member within the struct. diff --git a/kernel/sys.c b/kernel/sys.c index 3e332131000e..bce933ebb29f 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -386,7 +386,7 @@ void kernel_restart_prepare(char *cmd) /** * kernel_restart - reboot the system * @cmd: pointer to buffer containing command to execute for restart - * or NULL + * or %NULL * * Shutdown everything and perform a clean reboot. * This is not safe to call in interrupt context. -- cgit v1.2.3 From 24622efd11fc5ee569b008b9f89e5e268265811b Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 01:01:44 -0800 Subject: [PATCH] __deprecated_for_modules: insert_resource This looks like something which out-of-tree code could possibly be using. Give insert_resource the twelve-month treatment. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/feature-removal-schedule.txt | 8 ++++++++ include/linux/ioport.h | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index b67189a8d8d4..7fd8c80fa0fc 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -69,6 +69,14 @@ Who: Grant Coady --------------------------- +What: remove EXPORT_SYMBOL(insert_resource) +When: April 2006 +Files: kernel/resource.c +Why: No modular usage in the kernel. +Who: Adrian Bunk + +--------------------------- + What: PCMCIA control ioctl (needed for pcmcia-cs [cardmgr, cardctl]) When: November 2005 Files: drivers/pcmcia/: pcmcia_ioctl.c diff --git a/include/linux/ioport.h b/include/linux/ioport.h index 18d010bee635..cd6bd001ba4e 100644 --- a/include/linux/ioport.h +++ b/include/linux/ioport.h @@ -94,7 +94,7 @@ extern struct resource iomem_resource; extern int request_resource(struct resource *root, struct resource *new); extern struct resource * ____request_resource(struct resource *root, struct resource *new); extern int release_resource(struct resource *new); -extern int insert_resource(struct resource *parent, struct resource *new); +extern __deprecated_for_modules int insert_resource(struct resource *parent, struct resource *new); extern int allocate_resource(struct resource *root, struct resource *new, unsigned long size, unsigned long min, unsigned long max, -- cgit v1.2.3 From dfed04492f2459e47dcb290be6ed5a8bc37096d5 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 01:01:44 -0800 Subject: [PATCH] __deprecated_for_modules: panic_timeout This looks like something which out-of-tree code could possibly be using. Give panic_timeout the twelve-month treatment. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/feature-removal-schedule.txt | 8 ++++++++ include/linux/kernel.h | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 7fd8c80fa0fc..decdf9917e0d 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -69,6 +69,14 @@ Who: Grant Coady --------------------------- +What: remove EXPORT_SYMBOL(panic_timeout) +When: April 2006 +Files: kernel/panic.c +Why: No modular usage in the kernel. +Who: Adrian Bunk + +--------------------------- + What: remove EXPORT_SYMBOL(insert_resource) When: April 2006 Files: kernel/resource.c diff --git a/include/linux/kernel.h b/include/linux/kernel.h index b6419489b27b..b1e407a4fbda 100644 --- a/include/linux/kernel.h +++ b/include/linux/kernel.h @@ -168,7 +168,7 @@ static inline void console_verbose(void) extern void bust_spinlocks(int yes); extern int oops_in_progress; /* If set, an oops, panic(), BUG() or die() is in progress */ -extern int panic_timeout; +extern __deprecated_for_modules int panic_timeout; extern int panic_on_oops; extern int tainted; extern const char *print_tainted(void); -- cgit v1.2.3 From b449f63c8ce4a517cb91f237cc3d68d083ec2dd3 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 7 Nov 2005 01:01:48 -0800 Subject: [PATCH] drivers/pnp/: cleanups This patch contains the following possible cleanups: - make needlessly global code static - #if 0 the following unused global function: - core.c: pnp_remove_device - #if 0 the following unneeded EXPORT_SYMBOL's: - card.c: pnp_add_card - card.c: pnp_remove_card - card.c: pnp_add_card_device - card.c: pnp_remove_card_device - card.c: pnp_add_card_id - core.c: pnp_register_protocol - core.c: pnp_unregister_protocol - core.c: pnp_add_device - core.c: pnp_remove_device - pnpacpi/core.c: pnpacpi_protocol - driver.c: pnp_add_id - isapnp/core.c: isapnp_read_byte - manager.c: pnp_auto_config_dev - resource.c: pnp_register_dependent_option - resource.c: pnp_register_independent_option - resource.c: pnp_register_irq_resource - resource.c: pnp_register_dma_resource - resource.c: pnp_register_port_resource - resource.c: pnp_register_mem_resource Note that this patch #if 0's exactly one functions and removes no functions. Most it does is the #if 0 of EXPORT_SYMBOL's, so if any modular code will use any of them, re-adding will be trivial. Modular ISAPnP might be interesting in some cases, but this is more legacy code. If someone would work on it to sort all the issues out (starting with the point that most users of __ISAPNP__ will have to be fixed) re-enabling the required EXPORT_SYMBOL's won't be hard for him. Signed-off-by: Adrian Bunk Cc: Adam Belay Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pnp/card.c | 4 +++- drivers/pnp/core.c | 5 ++++- drivers/pnp/driver.c | 2 ++ drivers/pnp/isapnp/core.c | 2 ++ drivers/pnp/manager.c | 2 ++ drivers/pnp/pnpacpi/core.c | 6 ++++-- drivers/pnp/resource.c | 2 ++ include/linux/pnp.h | 2 -- 8 files changed, 19 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c index e95ed67d4f05..bd7c966ea2d7 100644 --- a/drivers/pnp/card.c +++ b/drivers/pnp/card.c @@ -12,7 +12,7 @@ #include "base.h" LIST_HEAD(pnp_cards); -LIST_HEAD(pnp_card_drivers); +static LIST_HEAD(pnp_card_drivers); static const struct pnp_card_device_id * match_card(struct pnp_card_driver * drv, struct pnp_card * card) @@ -374,11 +374,13 @@ void pnp_unregister_card_driver(struct pnp_card_driver * drv) pnp_unregister_driver(&drv->link); } +#if 0 EXPORT_SYMBOL(pnp_add_card); EXPORT_SYMBOL(pnp_remove_card); EXPORT_SYMBOL(pnp_add_card_device); EXPORT_SYMBOL(pnp_remove_card_device); EXPORT_SYMBOL(pnp_add_card_id); +#endif /* 0 */ EXPORT_SYMBOL(pnp_request_card_device); EXPORT_SYMBOL(pnp_release_card_device); EXPORT_SYMBOL(pnp_register_card_driver); diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c index deed92459bc5..aec83ec5ea23 100644 --- a/drivers/pnp/core.c +++ b/drivers/pnp/core.c @@ -158,13 +158,14 @@ void __pnp_remove_device(struct pnp_dev *dev) * * this function will free all mem used by dev */ - +#if 0 void pnp_remove_device(struct pnp_dev *dev) { if (!dev || dev->card) return; __pnp_remove_device(dev); } +#endif /* 0 */ static int __init pnp_init(void) { @@ -174,7 +175,9 @@ static int __init pnp_init(void) subsys_initcall(pnp_init); +#if 0 EXPORT_SYMBOL(pnp_register_protocol); EXPORT_SYMBOL(pnp_unregister_protocol); EXPORT_SYMBOL(pnp_add_device); EXPORT_SYMBOL(pnp_remove_device); +#endif /* 0 */ diff --git a/drivers/pnp/driver.c b/drivers/pnp/driver.c index 33da25f3213f..d3ccce706ab4 100644 --- a/drivers/pnp/driver.c +++ b/drivers/pnp/driver.c @@ -214,6 +214,8 @@ int pnp_add_id(struct pnp_id *id, struct pnp_dev *dev) EXPORT_SYMBOL(pnp_register_driver); EXPORT_SYMBOL(pnp_unregister_driver); +#if 0 EXPORT_SYMBOL(pnp_add_id); +#endif EXPORT_SYMBOL(pnp_device_attach); EXPORT_SYMBOL(pnp_device_detach); diff --git a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c index beedd86800f4..57fd60314d59 100644 --- a/drivers/pnp/isapnp/core.c +++ b/drivers/pnp/isapnp/core.c @@ -941,7 +941,9 @@ EXPORT_SYMBOL(isapnp_protocol); EXPORT_SYMBOL(isapnp_present); EXPORT_SYMBOL(isapnp_cfg_begin); EXPORT_SYMBOL(isapnp_cfg_end); +#if 0 EXPORT_SYMBOL(isapnp_read_byte); +#endif EXPORT_SYMBOL(isapnp_write_byte); static int isapnp_read_resources(struct pnp_dev *dev, struct pnp_resource_table *res) diff --git a/drivers/pnp/manager.c b/drivers/pnp/manager.c index cbb2749db178..261668618b2d 100644 --- a/drivers/pnp/manager.c +++ b/drivers/pnp/manager.c @@ -555,7 +555,9 @@ void pnp_resource_change(struct resource *resource, unsigned long start, unsigne EXPORT_SYMBOL(pnp_manual_config_dev); +#if 0 EXPORT_SYMBOL(pnp_auto_config_dev); +#endif EXPORT_SYMBOL(pnp_activate_dev); EXPORT_SYMBOL(pnp_disable_dev); EXPORT_SYMBOL(pnp_resource_change); diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 1a8915e74160..816479ad217b 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c @@ -117,7 +117,7 @@ static int pnpacpi_disable_resources(struct pnp_dev *dev) return ACPI_FAILURE(status) ? -ENODEV : 0; } -struct pnp_protocol pnpacpi_protocol = { +static struct pnp_protocol pnpacpi_protocol = { .name = "Plug and Play ACPI", .get = pnpacpi_get_resources, .set = pnpacpi_set_resources, @@ -234,7 +234,7 @@ static acpi_status __init pnpacpi_add_device_handler(acpi_handle handle, } int pnpacpi_disabled __initdata; -int __init pnpacpi_init(void) +static int __init pnpacpi_init(void) { if (acpi_disabled || pnpacpi_disabled) { pnp_info("PnP ACPI: disabled"); @@ -258,4 +258,6 @@ static int __init pnpacpi_setup(char *str) } __setup("pnpacpi=", pnpacpi_setup); +#if 0 EXPORT_SYMBOL(pnpacpi_protocol); +#endif diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 887ad8939349..6ded527169f4 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c @@ -477,12 +477,14 @@ int pnp_check_dma(struct pnp_dev * dev, int idx) } +#if 0 EXPORT_SYMBOL(pnp_register_dependent_option); EXPORT_SYMBOL(pnp_register_independent_option); EXPORT_SYMBOL(pnp_register_irq_resource); EXPORT_SYMBOL(pnp_register_dma_resource); EXPORT_SYMBOL(pnp_register_port_resource); EXPORT_SYMBOL(pnp_register_mem_resource); +#endif /* 0 */ /* format is: pnp_reserve_irq=irq1[,irq2] .... */ diff --git a/include/linux/pnp.h b/include/linux/pnp.h index aadbac29103c..584d57cb393a 100644 --- a/include/linux/pnp.h +++ b/include/linux/pnp.h @@ -353,7 +353,6 @@ struct pnp_protocol { int pnp_register_protocol(struct pnp_protocol *protocol); void pnp_unregister_protocol(struct pnp_protocol *protocol); int pnp_add_device(struct pnp_dev *dev); -void pnp_remove_device(struct pnp_dev *dev); int pnp_device_attach(struct pnp_dev *pnp_dev); void pnp_device_detach(struct pnp_dev *pnp_dev); extern struct list_head pnp_global; @@ -399,7 +398,6 @@ static inline int pnp_register_protocol(struct pnp_protocol *protocol) { return static inline void pnp_unregister_protocol(struct pnp_protocol *protocol) { } static inline int pnp_init_device(struct pnp_dev *dev) { return -ENODEV; } static inline int pnp_add_device(struct pnp_dev *dev) { return -ENODEV; } -static inline void pnp_remove_device(struct pnp_dev *dev) { } static inline int pnp_device_attach(struct pnp_dev *pnp_dev) { return -ENODEV; } static inline void pnp_device_detach(struct pnp_dev *pnp_dev) { ; } -- cgit v1.2.3 From 183d020258dfd08178a05c6793dae10409db8abb Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 7 Nov 2005 14:29:02 +1100 Subject: [PATCH] ppc64: SMU partition recovery This patch adds the ability to the SMU driver to recover missing calibration partitions from the SMU chip itself. It also adds some dynamic mecanism to /proc/device-tree so that new properties are visible to userland. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Paul Mackerras --- arch/powerpc/kernel/prom.c | 21 +++++- arch/ppc/syslib/prom.c | 4 +- arch/ppc64/kernel/prom.c | 24 +++++-- drivers/macintosh/smu.c | 164 ++++++++++++++++++++++++++++++++++++++++++--- fs/proc/proc_devtree.c | 57 ++++++++++------ include/asm-powerpc/prom.h | 2 +- include/asm-powerpc/smu.h | 153 +++++++++++++++++++++++++++++++++++++++--- include/asm-ppc/prom.h | 2 +- include/asm-ppc64/prom.h | 2 +- include/linux/proc_fs.h | 9 +-- 10 files changed, 381 insertions(+), 57 deletions(-) (limited to 'include/linux') diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 3675ef4bac90..f645adb57534 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -1974,14 +1974,29 @@ EXPORT_SYMBOL(get_property); /* * Add a property to a node */ -void prom_add_property(struct device_node* np, struct property* prop) +int prom_add_property(struct device_node* np, struct property* prop) { - struct property **next = &np->properties; + struct property **next; prop->next = NULL; - while (*next) + write_lock(&devtree_lock); + next = &np->properties; + while (*next) { + if (strcmp(prop->name, (*next)->name) == 0) { + /* duplicate ! don't insert it */ + write_unlock(&devtree_lock); + return -1; + } next = &(*next)->next; + } *next = prop; + write_unlock(&devtree_lock); + + /* try to add to proc as well if it was initialized */ + if (np->pde) + proc_device_tree_add_prop(np->pde, prop); + + return 0; } /* I quickly hacked that one, check against spec ! */ diff --git a/arch/ppc/syslib/prom.c b/arch/ppc/syslib/prom.c index 1b9aa0d6a924..03b1fc9b9501 100644 --- a/arch/ppc/syslib/prom.c +++ b/arch/ppc/syslib/prom.c @@ -1165,7 +1165,7 @@ get_property(struct device_node *np, const char *name, int *lenp) /* * Add a property to a node */ -void +int prom_add_property(struct device_node* np, struct property* prop) { struct property **next = &np->properties; @@ -1174,6 +1174,8 @@ prom_add_property(struct device_node* np, struct property* prop) while (*next) next = &(*next)->next; *next = prop; + + return 0; } /* I quickly hacked that one, check against spec ! */ diff --git a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c index 0e8961dea3bc..3402fbee62c7 100644 --- a/arch/ppc64/kernel/prom.c +++ b/arch/ppc64/kernel/prom.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -1865,17 +1866,32 @@ get_property(struct device_node *np, const char *name, int *lenp) EXPORT_SYMBOL(get_property); /* - * Add a property to a node + * Add a property to a node. */ -void +int prom_add_property(struct device_node* np, struct property* prop) { - struct property **next = &np->properties; + struct property **next; prop->next = NULL; - while (*next) + write_lock(&devtree_lock); + next = &np->properties; + while (*next) { + if (strcmp(prop->name, (*next)->name) == 0) { + /* duplicate ! don't insert it */ + write_unlock(&devtree_lock); + return -1; + } next = &(*next)->next; + } *next = prop; + write_unlock(&devtree_lock); + + /* try to add to proc as well if it was initialized */ + if (np->pde) + proc_device_tree_add_prop(np->pde, prop); + + return 0; } #if 0 diff --git a/drivers/macintosh/smu.c b/drivers/macintosh/smu.c index a931e508feb6..a83c4acf5710 100644 --- a/drivers/macintosh/smu.c +++ b/drivers/macintosh/smu.c @@ -47,13 +47,13 @@ #include #include -#define VERSION "0.6" +#define VERSION "0.7" #define AUTHOR "(c) 2005 Benjamin Herrenschmidt, IBM Corp." #undef DEBUG_SMU #ifdef DEBUG_SMU -#define DPRINTK(fmt, args...) do { printk(KERN_DEBUG fmt , ##args); } while (0) +#define DPRINTK(fmt, args...) do { udbg_printf(KERN_DEBUG fmt , ##args); } while (0) #else #define DPRINTK(fmt, args...) do { } while (0) #endif @@ -92,7 +92,7 @@ struct smu_device { * for now, just hard code that */ static struct smu_device *smu; - +static DECLARE_MUTEX(smu_part_access); /* * SMU driver low level stuff @@ -113,9 +113,11 @@ static void smu_start_cmd(void) DPRINTK("SMU: starting cmd %x, %d bytes data\n", cmd->cmd, cmd->data_len); - DPRINTK("SMU: data buffer: %02x %02x %02x %02x ...\n", + DPRINTK("SMU: data buffer: %02x %02x %02x %02x %02x %02x %02x %02x\n", ((u8 *)cmd->data_buf)[0], ((u8 *)cmd->data_buf)[1], - ((u8 *)cmd->data_buf)[2], ((u8 *)cmd->data_buf)[3]); + ((u8 *)cmd->data_buf)[2], ((u8 *)cmd->data_buf)[3], + ((u8 *)cmd->data_buf)[4], ((u8 *)cmd->data_buf)[5], + ((u8 *)cmd->data_buf)[6], ((u8 *)cmd->data_buf)[7]); /* Fill the SMU command buffer */ smu->cmd_buf->cmd = cmd->cmd; @@ -440,7 +442,7 @@ int smu_present(void) EXPORT_SYMBOL(smu_present); -int smu_init (void) +int __init smu_init (void) { struct device_node *np; u32 *data; @@ -845,16 +847,154 @@ int smu_queue_i2c(struct smu_i2c_cmd *cmd) return 0; } -struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size) +/* + * Handling of "partitions" + */ + +static int smu_read_datablock(u8 *dest, unsigned int addr, unsigned int len) +{ + DECLARE_COMPLETION(comp); + unsigned int chunk; + struct smu_cmd cmd; + int rc; + u8 params[8]; + + /* We currently use a chunk size of 0xe. We could check the + * SMU firmware version and use bigger sizes though + */ + chunk = 0xe; + + while (len) { + unsigned int clen = min(len, chunk); + + cmd.cmd = SMU_CMD_MISC_ee_COMMAND; + cmd.data_len = 7; + cmd.data_buf = params; + cmd.reply_len = chunk; + cmd.reply_buf = dest; + cmd.done = smu_done_complete; + cmd.misc = ∁ + params[0] = SMU_CMD_MISC_ee_GET_DATABLOCK_REC; + params[1] = 0x4; + *((u32 *)¶ms[2]) = addr; + params[6] = clen; + + rc = smu_queue_cmd(&cmd); + if (rc) + return rc; + wait_for_completion(&comp); + if (cmd.status != 0) + return rc; + if (cmd.reply_len != clen) { + printk(KERN_DEBUG "SMU: short read in " + "smu_read_datablock, got: %d, want: %d\n", + cmd.reply_len, clen); + return -EIO; + } + len -= clen; + addr += clen; + dest += clen; + } + return 0; +} + +static struct smu_sdbp_header *smu_create_sdb_partition(int id) +{ + DECLARE_COMPLETION(comp); + struct smu_simple_cmd cmd; + unsigned int addr, len, tlen; + struct smu_sdbp_header *hdr; + struct property *prop; + + /* First query the partition info */ + smu_queue_simple(&cmd, SMU_CMD_PARTITION_COMMAND, 2, + smu_done_complete, &comp, + SMU_CMD_PARTITION_LATEST, id); + wait_for_completion(&comp); + + /* Partition doesn't exist (or other error) */ + if (cmd.cmd.status != 0 || cmd.cmd.reply_len != 6) + return NULL; + + /* Fetch address and length from reply */ + addr = *((u16 *)cmd.buffer); + len = cmd.buffer[3] << 2; + /* Calucluate total length to allocate, including the 17 bytes + * for "sdb-partition-XX" that we append at the end of the buffer + */ + tlen = sizeof(struct property) + len + 18; + + prop = kcalloc(tlen, 1, GFP_KERNEL); + if (prop == NULL) + return NULL; + hdr = (struct smu_sdbp_header *)(prop + 1); + prop->name = ((char *)prop) + tlen - 18; + sprintf(prop->name, "sdb-partition-%02x", id); + prop->length = len; + prop->value = (unsigned char *)hdr; + prop->next = NULL; + + /* Read the datablock */ + if (smu_read_datablock((u8 *)hdr, addr, len)) { + printk(KERN_DEBUG "SMU: datablock read failed while reading " + "partition %02x !\n", id); + goto failure; + } + + /* Got it, check a few things and create the property */ + if (hdr->id != id) { + printk(KERN_DEBUG "SMU: Reading partition %02x and got " + "%02x !\n", id, hdr->id); + goto failure; + } + if (prom_add_property(smu->of_node, prop)) { + printk(KERN_DEBUG "SMU: Failed creating sdb-partition-%02x " + "property !\n", id); + goto failure; + } + + return hdr; + failure: + kfree(prop); + return NULL; +} + +/* Note: Only allowed to return error code in pointers (using ERR_PTR) + * when interruptible is 1 + */ +struct smu_sdbp_header *__smu_get_sdb_partition(int id, unsigned int *size, + int interruptible) { char pname[32]; + struct smu_sdbp_header *part; if (!smu) return NULL; sprintf(pname, "sdb-partition-%02x", id); - return (struct smu_sdbp_header *)get_property(smu->of_node, + + if (interruptible) { + int rc; + rc = down_interruptible(&smu_part_access); + if (rc) + return ERR_PTR(rc); + } else + down(&smu_part_access); + + part = (struct smu_sdbp_header *)get_property(smu->of_node, pname, size); + if (part == NULL) { + part = smu_create_sdb_partition(id); + if (part != NULL && size) + *size = part->len << 2; + } + up(&smu_part_access); + return part; +} + +struct smu_sdbp_header *smu_get_sdb_partition(int id, unsigned int *size) +{ + return __smu_get_sdb_partition(id, size, 0); } EXPORT_SYMBOL(smu_get_sdb_partition); @@ -930,6 +1070,14 @@ static ssize_t smu_write(struct file *file, const char __user *buf, else if (hdr.cmdtype == SMU_CMDTYPE_WANTS_EVENTS) { pp->mode = smu_file_events; return 0; + } else if (hdr.cmdtype == SMU_CMDTYPE_GET_PARTITION) { + struct smu_sdbp_header *part; + part = __smu_get_sdb_partition(hdr.cmd, NULL, 1); + if (part == NULL) + return -EINVAL; + else if (IS_ERR(part)) + return PTR_ERR(part); + return 0; } else if (hdr.cmdtype != SMU_CMDTYPE_SMU) return -EINVAL; else if (pp->mode != smu_file_commands) diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c index 6fd57f154197..fb117b74809e 100644 --- a/fs/proc/proc_devtree.c +++ b/fs/proc/proc_devtree.c @@ -48,6 +48,39 @@ static int property_read_proc(char *page, char **start, off_t off, * and "@10" to it. */ +/* + * Add a property to a node + */ +static struct proc_dir_entry * +__proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp) +{ + struct proc_dir_entry *ent; + + /* + * Unfortunately proc_register puts each new entry + * at the beginning of the list. So we rearrange them. + */ + ent = create_proc_read_entry(pp->name, + strncmp(pp->name, "security-", 9) + ? S_IRUGO : S_IRUSR, de, + property_read_proc, pp); + if (ent == NULL) + return NULL; + + if (!strncmp(pp->name, "security-", 9)) + ent->size = 0; /* don't leak number of password chars */ + else + ent->size = pp->length; + + return ent; +} + + +void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop) +{ + __proc_device_tree_add_prop(pde, prop); +} + /* * Process a node, adding entries for its children and its properties. */ @@ -57,11 +90,9 @@ void proc_device_tree_add_node(struct device_node *np, struct property *pp; struct proc_dir_entry *ent; struct device_node *child; - struct proc_dir_entry *list = NULL, **lastp; const char *p; set_node_proc_entry(np, de); - lastp = &list; for (child = NULL; (child = of_get_next_child(np, child));) { p = strrchr(child->full_name, '/'); if (!p) @@ -71,9 +102,6 @@ void proc_device_tree_add_node(struct device_node *np, ent = proc_mkdir(p, de); if (ent == 0) break; - *lastp = ent; - ent->next = NULL; - lastp = &ent->next; proc_device_tree_add_node(child, ent); } of_node_put(child); @@ -84,7 +112,7 @@ void proc_device_tree_add_node(struct device_node *np, * properties are quite unimportant for us though, thus we * simply "skip" them here, but we do have to check. */ - for (ent = list; ent != NULL; ent = ent->next) + for (ent = de->subdir; ent != NULL; ent = ent->next) if (!strcmp(ent->name, pp->name)) break; if (ent != NULL) { @@ -94,25 +122,10 @@ void proc_device_tree_add_node(struct device_node *np, continue; } - /* - * Unfortunately proc_register puts each new entry - * at the beginning of the list. So we rearrange them. - */ - ent = create_proc_read_entry(pp->name, - strncmp(pp->name, "security-", 9) - ? S_IRUGO : S_IRUSR, de, - property_read_proc, pp); + ent = __proc_device_tree_add_prop(de, pp); if (ent == 0) break; - if (!strncmp(pp->name, "security-", 9)) - ent->size = 0; /* don't leak number of password chars */ - else - ent->size = pp->length; - ent->next = NULL; - *lastp = ent; - lastp = &ent->next; } - de->subdir = list; } /* diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 7587bf5f38c6..f999df1c5c90 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -203,7 +203,7 @@ extern int prom_n_addr_cells(struct device_node* np); extern int prom_n_size_cells(struct device_node* np); extern int prom_n_intr_cells(struct device_node* np); extern void prom_get_irq_senses(unsigned char *senses, int off, int max); -extern void prom_add_property(struct device_node* np, struct property* prop); +extern int prom_add_property(struct device_node* np, struct property* prop); #ifdef CONFIG_PPC32 /* diff --git a/include/asm-powerpc/smu.h b/include/asm-powerpc/smu.h index 959bad660233..76c29a9784dd 100644 --- a/include/asm-powerpc/smu.h +++ b/include/asm-powerpc/smu.h @@ -20,16 +20,52 @@ /* * Partition info commands * - * I do not know what those are for at this point + * These commands are used to retreive the sdb-partition-XX datas from + * the SMU. The lenght is always 2. First byte is the subcommand code + * and second byte is the partition ID. + * + * The reply is 6 bytes: + * + * - 0..1 : partition address + * - 2 : a byte containing the partition ID + * - 3 : length (maybe other bits are rest of header ?) + * + * The data must then be obtained with calls to another command: + * SMU_CMD_MISC_ee_GET_DATABLOCK_REC (described below). */ #define SMU_CMD_PARTITION_COMMAND 0x3e +#define SMU_CMD_PARTITION_LATEST 0x01 +#define SMU_CMD_PARTITION_BASE 0x02 +#define SMU_CMD_PARTITION_UPDATE 0x03 /* * Fan control * - * This is a "mux" for fan control commands, first byte is the - * "sub" command. + * This is a "mux" for fan control commands. The command seem to + * act differently based on the number of arguments. With 1 byte + * of argument, this seem to be queries for fans status, setpoint, + * etc..., while with 0xe arguments, we will set the fans speeds. + * + * Queries (1 byte arg): + * --------------------- + * + * arg=0x01: read RPM fans status + * arg=0x02: read RPM fans setpoint + * arg=0x11: read PWM fans status + * arg=0x12: read PWM fans setpoint + * + * the "status" queries return the current speed while the "setpoint" ones + * return the programmed/target speed. It _seems_ that the result is a bit + * mask in the first byte of active/available fans, followed by 6 words (16 + * bits) containing the requested speed. + * + * Setpoint (14 bytes arg): + * ------------------------ + * + * first arg byte is 0 for RPM fans and 0x10 for PWM. Second arg byte is the + * mask of fans affected by the command. Followed by 6 words containing the + * setpoint value for selected fans in the mask (or 0 if mask value is 0) */ #define SMU_CMD_FAN_COMMAND 0x4a @@ -156,6 +192,14 @@ #define SMU_CMD_POWER_SHUTDOWN "SHUTDOWN" #define SMU_CMD_POWER_VOLTAGE_SLEW "VSLEW" +/* + * Read ADC sensors + * + * This command takes one byte of parameter: the sensor ID (or "reg" + * value in the device-tree) and returns a 16 bits value + */ +#define SMU_CMD_READ_ADC 0xd8 + /* Misc commands * * This command seem to be a grab bag of various things @@ -176,6 +220,25 @@ * Misc commands * * This command seem to be a grab bag of various things + * + * SMU_CMD_MISC_ee_GET_DATABLOCK_REC is used, among others, to + * transfer blocks of data from the SMU. So far, I've decrypted it's + * usage to retreive partition data. In order to do that, you have to + * break your transfer in "chunks" since that command cannot transfer + * more than a chunk at a time. The chunk size used by OF is 0xe bytes, + * but it seems that the darwin driver will let you do 0x1e bytes if + * your "PMU" version is >= 0x30. You can get the "PMU" version apparently + * either in the last 16 bits of property "smu-version-pmu" or as the 16 + * bytes at offset 1 of "smu-version-info" + * + * For each chunk, the command takes 7 bytes of arguments: + * byte 0: subcommand code (0x02) + * byte 1: 0x04 (always, I don't know what it means, maybe the address + * space to use or some other nicety. It's hard coded in OF) + * byte 2..5: SMU address of the chunk (big endian 32 bits) + * byte 6: size to transfer (up to max chunk size) + * + * The data is returned directly */ #define SMU_CMD_MISC_ee_COMMAND 0xee #define SMU_CMD_MISC_ee_GET_DATABLOCK_REC 0x02 @@ -353,21 +416,26 @@ struct smu_sdbp_header { __u8 flags; }; -/* - * 32 bits integers are usually encoded with 2x16 bits swapped, - * this demangles them + + /* + * demangle 16 and 32 bits integer in some SMU partitions + * (currently, afaik, this concerns only the FVT partition + * (0x12) */ -#define SMU_U32_MIX(x) ((((x) << 16) & 0xffff0000u) | (((x) >> 16) & 0xffffu)) +#define SMU_U16_MIX(x) le16_to_cpu(x); +#define SMU_U32_MIX(x) ((((x) & 0xff00ff00u) >> 8)|(((x) & 0x00ff00ffu) << 8)) + /* This is the definition of the SMU sdb-partition-0x12 table (called * CPU F/V/T operating points in Darwin). The definition for all those * SMU tables should be moved to some separate file */ -#define SMU_SDB_FVT_ID 0x12 +#define SMU_SDB_FVT_ID 0x12 struct smu_sdbp_fvt { __u32 sysclk; /* Base SysClk frequency in Hz for - * this operating point + * this operating point. Value need to + * be unmixed with SMU_U32_MIX() */ __u8 pad; __u8 maxtemp; /* Max temp. supported by this @@ -376,10 +444,73 @@ struct smu_sdbp_fvt { __u16 volts[3]; /* CPU core voltage for the 3 * PowerTune modes, a mode with - * 0V = not supported. + * 0V = not supported. Value need + * to be unmixed with SMU_U16_MIX() */ }; +/* This partition contains voltage & current sensor calibration + * informations + */ +#define SMU_SDB_CPUVCP_ID 0x21 + +struct smu_sdbp_cpuvcp { + __u16 volt_scale; /* u4.12 fixed point */ + __s16 volt_offset; /* s4.12 fixed point */ + __u16 curr_scale; /* u4.12 fixed point */ + __s16 curr_offset; /* s4.12 fixed point */ + __s32 power_quads[3]; /* s4.28 fixed point */ +}; + +/* This partition contains CPU thermal diode calibration + */ +#define SMU_SDB_CPUDIODE_ID 0x18 + +struct smu_sdbp_cpudiode { + __u16 m_value; /* u1.15 fixed point */ + __s16 b_value; /* s10.6 fixed point */ + +}; + +/* This partition contains Slots power calibration + */ +#define SMU_SDB_SLOTSPOW_ID 0x78 + +struct smu_sdbp_slotspow { + __u16 pow_scale; /* u4.12 fixed point */ + __s16 pow_offset; /* s4.12 fixed point */ +}; + +/* This partition contains machine specific version information about + * the sensor/control layout + */ +#define SMU_SDB_SENSORTREE_ID 0x25 + +struct smu_sdbp_sensortree { + u8 model_id; + u8 unknown[3]; +}; + +/* This partition contains CPU thermal control PID informations. So far + * only single CPU machines have been seen with an SMU, so we assume this + * carries only informations for those + */ +#define SMU_SDB_CPUPIDDATA_ID 0x17 + +struct smu_sdbp_cpupiddata { + u8 unknown1; + u8 target_temp_delta; + u8 unknown2; + u8 history_len; + s16 power_adj; + u16 max_power; + s32 gp,gr,gd; +}; + + +/* Other partitions without known structures */ +#define SMU_SDB_DEBUG_SWITCHES_ID 0x05 + #ifdef __KERNEL__ /* * This returns the pointer to an SMU "sdb" partition data or NULL @@ -423,8 +554,10 @@ struct smu_user_cmd_hdr __u32 cmdtype; #define SMU_CMDTYPE_SMU 0 /* SMU command */ #define SMU_CMDTYPE_WANTS_EVENTS 1 /* switch fd to events mode */ +#define SMU_CMDTYPE_GET_PARTITION 2 /* retreive an sdb partition */ __u8 cmd; /* SMU command byte */ + __u8 pad[3]; /* padding */ __u32 data_len; /* Lenght of data following */ }; diff --git a/include/asm-ppc/prom.h b/include/asm-ppc/prom.h index 75c0637acdc8..3e39827ed566 100644 --- a/include/asm-ppc/prom.h +++ b/include/asm-ppc/prom.h @@ -93,7 +93,7 @@ extern int device_is_compatible(struct device_node *device, const char *); extern int machine_is_compatible(const char *compat); extern unsigned char *get_property(struct device_node *node, const char *name, int *lenp); -extern void prom_add_property(struct device_node* np, struct property* prop); +extern int prom_add_property(struct device_node* np, struct property* prop); extern void prom_get_irq_senses(unsigned char *, int, int); extern int prom_n_addr_cells(struct device_node* np); extern int prom_n_size_cells(struct device_node* np); diff --git a/include/asm-ppc64/prom.h b/include/asm-ppc64/prom.h index bdb47174ff0e..76bb0266d67c 100644 --- a/include/asm-ppc64/prom.h +++ b/include/asm-ppc64/prom.h @@ -213,6 +213,6 @@ extern int prom_n_addr_cells(struct device_node* np); extern int prom_n_size_cells(struct device_node* np); extern int prom_n_intr_cells(struct device_node* np); extern void prom_get_irq_senses(unsigned char *senses, int off, int max); -extern void prom_add_property(struct device_node* np, struct property* prop); +extern int prom_add_property(struct device_node* np, struct property* prop); #endif /* _PPC64_PROM_H */ diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 0563581e3a02..65ceeaa30652 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -139,15 +139,12 @@ extern void proc_tty_unregister_driver(struct tty_driver *driver); /* * proc_devtree.c */ +#ifdef CONFIG_PROC_DEVICETREE struct device_node; +struct property; extern void proc_device_tree_init(void); -#ifdef CONFIG_PROC_DEVICETREE extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *); -#else /* !CONFIG_PROC_DEVICETREE */ -static inline void proc_device_tree_add_node(struct device_node *np, struct proc_dir_entry *pde) -{ - return; -} +extern void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop); #endif /* CONFIG_PROC_DEVICETREE */ extern struct proc_dir_entry *proc_symlink(const char *, -- cgit v1.2.3 From 7b7b1ace2d9d06d76bce7481a045c22ed75e35dd Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 7 Nov 2005 17:13:39 -0500 Subject: [PATCH] saner handling of auto_acct_off() and DQUOT_OFF() in umount The way we currently deal with quota and process accounting that might keep vfsmount busy at umount time is inherently broken; we try to turn them off just in case (not quite correctly, at that) and a) pray umount doesn't fail (otherwise they'll stay turned off) b) pray nobody doesn anything funny just as we turn quota off Moreover, LSM provides hooks for doing the same sort of broken logics. The proper way to deal with that is to introduce the second kind of reference to vfsmount. Semantics: - when the last normal reference is dropped, all special ones are converted to normal ones and if there had been any, cleanup is done. - normal reference can be cloned into a special one - special reference can be converted to normal one; that's a no-op if we'd already passed the point of no return (i.e. mntput() had converted special references to normal and started cleanup). The way it works: e.g. starting process accounting converts the vfsmount reference pinned by the opened file into special one and turns it back to normal when it gets shut down; acct_auto_close() is done when no normal references are left. That way it does *not* obstruct umount(2) and it silently gets turned off when the last normal reference to vfsmount is gone. Which is exactly what we want... The same should be done by LSM module that holds some internal references to vfsmount and wants to shut them down on umount - it should make them special and security_sb_umount_close() will be called exactly when the last normal reference to vfsmount is gone. quota handling is even simpler - we don't use normal file IO anymore, so there's no need to hold vfsmounts at all. DQUOT_OFF() is done from deactivate_super(), where it really belongs. Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/dquot.c | 18 ++-------- fs/namespace.c | 64 ++++++++++++++++++++++------------- fs/super.c | 1 + include/linux/acct.h | 3 ++ include/linux/mount.h | 13 +++----- include/linux/quota.h | 1 - kernel/acct.c | 92 ++++++++++++++++++++++++++++++++++----------------- 7 files changed, 113 insertions(+), 79 deletions(-) (limited to 'include/linux') diff --git a/fs/dquot.c b/fs/dquot.c index afa06a893468..05b60283c9c2 100644 --- a/fs/dquot.c +++ b/fs/dquot.c @@ -1321,13 +1321,11 @@ int vfs_quota_off(struct super_block *sb, int type) int cnt; struct quota_info *dqopt = sb_dqopt(sb); struct inode *toputinode[MAXQUOTAS]; - struct vfsmount *toputmnt[MAXQUOTAS]; /* We need to serialize quota_off() for device */ down(&dqopt->dqonoff_sem); for (cnt = 0; cnt < MAXQUOTAS; cnt++) { toputinode[cnt] = NULL; - toputmnt[cnt] = NULL; if (type != -1 && cnt != type) continue; if (!sb_has_quota_enabled(sb, cnt)) @@ -1348,9 +1346,7 @@ int vfs_quota_off(struct super_block *sb, int type) put_quota_format(dqopt->info[cnt].dqi_format); toputinode[cnt] = dqopt->files[cnt]; - toputmnt[cnt] = dqopt->mnt[cnt]; dqopt->files[cnt] = NULL; - dqopt->mnt[cnt] = NULL; dqopt->info[cnt].dqi_flags = 0; dqopt->info[cnt].dqi_igrace = 0; dqopt->info[cnt].dqi_bgrace = 0; @@ -1358,10 +1354,7 @@ int vfs_quota_off(struct super_block *sb, int type) } up(&dqopt->dqonoff_sem); /* Sync the superblock so that buffers with quota data are written to - * disk (and so userspace sees correct data afterwards). - * The reference to vfsmnt we are still holding protects us from - * umount (we don't have it only when quotas are turned on/off for - * journal replay but in that case we are guarded by the fs anyway). */ + * disk (and so userspace sees correct data afterwards). */ if (sb->s_op->sync_fs) sb->s_op->sync_fs(sb, 1); sync_blockdev(sb->s_bdev); @@ -1385,10 +1378,6 @@ int vfs_quota_off(struct super_block *sb, int type) iput(toputinode[cnt]); } up(&dqopt->dqonoff_sem); - /* We don't hold the reference when we turned on quotas - * just for the journal replay... */ - if (toputmnt[cnt]) - mntput(toputmnt[cnt]); } if (sb->s_bdev) invalidate_bdev(sb->s_bdev, 0); @@ -1503,11 +1492,8 @@ int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path) /* Quota file not on the same filesystem? */ if (nd.mnt->mnt_sb != sb) error = -EXDEV; - else { + else error = vfs_quota_on_inode(nd.dentry->d_inode, type, format_id); - if (!error) - sb_dqopt(sb)->mnt[type] = mntget(nd.mnt); - } out_path: path_release(&nd); return error; diff --git a/fs/namespace.c b/fs/namespace.c index 2fa9fdf7d6f5..1d83302f30c3 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -172,7 +172,7 @@ clone_mnt(struct vfsmount *old, struct dentry *root) return mnt; } -void __mntput(struct vfsmount *mnt) +static inline void __mntput(struct vfsmount *mnt) { struct super_block *sb = mnt->mnt_sb; dput(mnt->mnt_root); @@ -180,7 +180,46 @@ void __mntput(struct vfsmount *mnt) deactivate_super(sb); } -EXPORT_SYMBOL(__mntput); +void mntput_no_expire(struct vfsmount *mnt) +{ +repeat: + if (atomic_dec_and_lock(&mnt->mnt_count, &vfsmount_lock)) { + if (likely(!mnt->mnt_pinned)) { + spin_unlock(&vfsmount_lock); + __mntput(mnt); + return; + } + atomic_add(mnt->mnt_pinned + 1, &mnt->mnt_count); + mnt->mnt_pinned = 0; + spin_unlock(&vfsmount_lock); + acct_auto_close_mnt(mnt); + security_sb_umount_close(mnt); + goto repeat; + } +} + +EXPORT_SYMBOL(mntput_no_expire); + +void mnt_pin(struct vfsmount *mnt) +{ + spin_lock(&vfsmount_lock); + mnt->mnt_pinned++; + spin_unlock(&vfsmount_lock); +} + +EXPORT_SYMBOL(mnt_pin); + +void mnt_unpin(struct vfsmount *mnt) +{ + spin_lock(&vfsmount_lock); + if (mnt->mnt_pinned) { + atomic_inc(&mnt->mnt_count); + mnt->mnt_pinned--; + } + spin_unlock(&vfsmount_lock); +} + +EXPORT_SYMBOL(mnt_unpin); /* iterator */ static void *m_start(struct seq_file *m, loff_t *pos) @@ -435,16 +474,6 @@ static int do_umount(struct vfsmount *mnt, int flags) down_write(¤t->namespace->sem); spin_lock(&vfsmount_lock); - if (atomic_read(&sb->s_active) == 1) { - /* last instance - try to be smart */ - spin_unlock(&vfsmount_lock); - lock_kernel(); - DQUOT_OFF(sb); - acct_auto_close(sb); - unlock_kernel(); - security_sb_umount_close(mnt); - spin_lock(&vfsmount_lock); - } retval = -EBUSY; if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) { if (!list_empty(&mnt->mnt_list)) @@ -850,17 +879,6 @@ static void expire_mount(struct vfsmount *mnt, struct list_head *mounts) detach_mnt(mnt, &old_nd); spin_unlock(&vfsmount_lock); path_release(&old_nd); - - /* - * Now lay it to rest if this was the last ref on the superblock - */ - if (atomic_read(&mnt->mnt_sb->s_active) == 1) { - /* last instance - try to be smart */ - lock_kernel(); - DQUOT_OFF(mnt->mnt_sb); - acct_auto_close(mnt->mnt_sb); - unlock_kernel(); - } mntput(mnt); } else { /* diff --git a/fs/super.c b/fs/super.c index eed6c3132905..6689dded3c84 100644 --- a/fs/super.c +++ b/fs/super.c @@ -171,6 +171,7 @@ void deactivate_super(struct super_block *s) if (atomic_dec_and_lock(&s->s_active, &sb_lock)) { s->s_count -= S_BIAS-1; spin_unlock(&sb_lock); + DQUOT_OFF(s); down_write(&s->s_umount); fs->kill_sb(s); put_filesystem(fs); diff --git a/include/linux/acct.h b/include/linux/acct.h index 19f70462b3be..93c5b3cdf951 100644 --- a/include/linux/acct.h +++ b/include/linux/acct.h @@ -117,12 +117,15 @@ struct acct_v3 #include #ifdef CONFIG_BSD_PROCESS_ACCT +struct vfsmount; struct super_block; +extern void acct_auto_close_mnt(struct vfsmount *m); extern void acct_auto_close(struct super_block *sb); extern void acct_process(long exitcode); extern void acct_update_integrals(struct task_struct *tsk); extern void acct_clear_integrals(struct task_struct *tsk); #else +#define acct_auto_close_mnt(x) do { } while (0) #define acct_auto_close(x) do { } while (0) #define acct_process(x) do { } while (0) #define acct_update_integrals(x) do { } while (0) diff --git a/include/linux/mount.h b/include/linux/mount.h index f8f39937e301..ffb0b5089880 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -37,6 +37,7 @@ struct vfsmount struct list_head mnt_list; struct list_head mnt_expire; /* link in fs-specific expiry list */ struct namespace *mnt_namespace; /* containing namespace */ + int mnt_pinned; }; static inline struct vfsmount *mntget(struct vfsmount *mnt) @@ -46,15 +47,9 @@ static inline struct vfsmount *mntget(struct vfsmount *mnt) return mnt; } -extern void __mntput(struct vfsmount *mnt); - -static inline void mntput_no_expire(struct vfsmount *mnt) -{ - if (mnt) { - if (atomic_dec_and_test(&mnt->mnt_count)) - __mntput(mnt); - } -} +extern void mntput_no_expire(struct vfsmount *mnt); +extern void mnt_pin(struct vfsmount *mnt); +extern void mnt_unpin(struct vfsmount *mnt); static inline void mntput(struct vfsmount *mnt) { diff --git a/include/linux/quota.h b/include/linux/quota.h index 700ead45084f..f33aeb22c26a 100644 --- a/include/linux/quota.h +++ b/include/linux/quota.h @@ -289,7 +289,6 @@ struct quota_info { struct semaphore dqonoff_sem; /* Serialize quotaon & quotaoff */ struct rw_semaphore dqptr_sem; /* serialize ops using quota_info struct, pointers from inode to dquots */ struct inode *files[MAXQUOTAS]; /* inodes of quotafiles */ - struct vfsmount *mnt[MAXQUOTAS]; /* mountpoint entries of filesystems with quota files */ struct mem_dqinfo info[MAXQUOTAS]; /* Information for each quota type */ struct quota_format_ops *ops[MAXQUOTAS]; /* Operations for each type */ }; diff --git a/kernel/acct.c b/kernel/acct.c index 2e3f4a47e7d0..6312d6bd43e3 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include /* sector_div */ @@ -192,6 +193,7 @@ static void acct_file_reopen(struct file *file) add_timer(&acct_globals.timer); } if (old_acct) { + mnt_unpin(old_acct->f_vfsmnt); spin_unlock(&acct_globals.lock); do_acct_process(0, old_acct); filp_close(old_acct, NULL); @@ -199,6 +201,42 @@ static void acct_file_reopen(struct file *file) } } +static int acct_on(char *name) +{ + struct file *file; + int error; + + /* Difference from BSD - they don't do O_APPEND */ + file = filp_open(name, O_WRONLY|O_APPEND|O_LARGEFILE, 0); + if (IS_ERR(file)) + return PTR_ERR(file); + + if (!S_ISREG(file->f_dentry->d_inode->i_mode)) { + filp_close(file, NULL); + return -EACCES; + } + + if (!file->f_op->write) { + filp_close(file, NULL); + return -EIO; + } + + error = security_acct(file); + if (error) { + filp_close(file, NULL); + return error; + } + + spin_lock(&acct_globals.lock); + mnt_pin(file->f_vfsmnt); + acct_file_reopen(file); + spin_unlock(&acct_globals.lock); + + mntput(file->f_vfsmnt); /* it's pinned, now give up active reference */ + + return 0; +} + /** * sys_acct - enable/disable process accounting * @name: file name for accounting records or NULL to shutdown accounting @@ -212,47 +250,41 @@ static void acct_file_reopen(struct file *file) */ asmlinkage long sys_acct(const char __user *name) { - struct file *file = NULL; - char *tmp; int error; if (!capable(CAP_SYS_PACCT)) return -EPERM; if (name) { - tmp = getname(name); - if (IS_ERR(tmp)) { + char *tmp = getname(name); + if (IS_ERR(tmp)) return (PTR_ERR(tmp)); - } - /* Difference from BSD - they don't do O_APPEND */ - file = filp_open(tmp, O_WRONLY|O_APPEND|O_LARGEFILE, 0); + error = acct_on(tmp); putname(tmp); - if (IS_ERR(file)) { - return (PTR_ERR(file)); - } - if (!S_ISREG(file->f_dentry->d_inode->i_mode)) { - filp_close(file, NULL); - return (-EACCES); - } - - if (!file->f_op->write) { - filp_close(file, NULL); - return (-EIO); + } else { + error = security_acct(NULL); + if (!error) { + spin_lock(&acct_globals.lock); + acct_file_reopen(NULL); + spin_unlock(&acct_globals.lock); } } + return error; +} - error = security_acct(file); - if (error) { - if (file) - filp_close(file, NULL); - return error; - } - +/** + * acct_auto_close - turn off a filesystem's accounting if it is on + * @m: vfsmount being shut down + * + * If the accounting is turned on for a file in the subtree pointed to + * to by m, turn accounting off. Done when m is about to die. + */ +void acct_auto_close_mnt(struct vfsmount *m) +{ spin_lock(&acct_globals.lock); - acct_file_reopen(file); + if (acct_globals.file && acct_globals.file->f_vfsmnt == m) + acct_file_reopen(NULL); spin_unlock(&acct_globals.lock); - - return (0); } /** @@ -266,8 +298,8 @@ void acct_auto_close(struct super_block *sb) { spin_lock(&acct_globals.lock); if (acct_globals.file && - acct_globals.file->f_dentry->d_inode->i_sb == sb) { - acct_file_reopen((struct file *)NULL); + acct_globals.file->f_vfsmnt->mnt_sb == sb) { + acct_file_reopen(NULL); } spin_unlock(&acct_globals.lock); } -- cgit v1.2.3 From 5addc5dd8836aa061f6efc4a0d9ba6323726297a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 7 Nov 2005 17:15:49 -0500 Subject: [PATCH] make /proc/mounts pollable Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 30 ++++++++++++++++++++++- fs/proc/base.c | 62 +++++++++++++++++++++++++++++++++++------------ include/linux/namespace.h | 2 ++ 3 files changed, 78 insertions(+), 16 deletions(-) (limited to 'include/linux') diff --git a/fs/namespace.c b/fs/namespace.c index 611f777bbd61..d1aca685aacf 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -37,7 +37,9 @@ static inline int sysfs_init(void) #endif /* spinlock for vfsmount related operations, inplace of dcache_lock */ - __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock); +__cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock); + +static int event; static struct list_head *mount_hashtable; static int hash_mask __read_mostly, hash_bits __read_mostly; @@ -111,6 +113,22 @@ static inline int check_mnt(struct vfsmount *mnt) return mnt->mnt_namespace == current->namespace; } +static void touch_namespace(struct namespace *ns) +{ + if (ns) { + ns->event = ++event; + wake_up_interruptible(&ns->poll); + } +} + +static void __touch_namespace(struct namespace *ns) +{ + if (ns && ns->event != event) { + ns->event = event; + wake_up_interruptible(&ns->poll); + } +} + static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd) { old_nd->dentry = mnt->mnt_mountpoint; @@ -384,6 +402,7 @@ static void umount_tree(struct vfsmount *mnt) for (p = mnt; p; p = next_mnt(p, mnt)) { list_del(&p->mnt_list); list_add(&p->mnt_list, &kill); + __touch_namespace(p->mnt_namespace); p->mnt_namespace = NULL; } @@ -473,6 +492,7 @@ static int do_umount(struct vfsmount *mnt, int flags) down_write(¤t->namespace->sem); spin_lock(&vfsmount_lock); + event++; retval = -EBUSY; if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) { @@ -634,6 +654,7 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) list_splice(&head, current->namespace->list.prev); mntget(mnt); err = 0; + touch_namespace(current->namespace); } spin_unlock(&vfsmount_lock); out_unlock: @@ -771,6 +792,7 @@ static int do_move_mount(struct nameidata *nd, char *old_name) detach_mnt(old_nd.mnt, &parent_nd); attach_mnt(old_nd.mnt, nd); + touch_namespace(current->namespace); /* if the mount is moved, it should no longer be expire * automatically */ @@ -877,6 +899,7 @@ static void expire_mount(struct vfsmount *mnt, struct list_head *mounts) struct nameidata old_nd; /* delete from the namespace */ + touch_namespace(mnt->mnt_namespace); list_del_init(&mnt->mnt_list); mnt->mnt_namespace = NULL; detach_mnt(mnt, &old_nd); @@ -1114,6 +1137,8 @@ int copy_namespace(int flags, struct task_struct *tsk) atomic_set(&new_ns->count, 1); init_rwsem(&new_ns->sem); INIT_LIST_HEAD(&new_ns->list); + init_waitqueue_head(&new_ns->poll); + new_ns->event = 0; down_write(&tsk->namespace->sem); /* First pass: copy the tree topology */ @@ -1377,6 +1402,7 @@ asmlinkage long sys_pivot_root(const char __user *new_root, const char __user *p detach_mnt(user_nd.mnt, &root_parent); attach_mnt(user_nd.mnt, &old_nd); /* mount old root on put_old */ attach_mnt(new_nd.mnt, &root_parent); /* mount new_root on / */ + touch_namespace(current->namespace); spin_unlock(&vfsmount_lock); chroot_fs_refs(&user_nd, &new_nd); security_sb_post_pivotroot(&user_nd, &new_nd); @@ -1413,6 +1439,8 @@ static void __init init_mount_tree(void) atomic_set(&namespace->count, 1); INIT_LIST_HEAD(&namespace->list); init_rwsem(&namespace->sem); + init_waitqueue_head(&namespace->poll); + namespace->event = 0; list_add(&mnt->mnt_list, &namespace->list); namespace->root = mnt; mnt->mnt_namespace = namespace; diff --git a/fs/proc/base.c b/fs/proc/base.c index a170450aadb1..634355e16986 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -70,6 +70,7 @@ #include #include #include +#include #include "internal.h" /* @@ -660,26 +661,38 @@ static struct file_operations proc_smaps_operations = { #endif extern struct seq_operations mounts_op; +struct proc_mounts { + struct seq_file m; + int event; +}; + static int mounts_open(struct inode *inode, struct file *file) { struct task_struct *task = proc_task(inode); - int ret = seq_open(file, &mounts_op); + struct namespace *namespace; + struct proc_mounts *p; + int ret = -EINVAL; - if (!ret) { - struct seq_file *m = file->private_data; - struct namespace *namespace; - task_lock(task); - namespace = task->namespace; - if (namespace) - get_namespace(namespace); - task_unlock(task); - - if (namespace) - m->private = namespace; - else { - seq_release(inode, file); - ret = -EINVAL; + task_lock(task); + namespace = task->namespace; + if (namespace) + get_namespace(namespace); + task_unlock(task); + + if (namespace) { + ret = -ENOMEM; + p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL); + if (p) { + file->private_data = &p->m; + ret = seq_open(file, &mounts_op); + if (!ret) { + p->m.private = namespace; + p->event = namespace->event; + return 0; + } + kfree(p); } + put_namespace(namespace); } return ret; } @@ -692,11 +705,30 @@ static int mounts_release(struct inode *inode, struct file *file) return seq_release(inode, file); } +static unsigned mounts_poll(struct file *file, poll_table *wait) +{ + struct proc_mounts *p = file->private_data; + struct namespace *ns = p->m.private; + unsigned res = 0; + + poll_wait(file, &ns->poll, wait); + + spin_lock(&vfsmount_lock); + if (p->event != ns->event) { + p->event = ns->event; + res = POLLERR; + } + spin_unlock(&vfsmount_lock); + + return res; +} + static struct file_operations proc_mounts_operations = { .open = mounts_open, .read = seq_read, .llseek = seq_lseek, .release = mounts_release, + .poll = mounts_poll, }; #define PROC_BLOCK_SIZE (3*1024) /* 4K page size but our output routines use some slack for overruns */ diff --git a/include/linux/namespace.h b/include/linux/namespace.h index 0e5a86f13b2f..6f0f25d64c38 100644 --- a/include/linux/namespace.h +++ b/include/linux/namespace.h @@ -10,6 +10,8 @@ struct namespace { struct vfsmount * root; struct list_head list; struct rw_semaphore sem; + wait_queue_head_t poll; + int event; }; extern int copy_namespace(int, struct task_struct *); -- cgit v1.2.3 From 390c684367de37e1c2f9005cf92f7a746c69fdd3 Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:17:51 -0500 Subject: [PATCH] making namespace_sem global This removes the per-namespace semaphore in favor of a global semaphore. This can have an effect on namespace scalability. Signed-off-by: Miklos Szeredi Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 46 +++++++++++++++++++++++----------------------- include/linux/namespace.h | 1 - 2 files changed, 23 insertions(+), 24 deletions(-) (limited to 'include/linux') diff --git a/fs/namespace.c b/fs/namespace.c index 65f9c0ecc21c..4abee9ab009f 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -46,6 +46,7 @@ static int event; static struct list_head *mount_hashtable; static int hash_mask __read_mostly, hash_bits __read_mostly; static kmem_cache_t *mnt_cache; +static struct rw_semaphore namespace_sem; static inline unsigned long hash(struct vfsmount *mnt, struct dentry *dentry) { @@ -250,7 +251,7 @@ static void *m_start(struct seq_file *m, loff_t *pos) struct list_head *p; loff_t l = *pos; - down_read(&n->sem); + down_read(&namespace_sem); list_for_each(p, &n->list) if (!l--) return list_entry(p, struct vfsmount, mnt_list); @@ -267,8 +268,7 @@ static void *m_next(struct seq_file *m, void *v, loff_t *pos) static void m_stop(struct seq_file *m, void *v) { - struct namespace *n = m->private; - up_read(&n->sem); + up_read(&namespace_sem); } static inline void mangle(struct seq_file *m, const char *s) @@ -487,7 +487,7 @@ static int do_umount(struct vfsmount *mnt, int flags) return retval; } - down_write(¤t->namespace->sem); + down_write(&namespace_sem); spin_lock(&vfsmount_lock); event++; @@ -500,7 +500,7 @@ static int do_umount(struct vfsmount *mnt, int flags) spin_unlock(&vfsmount_lock); if (retval) security_sb_umount_busy(mnt); - up_write(¤t->namespace->sem); + up_write(&namespace_sem); release_mounts(&umount_list); return retval; } @@ -678,7 +678,7 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) if (err) return err; - down_write(¤t->namespace->sem); + down_write(&namespace_sem); err = -EINVAL; if (!check_mnt(nd->mnt) || !check_mnt(old_nd.mnt)) goto out; @@ -702,7 +702,7 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) } out: - up_write(¤t->namespace->sem); + up_write(&namespace_sem); path_release(&old_nd); return err; } @@ -750,7 +750,7 @@ static int do_move_mount(struct nameidata *nd, char *old_name) if (err) return err; - down_write(¤t->namespace->sem); + down_write(&namespace_sem); while (d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) ; err = -EINVAL; @@ -795,7 +795,7 @@ out2: out1: up(&nd->dentry->d_inode->i_sem); out: - up_write(¤t->namespace->sem); + up_write(&namespace_sem); if (!err) path_release(&parent_nd); path_release(&old_nd); @@ -834,7 +834,7 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd, { int err; - down_write(¤t->namespace->sem); + down_write(&namespace_sem); /* Something was mounted here while we slept */ while (d_mountpoint(nd->dentry) && follow_down(&nd->mnt, &nd->dentry)) ; @@ -862,11 +862,11 @@ int do_add_mount(struct vfsmount *newmnt, struct nameidata *nd, list_add_tail(&newmnt->mnt_expire, fslist); spin_unlock(&vfsmount_lock); } - up_write(¤t->namespace->sem); + up_write(&namespace_sem); return 0; unlock: - up_write(¤t->namespace->sem); + up_write(&namespace_sem); mntput(newmnt); return err; } @@ -958,9 +958,9 @@ void mark_mounts_for_expiry(struct list_head *mounts) get_namespace(namespace); spin_unlock(&vfsmount_lock); - down_write(&namespace->sem); + down_write(&namespace_sem); expire_mount(mnt, mounts, &umounts); - up_write(&namespace->sem); + up_write(&namespace_sem); release_mounts(&umounts); mntput(mnt); put_namespace(namespace); @@ -1127,17 +1127,16 @@ int copy_namespace(int flags, struct task_struct *tsk) goto out; atomic_set(&new_ns->count, 1); - init_rwsem(&new_ns->sem); INIT_LIST_HEAD(&new_ns->list); init_waitqueue_head(&new_ns->poll); new_ns->event = 0; - down_write(&tsk->namespace->sem); + down_write(&namespace_sem); /* First pass: copy the tree topology */ new_ns->root = copy_tree(namespace->root, namespace->root->mnt_root, CL_EXPIRE); if (!new_ns->root) { - up_write(&tsk->namespace->sem); + up_write(&namespace_sem); kfree(new_ns); goto out; } @@ -1171,7 +1170,7 @@ int copy_namespace(int flags, struct task_struct *tsk) p = next_mnt(p, namespace->root); q = next_mnt(q, new_ns->root); } - up_write(&tsk->namespace->sem); + up_write(&namespace_sem); tsk->namespace = new_ns; @@ -1356,7 +1355,7 @@ asmlinkage long sys_pivot_root(const char __user * new_root, user_nd.mnt = mntget(current->fs->rootmnt); user_nd.dentry = dget(current->fs->root); read_unlock(¤t->fs->lock); - down_write(¤t->namespace->sem); + down_write(&namespace_sem); down(&old_nd.dentry->d_inode->i_sem); error = -EINVAL; if (!check_mnt(user_nd.mnt)) @@ -1407,7 +1406,7 @@ asmlinkage long sys_pivot_root(const char __user * new_root, path_release(&parent_nd); out2: up(&old_nd.dentry->d_inode->i_sem); - up_write(¤t->namespace->sem); + up_write(&namespace_sem); path_release(&user_nd); path_release(&old_nd); out1: @@ -1434,7 +1433,6 @@ static void __init init_mount_tree(void) panic("Can't allocate initial namespace"); atomic_set(&namespace->count, 1); INIT_LIST_HEAD(&namespace->list); - init_rwsem(&namespace->sem); init_waitqueue_head(&namespace->poll); namespace->event = 0; list_add(&mnt->mnt_list, &namespace->list); @@ -1459,6 +1457,8 @@ void __init mnt_init(unsigned long mempages) unsigned int nr_hash; int i; + init_rwsem(&namespace_sem); + mnt_cache = kmem_cache_create("mnt_cache", sizeof(struct vfsmount), 0, SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL, NULL); @@ -1507,11 +1507,11 @@ void __put_namespace(struct namespace *namespace) LIST_HEAD(umount_list); namespace->root = NULL; spin_unlock(&vfsmount_lock); - down_write(&namespace->sem); + down_write(&namespace_sem); spin_lock(&vfsmount_lock); umount_tree(root, &umount_list); spin_unlock(&vfsmount_lock); - up_write(&namespace->sem); + up_write(&namespace_sem); release_mounts(&umount_list); kfree(namespace); } diff --git a/include/linux/namespace.h b/include/linux/namespace.h index 6f0f25d64c38..6731977c4c13 100644 --- a/include/linux/namespace.h +++ b/include/linux/namespace.h @@ -9,7 +9,6 @@ struct namespace { atomic_t count; struct vfsmount * root; struct list_head list; - struct rw_semaphore sem; wait_queue_head_t poll; int event; }; -- cgit v1.2.3 From 07b20889e3052c7e77d6a6a54e7e83446eb1ba84 Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:19:07 -0500 Subject: [PATCH] beginning of the shared-subtree proper A private mount does not forward or receive propagation. This patch provides user the ability to convert any mount to private. Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/Makefile | 2 +- fs/namespace.c | 24 ++++++++++++++++++++++++ fs/pnode.c | 17 +++++++++++++++++ fs/pnode.h | 14 ++++++++++++++ include/linux/fs.h | 1 + include/linux/mount.h | 10 +++++----- 6 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 fs/pnode.c create mode 100644 fs/pnode.h (limited to 'include/linux') diff --git a/fs/Makefile b/fs/Makefile index 1972da186272..4c2655759078 100644 --- a/fs/Makefile +++ b/fs/Makefile @@ -10,7 +10,7 @@ obj-y := open.o read_write.o file_table.o buffer.o bio.o super.o \ ioctl.o readdir.o select.o fifo.o locks.o dcache.o inode.o \ attr.o bad_inode.o file.o filesystems.o namespace.o aio.o \ seq_file.o xattr.o libfs.o fs-writeback.o mpage.o direct-io.o \ - ioprio.o + ioprio.o pnode.o obj-$(CONFIG_INOTIFY) += inotify.o obj-$(CONFIG_EPOLL) += eventpoll.o diff --git a/fs/namespace.c b/fs/namespace.c index 4abee9ab009f..3782923d6d4d 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -24,6 +24,7 @@ #include #include #include +#include "pnode.h" extern int __init init_rootfs(void); @@ -662,6 +663,27 @@ out_unlock: return err; } +/* + * recursively change the type of the mountpoint. + */ +static int do_change_type(struct nameidata *nd, int flag) +{ + struct vfsmount *m, *mnt = nd->mnt; + int recurse = flag & MS_REC; + int type = flag & ~MS_REC; + + if (nd->dentry != nd->mnt->mnt_root) + return -EINVAL; + + down_write(&namespace_sem); + spin_lock(&vfsmount_lock); + for (m = mnt; m; m = (recurse ? next_mnt(m, mnt) : NULL)) + change_mnt_propagation(m, type); + spin_unlock(&vfsmount_lock); + up_write(&namespace_sem); + return 0; +} + /* * do loopback mount. */ @@ -1091,6 +1113,8 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, data_page); else if (flags & MS_BIND) retval = do_loopback(&nd, dev_name, flags & MS_REC); + else if (flags & MS_PRIVATE) + retval = do_change_type(&nd, flags); else if (flags & MS_MOVE) retval = do_move_mount(&nd, dev_name); else diff --git a/fs/pnode.c b/fs/pnode.c new file mode 100644 index 000000000000..aaa0dffda12a --- /dev/null +++ b/fs/pnode.c @@ -0,0 +1,17 @@ +/* + * linux/fs/pnode.c + * + * (C) Copyright IBM Corporation 2005. + * Released under GPL v2. + * Author : Ram Pai (linuxram@us.ibm.com) + * + */ +#include +#include +#include +#include "pnode.h" + +void change_mnt_propagation(struct vfsmount *mnt, int type) +{ + mnt->mnt_flags &= ~MNT_PNODE_MASK; +} diff --git a/fs/pnode.h b/fs/pnode.h new file mode 100644 index 000000000000..33549a3a74eb --- /dev/null +++ b/fs/pnode.h @@ -0,0 +1,14 @@ +/* + * linux/fs/pnode.h + * + * (C) Copyright IBM Corporation 2005. + * Released under GPL v2. + * + */ +#ifndef _LINUX_PNODE_H +#define _LINUX_PNODE_H + +#include +#include +void change_mnt_propagation(struct vfsmount *, int); +#endif /* _LINUX_PNODE_H */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 9a593ef262ef..6c431086abb3 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -104,6 +104,7 @@ extern int dir_notify_enable; #define MS_MOVE 8192 #define MS_REC 16384 #define MS_VERBOSE 32768 +#define MS_PRIVATE (1<<18) /* change to private */ #define MS_POSIXACL (1<<16) /* VFS does not apply the umask */ #define MS_ACTIVE (1<<30) #define MS_NOUSER (1<<31) diff --git a/include/linux/mount.h b/include/linux/mount.h index ffb0b5089880..8eadd3b65899 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -17,12 +17,12 @@ #include #include -#define MNT_NOSUID 1 -#define MNT_NODEV 2 -#define MNT_NOEXEC 4 +#define MNT_NOSUID 0x01 +#define MNT_NODEV 0x02 +#define MNT_NOEXEC 0x04 +#define MNT_PNODE_MASK 0x30 /* propogation flag mask */ -struct vfsmount -{ +struct vfsmount { struct list_head mnt_hash; struct vfsmount *mnt_parent; /* fs we are mounted on */ struct dentry *mnt_mountpoint; /* dentry of mountpoint */ -- cgit v1.2.3 From 03e06e68ff76294e53ffa898cb844d2a997b043e Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:19:33 -0500 Subject: [PATCH] introduce shared mounts This creates shared mounts. A shared mount when bind-mounted to some mountpoint, propagates mount/umount events to each other. All the shared mounts that propagate events to each other belong to the same peer-group. Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 3 ++- fs/pnode.c | 13 ++++++++++++- fs/pnode.h | 4 ++++ include/linux/fs.h | 1 + include/linux/mount.h | 2 ++ 5 files changed, 21 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/fs/namespace.c b/fs/namespace.c index 3782923d6d4d..f6861a5487df 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -68,6 +68,7 @@ struct vfsmount *alloc_vfsmnt(const char *name) INIT_LIST_HEAD(&mnt->mnt_mounts); INIT_LIST_HEAD(&mnt->mnt_list); INIT_LIST_HEAD(&mnt->mnt_expire); + INIT_LIST_HEAD(&mnt->mnt_share); if (name) { int size = strlen(name) + 1; char *newname = kmalloc(size, GFP_KERNEL); @@ -1113,7 +1114,7 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, data_page); else if (flags & MS_BIND) retval = do_loopback(&nd, dev_name, flags & MS_REC); - else if (flags & MS_PRIVATE) + else if (flags & (MS_SHARED | MS_PRIVATE)) retval = do_change_type(&nd, flags); else if (flags & MS_MOVE) retval = do_move_mount(&nd, dev_name); diff --git a/fs/pnode.c b/fs/pnode.c index aaa0dffda12a..1e22165ea41f 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -11,7 +11,18 @@ #include #include "pnode.h" +/* return the next shared peer mount of @p */ +static inline struct vfsmount *next_peer(struct vfsmount *p) +{ + return list_entry(p->mnt_share.next, struct vfsmount, mnt_share); +} + void change_mnt_propagation(struct vfsmount *mnt, int type) { - mnt->mnt_flags &= ~MNT_PNODE_MASK; + if (type == MS_SHARED) { + mnt->mnt_flags |= MNT_SHARED; + } else { + list_del_init(&mnt->mnt_share); + mnt->mnt_flags &= ~MNT_PNODE_MASK; + } } diff --git a/fs/pnode.h b/fs/pnode.h index 33549a3a74eb..ab1bdaee4e08 100644 --- a/fs/pnode.h +++ b/fs/pnode.h @@ -10,5 +10,9 @@ #include #include + +#define IS_MNT_SHARED(mnt) (mnt->mnt_flags & MNT_SHARED) +#define CLEAR_MNT_SHARED(mnt) (mnt->mnt_flags &= ~MNT_SHARED) + void change_mnt_propagation(struct vfsmount *, int); #endif /* _LINUX_PNODE_H */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 6c431086abb3..551fba303cf8 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -105,6 +105,7 @@ extern int dir_notify_enable; #define MS_REC 16384 #define MS_VERBOSE 32768 #define MS_PRIVATE (1<<18) /* change to private */ +#define MS_SHARED (1<<20) /* change to shared */ #define MS_POSIXACL (1<<16) /* VFS does not apply the umask */ #define MS_ACTIVE (1<<30) #define MS_NOUSER (1<<31) diff --git a/include/linux/mount.h b/include/linux/mount.h index 8eadd3b65899..2582559718fc 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -20,6 +20,7 @@ #define MNT_NOSUID 0x01 #define MNT_NODEV 0x02 #define MNT_NOEXEC 0x04 +#define MNT_SHARED 0x10 /* if the vfsmount is a shared mount */ #define MNT_PNODE_MASK 0x30 /* propogation flag mask */ struct vfsmount { @@ -36,6 +37,7 @@ struct vfsmount { char *mnt_devname; /* Name of device e.g. /dev/dsk/hda1 */ struct list_head mnt_list; struct list_head mnt_expire; /* link in fs-specific expiry list */ + struct list_head mnt_share; /* circular list of shared mounts */ struct namespace *mnt_namespace; /* containing namespace */ int mnt_pinned; }; -- cgit v1.2.3 From b90fa9ae8f51f098ee480bbaabd6867992e9fc58 Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:19:50 -0500 Subject: [PATCH] shared mount handling: bind and rbind Implement handling of MS_BIND in presense of shared mounts (see Documentation/sharedsubtree.txt in the end of patch series for detailed description). Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 126 ++++++++++++++++++++++++++++++++++++++++++++--------- fs/pnode.c | 81 +++++++++++++++++++++++++++++++++- fs/pnode.h | 14 ++++++ include/linux/fs.h | 5 +++ 4 files changed, 204 insertions(+), 22 deletions(-) (limited to 'include/linux') diff --git a/fs/namespace.c b/fs/namespace.c index f6861a5487df..9f5a084b239f 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -28,8 +28,6 @@ extern int __init init_rootfs(void); -#define CL_EXPIRE 0x01 - #ifdef CONFIG_SYSFS extern int __init sysfs_init(void); #else @@ -145,13 +143,43 @@ static void detach_mnt(struct vfsmount *mnt, struct nameidata *old_nd) old_nd->dentry->d_mounted--; } +void mnt_set_mountpoint(struct vfsmount *mnt, struct dentry *dentry, + struct vfsmount *child_mnt) +{ + child_mnt->mnt_parent = mntget(mnt); + child_mnt->mnt_mountpoint = dget(dentry); + dentry->d_mounted++; +} + static void attach_mnt(struct vfsmount *mnt, struct nameidata *nd) { - mnt->mnt_parent = mntget(nd->mnt); - mnt->mnt_mountpoint = dget(nd->dentry); - list_add(&mnt->mnt_hash, mount_hashtable + hash(nd->mnt, nd->dentry)); + mnt_set_mountpoint(nd->mnt, nd->dentry, mnt); + list_add_tail(&mnt->mnt_hash, mount_hashtable + + hash(nd->mnt, nd->dentry)); list_add_tail(&mnt->mnt_child, &nd->mnt->mnt_mounts); - nd->dentry->d_mounted++; +} + +/* + * the caller must hold vfsmount_lock + */ +static void commit_tree(struct vfsmount *mnt) +{ + struct vfsmount *parent = mnt->mnt_parent; + struct vfsmount *m; + LIST_HEAD(head); + struct namespace *n = parent->mnt_namespace; + + BUG_ON(parent == mnt); + + list_add_tail(&head, &mnt->mnt_list); + list_for_each_entry(m, &head, mnt_list) + m->mnt_namespace = n; + list_splice(&head, n->list.prev); + + list_add_tail(&mnt->mnt_hash, mount_hashtable + + hash(parent, mnt->mnt_mountpoint)); + list_add_tail(&mnt->mnt_child, &parent->mnt_mounts); + touch_namespace(n); } static struct vfsmount *next_mnt(struct vfsmount *p, struct vfsmount *root) @@ -183,7 +211,11 @@ static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, mnt->mnt_root = dget(root); mnt->mnt_mountpoint = mnt->mnt_root; mnt->mnt_parent = mnt; - mnt->mnt_namespace = current->namespace; + + if ((flag & CL_PROPAGATION) || IS_MNT_SHARED(old)) + list_add(&mnt->mnt_share, &old->mnt_share); + if (flag & CL_MAKE_SHARED) + set_mnt_shared(mnt); /* stick the duplicate mount on the same expiry list * as the original if that was on one */ @@ -379,7 +411,7 @@ int may_umount(struct vfsmount *mnt) EXPORT_SYMBOL(may_umount); -static void release_mounts(struct list_head *head) +void release_mounts(struct list_head *head) { struct vfsmount *mnt; while(!list_empty(head)) { @@ -401,7 +433,7 @@ static void release_mounts(struct list_head *head) } } -static void umount_tree(struct vfsmount *mnt, struct list_head *kill) +void umount_tree(struct vfsmount *mnt, struct list_head *kill) { struct vfsmount *p; @@ -581,7 +613,7 @@ static int lives_below_in_same_fs(struct dentry *d, struct dentry *dentry) } } -static struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, +struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, int flag) { struct vfsmount *res, *p, *q, *r, *s; @@ -626,6 +658,67 @@ Enomem: return NULL; } +/* + * @source_mnt : mount tree to be attached + * @nd : place the mount tree @source_mnt is attached + * + * NOTE: in the table below explains the semantics when a source mount + * of a given type is attached to a destination mount of a given type. + * --------------------------------------------- + * | BIND MOUNT OPERATION | + * |******************************************** + * | source-->| shared | private | + * | dest | | | + * | | | | | + * | v | | | + * |******************************************** + * | shared | shared (++) | shared (+) | + * | | | | + * |non-shared| shared (+) | private | + * ********************************************* + * A bind operation clones the source mount and mounts the clone on the + * destination mount. + * + * (++) the cloned mount is propagated to all the mounts in the propagation + * tree of the destination mount and the cloned mount is added to + * the peer group of the source mount. + * (+) the cloned mount is created under the destination mount and is marked + * as shared. The cloned mount is added to the peer group of the source + * mount. + * + * if the source mount is a tree, the operations explained above is + * applied to each mount in the tree. + * Must be called without spinlocks held, since this function can sleep + * in allocations. + */ +static int attach_recursive_mnt(struct vfsmount *source_mnt, + struct nameidata *nd) +{ + LIST_HEAD(tree_list); + struct vfsmount *dest_mnt = nd->mnt; + struct dentry *dest_dentry = nd->dentry; + struct vfsmount *child, *p; + + if (propagate_mnt(dest_mnt, dest_dentry, source_mnt, &tree_list)) + return -EINVAL; + + if (IS_MNT_SHARED(dest_mnt)) { + for (p = source_mnt; p; p = next_mnt(p, source_mnt)) + set_mnt_shared(p); + } + + spin_lock(&vfsmount_lock); + mnt_set_mountpoint(dest_mnt, dest_dentry, source_mnt); + commit_tree(source_mnt); + + list_for_each_entry_safe(child, p, &tree_list, mnt_hash) { + list_del_init(&child->mnt_hash); + commit_tree(child); + } + spin_unlock(&vfsmount_lock); + return 0; +} + static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) { int err; @@ -646,17 +739,8 @@ static int graft_tree(struct vfsmount *mnt, struct nameidata *nd) goto out_unlock; err = -ENOENT; - spin_lock(&vfsmount_lock); - if (IS_ROOT(nd->dentry) || !d_unhashed(nd->dentry)) { - struct list_head head; - - attach_mnt(mnt, nd); - list_add_tail(&head, &mnt->mnt_list); - list_splice(&head, current->namespace->list.prev); - err = 0; - touch_namespace(current->namespace); - } - spin_unlock(&vfsmount_lock); + if (IS_ROOT(nd->dentry) || !d_unhashed(nd->dentry)) + err = attach_recursive_mnt(mnt, nd); out_unlock: up(&nd->dentry->d_inode->i_sem); if (!err) diff --git a/fs/pnode.c b/fs/pnode.c index 1e22165ea41f..2d572b88e6f6 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -20,9 +20,88 @@ static inline struct vfsmount *next_peer(struct vfsmount *p) void change_mnt_propagation(struct vfsmount *mnt, int type) { if (type == MS_SHARED) { - mnt->mnt_flags |= MNT_SHARED; + set_mnt_shared(mnt); } else { list_del_init(&mnt->mnt_share); mnt->mnt_flags &= ~MNT_PNODE_MASK; } } + +/* + * get the next mount in the propagation tree. + * @m: the mount seen last + * @origin: the original mount from where the tree walk initiated + */ +static struct vfsmount *propagation_next(struct vfsmount *m, + struct vfsmount *origin) +{ + m = next_peer(m); + if (m == origin) + return NULL; + return m; +} + +/* + * mount 'source_mnt' under the destination 'dest_mnt' at + * dentry 'dest_dentry'. And propagate that mount to + * all the peer and slave mounts of 'dest_mnt'. + * Link all the new mounts into a propagation tree headed at + * source_mnt. Also link all the new mounts using ->mnt_list + * headed at source_mnt's ->mnt_list + * + * @dest_mnt: destination mount. + * @dest_dentry: destination dentry. + * @source_mnt: source mount. + * @tree_list : list of heads of trees to be attached. + */ +int propagate_mnt(struct vfsmount *dest_mnt, struct dentry *dest_dentry, + struct vfsmount *source_mnt, struct list_head *tree_list) +{ + struct vfsmount *m, *child; + int ret = 0; + struct vfsmount *prev_dest_mnt = dest_mnt; + struct vfsmount *prev_src_mnt = source_mnt; + LIST_HEAD(tmp_list); + LIST_HEAD(umount_list); + + for (m = propagation_next(dest_mnt, dest_mnt); m; + m = propagation_next(m, dest_mnt)) { + int type = CL_PROPAGATION; + + if (IS_MNT_NEW(m)) + continue; + + if (IS_MNT_SHARED(m)) + type |= CL_MAKE_SHARED; + + if (!(child = copy_tree(source_mnt, source_mnt->mnt_root, + type))) { + ret = -ENOMEM; + list_splice(tree_list, tmp_list.prev); + goto out; + } + + if (is_subdir(dest_dentry, m->mnt_root)) { + mnt_set_mountpoint(m, dest_dentry, child); + list_add_tail(&child->mnt_hash, tree_list); + } else { + /* + * This can happen if the parent mount was bind mounted + * on some subdirectory of a shared/slave mount. + */ + list_add_tail(&child->mnt_hash, &tmp_list); + } + prev_dest_mnt = m; + prev_src_mnt = child; + } +out: + spin_lock(&vfsmount_lock); + while (!list_empty(&tmp_list)) { + child = list_entry(tmp_list.next, struct vfsmount, mnt_hash); + list_del_init(&child->mnt_hash); + umount_tree(child, &umount_list); + } + spin_unlock(&vfsmount_lock); + release_mounts(&umount_list); + return ret; +} diff --git a/fs/pnode.h b/fs/pnode.h index ab1bdaee4e08..c62c72fad212 100644 --- a/fs/pnode.h +++ b/fs/pnode.h @@ -12,7 +12,21 @@ #include #define IS_MNT_SHARED(mnt) (mnt->mnt_flags & MNT_SHARED) +#define IS_MNT_NEW(mnt) (!mnt->mnt_namespace) #define CLEAR_MNT_SHARED(mnt) (mnt->mnt_flags &= ~MNT_SHARED) +#define CL_EXPIRE 0x01 +#define CL_COPY_ALL 0x04 +#define CL_MAKE_SHARED 0x08 +#define CL_PROPAGATION 0x10 + +static inline void set_mnt_shared(struct vfsmount *mnt) +{ + mnt->mnt_flags &= ~MNT_PNODE_MASK; + mnt->mnt_flags |= MNT_SHARED; +} + void change_mnt_propagation(struct vfsmount *, int); +int propagate_mnt(struct vfsmount *, struct dentry *, struct vfsmount *, + struct list_head *); #endif /* _LINUX_PNODE_H */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 551fba303cf8..5e188b773e9c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1251,7 +1251,12 @@ extern int unregister_filesystem(struct file_system_type *); extern struct vfsmount *kern_mount(struct file_system_type *); extern int may_umount_tree(struct vfsmount *); extern int may_umount(struct vfsmount *); +extern void umount_tree(struct vfsmount *, struct list_head *); +extern void release_mounts(struct list_head *); extern long do_mount(char *, char *, char *, unsigned long, void *); +extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int); +extern void mnt_set_mountpoint(struct vfsmount *, struct dentry *, + struct vfsmount *); extern int vfs_statfs(struct super_block *, struct kstatfs *); -- cgit v1.2.3 From a05964f3917c7c55368c229d7985f8e7c9977e97 Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:20:17 -0500 Subject: [PATCH] shared mounts handling: umount An unmount of a mount creates a umount event on the parent. If the parent is a shared mount, it gets propagated to all mounts in the peer group. Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 56 +++++++++++++++++++++----------- fs/pnode.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++- fs/pnode.h | 2 ++ include/linux/dcache.h | 1 + include/linux/fs.h | 2 +- 5 files changed, 128 insertions(+), 20 deletions(-) (limited to 'include/linux') diff --git a/fs/namespace.c b/fs/namespace.c index 1487982dbc24..4b1af01c2fb4 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -86,31 +86,44 @@ void free_vfsmnt(struct vfsmount *mnt) } /* - * Now, lookup_mnt increments the ref count before returning - * the vfsmount struct. + * find the first or last mount at @dentry on vfsmount @mnt depending on + * @dir. If @dir is set return the first mount else return the last mount. */ -struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry) +struct vfsmount *__lookup_mnt(struct vfsmount *mnt, struct dentry *dentry, + int dir) { struct list_head *head = mount_hashtable + hash(mnt, dentry); struct list_head *tmp = head; struct vfsmount *p, *found = NULL; - spin_lock(&vfsmount_lock); for (;;) { - tmp = tmp->next; + tmp = dir ? tmp->next : tmp->prev; p = NULL; if (tmp == head) break; p = list_entry(tmp, struct vfsmount, mnt_hash); if (p->mnt_parent == mnt && p->mnt_mountpoint == dentry) { - found = mntget(p); + found = p; break; } } - spin_unlock(&vfsmount_lock); return found; } +/* + * lookup_mnt increments the ref count before returning + * the vfsmount struct. + */ +struct vfsmount *lookup_mnt(struct vfsmount *mnt, struct dentry *dentry) +{ + struct vfsmount *child_mnt; + spin_lock(&vfsmount_lock); + if ((child_mnt = __lookup_mnt(mnt, dentry, 1))) + mntget(child_mnt); + spin_unlock(&vfsmount_lock); + return child_mnt; +} + static inline int check_mnt(struct vfsmount *mnt) { return mnt->mnt_namespace == current->namespace; @@ -404,9 +417,12 @@ EXPORT_SYMBOL(may_umount_tree); */ int may_umount(struct vfsmount *mnt) { - if (atomic_read(&mnt->mnt_count) > 2) - return -EBUSY; - return 0; + int ret = 0; + spin_lock(&vfsmount_lock); + if (propagate_mount_busy(mnt, 2)) + ret = -EBUSY; + spin_unlock(&vfsmount_lock); + return ret; } EXPORT_SYMBOL(may_umount); @@ -433,7 +449,7 @@ void release_mounts(struct list_head *head) } } -void umount_tree(struct vfsmount *mnt, struct list_head *kill) +void umount_tree(struct vfsmount *mnt, int propagate, struct list_head *kill) { struct vfsmount *p; @@ -442,6 +458,9 @@ void umount_tree(struct vfsmount *mnt, struct list_head *kill) list_add(&p->mnt_hash, kill); } + if (propagate) + propagate_umount(kill); + list_for_each_entry(p, kill, mnt_hash) { list_del_init(&p->mnt_expire); list_del_init(&p->mnt_list); @@ -450,6 +469,7 @@ void umount_tree(struct vfsmount *mnt, struct list_head *kill) list_del_init(&p->mnt_child); if (p->mnt_parent != p) mnt->mnt_mountpoint->d_mounted--; + change_mnt_propagation(p, MS_PRIVATE); } } @@ -526,9 +546,9 @@ static int do_umount(struct vfsmount *mnt, int flags) event++; retval = -EBUSY; - if (atomic_read(&mnt->mnt_count) == 2 || flags & MNT_DETACH) { + if (flags & MNT_DETACH || !propagate_mount_busy(mnt, 2)) { if (!list_empty(&mnt->mnt_list)) - umount_tree(mnt, &umount_list); + umount_tree(mnt, 1, &umount_list); retval = 0; } spin_unlock(&vfsmount_lock); @@ -651,7 +671,7 @@ Enomem: if (res) { LIST_HEAD(umount_list); spin_lock(&vfsmount_lock); - umount_tree(res, &umount_list); + umount_tree(res, 0, &umount_list); spin_unlock(&vfsmount_lock); release_mounts(&umount_list); } @@ -827,7 +847,7 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) if (err) { LIST_HEAD(umount_list); spin_lock(&vfsmount_lock); - umount_tree(mnt, &umount_list); + umount_tree(mnt, 0, &umount_list); spin_unlock(&vfsmount_lock); release_mounts(&umount_list); } @@ -1023,12 +1043,12 @@ static void expire_mount(struct vfsmount *mnt, struct list_head *mounts, * Check that it is still dead: the count should now be 2 - as * contributed by the vfsmount parent and the mntget above */ - if (atomic_read(&mnt->mnt_count) == 2) { + if (!propagate_mount_busy(mnt, 2)) { /* delete from the namespace */ touch_namespace(mnt->mnt_namespace); list_del_init(&mnt->mnt_list); mnt->mnt_namespace = NULL; - umount_tree(mnt, umounts); + umount_tree(mnt, 1, umounts); spin_unlock(&vfsmount_lock); } else { /* @@ -1647,7 +1667,7 @@ void __put_namespace(struct namespace *namespace) spin_unlock(&vfsmount_lock); down_write(&namespace_sem); spin_lock(&vfsmount_lock); - umount_tree(root, &umount_list); + umount_tree(root, 0, &umount_list); spin_unlock(&vfsmount_lock); up_write(&namespace_sem); release_mounts(&umount_list); diff --git a/fs/pnode.c b/fs/pnode.c index 2d572b88e6f6..7bc942d047cd 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -99,9 +99,94 @@ out: while (!list_empty(&tmp_list)) { child = list_entry(tmp_list.next, struct vfsmount, mnt_hash); list_del_init(&child->mnt_hash); - umount_tree(child, &umount_list); + umount_tree(child, 0, &umount_list); } spin_unlock(&vfsmount_lock); release_mounts(&umount_list); return ret; } + +/* + * return true if the refcount is greater than count + */ +static inline int do_refcount_check(struct vfsmount *mnt, int count) +{ + int mycount = atomic_read(&mnt->mnt_count); + return (mycount > count); +} + +/* + * check if the mount 'mnt' can be unmounted successfully. + * @mnt: the mount to be checked for unmount + * NOTE: unmounting 'mnt' would naturally propagate to all + * other mounts its parent propagates to. + * Check if any of these mounts that **do not have submounts** + * have more references than 'refcnt'. If so return busy. + */ +int propagate_mount_busy(struct vfsmount *mnt, int refcnt) +{ + struct vfsmount *m, *child; + struct vfsmount *parent = mnt->mnt_parent; + int ret = 0; + + if (mnt == parent) + return do_refcount_check(mnt, refcnt); + + /* + * quickly check if the current mount can be unmounted. + * If not, we don't have to go checking for all other + * mounts + */ + if (!list_empty(&mnt->mnt_mounts) || do_refcount_check(mnt, refcnt)) + return 1; + + for (m = propagation_next(parent, parent); m; + m = propagation_next(m, parent)) { + child = __lookup_mnt(m, mnt->mnt_mountpoint, 0); + if (child && list_empty(&child->mnt_mounts) && + (ret = do_refcount_check(child, 1))) + break; + } + return ret; +} + +/* + * NOTE: unmounting 'mnt' naturally propagates to all other mounts its + * parent propagates to. + */ +static void __propagate_umount(struct vfsmount *mnt) +{ + struct vfsmount *parent = mnt->mnt_parent; + struct vfsmount *m; + + BUG_ON(parent == mnt); + + for (m = propagation_next(parent, parent); m; + m = propagation_next(m, parent)) { + + struct vfsmount *child = __lookup_mnt(m, + mnt->mnt_mountpoint, 0); + /* + * umount the child only if the child has no + * other children + */ + if (child && list_empty(&child->mnt_mounts)) { + list_del(&child->mnt_hash); + list_add_tail(&child->mnt_hash, &mnt->mnt_hash); + } + } +} + +/* + * collect all mounts that receive propagation from the mount in @list, + * and return these additional mounts in the same list. + * @list: the list of mounts to be unmounted. + */ +int propagate_umount(struct list_head *list) +{ + struct vfsmount *mnt; + + list_for_each_entry(mnt, list, mnt_hash) + __propagate_umount(mnt); + return 0; +} diff --git a/fs/pnode.h b/fs/pnode.h index c62c72fad212..9b88ba06794a 100644 --- a/fs/pnode.h +++ b/fs/pnode.h @@ -29,4 +29,6 @@ static inline void set_mnt_shared(struct vfsmount *mnt) void change_mnt_propagation(struct vfsmount *, int); int propagate_mnt(struct vfsmount *, struct dentry *, struct vfsmount *, struct list_head *); +int propagate_umount(struct list_head *); +int propagate_mount_busy(struct vfsmount *, int); #endif /* _LINUX_PNODE_H */ diff --git a/include/linux/dcache.h b/include/linux/dcache.h index ab04b4f9b0db..46a2ba617595 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -329,6 +329,7 @@ static inline int d_mountpoint(struct dentry *dentry) } extern struct vfsmount *lookup_mnt(struct vfsmount *, struct dentry *); +extern struct vfsmount *__lookup_mnt(struct vfsmount *, struct dentry *, int); extern struct dentry *lookup_create(struct nameidata *nd, int is_dir); extern int sysctl_vfs_cache_pressure; diff --git a/include/linux/fs.h b/include/linux/fs.h index 5e188b773e9c..8bdb504be73b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1251,7 +1251,7 @@ extern int unregister_filesystem(struct file_system_type *); extern struct vfsmount *kern_mount(struct file_system_type *); extern int may_umount_tree(struct vfsmount *); extern int may_umount(struct vfsmount *); -extern void umount_tree(struct vfsmount *, struct list_head *); +extern void umount_tree(struct vfsmount *, int, struct list_head *); extern void release_mounts(struct list_head *); extern long do_mount(char *, char *, char *, unsigned long, void *); extern struct vfsmount *copy_tree(struct vfsmount *, struct dentry *, int); -- cgit v1.2.3 From a58b0eb8e64b78d9315a5491955e78b1391d42e5 Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:20:48 -0500 Subject: [PATCH] introduce slave mounts A slave mount always has a master mount from which it receives mount/umount events. Unlike shared mount the event propagation does not flow from the slave mount to the master. Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 4 +++- fs/pnode.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++--- fs/pnode.h | 2 ++ include/linux/fs.h | 1 + include/linux/mount.h | 3 +++ 5 files changed, 60 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/fs/namespace.c b/fs/namespace.c index 4b1af01c2fb4..46f99bc585bd 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -67,6 +67,8 @@ struct vfsmount *alloc_vfsmnt(const char *name) INIT_LIST_HEAD(&mnt->mnt_list); INIT_LIST_HEAD(&mnt->mnt_expire); INIT_LIST_HEAD(&mnt->mnt_share); + INIT_LIST_HEAD(&mnt->mnt_slave_list); + INIT_LIST_HEAD(&mnt->mnt_slave); if (name) { int size = strlen(name) + 1; char *newname = kmalloc(size, GFP_KERNEL); @@ -1243,7 +1245,7 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, data_page); else if (flags & MS_BIND) retval = do_loopback(&nd, dev_name, flags & MS_REC); - else if (flags & (MS_SHARED | MS_PRIVATE)) + else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE)) retval = do_change_type(&nd, flags); else if (flags & MS_MOVE) retval = do_move_mount(&nd, dev_name); diff --git a/fs/pnode.c b/fs/pnode.c index 7bc942d047cd..f73eba24f1d1 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -17,13 +17,61 @@ static inline struct vfsmount *next_peer(struct vfsmount *p) return list_entry(p->mnt_share.next, struct vfsmount, mnt_share); } +static int do_make_slave(struct vfsmount *mnt) +{ + struct vfsmount *peer_mnt = mnt, *master = mnt->mnt_master; + struct vfsmount *slave_mnt; + + /* + * slave 'mnt' to a peer mount that has the + * same root dentry. If none is available than + * slave it to anything that is available. + */ + while ((peer_mnt = next_peer(peer_mnt)) != mnt && + peer_mnt->mnt_root != mnt->mnt_root) ; + + if (peer_mnt == mnt) { + peer_mnt = next_peer(mnt); + if (peer_mnt == mnt) + peer_mnt = NULL; + } + list_del_init(&mnt->mnt_share); + + if (peer_mnt) + master = peer_mnt; + + if (master) { + list_for_each_entry(slave_mnt, &mnt->mnt_slave_list, mnt_slave) + slave_mnt->mnt_master = master; + list_del(&mnt->mnt_slave); + list_add(&mnt->mnt_slave, &master->mnt_slave_list); + list_splice(&mnt->mnt_slave_list, master->mnt_slave_list.prev); + INIT_LIST_HEAD(&mnt->mnt_slave_list); + } else { + struct list_head *p = &mnt->mnt_slave_list; + while (!list_empty(p)) { + slave_mnt = list_entry(p->next, + struct vfsmount, mnt_slave); + list_del_init(&slave_mnt->mnt_slave); + slave_mnt->mnt_master = NULL; + } + } + mnt->mnt_master = master; + CLEAR_MNT_SHARED(mnt); + INIT_LIST_HEAD(&mnt->mnt_slave_list); + return 0; +} + void change_mnt_propagation(struct vfsmount *mnt, int type) { if (type == MS_SHARED) { set_mnt_shared(mnt); - } else { - list_del_init(&mnt->mnt_share); - mnt->mnt_flags &= ~MNT_PNODE_MASK; + return; + } + do_make_slave(mnt); + if (type != MS_SLAVE) { + list_del_init(&mnt->mnt_slave); + mnt->mnt_master = NULL; } } diff --git a/fs/pnode.h b/fs/pnode.h index 9b88ba06794a..b59f0e9fe6b1 100644 --- a/fs/pnode.h +++ b/fs/pnode.h @@ -12,10 +12,12 @@ #include #define IS_MNT_SHARED(mnt) (mnt->mnt_flags & MNT_SHARED) +#define IS_MNT_SLAVE(mnt) (mnt->mnt_master) #define IS_MNT_NEW(mnt) (!mnt->mnt_namespace) #define CLEAR_MNT_SHARED(mnt) (mnt->mnt_flags &= ~MNT_SHARED) #define CL_EXPIRE 0x01 +#define CL_SLAVE 0x02 #define CL_COPY_ALL 0x04 #define CL_MAKE_SHARED 0x08 #define CL_PROPAGATION 0x10 diff --git a/include/linux/fs.h b/include/linux/fs.h index 8bdb504be73b..eef66f54c017 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -105,6 +105,7 @@ extern int dir_notify_enable; #define MS_REC 16384 #define MS_VERBOSE 32768 #define MS_PRIVATE (1<<18) /* change to private */ +#define MS_SLAVE (1<<19) /* change to slave */ #define MS_SHARED (1<<20) /* change to shared */ #define MS_POSIXACL (1<<16) /* VFS does not apply the umask */ #define MS_ACTIVE (1<<30) diff --git a/include/linux/mount.h b/include/linux/mount.h index 2582559718fc..7e133ae2a94f 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -38,6 +38,9 @@ struct vfsmount { struct list_head mnt_list; struct list_head mnt_expire; /* link in fs-specific expiry list */ struct list_head mnt_share; /* circular list of shared mounts */ + struct list_head mnt_slave_list;/* list of slave mounts */ + struct list_head mnt_slave; /* slave list entry */ + struct vfsmount *mnt_master; /* slave is on master->mnt_slave_list */ struct namespace *mnt_namespace; /* containing namespace */ int mnt_pinned; }; -- cgit v1.2.3 From 9676f0c6389b62bd6b24d77d4b3abdbcfa32d0f2 Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Mon, 7 Nov 2005 17:21:20 -0500 Subject: [PATCH] unbindable mounts An unbindable mount does not forward or receive propagation. Also unbindable mount disallows bind mounts. The semantics is as follows. Bind semantics: It is invalid to bind mount an unbindable mount. Move semantics: It is invalid to move an unbindable mount under shared mount. Clone-namespace semantics: If a mount is unbindable in the parent namespace, the corresponding cloned mount in the child namespace becomes unbindable too. Note: there is subtle difference, unbindable mounts cannot be bind mounted but can be cloned during clone-namespace. Signed-off-by: Ram Pai Signed-off-by: Al Viro Signed-off-by: Linus Torvalds --- fs/namespace.c | 88 ++++++++++++++++++++++++++++++++++++--------------- fs/pnode.c | 2 ++ fs/pnode.h | 1 + include/linux/fs.h | 1 + include/linux/mount.h | 1 + 5 files changed, 67 insertions(+), 26 deletions(-) (limited to 'include/linux') diff --git a/fs/namespace.c b/fs/namespace.c index 089670363704..caa9187f67e5 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -213,6 +213,16 @@ static struct vfsmount *next_mnt(struct vfsmount *p, struct vfsmount *root) return list_entry(next, struct vfsmount, mnt_child); } +static struct vfsmount *skip_mnt_tree(struct vfsmount *p) +{ + struct list_head *prev = p->mnt_mounts.prev; + while (prev != &p->mnt_mounts) { + p = list_entry(prev, struct vfsmount, mnt_child); + prev = p->mnt_mounts.prev; + } + return p; +} + static struct vfsmount *clone_mnt(struct vfsmount *old, struct dentry *root, int flag) { @@ -650,6 +660,9 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, struct vfsmount *res, *p, *q, *r, *s; struct nameidata nd; + if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(mnt)) + return NULL; + res = q = clone_mnt(mnt, dentry, flag); if (!q) goto Enomem; @@ -661,6 +674,10 @@ struct vfsmount *copy_tree(struct vfsmount *mnt, struct dentry *dentry, continue; for (s = r; s; s = next_mnt(s, r)) { + if (!(flag & CL_COPY_ALL) && IS_MNT_UNBINDABLE(s)) { + s = skip_mnt_tree(s); + continue; + } while (p != s->mnt_parent) { p = p->mnt_parent; q = q->mnt_parent; @@ -698,18 +715,18 @@ Enomem: * * NOTE: in the table below explains the semantics when a source mount * of a given type is attached to a destination mount of a given type. - * ------------------------------------------------------------- - * | BIND MOUNT OPERATION | - * |************************************************************* - * | source-->| shared | private | slave | - * | dest | | | | - * | | | | | | - * | v | | | | - * |************************************************************* - * | shared | shared (++) | shared (+) | shared(+++)| - * | | | | | - * |non-shared| shared (+) | private | slave (*) | - * ************************************************************** + * --------------------------------------------------------------------------- + * | BIND MOUNT OPERATION | + * |************************************************************************** + * | source-->| shared | private | slave | unbindable | + * | dest | | | | | + * | | | | | | | + * | v | | | | | + * |************************************************************************** + * | shared | shared (++) | shared (+) | shared(+++)| invalid | + * | | | | | | + * |non-shared| shared (+) | private | slave (*) | invalid | + * *************************************************************************** * A bind operation clones the source mount and mounts the clone on the * destination mount. * @@ -726,18 +743,18 @@ Enomem: * (*) the cloned mount is made a slave of the same master as that of the * source mount. * - * -------------------------------------------------------------- - * | MOVE MOUNT OPERATION | - * |************************************************************* - * | source-->| shared | private | slave | - * | dest | | | | - * | | | | | | - * | v | | | | - * |************************************************************* - * | shared | shared (+) | shared (+) | shared(+++) | - * | | | | | - * |non-shared| shared (+*) | private | slave (*) | - * ************************************************************** + * --------------------------------------------------------------------------- + * | MOVE MOUNT OPERATION | + * |************************************************************************** + * | source-->| shared | private | slave | unbindable | + * | dest | | | | | + * | | | | | | | + * | v | | | | | + * |************************************************************************** + * | shared | shared (+) | shared (+) | shared(+++) | invalid | + * | | | | | | + * |non-shared| shared (+*) | private | slave (*) | unbindable | + * *************************************************************************** * * (+) the mount is moved to the destination. And is then propagated to * all the mounts in the propagation tree of the destination mount. @@ -854,6 +871,9 @@ static int do_loopback(struct nameidata *nd, char *old_name, int recurse) down_write(&namespace_sem); err = -EINVAL; + if (IS_MNT_UNBINDABLE(old_nd.mnt)) + goto out; + if (!check_mnt(nd->mnt) || !check_mnt(old_nd.mnt)) goto out; @@ -911,6 +931,16 @@ static int do_remount(struct nameidata *nd, int flags, int mnt_flags, return err; } +static inline int tree_contains_unbindable(struct vfsmount *mnt) +{ + struct vfsmount *p; + for (p = mnt; p; p = next_mnt(p, mnt)) { + if (IS_MNT_UNBINDABLE(p)) + return 1; + } + return 0; +} + static int do_move_mount(struct nameidata *nd, char *old_name) { struct nameidata old_nd, parent_nd; @@ -954,6 +984,12 @@ static int do_move_mount(struct nameidata *nd, char *old_name) */ if (old_nd.mnt->mnt_parent && IS_MNT_SHARED(old_nd.mnt->mnt_parent)) goto out1; + /* + * Don't move a mount tree containing unbindable mounts to a destination + * mount which is shared. + */ + if (IS_MNT_SHARED(nd->mnt) && tree_contains_unbindable(old_nd.mnt)) + goto out1; err = -ELOOP; for (p = nd->mnt; p->mnt_parent != p; p = p->mnt_parent) if (p == old_nd.mnt) @@ -1266,7 +1302,7 @@ long do_mount(char *dev_name, char *dir_name, char *type_page, data_page); else if (flags & MS_BIND) retval = do_loopback(&nd, dev_name, flags & MS_REC); - else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE)) + else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE)) retval = do_change_type(&nd, flags); else if (flags & MS_MOVE) retval = do_move_mount(&nd, dev_name); @@ -1311,7 +1347,7 @@ int copy_namespace(int flags, struct task_struct *tsk) down_write(&namespace_sem); /* First pass: copy the tree topology */ new_ns->root = copy_tree(namespace->root, namespace->root->mnt_root, - CL_EXPIRE); + CL_COPY_ALL | CL_EXPIRE); if (!new_ns->root) { up_write(&namespace_sem); kfree(new_ns); diff --git a/fs/pnode.c b/fs/pnode.c index 3e266c5a3071..aeeec8ba8dd2 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -82,6 +82,8 @@ void change_mnt_propagation(struct vfsmount *mnt, int type) if (type != MS_SLAVE) { list_del_init(&mnt->mnt_slave); mnt->mnt_master = NULL; + if (type == MS_UNBINDABLE) + mnt->mnt_flags |= MNT_UNBINDABLE; } } diff --git a/fs/pnode.h b/fs/pnode.h index b59f0e9fe6b1..020e1bb60fdb 100644 --- a/fs/pnode.h +++ b/fs/pnode.h @@ -15,6 +15,7 @@ #define IS_MNT_SLAVE(mnt) (mnt->mnt_master) #define IS_MNT_NEW(mnt) (!mnt->mnt_namespace) #define CLEAR_MNT_SHARED(mnt) (mnt->mnt_flags &= ~MNT_SHARED) +#define IS_MNT_UNBINDABLE(mnt) (mnt->mnt_flags & MNT_UNBINDABLE) #define CL_EXPIRE 0x01 #define CL_SLAVE 0x02 diff --git a/include/linux/fs.h b/include/linux/fs.h index eef66f54c017..1b5f502a4b8f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -104,6 +104,7 @@ extern int dir_notify_enable; #define MS_MOVE 8192 #define MS_REC 16384 #define MS_VERBOSE 32768 +#define MS_UNBINDABLE (1<<17) /* change to unbindable */ #define MS_PRIVATE (1<<18) /* change to private */ #define MS_SLAVE (1<<19) /* change to slave */ #define MS_SHARED (1<<20) /* change to shared */ diff --git a/include/linux/mount.h b/include/linux/mount.h index 7e133ae2a94f..dd4e83eba933 100644 --- a/include/linux/mount.h +++ b/include/linux/mount.h @@ -21,6 +21,7 @@ #define MNT_NODEV 0x02 #define MNT_NOEXEC 0x04 #define MNT_SHARED 0x10 /* if the vfsmount is a shared mount */ +#define MNT_UNBINDABLE 0x20 /* if the vfsmount is a unbindable mount */ #define MNT_PNODE_MASK 0x30 /* propogation flag mask */ struct vfsmount { -- cgit v1.2.3 From 48888cc6120ff945675ef79a3ba2955afa0f5124 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 5 Nov 2005 20:01:47 +0100 Subject: [PATCH] kill include/linux/eeprom.h This patch kills include/linux/eeprom.h . Rationale: - it was only used by one single driver - even this driver didn't do anything useful with it - most of this file are non-inline and non-static functions (sic) This removes include/linux/eeprom.h and cleans drivers/net/ns83820.c up. If you think eeprom.h should be used more extensively, please consider: - the code has to be moved from the header file to a .c file - the currently empty write function has to be implemented - ns83820.c or any other driver should actually use it Noone did any of these during the more than 3 years eeprom.h already exists... Signed-off-by: Adrian Bunk Signed-off-by: John W. Linville --- drivers/net/ns83820.c | 13 +---- include/linux/eeprom.h | 136 ------------------------------------------------- 2 files changed, 2 insertions(+), 147 deletions(-) delete mode 100644 include/linux/eeprom.h (limited to 'include/linux') diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index a3c3fc9c0d8a..f857ae94d261 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c @@ -110,7 +110,6 @@ #include #include /* for iph */ #include /* for IPPROTO_... */ -#include #include #include #include @@ -445,7 +444,6 @@ struct ns83820 { u32 MEAR_cache; u32 IMR_cache; - struct eeprom ee; unsigned linkstate; @@ -1558,15 +1556,13 @@ static void ns83820_getmac(struct ns83820 *dev, u8 *mac) unsigned i; for (i=0; i<3; i++) { u32 data; -#if 0 /* I've left this in as an example of how to use eeprom.h */ - data = eeprom_readw(&dev->ee, 0xa + 2 - i); -#else + /* Read from the perfect match memory: this is loaded by * the chip from the EEPROM via the EELOAD self test. */ writel(i*2, dev->base + RFCR); data = readl(dev->base + RFDR); -#endif + *mac++ = data; *mac++ = data >> 8; } @@ -1851,8 +1847,6 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ spin_lock_init(&dev->misc_lock); dev->pci_dev = pci_dev; - dev->ee.cache = &dev->MEAR_cache; - dev->ee.lock = &dev->misc_lock; SET_MODULE_OWNER(ndev); SET_NETDEV_DEV(ndev, &pci_dev->dev); @@ -1887,9 +1881,6 @@ static int __devinit ns83820_init_one(struct pci_dev *pci_dev, const struct pci_ dev->IMR_cache = 0; - setup_ee_mem_bitbanger(&dev->ee, dev->base + MEAR, 3, 2, 1, 0, - 0); - err = request_irq(pci_dev->irq, ns83820_irq, SA_SHIRQ, DRV_NAME, ndev); if (err) { diff --git a/include/linux/eeprom.h b/include/linux/eeprom.h deleted file mode 100644 index 38afd9da1dfe..000000000000 --- a/include/linux/eeprom.h +++ /dev/null @@ -1,136 +0,0 @@ -/* credit winbond-840.c - */ -#include -struct eeprom_ops { - void (*set_cs)(void *ee); - void (*clear_cs)(void *ee); -}; - -#define EEPOL_EEDI 0x01 -#define EEPOL_EEDO 0x02 -#define EEPOL_EECLK 0x04 -#define EEPOL_EESEL 0x08 - -struct eeprom { - void *dev; - struct eeprom_ops *ops; - - void __iomem * addr; - - unsigned ee_addr_bits; - - unsigned eesel; - unsigned eeclk; - unsigned eedo; - unsigned eedi; - unsigned polarity; - unsigned ee_state; - - spinlock_t *lock; - u32 *cache; -}; - - -u8 eeprom_readb(struct eeprom *ee, unsigned address); -void eeprom_read(struct eeprom *ee, unsigned address, u8 *bytes, - unsigned count); -void eeprom_writeb(struct eeprom *ee, unsigned address, u8 data); -void eeprom_write(struct eeprom *ee, unsigned address, u8 *bytes, - unsigned count); - -/* The EEPROM commands include the alway-set leading bit. */ -enum EEPROM_Cmds { - EE_WriteCmd=(5 << 6), EE_ReadCmd=(6 << 6), EE_EraseCmd=(7 << 6), -}; - -void setup_ee_mem_bitbanger(struct eeprom *ee, void __iomem *memaddr, int eesel_bit, int eeclk_bit, int eedo_bit, int eedi_bit, unsigned polarity) -{ - ee->addr = memaddr; - ee->eesel = 1 << eesel_bit; - ee->eeclk = 1 << eeclk_bit; - ee->eedo = 1 << eedo_bit; - ee->eedi = 1 << eedi_bit; - - ee->polarity = polarity; - - *ee->cache = readl(ee->addr); -} - -/* foo. put this in a .c file */ -static inline void eeprom_update(struct eeprom *ee, u32 mask, int pol) -{ - unsigned long flags; - u32 data; - - spin_lock_irqsave(ee->lock, flags); - data = *ee->cache; - - data &= ~mask; - if (pol) - data |= mask; - - *ee->cache = data; -//printk("update: %08x\n", data); - writel(data, ee->addr); - spin_unlock_irqrestore(ee->lock, flags); -} - -void eeprom_clk_lo(struct eeprom *ee) -{ - int pol = !!(ee->polarity & EEPOL_EECLK); - - eeprom_update(ee, ee->eeclk, pol); - udelay(2); -} - -void eeprom_clk_hi(struct eeprom *ee) -{ - int pol = !!(ee->polarity & EEPOL_EECLK); - - eeprom_update(ee, ee->eeclk, !pol); - udelay(2); -} - -void eeprom_send_addr(struct eeprom *ee, unsigned address) -{ - int pol = !!(ee->polarity & EEPOL_EEDI); - unsigned i; - address |= 6 << 6; - - /* Shift the read command bits out. */ - for (i=0; i<11; i++) { - eeprom_update(ee, ee->eedi, ((address >> 10) & 1) ^ pol); - address <<= 1; - eeprom_clk_hi(ee); - eeprom_clk_lo(ee); - } - eeprom_update(ee, ee->eedi, pol); -} - -u16 eeprom_readw(struct eeprom *ee, unsigned address) -{ - unsigned i; - u16 res = 0; - - eeprom_clk_lo(ee); - eeprom_update(ee, ee->eesel, 1 ^ !!(ee->polarity & EEPOL_EESEL)); - eeprom_send_addr(ee, address); - - for (i=0; i<16; i++) { - u32 data; - eeprom_clk_hi(ee); - res <<= 1; - data = readl(ee->addr); -//printk("eeprom_readw: %08x\n", data); - res |= !!(data & ee->eedo) ^ !!(ee->polarity & EEPOL_EEDO); - eeprom_clk_lo(ee); - } - eeprom_update(ee, ee->eesel, 0 ^ !!(ee->polarity & EEPOL_EESEL)); - - return res; -} - - -void eeprom_writeb(struct eeprom *ee, unsigned address, u8 data) -{ -} -- cgit v1.2.3 From b3f9b92a6ec1a9a5e4b4b36e484f2f62cc73277c Mon Sep 17 00:00:00 2001 From: Matt Domsch Date: Tue, 8 Nov 2005 09:40:47 -0800 Subject: [PPP]: add PPP MPPE encryption module From: Matt Domsch The patch below implements the Microsoft Point-to-Point Encryption method as a PPP compressor/decompressor. This is necessary for Linux clients and servers to interoperate with Microsoft Point-to-Point Tunneling Protocol (PPTP) servers (either Microsoft PPTP servers or the poptop project) which use MPPE to encrypt data when creating a VPN. This patch differs from the kernel_ppp_mppe DKMS pacakge at pptpclient.sourceforge.net by utilizing the kernel crypto routines rather than providing its own SHA1 and arcfour implementations. Minor changes to ppp_generic.c try to prevent a link from disabling compression (in our case, the encryption) after it has started using compression (encryption). Feedback to please. Signed-off-by: Matt Domsch Cc: James Cameron Cc: "David S. Miller" Signed-off-by: Brice Goglin Acked-by: Paul Mackerras Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/net/Kconfig | 13 + drivers/net/Makefile | 1 + drivers/net/ppp_generic.c | 88 ++++-- drivers/net/ppp_mppe.c | 724 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/net/ppp_mppe.h | 86 ++++++ include/linux/if_ppp.h | 7 +- include/linux/ppp-comp.h | 9 + 7 files changed, 902 insertions(+), 26 deletions(-) create mode 100644 drivers/net/ppp_mppe.c create mode 100644 drivers/net/ppp_mppe.h (limited to 'include/linux') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 1958d9e16a3a..24f1691b84f9 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2523,6 +2523,19 @@ config PPP_BSDCOMP module; it is called bsd_comp and will show up in the directory modules once you have said "make modules". If unsure, say N. +config PPP_MPPE + tristate "PPP MPPE compression (encryption) (EXPERIMENTAL)" + depends on PPP && EXPERIMENTAL + select CRYPTO + select CRYPTO_SHA1 + select CRYPTO_ARC4 + ---help--- + Support for the MPPE Encryption protocol, as employed by the + Microsoft Point-to-Point Tunneling Protocol. + + See http://pptpclient.sourceforge.net/ for information on + configuring PPTP clients and servers to utilize this method. + config PPPOE tristate "PPP over Ethernet (EXPERIMENTAL)" depends on EXPERIMENTAL && PPP diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 7c313cb341b8..4cffd34442aa 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -112,6 +112,7 @@ obj-$(CONFIG_PPP_ASYNC) += ppp_async.o obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o +obj-$(CONFIG_PPP_MPPE) += ppp_mppe.o obj-$(CONFIG_PPPOE) += pppox.o pppoe.o obj-$(CONFIG_SLIP) += slip.o diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index d3c9958b00d0..50430f79f8cf 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c @@ -137,13 +137,14 @@ struct ppp { /* * Bits in flags: SC_NO_TCP_CCID, SC_CCP_OPEN, SC_CCP_UP, SC_LOOP_TRAFFIC, - * SC_MULTILINK, SC_MP_SHORTSEQ, SC_MP_XSHORTSEQ, SC_COMP_TCP, SC_REJ_COMP_TCP. + * SC_MULTILINK, SC_MP_SHORTSEQ, SC_MP_XSHORTSEQ, SC_COMP_TCP, SC_REJ_COMP_TCP, + * SC_MUST_COMP * Bits in rstate: SC_DECOMP_RUN, SC_DC_ERROR, SC_DC_FERROR. * Bits in xstate: SC_COMP_RUN */ #define SC_FLAG_BITS (SC_NO_TCP_CCID|SC_CCP_OPEN|SC_CCP_UP|SC_LOOP_TRAFFIC \ |SC_MULTILINK|SC_MP_SHORTSEQ|SC_MP_XSHORTSEQ \ - |SC_COMP_TCP|SC_REJ_COMP_TCP) + |SC_COMP_TCP|SC_REJ_COMP_TCP|SC_MUST_COMP) /* * Private data structure for each channel. @@ -1027,6 +1028,56 @@ ppp_xmit_process(struct ppp *ppp) ppp_xmit_unlock(ppp); } +static inline struct sk_buff * +pad_compress_skb(struct ppp *ppp, struct sk_buff *skb) +{ + struct sk_buff *new_skb; + int len; + int new_skb_size = ppp->dev->mtu + + ppp->xcomp->comp_extra + ppp->dev->hard_header_len; + int compressor_skb_size = ppp->dev->mtu + + ppp->xcomp->comp_extra + PPP_HDRLEN; + new_skb = alloc_skb(new_skb_size, GFP_ATOMIC); + if (!new_skb) { + if (net_ratelimit()) + printk(KERN_ERR "PPP: no memory (comp pkt)\n"); + return NULL; + } + if (ppp->dev->hard_header_len > PPP_HDRLEN) + skb_reserve(new_skb, + ppp->dev->hard_header_len - PPP_HDRLEN); + + /* compressor still expects A/C bytes in hdr */ + len = ppp->xcomp->compress(ppp->xc_state, skb->data - 2, + new_skb->data, skb->len + 2, + compressor_skb_size); + if (len > 0 && (ppp->flags & SC_CCP_UP)) { + kfree_skb(skb); + skb = new_skb; + skb_put(skb, len); + skb_pull(skb, 2); /* pull off A/C bytes */ + } else if (len == 0) { + /* didn't compress, or CCP not up yet */ + kfree_skb(new_skb); + new_skb = skb; + } else { + /* + * (len < 0) + * MPPE requires that we do not send unencrypted + * frames. The compressor will return -1 if we + * should drop the frame. We cannot simply test + * the compress_proto because MPPE and MPPC share + * the same number. + */ + if (net_ratelimit()) + printk(KERN_ERR "ppp: compressor dropped pkt\n"); + kfree_skb(skb); + kfree_skb(new_skb); + new_skb = NULL; + } + return new_skb; +} + /* * Compress and send a frame. * The caller should have locked the xmit path, @@ -1113,29 +1164,14 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) /* try to do packet compression */ if ((ppp->xstate & SC_COMP_RUN) && ppp->xc_state != 0 && proto != PPP_LCP && proto != PPP_CCP) { - new_skb = alloc_skb(ppp->dev->mtu + ppp->dev->hard_header_len, - GFP_ATOMIC); - if (new_skb == 0) { - printk(KERN_ERR "PPP: no memory (comp pkt)\n"); + if (!(ppp->flags & SC_CCP_UP) && (ppp->flags & SC_MUST_COMP)) { + if (net_ratelimit()) + printk(KERN_ERR "ppp: compression required but down - pkt dropped.\n"); goto drop; } - if (ppp->dev->hard_header_len > PPP_HDRLEN) - skb_reserve(new_skb, - ppp->dev->hard_header_len - PPP_HDRLEN); - - /* compressor still expects A/C bytes in hdr */ - len = ppp->xcomp->compress(ppp->xc_state, skb->data - 2, - new_skb->data, skb->len + 2, - ppp->dev->mtu + PPP_HDRLEN); - if (len > 0 && (ppp->flags & SC_CCP_UP)) { - kfree_skb(skb); - skb = new_skb; - skb_put(skb, len); - skb_pull(skb, 2); /* pull off A/C bytes */ - } else { - /* didn't compress, or CCP not up yet */ - kfree_skb(new_skb); - } + skb = pad_compress_skb(ppp, skb); + if (!skb) + goto drop; } /* @@ -1155,7 +1191,8 @@ ppp_send_frame(struct ppp *ppp, struct sk_buff *skb) return; drop: - kfree_skb(skb); + if (skb) + kfree_skb(skb); ++ppp->stats.tx_errors; } @@ -1552,6 +1589,9 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) && (ppp->rstate & (SC_DC_FERROR | SC_DC_ERROR)) == 0) skb = ppp_decompress_frame(ppp, skb); + if (ppp->flags & SC_MUST_COMP && ppp->rstate & SC_DC_FERROR) + goto err; + proto = PPP_PROTO(skb); switch (proto) { case PPP_VJC_COMP: diff --git a/drivers/net/ppp_mppe.c b/drivers/net/ppp_mppe.c new file mode 100644 index 000000000000..1985d1b57c45 --- /dev/null +++ b/drivers/net/ppp_mppe.c @@ -0,0 +1,724 @@ +/* + * ppp_mppe.c - interface MPPE to the PPP code. + * This version is for use with Linux kernel 2.6.14+ + * + * By Frank Cusack . + * Copyright (c) 2002,2003,2004 Google, Inc. + * All rights reserved. + * + * License: + * Permission to use, copy, modify, and distribute this software and its + * documentation is hereby granted, provided that the above copyright + * notice appears in all copies. This software is provided without any + * warranty, express or implied. + * + * ALTERNATIVELY, provided that this notice is retained in full, this product + * may be distributed under the terms of the GNU General Public License (GPL), + * in which case the provisions of the GPL apply INSTEAD OF those given above. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * Changelog: + * 08/12/05 - Matt Domsch + * Only need extra skb padding on transmit, not receive. + * 06/18/04 - Matt Domsch , Oleg Makarenko + * Use Linux kernel 2.6 arc4 and sha1 routines rather than + * providing our own. + * 2/15/04 - TS: added #include and testing for Kernel + * version before using + * MOD_DEC_USAGE_COUNT/MOD_INC_USAGE_COUNT which are + * deprecated in 2.6 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ppp_mppe.h" + +MODULE_AUTHOR("Frank Cusack "); +MODULE_DESCRIPTION("Point-to-Point Protocol Microsoft Point-to-Point Encryption support"); +MODULE_LICENSE("Dual BSD/GPL"); +MODULE_ALIAS("ppp-compress-" __stringify(CI_MPPE)); +MODULE_VERSION("1.0.2"); + +static void +setup_sg(struct scatterlist *sg, const void *address, unsigned int length) +{ + sg[0].page = virt_to_page(address); + sg[0].offset = offset_in_page(address); + sg[0].length = length; +} + +#define SHA1_PAD_SIZE 40 + +/* + * kernel crypto API needs its arguments to be in kmalloc'd memory, not in the module + * static data area. That means sha_pad needs to be kmalloc'd. + */ + +struct sha_pad { + unsigned char sha_pad1[SHA1_PAD_SIZE]; + unsigned char sha_pad2[SHA1_PAD_SIZE]; +}; +static struct sha_pad *sha_pad; + +static inline void sha_pad_init(struct sha_pad *shapad) +{ + memset(shapad->sha_pad1, 0x00, sizeof(shapad->sha_pad1)); + memset(shapad->sha_pad2, 0xF2, sizeof(shapad->sha_pad2)); +} + +/* + * State for an MPPE (de)compressor. + */ +struct ppp_mppe_state { + struct crypto_tfm *arc4; + struct crypto_tfm *sha1; + unsigned char *sha1_digest; + unsigned char master_key[MPPE_MAX_KEY_LEN]; + unsigned char session_key[MPPE_MAX_KEY_LEN]; + unsigned keylen; /* key length in bytes */ + /* NB: 128-bit == 16, 40-bit == 8! */ + /* If we want to support 56-bit, */ + /* the unit has to change to bits */ + unsigned char bits; /* MPPE control bits */ + unsigned ccount; /* 12-bit coherency count (seqno) */ + unsigned stateful; /* stateful mode flag */ + int discard; /* stateful mode packet loss flag */ + int sanity_errors; /* take down LCP if too many */ + int unit; + int debug; + struct compstat stats; +}; + +/* struct ppp_mppe_state.bits definitions */ +#define MPPE_BIT_A 0x80 /* Encryption table were (re)inititalized */ +#define MPPE_BIT_B 0x40 /* MPPC only (not implemented) */ +#define MPPE_BIT_C 0x20 /* MPPC only (not implemented) */ +#define MPPE_BIT_D 0x10 /* This is an encrypted frame */ + +#define MPPE_BIT_FLUSHED MPPE_BIT_A +#define MPPE_BIT_ENCRYPTED MPPE_BIT_D + +#define MPPE_BITS(p) ((p)[4] & 0xf0) +#define MPPE_CCOUNT(p) ((((p)[4] & 0x0f) << 8) + (p)[5]) +#define MPPE_CCOUNT_SPACE 0x1000 /* The size of the ccount space */ + +#define MPPE_OVHD 2 /* MPPE overhead/packet */ +#define SANITY_MAX 1600 /* Max bogon factor we will tolerate */ + +/* + * Key Derivation, from RFC 3078, RFC 3079. + * Equivalent to Get_Key() for MS-CHAP as described in RFC 3079. + */ +static void get_new_key_from_sha(struct ppp_mppe_state * state, unsigned char *InterimKey) +{ + struct scatterlist sg[4]; + + setup_sg(&sg[0], state->master_key, state->keylen); + setup_sg(&sg[1], sha_pad->sha_pad1, sizeof(sha_pad->sha_pad1)); + setup_sg(&sg[2], state->session_key, state->keylen); + setup_sg(&sg[3], sha_pad->sha_pad2, sizeof(sha_pad->sha_pad2)); + + crypto_digest_digest (state->sha1, sg, 4, state->sha1_digest); + + memcpy(InterimKey, state->sha1_digest, state->keylen); +} + +/* + * Perform the MPPE rekey algorithm, from RFC 3078, sec. 7.3. + * Well, not what's written there, but rather what they meant. + */ +static void mppe_rekey(struct ppp_mppe_state * state, int initial_key) +{ + unsigned char InterimKey[MPPE_MAX_KEY_LEN]; + struct scatterlist sg_in[1], sg_out[1]; + + get_new_key_from_sha(state, InterimKey); + if (!initial_key) { + crypto_cipher_setkey(state->arc4, InterimKey, state->keylen); + setup_sg(sg_in, InterimKey, state->keylen); + setup_sg(sg_out, state->session_key, state->keylen); + if (crypto_cipher_encrypt(state->arc4, sg_out, sg_in, + state->keylen) != 0) { + printk(KERN_WARNING "mppe_rekey: cipher_encrypt failed\n"); + } + } else { + memcpy(state->session_key, InterimKey, state->keylen); + } + if (state->keylen == 8) { + /* See RFC 3078 */ + state->session_key[0] = 0xd1; + state->session_key[1] = 0x26; + state->session_key[2] = 0x9e; + } + crypto_cipher_setkey(state->arc4, state->session_key, state->keylen); +} + +/* + * Allocate space for a (de)compressor. + */ +static void *mppe_alloc(unsigned char *options, int optlen) +{ + struct ppp_mppe_state *state; + unsigned int digestsize; + + if (optlen != CILEN_MPPE + sizeof(state->master_key) + || options[0] != CI_MPPE || options[1] != CILEN_MPPE) + goto out; + + state = (struct ppp_mppe_state *) kmalloc(sizeof(*state), GFP_KERNEL); + if (state == NULL) + goto out; + + memset(state, 0, sizeof(*state)); + + state->arc4 = crypto_alloc_tfm("arc4", 0); + if (!state->arc4) + goto out_free; + + state->sha1 = crypto_alloc_tfm("sha1", 0); + if (!state->sha1) + goto out_free; + + digestsize = crypto_tfm_alg_digestsize(state->sha1); + if (digestsize < MPPE_MAX_KEY_LEN) + goto out_free; + + state->sha1_digest = kmalloc(digestsize, GFP_KERNEL); + if (!state->sha1_digest) + goto out_free; + + /* Save keys. */ + memcpy(state->master_key, &options[CILEN_MPPE], + sizeof(state->master_key)); + memcpy(state->session_key, state->master_key, + sizeof(state->master_key)); + + /* + * We defer initial key generation until mppe_init(), as mppe_alloc() + * is called frequently during negotiation. + */ + + return (void *)state; + + out_free: + if (state->sha1_digest) + kfree(state->sha1_digest); + if (state->sha1) + crypto_free_tfm(state->sha1); + if (state->arc4) + crypto_free_tfm(state->arc4); + kfree(state); + out: + return NULL; +} + +/* + * Deallocate space for a (de)compressor. + */ +static void mppe_free(void *arg) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; + if (state) { + if (state->sha1_digest) + kfree(state->sha1_digest); + if (state->sha1) + crypto_free_tfm(state->sha1); + if (state->arc4) + crypto_free_tfm(state->arc4); + kfree(state); + } +} + +/* + * Initialize (de)compressor state. + */ +static int +mppe_init(void *arg, unsigned char *options, int optlen, int unit, int debug, + const char *debugstr) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; + unsigned char mppe_opts; + + if (optlen != CILEN_MPPE + || options[0] != CI_MPPE || options[1] != CILEN_MPPE) + return 0; + + MPPE_CI_TO_OPTS(&options[2], mppe_opts); + if (mppe_opts & MPPE_OPT_128) + state->keylen = 16; + else if (mppe_opts & MPPE_OPT_40) + state->keylen = 8; + else { + printk(KERN_WARNING "%s[%d]: unknown key length\n", debugstr, + unit); + return 0; + } + if (mppe_opts & MPPE_OPT_STATEFUL) + state->stateful = 1; + + /* Generate the initial session key. */ + mppe_rekey(state, 1); + + if (debug) { + int i; + char mkey[sizeof(state->master_key) * 2 + 1]; + char skey[sizeof(state->session_key) * 2 + 1]; + + printk(KERN_DEBUG "%s[%d]: initialized with %d-bit %s mode\n", + debugstr, unit, (state->keylen == 16) ? 128 : 40, + (state->stateful) ? "stateful" : "stateless"); + + for (i = 0; i < sizeof(state->master_key); i++) + sprintf(mkey + i * 2, "%02x", state->master_key[i]); + for (i = 0; i < sizeof(state->session_key); i++) + sprintf(skey + i * 2, "%02x", state->session_key[i]); + printk(KERN_DEBUG + "%s[%d]: keys: master: %s initial session: %s\n", + debugstr, unit, mkey, skey); + } + + /* + * Initialize the coherency count. The initial value is not specified + * in RFC 3078, but we can make a reasonable assumption that it will + * start at 0. Setting it to the max here makes the comp/decomp code + * do the right thing (determined through experiment). + */ + state->ccount = MPPE_CCOUNT_SPACE - 1; + + /* + * Note that even though we have initialized the key table, we don't + * set the FLUSHED bit. This is contrary to RFC 3078, sec. 3.1. + */ + state->bits = MPPE_BIT_ENCRYPTED; + + state->unit = unit; + state->debug = debug; + + return 1; +} + +static int +mppe_comp_init(void *arg, unsigned char *options, int optlen, int unit, + int hdrlen, int debug) +{ + /* ARGSUSED */ + return mppe_init(arg, options, optlen, unit, debug, "mppe_comp_init"); +} + +/* + * We received a CCP Reset-Request (actually, we are sending a Reset-Ack), + * tell the compressor to rekey. Note that we MUST NOT rekey for + * every CCP Reset-Request; we only rekey on the next xmit packet. + * We might get multiple CCP Reset-Requests if our CCP Reset-Ack is lost. + * So, rekeying for every CCP Reset-Request is broken as the peer will not + * know how many times we've rekeyed. (If we rekey and THEN get another + * CCP Reset-Request, we must rekey again.) + */ +static void mppe_comp_reset(void *arg) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; + + state->bits |= MPPE_BIT_FLUSHED; +} + +/* + * Compress (encrypt) a packet. + * It's strange to call this a compressor, since the output is always + * MPPE_OVHD + 2 bytes larger than the input. + */ +static int +mppe_compress(void *arg, unsigned char *ibuf, unsigned char *obuf, + int isize, int osize) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; + int proto; + struct scatterlist sg_in[1], sg_out[1]; + + /* + * Check that the protocol is in the range we handle. + */ + proto = PPP_PROTOCOL(ibuf); + if (proto < 0x0021 || proto > 0x00fa) + return 0; + + /* Make sure we have enough room to generate an encrypted packet. */ + if (osize < isize + MPPE_OVHD + 2) { + /* Drop the packet if we should encrypt it, but can't. */ + printk(KERN_DEBUG "mppe_compress[%d]: osize too small! " + "(have: %d need: %d)\n", state->unit, + osize, osize + MPPE_OVHD + 2); + return -1; + } + + osize = isize + MPPE_OVHD + 2; + + /* + * Copy over the PPP header and set control bits. + */ + obuf[0] = PPP_ADDRESS(ibuf); + obuf[1] = PPP_CONTROL(ibuf); + obuf[2] = PPP_COMP >> 8; /* isize + MPPE_OVHD + 1 */ + obuf[3] = PPP_COMP; /* isize + MPPE_OVHD + 2 */ + obuf += PPP_HDRLEN; + + state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; + if (state->debug >= 7) + printk(KERN_DEBUG "mppe_compress[%d]: ccount %d\n", state->unit, + state->ccount); + obuf[0] = state->ccount >> 8; + obuf[1] = state->ccount & 0xff; + + if (!state->stateful || /* stateless mode */ + ((state->ccount & 0xff) == 0xff) || /* "flag" packet */ + (state->bits & MPPE_BIT_FLUSHED)) { /* CCP Reset-Request */ + /* We must rekey */ + if (state->debug && state->stateful) + printk(KERN_DEBUG "mppe_compress[%d]: rekeying\n", + state->unit); + mppe_rekey(state, 0); + state->bits |= MPPE_BIT_FLUSHED; + } + obuf[0] |= state->bits; + state->bits &= ~MPPE_BIT_FLUSHED; /* reset for next xmit */ + + obuf += MPPE_OVHD; + ibuf += 2; /* skip to proto field */ + isize -= 2; + + /* Encrypt packet */ + setup_sg(sg_in, ibuf, isize); + setup_sg(sg_out, obuf, osize); + if (crypto_cipher_encrypt(state->arc4, sg_out, sg_in, isize) != 0) { + printk(KERN_DEBUG "crypto_cypher_encrypt failed\n"); + return -1; + } + + state->stats.unc_bytes += isize; + state->stats.unc_packets++; + state->stats.comp_bytes += osize; + state->stats.comp_packets++; + + return osize; +} + +/* + * Since every frame grows by MPPE_OVHD + 2 bytes, this is always going + * to look bad ... and the longer the link is up the worse it will get. + */ +static void mppe_comp_stats(void *arg, struct compstat *stats) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; + + *stats = state->stats; +} + +static int +mppe_decomp_init(void *arg, unsigned char *options, int optlen, int unit, + int hdrlen, int mru, int debug) +{ + /* ARGSUSED */ + return mppe_init(arg, options, optlen, unit, debug, "mppe_decomp_init"); +} + +/* + * We received a CCP Reset-Ack. Just ignore it. + */ +static void mppe_decomp_reset(void *arg) +{ + /* ARGSUSED */ + return; +} + +/* + * Decompress (decrypt) an MPPE packet. + */ +static int +mppe_decompress(void *arg, unsigned char *ibuf, int isize, unsigned char *obuf, + int osize) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; + unsigned ccount; + int flushed = MPPE_BITS(ibuf) & MPPE_BIT_FLUSHED; + int sanity = 0; + struct scatterlist sg_in[1], sg_out[1]; + + if (isize <= PPP_HDRLEN + MPPE_OVHD) { + if (state->debug) + printk(KERN_DEBUG + "mppe_decompress[%d]: short pkt (%d)\n", + state->unit, isize); + return DECOMP_ERROR; + } + + /* + * Make sure we have enough room to decrypt the packet. + * Note that for our test we only subtract 1 byte whereas in + * mppe_compress() we added 2 bytes (+MPPE_OVHD); + * this is to account for possible PFC. + */ + if (osize < isize - MPPE_OVHD - 1) { + printk(KERN_DEBUG "mppe_decompress[%d]: osize too small! " + "(have: %d need: %d)\n", state->unit, + osize, isize - MPPE_OVHD - 1); + return DECOMP_ERROR; + } + osize = isize - MPPE_OVHD - 2; /* assume no PFC */ + + ccount = MPPE_CCOUNT(ibuf); + if (state->debug >= 7) + printk(KERN_DEBUG "mppe_decompress[%d]: ccount %d\n", + state->unit, ccount); + + /* sanity checks -- terminate with extreme prejudice */ + if (!(MPPE_BITS(ibuf) & MPPE_BIT_ENCRYPTED)) { + printk(KERN_DEBUG + "mppe_decompress[%d]: ENCRYPTED bit not set!\n", + state->unit); + state->sanity_errors += 100; + sanity = 1; + } + if (!state->stateful && !flushed) { + printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set in " + "stateless mode!\n", state->unit); + state->sanity_errors += 100; + sanity = 1; + } + if (state->stateful && ((ccount & 0xff) == 0xff) && !flushed) { + printk(KERN_DEBUG "mppe_decompress[%d]: FLUSHED bit not set on " + "flag packet!\n", state->unit); + state->sanity_errors += 100; + sanity = 1; + } + + if (sanity) { + if (state->sanity_errors < SANITY_MAX) + return DECOMP_ERROR; + else + /* + * Take LCP down if the peer is sending too many bogons. + * We don't want to do this for a single or just a few + * instances since it could just be due to packet corruption. + */ + return DECOMP_FATALERROR; + } + + /* + * Check the coherency count. + */ + + if (!state->stateful) { + /* RFC 3078, sec 8.1. Rekey for every packet. */ + while (state->ccount != ccount) { + mppe_rekey(state, 0); + state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; + } + } else { + /* RFC 3078, sec 8.2. */ + if (!state->discard) { + /* normal state */ + state->ccount = (state->ccount + 1) % MPPE_CCOUNT_SPACE; + if (ccount != state->ccount) { + /* + * (ccount > state->ccount) + * Packet loss detected, enter the discard state. + * Signal the peer to rekey (by sending a CCP Reset-Request). + */ + state->discard = 1; + return DECOMP_ERROR; + } + } else { + /* discard state */ + if (!flushed) { + /* ccp.c will be silent (no additional CCP Reset-Requests). */ + return DECOMP_ERROR; + } else { + /* Rekey for every missed "flag" packet. */ + while ((ccount & ~0xff) != + (state->ccount & ~0xff)) { + mppe_rekey(state, 0); + state->ccount = + (state->ccount + + 256) % MPPE_CCOUNT_SPACE; + } + + /* reset */ + state->discard = 0; + state->ccount = ccount; + /* + * Another problem with RFC 3078 here. It implies that the + * peer need not send a Reset-Ack packet. But RFC 1962 + * requires it. Hopefully, M$ does send a Reset-Ack; even + * though it isn't required for MPPE synchronization, it is + * required to reset CCP state. + */ + } + } + if (flushed) + mppe_rekey(state, 0); + } + + /* + * Fill in the first part of the PPP header. The protocol field + * comes from the decrypted data. + */ + obuf[0] = PPP_ADDRESS(ibuf); /* +1 */ + obuf[1] = PPP_CONTROL(ibuf); /* +1 */ + obuf += 2; + ibuf += PPP_HDRLEN + MPPE_OVHD; + isize -= PPP_HDRLEN + MPPE_OVHD; /* -6 */ + /* net osize: isize-4 */ + + /* + * Decrypt the first byte in order to check if it is + * a compressed or uncompressed protocol field. + */ + setup_sg(sg_in, ibuf, 1); + setup_sg(sg_out, obuf, 1); + if (crypto_cipher_decrypt(state->arc4, sg_out, sg_in, 1) != 0) { + printk(KERN_DEBUG "crypto_cypher_decrypt failed\n"); + return DECOMP_ERROR; + } + + /* + * Do PFC decompression. + * This would be nicer if we were given the actual sk_buff + * instead of a char *. + */ + if ((obuf[0] & 0x01) != 0) { + obuf[1] = obuf[0]; + obuf[0] = 0; + obuf++; + osize++; + } + + /* And finally, decrypt the rest of the packet. */ + setup_sg(sg_in, ibuf + 1, isize - 1); + setup_sg(sg_out, obuf + 1, osize - 1); + if (crypto_cipher_decrypt(state->arc4, sg_out, sg_in, isize - 1) != 0) { + printk(KERN_DEBUG "crypto_cypher_decrypt failed\n"); + return DECOMP_ERROR; + } + + state->stats.unc_bytes += osize; + state->stats.unc_packets++; + state->stats.comp_bytes += isize; + state->stats.comp_packets++; + + /* good packet credit */ + state->sanity_errors >>= 1; + + return osize; +} + +/* + * Incompressible data has arrived (this should never happen!). + * We should probably drop the link if the protocol is in the range + * of what should be encrypted. At the least, we should drop this + * packet. (How to do this?) + */ +static void mppe_incomp(void *arg, unsigned char *ibuf, int icnt) +{ + struct ppp_mppe_state *state = (struct ppp_mppe_state *) arg; + + if (state->debug && + (PPP_PROTOCOL(ibuf) >= 0x0021 && PPP_PROTOCOL(ibuf) <= 0x00fa)) + printk(KERN_DEBUG + "mppe_incomp[%d]: incompressible (unencrypted) data! " + "(proto %04x)\n", state->unit, PPP_PROTOCOL(ibuf)); + + state->stats.inc_bytes += icnt; + state->stats.inc_packets++; + state->stats.unc_bytes += icnt; + state->stats.unc_packets++; +} + +/************************************************************* + * Module interface table + *************************************************************/ + +/* + * Procedures exported to if_ppp.c. + */ +static struct compressor ppp_mppe = { + .compress_proto = CI_MPPE, + .comp_alloc = mppe_alloc, + .comp_free = mppe_free, + .comp_init = mppe_comp_init, + .comp_reset = mppe_comp_reset, + .compress = mppe_compress, + .comp_stat = mppe_comp_stats, + .decomp_alloc = mppe_alloc, + .decomp_free = mppe_free, + .decomp_init = mppe_decomp_init, + .decomp_reset = mppe_decomp_reset, + .decompress = mppe_decompress, + .incomp = mppe_incomp, + .decomp_stat = mppe_comp_stats, + .owner = THIS_MODULE, + .comp_extra = MPPE_PAD, +}; + +/* + * ppp_mppe_init() + * + * Prior to allowing load, try to load the arc4 and sha1 crypto + * libraries. The actual use will be allocated later, but + * this way the module will fail to insmod if they aren't available. + */ + +static int __init ppp_mppe_init(void) +{ + int answer; + if (!(crypto_alg_available("arc4", 0) && + crypto_alg_available("sha1", 0))) + return -ENODEV; + + sha_pad = kmalloc(sizeof(struct sha_pad), GFP_KERNEL); + if (!sha_pad) + return -ENOMEM; + sha_pad_init(sha_pad); + + answer = ppp_register_compressor(&ppp_mppe); + + if (answer == 0) + printk(KERN_INFO "PPP MPPE Compression module registered\n"); + else + kfree(sha_pad); + + return answer; +} + +static void __exit ppp_mppe_cleanup(void) +{ + ppp_unregister_compressor(&ppp_mppe); + kfree(sha_pad); +} + +module_init(ppp_mppe_init); +module_exit(ppp_mppe_cleanup); diff --git a/drivers/net/ppp_mppe.h b/drivers/net/ppp_mppe.h new file mode 100644 index 000000000000..7a14e058c668 --- /dev/null +++ b/drivers/net/ppp_mppe.h @@ -0,0 +1,86 @@ +#define MPPE_PAD 4 /* MPPE growth per frame */ +#define MPPE_MAX_KEY_LEN 16 /* largest key length (128-bit) */ + +/* option bits for ccp_options.mppe */ +#define MPPE_OPT_40 0x01 /* 40 bit */ +#define MPPE_OPT_128 0x02 /* 128 bit */ +#define MPPE_OPT_STATEFUL 0x04 /* stateful mode */ +/* unsupported opts */ +#define MPPE_OPT_56 0x08 /* 56 bit */ +#define MPPE_OPT_MPPC 0x10 /* MPPC compression */ +#define MPPE_OPT_D 0x20 /* Unknown */ +#define MPPE_OPT_UNSUPPORTED (MPPE_OPT_56|MPPE_OPT_MPPC|MPPE_OPT_D) +#define MPPE_OPT_UNKNOWN 0x40 /* Bits !defined in RFC 3078 were set */ + +/* + * This is not nice ... the alternative is a bitfield struct though. + * And unfortunately, we cannot share the same bits for the option + * names above since C and H are the same bit. We could do a u_int32 + * but then we have to do a htonl() all the time and/or we still need + * to know which octet is which. + */ +#define MPPE_C_BIT 0x01 /* MPPC */ +#define MPPE_D_BIT 0x10 /* Obsolete, usage unknown */ +#define MPPE_L_BIT 0x20 /* 40-bit */ +#define MPPE_S_BIT 0x40 /* 128-bit */ +#define MPPE_M_BIT 0x80 /* 56-bit, not supported */ +#define MPPE_H_BIT 0x01 /* Stateless (in a different byte) */ + +/* Does not include H bit; used for least significant octet only. */ +#define MPPE_ALL_BITS (MPPE_D_BIT|MPPE_L_BIT|MPPE_S_BIT|MPPE_M_BIT|MPPE_H_BIT) + +/* Build a CI from mppe opts (see RFC 3078) */ +#define MPPE_OPTS_TO_CI(opts, ci) \ + do { \ + u_char *ptr = ci; /* u_char[4] */ \ + \ + /* H bit */ \ + if (opts & MPPE_OPT_STATEFUL) \ + *ptr++ = 0x0; \ + else \ + *ptr++ = MPPE_H_BIT; \ + *ptr++ = 0; \ + *ptr++ = 0; \ + \ + /* S,L bits */ \ + *ptr = 0; \ + if (opts & MPPE_OPT_128) \ + *ptr |= MPPE_S_BIT; \ + if (opts & MPPE_OPT_40) \ + *ptr |= MPPE_L_BIT; \ + /* M,D,C bits not supported */ \ + } while (/* CONSTCOND */ 0) + +/* The reverse of the above */ +#define MPPE_CI_TO_OPTS(ci, opts) \ + do { \ + u_char *ptr = ci; /* u_char[4] */ \ + \ + opts = 0; \ + \ + /* H bit */ \ + if (!(ptr[0] & MPPE_H_BIT)) \ + opts |= MPPE_OPT_STATEFUL; \ + \ + /* S,L bits */ \ + if (ptr[3] & MPPE_S_BIT) \ + opts |= MPPE_OPT_128; \ + if (ptr[3] & MPPE_L_BIT) \ + opts |= MPPE_OPT_40; \ + \ + /* M,D,C bits */ \ + if (ptr[3] & MPPE_M_BIT) \ + opts |= MPPE_OPT_56; \ + if (ptr[3] & MPPE_D_BIT) \ + opts |= MPPE_OPT_D; \ + if (ptr[3] & MPPE_C_BIT) \ + opts |= MPPE_OPT_MPPC; \ + \ + /* Other bits */ \ + if (ptr[0] & ~MPPE_H_BIT) \ + opts |= MPPE_OPT_UNKNOWN; \ + if (ptr[1] || ptr[2]) \ + opts |= MPPE_OPT_UNKNOWN; \ + if (ptr[3] & ~MPPE_ALL_BITS) \ + opts |= MPPE_OPT_UNKNOWN; \ + } while (/* CONSTCOND */ 0) diff --git a/include/linux/if_ppp.h b/include/linux/if_ppp.h index 572aff7daa21..768372f07caa 100644 --- a/include/linux/if_ppp.h +++ b/include/linux/if_ppp.h @@ -21,7 +21,7 @@ */ /* - * ==FILEVERSION 20000724== + * ==FILEVERSION 20050812== * * NOTE TO MAINTAINERS: * If you modify this file at all, please set the above date. @@ -35,6 +35,8 @@ #ifndef _IF_PPP_H_ #define _IF_PPP_H_ +#include + /* * Packet sizes */ @@ -70,7 +72,8 @@ #define SC_LOG_RAWIN 0x00080000 /* log all chars received */ #define SC_LOG_FLUSH 0x00100000 /* log all chars flushed */ #define SC_SYNC 0x00200000 /* synchronous serial mode */ -#define SC_MASK 0x0f200fff /* bits that user can change */ +#define SC_MUST_COMP 0x00400000 /* no uncompressed packets may be sent or received */ +#define SC_MASK 0x0f600fff /* bits that user can change */ /* state bits */ #define SC_XMIT_BUSY 0x10000000 /* (used by isdn_ppp?) */ diff --git a/include/linux/ppp-comp.h b/include/linux/ppp-comp.h index 7227e653b3be..e86a7a5cf355 100644 --- a/include/linux/ppp-comp.h +++ b/include/linux/ppp-comp.h @@ -111,6 +111,8 @@ struct compressor { /* Used in locking compressor modules */ struct module *owner; + /* Extra skb space needed by the compressor algorithm */ + unsigned int comp_extra; }; /* @@ -190,6 +192,13 @@ struct compressor { #define DEFLATE_MAKE_OPT(w) ((((w) - 8) << 4) + DEFLATE_METHOD_VAL) #define DEFLATE_CHK_SEQUENCE 0 +/* + * Definitions for MPPE. + */ + +#define CI_MPPE 18 /* config option for MPPE */ +#define CILEN_MPPE 6 /* length of config option */ + /* * Definitions for other, as yet unsupported, compression methods. */ -- cgit v1.2.3 From 330d57fb98a916fa8e1363846540dd420e99499a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 4 Nov 2005 10:18:40 +0000 Subject: [PATCH] Fix sysctl unregistration oops (CVE-2005-2709) You could open the /proc/sys/net/ipv4/conf// file, then wait for interface to go away, try to grab as much memory as possible in hope to hit the (kfreed) ctl_table. Then fill it with pointers to your function. Then do read from file you've opened and if you are lucky, you'll get it called as ->proc_handler() in kernel mode. So this is at least an Oops and possibly more. It does depend on an interface going away though, so less of a security risk than it would otherwise be. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Linus Torvalds --- arch/s390/appldata/appldata_base.c | 7 +- include/linux/proc_fs.h | 1 + include/linux/sysctl.h | 3 + kernel/sysctl.c | 136 +++++++++++++++++++++++++++++-------- 4 files changed, 116 insertions(+), 31 deletions(-) (limited to 'include/linux') diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index c9f2f60cfa58..dee6ab54984d 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c @@ -592,12 +592,15 @@ int appldata_register_ops(struct appldata_ops *ops) */ void appldata_unregister_ops(struct appldata_ops *ops) { + void *table; spin_lock(&appldata_ops_lock); - unregister_sysctl_table(ops->sysctl_header); list_del(&ops->list); - kfree(ops->ctl_table); + /* at that point any incoming access will fail */ + table = ops->ctl_table; ops->ctl_table = NULL; spin_unlock(&appldata_ops_lock); + unregister_sysctl_table(ops->sysctl_header); + kfree(table); P_INFO("%s-ops unregistered!\n", ops->name); } /********************** module-ops management **************************/ diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h index 65ceeaa30652..74488e49166d 100644 --- a/include/linux/proc_fs.h +++ b/include/linux/proc_fs.h @@ -66,6 +66,7 @@ struct proc_dir_entry { write_proc_t *write_proc; atomic_t count; /* use count */ int deleted; /* delete flag */ + void *set; }; struct kcore_list { diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h index fc8e367f671e..fc131d6602b9 100644 --- a/include/linux/sysctl.h +++ b/include/linux/sysctl.h @@ -24,6 +24,7 @@ #include struct file; +struct completion; #define CTL_MAXNAME 10 /* how many path components do we allow in a call to sysctl? In other words, what is @@ -925,6 +926,8 @@ struct ctl_table_header { ctl_table *ctl_table; struct list_head ctl_entry; + int used; + struct completion *unregistering; }; struct ctl_table_header * register_sysctl_table(ctl_table * table, diff --git a/kernel/sysctl.c b/kernel/sysctl.c index c4f35f96884d..9990e10192e8 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -169,7 +169,7 @@ struct file_operations proc_sys_file_operations = { extern struct proc_dir_entry *proc_sys_root; -static void register_proc_table(ctl_table *, struct proc_dir_entry *); +static void register_proc_table(ctl_table *, struct proc_dir_entry *, void *); static void unregister_proc_table(ctl_table *, struct proc_dir_entry *); #endif @@ -992,10 +992,51 @@ static ctl_table dev_table[] = { extern void init_irq_proc (void); +static DEFINE_SPINLOCK(sysctl_lock); + +/* called under sysctl_lock */ +static int use_table(struct ctl_table_header *p) +{ + if (unlikely(p->unregistering)) + return 0; + p->used++; + return 1; +} + +/* called under sysctl_lock */ +static void unuse_table(struct ctl_table_header *p) +{ + if (!--p->used) + if (unlikely(p->unregistering)) + complete(p->unregistering); +} + +/* called under sysctl_lock, will reacquire if has to wait */ +static void start_unregistering(struct ctl_table_header *p) +{ + /* + * if p->used is 0, nobody will ever touch that entry again; + * we'll eliminate all paths to it before dropping sysctl_lock + */ + if (unlikely(p->used)) { + struct completion wait; + init_completion(&wait); + p->unregistering = &wait; + spin_unlock(&sysctl_lock); + wait_for_completion(&wait); + spin_lock(&sysctl_lock); + } + /* + * do not remove from the list until nobody holds it; walking the + * list in do_sysctl() relies on that. + */ + list_del_init(&p->ctl_entry); +} + void __init sysctl_init(void) { #ifdef CONFIG_PROC_FS - register_proc_table(root_table, proc_sys_root); + register_proc_table(root_table, proc_sys_root, &root_table_header); init_irq_proc(); #endif } @@ -1004,6 +1045,7 @@ int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *ol void __user *newval, size_t newlen) { struct list_head *tmp; + int error = -ENOTDIR; if (nlen <= 0 || nlen >= CTL_MAXNAME) return -ENOTDIR; @@ -1012,20 +1054,30 @@ int do_sysctl(int __user *name, int nlen, void __user *oldval, size_t __user *ol if (!oldlenp || get_user(old_len, oldlenp)) return -EFAULT; } + spin_lock(&sysctl_lock); tmp = &root_table_header.ctl_entry; do { struct ctl_table_header *head = list_entry(tmp, struct ctl_table_header, ctl_entry); void *context = NULL; - int error = parse_table(name, nlen, oldval, oldlenp, + + if (!use_table(head)) + continue; + + spin_unlock(&sysctl_lock); + + error = parse_table(name, nlen, oldval, oldlenp, newval, newlen, head->ctl_table, &context); kfree(context); + + spin_lock(&sysctl_lock); + unuse_table(head); if (error != -ENOTDIR) - return error; - tmp = tmp->next; - } while (tmp != &root_table_header.ctl_entry); - return -ENOTDIR; + break; + } while ((tmp = tmp->next) != &root_table_header.ctl_entry); + spin_unlock(&sysctl_lock); + return error; } asmlinkage long sys_sysctl(struct __sysctl_args __user *args) @@ -1236,12 +1288,16 @@ struct ctl_table_header *register_sysctl_table(ctl_table * table, return NULL; tmp->ctl_table = table; INIT_LIST_HEAD(&tmp->ctl_entry); + tmp->used = 0; + tmp->unregistering = NULL; + spin_lock(&sysctl_lock); if (insert_at_head) list_add(&tmp->ctl_entry, &root_table_header.ctl_entry); else list_add_tail(&tmp->ctl_entry, &root_table_header.ctl_entry); + spin_unlock(&sysctl_lock); #ifdef CONFIG_PROC_FS - register_proc_table(table, proc_sys_root); + register_proc_table(table, proc_sys_root, tmp); #endif return tmp; } @@ -1255,10 +1311,13 @@ struct ctl_table_header *register_sysctl_table(ctl_table * table, */ void unregister_sysctl_table(struct ctl_table_header * header) { - list_del(&header->ctl_entry); + might_sleep(); + spin_lock(&sysctl_lock); + start_unregistering(header); #ifdef CONFIG_PROC_FS unregister_proc_table(header->ctl_table, proc_sys_root); #endif + spin_unlock(&sysctl_lock); kfree(header); } @@ -1269,7 +1328,7 @@ void unregister_sysctl_table(struct ctl_table_header * header) #ifdef CONFIG_PROC_FS /* Scan the sysctl entries in table and add them all into /proc */ -static void register_proc_table(ctl_table * table, struct proc_dir_entry *root) +static void register_proc_table(ctl_table * table, struct proc_dir_entry *root, void *set) { struct proc_dir_entry *de; int len; @@ -1305,13 +1364,14 @@ static void register_proc_table(ctl_table * table, struct proc_dir_entry *root) de = create_proc_entry(table->procname, mode, root); if (!de) continue; + de->set = set; de->data = (void *) table; if (table->proc_handler) de->proc_fops = &proc_sys_file_operations; } table->de = de; if (de->mode & S_IFDIR) - register_proc_table(table->child, de); + register_proc_table(table->child, de, set); } } @@ -1336,6 +1396,13 @@ static void unregister_proc_table(ctl_table * table, struct proc_dir_entry *root continue; } + /* + * In any case, mark the entry as goner; we'll keep it + * around if it's busy, but we'll know to do nothing with + * its fields. We are under sysctl_lock here. + */ + de->data = NULL; + /* Don't unregister proc entries that are still being used.. */ if (atomic_read(&de->count)) continue; @@ -1349,27 +1416,38 @@ static ssize_t do_rw_proc(int write, struct file * file, char __user * buf, size_t count, loff_t *ppos) { int op; - struct proc_dir_entry *de; + struct proc_dir_entry *de = PDE(file->f_dentry->d_inode); struct ctl_table *table; size_t res; - ssize_t error; - - de = PDE(file->f_dentry->d_inode); - if (!de || !de->data) - return -ENOTDIR; - table = (struct ctl_table *) de->data; - if (!table || !table->proc_handler) - return -ENOTDIR; - op = (write ? 002 : 004); - if (ctl_perm(table, op)) - return -EPERM; + ssize_t error = -ENOTDIR; - res = count; - - error = (*table->proc_handler) (table, write, file, buf, &res, ppos); - if (error) - return error; - return res; + spin_lock(&sysctl_lock); + if (de && de->data && use_table(de->set)) { + /* + * at that point we know that sysctl was not unregistered + * and won't be until we finish + */ + spin_unlock(&sysctl_lock); + table = (struct ctl_table *) de->data; + if (!table || !table->proc_handler) + goto out; + error = -EPERM; + op = (write ? 002 : 004); + if (ctl_perm(table, op)) + goto out; + + /* careful: calling conventions are nasty here */ + res = count; + error = (*table->proc_handler)(table, write, file, + buf, &res, ppos); + if (!error) + error = res; + out: + spin_lock(&sysctl_lock); + unuse_table(de->set); + } + spin_unlock(&sysctl_lock); + return error; } static int proc_opensys(struct inode *inode, struct file *file) -- cgit v1.2.3 From 90d45d17f3e68608ac7ba8fc3d7acce022a19c8e Mon Sep 17 00:00:00 2001 From: Ashok Raj Date: Tue, 8 Nov 2005 21:34:24 -0800 Subject: [PATCH] cpu hotplug: fix locking in cpufreq drivers When calling target drivers to set frequency, we take cpucontrol lock. When we modified the code to accomodate CPU hotplug, there was an attempt to take a double lock of cpucontrol leading to a deadlock. Since the current thread context is already holding the cpucontrol lock, we dont need to make another attempt to acquire it. Now we leave a trace in current->flags indicating current thread already is under cpucontrol lock held, so we dont attempt to do this another time. Thanks to Andrew Morton for the beating:-) From: Brice Goglin Build fix (akpm: this patch is still unpleasant. Ashok continues to look for a cleaner solution, doesn't he? ;)) Signed-off-by: Ashok Raj Signed-off-by: Brice Goglin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/cpufreq/cpufreq.c | 24 ++++++++++-------------- include/linux/cpu.h | 5 +++++ include/linux/sched.h | 1 + kernel/cpu.c | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 14 deletions(-) (limited to 'include/linux') diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 25acf478c9e8..23a63207d747 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -38,7 +38,6 @@ static struct cpufreq_driver *cpufreq_driver; static struct cpufreq_policy *cpufreq_cpu_data[NR_CPUS]; static DEFINE_SPINLOCK(cpufreq_driver_lock); - /* internal prototypes */ static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); static void handle_update(void *data); @@ -1115,24 +1114,21 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy, int retval = -EINVAL; /* - * Converted the lock_cpu_hotplug to preempt_disable() - * and preempt_enable(). This is a bit kludgy and relies on how cpu - * hotplug works. All we need is a guarantee that cpu hotplug won't make - * progress on any cpu. Once we do preempt_disable(), this would ensure - * that hotplug threads don't get onto this cpu, thereby delaying - * the cpu remove process. - * - * We removed the lock_cpu_hotplug since we need to call this function - * via cpu hotplug callbacks, which result in locking the cpu hotplug - * thread itself. Agree this is not very clean, cpufreq community - * could improve this if required. - Ashok Raj + * If we are already in context of hotplug thread, we dont need to + * acquire the hotplug lock. Otherwise acquire cpucontrol to prevent + * hotplug from removing this cpu that we are working on. */ - preempt_disable(); + if (!current_in_cpu_hotplug()) + lock_cpu_hotplug(); + dprintk("target for CPU %u: %u kHz, relation %u\n", policy->cpu, target_freq, relation); if (cpu_online(policy->cpu) && cpufreq_driver->target) retval = cpufreq_driver->target(policy, target_freq, relation); - preempt_enable(); + + if (!current_in_cpu_hotplug()) + unlock_cpu_hotplug(); + return retval; } EXPORT_SYMBOL_GPL(__cpufreq_driver_target); diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 1f7b2c097503..43c44530ef9d 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -42,6 +42,7 @@ struct notifier_block; /* Need to know about CPUs going up/down? */ extern int register_cpu_notifier(struct notifier_block *nb); extern void unregister_cpu_notifier(struct notifier_block *nb); +extern int current_in_cpu_hotplug(void); int cpu_up(unsigned int cpu); @@ -54,6 +55,10 @@ static inline int register_cpu_notifier(struct notifier_block *nb) static inline void unregister_cpu_notifier(struct notifier_block *nb) { } +static inline int current_in_cpu_hotplug(void) +{ + return 0; +} #endif /* CONFIG_SMP */ extern struct sysdev_class cpu_sysdev_class; diff --git a/include/linux/sched.h b/include/linux/sched.h index 03b68a7b4b82..2bbf968b23d9 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -909,6 +909,7 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0) #define PF_SYNCWRITE 0x00200000 /* I am doing a sync write */ #define PF_BORROWED_MM 0x00400000 /* I am a kthread doing use_mm */ #define PF_RANDOMIZE 0x00800000 /* randomize virtual address space */ +#define PF_HOTPLUG_CPU 0x01000000 /* Currently performing CPU hotplug */ /* * Only the _current_ task can read/write to tsk->flags, but other diff --git a/kernel/cpu.c b/kernel/cpu.c index 3619e939182e..d61ba88f34e5 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -21,6 +21,24 @@ EXPORT_SYMBOL_GPL(cpucontrol); static struct notifier_block *cpu_chain; +/* + * Used to check by callers if they need to acquire the cpucontrol + * or not to protect a cpu from being removed. Its sometimes required to + * call these functions both for normal operations, and in response to + * a cpu being added/removed. If the context of the call is in the same + * thread context as a CPU hotplug thread, we dont need to take the lock + * since its already protected + * check drivers/cpufreq/cpufreq.c for its usage - Ashok Raj + */ + +int current_in_cpu_hotplug(void) +{ + return (current->flags & PF_HOTPLUG_CPU); +} + +EXPORT_SYMBOL_GPL(current_in_cpu_hotplug); + + /* Need to know about CPUs going up/down? */ int register_cpu_notifier(struct notifier_block *nb) { @@ -94,6 +112,13 @@ int cpu_down(unsigned int cpu) goto out; } + /* + * Leave a trace in current->flags indicating we are already in + * process of performing CPU hotplug. Callers can check if cpucontrol + * is already acquired by current thread, and if so not cause + * a dead lock by not acquiring the lock + */ + current->flags |= PF_HOTPLUG_CPU; err = notifier_call_chain(&cpu_chain, CPU_DOWN_PREPARE, (void *)(long)cpu); if (err == NOTIFY_BAD) { @@ -146,6 +171,7 @@ out_thread: out_allowed: set_cpus_allowed(current, old_allowed); out: + current->flags &= ~PF_HOTPLUG_CPU; unlock_cpu_hotplug(); return err; } @@ -163,6 +189,12 @@ int __devinit cpu_up(unsigned int cpu) ret = -EINVAL; goto out; } + + /* + * Leave a trace in current->flags indicating we are already in + * process of performing CPU hotplug. + */ + current->flags |= PF_HOTPLUG_CPU; ret = notifier_call_chain(&cpu_chain, CPU_UP_PREPARE, hcpu); if (ret == NOTIFY_BAD) { printk("%s: attempt to bring up CPU %u failed\n", @@ -185,6 +217,7 @@ out_notify: if (ret != 0) notifier_call_chain(&cpu_chain, CPU_UP_CANCELED, hcpu); out: + current->flags &= ~PF_HOTPLUG_CPU; up(&cpucontrol); return ret; } -- cgit v1.2.3 From 733482e445ca4450cf41381b1c95e2b8c7145114 Mon Sep 17 00:00:00 2001 From: Olaf Hering Date: Tue, 8 Nov 2005 21:34:55 -0800 Subject: [PATCH] changing CONFIG_LOCALVERSION rebuilds too much, for no good reason This patch removes almost all inclusions of linux/version.h. The 3 #defines are unused in most of the touched files. A few drivers use the simple KERNEL_VERSION(a,b,c) macro, which is unfortunatly in linux/version.h. There are also lots of #ifdef for long obsolete kernels, this was not touched. In a few places, the linux/version.h include was move to where the LINUX_VERSION_CODE was used. quilt vi `find * -type f -name "*.[ch]"|xargs grep -El '(UTS_RELEASE|LINUX_VERSION_CODE|KERNEL_VERSION|linux/version.h)'|grep -Ev '(/(boot|coda|drm)/|~$)'` search pattern: /UTS_RELEASE\|LINUX_VERSION_CODE\|KERNEL_VERSION\|linux\/\(utsname\|version\).h Signed-off-by: Olaf Hering Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm/mach-omap1/leds-h2p2-debug.c | 1 - arch/arm/plat-omap/ocpi.c | 1 - arch/cris/arch-v10/drivers/pcf8563.c | 1 - arch/cris/arch-v10/kernel/fasttimer.c | 1 - arch/cris/arch-v32/drivers/nandflash.c | 1 - arch/cris/arch-v32/drivers/pcf8563.c | 1 - arch/mips/tx4938/toshiba_rbtx4938/irq.c | 1 - arch/parisc/kernel/asm-offsets.c | 1 - arch/ppc/syslib/prom.c | 1 - arch/ppc/syslib/prom_init.c | 1 - drivers/block/amiflop.c | 1 - drivers/char/ip2.c | 1 - drivers/char/mwave/tp3780i.c | 1 - drivers/char/mxser.c | 1 - drivers/char/specialix.c | 1 - drivers/char/tpm/tpm.h | 1 - drivers/char/viocons.c | 1 - drivers/char/viotape.c | 1 - drivers/firmware/dell_rbu.c | 1 - drivers/infiniband/ulp/srp/ib_srp.c | 1 - drivers/isdn/divert/divert_init.c | 1 - drivers/isdn/divert/divert_procfs.c | 1 - drivers/isdn/divert/isdn_divert.c | 1 - drivers/isdn/hisax/hisax_fcpcipnp.c | 1 - drivers/isdn/hisax/st5481_init.c | 1 - drivers/isdn/hysdn/hycapi.c | 1 - drivers/isdn/hysdn/hysdn_init.c | 1 - drivers/isdn/hysdn/hysdn_net.c | 1 - drivers/isdn/hysdn/hysdn_procconf.c | 1 - drivers/isdn/hysdn/hysdn_proclog.c | 1 - drivers/isdn/i4l/isdn_common.c | 1 - drivers/isdn/icn/icn.h | 1 - drivers/isdn/isdnloop/isdnloop.h | 1 - drivers/isdn/sc/includes.h | 1 - drivers/md/bitmap.c | 1 - drivers/media/video/arv.c | 1 - drivers/media/video/zr36016.c | 1 - drivers/media/video/zr36050.c | 1 - drivers/media/video/zr36060.c | 1 - drivers/message/fusion/mptbase.c | 1 - drivers/message/fusion/mptbase.h | 1 - drivers/message/fusion/mptctl.c | 1 - drivers/message/fusion/mptctl.h | 1 - drivers/message/fusion/mptlan.h | 1 - drivers/misc/hdpuftrs/hdpu_cpustate.c | 1 - drivers/misc/hdpuftrs/hdpu_nexus.c | 1 - drivers/misc/ibmasm/ibmasm.h | 1 - drivers/mtd/chips/cfi_cmdset_0020.c | 1 - drivers/mtd/devices/pmc551.c | 1 - drivers/mtd/maps/ebony.c | 1 - drivers/mtd/maps/ocotea.c | 1 - drivers/mtd/maps/walnut.c | 1 - drivers/mtd/nand/au1550nd.c | 1 + drivers/mtd/nand/autcpu12.c | 1 - drivers/net/b44.c | 1 - drivers/net/cassini.c | 1 - drivers/net/dm9000.c | 1 - drivers/net/fs_enet/fs_enet.h | 1 - drivers/net/gianfar.c | 1 - drivers/net/gianfar.h | 1 - drivers/net/gianfar_ethtool.c | 1 - drivers/net/gianfar_mii.c | 1 - drivers/net/hp100.c | 1 - drivers/net/ibmveth.c | 1 - drivers/net/iseries_veth.c | 1 - drivers/net/mac8390.c | 1 - drivers/net/mv643xx_eth.h | 1 - drivers/net/s2io.c | 1 - drivers/net/sk98lin/h/skdrv1st.h | 3 --- drivers/net/sk_mca.c | 1 - drivers/net/sk_mca.h | 2 -- drivers/net/starfire.c | 1 - drivers/net/via-velocity.c | 1 - drivers/net/wireless/hostap/hostap.c | 1 - drivers/net/wireless/hostap/hostap_hw.c | 1 - drivers/net/wireless/hostap/hostap_pci.c | 1 - drivers/net/wireless/hostap/hostap_plx.c | 1 - drivers/net/wireless/ipw2100.h | 1 - drivers/net/wireless/ipw2200.c | 1 + drivers/net/wireless/ipw2200.h | 1 - drivers/net/wireless/orinoco.h | 1 - drivers/net/wireless/prism54/isl_38xx.c | 1 - drivers/net/wireless/prism54/isl_38xx.h | 1 - drivers/net/wireless/prism54/isl_ioctl.c | 1 - drivers/net/wireless/prism54/islpci_dev.c | 1 - drivers/net/wireless/prism54/islpci_dev.h | 1 - drivers/net/wireless/prism54/islpci_eth.c | 1 - drivers/net/wireless/prism54/islpci_hotplug.c | 1 - drivers/pcmcia/au1000_pb1x00.c | 1 - drivers/pcmcia/au1000_xxs1500.c | 1 - drivers/s390/crypto/z90main.c | 1 - drivers/s390/net/claw.c | 1 - drivers/scsi/3w-xxxx.h | 1 - drivers/scsi/a2091.c | 1 - drivers/scsi/aic7xxx/aic79xx_osm.h | 1 - drivers/scsi/aic7xxx/aic7xxx_osm.h | 1 - drivers/scsi/amiga7xx.c | 1 - drivers/scsi/bvme6000.c | 1 - drivers/scsi/gvp11.c | 1 - drivers/scsi/ibmmca.c | 6 ------ drivers/scsi/ips.h | 1 + drivers/scsi/megaraid/mega_common.h | 1 - drivers/scsi/megaraid/megaraid_mm.h | 1 - drivers/scsi/megaraid/megaraid_sas.c | 1 - drivers/scsi/mvme147.c | 1 - drivers/scsi/mvme16x.c | 1 - drivers/scsi/nsp32.h | 1 + drivers/scsi/pci2000.h | 3 --- drivers/scsi/scsi_debug.c | 4 ---- drivers/scsi/sg.c | 4 ---- drivers/scsi/sgiwd93.c | 1 - drivers/scsi/wd33c93.c | 1 - drivers/telephony/ixj.h | 1 - drivers/usb/gadget/dummy_hcd.c | 1 - drivers/usb/gadget/lh7a40x_udc.h | 1 - drivers/usb/gadget/pxa2xx_udc.c | 1 - drivers/usb/gadget/rndis.c | 1 - drivers/usb/host/hc_crisv10.c | 1 - drivers/usb/media/pwc/pwc-if.c | 1 + drivers/usb/media/pwc/pwc.h | 2 -- drivers/usb/media/w9968cf.c | 1 - drivers/usb/misc/sisusbvga/sisusb.c | 1 - drivers/usb/misc/sisusbvga/sisusb.h | 1 + drivers/usb/misc/sisusbvga/sisusb_con.c | 1 - drivers/usb/misc/sisusbvga/sisusb_init.c | 1 - drivers/video/backlight/backlight.c | 1 - drivers/video/backlight/lcd.c | 1 - drivers/video/intelfb/intelfbdrv.c | 1 - drivers/video/intelfb/intelfbhw.c | 1 - fs/9p/vfs_file.c | 1 - fs/adfs/adfs.h | 1 - fs/hfs/hfs_fs.h | 1 - fs/hfs/inode.c | 1 - fs/hfsplus/bnode.c | 1 - fs/hfsplus/dir.c | 1 - fs/hfsplus/extents.c | 1 - fs/hfsplus/hfsplus_fs.h | 1 - fs/hfsplus/inode.c | 1 - fs/hfsplus/super.c | 1 - fs/hfsplus/wrapper.c | 1 - fs/hostfs/hostfs_kern.c | 1 - fs/xfs/linux-2.6/xfs_linux.h | 1 - fs/xfs/xfs.h | 7 ------- fs/xfs/xfs_dmapi.h | 1 + include/linux/fs_enet_pd.h | 1 - include/linux/if_wanpipe_common.h | 2 -- include/linux/istallion.h | 2 -- include/linux/mtd/cfi.h | 1 - include/linux/mtd/mtd.h | 1 - include/linux/phonedev.h | 1 - include/linux/stallion.h | 2 -- sound/oss/msnd.c | 1 - sound/oss/os.h | 2 -- sound/oss/rme96xx.c | 1 - sound/oss/sh_dac_audio.c | 1 - sound/ppc/pmac.h | 1 - 156 files changed, 7 insertions(+), 176 deletions(-) (limited to 'include/linux') diff --git a/arch/arm/mach-omap1/leds-h2p2-debug.c b/arch/arm/mach-omap1/leds-h2p2-debug.c index be283cda63dd..399010c14036 100644 --- a/arch/arm/mach-omap1/leds-h2p2-debug.c +++ b/arch/arm/mach-omap1/leds-h2p2-debug.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include diff --git a/arch/arm/plat-omap/ocpi.c b/arch/arm/plat-omap/ocpi.c index 1fb16f9edfd5..2ede2ee8cae4 100644 --- a/arch/arm/plat-omap/ocpi.c +++ b/arch/arm/plat-omap/ocpi.c @@ -25,7 +25,6 @@ #include #include -#include #include #include #include diff --git a/arch/cris/arch-v10/drivers/pcf8563.c b/arch/cris/arch-v10/drivers/pcf8563.c index 201f4c90d961..f2c55742e90c 100644 --- a/arch/cris/arch-v10/drivers/pcf8563.c +++ b/arch/cris/arch-v10/drivers/pcf8563.c @@ -19,7 +19,6 @@ */ #include -#include #include #include #include diff --git a/arch/cris/arch-v10/kernel/fasttimer.c b/arch/cris/arch-v10/kernel/fasttimer.c index 094ff45ae85b..cac05a5e514c 100644 --- a/arch/cris/arch-v10/kernel/fasttimer.c +++ b/arch/cris/arch-v10/kernel/fasttimer.c @@ -112,7 +112,6 @@ #include #include -#include #include #include diff --git a/arch/cris/arch-v32/drivers/nandflash.c b/arch/cris/arch-v32/drivers/nandflash.c index fc2a619b035d..93ddea4d9564 100644 --- a/arch/cris/arch-v32/drivers/nandflash.c +++ b/arch/cris/arch-v32/drivers/nandflash.c @@ -14,7 +14,6 @@ * */ -#include #include #include #include diff --git a/arch/cris/arch-v32/drivers/pcf8563.c b/arch/cris/arch-v32/drivers/pcf8563.c index f894580b648b..d788bda3578c 100644 --- a/arch/cris/arch-v32/drivers/pcf8563.c +++ b/arch/cris/arch-v32/drivers/pcf8563.c @@ -18,7 +18,6 @@ */ #include -#include #include #include #include diff --git a/arch/mips/tx4938/toshiba_rbtx4938/irq.c b/arch/mips/tx4938/toshiba_rbtx4938/irq.c index 230f5a93c2e6..9cd9c0fe2265 100644 --- a/arch/mips/tx4938/toshiba_rbtx4938/irq.c +++ b/arch/mips/tx4938/toshiba_rbtx4938/irq.c @@ -84,7 +84,6 @@ IRQ Device #include #include #include -#include #include #include diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c index 1ad44f92d6e4..e23c4e1e3a25 100644 --- a/arch/parisc/kernel/asm-offsets.c +++ b/arch/parisc/kernel/asm-offsets.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include diff --git a/arch/ppc/syslib/prom.c b/arch/ppc/syslib/prom.c index 03b1fc9b9501..af4deace49e0 100644 --- a/arch/ppc/syslib/prom.c +++ b/arch/ppc/syslib/prom.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include diff --git a/arch/ppc/syslib/prom_init.c b/arch/ppc/syslib/prom_init.c index 7f15136830f4..df14422ae1c6 100644 --- a/arch/ppc/syslib/prom_init.c +++ b/arch/ppc/syslib/prom_init.c @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 1468e8cf712d..0acbfff8ad28 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c @@ -1816,7 +1816,6 @@ out_blkdev: } #ifdef MODULE -#include int init_module(void) { diff --git a/drivers/char/ip2.c b/drivers/char/ip2.c index 6cd12f23aa58..7cadfc6ef352 100644 --- a/drivers/char/ip2.c +++ b/drivers/char/ip2.c @@ -7,7 +7,6 @@ // #include -#include #include #include diff --git a/drivers/char/mwave/tp3780i.c b/drivers/char/mwave/tp3780i.c index d6c72e0934e2..cc3e54dd7234 100644 --- a/drivers/char/mwave/tp3780i.c +++ b/drivers/char/mwave/tp3780i.c @@ -46,7 +46,6 @@ * First release to the public */ -#include #include #include #include diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index 3b965a651da4..26448f176803 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c @@ -38,7 +38,6 @@ #include #include -#include #include #include #include diff --git a/drivers/char/specialix.c b/drivers/char/specialix.c index 352547eabf7b..0bbfce43031c 100644 --- a/drivers/char/specialix.c +++ b/drivers/char/specialix.c @@ -90,7 +90,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 99a60496ecc6..9293bcc4dc62 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -19,7 +19,6 @@ * */ #include -#include #include #include #include diff --git a/drivers/char/viocons.c b/drivers/char/viocons.c index 98601c7d04a9..4d75c261f98a 100644 --- a/drivers/char/viocons.c +++ b/drivers/char/viocons.c @@ -26,7 +26,6 @@ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include -#include #include #include #include diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c index 867cc4e418c7..60aabdb4a046 100644 --- a/drivers/char/viotape.c +++ b/drivers/char/viotape.c @@ -32,7 +32,6 @@ * iseries/vio.h */ #include -#include #include #include #include diff --git a/drivers/firmware/dell_rbu.c b/drivers/firmware/dell_rbu.c index ba17292eb290..6d83299e7c9b 100644 --- a/drivers/firmware/dell_rbu.c +++ b/drivers/firmware/dell_rbu.c @@ -34,7 +34,6 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ -#include #include #include #include diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 2687e34aa5bc..321a3a10e69b 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -32,7 +32,6 @@ * $Id: ib_srp.c 3932 2005-11-01 17:19:29Z roland $ */ -#include #include #include #include diff --git a/drivers/isdn/divert/divert_init.c b/drivers/isdn/divert/divert_init.c index 434e684f5dbb..2f7c9fc2e898 100644 --- a/drivers/isdn/divert/divert_init.c +++ b/drivers/isdn/divert/divert_init.c @@ -10,7 +10,6 @@ */ #include -#include #include #include diff --git a/drivers/isdn/divert/divert_procfs.c b/drivers/isdn/divert/divert_procfs.c index 0b0ea26023e5..1b37d86d5ee1 100644 --- a/drivers/isdn/divert/divert_procfs.c +++ b/drivers/isdn/divert/divert_procfs.c @@ -11,7 +11,6 @@ #include #include -#include #include #include #ifdef CONFIG_PROC_FS diff --git a/drivers/isdn/divert/isdn_divert.c b/drivers/isdn/divert/isdn_divert.c index 0bfd698726a6..f1a1f9a9b88e 100644 --- a/drivers/isdn/divert/isdn_divert.c +++ b/drivers/isdn/divert/isdn_divert.c @@ -9,7 +9,6 @@ * */ -#include #include #include "isdn_divert.h" diff --git a/drivers/isdn/hisax/hisax_fcpcipnp.c b/drivers/isdn/hisax/hisax_fcpcipnp.c index b4d795d40154..dc7ef957e897 100644 --- a/drivers/isdn/hisax/hisax_fcpcipnp.c +++ b/drivers/isdn/hisax/hisax_fcpcipnp.c @@ -23,7 +23,6 @@ * o tx_skb at PH_DEACTIVATE time */ -#include #include #include #include diff --git a/drivers/isdn/hisax/st5481_init.c b/drivers/isdn/hisax/st5481_init.c index 2cf5d1a6df6c..8e192a3a3490 100644 --- a/drivers/isdn/hisax/st5481_init.c +++ b/drivers/isdn/hisax/st5481_init.c @@ -25,7 +25,6 @@ */ #include -#include #include #include #include diff --git a/drivers/isdn/hysdn/hycapi.c b/drivers/isdn/hysdn/hycapi.c index 1fd3d4e5f284..acc1d3cceebb 100644 --- a/drivers/isdn/hysdn/hycapi.c +++ b/drivers/isdn/hysdn/hycapi.c @@ -11,7 +11,6 @@ */ #include -#include #include #include #include diff --git a/drivers/isdn/hysdn/hysdn_init.c b/drivers/isdn/hysdn/hysdn_init.c index 12c8137b5161..cb791f8e793a 100644 --- a/drivers/isdn/hysdn/hysdn_init.c +++ b/drivers/isdn/hysdn/hysdn_init.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/isdn/hysdn/hysdn_net.c b/drivers/isdn/hysdn/hysdn_net.c index babec8157ae6..aa01628d74c6 100644 --- a/drivers/isdn/hysdn/hysdn_net.c +++ b/drivers/isdn/hysdn/hysdn_net.c @@ -14,7 +14,6 @@ */ #include -#include #include #include #include diff --git a/drivers/isdn/hysdn/hysdn_procconf.c b/drivers/isdn/hysdn/hysdn_procconf.c index 87f59a0e2a95..40e56143c768 100644 --- a/drivers/isdn/hysdn/hysdn_procconf.c +++ b/drivers/isdn/hysdn/hysdn_procconf.c @@ -12,7 +12,6 @@ */ #include -#include #include #include #include diff --git a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c index 4d57011c5737..6c26f1efabd5 100644 --- a/drivers/isdn/hysdn/hysdn_proclog.c +++ b/drivers/isdn/hysdn/hysdn_proclog.c @@ -11,7 +11,6 @@ */ #include -#include #include #include #include diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index 8a7d54a5c97d..4643df097bfe 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/isdn/icn/icn.h b/drivers/isdn/icn/icn.h index 9028cc3b5071..7d7245fb0b32 100644 --- a/drivers/isdn/icn/icn.h +++ b/drivers/isdn/icn/icn.h @@ -35,7 +35,6 @@ typedef struct icn_cdef { #ifdef __KERNEL__ /* Kernel includes */ -#include #include #include #include diff --git a/drivers/isdn/isdnloop/isdnloop.h b/drivers/isdn/isdnloop/isdnloop.h index 8fb7bc1bfe0f..d699fe53e1c3 100644 --- a/drivers/isdn/isdnloop/isdnloop.h +++ b/drivers/isdn/isdnloop/isdnloop.h @@ -33,7 +33,6 @@ typedef struct isdnloop_sdef { #ifdef __KERNEL__ /* Kernel includes */ -#include #include #include #include diff --git a/drivers/isdn/sc/includes.h b/drivers/isdn/sc/includes.h index 4611da6e9231..5286e0c810a9 100644 --- a/drivers/isdn/sc/includes.h +++ b/drivers/isdn/sc/includes.h @@ -4,7 +4,6 @@ * */ -#include #include #include #include diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 01654fcabc52..e59694bc5758 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -21,7 +21,6 @@ */ #include -#include #include #include #include diff --git a/drivers/media/video/arv.c b/drivers/media/video/arv.c index 0823ddaf7004..881cdcb1875d 100644 --- a/drivers/media/video/arv.c +++ b/drivers/media/video/arv.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/media/video/zr36016.c b/drivers/media/video/zr36016.c index d4740a89cea1..4ed898585c70 100644 --- a/drivers/media/video/zr36016.c +++ b/drivers/media/video/zr36016.c @@ -26,7 +26,6 @@ #define ZR016_VERSION "v0.7" -#include #include #include #include diff --git a/drivers/media/video/zr36050.c b/drivers/media/video/zr36050.c index 13b1e7b6fd6e..0144576a6123 100644 --- a/drivers/media/video/zr36050.c +++ b/drivers/media/video/zr36050.c @@ -26,7 +26,6 @@ #define ZR050_VERSION "v0.7.1" -#include #include #include #include diff --git a/drivers/media/video/zr36060.c b/drivers/media/video/zr36060.c index b50dc403e6db..129744a07abd 100644 --- a/drivers/media/video/zr36060.c +++ b/drivers/media/video/zr36060.c @@ -26,7 +26,6 @@ #define ZR060_VERSION "v0.7" -#include #include #include #include diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 790a2932ded9..65c2ec5c421b 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -47,7 +47,6 @@ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ #include -#include #include #include #include diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index e7efeb7740b9..5f5b3fb5b4d7 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -49,7 +49,6 @@ #define MPTBASE_H_INCLUDED /*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#include #include #include #include diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index cb2d59d5f5af..602138f8544d 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -45,7 +45,6 @@ */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#include #include #include #include diff --git a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h index 28754a9cb803..518996e03481 100644 --- a/drivers/message/fusion/mptctl.h +++ b/drivers/message/fusion/mptctl.h @@ -49,7 +49,6 @@ #define MPTCTL_H_INCLUDED /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -#include "linux/version.h" /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ diff --git a/drivers/message/fusion/mptlan.h b/drivers/message/fusion/mptlan.h index 750e343eb981..3726ecba5707 100644 --- a/drivers/message/fusion/mptlan.h +++ b/drivers/message/fusion/mptlan.h @@ -66,7 +66,6 @@ #include #include #include -#include #include #include // #include diff --git a/drivers/misc/hdpuftrs/hdpu_cpustate.c b/drivers/misc/hdpuftrs/hdpu_cpustate.c index 9c4dd682ac74..bc2b72b32905 100644 --- a/drivers/misc/hdpuftrs/hdpu_cpustate.c +++ b/drivers/misc/hdpuftrs/hdpu_cpustate.c @@ -14,7 +14,6 @@ * */ -#include #include #include #include diff --git a/drivers/misc/hdpuftrs/hdpu_nexus.c b/drivers/misc/hdpuftrs/hdpu_nexus.c index 165f3405df27..4bb461793851 100644 --- a/drivers/misc/hdpuftrs/hdpu_nexus.c +++ b/drivers/misc/hdpuftrs/hdpu_nexus.c @@ -14,7 +14,6 @@ * */ -#include #include #include #include diff --git a/drivers/misc/ibmasm/ibmasm.h b/drivers/misc/ibmasm/ibmasm.h index ecce4ffd3e23..d7e20a34f88d 100644 --- a/drivers/misc/ibmasm/ibmasm.h +++ b/drivers/misc/ibmasm/ibmasm.h @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c index c4a19d2dc67f..0807c1c91e55 100644 --- a/drivers/mtd/chips/cfi_cmdset_0020.c +++ b/drivers/mtd/chips/cfi_cmdset_0020.c @@ -20,7 +20,6 @@ * - Plugged memory leak in cfi_staa_writev(). */ -#include #include #include #include diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c index de48b35f5609..666cce1bf60c 100644 --- a/drivers/mtd/devices/pmc551.c +++ b/drivers/mtd/devices/pmc551.c @@ -82,7 +82,6 @@ * * Comb the init routine. It's still a bit cludgy on a few things. */ -#include #include #include #include diff --git a/drivers/mtd/maps/ebony.c b/drivers/mtd/maps/ebony.c index c0daf58357ca..60a6e51d662f 100644 --- a/drivers/mtd/maps/ebony.c +++ b/drivers/mtd/maps/ebony.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/mtd/maps/ocotea.c b/drivers/mtd/maps/ocotea.c index 6e559bc14636..c223514ca2eb 100644 --- a/drivers/mtd/maps/ocotea.c +++ b/drivers/mtd/maps/ocotea.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/mtd/maps/walnut.c b/drivers/mtd/maps/walnut.c index 5c17bca3a37e..f46bec66150f 100644 --- a/drivers/mtd/maps/walnut.c +++ b/drivers/mtd/maps/walnut.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 3cafcdf28aed..9c5945d6df88 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c @@ -17,6 +17,7 @@ #include #include #include +#include #include /* fixme: this is ugly */ diff --git a/drivers/mtd/nand/autcpu12.c b/drivers/mtd/nand/autcpu12.c index 056dfc17a075..a3c7fea404d0 100644 --- a/drivers/mtd/nand/autcpu12.c +++ b/drivers/mtd/nand/autcpu12.c @@ -27,7 +27,6 @@ * 10-06-2002 TG 128K card support added */ -#include #include #include #include diff --git a/drivers/net/b44.c b/drivers/net/b44.c index 0ee3e27969c6..819a17921cb9 100644 --- a/drivers/net/b44.c +++ b/drivers/net/b44.c @@ -18,7 +18,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 50f43dbf31ae..1f7ca453bb4a 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -67,7 +67,6 @@ */ #include -#include #include #include diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index c0af6fb1fbba..f8c9bcdab68b 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -60,7 +60,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/fs_enet/fs_enet.h b/drivers/net/fs_enet/fs_enet.h index 1105543b9d88..e7ec96c964a9 100644 --- a/drivers/net/fs_enet/fs_enet.h +++ b/drivers/net/fs_enet/fs_enet.h @@ -4,7 +4,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 962580f2c4ab..54d294ad6df5 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -90,7 +90,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index c77ca6c0d04a..220084e53341 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -43,7 +43,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/gianfar_ethtool.c b/drivers/net/gianfar_ethtool.c index 68e3578e7613..5a2d810ce575 100644 --- a/drivers/net/gianfar_ethtool.c +++ b/drivers/net/gianfar_ethtool.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/gianfar_mii.c b/drivers/net/gianfar_mii.c index 5a74d3d3dbe1..7263395d78bb 100644 --- a/drivers/net/gianfar_mii.c +++ b/drivers/net/gianfar_mii.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/hp100.c b/drivers/net/hp100.c index b71fab6e34f4..e92c17f6931c 100644 --- a/drivers/net/hp100.c +++ b/drivers/net/hp100.c @@ -96,7 +96,6 @@ #undef HP100_MULTICAST_FILTER /* Need to be debugged... */ -#include #include #include #include diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index 94239f67f3a3..be191d80ef9c 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -35,7 +35,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/iseries_veth.c b/drivers/net/iseries_veth.c index d86d8f055a6c..77eadf84cb2c 100644 --- a/drivers/net/iseries_veth.c +++ b/drivers/net/iseries_veth.c @@ -58,7 +58,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c index ce5761816a64..d8c99f038fa0 100644 --- a/drivers/net/mac8390.c +++ b/drivers/net/mac8390.c @@ -15,7 +15,6 @@ * and fixed access to Sonic Sys card which masquerades as a Farallon * by rayk@knightsmanor.org */ -#include #include #include #include diff --git a/drivers/net/mv643xx_eth.h b/drivers/net/mv643xx_eth.h index bcfda5192da0..f769f9b626ea 100644 --- a/drivers/net/mv643xx_eth.h +++ b/drivers/net/mv643xx_eth.h @@ -1,7 +1,6 @@ #ifndef __MV643XX_ETH_H__ #define __MV643XX_ETH_H__ -#include #include #include #include diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 0745dd9d01f3..8e41f4cea272 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -55,7 +55,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/sk98lin/h/skdrv1st.h b/drivers/net/sk98lin/h/skdrv1st.h index 308440bd0e12..91b8d4f45904 100644 --- a/drivers/net/sk98lin/h/skdrv1st.h +++ b/drivers/net/sk98lin/h/skdrv1st.h @@ -39,9 +39,6 @@ #ifndef __INC_SKDRV1ST_H #define __INC_SKDRV1ST_H -/* Check kernel version */ -#include - typedef struct s_AC SK_AC; /* Set card versions */ diff --git a/drivers/net/sk_mca.c b/drivers/net/sk_mca.c index 4c56b8d8221b..e5d6d95960c7 100644 --- a/drivers/net/sk_mca.c +++ b/drivers/net/sk_mca.c @@ -93,7 +93,6 @@ History: #include #include #include -#include #include #include #include diff --git a/drivers/net/sk_mca.h b/drivers/net/sk_mca.h index 7e7c99582746..d6fa1823dfa6 100644 --- a/drivers/net/sk_mca.h +++ b/drivers/net/sk_mca.h @@ -1,5 +1,3 @@ -#include - #ifndef _SK_MCA_INCLUDE_ #define _SK_MCA_INCLUDE_ diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index 38b2b0a3ce96..d167deda9a53 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -147,7 +147,6 @@ TODO: - fix forced speed/duplexing code (broken a long time ago, when #define DRV_RELDATE "October 3, 2005" #include -#include #include #include #include diff --git a/drivers/net/via-velocity.c b/drivers/net/via-velocity.c index a368d08e7d19..82c6b757d306 100644 --- a/drivers/net/via-velocity.c +++ b/drivers/net/via-velocity.c @@ -61,7 +61,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/wireless/hostap/hostap.c b/drivers/net/wireless/hostap/hostap.c index 6a96cd9f2685..3d2ea61033be 100644 --- a/drivers/net/wireless/hostap/hostap.c +++ b/drivers/net/wireless/hostap/hostap.c @@ -13,7 +13,6 @@ */ #include -#include #include #include #include diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c index 59fc15572395..abfae7fedebc 100644 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ b/drivers/net/wireless/hostap/hostap_hw.c @@ -31,7 +31,6 @@ #include -#include #include #include diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c index da0c80fb941c..2e85bdced2dd 100644 --- a/drivers/net/wireless/hostap/hostap_pci.c +++ b/drivers/net/wireless/hostap/hostap_pci.c @@ -5,7 +5,6 @@ * Andy Warner */ #include -#include #include #include #include diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c index 78d67b408b2f..94fe2449f099 100644 --- a/drivers/net/wireless/hostap/hostap_plx.c +++ b/drivers/net/wireless/hostap/hostap_plx.c @@ -8,7 +8,6 @@ #include -#include #include #include #include diff --git a/drivers/net/wireless/ipw2100.h b/drivers/net/wireless/ipw2100.h index c9e99ce15d66..1f23650c077f 100644 --- a/drivers/net/wireless/ipw2100.h +++ b/drivers/net/wireless/ipw2100.h @@ -37,7 +37,6 @@ #include #include #include -#include #include // new driver API #include diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 3db0c32afe82..589aef8ba4e6 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -31,6 +31,7 @@ ******************************************************************************/ #include "ipw2200.h" +#include #define IPW2200_VERSION "1.0.0" #define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" diff --git a/drivers/net/wireless/ipw2200.h b/drivers/net/wireless/ipw2200.h index e9cf32bf3e31..0873b758f499 100644 --- a/drivers/net/wireless/ipw2200.h +++ b/drivers/net/wireless/ipw2200.h @@ -34,7 +34,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/wireless/orinoco.h b/drivers/net/wireless/orinoco.h index 7a17bb31fc89..f5d856db92a1 100644 --- a/drivers/net/wireless/orinoco.h +++ b/drivers/net/wireless/orinoco.h @@ -12,7 +12,6 @@ #include #include #include -#include #include "hermes.h" diff --git a/drivers/net/wireless/prism54/isl_38xx.c b/drivers/net/wireless/prism54/isl_38xx.c index adc7499136dc..aaa958798f3f 100644 --- a/drivers/net/wireless/prism54/isl_38xx.c +++ b/drivers/net/wireless/prism54/isl_38xx.c @@ -18,7 +18,6 @@ * */ -#include #include #include #include diff --git a/drivers/net/wireless/prism54/isl_38xx.h b/drivers/net/wireless/prism54/isl_38xx.h index e83e4912ab66..8af20980af8d 100644 --- a/drivers/net/wireless/prism54/isl_38xx.h +++ b/drivers/net/wireless/prism54/isl_38xx.h @@ -20,7 +20,6 @@ #ifndef _ISL_38XX_H #define _ISL_38XX_H -#include #include #include diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c index 5c1a1adf1ff8..135a156db25d 100644 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ b/drivers/net/wireless/prism54/isl_ioctl.c @@ -20,7 +20,6 @@ * */ -#include #include #include #include diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c index 78bdb359835e..5ddf29599032 100644 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ b/drivers/net/wireless/prism54/islpci_dev.c @@ -19,7 +19,6 @@ * */ -#include #include #include diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h index efbed4397951..07053165e4c5 100644 --- a/drivers/net/wireless/prism54/islpci_dev.h +++ b/drivers/net/wireless/prism54/islpci_dev.h @@ -23,7 +23,6 @@ #ifndef _ISLPCI_DEV_H #define _ISLPCI_DEV_H -#include #include #include #include diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c index fc1eb3564832..80ae081ab4b7 100644 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ b/drivers/net/wireless/prism54/islpci_eth.c @@ -17,7 +17,6 @@ * */ -#include #include #include diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c index dc040caab7d7..b41d666fea3c 100644 --- a/drivers/net/wireless/prism54/islpci_hotplug.c +++ b/drivers/net/wireless/prism54/islpci_hotplug.c @@ -18,7 +18,6 @@ * */ -#include #include #include #include diff --git a/drivers/pcmcia/au1000_pb1x00.c b/drivers/pcmcia/au1000_pb1x00.c index d414a3bb50b9..86c0808d6a05 100644 --- a/drivers/pcmcia/au1000_pb1x00.c +++ b/drivers/pcmcia/au1000_pb1x00.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include diff --git a/drivers/pcmcia/au1000_xxs1500.c b/drivers/pcmcia/au1000_xxs1500.c index f113b69d699b..01a895bc9a47 100644 --- a/drivers/pcmcia/au1000_xxs1500.c +++ b/drivers/pcmcia/au1000_xxs1500.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include diff --git a/drivers/s390/crypto/z90main.c b/drivers/s390/crypto/z90main.c index 04c2ef778ec6..4010f2bb85af 100644 --- a/drivers/s390/crypto/z90main.c +++ b/drivers/s390/crypto/z90main.c @@ -37,7 +37,6 @@ #include #include #include -#include #include "z90crypt.h" #include "z90common.h" diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index 1a1c3decea72..6b63d21612ec 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c @@ -88,7 +88,6 @@ #include #include #include -#include #include "cu3088.h" #include "claw.h" diff --git a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h index 98bad773f240..4f81fc39ec57 100644 --- a/drivers/scsi/3w-xxxx.h +++ b/drivers/scsi/3w-xxxx.h @@ -54,7 +54,6 @@ #ifndef _3W_XXXX_H #define _3W_XXXX_H -#include #include /* AEN strings */ diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c index f7a1751e892d..30a14ba77a6a 100644 --- a/drivers/scsi/a2091.c +++ b/drivers/scsi/a2091.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h index 052c6619accc..bc44222d6cc3 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.h +++ b/drivers/scsi/aic7xxx/aic79xx_osm.h @@ -49,7 +49,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h index be9edbe26dbe..f2a95447142c 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.h +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h @@ -66,7 +66,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/amiga7xx.c b/drivers/scsi/amiga7xx.c index 5f13546d6392..dea8446f5360 100644 --- a/drivers/scsi/amiga7xx.c +++ b/drivers/scsi/amiga7xx.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/bvme6000.c b/drivers/scsi/bvme6000.c index 29c7ed30c09e..130f30f51a9b 100644 --- a/drivers/scsi/bvme6000.c +++ b/drivers/scsi/bvme6000.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include diff --git a/drivers/scsi/gvp11.c b/drivers/scsi/gvp11.c index d12342fa8199..ab22387c9df1 100644 --- a/drivers/scsi/gvp11.c +++ b/drivers/scsi/gvp11.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c index 887a5c3ded28..8d97999db60e 100644 --- a/drivers/scsi/ibmmca.c +++ b/drivers/scsi/ibmmca.c @@ -18,12 +18,6 @@ */ #include -#ifndef LINUX_VERSION_CODE -#include -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,45) -#error "This driver works only with kernel 2.5.45 or higher!" -#endif #include #include #include diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h index 505e967013de..adc6eabbf610 100644 --- a/drivers/scsi/ips.h +++ b/drivers/scsi/ips.h @@ -50,6 +50,7 @@ #ifndef _IPS_H_ #define _IPS_H_ +#include #include #include diff --git a/drivers/scsi/megaraid/mega_common.h b/drivers/scsi/megaraid/mega_common.h index 69df1a9b935d..8e547130e97d 100644 --- a/drivers/scsi/megaraid/mega_common.h +++ b/drivers/scsi/megaraid/mega_common.h @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/megaraid/megaraid_mm.h b/drivers/scsi/megaraid/megaraid_mm.h index 7e36c46e7c43..eb8c390a0fa3 100644 --- a/drivers/scsi/megaraid/megaraid_mm.h +++ b/drivers/scsi/megaraid/megaraid_mm.h @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 4245d05e628b..801a63bea8a5 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/mvme147.c b/drivers/scsi/mvme147.c index 2fb31ee6d9f5..33380cee9b77 100644 --- a/drivers/scsi/mvme147.c +++ b/drivers/scsi/mvme147.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include diff --git a/drivers/scsi/mvme16x.c b/drivers/scsi/mvme16x.c index b2d8d8ea1604..29ec699e0e4d 100644 --- a/drivers/scsi/mvme16x.c +++ b/drivers/scsi/mvme16x.c @@ -7,7 +7,6 @@ #include #include #include -#include #include #include diff --git a/drivers/scsi/nsp32.h b/drivers/scsi/nsp32.h index 5664398fa0ad..5addf9fb1e15 100644 --- a/drivers/scsi/nsp32.h +++ b/drivers/scsi/nsp32.h @@ -16,6 +16,7 @@ #ifndef _NSP32_H #define _NSP32_H +#include //#define NSP32_DEBUG 9 /* diff --git a/drivers/scsi/pci2000.h b/drivers/scsi/pci2000.h index c65afc964121..6c962d7dca47 100644 --- a/drivers/scsi/pci2000.h +++ b/drivers/scsi/pci2000.h @@ -26,9 +26,6 @@ #ifndef PSI_EIDE_SCSIOP #define PSI_EIDE_SCSIOP 1 -#ifndef LINUX_VERSION_CODE -#include -#endif #define LINUXVERSION(v,p,s) (((v)<<16) + ((p)<<8) + (s)) /************************************************/ diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index aadf051274fa..b61fb1295b8b 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -48,10 +48,6 @@ #include -#ifndef LINUX_VERSION_CODE -#include -#endif - #include "scsi_logging.h" #include "scsi_debug.h" diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 62e3f340cc52..72ec59456e69 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -68,10 +68,6 @@ static int sg_proc_init(void); static void sg_proc_cleanup(void); #endif -#ifndef LINUX_VERSION_CODE -#include -#endif /* LINUX_VERSION_CODE */ - #define SG_ALLOW_DIO_DEF 0 #define SG_ALLOW_DIO_CODE /* compile out by commenting this define */ diff --git a/drivers/scsi/sgiwd93.c b/drivers/scsi/sgiwd93.c index 09fd203e4b86..f37147f8f7bf 100644 --- a/drivers/scsi/sgiwd93.c +++ b/drivers/scsi/sgiwd93.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c index 5754445fb36a..fd63add6a577 100644 --- a/drivers/scsi/wd33c93.c +++ b/drivers/scsi/wd33c93.c @@ -77,7 +77,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/telephony/ixj.h b/drivers/telephony/ixj.h index 51e3f7f6597b..fbea4541c234 100644 --- a/drivers/telephony/ixj.h +++ b/drivers/telephony/ixj.h @@ -40,7 +40,6 @@ *****************************************************************************/ #define IXJ_VERSION 3031 -#include #include #include diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 975ace3f5b1e..904519085334 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -49,7 +49,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/usb/gadget/lh7a40x_udc.h b/drivers/usb/gadget/lh7a40x_udc.h index 1bb455c045a9..9b2e6f7cbb8b 100644 --- a/drivers/usb/gadget/lh7a40x_udc.h +++ b/drivers/usb/gadget/lh7a40x_udc.h @@ -29,7 +29,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/usb/gadget/pxa2xx_udc.c b/drivers/usb/gadget/pxa2xx_udc.c index ee9cd7869d92..510d28a924db 100644 --- a/drivers/usb/gadget/pxa2xx_udc.c +++ b/drivers/usb/gadget/pxa2xx_udc.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index 06b6eba925b5..9689efeb364c 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/usb/host/hc_crisv10.c b/drivers/usb/host/hc_crisv10.c index a8267cf17db4..0eaabeb37ac3 100644 --- a/drivers/usb/host/hc_crisv10.c +++ b/drivers/usb/host/hc_crisv10.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include diff --git a/drivers/usb/media/pwc/pwc-if.c b/drivers/usb/media/pwc/pwc-if.c index b77e65c03659..5524fd70210b 100644 --- a/drivers/usb/media/pwc/pwc-if.c +++ b/drivers/usb/media/pwc/pwc-if.c @@ -62,6 +62,7 @@ #include #include #include +#include #include #include "pwc.h" diff --git a/drivers/usb/media/pwc/pwc.h b/drivers/usb/media/pwc/pwc.h index 267869dab185..6dd76bb3dff1 100644 --- a/drivers/usb/media/pwc/pwc.h +++ b/drivers/usb/media/pwc/pwc.h @@ -25,8 +25,6 @@ #ifndef PWC_H #define PWC_H -#include - #include #include #include diff --git a/drivers/usb/media/w9968cf.c b/drivers/usb/media/w9968cf.c index f36c0b6c6e36..67612c81cb9f 100644 --- a/drivers/usb/media/w9968cf.c +++ b/drivers/usb/media/w9968cf.c @@ -25,7 +25,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * ***************************************************************************/ -#include #include #include #include diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index c946c9a538a0..41ef2b606751 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -37,7 +37,6 @@ */ #include -#include #include #include #include diff --git a/drivers/usb/misc/sisusbvga/sisusb.h b/drivers/usb/misc/sisusbvga/sisusb.h index 401ff21d7881..1d7a77cc7c4a 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.h +++ b/drivers/usb/misc/sisusbvga/sisusb.h @@ -37,6 +37,7 @@ #ifndef _SISUSB_H_ #define _SISUSB_H_ +#include #ifdef CONFIG_COMPAT #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,10) #include diff --git a/drivers/usb/misc/sisusbvga/sisusb_con.c b/drivers/usb/misc/sisusbvga/sisusb_con.c index 24584463553d..be5c1a25ae21 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_con.c +++ b/drivers/usb/misc/sisusbvga/sisusb_con.c @@ -48,7 +48,6 @@ */ #include -#include #include #include #include diff --git a/drivers/usb/misc/sisusbvga/sisusb_init.c b/drivers/usb/misc/sisusbvga/sisusb_init.c index f28bc240f9b6..044fa4482f9f 100644 --- a/drivers/usb/misc/sisusbvga/sisusb_init.c +++ b/drivers/usb/misc/sisusbvga/sisusb_init.c @@ -37,7 +37,6 @@ */ #include -#include #include #include #include diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c index acc81cb01d56..9d5015e99372 100644 --- a/drivers/video/backlight/backlight.c +++ b/drivers/video/backlight/backlight.c @@ -5,7 +5,6 @@ * */ -#include #include #include #include diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c index 470e6f0ee4dd..68c690605aa7 100644 --- a/drivers/video/backlight/lcd.c +++ b/drivers/video/backlight/lcd.c @@ -5,7 +5,6 @@ * */ -#include #include #include #include diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c index 0799b999b314..427689e584da 100644 --- a/drivers/video/intelfb/intelfbdrv.c +++ b/drivers/video/intelfb/intelfbdrv.c @@ -122,7 +122,6 @@ #include #include #include -#include #include diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c index ac94c2e5ff85..624c4bc96f0d 100644 --- a/drivers/video/intelfb/intelfbhw.c +++ b/drivers/video/intelfb/intelfbhw.c @@ -34,7 +34,6 @@ #include #include #include -#include #include diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index bbc3cc63854f..89c849da8504 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include diff --git a/fs/adfs/adfs.h b/fs/adfs/adfs.h index fd528433de43..f6cd01352cc8 100644 --- a/fs/adfs/adfs.h +++ b/fs/adfs/adfs.h @@ -12,7 +12,6 @@ #define ADFS_NDA_PUBLIC_READ (1 << 5) #define ADFS_NDA_PUBLIC_WRITE (1 << 6) -#include #include "dir_f.h" struct buffer_head; diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h index aae019aadf88..cc5dcd52e23d 100644 --- a/fs/hfs/hfs_fs.h +++ b/fs/hfs/hfs_fs.h @@ -9,7 +9,6 @@ #ifndef _LINUX_HFS_FS_H #define _LINUX_HFS_FS_H -#include #include #include #include diff --git a/fs/hfs/inode.c b/fs/hfs/inode.c index 3f680c5675bf..d499393a8ae7 100644 --- a/fs/hfs/inode.c +++ b/fs/hfs/inode.c @@ -12,7 +12,6 @@ */ #include -#include #include #include "hfs_fs.h" diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c index b85abc6e6f83..930cd9212de8 100644 --- a/fs/hfsplus/bnode.c +++ b/fs/hfsplus/bnode.c @@ -13,7 +13,6 @@ #include #include #include -#include #include "hfsplus_fs.h" #include "hfsplus_raw.h" diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index 7bda76667a4a..50c8f44b6c66 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c @@ -13,7 +13,6 @@ #include #include #include -#include #include "hfsplus_fs.h" #include "hfsplus_raw.h" diff --git a/fs/hfsplus/extents.c b/fs/hfsplus/extents.c index e7235ca79a95..e3ff56a03011 100644 --- a/fs/hfsplus/extents.c +++ b/fs/hfsplus/extents.c @@ -11,7 +11,6 @@ #include #include #include -#include #include "hfsplus_fs.h" #include "hfsplus_raw.h" diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 2bc0cdd30e56..c60e5635498d 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h @@ -11,7 +11,6 @@ #define _LINUX_HFSPLUS_FS_H #include -#include #include #include "hfsplus_raw.h" diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index f205773ddfbe..fc98583cf045 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include "hfsplus_fs.h" diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 452fc1fdbd32..0ce1c455ae55 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c @@ -14,7 +14,6 @@ #include #include #include -#include #include #include diff --git a/fs/hfsplus/wrapper.c b/fs/hfsplus/wrapper.c index 0c51d6338b0b..95455e839231 100644 --- a/fs/hfsplus/wrapper.c +++ b/fs/hfsplus/wrapper.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include "hfsplus_fs.h" diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index a33fb1d91373..4684eb7d48c6 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -8,7 +8,6 @@ #include #include -#include #include #include #include diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index 44fed10af0dd..d8e21ba0cccc 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h @@ -72,7 +72,6 @@ #include #include #include -#include #include #include diff --git a/fs/xfs/xfs.h b/fs/xfs/xfs.h index 99b50d2bda9b..1a48dbb902a7 100644 --- a/fs/xfs/xfs.h +++ b/fs/xfs/xfs.h @@ -17,12 +17,5 @@ */ #ifndef __XFS_H__ #define __XFS_H__ - -#include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) #include -#else -#include -#endif - #endif /* __XFS_H__ */ diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h index 5a5c7a63e80b..864bf6955689 100644 --- a/fs/xfs/xfs_dmapi.h +++ b/fs/xfs/xfs_dmapi.h @@ -18,6 +18,7 @@ #ifndef __XFS_DMAPI_H__ #define __XFS_DMAPI_H__ +#include /* Values used to define the on-disk version of dm_attrname_t. All * on-disk attribute names start with the 8-byte string "SGI_DMI_". * diff --git a/include/linux/fs_enet_pd.h b/include/linux/fs_enet_pd.h index bef23bbf8690..783c476b8674 100644 --- a/include/linux/fs_enet_pd.h +++ b/include/linux/fs_enet_pd.h @@ -16,7 +16,6 @@ #ifndef FS_ENET_PD_H #define FS_ENET_PD_H -#include #include #define FS_ENET_NAME "fs_enet" diff --git a/include/linux/if_wanpipe_common.h b/include/linux/if_wanpipe_common.h index f25fec8ee2ca..6e5461d69fdd 100644 --- a/include/linux/if_wanpipe_common.h +++ b/include/linux/if_wanpipe_common.h @@ -17,8 +17,6 @@ #ifndef _WANPIPE_SOCK_DRIVER_COMMON_H #define _WANPIPE_SOCK_DRIVER_COMMON_H -#include - typedef struct { struct net_device *slave; atomic_t packet_sent; diff --git a/include/linux/istallion.h b/include/linux/istallion.h index 5f4ee646c119..1f996621bc9c 100644 --- a/include/linux/istallion.h +++ b/include/linux/istallion.h @@ -21,8 +21,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include - /*****************************************************************************/ #ifndef _ISTALLION_H #define _ISTALLION_H diff --git a/include/linux/mtd/cfi.h b/include/linux/mtd/cfi.h index 39f1430bd6d5..3c9ea4b7adda 100644 --- a/include/linux/mtd/cfi.h +++ b/include/linux/mtd/cfi.h @@ -8,7 +8,6 @@ #define __MTD_CFI_H__ #include -#include #include #include #include diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index e95d0463a3e5..b6f2fdae65c6 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -14,7 +14,6 @@ #endif #include -#include #include #include #include diff --git a/include/linux/phonedev.h b/include/linux/phonedev.h index d54049eed0c3..a0e31adf3abe 100644 --- a/include/linux/phonedev.h +++ b/include/linux/phonedev.h @@ -2,7 +2,6 @@ #define __LINUX_PHONEDEV_H #include -#include #ifdef __KERNEL__ diff --git a/include/linux/stallion.h b/include/linux/stallion.h index e89b77b6505a..13a37f137ea2 100644 --- a/include/linux/stallion.h +++ b/include/linux/stallion.h @@ -21,8 +21,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include - /*****************************************************************************/ #ifndef _STALLION_H #define _STALLION_H diff --git a/sound/oss/msnd.c b/sound/oss/msnd.c index 4f1ff1bccdce..a7ad2b0a2ac0 100644 --- a/sound/oss/msnd.c +++ b/sound/oss/msnd.c @@ -24,7 +24,6 @@ * ********************************************************************/ -#include #include #include #include diff --git a/sound/oss/os.h b/sound/oss/os.h index 80dce329cc3a..0490562c7f7f 100644 --- a/sound/oss/os.h +++ b/sound/oss/os.h @@ -5,10 +5,8 @@ #undef DO_TIMINGS #include -#include #ifdef __KERNEL__ -#include #include #include #include diff --git a/sound/oss/rme96xx.c b/sound/oss/rme96xx.c index 7609c68a89f4..318dc51009fe 100644 --- a/sound/oss/rme96xx.c +++ b/sound/oss/rme96xx.c @@ -44,7 +44,6 @@ TODO: #define RMEVERSION "0.8" #endif -#include #include #include #include diff --git a/sound/oss/sh_dac_audio.c b/sound/oss/sh_dac_audio.c index c09cdeedc191..8a9917c919c2 100644 --- a/sound/oss/sh_dac_audio.c +++ b/sound/oss/sh_dac_audio.c @@ -2,7 +2,6 @@ #include #include #include -#include #include #include #include diff --git a/sound/ppc/pmac.h b/sound/ppc/pmac.h index ae3bb6c6edff..bfff788e9847 100644 --- a/sound/ppc/pmac.h +++ b/sound/ppc/pmac.h @@ -22,7 +22,6 @@ #ifndef __PMAC_H #define __PMAC_H -#include #include #include #include "awacs.h" -- cgit v1.2.3 From e4543eddfd3bf3e0d625841377fa695a519edfd4 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 8 Nov 2005 21:35:04 -0800 Subject: [PATCH] add a vfs_permission helper Most permission() calls have a struct nameidata * available. This helper takes that as an argument and thus makes sure we pass it down for lookup intents and prepares for per-mount read-only support where we need a struct vfsmount for checking whether a file is writeable. Signed-off-by: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/exec.c | 4 ++-- fs/inotify.c | 2 +- fs/namei.c | 23 +++++++++++++++++++---- fs/namespace.c | 2 +- fs/open.c | 12 ++++++------ include/linux/fs.h | 1 + net/unix/af_unix.c | 2 +- 7 files changed, 31 insertions(+), 15 deletions(-) (limited to 'include/linux') diff --git a/fs/exec.c b/fs/exec.c index 5a4e3acc2e9f..7bbb781b9ac6 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -135,7 +135,7 @@ asmlinkage long sys_uselib(const char __user * library) if (!S_ISREG(nd.dentry->d_inode->i_mode)) goto exit; - error = permission(nd.dentry->d_inode, MAY_READ | MAY_EXEC, &nd); + error = vfs_permission(&nd, MAY_READ | MAY_EXEC); if (error) goto exit; @@ -495,7 +495,7 @@ struct file *open_exec(const char *name) file = ERR_PTR(-EACCES); if (!(nd.mnt->mnt_flags & MNT_NOEXEC) && S_ISREG(inode->i_mode)) { - int err = permission(inode, MAY_EXEC, &nd); + int err = vfs_permission(&nd, MAY_EXEC); if (!err && !(inode->i_mode & 0111)) err = -EACCES; file = ERR_PTR(err); diff --git a/fs/inotify.c b/fs/inotify.c index 9fbaebfdf40b..bf7ce1d2412b 100644 --- a/fs/inotify.c +++ b/fs/inotify.c @@ -372,7 +372,7 @@ static int find_inode(const char __user *dirname, struct nameidata *nd) if (error) return error; /* you can only watch an inode if you have read permissions on it */ - error = permission(nd->dentry->d_inode, MAY_READ, NULL); + error = vfs_permission(nd, MAY_READ); if (error) path_release(nd); return error; diff --git a/fs/namei.c b/fs/namei.c index b3f8a1966c9c..25e4ab4ce8b7 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -256,6 +256,21 @@ int permission(struct inode *inode, int mask, struct nameidata *nd) return security_inode_permission(inode, mask, nd); } +/** + * vfs_permission - check for access rights to a given path + * @nd: lookup result that describes the path + * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) + * + * Used to check for read/write/execute permissions on a path. + * We use "fsuid" for this, letting us set arbitrary permissions + * for filesystem access without changing the "normal" uids which + * are used for other things. + */ +int vfs_permission(struct nameidata *nd, int mask) +{ + return permission(nd->dentry->d_inode, mask, nd); +} + /* * get_write_access() gets write permission for a file. * put_write_access() releases this write permission. @@ -765,9 +780,8 @@ static fastcall int __link_path_walk(const char * name, struct nameidata *nd) nd->flags |= LOOKUP_CONTINUE; err = exec_permission_lite(inode, nd); - if (err == -EAGAIN) { - err = permission(inode, MAY_EXEC, nd); - } + if (err == -EAGAIN) + err = vfs_permission(nd, MAY_EXEC); if (err) break; @@ -1407,7 +1421,7 @@ int may_open(struct nameidata *nd, int acc_mode, int flag) if (S_ISDIR(inode->i_mode) && (flag & FMODE_WRITE)) return -EISDIR; - error = permission(inode, acc_mode, nd); + error = vfs_permission(nd, acc_mode); if (error) return error; @@ -2536,6 +2550,7 @@ EXPORT_SYMBOL(path_lookup); EXPORT_SYMBOL(path_release); EXPORT_SYMBOL(path_walk); EXPORT_SYMBOL(permission); +EXPORT_SYMBOL(vfs_permission); EXPORT_SYMBOL(unlock_rename); EXPORT_SYMBOL(vfs_create); EXPORT_SYMBOL(vfs_follow_link); diff --git a/fs/namespace.c b/fs/namespace.c index caa9187f67e5..2019899f2ab8 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -637,7 +637,7 @@ static int mount_is_safe(struct nameidata *nd) if (current->uid != nd->dentry->d_inode->i_uid) return -EPERM; } - if (permission(nd->dentry->d_inode, MAY_WRITE, nd)) + if (vfs_permission(nd, MAY_WRITE)) return -EPERM; return 0; #endif diff --git a/fs/open.c b/fs/open.c index 6e8136751e9a..baffc084580d 100644 --- a/fs/open.c +++ b/fs/open.c @@ -240,7 +240,7 @@ static inline long do_sys_truncate(const char __user * path, loff_t length) if (!S_ISREG(inode->i_mode)) goto dput_and_out; - error = permission(inode,MAY_WRITE,&nd); + error = vfs_permission(&nd, MAY_WRITE); if (error) goto dput_and_out; @@ -394,7 +394,7 @@ asmlinkage long sys_utime(char __user * filename, struct utimbuf __user * times) goto dput_and_out; if (current->fsuid != inode->i_uid && - (error = permission(inode,MAY_WRITE,&nd)) != 0) + (error = vfs_permission(&nd, MAY_WRITE)) != 0) goto dput_and_out; } down(&inode->i_sem); @@ -447,7 +447,7 @@ long do_utimes(char __user * filename, struct timeval * times) goto dput_and_out; if (current->fsuid != inode->i_uid && - (error = permission(inode,MAY_WRITE,&nd)) != 0) + (error = vfs_permission(&nd, MAY_WRITE)) != 0) goto dput_and_out; } down(&inode->i_sem); @@ -506,7 +506,7 @@ asmlinkage long sys_access(const char __user * filename, int mode) res = __user_walk(filename, LOOKUP_FOLLOW|LOOKUP_ACCESS, &nd); if (!res) { - res = permission(nd.dentry->d_inode, mode, &nd); + res = vfs_permission(&nd, mode); /* SuS v2 requires we report a read only fs too */ if(!res && (mode & S_IWOTH) && IS_RDONLY(nd.dentry->d_inode) && !special_file(nd.dentry->d_inode->i_mode)) @@ -530,7 +530,7 @@ asmlinkage long sys_chdir(const char __user * filename) if (error) goto out; - error = permission(nd.dentry->d_inode,MAY_EXEC,&nd); + error = vfs_permission(&nd, MAY_EXEC); if (error) goto dput_and_out; @@ -581,7 +581,7 @@ asmlinkage long sys_chroot(const char __user * filename) if (error) goto out; - error = permission(nd.dentry->d_inode,MAY_EXEC,&nd); + error = vfs_permission(&nd, MAY_EXEC); if (error) goto dput_and_out; diff --git a/include/linux/fs.h b/include/linux/fs.h index 1b5f502a4b8f..c3b8c1dc7cdf 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -874,6 +874,7 @@ static inline void unlock_super(struct super_block * sb) /* * VFS helper functions.. */ +extern int vfs_permission(struct nameidata *, int); extern int vfs_create(struct inode *, struct dentry *, int, struct nameidata *); extern int vfs_mkdir(struct inode *, struct dentry *, int); extern int vfs_mknod(struct inode *, struct dentry *, int, dev_t); diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 41feca3bef86..acc73ba8bade 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -676,7 +676,7 @@ static struct sock *unix_find_other(struct sockaddr_un *sunname, int len, err = path_lookup(sunname->sun_path, LOOKUP_FOLLOW, &nd); if (err) goto fail; - err = permission(nd.dentry->d_inode,MAY_WRITE, &nd); + err = vfs_permission(&nd, MAY_WRITE); if (err) goto put_fail; -- cgit v1.2.3 From 8c744fb83da0771afa04695028e3550b798dad90 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 8 Nov 2005 21:35:04 -0800 Subject: [PATCH] add a file_permission helper A few more callers of permission() just want to check for a different access pattern on an already open file. This patch adds a wrapper for permission() that takes a file in preparation of per-mount read-only support and to clean up the callers a little. The helper is not intended for new code, everything without the interface set in stone should use vfs_permission() Signed-off-by: Christoph Hellwig Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/floppy.c | 3 +-- fs/binfmt_misc.c | 2 +- fs/exec.c | 2 +- fs/namei.c | 18 ++++++++++++++++++ fs/ncpfs/ioctl.c | 34 +++++++++++++++++++--------------- fs/open.c | 2 +- fs/udf/file.c | 2 +- include/linux/fs.h | 5 +++++ 8 files changed, 47 insertions(+), 21 deletions(-) (limited to 'include/linux') diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index dd1935d55424..28002de783b6 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -3776,8 +3776,7 @@ static int floppy_open(struct inode *inode, struct file *filp) /* Allow ioctls if we have write-permissions even if read-only open. * Needed so that programs such as fdrawcmd still can work on write * protected disks */ - if (filp->f_mode & 2 - || permission(filp->f_dentry->d_inode, 2, NULL) == 0) + if ((filp->f_mode & FMODE_WRITE) || !file_permission(filp, MAY_WRITE)) filp->private_data = (void *)8; if (UFDCS->rawcmd == 1) diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index 8ae0db6cd69c..2568eb41cb3a 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c @@ -150,7 +150,7 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) /* if the binary is not readable than enforce mm->dumpable=0 regardless of the interpreter's permissions */ - if (permission(bprm->file->f_dentry->d_inode, MAY_READ, NULL)) + if (file_permission(bprm->file, MAY_READ)) bprm->interp_flags |= BINPRM_FLAGS_ENFORCE_NONDUMP; allow_write_access(bprm->file); diff --git a/fs/exec.c b/fs/exec.c index 7bbb781b9ac6..c466fec5de20 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -896,7 +896,7 @@ int flush_old_exec(struct linux_binprm * bprm) flush_thread(); if (bprm->e_uid != current->euid || bprm->e_gid != current->egid || - permission(bprm->file->f_dentry->d_inode,MAY_READ, NULL) || + file_permission(bprm->file, MAY_READ) || (bprm->interp_flags & BINPRM_FLAGS_ENFORCE_NONDUMP)) { suid_keys(current); current->mm->dumpable = suid_dumpable; diff --git a/fs/namei.c b/fs/namei.c index 25e4ab4ce8b7..b69f6ebadb95 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -271,6 +271,23 @@ int vfs_permission(struct nameidata *nd, int mask) return permission(nd->dentry->d_inode, mask, nd); } +/** + * file_permission - check for additional access rights to a given file + * @file: file to check access rights for + * @mask: right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC) + * + * Used to check for read/write/execute permissions on an already opened + * file. + * + * Note: + * Do not use this function in new code. All access checks should + * be done using vfs_permission(). + */ +int file_permission(struct file *file, int mask) +{ + return permission(file->f_dentry->d_inode, mask, NULL); +} + /* * get_write_access() gets write permission for a file. * put_write_access() releases this write permission. @@ -2551,6 +2568,7 @@ EXPORT_SYMBOL(path_release); EXPORT_SYMBOL(path_walk); EXPORT_SYMBOL(permission); EXPORT_SYMBOL(vfs_permission); +EXPORT_SYMBOL(file_permission); EXPORT_SYMBOL(unlock_rename); EXPORT_SYMBOL(vfs_create); EXPORT_SYMBOL(vfs_follow_link); diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c index 88df79356a1f..fd3efdca5ae3 100644 --- a/fs/ncpfs/ioctl.c +++ b/fs/ncpfs/ioctl.c @@ -30,11 +30,13 @@ #define NCP_PACKET_SIZE_INTERNAL 65536 static int -ncp_get_fs_info(struct ncp_server* server, struct inode* inode, struct ncp_fs_info __user *arg) +ncp_get_fs_info(struct ncp_server * server, struct file *file, + struct ncp_fs_info __user *arg) { + struct inode *inode = file->f_dentry->d_inode; struct ncp_fs_info info; - if ((permission(inode, MAY_WRITE, NULL) != 0) + if ((file_permission(file, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; } @@ -58,11 +60,13 @@ ncp_get_fs_info(struct ncp_server* server, struct inode* inode, struct ncp_fs_in } static int -ncp_get_fs_info_v2(struct ncp_server* server, struct inode* inode, struct ncp_fs_info_v2 __user * arg) +ncp_get_fs_info_v2(struct ncp_server * server, struct file *file, + struct ncp_fs_info_v2 __user * arg) { + struct inode *inode = file->f_dentry->d_inode; struct ncp_fs_info_v2 info2; - if ((permission(inode, MAY_WRITE, NULL) != 0) + if ((file_permission(file, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; } @@ -190,7 +194,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, switch (cmd) { case NCP_IOC_NCPREQUEST: - if ((permission(inode, MAY_WRITE, NULL) != 0) + if ((file_permission(filp, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; } @@ -245,16 +249,16 @@ int ncp_ioctl(struct inode *inode, struct file *filp, return ncp_conn_logged_in(inode->i_sb); case NCP_IOC_GET_FS_INFO: - return ncp_get_fs_info(server, inode, argp); + return ncp_get_fs_info(server, filp, argp); case NCP_IOC_GET_FS_INFO_V2: - return ncp_get_fs_info_v2(server, inode, argp); + return ncp_get_fs_info_v2(server, filp, argp); case NCP_IOC_GETMOUNTUID2: { unsigned long tmp = server->m.mounted_uid; - if ( (permission(inode, MAY_READ, NULL) != 0) + if ((file_permission(filp, MAY_READ) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; @@ -268,7 +272,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, { struct ncp_setroot_ioctl sr; - if ( (permission(inode, MAY_READ, NULL) != 0) + if ((file_permission(filp, MAY_READ) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; @@ -343,7 +347,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, #ifdef CONFIG_NCPFS_PACKET_SIGNING case NCP_IOC_SIGN_INIT: - if ((permission(inode, MAY_WRITE, NULL) != 0) + if ((file_permission(filp, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; @@ -366,7 +370,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, return 0; case NCP_IOC_SIGN_WANTED: - if ( (permission(inode, MAY_READ, NULL) != 0) + if ((file_permission(filp, MAY_READ) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; @@ -379,7 +383,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, { int newstate; - if ( (permission(inode, MAY_WRITE, NULL) != 0) + if ((file_permission(filp, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; @@ -400,7 +404,7 @@ int ncp_ioctl(struct inode *inode, struct file *filp, #ifdef CONFIG_NCPFS_IOCTL_LOCKING case NCP_IOC_LOCKUNLOCK: - if ( (permission(inode, MAY_WRITE, NULL) != 0) + if ((file_permission(filp, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; @@ -605,7 +609,7 @@ outrel: #endif /* CONFIG_NCPFS_NLS */ case NCP_IOC_SETDENTRYTTL: - if ((permission(inode, MAY_WRITE, NULL) != 0) && + if ((file_permission(filp, MAY_WRITE) != 0) && (current->uid != server->m.mounted_uid)) return -EACCES; { @@ -635,7 +639,7 @@ outrel: so we have this out of switch */ if (cmd == NCP_IOC_GETMOUNTUID) { __kernel_uid_t uid = 0; - if ((permission(inode, MAY_READ, NULL) != 0) + if ((file_permission(filp, MAY_READ) != 0) && (current->uid != server->m.mounted_uid)) { return -EACCES; } diff --git a/fs/open.c b/fs/open.c index baffc084580d..f53a5b9ffb7d 100644 --- a/fs/open.c +++ b/fs/open.c @@ -563,7 +563,7 @@ asmlinkage long sys_fchdir(unsigned int fd) if (!S_ISDIR(inode->i_mode)) goto out_putf; - error = permission(inode, MAY_EXEC, NULL); + error = file_permission(file, MAY_EXEC); if (!error) set_fs_pwd(current->fs, mnt, dentry); out_putf: diff --git a/fs/udf/file.c b/fs/udf/file.c index bb40d63f328f..01f520c71dc1 100644 --- a/fs/udf/file.c +++ b/fs/udf/file.c @@ -186,7 +186,7 @@ int udf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, { int result = -EINVAL; - if ( permission(inode, MAY_READ, NULL) != 0 ) + if ( file_permission(filp, MAY_READ) != 0 ) { udf_debug("no permission to access inode %lu\n", inode->i_ino); diff --git a/include/linux/fs.h b/include/linux/fs.h index c3b8c1dc7cdf..cc35b6ac778d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -889,6 +889,11 @@ extern int vfs_rename(struct inode *, struct dentry *, struct inode *, struct de */ extern void dentry_unhash(struct dentry *dentry); +/* + * VFS file helper functions. + */ +extern int file_permission(struct file *, int); + /* * File types * -- cgit v1.2.3 From 49705b7743fd8f5632a95ec4c6547d169d27ac1f Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 8 Nov 2005 21:35:06 -0800 Subject: [PATCH] sanitize lookup_hash prototype ->permission and ->lookup have a struct nameidata * argument these days to pass down lookup intents. Unfortunately some callers of lookup_hash don't actually pass this one down. For lookup_one_len() we don't have a struct nameidata to pass down, but as this function is a library function only used by filesystem code this is an acceptable limitation. All other callers should pass down the nameidata, so this patch changes the lookup_hash interface to only take a struct nameidata argument and derives the other two arguments to __lookup_hash from it. All callers already have the nameidata argument available so this is not a problem. At the same time I'd like to deprecate the lookup_hash interface as there are better exported interfaces for filesystem usage. Before it can actually be removed I need to fix up rpc_pipefs. Signed-off-by: Christoph Hellwig Cc: Ram Pai Cc: Jeff Mahoney Cc: Al Viro Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/feature-removal-schedule.txt | 7 +++++++ fs/namei.c | 20 ++++++++++---------- include/linux/namei.h | 2 +- net/sunrpc/rpc_pipe.c | 6 +++--- 4 files changed, 21 insertions(+), 14 deletions(-) (limited to 'include/linux') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 910cc9998731..66e4ca28fc0a 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -118,3 +118,10 @@ Why: This interface has been obsoleted by the new layer3-independent to link against API-compatible library on top of libnfnetlink_queue instead of the current 'libipq'. Who: Harald Welte + +--------------------------- + +What: EXPORT_SYMBOL(lookup_hash) +When: January 2006 +Why: Too low-level interface. Use lookup_one_len or lookup_create instead. +Who: Christoph Hellwig diff --git a/fs/namei.c b/fs/namei.c index b69f6ebadb95..f02ec0e50fca 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -1204,9 +1204,9 @@ out: return dentry; } -struct dentry * lookup_hash(struct qstr *name, struct dentry * base) +struct dentry * lookup_hash(struct nameidata *nd) { - return __lookup_hash(name, base, NULL); + return __lookup_hash(&nd->last, nd->dentry, nd); } /* SMP-safe */ @@ -1230,7 +1230,7 @@ struct dentry * lookup_one_len(const char * name, struct dentry * base, int len) } this.hash = end_name_hash(hash); - return lookup_hash(&this, base); + return __lookup_hash(&this, base, NULL); access: return ERR_PTR(-EACCES); } @@ -1563,7 +1563,7 @@ int open_namei(const char * pathname, int flag, int mode, struct nameidata *nd) dir = nd->dentry; nd->flags &= ~LOOKUP_PARENT; down(&dir->d_inode->i_sem); - path.dentry = __lookup_hash(&nd->last, nd->dentry, nd); + path.dentry = lookup_hash(nd); path.mnt = nd->mnt; do_last: @@ -1665,7 +1665,7 @@ do_link: } dir = nd->dentry; down(&dir->d_inode->i_sem); - path.dentry = __lookup_hash(&nd->last, nd->dentry, nd); + path.dentry = lookup_hash(nd); path.mnt = nd->mnt; __putname(nd->last.name); goto do_last; @@ -1697,7 +1697,7 @@ struct dentry *lookup_create(struct nameidata *nd, int is_dir) /* * Do the final lookup. */ - dentry = lookup_hash(&nd->last, nd->dentry); + dentry = lookup_hash(nd); if (IS_ERR(dentry)) goto fail; @@ -1932,7 +1932,7 @@ asmlinkage long sys_rmdir(const char __user * pathname) goto exit1; } down(&nd.dentry->d_inode->i_sem); - dentry = lookup_hash(&nd.last, nd.dentry); + dentry = lookup_hash(&nd); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { error = vfs_rmdir(nd.dentry->d_inode, dentry); @@ -2001,7 +2001,7 @@ asmlinkage long sys_unlink(const char __user * pathname) if (nd.last_type != LAST_NORM) goto exit1; down(&nd.dentry->d_inode->i_sem); - dentry = lookup_hash(&nd.last, nd.dentry); + dentry = lookup_hash(&nd); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { /* Why not before? Because we want correct error value */ @@ -2344,7 +2344,7 @@ static inline int do_rename(const char * oldname, const char * newname) trap = lock_rename(new_dir, old_dir); - old_dentry = lookup_hash(&oldnd.last, old_dir); + old_dentry = lookup_hash(&oldnd); error = PTR_ERR(old_dentry); if (IS_ERR(old_dentry)) goto exit3; @@ -2364,7 +2364,7 @@ static inline int do_rename(const char * oldname, const char * newname) error = -EINVAL; if (old_dentry == trap) goto exit4; - new_dentry = lookup_hash(&newnd.last, new_dir); + new_dentry = lookup_hash(&newnd); error = PTR_ERR(new_dentry); if (IS_ERR(new_dentry)) goto exit4; diff --git a/include/linux/namei.h b/include/linux/namei.h index 1c975d0d9e94..455660eafba9 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -74,7 +74,7 @@ extern struct file *nameidata_to_filp(struct nameidata *nd, int flags); extern void release_open_intent(struct nameidata *); extern struct dentry * lookup_one_len(const char *, struct dentry *, int); -extern struct dentry * lookup_hash(struct qstr *, struct dentry *); +extern struct dentry * lookup_hash(struct nameidata *); extern int follow_down(struct vfsmount **, struct dentry **); extern int follow_up(struct vfsmount **, struct dentry **); diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index 4f188d0a5d11..81e00a6c19de 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c @@ -603,7 +603,7 @@ rpc_lookup_negative(char *path, struct nameidata *nd) return ERR_PTR(error); dir = nd->dentry->d_inode; down(&dir->i_sem); - dentry = lookup_hash(&nd->last, nd->dentry); + dentry = lookup_hash(nd); if (IS_ERR(dentry)) goto out_err; if (dentry->d_inode) { @@ -665,7 +665,7 @@ rpc_rmdir(char *path) return error; dir = nd.dentry->d_inode; down(&dir->i_sem); - dentry = lookup_hash(&nd.last, nd.dentry); + dentry = lookup_hash(&nd); if (IS_ERR(dentry)) { error = PTR_ERR(dentry); goto out_release; @@ -726,7 +726,7 @@ rpc_unlink(char *path) return error; dir = nd.dentry->d_inode; down(&dir->i_sem); - dentry = lookup_hash(&nd.last, nd.dentry); + dentry = lookup_hash(&nd); if (IS_ERR(dentry)) { error = PTR_ERR(dentry); goto out_release; -- cgit v1.2.3 From b05a581d4865d74c0e270d27156a88d2dee9494e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Tue, 8 Nov 2005 21:35:08 -0800 Subject: [PATCH] move some COMPATIBLE_IOCTL entries from x86_64 to common code Signed-off-by: Christoph Hellwig Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/ia32/ia32_ioctl.c | 6 ------ include/linux/compat_ioctl.h | 8 ++++++++ 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'include/linux') diff --git a/arch/x86_64/ia32/ia32_ioctl.c b/arch/x86_64/ia32/ia32_ioctl.c index 4ba0e293d5e5..e335bd0b637d 100644 --- a/arch/x86_64/ia32/ia32_ioctl.c +++ b/arch/x86_64/ia32/ia32_ioctl.c @@ -64,12 +64,6 @@ struct ioctl_trans ioctl_start[] = { #include #define DECLARES #include "compat_ioctl.c" -COMPATIBLE_IOCTL(HDIO_SET_KEEPSETTINGS) -COMPATIBLE_IOCTL(HDIO_SCAN_HWIF) -COMPATIBLE_IOCTL(BLKRASET) -COMPATIBLE_IOCTL(0x4B50) /* KDGHWCLK - not in the kernel, but don't complain */ -COMPATIBLE_IOCTL(0x4B51) /* KDSHWCLK - not in the kernel, but don't complain */ -COMPATIBLE_IOCTL(FIOQSIZE) /* And these ioctls need translation */ /* realtime device */ diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h index ecb0d39c0798..4c63c2963019 100644 --- a/include/linux/compat_ioctl.h +++ b/include/linux/compat_ioctl.h @@ -10,6 +10,10 @@ #define ULONG_IOCTL(cmd) HANDLE_IOCTL((cmd),(ioctl_trans_handler_t)sys_ioctl) #endif + +COMPATIBLE_IOCTL(0x4B50) /* KDGHWCLK - not in the kernel, but don't complain */ +COMPATIBLE_IOCTL(0x4B51) /* KDSHWCLK - not in the kernel, but don't complain */ + /* Big T */ COMPATIBLE_IOCTL(TCGETA) COMPATIBLE_IOCTL(TCSETA) @@ -81,6 +85,8 @@ COMPATIBLE_IOCTL(HDIO_DRIVE_CMD) COMPATIBLE_IOCTL(HDIO_DRIVE_TASK) COMPATIBLE_IOCTL(HDIO_SET_PIO_MODE) COMPATIBLE_IOCTL(HDIO_SET_NICE) +COMPATIBLE_IOCTL(HDIO_SET_KEEPSETTINGS) +COMPATIBLE_IOCTL(HDIO_SCAN_HWIF) /* 0x02 -- Floppy ioctls */ COMPATIBLE_IOCTL(FDMSGON) COMPATIBLE_IOCTL(FDMSGOFF) @@ -99,6 +105,7 @@ COMPATIBLE_IOCTL(FDTWADDLE) COMPATIBLE_IOCTL(FDFMTTRK) COMPATIBLE_IOCTL(FDRAWCMD) /* 0x12 */ +COMPATIBLE_IOCTL(BLKRASET) COMPATIBLE_IOCTL(BLKROSET) COMPATIBLE_IOCTL(BLKROGET) COMPATIBLE_IOCTL(BLKRRPART) @@ -262,6 +269,7 @@ COMPATIBLE_IOCTL(RTC_WKALM_RD) /* Little m */ COMPATIBLE_IOCTL(MTIOCTOP) /* Socket level stuff */ +COMPATIBLE_IOCTL(FIOQSIZE) COMPATIBLE_IOCTL(FIOSETOWN) COMPATIBLE_IOCTL(SIOCSPGRP) COMPATIBLE_IOCTL(FIOGETOWN) -- cgit v1.2.3 From 299392bf2040fc53ebfc94363ac0abdd0f0bf619 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Tue, 8 Nov 2005 21:37:42 -0800 Subject: [PATCH] v4l: 798: this patch adds the vidioc log status to videodev2 h and adds - This patch adds the VIDIOC_LOG_STATUS to videodev2.h and adds LOG_STATUS support to tda9887.c and bttv-driver.c. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bttv-driver.c | 6 ++++++ drivers/media/video/tda9887.c | 29 +++++++++++++++++------------ include/linux/videodev2.h | 1 + 3 files changed, 24 insertions(+), 12 deletions(-) (limited to 'include/linux') diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index 058b923b4b13..f8307407e320 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -1851,6 +1851,11 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) up(&btv->lock); return 0; } + case VIDIOC_LOG_STATUS: + { + bttv_call_i2c_clients(btv, VIDIOC_LOG_STATUS, 0); + return 0; + } default: return -ENOIOCTLCMD; @@ -2856,6 +2861,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, case VIDIOC_S_TUNER: case VIDIOC_G_FREQUENCY: case VIDIOC_S_FREQUENCY: + case VIDIOC_LOG_STATUS: return bttv_common_ioctls(btv,cmd,arg); default: diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 796110d4ff72..6d2914f738f2 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -60,6 +60,7 @@ struct tda9887 { unsigned int pinnacle_id; unsigned int using_v4l2; unsigned int radio_mode; + unsigned char data[4]; }; struct tvnorm { @@ -575,32 +576,31 @@ static int tda9887_status(struct tda9887 *t) static int tda9887_configure(struct tda9887 *t) { - unsigned char buf[4]; int rc; - memset(buf,0,sizeof(buf)); - tda9887_set_tvnorm(t,buf); + memset(t->data,0,sizeof(t->data)); + tda9887_set_tvnorm(t,t->data); - buf[1] |= cOutputPort1Inactive; - buf[1] |= cOutputPort2Inactive; + t->data[1] |= cOutputPort1Inactive; + t->data[1] |= cOutputPort2Inactive; if (UNSET != t->pinnacle_id) { - tda9887_set_pinnacle(t,buf); + tda9887_set_pinnacle(t,t->data); } - tda9887_set_config(t,buf); - tda9887_set_insmod(t,buf); + tda9887_set_config(t,t->data); + tda9887_set_insmod(t,t->data); if (t->mode == T_STANDBY) { - buf[1] |= cForcedMuteAudioON; + t->data[1] |= cForcedMuteAudioON; } tda9887_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n", - buf[1],buf[2],buf[3]); + t->data[1],t->data[2],t->data[3]); if (debug > 1) - dump_write_message(t, buf); + dump_write_message(t, t->data); - if (4 != (rc = i2c_master_send(&t->client,buf,4))) + if (4 != (rc = i2c_master_send(&t->client,t->data,4))) tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc); if (debug > 2) { @@ -785,6 +785,11 @@ tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) } break; } + case VIDIOC_LOG_STATUS: + { + tda9887_info("Data bytes: b=%02x c=%02x e=%02x\n", t->data[1], t->data[2], t->data[3]); + break; + } default: /* nothing */ break; diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 89a055761bed..27979003db44 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -981,6 +981,7 @@ struct v4l2_streamparm #if 1 #define VIDIOC_G_SLICED_VBI_CAP _IOR ('V', 69, struct v4l2_sliced_vbi_cap) #endif +#define VIDIOC_LOG_STATUS _IO ('V', 70) /* for compatibility, will go away some day */ #define VIDIOC_OVERLAY_OLD _IOWR ('V', 14, int) -- cgit v1.2.3 From 4ac97914c6c35f6bf132071c718e034d0846b9f5 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:43 -0800 Subject: [PATCH] v4l: 800: whitespace cleanups - Whitespace Cleanups. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/README.cx88 | 6 +- Documentation/video4linux/bttv/Cards | 18 +- Documentation/video4linux/bttv/README | 6 +- Documentation/video4linux/bttv/Sound-FAQ | 6 +- Documentation/video4linux/lifeview.txt | 58 +-- drivers/media/common/ir-common.c | 4 +- drivers/media/video/bt832.c | 88 ++--- drivers/media/video/bt832.h | 4 +- drivers/media/video/bttv-cards.c | 260 ++++++------- drivers/media/video/bttv-driver.c | 342 ++++++++--------- drivers/media/video/bttv-gpio.c | 2 +- drivers/media/video/bttv-i2c.c | 42 +-- drivers/media/video/bttv-if.c | 4 +- drivers/media/video/bttv-risc.c | 110 +++--- drivers/media/video/bttv.h | 20 +- drivers/media/video/bttvp.h | 14 +- drivers/media/video/cx88/cx88-blackbird.c | 40 +- drivers/media/video/cx88/cx88-cards.c | 340 ++++++++--------- drivers/media/video/cx88/cx88-core.c | 40 +- drivers/media/video/cx88/cx88-dvb.c | 16 +- drivers/media/video/cx88/cx88-i2c.c | 22 +- drivers/media/video/cx88/cx88-input.c | 2 +- drivers/media/video/cx88/cx88-mpeg.c | 18 +- drivers/media/video/cx88/cx88-reg.h | 12 +- drivers/media/video/cx88/cx88-video.c | 22 +- drivers/media/video/cx88/cx88.h | 4 +- drivers/media/video/em28xx/em28xx-cards.c | 4 +- drivers/media/video/em28xx/em28xx-core.c | 28 +- drivers/media/video/em28xx/em28xx-i2c.c | 4 +- drivers/media/video/em28xx/em28xx-input.c | 52 +-- drivers/media/video/em28xx/em28xx-video.c | 10 +- drivers/media/video/em28xx/em28xx.h | 12 +- drivers/media/video/ir-kbd-gpio.c | 4 +- drivers/media/video/ir-kbd-i2c.c | 22 +- drivers/media/video/msp3400.c | 62 ++-- drivers/media/video/mt20xx.c | 204 +++++------ drivers/media/video/saa711x.c | 4 +- drivers/media/video/saa7134/saa6752hs.c | 62 ++-- drivers/media/video/saa7134/saa7134-alsa.c | 504 +++++++++++++------------- drivers/media/video/saa7134/saa7134-cards.c | 314 ++++++++-------- drivers/media/video/saa7134/saa7134-core.c | 38 +- drivers/media/video/saa7134/saa7134-dvb.c | 4 +- drivers/media/video/saa7134/saa7134-empress.c | 6 +- drivers/media/video/saa7134/saa7134-i2c.c | 14 +- drivers/media/video/saa7134/saa7134-input.c | 100 ++--- drivers/media/video/saa7134/saa7134-oss.c | 68 ++-- drivers/media/video/saa7134/saa7134-reg.h | 18 +- drivers/media/video/saa7134/saa7134-ts.c | 4 +- drivers/media/video/saa7134/saa7134-tvaudio.c | 12 +- drivers/media/video/saa7134/saa7134-video.c | 106 +++--- drivers/media/video/saa7134/saa7134.h | 12 +- drivers/media/video/tda7432.c | 16 +- drivers/media/video/tda8290.c | 2 +- drivers/media/video/tda9875.c | 56 +-- drivers/media/video/tda9887.c | 36 +- drivers/media/video/tea5767.c | 8 +- drivers/media/video/tuner-core.c | 30 +- drivers/media/video/tuner-simple.c | 106 +++--- drivers/media/video/tvaudio.c | 20 +- drivers/media/video/tveeprom.c | 20 +- drivers/media/video/tvmixer.c | 54 +-- drivers/media/video/v4l1-compat.c | 2 +- drivers/media/video/video-buf.c | 18 +- drivers/media/video/wm8775.c | 4 +- include/linux/videodev.h | 6 +- include/linux/videodev2.h | 118 +++--- include/media/audiochip.h | 14 +- include/media/tuner.h | 8 +- include/media/video-buf.h | 2 +- 69 files changed, 1844 insertions(+), 1844 deletions(-) (limited to 'include/linux') diff --git a/Documentation/video4linux/README.cx88 b/Documentation/video4linux/README.cx88 index 0b93455bbc17..06a33a4f52fd 100644 --- a/Documentation/video4linux/README.cx88 +++ b/Documentation/video4linux/README.cx88 @@ -17,9 +17,9 @@ audio - The chip specs for the on-chip TV sound decoder are next to useless :-/ - Neverless the builtin TV sound decoder starts working now, - at least for PAL-BG. Other TV norms need other code ... - FOR ANY REPORTS ON THIS PLEASE MENTION THE TV NORM YOU ARE - USING. + at least for PAL-BG. Other TV norms need other code ... + FOR ANY REPORTS ON THIS PLEASE MENTION THE TV NORM YOU ARE + USING. - Most tuner chips do provide mono sound, which may or may not be useable depending on the board design. With the Hauppauge cards it works, so there is mono sound available as fallback. diff --git a/Documentation/video4linux/bttv/Cards b/Documentation/video4linux/bttv/Cards index 8f1941ede4da..d3389655ad96 100644 --- a/Documentation/video4linux/bttv/Cards +++ b/Documentation/video4linux/bttv/Cards @@ -149,11 +149,11 @@ Lifeview Flyvideo Series: 2) There is a print on the PCB: LR25 = Flyvideo (Zoran ZR36120, SAA7110A) LR26 Rev.N = Flyvideo II (Bt848) - Rev.O = Flyvideo II (Bt878) + Rev.O = Flyvideo II (Bt878) LR37 Rev.C = Flyvideo EZ (Capture only, ZR36120 + SAA7110) LR38 Rev.A1= Flyvideo II EZ (Bt848 capture only) LR50 Rev.Q = Flyvideo 98 (w/eeprom and PCI subsystem ID) - Rev.W = Flyvideo 98 (no eeprom) + Rev.W = Flyvideo 98 (no eeprom) LR51 Rev.E = Flyvideo 98 EZ (capture only) LR90 = Flyvideo 2000 (Bt878) Flyvideo 2000S (Bt878) w/Stereo TV (Package incl. LR91 daughterboard) @@ -163,7 +163,7 @@ Lifeview Flyvideo Series: LR136 = Flyvideo 2100/3100 (Low profile, SAA7130/SAA7134) LR137 = Flyvideo DV2000/DV3000 (SAA7130/SAA7134 + IEEE1394) LR138 Rev.C= Flyvideo 2000 (SAA7130) - or Flyvideo 3000 (SAA7134) w/Stereo TV + or Flyvideo 3000 (SAA7134) w/Stereo TV These exist in variations w/FM and w/Remote sometimes denoted by suffixes "FM" and "R". 3) You have a laptop (miniPCI card): @@ -197,7 +197,7 @@ Typhoon TV card series: 50680 "TV Tuner Pal BG" (blue package)= Pixelview PV-BT878P+ (Rev 9B) 50681 "TV Tuner PCI Pal I" (variant of 50680) 50682 "TView TV/FM Tuner Pal BG" = Flyvideo 98FM (LR50 Rev.Q) - Note: The package has a picture of CPH05x (which would be a real TView) + Note: The package has a picture of CPH05x (which would be a real TView) 50683 "TV Tuner PCI SECAM" (variant of 50680) 50684 "TV Tuner Pal BG" = Pixelview 878TV(Rev.3D) 50686 "TV Tuner" = KNC1 TV Station @@ -418,9 +418,9 @@ Lifetec/Medion/Tevion/Aldi -------------------------- LT9306/MD9306 = CPH061 LT9415/MD9415 = LR90 Rev.F or Rev.G - MD9592 = Avermedia TVphone98 (PCI_ID=1461:0003), PCB-Rev=M168II-B (w/TDA9873H) - MD9717 = KNC One (Rev D4, saa7134, FM1216 MK2 tuner) - MD5044 = KNC One (Rev D4, saa7134, FM1216ME MK3 tuner) + MD9592 = Avermedia TVphone98 (PCI_ID=1461:0003), PCB-Rev=M168II-B (w/TDA9873H) + MD9717 = KNC One (Rev D4, saa7134, FM1216 MK2 tuner) + MD5044 = KNC One (Rev D4, saa7134, FM1216ME MK3 tuner) Modular Technologies (www.modulartech.com) UK --------------------------------------------- @@ -453,10 +453,10 @@ Technisat Discos ADR PC-Karte ISA (no TV!) Discos ADR PC-Karte PCI (probably no TV?) Techni-PC-Sat (Sat. analog) - Rev 1.2 (zr36120, vpx3220, stv0030, saa5246, BSJE3-494A) + Rev 1.2 (zr36120, vpx3220, stv0030, saa5246, BSJE3-494A) Mediafocus I (zr36120/zr36125, drp3510, Sat. analog + ADR Radio) Mediafocus II (saa7146, Sat. analog) - SatADR Rev 2.1 (saa7146a, saa7113h, stv0056a, msp3400c, drp3510a, BSKE3-307A) + SatADR Rev 2.1 (saa7146a, saa7113h, stv0056a, msp3400c, drp3510a, BSKE3-307A) SkyStar 1 DVB (AV7110) = Technotrend Premium SkyStar 2 DVB (B2C2) (=Sky2PC) diff --git a/Documentation/video4linux/bttv/README b/Documentation/video4linux/bttv/README index a72f4c94fb0b..7ca2154c2bf5 100644 --- a/Documentation/video4linux/bttv/README +++ b/Documentation/video4linux/bttv/README @@ -42,9 +42,9 @@ bttv uses the PCI Subsystem ID to autodetect the card type. lspci lists the Subsystem ID in the second line, looks like this: 00:0a.0 Multimedia video controller: Brooktree Corporation Bt878 (rev 02) - Subsystem: Hauppauge computer works Inc. WinTV/GO - Flags: bus master, medium devsel, latency 32, IRQ 5 - Memory at e2000000 (32-bit, prefetchable) [size=4K] + Subsystem: Hauppauge computer works Inc. WinTV/GO + Flags: bus master, medium devsel, latency 32, IRQ 5 + Memory at e2000000 (32-bit, prefetchable) [size=4K] only bt878-based cards can have a subsystem ID (which does not mean that every card really has one). bt848 cards can't have a Subsystem diff --git a/Documentation/video4linux/bttv/Sound-FAQ b/Documentation/video4linux/bttv/Sound-FAQ index 5c9822492034..1e6328f91083 100644 --- a/Documentation/video4linux/bttv/Sound-FAQ +++ b/Documentation/video4linux/bttv/Sound-FAQ @@ -61,8 +61,8 @@ line for your board. The important fields are these two: struct tvcard { [ ... ] - u32 gpiomask; - u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */ + u32 gpiomask; + u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */ }; gpiomask specifies which pins are used to control the audio mux chip. @@ -126,7 +126,7 @@ muxsel - video mux, input->registervalue mapping pll - same as pll= insmod option tuner_type - same as tuner= insmod option *_modulename - hint whenever some card needs this or that audio - module loaded to work properly. + module loaded to work properly. has_radio - whenever this TV card has a radio tuner. no_msp34xx - "1" disables loading of msp3400.o module no_tda9875 - "1" disables loading of tda9875.o module diff --git a/Documentation/video4linux/lifeview.txt b/Documentation/video4linux/lifeview.txt index b07ea79c2b7e..f66320bd7b67 100644 --- a/Documentation/video4linux/lifeview.txt +++ b/Documentation/video4linux/lifeview.txt @@ -10,33 +10,33 @@ bt878: ------------------------------------------------------------------------------ saa7134: - /* LifeView FlyTV Platinum FM (LR214WF) */ - /* "Peter Missel */ - .name = "LifeView FlyTV Platinum FM", - /* GP27 MDT2005 PB4 pin 10 */ - /* GP26 MDT2005 PB3 pin 9 */ - /* GP25 MDT2005 PB2 pin 8 */ - /* GP23 MDT2005 PB1 pin 7 */ - /* GP22 MDT2005 PB0 pin 6 */ - /* GP21 MDT2005 PB5 pin 11 */ - /* GP20 MDT2005 PB6 pin 12 */ - /* GP19 MDT2005 PB7 pin 13 */ - /* nc MDT2005 PA3 pin 2 */ - /* Remote MDT2005 PA2 pin 1 */ - /* GP18 MDT2005 PA1 pin 18 */ - /* nc MDT2005 PA0 pin 17 strap low */ + /* LifeView FlyTV Platinum FM (LR214WF) */ + /* "Peter Missel */ + .name = "LifeView FlyTV Platinum FM", + /* GP27 MDT2005 PB4 pin 10 */ + /* GP26 MDT2005 PB3 pin 9 */ + /* GP25 MDT2005 PB2 pin 8 */ + /* GP23 MDT2005 PB1 pin 7 */ + /* GP22 MDT2005 PB0 pin 6 */ + /* GP21 MDT2005 PB5 pin 11 */ + /* GP20 MDT2005 PB6 pin 12 */ + /* GP19 MDT2005 PB7 pin 13 */ + /* nc MDT2005 PA3 pin 2 */ + /* Remote MDT2005 PA2 pin 1 */ + /* GP18 MDT2005 PA1 pin 18 */ + /* nc MDT2005 PA0 pin 17 strap low */ - /* GP17 Strap "GP7"=High */ - /* GP16 Strap "GP6"=High - 0=Radio 1=TV - Drives SA630D ENCH1 and HEF4052 A1 pins - to do FM radio through SIF input */ - /* GP15 nc */ - /* GP14 nc */ - /* GP13 nc */ - /* GP12 Strap "GP5" = High */ - /* GP11 Strap "GP4" = High */ - /* GP10 Strap "GP3" = High */ - /* GP09 Strap "GP2" = Low */ - /* GP08 Strap "GP1" = Low */ - /* GP07.00 nc */ + /* GP17 Strap "GP7"=High */ + /* GP16 Strap "GP6"=High + 0=Radio 1=TV + Drives SA630D ENCH1 and HEF4052 A1 pins + to do FM radio through SIF input */ + /* GP15 nc */ + /* GP14 nc */ + /* GP13 nc */ + /* GP12 Strap "GP5" = High */ + /* GP11 Strap "GP4" = High */ + /* GP10 Strap "GP3" = High */ + /* GP09 Strap "GP2" = Low */ + /* GP08 Strap "GP1" = Low */ + /* GP07.00 nc */ diff --git a/drivers/media/common/ir-common.c b/drivers/media/common/ir-common.c index 31fccb4f05d6..4b71fd6f7aed 100644 --- a/drivers/media/common/ir-common.c +++ b/drivers/media/common/ir-common.c @@ -116,7 +116,7 @@ IR_KEYTAB_TYPE ir_codes_winfast[IR_KEYTAB_SIZE] = { [ 46 ] = KEY_BLUE, [ 24 ] = KEY_KPPLUS, /* fine tune + */ [ 25 ] = KEY_KPMINUS, /* fine tune - */ - [ 33 ] = KEY_KPDOT, + [ 33 ] = KEY_KPDOT, [ 19 ] = KEY_KPENTER, [ 34 ] = KEY_BACK, [ 35 ] = KEY_PLAYPAUSE, @@ -239,7 +239,7 @@ static void ir_input_key_event(struct input_dev *dev, struct ir_input_state *ir) dprintk(1,"%s: key event code=%d down=%d\n", dev->name,ir->keycode,ir->keypressed); input_report_key(dev,ir->keycode,ir->keypressed); - input_sync(dev); + input_sync(dev); } /* -------------------------------------------------------------------------- */ diff --git a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c index 76c1b63ebdf2..3e42493a4e0a 100644 --- a/drivers/media/video/bt832.c +++ b/drivers/media/video/bt832.c @@ -54,36 +54,36 @@ static struct i2c_driver driver; static struct i2c_client client_template; struct bt832 { - struct i2c_client client; + struct i2c_client client; }; int bt832_hexdump(struct i2c_client *i2c_client_s, unsigned char *buf) { int i,rc; buf[0]=0x80; // start at register 0 with auto-increment - if (1 != (rc = i2c_master_send(i2c_client_s,buf,1))) - printk("bt832: i2c i/o error: rc == %d (should be 1)\n",rc); + if (1 != (rc = i2c_master_send(i2c_client_s,buf,1))) + printk("bt832: i2c i/o error: rc == %d (should be 1)\n",rc); - for(i=0;i<65;i++) - buf[i]=0; - if (65 != (rc=i2c_master_recv(i2c_client_s,buf,65))) - printk("bt832: i2c i/o error: rc == %d (should be 65)\n",rc); + for(i=0;i<65;i++) + buf[i]=0; + if (65 != (rc=i2c_master_recv(i2c_client_s,buf,65))) + printk("bt832: i2c i/o error: rc == %d (should be 65)\n",rc); - // Note: On READ the first byte is the current index - // (e.g. 0x80, what we just wrote) + // Note: On READ the first byte is the current index + // (e.g. 0x80, what we just wrote) - if(1) { - int i; - printk("BT832 hexdump:\n"); - for(i=1;i<65;i++) { + if(1) { + int i; + printk("BT832 hexdump:\n"); + for(i=1;i<65;i++) { if(i!=1) { if(((i-1)%8)==0) printk(" "); - if(((i-1)%16)==0) printk("\n"); + if(((i-1)%16)==0) printk("\n"); } - printk(" %02x",buf[i]); - } - printk("\n"); - } + printk(" %02x",buf[i]); + } + printk("\n"); + } return 0; } @@ -102,13 +102,13 @@ int bt832_init(struct i2c_client *i2c_client_s) return 0; } - printk("Write 0 tp VPSTATUS\n"); - buf[0]=BT832_VP_STATUS; // Reg.52 - buf[1]= 0x00; - if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - printk("bt832: i2c i/o error VPS: rc == %d (should be 2)\n",rc); + printk("Write 0 tp VPSTATUS\n"); + buf[0]=BT832_VP_STATUS; // Reg.52 + buf[1]= 0x00; + if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) + printk("bt832: i2c i/o error VPS: rc == %d (should be 2)\n",rc); - bt832_hexdump(i2c_client_s,buf); + bt832_hexdump(i2c_client_s,buf); // Leave low power mode: @@ -116,17 +116,17 @@ int bt832_init(struct i2c_client *i2c_client_s) buf[0]=BT832_CAM_SETUP0; //0x39 57 buf[1]=0x08; if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - printk("bt832: i2c i/o error LLPM: rc == %d (should be 2)\n",rc); + printk("bt832: i2c i/o error LLPM: rc == %d (should be 2)\n",rc); - bt832_hexdump(i2c_client_s,buf); + bt832_hexdump(i2c_client_s,buf); printk("Write 0 tp VPSTATUS\n"); - buf[0]=BT832_VP_STATUS; // Reg.52 - buf[1]= 0x00; - if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - printk("bt832: i2c i/o error VPS: rc == %d (should be 2)\n",rc); + buf[0]=BT832_VP_STATUS; // Reg.52 + buf[1]= 0x00; + if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) + printk("bt832: i2c i/o error VPS: rc == %d (should be 2)\n",rc); - bt832_hexdump(i2c_client_s,buf); + bt832_hexdump(i2c_client_s,buf); // Enable Output @@ -134,22 +134,22 @@ int bt832_init(struct i2c_client *i2c_client_s) buf[0]=BT832_VP_CONTROL1; // Reg.40 buf[1]= 0x27 & (~0x01); // Default | !skip if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - printk("bt832: i2c i/o error EO: rc == %d (should be 2)\n",rc); + printk("bt832: i2c i/o error EO: rc == %d (should be 2)\n",rc); - bt832_hexdump(i2c_client_s,buf); + bt832_hexdump(i2c_client_s,buf); // for testing (even works when no camera attached) printk("bt832: *** Generate NTSC M Bars *****\n"); buf[0]=BT832_VP_TESTCONTROL0; // Reg. 42 buf[1]=3; // Generate NTSC System M bars, Generate Frame timing internally - if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) - printk("bt832: i2c i/o error MBAR: rc == %d (should be 2)\n",rc); + if (2 != (rc = i2c_master_send(i2c_client_s,buf,2))) + printk("bt832: i2c i/o error MBAR: rc == %d (should be 2)\n",rc); printk("Bt832: Camera Present: %s\n", (buf[1+BT832_CAM_STATUS] & BT832_56_CAMERA_PRESENT) ? "yes":"no"); - bt832_hexdump(i2c_client_s,buf); + bt832_hexdump(i2c_client_s,buf); kfree(buf); return 1; } @@ -162,17 +162,17 @@ static int bt832_attach(struct i2c_adapter *adap, int addr, int kind) printk("bt832_attach\n"); - client_template.adapter = adap; - client_template.addr = addr; + client_template.adapter = adap; + client_template.addr = addr; - printk("bt832: chip found @ 0x%x\n", addr<<1); + printk("bt832: chip found @ 0x%x\n", addr<<1); - if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL))) - return -ENOMEM; + if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL))) + return -ENOMEM; memset(t,0,sizeof(*t)); t->client = client_template; - i2c_set_clientdata(&t->client, t); - i2c_attach_client(&t->client); + i2c_set_clientdata(&t->client, t); + i2c_attach_client(&t->client); if(! bt832_init(&t->client)) { bt832_detach(&t->client); @@ -211,7 +211,7 @@ bt832_command(struct i2c_client *client, unsigned int cmd, void *arg) printk("bt832: command %x\n",cmd); - switch (cmd) { + switch (cmd) { case BT832_HEXDUMP: { unsigned char *buf; buf=kmalloc(65,GFP_KERNEL); diff --git a/drivers/media/video/bt832.h b/drivers/media/video/bt832.h index 9b6a8d2c96b5..1ce8fa71f7db 100644 --- a/drivers/media/video/bt832.h +++ b/drivers/media/video/bt832.h @@ -233,8 +233,8 @@ SetInterlaceMode( spec.interlace ); /* from web: Video Sampling Digital video is a sampled form of analog video. The most common sampling schemes in use today are: - Pixel Clock Horiz Horiz Vert - Rate Total Active + Pixel Clock Horiz Horiz Vert + Rate Total Active NTSC square pixel 12.27 MHz 780 640 525 NTSC CCIR-601 13.5 MHz 858 720 525 NTSC 4FSc 14.32 MHz 910 768 525 diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 3937da065e4f..92bb515fbe4d 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -6,7 +6,7 @@ like the big tvcards array for the most part Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) (c) 1999-2001 Gerd Knorr This program is free software; you can redistribute it and/or modify @@ -163,10 +163,10 @@ static struct CARD { { 0x6609107d, BTTV_BOARD_WINFAST2000, "Leadtek TV 2000 XP" }, { 0x263610b4, BTTV_BOARD_STB2, "STB TV PCI FM, Gateway P/N 6000704" }, { 0x264510b4, BTTV_BOARD_STB2, "STB TV PCI FM, Gateway P/N 6000704" }, - { 0x402010fc, BTTV_BOARD_GVBCTV3PCI, "I-O Data Co. GV-BCTV3/PCI" }, + { 0x402010fc, BTTV_BOARD_GVBCTV3PCI, "I-O Data Co. GV-BCTV3/PCI" }, { 0x405010fc, BTTV_BOARD_GVBCTV4PCI, "I-O Data Co. GV-BCTV4/PCI" }, { 0x407010fc, BTTV_BOARD_GVBCTV5PCI, "I-O Data Co. GV-BCTV5/PCI" }, - { 0xd01810fc, BTTV_BOARD_GVBCTV5PCI, "I-O Data Co. GV-BCTV5/PCI" }, + { 0xd01810fc, BTTV_BOARD_GVBCTV5PCI, "I-O Data Co. GV-BCTV5/PCI" }, { 0x001211bd, BTTV_BOARD_PINNACLE, "Pinnacle PCTV" }, /* some cards ship with byteswapped IDs ... */ @@ -277,7 +277,7 @@ static struct CARD { { 0x20007063, BTTV_BOARD_PC_HDTV, "pcHDTV HD-2000 TV"}, { 0x82b2aa6a, BTTV_BOARD_SIMUS_GVC1100, "SIMUS GVC1100" }, { 0x146caa0c, BTTV_BOARD_PV951, "ituner spectra8" }, - { 0x200a1295, BTTV_BOARD_PXC200, "ImageNation PXC200A" }, + { 0x200a1295, BTTV_BOARD_PXC200, "ImageNation PXC200A" }, { 0x40111554, BTTV_BOARD_PV_BT878P_9B, "Prolink Pixelview PV-BT" }, { 0x17de0a01, BTTV_BOARD_KWORLD, "Mecer TV/FM/Video Tuner" }, @@ -1346,17 +1346,17 @@ struct tvcard bttv_tvcards[] = { }, [BTTV_BOARD_GMV1] = { /* Adrian Cox c.type = type; @@ -2929,7 +2929,7 @@ static void flyvideo_gpio(struct bttv *btv) switch(ttype) { case 0x0: tuner=2; /* NTSC, e.g. TPI8NSR11P */ break; - case 0x2: tuner=39;/* LG NTSC (newer TAPC series) TAPC-H701P */ + case 0x2: tuner=39;/* LG NTSC (newer TAPC series) TAPC-H701P */ break; case 0x4: tuner=5; /* Philips PAL TPI8PSB02P, TPI8PSB12P, TPI8PSB12D or FI1216, FM1216 */ break; @@ -2945,7 +2945,7 @@ static void flyvideo_gpio(struct bttv *btv) has_radio = gpio & 0x400000; /* unknown 0x200000; * unknown2 0x100000; */ - is_capture_only = !(gpio & 0x008000); /* GPIO15 */ + is_capture_only = !(gpio & 0x008000); /* GPIO15 */ has_tda9820_tda9821 = !(gpio & 0x004000); is_lr90 = !(gpio & 0x002000); /* else LR26/LR50 (LR38/LR51 f. capture only) */ /* @@ -2982,7 +2982,7 @@ static void miro_pinnacle_gpio(struct bttv *btv) char *info; gpio_inout(0xffffff, 0); - gpio = gpio_read(); + gpio = gpio_read(); id = ((gpio>>10) & 63) -1; msp = bttv_I2CRead(btv, I2C_MSP3400, "MSP34xx"); if (id < 32) { @@ -3093,7 +3093,7 @@ static void eagle_muxsel(struct bttv *btv, unsigned int input) static void gvc1100_muxsel(struct bttv *btv, unsigned int input) { - static const int masks[] = {0x30, 0x01, 0x12, 0x23}; + static const int masks[] = {0x30, 0x01, 0x12, 0x23}; gpio_write(masks[input%4]); } @@ -3161,10 +3161,10 @@ void __devinit bttv_init_card1(struct bttv *btv) switch (btv->c.type) { case BTTV_BOARD_HAUPPAUGE: case BTTV_BOARD_HAUPPAUGE878: - boot_msp34xx(btv,5); + boot_msp34xx(btv,5); break; case BTTV_BOARD_VOODOOTV_FM: - boot_msp34xx(btv,20); + boot_msp34xx(btv,20); break; case BTTV_BOARD_AVERMEDIA98: boot_msp34xx(btv,11); @@ -3192,7 +3192,7 @@ void __devinit bttv_init_card2(struct bttv *btv) int tda9887; int addr=ADDR_UNSET, radio_addr=ADDR_UNSET; - btv->tuner_type = -1; + btv->tuner_type = -1; if (BTTV_BOARD_UNKNOWN == btv->c.type) { bttv_readee(btv,eeprom_data,0xa0); @@ -3225,7 +3225,7 @@ void __devinit bttv_init_card2(struct bttv *btv) case BTTV_BOARD_HAUPPAUGEPVR: /* pick up some config infos from the eeprom */ bttv_readee(btv,eeprom_data,0xa0); - hauppauge_eeprom(btv); + hauppauge_eeprom(btv); break; case BTTV_BOARD_AVERMEDIA98: case BTTV_BOARD_AVPHONE98: @@ -3258,7 +3258,7 @@ void __devinit bttv_init_card2(struct bttv *btv) } break; case BTTV_BOARD_STB2: - if (btv->cardid == 0x3060121a) { + if (btv->cardid == 0x3060121a) { /* Fix up entry for 3DFX VoodooTV 100, which is an OEM STB card variant. */ btv->has_radio=0; @@ -3277,7 +3277,7 @@ void __devinit bttv_init_card2(struct bttv *btv) case BTTV_BOARD_OSPREY540: case BTTV_BOARD_OSPREY2000: bttv_readee(btv,eeprom_data,0xa0); - osprey_eeprom(btv); + osprey_eeprom(btv); break; case BTTV_BOARD_IDS_EAGLE: init_ids_eagle(btv); @@ -3298,7 +3298,7 @@ void __devinit bttv_init_card2(struct bttv *btv) } /* pll configuration */ - if (!(btv->id==848 && btv->revision==0x11)) { + if (!(btv->id==848 && btv->revision==0x11)) { /* defaults from card list */ if (PLL_28 == bttv_tvcards[btv->c.type].pll) { btv->pll.pll_ifreq=28636363; @@ -3309,26 +3309,26 @@ void __devinit bttv_init_card2(struct bttv *btv) btv->pll.pll_crystal=BT848_IFORM_XT1; } /* insmod options can override */ - switch (pll[btv->c.nr]) { - case 0: /* none */ + switch (pll[btv->c.nr]) { + case 0: /* none */ btv->pll.pll_crystal = 0; btv->pll.pll_ifreq = 0; btv->pll.pll_ofreq = 0; - break; - case 1: /* 28 MHz */ + break; + case 1: /* 28 MHz */ case 28: - btv->pll.pll_ifreq = 28636363; + btv->pll.pll_ifreq = 28636363; btv->pll.pll_ofreq = 0; - btv->pll.pll_crystal = BT848_IFORM_XT0; - break; - case 2: /* 35 MHz */ + btv->pll.pll_crystal = BT848_IFORM_XT0; + break; + case 2: /* 35 MHz */ case 35: - btv->pll.pll_ifreq = 35468950; + btv->pll.pll_ifreq = 35468950; btv->pll.pll_ofreq = 0; - btv->pll.pll_crystal = BT848_IFORM_XT1; - break; - } - } + btv->pll.pll_crystal = BT848_IFORM_XT1; + break; + } + } btv->pll.pll_current = -1; /* tuner configuration (from card list / autodetect / insmod option) */ @@ -3340,7 +3340,7 @@ void __devinit bttv_init_card2(struct bttv *btv) if (UNSET != bttv_tvcards[btv->c.type].tuner_type) if(UNSET == btv->tuner_type) - btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type; + btv->tuner_type = bttv_tvcards[btv->c.type].tuner_type; if (UNSET != tuner[btv->c.nr]) btv->tuner_type = tuner[btv->c.nr]; printk("bttv%d: using tuner=%d\n",btv->c.nr,btv->tuner_type); @@ -3348,14 +3348,14 @@ void __devinit bttv_init_card2(struct bttv *btv) bttv_call_i2c_clients(btv, AUDC_CONFIG_PINNACLE, &btv->pinnacle_id); if (btv->tuner_type != UNSET) { - struct tuner_setup tun_setup; + struct tuner_setup tun_setup; - tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; + tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV; tun_setup.type = btv->tuner_type; tun_setup.addr = addr; if (addr == radio_addr) - tun_setup.mode_mask = T_RADIO; + tun_setup.mode_mask = T_RADIO; bttv_call_i2c_clients(btv, TUNER_SET_TYPE_ADDR, &tun_setup); } @@ -3433,11 +3433,11 @@ static void modtec_eeprom(struct bttv *btv) } else if (strncmp(&(eeprom_data[0x1e]),"Alps TSBB5",10) ==0) { btv->tuner_type=TUNER_ALPS_TSBB5_PAL_I; printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n", - btv->c.nr,&eeprom_data[0x1e]); - } else if (strncmp(&(eeprom_data[0x1e]),"Philips FM1246",14) ==0) { - btv->tuner_type=TUNER_PHILIPS_NTSC; - printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n", - btv->c.nr,&eeprom_data[0x1e]); + btv->c.nr,&eeprom_data[0x1e]); + } else if (strncmp(&(eeprom_data[0x1e]),"Philips FM1246",14) ==0) { + btv->tuner_type=TUNER_PHILIPS_NTSC; + printk("bttv%d: Modtec: Tuner autodetected by eeprom: %s\n", + btv->c.nr,&eeprom_data[0x1e]); } else { printk("bttv%d: Modtec: Unknown TunerString: %s\n", btv->c.nr,&eeprom_data[0x1e]); @@ -3502,7 +3502,7 @@ static int terratec_active_radio_upgrade(struct bttv *btv) static int __devinit pvr_altera_load(struct bttv *btv, u8 *micro, u32 microlen) { u32 n; - u8 bits; + u8 bits; int i; gpio_inout(0xffffff,BTTV_ALT_DATA|BTTV_ALT_DCLK|BTTV_ALT_NCONFIG); @@ -3538,19 +3538,19 @@ static int __devinit pvr_altera_load(struct bttv *btv, u8 *micro, u32 microlen) static int __devinit pvr_boot(struct bttv *btv) { - const struct firmware *fw_entry; + const struct firmware *fw_entry; int rc; rc = request_firmware(&fw_entry, "hcwamc.rbf", &btv->c.pci->dev); if (rc != 0) { printk(KERN_WARNING "bttv%d: no altera firmware [via hotplug]\n", btv->c.nr); - return rc; - } + return rc; + } rc = pvr_altera_load(btv, fw_entry->data, fw_entry->size); printk(KERN_INFO "bttv%d: altera firmware upload %s\n", btv->c.nr, (rc < 0) ? "failed" : "ok"); - release_firmware(fw_entry); + release_firmware(fw_entry); return rc; } @@ -3564,33 +3564,33 @@ static void __devinit osprey_eeprom(struct bttv *btv) unsigned long serial = 0; if (btv->c.type == 0) { - /* this might be an antique... check for MMAC label in eeprom */ - if ((ee[0]=='M') && (ee[1]=='M') && (ee[2]=='A') && (ee[3]=='C')) { - unsigned char checksum = 0; - for (i =0; i<21; i++) + /* this might be an antique... check for MMAC label in eeprom */ + if ((ee[0]=='M') && (ee[1]=='M') && (ee[2]=='A') && (ee[3]=='C')) { + unsigned char checksum = 0; + for (i =0; i<21; i++) checksum += ee[i]; - if (checksum != ee[21]) + if (checksum != ee[21]) return; btv->c.type = BTTV_BOARD_OSPREY1x0_848; for (i = 12; i < 21; i++) serial *= 10, serial += ee[i] - '0'; - } + } } else { unsigned short type; - int offset = 4*16; - - for(; offset < 8*16; offset += 16) { - unsigned short checksum = 0; - /* verify the checksum */ - for(i = 0; i<14; i++) checksum += ee[i+offset]; - checksum = ~checksum; /* no idea why */ - if ((((checksum>>8)&0x0FF) == ee[offset+14]) && - ((checksum & 0x0FF) == ee[offset+15])) { - break; - } - } - - if (offset >= 8*16) + int offset = 4*16; + + for(; offset < 8*16; offset += 16) { + unsigned short checksum = 0; + /* verify the checksum */ + for(i = 0; i<14; i++) checksum += ee[i+offset]; + checksum = ~checksum; /* no idea why */ + if ((((checksum>>8)&0x0FF) == ee[offset+14]) && + ((checksum & 0x0FF) == ee[offset+15])) { + break; + } + } + + if (offset >= 8*16) return; /* found a valid descriptor */ @@ -3606,7 +3606,7 @@ static void __devinit osprey_eeprom(struct bttv *btv) btv->c.type = BTTV_BOARD_OSPREY101_848; break; - /* 878 based */ + /* 878 based */ case 0x0012: case 0x0013: btv->c.type = BTTV_BOARD_OSPREY1x0; @@ -3662,27 +3662,27 @@ static void __devinit osprey_eeprom(struct bttv *btv) /* AVermedia specific stuff, from bktr_card.c */ static int tuner_0_table[] = { - TUNER_PHILIPS_NTSC, TUNER_PHILIPS_PAL /* PAL-BG*/, - TUNER_PHILIPS_PAL, TUNER_PHILIPS_PAL /* PAL-I*/, - TUNER_PHILIPS_PAL, TUNER_PHILIPS_PAL, - TUNER_PHILIPS_SECAM, TUNER_PHILIPS_SECAM, - TUNER_PHILIPS_SECAM, TUNER_PHILIPS_PAL, + TUNER_PHILIPS_NTSC, TUNER_PHILIPS_PAL /* PAL-BG*/, + TUNER_PHILIPS_PAL, TUNER_PHILIPS_PAL /* PAL-I*/, + TUNER_PHILIPS_PAL, TUNER_PHILIPS_PAL, + TUNER_PHILIPS_SECAM, TUNER_PHILIPS_SECAM, + TUNER_PHILIPS_SECAM, TUNER_PHILIPS_PAL, TUNER_PHILIPS_FM1216ME_MK3 }; static int tuner_1_table[] = { - TUNER_TEMIC_NTSC, TUNER_TEMIC_PAL, + TUNER_TEMIC_NTSC, TUNER_TEMIC_PAL, TUNER_TEMIC_PAL, TUNER_TEMIC_PAL, TUNER_TEMIC_PAL, TUNER_TEMIC_PAL, - TUNER_TEMIC_4012FY5, TUNER_TEMIC_4012FY5, /* TUNER_TEMIC_SECAM */ - TUNER_TEMIC_4012FY5, TUNER_TEMIC_PAL}; + TUNER_TEMIC_4012FY5, TUNER_TEMIC_4012FY5, /* TUNER_TEMIC_SECAM */ + TUNER_TEMIC_4012FY5, TUNER_TEMIC_PAL}; static void __devinit avermedia_eeprom(struct bttv *btv) { - int tuner_make,tuner_tv_fm,tuner_format,tuner=0; + int tuner_make,tuner_tv_fm,tuner_format,tuner=0; tuner_make = (eeprom_data[0x41] & 0x7); - tuner_tv_fm = (eeprom_data[0x41] & 0x18) >> 3; - tuner_format = (eeprom_data[0x42] & 0xf0) >> 4; + tuner_tv_fm = (eeprom_data[0x41] & 0x18) >> 3; + tuner_format = (eeprom_data[0x42] & 0xf0) >> 4; btv->has_remote = (eeprom_data[0x42] & 0x01); if (tuner_make == 0 || tuner_make == 2) @@ -3718,8 +3718,8 @@ void bttv_tda9880_setnorm(struct bttv *btv, int norm) dprintk("bttv_tda9880_setnorm to NTSC\n"); } else { - bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[0]=0x947fff; - bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[4]=0x947fff; + bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[0]=0x947fff; + bttv_tvcards[BTTV_BOARD_VOODOOTV_FM].audiomux[4]=0x947fff; dprintk("bttv_tda9880_setnorm to PAL\n"); } /* set GPIO according */ @@ -3741,7 +3741,7 @@ static void __devinit boot_msp34xx(struct bttv *btv, int pin) gpio_inout(mask,mask); gpio_bits(mask,0); - udelay(2500); + udelay(2500); gpio_bits(mask,mask); if (bttv_gpio) @@ -3817,7 +3817,7 @@ static void __devinit init_PXC200(struct bttv *btv) udelay(10); gpio_write(1<<2); - for (i = 0; i < ARRAY_SIZE(vals); i++) { + for (i = 0; i < ARRAY_SIZE(vals); i++) { tmp=bttv_I2CWrite(btv,0x1E,0,vals[i],1); if (tmp != -1) { printk(KERN_INFO @@ -4260,30 +4260,30 @@ avermedia_tv_stereo_audio(struct bttv *btv, struct video_audio *v, int set) static void lt9415_audio(struct bttv *btv, struct video_audio *v, int set) { - int val = 0; + int val = 0; - if (gpio_read() & 0x4000) { + if (gpio_read() & 0x4000) { v->mode = VIDEO_SOUND_MONO; return; } - if (set) { - if (v->mode & VIDEO_SOUND_LANG2) /* A2 SAP */ - val = 0x0080; + if (set) { + if (v->mode & VIDEO_SOUND_LANG2) /* A2 SAP */ + val = 0x0080; if (v->mode & VIDEO_SOUND_STEREO) /* A2 stereo */ - val = 0x0880; - if ((v->mode & VIDEO_SOUND_LANG1) || + val = 0x0880; + if ((v->mode & VIDEO_SOUND_LANG1) || (v->mode & VIDEO_SOUND_MONO)) val = 0; gpio_bits(0x0880, val); - if (bttv_gpio) - bttv_gpio_tracking(btv,"lt9415"); - } else { + if (bttv_gpio) + bttv_gpio_tracking(btv,"lt9415"); + } else { /* autodetect doesn't work with this card :-( */ - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - return; - } + return; + } } /* TDA9821 on TerraTV+ Bt848, Bt878 */ @@ -4406,26 +4406,26 @@ fv2000s_audio(struct bttv *btv, struct video_audio *v, int set) static void windvr_audio(struct bttv *btv, struct video_audio *v, int set) { - unsigned long val = 0; - - if (set) { - if (v->mode & VIDEO_SOUND_MONO) - val = 0x040000; - if (v->mode & VIDEO_SOUND_LANG1) - val = 0; - if (v->mode & VIDEO_SOUND_LANG2) - val = 0x100000; - if (v->mode & VIDEO_SOUND_STEREO) - val = 0; - if (val) { + unsigned long val = 0; + + if (set) { + if (v->mode & VIDEO_SOUND_MONO) + val = 0x040000; + if (v->mode & VIDEO_SOUND_LANG1) + val = 0; + if (v->mode & VIDEO_SOUND_LANG2) + val = 0x100000; + if (v->mode & VIDEO_SOUND_STEREO) + val = 0; + if (val) { gpio_bits(0x140000, val); - if (bttv_gpio) - bttv_gpio_tracking(btv,"windvr"); - } - } else { - v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | - VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; - } + if (bttv_gpio) + bttv_gpio_tracking(btv,"windvr"); + } + } else { + v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | + VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2; + } } /* @@ -4668,10 +4668,10 @@ static void kodicom4400r_init(struct bttv *btv) static void xguard_muxsel(struct bttv *btv, unsigned int input) { static const int masks[] = { - ENB0, ENB0|IN00, ENB0|IN10, ENB0|IN00|IN10, - ENA0, ENA0|IN00, ENA0|IN10, ENA0|IN00|IN10, - ENB1, ENB1|IN01, ENB1|IN11, ENB1|IN01|IN11, - ENA1, ENA1|IN01, ENA1|IN11, ENA1|IN01|IN11, + ENB0, ENB0|IN00, ENB0|IN10, ENB0|IN00|IN10, + ENA0, ENA0|IN00, ENA0|IN10, ENA0|IN00|IN10, + ENB1, ENB1|IN01, ENB1|IN11, ENB1|IN01|IN11, + ENA1, ENA1|IN01, ENA1|IN11, ENA1|IN01|IN11, }; gpio_write(masks[input%16]); } @@ -4776,10 +4776,10 @@ static void ivc120_muxsel(struct bttv *btv, unsigned int input) static void PXC200_muxsel(struct bttv *btv, unsigned int input) { - int rc; + int rc; long mux; int bitmask; - unsigned char buf[2]; + unsigned char buf[2]; /* Read PIC config to determine if this is a PXC200F */ /* PX_I2C_CMD_CFG*/ @@ -4809,14 +4809,14 @@ static void PXC200_muxsel(struct bttv *btv, unsigned int input) /* bitmask=0x30f; */ bitmask=0x302; /* check whether we have a PXC200A */ - if (btv->cardid == PX_PXC200A_CARDID) { + if (btv->cardid == PX_PXC200A_CARDID) { bitmask ^= 0x180; /* use 7 and 9, not 8 and 9 */ bitmask |= 7<<4; /* the DAC */ } btwrite(bitmask, BT848_GPIO_OUT_EN); bitmask = btread(BT848_GPIO_DATA); - if (btv->cardid == PX_PXC200A_CARDID) + if (btv->cardid == PX_PXC200A_CARDID) bitmask = (bitmask & ~0x280) | ((mux & 2) << 8) | ((mux & 1) << 7); else /* older device */ bitmask = (bitmask & ~0x300) | ((mux & 3) << 8); @@ -4829,7 +4829,7 @@ static void PXC200_muxsel(struct bttv *btv, unsigned int input) * * needed because bttv-driver sets mux before calling this function */ - if (btv->cardid == PX_PXC200A_CARDID) + if (btv->cardid == PX_PXC200A_CARDID) btaor(2<<5, ~BT848_IFORM_MUXSEL, BT848_IFORM); else /* older device */ btand(~BT848_IFORM_MUXSEL,BT848_IFORM); @@ -4875,7 +4875,7 @@ void __devinit bttv_check_chipset(void) printk(KERN_INFO "bttv: pci latency fixup [%d]\n",latency); while ((dev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82441, dev))) { - unsigned char b; + unsigned char b; pci_read_config_byte(dev, 0x53, &b); if (bttv_debug) printk(KERN_INFO "bttv: Host bridge: 82441FX Natoma, " @@ -4885,7 +4885,7 @@ void __devinit bttv_check_chipset(void) int __devinit bttv_handle_chipset(struct bttv *btv) { - unsigned char command; + unsigned char command; if (!triton1 && !vsfx && UNSET == latency) return 0; @@ -4906,13 +4906,13 @@ int __devinit bttv_handle_chipset(struct bttv *btv) btv->triton1 = BT848_INT_ETBF; } else { /* bt878 has a bit in the pci config space for it */ - pci_read_config_byte(btv->c.pci, BT878_DEVCTRL, &command); + pci_read_config_byte(btv->c.pci, BT878_DEVCTRL, &command); if (triton1) command |= BT878_EN_TBFX; if (vsfx) command |= BT878_EN_VSFX; - pci_write_config_byte(btv->c.pci, BT878_DEVCTRL, command); - } + pci_write_config_byte(btv->c.pci, BT878_DEVCTRL, command); + } if (UNSET != latency) pci_write_config_byte(btv->c.pci, PCI_LATENCY_TIMER, latency); return 0; diff --git a/drivers/media/video/bttv-driver.c b/drivers/media/video/bttv-driver.c index f8307407e320..0005741d5514 100644 --- a/drivers/media/video/bttv-driver.c +++ b/drivers/media/video/bttv-driver.c @@ -3,7 +3,7 @@ bttv - Bt848 frame grabber driver Copyright (C) 1996,97,98 Ralph Metzler - & Marcus Metzler + & Marcus Metzler (c) 1999-2002 Gerd Knorr some v4l2 code lines are taken from Justin's bttv2 driver which is @@ -192,8 +192,8 @@ static u8 SRAM_Table[][60] = const struct bttv_tvnorm bttv_tvnorms[] = { /* PAL-BDGHI */ - /* max. active video is actually 922, but 924 is divisible by 4 and 3! */ - /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */ + /* max. active video is actually 922, but 924 is divisible by 4 and 3! */ + /* actually, max active PAL with HSCALE=0 is 948, NTSC is 768 - nil */ { .v4l2_id = V4L2_STD_PAL, .name = "PAL", @@ -806,9 +806,9 @@ static void bt848A_set_timing(struct bttv *btv) btv->c.nr,table_idx); /* timing change...reset timing generator address */ - btwrite(0x00, BT848_TGCTRL); - btwrite(0x02, BT848_TGCTRL); - btwrite(0x00, BT848_TGCTRL); + btwrite(0x00, BT848_TGCTRL); + btwrite(0x02, BT848_TGCTRL); + btwrite(0x00, BT848_TGCTRL); len=SRAM_Table[table_idx][0]; for(i = 1; i <= len; i++) @@ -847,7 +847,7 @@ static void bt848_hue(struct bttv *btv, int hue) /* -128 to 127 */ value = (hue >> 8) - 128; - btwrite(value & 0xff, BT848_HUE); + btwrite(value & 0xff, BT848_HUE); } static void bt848_contrast(struct bttv *btv, int cont) @@ -859,9 +859,9 @@ static void bt848_contrast(struct bttv *btv, int cont) /* 0-511 */ value = (cont >> 7); hibit = (value >> 6) & 4; - btwrite(value & 0xff, BT848_CONTRAST_LO); - btaor(hibit, ~4, BT848_E_CONTROL); - btaor(hibit, ~4, BT848_O_CONTROL); + btwrite(value & 0xff, BT848_CONTRAST_LO); + btaor(hibit, ~4, BT848_E_CONTROL); + btaor(hibit, ~4, BT848_O_CONTROL); } static void bt848_sat(struct bttv *btv, int color) @@ -873,12 +873,12 @@ static void bt848_sat(struct bttv *btv, int color) /* 0-511 for the color */ val_u = ((color * btv->opt_uv_ratio) / 50) >> 7; val_v = (((color * (100 - btv->opt_uv_ratio) / 50) >>7)*180L)/254; - hibits = (val_u >> 7) & 2; + hibits = (val_u >> 7) & 2; hibits |= (val_v >> 8) & 1; - btwrite(val_u & 0xff, BT848_SAT_U_LO); - btwrite(val_v & 0xff, BT848_SAT_V_LO); - btaor(hibits, ~3, BT848_E_CONTROL); - btaor(hibits, ~3, BT848_O_CONTROL); + btwrite(val_u & 0xff, BT848_SAT_U_LO); + btwrite(val_v & 0xff, BT848_SAT_V_LO); + btaor(hibits, ~3, BT848_E_CONTROL); + btaor(hibits, ~3, BT848_O_CONTROL); } /* ----------------------------------------------------------------------- */ @@ -891,7 +891,7 @@ video_mux(struct bttv *btv, unsigned int input) if (input >= bttv_tvcards[btv->c.type].video_inputs) return -EINVAL; - /* needed by RemoteVideo MX */ + /* needed by RemoteVideo MX */ mask2 = bttv_tvcards[btv->c.type].gpiomask2; if (mask2) gpio_inout(mask2,mask2); @@ -1055,22 +1055,22 @@ static void init_bt848(struct bttv *btv) btwrite(BT848_COLOR_CTL_GAMMA, BT848_COLOR_CTL); btwrite(BT848_IFORM_XTAUTO | BT848_IFORM_AUTO, BT848_IFORM); - /* set planar and packed mode trigger points and */ - /* set rising edge of inverted GPINTR pin as irq trigger */ - btwrite(BT848_GPIO_DMA_CTL_PKTP_32| - BT848_GPIO_DMA_CTL_PLTP1_16| - BT848_GPIO_DMA_CTL_PLTP23_16| - BT848_GPIO_DMA_CTL_GPINTC| - BT848_GPIO_DMA_CTL_GPINTI, - BT848_GPIO_DMA_CTL); + /* set planar and packed mode trigger points and */ + /* set rising edge of inverted GPINTR pin as irq trigger */ + btwrite(BT848_GPIO_DMA_CTL_PKTP_32| + BT848_GPIO_DMA_CTL_PLTP1_16| + BT848_GPIO_DMA_CTL_PLTP23_16| + BT848_GPIO_DMA_CTL_GPINTC| + BT848_GPIO_DMA_CTL_GPINTI, + BT848_GPIO_DMA_CTL); val = btv->opt_chroma_agc ? BT848_SCLOOP_CAGC : 0; - btwrite(val, BT848_E_SCLOOP); - btwrite(val, BT848_O_SCLOOP); + btwrite(val, BT848_E_SCLOOP); + btwrite(val, BT848_O_SCLOOP); - btwrite(0x20, BT848_E_VSCALE_HI); - btwrite(0x20, BT848_O_VSCALE_HI); - btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0), + btwrite(0x20, BT848_E_VSCALE_HI); + btwrite(0x20, BT848_O_VSCALE_HI); + btwrite(BT848_ADC_RESERVED | (btv->opt_adc_crush ? BT848_ADC_CRUSH : 0), BT848_ADC); btwrite(whitecrush_upper, BT848_WC_UP); @@ -1089,7 +1089,7 @@ static void init_bt848(struct bttv *btv) bt848_contrast(btv, btv->contrast); bt848_sat(btv, btv->saturation); - /* interrupt */ + /* interrupt */ init_irqreg(btv); } @@ -1105,7 +1105,7 @@ static void bttv_reinit_bt848(struct bttv *btv) spin_unlock_irqrestore(&btv->s_lock,flags); init_bt848(btv); - btv->pll.pll_current = -1; + btv->pll.pll_current = -1; set_input(btv,btv->input); } @@ -1398,7 +1398,7 @@ bttv_switch_overlay(struct bttv *btv, struct bttv_fh *fh, /* video4linux (1) interface */ static int bttv_prepare_buffer(struct bttv *btv, struct bttv_buffer *buf, - const struct bttv_format *fmt, + const struct bttv_format *fmt, unsigned int width, unsigned int height, enum v4l2_field field) { @@ -1521,8 +1521,8 @@ static const char *v4l1_ioctls[] = { static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) { switch (cmd) { - case BTTV_VERSION: - return BTTV_VERSION_CODE; + case BTTV_VERSION: + return BTTV_VERSION_CODE; /* *** v4l1 *** ************************************************ */ case VIDIOCGFREQ: @@ -1576,32 +1576,32 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) return 0; } - case VIDIOCGCHAN: - { - struct video_channel *v = arg; + case VIDIOCGCHAN: + { + struct video_channel *v = arg; unsigned int channel = v->channel; - if (channel >= bttv_tvcards[btv->c.type].video_inputs) - return -EINVAL; - v->tuners=0; - v->flags = VIDEO_VC_AUDIO; - v->type = VIDEO_TYPE_CAMERA; - v->norm = btv->tvnorm; + if (channel >= bttv_tvcards[btv->c.type].video_inputs) + return -EINVAL; + v->tuners=0; + v->flags = VIDEO_VC_AUDIO; + v->type = VIDEO_TYPE_CAMERA; + v->norm = btv->tvnorm; if (channel == bttv_tvcards[btv->c.type].tuner) { - strcpy(v->name,"Television"); - v->flags|=VIDEO_VC_TUNER; - v->type=VIDEO_TYPE_TV; - v->tuners=1; - } else if (channel == btv->svhs) { - strcpy(v->name,"S-Video"); - } else { - sprintf(v->name,"Composite%d",channel); + strcpy(v->name,"Television"); + v->flags|=VIDEO_VC_TUNER; + v->type=VIDEO_TYPE_TV; + v->tuners=1; + } else if (channel == btv->svhs) { + strcpy(v->name,"S-Video"); + } else { + sprintf(v->name,"Composite%d",channel); } return 0; - } - case VIDIOCSCHAN: - { - struct video_channel *v = arg; + } + case VIDIOCSCHAN: + { + struct video_channel *v = arg; unsigned int channel = v->channel; if (channel >= bttv_tvcards[btv->c.type].video_inputs) @@ -1623,7 +1623,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) return 0; } - case VIDIOCGAUDIO: + case VIDIOCGAUDIO: { struct video_audio *v = arg; @@ -1728,7 +1728,7 @@ static int bttv_common_ioctls(struct bttv *btv, unsigned int cmd, void *arg) } else if (i->index == btv->svhs) { sprintf(i->name, "S-Video"); } else { - sprintf(i->name,"Composite%d",i->index); + sprintf(i->name,"Composite%d",i->index); } if (i->index == btv->input) { __u32 dstatus = btread(BT848_DSTATUS); @@ -2168,7 +2168,7 @@ static int bttv_s_fmt(struct bttv_fh *fh, struct bttv *btv, if (0 != retval) return retval; if (locked_btres(fh->btv, RESOURCE_VBI)) - return -EBUSY; + return -EBUSY; bttv_vbi_try_fmt(fh,f); bttv_vbi_setlines(fh,btv,f->fmt.vbi.count[0]); bttv_vbi_get_fmt(fh,f); @@ -2206,9 +2206,9 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, bttv_reinit_bt848(btv); switch (cmd) { - case VIDIOCSFREQ: - case VIDIOCSTUNER: - case VIDIOCSCHAN: + case VIDIOCSFREQ: + case VIDIOCSTUNER: + case VIDIOCSCHAN: case VIDIOC_S_CTRL: case VIDIOC_S_STD: case VIDIOC_S_INPUT: @@ -2224,10 +2224,10 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, /* *** v4l1 *** ************************************************ */ case VIDIOCGCAP: { - struct video_capability *cap = arg; + struct video_capability *cap = arg; memset(cap,0,sizeof(*cap)); - strcpy(cap->name,btv->video_dev->name); + strcpy(cap->name,btv->video_dev->name); if (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type) { /* vbi */ cap->type = VID_TYPE_TUNER|VID_TYPE_TELETEXT; @@ -2247,7 +2247,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, } cap->channels = bttv_tvcards[btv->c.type].video_inputs; cap->audios = bttv_tvcards[btv->c.type].audio_inputs; - return 0; + return 0; } case VIDIOCGPICT: @@ -2296,7 +2296,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, bt848_hue(btv,pic->hue); bt848_sat(btv,pic->colour); up(&fh->cap.lock); - return 0; + return 0; } case VIDIOCGWIN: @@ -2357,8 +2357,8 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, unsigned long end; if(!capable(CAP_SYS_ADMIN) && - !capable(CAP_SYS_RAWIO)) - return -EPERM; + !capable(CAP_SYS_RAWIO)) + return -EPERM; end = (unsigned long)fbuf->base + fbuf->height * fbuf->bytesperline; down(&fh->cap.lock); @@ -2432,7 +2432,7 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, } /* switch over */ - retval = bttv_switch_overlay(btv,fh,new); + retval = bttv_switch_overlay(btv,fh,new); up(&fh->cap.lock); return retval; } @@ -2571,13 +2571,13 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, return 0; } - case BTTV_VERSION: - case VIDIOCGFREQ: - case VIDIOCSFREQ: - case VIDIOCGTUNER: - case VIDIOCSTUNER: - case VIDIOCGCHAN: - case VIDIOCSCHAN: + case BTTV_VERSION: + case VIDIOCGFREQ: + case VIDIOCSFREQ: + case VIDIOCGTUNER: + case VIDIOCSTUNER: + case VIDIOCGCHAN: + case VIDIOCSCHAN: case VIDIOCGAUDIO: case VIDIOCSAUDIO: return bttv_common_ioctls(btv,cmd,arg); @@ -2589,8 +2589,8 @@ static int bttv_do_ioctl(struct inode *inode, struct file *file, if (0 == v4l2) return -EINVAL; - strcpy(cap->driver,"bttv"); - strlcpy(cap->card,btv->video_dev->name,sizeof(cap->card)); + strcpy(cap->driver,"bttv"); + strlcpy(cap->card,btv->video_dev->name,sizeof(cap->card)); sprintf(cap->bus_info,"PCI:%s",pci_name(btv->c.pci)); cap->version = BTTV_VERSION_CODE; cap->capabilities = @@ -3097,7 +3097,7 @@ static struct video_device bttv_video_template = { .name = "UNSET", .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER| - VID_TYPE_CLIPPING|VID_TYPE_SCALES, + VID_TYPE_CLIPPING|VID_TYPE_SCALES, .hardware = VID_HARDWARE_BT848, .fops = &bttv_fops, .minor = -1, @@ -3143,7 +3143,7 @@ static int radio_open(struct inode *inode, struct file *file) audio_mux(btv,AUDIO_RADIO); up(&btv->lock); - return 0; + return 0; } static int radio_release(struct inode *inode, struct file *file) @@ -3166,34 +3166,34 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, switch (cmd) { case VIDIOCGCAP: { - struct video_capability *cap = arg; + struct video_capability *cap = arg; memset(cap,0,sizeof(*cap)); - strcpy(cap->name,btv->radio_dev->name); - cap->type = VID_TYPE_TUNER; + strcpy(cap->name,btv->radio_dev->name); + cap->type = VID_TYPE_TUNER; cap->channels = 1; cap->audios = 1; - return 0; + return 0; } - case VIDIOCGTUNER: - { - struct video_tuner *v = arg; + case VIDIOCGTUNER: + { + struct video_tuner *v = arg; - if(v->tuner) - return -EINVAL; + if(v->tuner) + return -EINVAL; memset(v,0,sizeof(*v)); - strcpy(v->name, "Radio"); - bttv_call_i2c_clients(btv,cmd,v); - return 0; - } - case VIDIOCSTUNER: + strcpy(v->name, "Radio"); + bttv_call_i2c_clients(btv,cmd,v); + return 0; + } + case VIDIOCSTUNER: /* nothing to do */ return 0; case BTTV_VERSION: - case VIDIOCGFREQ: - case VIDIOCSFREQ: + case VIDIOCGFREQ: + case VIDIOCSFREQ: case VIDIOCGAUDIO: case VIDIOCSAUDIO: return bttv_common_ioctls(btv,cmd,arg); @@ -3699,7 +3699,7 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs) } if (astat&BT848_INT_VSYNC) - btv->field_count++; + btv->field_count++; if (astat & BT848_INT_GPINT) { wake_up(&btv->gpioq); @@ -3711,13 +3711,13 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs) wake_up(&btv->i2c_queue); } - if ((astat & BT848_INT_RISCI) && (stat & (4<<28))) + if ((astat & BT848_INT_RISCI) && (stat & (4<<28))) bttv_irq_switch_vbi(btv); - if ((astat & BT848_INT_RISCI) && (stat & (2<<28))) + if ((astat & BT848_INT_RISCI) && (stat & (2<<28))) bttv_irq_wakeup_top(btv); - if ((astat & BT848_INT_RISCI) && (stat & (1<<28))) + if ((astat & BT848_INT_RISCI) && (stat & (1<<28))) bttv_irq_switch_video(btv); if ((astat & BT848_INT_HLOCK) && btv->opt_automute) @@ -3744,7 +3744,7 @@ static irqreturn_t bttv_irq(int irq, void *dev_id, struct pt_regs * regs) if (count > 4) { if (count > 8 || !(astat & BT848_INT_GPINT)) { - btwrite(0, BT848_INT_MASK); + btwrite(0, BT848_INT_MASK); printk(KERN_ERR "bttv%d: IRQ lockup, cleared int mask [", btv->c.nr); @@ -3826,7 +3826,7 @@ static int __devinit bttv_register_video(struct bttv *btv) /* video */ btv->video_dev = vdev_init(btv, &bttv_video_template, "video"); - if (NULL == btv->video_dev) + if (NULL == btv->video_dev) goto err; if (video_register_device(btv->video_dev,VFL_TYPE_GRABBER,video_nr)<0) goto err; @@ -3836,18 +3836,18 @@ static int __devinit bttv_register_video(struct bttv *btv) /* vbi */ btv->vbi_dev = vdev_init(btv, &bttv_vbi_template, "vbi"); - if (NULL == btv->vbi_dev) + if (NULL == btv->vbi_dev) goto err; - if (video_register_device(btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0) + if (video_register_device(btv->vbi_dev,VFL_TYPE_VBI,vbi_nr)<0) goto err; printk(KERN_INFO "bttv%d: registered device vbi%d\n", btv->c.nr,btv->vbi_dev->minor & 0x1f); - if (!btv->has_radio) + if (!btv->has_radio) return 0; /* radio */ btv->radio_dev = vdev_init(btv, &radio_template, "radio"); - if (NULL == btv->radio_dev) + if (NULL == btv->radio_dev) goto err; if (video_register_device(btv->radio_dev, VFL_TYPE_RADIO,radio_nr)<0) goto err; @@ -3868,11 +3868,11 @@ static int __devinit bttv_register_video(struct bttv *btv) static void pci_set_command(struct pci_dev *dev) { #if defined(__powerpc__) - unsigned int cmd; + unsigned int cmd; - pci_read_config_dword(dev, PCI_COMMAND, &cmd); - cmd = (cmd | PCI_COMMAND_MEMORY ); - pci_write_config_dword(dev, PCI_COMMAND, cmd); + pci_read_config_dword(dev, PCI_COMMAND, &cmd); + cmd = (cmd | PCI_COMMAND_MEMORY ); + pci_write_config_dword(dev, PCI_COMMAND, cmd); #endif } @@ -3886,21 +3886,21 @@ static int __devinit bttv_probe(struct pci_dev *dev, if (bttv_num == BTTV_MAX) return -ENOMEM; printk(KERN_INFO "bttv: Bt8xx card found (%d).\n", bttv_num); - btv=&bttvs[bttv_num]; + btv=&bttvs[bttv_num]; memset(btv,0,sizeof(*btv)); btv->c.nr = bttv_num; sprintf(btv->c.name,"bttv%d",btv->c.nr); /* initialize structs / fill in defaults */ - init_MUTEX(&btv->lock); - init_MUTEX(&btv->reslock); - spin_lock_init(&btv->s_lock); - spin_lock_init(&btv->gpio_lock); - init_waitqueue_head(&btv->gpioq); - init_waitqueue_head(&btv->i2c_queue); - INIT_LIST_HEAD(&btv->c.subs); - INIT_LIST_HEAD(&btv->capture); - INIT_LIST_HEAD(&btv->vcapture); + init_MUTEX(&btv->lock); + init_MUTEX(&btv->reslock); + spin_lock_init(&btv->s_lock); + spin_lock_init(&btv->gpio_lock); + init_waitqueue_head(&btv->gpioq); + init_waitqueue_head(&btv->i2c_queue); + INIT_LIST_HEAD(&btv->c.subs); + INIT_LIST_HEAD(&btv->capture); + INIT_LIST_HEAD(&btv->vcapture); v4l2_prio_init(&btv->prio); init_timer(&btv->timeout); @@ -3921,27 +3921,27 @@ static int __devinit bttv_probe(struct pci_dev *dev, btv->c.nr); return -EIO; } - if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) { - printk(KERN_WARNING "bttv%d: No suitable DMA available.\n", + if (pci_set_dma_mask(dev, DMA_32BIT_MASK)) { + printk(KERN_WARNING "bttv%d: No suitable DMA available.\n", btv->c.nr); return -EIO; - } + } if (!request_mem_region(pci_resource_start(dev,0), pci_resource_len(dev,0), btv->c.name)) { - printk(KERN_WARNING "bttv%d: can't request iomem (0x%lx).\n", + printk(KERN_WARNING "bttv%d: can't request iomem (0x%lx).\n", btv->c.nr, pci_resource_start(dev,0)); return -EBUSY; } - pci_set_master(dev); + pci_set_master(dev); pci_set_command(dev); pci_set_drvdata(dev,btv); - pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision); - pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); - printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %s, ", - bttv_num,btv->id, btv->revision, pci_name(dev)); - printk("irq: %d, latency: %d, mmio: 0x%lx\n", + pci_read_config_byte(dev, PCI_CLASS_REVISION, &btv->revision); + pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat); + printk(KERN_INFO "bttv%d: Bt%d (rev %d) at %s, ", + bttv_num,btv->id, btv->revision, pci_name(dev)); + printk("irq: %d, latency: %d, mmio: 0x%lx\n", btv->c.pci->irq, lat, pci_resource_start(dev,0)); schedule(); @@ -3952,23 +3952,23 @@ static int __devinit bttv_probe(struct pci_dev *dev, goto fail1; } - /* identify card */ + /* identify card */ bttv_idcard(btv); - /* disable irqs, register irq handler */ + /* disable irqs, register irq handler */ btwrite(0, BT848_INT_MASK); - result = request_irq(btv->c.pci->irq, bttv_irq, - SA_SHIRQ | SA_INTERRUPT,btv->c.name,(void *)btv); - if (result < 0) { - printk(KERN_ERR "bttv%d: can't get IRQ %d\n", + result = request_irq(btv->c.pci->irq, bttv_irq, + SA_SHIRQ | SA_INTERRUPT,btv->c.name,(void *)btv); + if (result < 0) { + printk(KERN_ERR "bttv%d: can't get IRQ %d\n", bttv_num,btv->c.pci->irq); goto fail1; - } + } if (0 != bttv_handle_chipset(btv)) { result = -EIO; goto fail2; - } + } /* init options from insmod args */ btv->opt_combfilter = combfilter; @@ -3994,29 +3994,29 @@ static int __devinit bttv_probe(struct pci_dev *dev, btv->input = 0; /* initialize hardware */ - if (bttv_gpio) - bttv_gpio_tracking(btv,"pre-init"); + if (bttv_gpio) + bttv_gpio_tracking(btv,"pre-init"); bttv_risc_init_main(btv); init_bt848(btv); /* gpio */ - btwrite(0x00, BT848_GPIO_REG_INP); - btwrite(0x00, BT848_GPIO_OUT_EN); - if (bttv_verbose) - bttv_gpio_tracking(btv,"init"); + btwrite(0x00, BT848_GPIO_REG_INP); + btwrite(0x00, BT848_GPIO_OUT_EN); + if (bttv_verbose) + bttv_gpio_tracking(btv,"init"); - /* needs to be done before i2c is registered */ - bttv_init_card1(btv); + /* needs to be done before i2c is registered */ + bttv_init_card1(btv); - /* register i2c + gpio */ - init_bttv_i2c(btv); + /* register i2c + gpio */ + init_bttv_i2c(btv); - /* some card-specific stuff (needs working i2c) */ - bttv_init_card2(btv); + /* some card-specific stuff (needs working i2c) */ + bttv_init_card2(btv); init_irqreg(btv); - /* register video4linux + input */ + /* register video4linux + input */ if (!bttv_tvcards[btv->c.type].no_video) { bttv_register_video(btv); bt848_bright(btv,32768); @@ -4035,10 +4035,10 @@ static int __devinit bttv_probe(struct pci_dev *dev, /* everything is fine */ bttv_num++; - return 0; + return 0; fail2: - free_irq(btv->c.pci->irq,btv); + free_irq(btv->c.pci->irq,btv); fail1: if (btv->bt848_mmio) @@ -4051,12 +4051,12 @@ static int __devinit bttv_probe(struct pci_dev *dev, static void __devexit bttv_remove(struct pci_dev *pci_dev) { - struct bttv *btv = pci_get_drvdata(pci_dev); + struct bttv *btv = pci_get_drvdata(pci_dev); if (bttv_verbose) printk("bttv%d: unloading\n",btv->c.nr); - /* shutdown everything (DMA+IRQs) */ + /* shutdown everything (DMA+IRQs) */ btand(~15, BT848_GPIO_DMA_CTL); btwrite(0, BT848_INT_MASK); btwrite(~0x0, BT848_INT_STAT); @@ -4069,7 +4069,7 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev) wake_up(&btv->gpioq); bttv_sub_del_devices(&btv->c); - /* unregister i2c_bus + input */ + /* unregister i2c_bus + input */ fini_bttv_i2c(btv); /* unregister video4linux */ @@ -4079,18 +4079,18 @@ static void __devexit bttv_remove(struct pci_dev *pci_dev) btcx_riscmem_free(btv->c.pci,&btv->main); /* free ressources */ - free_irq(btv->c.pci->irq,btv); + free_irq(btv->c.pci->irq,btv); iounmap(btv->bt848_mmio); - release_mem_region(pci_resource_start(btv->c.pci,0), - pci_resource_len(btv->c.pci,0)); + release_mem_region(pci_resource_start(btv->c.pci,0), + pci_resource_len(btv->c.pci,0)); pci_set_drvdata(pci_dev, NULL); - return; + return; } static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state) { - struct bttv *btv = pci_get_drvdata(pci_dev); + struct bttv *btv = pci_get_drvdata(pci_dev); struct bttv_buffer_set idle; unsigned long flags; @@ -4125,7 +4125,7 @@ static int bttv_suspend(struct pci_dev *pci_dev, pm_message_t state) static int bttv_resume(struct pci_dev *pci_dev) { - struct bttv *btv = pci_get_drvdata(pci_dev); + struct bttv *btv = pci_get_drvdata(pci_dev); unsigned long flags; int err; @@ -4170,24 +4170,24 @@ static int bttv_resume(struct pci_dev *pci_dev) } static struct pci_device_id bttv_pci_tbl[] = { - {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT848, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT849, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT878, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {PCI_VENDOR_ID_BROOKTREE, PCI_DEVICE_ID_BT879, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, - {0,} + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, + {0,} }; MODULE_DEVICE_TABLE(pci, bttv_pci_tbl); static struct pci_driver bttv_pci_driver = { - .name = "bttv", - .id_table = bttv_pci_tbl, - .probe = bttv_probe, - .remove = __devexit_p(bttv_remove), + .name = "bttv", + .id_table = bttv_pci_tbl, + .probe = bttv_probe, + .remove = __devexit_p(bttv_remove), .suspend = bttv_suspend, .resume = bttv_resume, }; diff --git a/drivers/media/video/bttv-gpio.c b/drivers/media/video/bttv-gpio.c index 6b280c03e398..575ce8b8e714 100644 --- a/drivers/media/video/bttv-gpio.c +++ b/drivers/media/video/bttv-gpio.c @@ -7,7 +7,7 @@ Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) (c) 1999-2003 Gerd Knorr This program is free software; you can redistribute it and/or modify diff --git a/drivers/media/video/bttv-i2c.c b/drivers/media/video/bttv-i2c.c index e684df37eb0e..06c5965b5616 100644 --- a/drivers/media/video/bttv-i2c.c +++ b/drivers/media/video/bttv-i2c.c @@ -5,7 +5,7 @@ bttv - Bt848 frame grabber driver Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) (c) 1999-2003 Gerd Knorr This program is free software; you can redistribute it and/or modify @@ -237,7 +237,7 @@ bttv_i2c_readbytes(struct bttv *btv, const struct i2c_msg *msg, int last) err: if (i2c_debug) printk(" ERR: %d\n",retval); - return retval; + return retval; } static int bttv_i2c_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num) @@ -290,7 +290,7 @@ static struct i2c_adapter bttv_i2c_adap_hw_template = { static int attach_inform(struct i2c_client *client) { - struct bttv *btv = i2c_get_adapdata(client->adapter); + struct bttv *btv = i2c_get_adapdata(client->adapter); if (bttv_debug) printk(KERN_DEBUG "bttv%d: %s i2c attach [addr=0x%x,client=%s]\n", @@ -300,9 +300,9 @@ static int attach_inform(struct i2c_client *client) return 0; if (btv->tuner_type != UNSET) { - struct tuner_setup tun_setup; + struct tuner_setup tun_setup; - tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV; + tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV; tun_setup.type = btv->tuner_type; tun_setup.addr = ADDR_UNSET; @@ -312,7 +312,7 @@ static int attach_inform(struct i2c_client *client) if (btv->pinnacle_id != UNSET) client->driver->command(client,AUDC_CONFIG_PINNACLE, &btv->pinnacle_id); - return 0; + return 0; } void bttv_call_i2c_clients(struct bttv *btv, unsigned int cmd, void *arg) @@ -330,43 +330,43 @@ static struct i2c_client bttv_i2c_client_template = { /* read I2C */ int bttv_I2CRead(struct bttv *btv, unsigned char addr, char *probe_for) { - unsigned char buffer = 0; + unsigned char buffer = 0; if (0 != btv->i2c_rc) return -1; if (bttv_verbose && NULL != probe_for) printk(KERN_INFO "bttv%d: i2c: checking for %s @ 0x%02x... ", btv->c.nr,probe_for,addr); - btv->i2c_client.addr = addr >> 1; - if (1 != i2c_master_recv(&btv->i2c_client, &buffer, 1)) { + btv->i2c_client.addr = addr >> 1; + if (1 != i2c_master_recv(&btv->i2c_client, &buffer, 1)) { if (NULL != probe_for) { if (bttv_verbose) printk("not found\n"); } else printk(KERN_WARNING "bttv%d: i2c read 0x%x: error\n", btv->c.nr,addr); - return -1; + return -1; } if (bttv_verbose && NULL != probe_for) printk("found\n"); - return buffer; + return buffer; } /* write I2C */ int bttv_I2CWrite(struct bttv *btv, unsigned char addr, unsigned char b1, - unsigned char b2, int both) + unsigned char b2, int both) { - unsigned char buffer[2]; - int bytes = both ? 2 : 1; + unsigned char buffer[2]; + int bytes = both ? 2 : 1; if (0 != btv->i2c_rc) return -1; - btv->i2c_client.addr = addr >> 1; - buffer[0] = b1; - buffer[1] = b2; - if (bytes != i2c_master_send(&btv->i2c_client, buffer, bytes)) + btv->i2c_client.addr = addr >> 1; + buffer[0] = b1; + buffer[1] = b2; + if (bytes != i2c_master_send(&btv->i2c_client, buffer, bytes)) return -1; - return 0; + return 0; } /* read EEPROM content */ @@ -431,8 +431,8 @@ int __devinit init_bttv_i2c(struct bttv *btv) "bt%d #%d [%s]", btv->id, btv->c.nr, btv->use_i2c_hw ? "hw" : "sw"); - i2c_set_adapdata(&btv->c.i2c_adap, btv); - btv->i2c_client.adapter = &btv->c.i2c_adap; + i2c_set_adapdata(&btv->c.i2c_adap, btv); + btv->i2c_client.adapter = &btv->c.i2c_adap; #ifdef I2C_CLASS_TV_ANALOG if (bttv_tvcards[btv->c.type].no_video) diff --git a/drivers/media/video/bttv-if.c b/drivers/media/video/bttv-if.c index e8aada772b89..19b564ab0e92 100644 --- a/drivers/media/video/bttv-if.c +++ b/drivers/media/video/bttv-if.c @@ -1,13 +1,13 @@ /* bttv-if.c -- old gpio interface to other kernel modules - don't use in new code, will go away in 2.7 + don't use in new code, will go away in 2.7 have a look at bttv-gpio.c instead. bttv - Bt848 frame grabber driver Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) (c) 1999-2003 Gerd Knorr This program is free software; you can redistribute it and/or modify diff --git a/drivers/media/video/bttv-risc.c b/drivers/media/video/bttv-risc.c index a5ed99b89445..3028862934dd 100644 --- a/drivers/media/video/bttv-risc.c +++ b/drivers/media/video/bttv-risc.c @@ -74,27 +74,27 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, } if (bpl <= sg_dma_len(sg)-offset) { /* fits into current chunk */ - *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL| + *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL| BT848_RISC_EOL|bpl); - *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); - offset+=bpl; + *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); + offset+=bpl; } else { /* scanline needs to be splitted */ - todo = bpl; - *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL| + todo = bpl; + *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_SOL| (sg_dma_len(sg)-offset)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); - todo -= (sg_dma_len(sg)-offset); - offset = 0; - sg++; - while (todo > sg_dma_len(sg)) { - *(rp++)=cpu_to_le32(BT848_RISC_WRITE| + *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); + todo -= (sg_dma_len(sg)-offset); + offset = 0; + sg++; + while (todo > sg_dma_len(sg)) { + *(rp++)=cpu_to_le32(BT848_RISC_WRITE| sg_dma_len(sg)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)); + *(rp++)=cpu_to_le32(sg_dma_address(sg)); todo -= sg_dma_len(sg); sg++; } - *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL| + *(rp++)=cpu_to_le32(BT848_RISC_WRITE|BT848_RISC_EOL| todo); *(rp++)=cpu_to_le32(sg_dma_address(sg)); offset += todo; @@ -201,8 +201,8 @@ bttv_risc_planar(struct bttv *btv, struct btcx_riscmem *risc, ri |= BT848_RISC_EOL; /* write risc instruction */ - *(rp++)=cpu_to_le32(ri | ylen); - *(rp++)=cpu_to_le32(((ylen >> hshift) << 16) | + *(rp++)=cpu_to_le32(ri | ylen); + *(rp++)=cpu_to_le32(((ylen >> hshift) << 16) | (ylen >> hshift)); *(rp++)=cpu_to_le32(sg_dma_address(ysg)+yoffset); yoffset += ylen; @@ -319,7 +319,7 @@ bttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo, int width, int height, int interleaved, int norm) { const struct bttv_tvnorm *tvnorm = &bttv_tvnorms[norm]; - u32 xsf, sr; + u32 xsf, sr; int vdelay; int swidth = tvnorm->swidth; @@ -334,52 +334,52 @@ bttv_calc_geo(struct bttv *btv, struct bttv_geometry *geo, vdelay = tvnorm->vdelay; - xsf = (width*scaledtwidth)/swidth; - geo->hscale = ((totalwidth*4096UL)/xsf-4096); - geo->hdelay = tvnorm->hdelayx1; - geo->hdelay = (geo->hdelay*width)/swidth; - geo->hdelay &= 0x3fe; - sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512; - geo->vscale = (0x10000UL-sr) & 0x1fff; - geo->crop = ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) | - ((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0); - geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0; - geo->vdelay = vdelay; - geo->width = width; - geo->sheight = tvnorm->sheight; + xsf = (width*scaledtwidth)/swidth; + geo->hscale = ((totalwidth*4096UL)/xsf-4096); + geo->hdelay = tvnorm->hdelayx1; + geo->hdelay = (geo->hdelay*width)/swidth; + geo->hdelay &= 0x3fe; + sr = ((tvnorm->sheight >> (interleaved?0:1))*512)/height - 512; + geo->vscale = (0x10000UL-sr) & 0x1fff; + geo->crop = ((width>>8)&0x03) | ((geo->hdelay>>6)&0x0c) | + ((tvnorm->sheight>>4)&0x30) | ((vdelay>>2)&0xc0); + geo->vscale |= interleaved ? (BT848_VSCALE_INT<<8) : 0; + geo->vdelay = vdelay; + geo->width = width; + geo->sheight = tvnorm->sheight; geo->vtotal = tvnorm->vtotal; - if (btv->opt_combfilter) { - geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0); - geo->comb = (width < 769) ? 1 : 0; - } else { - geo->vtc = 0; - geo->comb = 0; - } + if (btv->opt_combfilter) { + geo->vtc = (width < 193) ? 2 : ((width < 385) ? 1 : 0); + geo->comb = (width < 769) ? 1 : 0; + } else { + geo->vtc = 0; + geo->comb = 0; + } } static void bttv_apply_geo(struct bttv *btv, struct bttv_geometry *geo, int odd) { - int off = odd ? 0x80 : 0x00; + int off = odd ? 0x80 : 0x00; if (geo->comb) btor(BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); else btand(~BT848_VSCALE_COMB, BT848_E_VSCALE_HI+off); - btwrite(geo->vtc, BT848_E_VTC+off); - btwrite(geo->hscale >> 8, BT848_E_HSCALE_HI+off); - btwrite(geo->hscale & 0xff, BT848_E_HSCALE_LO+off); - btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off); - btwrite(geo->vscale & 0xff, BT848_E_VSCALE_LO+off); - btwrite(geo->width & 0xff, BT848_E_HACTIVE_LO+off); - btwrite(geo->hdelay & 0xff, BT848_E_HDELAY_LO+off); - btwrite(geo->sheight & 0xff, BT848_E_VACTIVE_LO+off); - btwrite(geo->vdelay & 0xff, BT848_E_VDELAY_LO+off); - btwrite(geo->crop, BT848_E_CROP+off); + btwrite(geo->vtc, BT848_E_VTC+off); + btwrite(geo->hscale >> 8, BT848_E_HSCALE_HI+off); + btwrite(geo->hscale & 0xff, BT848_E_HSCALE_LO+off); + btaor((geo->vscale>>8), 0xe0, BT848_E_VSCALE_HI+off); + btwrite(geo->vscale & 0xff, BT848_E_VSCALE_LO+off); + btwrite(geo->width & 0xff, BT848_E_HACTIVE_LO+off); + btwrite(geo->hdelay & 0xff, BT848_E_HDELAY_LO+off); + btwrite(geo->sheight & 0xff, BT848_E_VACTIVE_LO+off); + btwrite(geo->vdelay & 0xff, BT848_E_VDELAY_LO+off); + btwrite(geo->crop, BT848_E_CROP+off); btwrite(geo->vtotal>>8, BT848_VTOTAL_HI); - btwrite(geo->vtotal & 0xff, BT848_VTOTAL_LO); + btwrite(geo->vtotal & 0xff, BT848_VTOTAL_LO); } /* ---------------------------------------------------------- */ @@ -420,7 +420,7 @@ bttv_set_dma(struct bttv *btv, int override) } else { del_timer(&btv->timeout); } - btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd); + btv->main.cpu[RISC_SLOT_LOOP] = cpu_to_le32(cmd); btaor(capctl, ~0x0f, BT848_CAP_CTL); if (capctl) { @@ -432,7 +432,7 @@ bttv_set_dma(struct bttv *btv, int override) } else { if (!btv->dma_on) return; - btand(~3, BT848_GPIO_DMA_CTL); + btand(~3, BT848_GPIO_DMA_CTL); btv->dma_on = 0; } return; @@ -460,19 +460,19 @@ bttv_risc_init_main(struct bttv *btv) btv->main.cpu[6] = cpu_to_le32(BT848_RISC_JUMP); btv->main.cpu[7] = cpu_to_le32(btv->main.dma + (8<<2)); - btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC | + btv->main.cpu[8] = cpu_to_le32(BT848_RISC_SYNC | BT848_RISC_RESYNC | BT848_FIFO_STATUS_VRO); - btv->main.cpu[9] = cpu_to_le32(0); + btv->main.cpu[9] = cpu_to_le32(0); /* bottom field */ - btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP); + btv->main.cpu[10] = cpu_to_le32(BT848_RISC_JUMP); btv->main.cpu[11] = cpu_to_le32(btv->main.dma + (12<<2)); - btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP); + btv->main.cpu[12] = cpu_to_le32(BT848_RISC_JUMP); btv->main.cpu[13] = cpu_to_le32(btv->main.dma + (14<<2)); /* jump back to top field */ btv->main.cpu[14] = cpu_to_le32(BT848_RISC_JUMP); - btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2)); + btv->main.cpu[15] = cpu_to_le32(btv->main.dma + (0<<2)); return 0; } diff --git a/drivers/media/video/bttv.h b/drivers/media/video/bttv.h index 26cd117a6df4..124ea41dada4 100644 --- a/drivers/media/video/bttv.h +++ b/drivers/media/video/bttv.h @@ -202,7 +202,7 @@ struct bttv_core { struct list_head subs; /* struct bttv_sub_device */ /* device config */ - unsigned int nr; /* dev nr (for printk("bttv%d: ..."); */ + unsigned int nr; /* dev nr (for printk("bttv%d: ..."); */ unsigned int type; /* card type (pointer into tvcards[]) */ char name[8]; /* dev name */ }; @@ -211,16 +211,16 @@ struct bttv; struct tvcard { - char *name; - unsigned int video_inputs; - unsigned int audio_inputs; - unsigned int tuner; - unsigned int svhs; + char *name; + unsigned int video_inputs; + unsigned int audio_inputs; + unsigned int tuner; + unsigned int svhs; unsigned int digital_mode; // DIGITAL_MODE_CAMERA or DIGITAL_MODE_VIDEO - u32 gpiomask; - u32 muxsel[16]; - u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */ - u32 gpiomask2; /* GPIO MUX mask */ + u32 gpiomask; + u32 muxsel[16]; + u32 audiomux[6]; /* Tuner, Radio, external, internal, mute, stereo */ + u32 gpiomask2; /* GPIO MUX mask */ /* i2c audio flags */ unsigned int no_msp34xx:1; diff --git a/drivers/media/video/bttvp.h b/drivers/media/video/bttvp.h index e0e7c7a84bc5..386f546f7d11 100644 --- a/drivers/media/video/bttvp.h +++ b/drivers/media/video/bttvp.h @@ -77,14 +77,14 @@ struct bttv_tvnorm { int v4l2_id; char *name; - u32 Fsc; - u16 swidth, sheight; /* scaled standard width, height */ + u32 Fsc; + u16 swidth, sheight; /* scaled standard width, height */ u16 totalwidth; u8 adelay, bdelay, iform; u32 scaledtwidth; u16 hdelayx1, hactivex1; u16 vdelay; - u8 vbipack; + u8 vbipack; u16 vtotal; int sram; }; @@ -267,8 +267,8 @@ struct bttv { /* card configuration info */ unsigned int cardid; /* pci subsystem id (bt878 based ones) */ - unsigned int tuner_type; /* tuner chip type */ - unsigned int pinnacle_id; + unsigned int tuner_type; /* tuner chip type */ + unsigned int pinnacle_id; unsigned int svhs; struct bttv_pll_info pll; int triton1; @@ -301,9 +301,9 @@ struct bttv { /* locking */ spinlock_t s_lock; - struct semaphore lock; + struct semaphore lock; int resources; - struct semaphore reslock; + struct semaphore reslock; #ifdef VIDIOC_G_PRIORITY struct v4l2_prio_state prio; #endif diff --git a/drivers/media/video/cx88/cx88-blackbird.c b/drivers/media/video/cx88/cx88-blackbird.c index fac67d98a745..4ae3f78cccf2 100644 --- a/drivers/media/video/cx88/cx88-blackbird.c +++ b/drivers/media/video/cx88/cx88-blackbird.c @@ -436,7 +436,7 @@ static int memory_write(struct cx88_core *core, u32 address, u32 value) static int memory_read(struct cx88_core *core, u32 address, u32 *value) { - int retval; + int retval; u32 val; /* Warning: address is dword address (4 bytes) */ @@ -605,11 +605,11 @@ static int blackbird_load_firmware(struct cx8802_dev *dev) u32 *dataptr; retval = register_write(dev->core, IVTV_REG_VPU, 0xFFFFFFED); - retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); - retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_REFRESH, 0x80000640); - retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A); + retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); + retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_REFRESH, 0x80000640); + retval |= register_write(dev->core, IVTV_REG_ENC_SDRAM_PRECHARGE, 0x1A); msleep(1); - retval |= register_write(dev->core, IVTV_REG_APU, 0); + retval |= register_write(dev->core, IVTV_REG_APU, 0); if (retval < 0) dprintk(0, "Error with register_write\n"); @@ -657,13 +657,13 @@ static int blackbird_load_firmware(struct cx8802_dev *dev) release_firmware(firmware); dprintk(0, "Firmware upload successful.\n"); - retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); - retval |= register_read(dev->core, IVTV_REG_SPU, &value); - retval |= register_write(dev->core, IVTV_REG_SPU, value & 0xFFFFFFFE); + retval |= register_write(dev->core, IVTV_REG_HW_BLOCKS, IVTV_CMD_HW_BLOCKS_RST); + retval |= register_read(dev->core, IVTV_REG_SPU, &value); + retval |= register_write(dev->core, IVTV_REG_SPU, value & 0xFFFFFFFE); msleep(1); retval |= register_read(dev->core, IVTV_REG_VPU, &value); - retval |= register_write(dev->core, IVTV_REG_VPU, value & 0xFFFFFFE8); + retval |= register_write(dev->core, IVTV_REG_VPU, value & 0xFFFFFFE8); if (retval < 0) dprintk(0, "Error with register_write\n"); @@ -876,7 +876,7 @@ static void blackbird_set_default_params(struct cx8802_dev *dev) au_params |= 0; } else if( params->au_bitrate.target >= - mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate ) + mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate ) { /* clamp the bitrate to the max supported by the standard */ params->au_bitrate.target = mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate; @@ -942,7 +942,7 @@ static void blackbird_set_default_params(struct cx8802_dev *dev) /* TODO: implement the stream ID stuff: ts_pid_pmt, ts_pid_audio, ts_pid_video, ts_pid_pcr, ps_size, au_pesid, vi_pesid - */ + */ } #define CHECK_PARAM( name ) ( dev->params.name != params->name ) #define IF_PARAM( name ) if( CHECK_PARAM( name ) ) @@ -1068,7 +1068,7 @@ void blackbird_set_params(struct cx8802_dev *dev, struct v4l2_mpeg_compression * au_params |= 0; } else if( params->au_bitrate.target >= - mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate ) + mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate ) { /* clamp the bitrate to the max supported by the standard */ params->au_bitrate.target = mpeg_audio_bitrates[BITRATES_SIZE-1].layer[layer].rate; @@ -1150,7 +1150,7 @@ void blackbird_set_params(struct cx8802_dev *dev, struct v4l2_mpeg_compression * /* TODO: implement the stream ID stuff: ts_pid_pmt, ts_pid_audio, ts_pid_video, ts_pid_pcr, ps_size, au_pesid, vi_pesid - */ + */ UPDATE_PARAM( ts_pid_pmt ); UPDATE_PARAM( ts_pid_audio ); UPDATE_PARAM( ts_pid_video ); @@ -1712,7 +1712,7 @@ static int __devinit blackbird_probe(struct pci_dev *pci_dev, static void __devexit blackbird_remove(struct pci_dev *pci_dev) { - struct cx8802_dev *dev = pci_get_drvdata(pci_dev); + struct cx8802_dev *dev = pci_get_drvdata(pci_dev); /* blackbird */ blackbird_unregister_video(dev); @@ -1728,8 +1728,8 @@ static struct pci_device_id cx8802_pci_tbl[] = { { .vendor = 0x14f1, .device = 0x8802, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, },{ /* --- end of list --- */ } @@ -1737,10 +1737,10 @@ static struct pci_device_id cx8802_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); static struct pci_driver blackbird_pci_driver = { - .name = "cx88-blackbird", - .id_table = cx8802_pci_tbl, - .probe = blackbird_probe, - .remove = __devexit_p(blackbird_remove), + .name = "cx88-blackbird", + .id_table = cx8802_pci_tbl, + .probe = blackbird_probe, + .remove = __devexit_p(blackbird_remove), .suspend = cx8802_suspend_common, .resume = cx8802_resume_common, }; diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index cf17da836914..504917768794 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -126,27 +126,27 @@ struct cx88_board cx88_boards[] = { .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, - .gpio0 = 0x03ff, + .gpio0 = 0x03ff, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, - .gpio0 = 0x03fe, + .gpio0 = 0x03fe, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, - .gpio0 = 0x03fe, + .gpio0 = 0x03fe, }}, }, - [CX88_BOARD_WINFAST2000XP_EXPERT] = { - .name = "Leadtek Winfast 2000XP Expert", - .tuner_type = TUNER_PHILIPS_4IN1, + [CX88_BOARD_WINFAST2000XP_EXPERT] = { + .name = "Leadtek Winfast 2000XP Expert", + .tuner_type = TUNER_PHILIPS_4IN1, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, .gpio0 = 0x00F5e700, .gpio1 = 0x00003004, .gpio2 = 0x00F5e700, @@ -165,15 +165,15 @@ struct cx88_board cx88_boards[] = { .gpio1 = 0x00003004, .gpio2 = 0x00F5c700, .gpio3 = 0x02000000, - }}, - .radio = { - .type = CX88_RADIO, + }}, + .radio = { + .type = CX88_RADIO, .gpio0 = 0x00F5d700, .gpio1 = 0x00003004, .gpio2 = 0x00F5d700, .gpio3 = 0x02000000, - }, - }, + }, + }, [CX88_BOARD_AVERTV_303] = { .name = "AverTV Studio 303 (M126)", .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -214,32 +214,32 @@ struct cx88_board cx88_boards[] = { .gpio1 = 0x000080c0, .gpio2 = 0x0000ff40, },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, .gpio0 = 0x000040bf, .gpio1 = 0x000080c0, .gpio2 = 0x0000ff40, },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, + .type = CX88_VMUX_SVIDEO, + .vmux = 2, .gpio0 = 0x000040bf, .gpio1 = 0x000080c0, .gpio2 = 0x0000ff40, - }}, - .radio = { + }}, + .radio = { .type = CX88_RADIO, - }, + }, }, [CX88_BOARD_WINFAST_DV2000] = { - .name = "Leadtek Winfast DV2000", - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .name = "Leadtek Winfast DV2000", + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, .gpio0 = 0x0035e700, .gpio1 = 0x00003004, .gpio2 = 0x0035e700, @@ -260,14 +260,14 @@ struct cx88_board cx88_boards[] = { .gpio2 = 0x02000000, .gpio3 = 0x02000000, }}, - .radio = { + .radio = { .type = CX88_RADIO, .gpio0 = 0x0035d700, .gpio1 = 0x00007004, .gpio2 = 0x0035d700, .gpio3 = 0x02000000, }, - }, + }, [CX88_BOARD_LEADTEK_PVR2000] = { // gpio values for PAL version from regspy by DScaler .name = "Leadtek PVR 2000", @@ -296,25 +296,25 @@ struct cx88_board cx88_boards[] = { .blackbird = 1, }, [CX88_BOARD_IODATA_GVVCP3PCI] = { - .name = "IODATA GV-VCP3/PCI", + .name = "IODATA GV-VCP3/PCI", .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, + .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .input = {{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 0, - },{ - .type = CX88_VMUX_COMPOSITE2, - .vmux = 1, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - }}, - }, + .type = CX88_VMUX_COMPOSITE1, + .vmux = 0, + },{ + .type = CX88_VMUX_COMPOSITE2, + .vmux = 1, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + }}, + }, [CX88_BOARD_PROLINK_PLAYTVPVR] = { - .name = "Prolink PlayTV PVR", - .tuner_type = TUNER_PHILIPS_FM1236_MK3, + .name = "Prolink PlayTV PVR", + .tuner_type = TUNER_PHILIPS_FM1236_MK3, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, @@ -348,15 +348,15 @@ struct cx88_board cx88_boards[] = { .type = CX88_VMUX_TELEVISION, .vmux = 0, .gpio0 = 0x0000fde6, - },{ + },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, .gpio0 = 0x0000fde6, // 0x0000fda6 L,R RCA audio in? }}, - .radio = { - .type = CX88_RADIO, + .radio = { + .type = CX88_RADIO, .gpio0 = 0x0000fde2, - }, + }, .blackbird = 1, }, [CX88_BOARD_MSI_TVANYWHERE] = { @@ -372,34 +372,34 @@ struct cx88_board cx88_boards[] = { .gpio0 = 0x00000fbf, .gpio2 = 0x0000fc08, },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, .gpio0 = 0x00000fbf, .gpio2 = 0x0000fc68, },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, + .type = CX88_VMUX_SVIDEO, + .vmux = 2, .gpio0 = 0x00000fbf, .gpio2 = 0x0000fc68, - }}, + }}, }, - [CX88_BOARD_KWORLD_DVB_T] = { - .name = "KWorld/VStream XPert DVB-T", + [CX88_BOARD_KWORLD_DVB_T] = { + .name = "KWorld/VStream XPert DVB-T", .tuner_type = TUNER_ABSENT, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, + .input = {{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, .gpio0 = 0x0700, .gpio2 = 0x0101, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, .gpio0 = 0x0700, .gpio2 = 0x0101, - }}, + }}, .dvb = 1, }, [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1] = { @@ -425,27 +425,27 @@ struct cx88_board cx88_boards[] = { .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x07f8, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x07f8, },{ .type = CX88_VMUX_DEBUG, .vmux = 0, .gpio0 = 0x07f9, // mono from tuner chip - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x000007fa, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x000007fa, - }}, - .radio = { - .type = CX88_RADIO, - .gpio0 = 0x000007f8, - }, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x000007fa, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x000007fa, + }}, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x000007f8, + }, }, [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_Q] = { .name = "DViCO FusionHDTV 3 Gold-Q", @@ -489,28 +489,28 @@ struct cx88_board cx88_boards[] = { }}, .dvb = 1, }, - [CX88_BOARD_HAUPPAUGE_DVB_T1] = { + [CX88_BOARD_HAUPPAUGE_DVB_T1] = { .name = "Hauppauge Nova-T DVB-T", .tuner_type = TUNER_ABSENT, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - }}, + .type = CX88_VMUX_DVB, + .vmux = 0, + }}, .dvb = 1, }, - [CX88_BOARD_CONEXANT_DVB_T1] = { + [CX88_BOARD_CONEXANT_DVB_T1] = { .name = "Conexant DVB-T reference design", .tuner_type = TUNER_ABSENT, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .input = {{ - .type = CX88_VMUX_DVB, - .vmux = 0, - }}, + .input = {{ + .type = CX88_VMUX_DVB, + .vmux = 0, + }}, .dvb = 1, }, [CX88_BOARD_PROVIDEO_PV259] = { @@ -543,12 +543,12 @@ struct cx88_board cx88_boards[] = { .dvb = 1, }, [CX88_BOARD_DNTV_LIVE_DVB_T] = { - .name = "digitalnow DNTV Live! DVB-T", + .name = "digitalnow DNTV Live! DVB-T", .tuner_type = TUNER_ABSENT, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, - .input = {{ + .input = {{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, .gpio0 = 0x00000700, @@ -705,44 +705,44 @@ struct cx88_board cx88_boards[] = { .gpio0 = 0xbf60, }, }, - [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T] = { + [CX88_BOARD_DVICO_FUSIONHDTV_3_GOLD_T] = { .name = "DViCO FusionHDTV 3 Gold-T", .tuner_type = TUNER_THOMSON_DTT7611, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x97ed, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x97e9, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x97e9, - }}, + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x97ed, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x97e9, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x97e9, + }}, .dvb = 1, - }, - [CX88_BOARD_ADSTECH_DVB_T_PCI] = { - .name = "ADS Tech Instant TV DVB-T PCI", + }, + [CX88_BOARD_ADSTECH_DVB_T_PCI] = { + .name = "ADS Tech Instant TV DVB-T PCI", .tuner_type = TUNER_ABSENT, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .input = {{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, .gpio0 = 0x0700, .gpio2 = 0x0101, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, .gpio0 = 0x0700, .gpio2 = 0x0101, - }}, + }}, .dvb = 1, }, [CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1] = { @@ -762,18 +762,18 @@ struct cx88_board cx88_boards[] = { .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, .input = {{ - .type = CX88_VMUX_TELEVISION, - .vmux = 0, - .gpio0 = 0x87fd, - },{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x87f9, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x87f9, - }}, + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x87fd, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x87f9, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x87f9, + }}, .dvb = 1, }, [CX88_BOARD_AVERMEDIA_ULTRATV_MC_550] = { @@ -805,23 +805,23 @@ struct cx88_board cx88_boards[] = { }, [CX88_BOARD_KWORLD_VSTREAM_EXPERT_DVD] = { /* Alexander Wold */ - .name = "Kworld V-Stream Xpert DVD", - .tuner_type = UNSET, - .input = {{ - .type = CX88_VMUX_COMPOSITE1, - .vmux = 1, - .gpio0 = 0x03000000, - .gpio1 = 0x01000000, - .gpio2 = 0x02000000, - .gpio3 = 0x00100000, - },{ - .type = CX88_VMUX_SVIDEO, - .vmux = 2, - .gpio0 = 0x03000000, + .name = "Kworld V-Stream Xpert DVD", + .tuner_type = UNSET, + .input = {{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x03000000, .gpio1 = 0x01000000, .gpio2 = 0x02000000, .gpio3 = 0x00100000, - }}, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x03000000, + .gpio1 = 0x01000000, + .gpio2 = 0x02000000, + .gpio3 = 0x00100000, + }}, }, [CX88_BOARD_ATI_HDTVWONDER] = { .name = "ATI HDTV Wonder", @@ -892,26 +892,26 @@ struct cx88_subid cx88_subids[] = { .subdevice = 0x00f8, .card = CX88_BOARD_ATI_WONDER_PRO, },{ - .subvendor = 0x107d, - .subdevice = 0x6611, - .card = CX88_BOARD_WINFAST2000XP_EXPERT, + .subvendor = 0x107d, + .subdevice = 0x6611, + .card = CX88_BOARD_WINFAST2000XP_EXPERT, + },{ + .subvendor = 0x107d, + .subdevice = 0x6613, /* NTSC */ + .card = CX88_BOARD_WINFAST2000XP_EXPERT, + },{ + .subvendor = 0x107d, + .subdevice = 0x6620, + .card = CX88_BOARD_WINFAST_DV2000, },{ - .subvendor = 0x107d, - .subdevice = 0x6613, /* NTSC */ - .card = CX88_BOARD_WINFAST2000XP_EXPERT, + .subvendor = 0x107d, + .subdevice = 0x663b, + .card = CX88_BOARD_LEADTEK_PVR2000, },{ .subvendor = 0x107d, - .subdevice = 0x6620, - .card = CX88_BOARD_WINFAST_DV2000, - },{ - .subvendor = 0x107d, - .subdevice = 0x663b, - .card = CX88_BOARD_LEADTEK_PVR2000, - },{ - .subvendor = 0x107d, - .subdevice = 0x663C, - .card = CX88_BOARD_LEADTEK_PVR2000, - },{ + .subdevice = 0x663C, + .card = CX88_BOARD_LEADTEK_PVR2000, + },{ .subvendor = 0x1461, .subdevice = 0x000b, .card = CX88_BOARD_AVERTV_303, @@ -920,13 +920,13 @@ struct cx88_subid cx88_subids[] = { .subdevice = 0x8606, .card = CX88_BOARD_MSI_TVANYWHERE_MASTER, },{ - .subvendor = 0x10fc, - .subdevice = 0xd003, - .card = CX88_BOARD_IODATA_GVVCP3PCI, + .subvendor = 0x10fc, + .subdevice = 0xd003, + .card = CX88_BOARD_IODATA_GVVCP3PCI, },{ - .subvendor = 0x1043, - .subdevice = 0x4823, /* with mpeg encoder */ - .card = CX88_BOARD_ASUS_PVR_416, + .subvendor = 0x1043, + .subdevice = 0x4823, /* with mpeg encoder */ + .card = CX88_BOARD_ASUS_PVR_416, },{ .subvendor = 0x17de, .subdevice = 0x08a6, @@ -943,15 +943,15 @@ struct cx88_subid cx88_subids[] = { .subvendor = 0x18ac, .subdevice = 0xdb00, .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1, - },{ + },{ .subvendor = 0x0070, .subdevice = 0x9002, .card = CX88_BOARD_HAUPPAUGE_DVB_T1, - },{ + },{ .subvendor = 0x14f1, .subdevice = 0x0187, .card = CX88_BOARD_CONEXANT_DVB_T1, - },{ + },{ .subvendor = 0x1540, .subdevice = 0x2580, .card = CX88_BOARD_PROVIDEO_PV259, @@ -960,9 +960,9 @@ struct cx88_subid cx88_subids[] = { .subdevice = 0xdb10, .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS, },{ - .subvendor = 0x1554, - .subdevice = 0x4811, - .card = CX88_BOARD_PIXELVIEW, + .subvendor = 0x1554, + .subdevice = 0x4811, + .card = CX88_BOARD_PIXELVIEW, },{ .subvendor = 0x7063, .subdevice = 0x3000, /* HD-3000 card */ @@ -987,23 +987,23 @@ struct cx88_subid cx88_subids[] = { .subvendor = 0x1421, .subdevice = 0x0334, .card = CX88_BOARD_ADSTECH_DVB_T_PCI, - },{ + },{ .subvendor = 0x153b, .subdevice = 0x1166, .card = CX88_BOARD_TERRATEC_CINERGY_1400_DVB_T1, - },{ + },{ .subvendor = 0x18ac, .subdevice = 0xd500, .card = CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD, - },{ + },{ .subvendor = 0x1461, .subdevice = 0x8011, .card = CX88_BOARD_AVERMEDIA_ULTRATV_MC_550, - },{ + },{ .subvendor = PCI_VENDOR_ID_ATI, .subdevice = 0xa101, .card = CX88_BOARD_ATI_HDTVWONDER, - },{ + },{ .subvendor = 0x107d, .subdevice = 0x665f, .card = CX88_BOARD_WINFAST_DTV1000, diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index d4d39c1751af..f01a631d0c00 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -153,26 +153,26 @@ static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist, } if (bpl <= sg_dma_len(sg)-offset) { /* fits into current chunk */ - *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl); - *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); - offset+=bpl; + *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL|RISC_EOL|bpl); + *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); + offset+=bpl; } else { /* scanline needs to be splitted */ - todo = bpl; - *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL| + todo = bpl; + *(rp++)=cpu_to_le32(RISC_WRITE|RISC_SOL| (sg_dma_len(sg)-offset)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); - todo -= (sg_dma_len(sg)-offset); - offset = 0; - sg++; - while (todo > sg_dma_len(sg)) { - *(rp++)=cpu_to_le32(RISC_WRITE| + *(rp++)=cpu_to_le32(sg_dma_address(sg)+offset); + todo -= (sg_dma_len(sg)-offset); + offset = 0; + sg++; + while (todo > sg_dma_len(sg)) { + *(rp++)=cpu_to_le32(RISC_WRITE| sg_dma_len(sg)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)); + *(rp++)=cpu_to_le32(sg_dma_address(sg)); todo -= sg_dma_len(sg); sg++; } - *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo); + *(rp++)=cpu_to_le32(RISC_WRITE|RISC_EOL|todo); *(rp++)=cpu_to_le32(sg_dma_address(sg)); offset += todo; } @@ -309,7 +309,7 @@ struct sram_channel cx88_sram_channels[] = { .name = "video y / packed", .cmds_start = 0x180040, .ctrl_start = 0x180400, - .cdt = 0x180400 + 64, + .cdt = 0x180400 + 64, .fifo_start = 0x180c00, .fifo_size = 0x002800, .ptr1_reg = MO_DMA21_PTR1, @@ -321,7 +321,7 @@ struct sram_channel cx88_sram_channels[] = { .name = "video u", .cmds_start = 0x180080, .ctrl_start = 0x1804a0, - .cdt = 0x1804a0 + 64, + .cdt = 0x1804a0 + 64, .fifo_start = 0x183400, .fifo_size = 0x000800, .ptr1_reg = MO_DMA22_PTR1, @@ -333,7 +333,7 @@ struct sram_channel cx88_sram_channels[] = { .name = "video v", .cmds_start = 0x1800c0, .ctrl_start = 0x180540, - .cdt = 0x180540 + 64, + .cdt = 0x180540 + 64, .fifo_start = 0x183c00, .fifo_size = 0x000800, .ptr1_reg = MO_DMA23_PTR1, @@ -345,7 +345,7 @@ struct sram_channel cx88_sram_channels[] = { .name = "vbi", .cmds_start = 0x180100, .ctrl_start = 0x1805e0, - .cdt = 0x1805e0 + 64, + .cdt = 0x1805e0 + 64, .fifo_start = 0x184400, .fifo_size = 0x001000, .ptr1_reg = MO_DMA24_PTR1, @@ -357,7 +357,7 @@ struct sram_channel cx88_sram_channels[] = { .name = "audio from", .cmds_start = 0x180140, .ctrl_start = 0x180680, - .cdt = 0x180680 + 64, + .cdt = 0x180680 + 64, .fifo_start = 0x185400, .fifo_size = 0x000200, .ptr1_reg = MO_DMA25_PTR1, @@ -369,7 +369,7 @@ struct sram_channel cx88_sram_channels[] = { .name = "audio to", .cmds_start = 0x180180, .ctrl_start = 0x180720, - .cdt = 0x180680 + 64, /* same as audio IN */ + .cdt = 0x180680 + 64, /* same as audio IN */ .fifo_start = 0x185400, /* same as audio IN */ .fifo_size = 0x000200, /* same as audio IN */ .ptr1_reg = MO_DMA26_PTR1, @@ -1137,7 +1137,7 @@ struct cx88_core* cx88_core_get(struct pci_dev *pci) if (!core->radio_addr) core->radio_addr = cx88_boards[core->board].radio_addr; - printk(KERN_INFO "TV tuner %d at 0x%02x, Radio tuner %d at 0x%02x\n", + printk(KERN_INFO "TV tuner %d at 0x%02x, Radio tuner %d at 0x%02x\n", core->tuner_type, core->tuner_addr<<1, core->radio_type, core->radio_addr<<1); diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 579de88e3081..3be601cfc99b 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -128,7 +128,7 @@ static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe) static u8 reset [] = { 0x50, 0x80 }; static u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 }; static u8 agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF, - 0x00, 0xFF, 0x00, 0x40, 0x40 }; + 0x00, 0xFF, 0x00, 0x40, 0x40 }; static u8 dntv_extra[] = { 0xB5, 0x7A }; static u8 capt_range_cfg[] = { 0x75, 0x32 }; @@ -464,7 +464,7 @@ static int __devinit dvb_probe(struct pci_dev *pci_dev, static void __devexit dvb_remove(struct pci_dev *pci_dev) { - struct cx8802_dev *dev = pci_get_drvdata(pci_dev); + struct cx8802_dev *dev = pci_get_drvdata(pci_dev); /* dvb */ videobuf_dvb_unregister(&dev->dvb); @@ -479,8 +479,8 @@ static struct pci_device_id cx8802_pci_tbl[] = { { .vendor = 0x14f1, .device = 0x8802, - .subvendor = PCI_ANY_ID, - .subdevice = PCI_ANY_ID, + .subvendor = PCI_ANY_ID, + .subdevice = PCI_ANY_ID, },{ /* --- end of list --- */ } @@ -488,10 +488,10 @@ static struct pci_device_id cx8802_pci_tbl[] = { MODULE_DEVICE_TABLE(pci, cx8802_pci_tbl); static struct pci_driver dvb_pci_driver = { - .name = "cx88-dvb", - .id_table = cx8802_pci_tbl, - .probe = dvb_probe, - .remove = __devexit_p(dvb_remove), + .name = "cx88-dvb", + .id_table = cx8802_pci_tbl, + .probe = dvb_probe, + .remove = __devexit_p(dvb_remove), .suspend = cx8802_suspend_common, .resume = cx8802_resume_common, }; diff --git a/drivers/media/video/cx88/cx88-i2c.c b/drivers/media/video/cx88/cx88-i2c.c index 761cebd40dbd..9790d412f192 100644 --- a/drivers/media/video/cx88/cx88-i2c.c +++ b/drivers/media/video/cx88/cx88-i2c.c @@ -3,7 +3,7 @@ cx88-i2c.c -- all the i2c code is here Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) (c) 2002 Yurij Sysoev (c) 1999-2003 Gerd Knorr @@ -90,7 +90,7 @@ static int cx8800_bit_getsda(void *data) static int attach_inform(struct i2c_client *client) { - struct tuner_setup tun_setup; + struct tuner_setup tun_setup; struct cx88_core *core = i2c_get_adapdata(client->adapter); dprintk(1, "%s i2c attach [addr=0x%x,client=%s]\n", @@ -98,7 +98,7 @@ static int attach_inform(struct i2c_client *client) if (!client->driver->command) return 0; - if (core->radio_type != UNSET) { + if (core->radio_type != UNSET) { if ((core->radio_addr==ADDR_UNSET)||(core->radio_addr==client->addr)) { tun_setup.mode_mask = T_RADIO; tun_setup.type = core->radio_type; @@ -106,8 +106,8 @@ static int attach_inform(struct i2c_client *client) client->driver->command (client, TUNER_SET_TYPE_ADDR, &tun_setup); } - } - if (core->tuner_type != UNSET) { + } + if (core->tuner_type != UNSET) { if ((core->tuner_addr==ADDR_UNSET)||(core->tuner_addr==client->addr)) { tun_setup.mode_mask = T_ANALOG_TV; @@ -116,7 +116,7 @@ static int attach_inform(struct i2c_client *client) client->driver->command (client,TUNER_SET_TYPE_ADDR, &tun_setup); } - } + } if (core->tda9887_conf) client->driver->command(client, TDA9887_SET_CONFIG, &core->tda9887_conf); @@ -159,7 +159,7 @@ static struct i2c_adapter cx8800_i2c_adap_template = { }; static struct i2c_client cx8800_i2c_client_template = { - .name = "cx88xx internal", + .name = "cx88xx internal", }; static char *i2c_devs[128] = { @@ -202,10 +202,10 @@ int cx88_i2c_init(struct cx88_core *core, struct pci_dev *pci) core->i2c_adap.dev.parent = &pci->dev; strlcpy(core->i2c_adap.name,core->name,sizeof(core->i2c_adap.name)); - core->i2c_algo.data = core; - i2c_set_adapdata(&core->i2c_adap,core); - core->i2c_adap.algo_data = &core->i2c_algo; - core->i2c_client.adapter = &core->i2c_adap; + core->i2c_algo.data = core; + i2c_set_adapdata(&core->i2c_adap,core); + core->i2c_adap.algo_data = &core->i2c_algo; + core->i2c_client.adapter = &core->i2c_adap; cx8800_bit_setscl(core,1); cx8800_bit_setsda(core,1); diff --git a/drivers/media/video/cx88/cx88-input.c b/drivers/media/video/cx88/cx88-input.c index c27fe4c36f69..38b12ebaa49e 100644 --- a/drivers/media/video/cx88/cx88-input.c +++ b/drivers/media/video/cx88/cx88-input.c @@ -553,7 +553,7 @@ void cx88_ir_irq(struct cx88_core *core) if ((ircode & 0xffff) != 0xeb04) { /* wrong address */ ir_dprintk("pulse distance decoded wrong address\n"); - break; + break; } if (((~ircode >> 24) & 0xff) != ((ircode >> 16) & 0xff)) { /* wrong checksum */ diff --git a/drivers/media/video/cx88/cx88-mpeg.c b/drivers/media/video/cx88/cx88-mpeg.c index 2c4fbe9258d9..35e6d0c2b872 100644 --- a/drivers/media/video/cx88/cx88-mpeg.c +++ b/drivers/media/video/cx88/cx88-mpeg.c @@ -316,14 +316,14 @@ static void cx8802_mpeg_irq(struct cx8802_dev *dev) spin_unlock(&dev->slock); } - /* other general errors */ - if (status & 0x1f0100) { + /* other general errors */ + if (status & 0x1f0100) { dprintk( 0, "general errors: 0x%08x\n", status & 0x1f0100 ); - spin_lock(&dev->slock); + spin_lock(&dev->slock); cx8802_stop_dma(dev); - cx8802_restart_queue(dev,&dev->mpegq); - spin_unlock(&dev->slock); - } + cx8802_restart_queue(dev,&dev->mpegq); + spin_unlock(&dev->slock); + } } #define MAX_IRQ_LOOP 10 @@ -379,8 +379,8 @@ int cx8802_init_common(struct cx8802_dev *dev) } pci_read_config_byte(dev->pci, PCI_CLASS_REVISION, &dev->pci_rev); - pci_read_config_byte(dev->pci, PCI_LATENCY_TIMER, &dev->pci_lat); - printk(KERN_INFO "%s/2: found at %s, rev: %d, irq: %d, " + pci_read_config_byte(dev->pci, PCI_LATENCY_TIMER, &dev->pci_lat); + printk(KERN_INFO "%s/2: found at %s, rev: %d, irq: %d, " "latency: %d, mmio: 0x%lx\n", dev->core->name, pci_name(dev->pci), dev->pci_rev, dev->pci->irq, dev->pci_lat,pci_resource_start(dev->pci,0)); @@ -430,7 +430,7 @@ void cx8802_fini_common(struct cx8802_dev *dev) int cx8802_suspend_common(struct pci_dev *pci_dev, pm_message_t state) { - struct cx8802_dev *dev = pci_get_drvdata(pci_dev); + struct cx8802_dev *dev = pci_get_drvdata(pci_dev); struct cx88_core *core = dev->core; /* stop mpeg dma */ diff --git a/drivers/media/video/cx88/cx88-reg.h b/drivers/media/video/cx88/cx88-reg.h index 0a3a62fc9bbb..d3bf5b17b1d4 100644 --- a/drivers/media/video/cx88/cx88-reg.h +++ b/drivers/media/video/cx88/cx88-reg.h @@ -3,9 +3,9 @@ cx88x-hw.h - CX2388x register offsets Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - 2001 Michael Eskin - 2002 Yurij Sysoev - 2003 Gerd Knorr + 2001 Michael Eskin + 2002 Yurij Sysoev + 2003 Gerd Knorr 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 @@ -728,13 +728,13 @@ #define ColorFormatGamma 0x1000 #define Interlaced 0x1 -#define NonInterlaced 0x0 +#define NonInterlaced 0x0 #define FieldEven 0x1 #define FieldOdd 0x0 -#define TGReadWriteMode 0x0 -#define TGEnableMode 0x1 +#define TGReadWriteMode 0x0 +#define TGEnableMode 0x1 #define DV_CbAlign 0x0 #define DV_Y0Align 0x1 diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 4c99fc39bb2a..f22ccb65de1c 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -100,7 +100,7 @@ static struct cx88_tvnorm tvnorms[] = { .id = V4L2_STD_PAL_I, .cxiformat = VideoFormatPAL, .cxoformat = 0x181f0008, - },{ + },{ .name = "PAL-M", .id = V4L2_STD_PAL_M, .cxiformat = VideoFormatPALM, @@ -470,7 +470,7 @@ static int restart_video_queue(struct cx8800_dev *dev, struct list_head *item; if (!list_empty(&q->active)) { - buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); + buf = list_entry(q->active.next, struct cx88_buffer, vb.queue); dprintk(2,"restart_queue [%p/%d]: restart dma\n", buf, buf->vb.i); start_video_dma(dev, q, buf); @@ -486,7 +486,7 @@ static int restart_video_queue(struct cx8800_dev *dev, for (;;) { if (list_empty(&q->queued)) return 0; - buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue); + buf = list_entry(q->queued.next, struct cx88_buffer, vb.queue); if (NULL == prev) { list_del(&buf->vb.queue); list_add_tail(&buf->vb.queue,&q->active); @@ -783,7 +783,7 @@ static int video_open(struct inode *inode, struct file *file) cx88_call_i2c_clients(core,AUDC_SET_RADIO,NULL); } - return 0; + return 0; } static ssize_t @@ -922,7 +922,7 @@ static int set_control(struct cx88_core *core, struct v4l2_control *ctl) { /* struct cx88_core *core = dev->core; */ struct cx88_ctrl *c = NULL; - u32 v_sat_value; + u32 v_sat_value; u32 value; int i; @@ -1252,7 +1252,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, } int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, - struct cx88_core *core, unsigned int cmd, void *arg, v4l2_kioctl driver_ioctl) + struct cx88_core *core, unsigned int cmd, void *arg, v4l2_kioctl driver_ioctl) { int err; @@ -1399,7 +1399,7 @@ int cx88_do_ioctl(struct inode *inode, struct file *file, int radio, cx88_get_stereo(core ,t); reg = cx_read(MO_DEVICE_STATUS); - t->signal = (reg & (1<<5)) ? 0xffff : 0x0000; + t->signal = (reg & (1<<5)) ? 0xffff : 0x0000; return 0; } case VIDIOC_S_TUNER: @@ -1486,7 +1486,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, struct v4l2_capability *cap = arg; memset(cap,0,sizeof(*cap)); - strcpy(cap->driver, "cx8800"); + strcpy(cap->driver, "cx8800"); strlcpy(cap->card, cx88_boards[core->board].name, sizeof(cap->card)); sprintf(cap->bus_info,"PCI:%s", pci_name(dev->pci)); @@ -1827,8 +1827,8 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, /* print pci info */ pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev); - pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); - printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, " + pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); + printk(KERN_INFO "%s/0: found at %s, rev: %d, irq: %d, " "latency: %d, mmio: 0x%lx\n", core->name, pci_name(pci_dev), dev->pci_rev, pci_dev->irq, dev->pci_lat,pci_resource_start(pci_dev,0)); @@ -1944,7 +1944,7 @@ fail_free: static void __devexit cx8800_finidev(struct pci_dev *pci_dev) { - struct cx8800_dev *dev = pci_get_drvdata(pci_dev); + struct cx8800_dev *dev = pci_get_drvdata(pci_dev); struct cx88_core *core = dev->core; /* stop thread */ diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index ea5c092a779e..baeae1ac992c 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -259,8 +259,8 @@ struct cx88_core { /* pci stuff */ int pci_bus; int pci_slot; - u32 __iomem *lmmio; - u8 __iomem *bmmio; + u32 __iomem *lmmio; + u8 __iomem *bmmio; u32 shadow[SHADOW_MAX]; int pci_irqmask; diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 59f8fa0bea60..f0860532575a 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -2,8 +2,8 @@ em2820-cards.c - driver for Empia EM2800/EM2820/2840 USB video capture devices Copyright (C) 2005 Markus Rechberger - Ludovico Cavedon - Mauro Carvalho Chehab + Ludovico Cavedon + Mauro Carvalho Chehab Based on the em2800 driver from Sascha Sommer diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index f7b8fb035c9e..227a47d6e4bd 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -2,8 +2,8 @@ em2820-core.c - driver for Empia EM2800/EM2820/2840 USB video capture devices Copyright (C) 2005 Markus Rechberger - Ludovico Cavedon - Mauro Carvalho Chehab + Ludovico Cavedon + Mauro Carvalho Chehab Based on the em2800 driver from Sascha Sommer @@ -33,32 +33,32 @@ /* #define ENABLE_DEBUG_ISOC_FRAMES */ -unsigned int core_debug = 0; +unsigned int core_debug; module_param(core_debug,int,0644); MODULE_PARM_DESC(core_debug,"enable debug messages [core]"); #define em2820_coredbg(fmt, arg...) do {\ - if (core_debug) \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __FUNCTION__ , ##arg); } while (0) + if (core_debug) \ + printk(KERN_INFO "%s %s :"fmt, \ + dev->name, __FUNCTION__ , ##arg); } while (0) -unsigned int reg_debug = 0; +unsigned int reg_debug; module_param(reg_debug,int,0644); MODULE_PARM_DESC(reg_debug,"enable debug messages [URB reg]"); #define em2820_regdbg(fmt, arg...) do {\ - if (reg_debug) \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __FUNCTION__ , ##arg); } while (0) + if (reg_debug) \ + printk(KERN_INFO "%s %s :"fmt, \ + dev->name, __FUNCTION__ , ##arg); } while (0) -unsigned int isoc_debug = 0; +unsigned int isoc_debug; module_param(isoc_debug,int,0644); MODULE_PARM_DESC(isoc_debug,"enable debug messages [isoc transfers]"); #define em2820_isocdbg(fmt, arg...) do {\ - if (isoc_debug) \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __FUNCTION__ , ##arg); } while (0) + if (isoc_debug) \ + printk(KERN_INFO "%s %s :"fmt, \ + dev->name, __FUNCTION__ , ##arg); } while (0) static int alt = EM2820_PINOUT; module_param(alt, int, 0644); diff --git a/drivers/media/video/em28xx/em28xx-i2c.c b/drivers/media/video/em28xx/em28xx-i2c.c index f6bfc038777e..bfe0d8795b6d 100644 --- a/drivers/media/video/em28xx/em28xx-i2c.c +++ b/drivers/media/video/em28xx/em28xx-i2c.c @@ -2,8 +2,8 @@ em2820-i2c.c - driver for Empia EM2800/EM2820/2840 USB video capture devices Copyright (C) 2005 Markus Rechberger - Ludovico Cavedon - Mauro Carvalho Chehab + Ludovico Cavedon + Mauro Carvalho Chehab Based on the em2800 driver from Sascha Sommer diff --git a/drivers/media/video/em28xx/em28xx-input.c b/drivers/media/video/em28xx/em28xx-input.c index ba367a9796e7..8681a793a0bf 100644 --- a/drivers/media/video/em28xx/em28xx-input.c +++ b/drivers/media/video/em28xx/em28xx-input.c @@ -43,34 +43,34 @@ MODULE_PARM_DESC(ir_debug,"enable debug messages [IR]"); /* ---------------------------------------------------------------------- */ static IR_KEYTAB_TYPE ir_codes_em_terratec[IR_KEYTAB_SIZE] = { - [ 0x01 ] = KEY_CHANNEL, - [ 0x02 ] = KEY_SELECT, - [ 0x03 ] = KEY_MUTE, - [ 0x04 ] = KEY_POWER, - [ 0x05 ] = KEY_KP1, - [ 0x06 ] = KEY_KP2, - [ 0x07 ] = KEY_KP3, - [ 0x08 ] = KEY_CHANNELUP, - [ 0x09 ] = KEY_KP4, - [ 0x0a ] = KEY_KP5, - [ 0x0b ] = KEY_KP6, - [ 0x0c ] = KEY_CHANNELDOWN, - [ 0x0d ] = KEY_KP7, - [ 0x0e ] = KEY_KP8, - [ 0x0f ] = KEY_KP9, - [ 0x10 ] = KEY_VOLUMEUP, - [ 0x11 ] = KEY_KP0, - [ 0x12 ] = KEY_MENU, - [ 0x13 ] = KEY_PRINT, - [ 0x14 ] = KEY_VOLUMEDOWN, - [ 0x16 ] = KEY_PAUSE, - [ 0x18 ] = KEY_RECORD, - [ 0x19 ] = KEY_REWIND, - [ 0x1a ] = KEY_PLAY, + [ 0x01 ] = KEY_CHANNEL, + [ 0x02 ] = KEY_SELECT, + [ 0x03 ] = KEY_MUTE, + [ 0x04 ] = KEY_POWER, + [ 0x05 ] = KEY_KP1, + [ 0x06 ] = KEY_KP2, + [ 0x07 ] = KEY_KP3, + [ 0x08 ] = KEY_CHANNELUP, + [ 0x09 ] = KEY_KP4, + [ 0x0a ] = KEY_KP5, + [ 0x0b ] = KEY_KP6, + [ 0x0c ] = KEY_CHANNELDOWN, + [ 0x0d ] = KEY_KP7, + [ 0x0e ] = KEY_KP8, + [ 0x0f ] = KEY_KP9, + [ 0x10 ] = KEY_VOLUMEUP, + [ 0x11 ] = KEY_KP0, + [ 0x12 ] = KEY_MENU, + [ 0x13 ] = KEY_PRINT, + [ 0x14 ] = KEY_VOLUMEDOWN, + [ 0x16 ] = KEY_PAUSE, + [ 0x18 ] = KEY_RECORD, + [ 0x19 ] = KEY_REWIND, + [ 0x1a ] = KEY_PLAY, [ 0x1b ] = KEY_FORWARD, [ 0x1c ] = KEY_BACKSPACE, - [ 0x1e ] = KEY_STOP, - [ 0x40 ] = KEY_ZOOM, + [ 0x1e ] = KEY_STOP, + [ 0x40 ] = KEY_ZOOM, }; /* ----------------------------------------------------------------------- */ diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 048ad1d77bab..e5066d05697e 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -2,8 +2,8 @@ em2820-video.c - driver for Empia EM2800/EM2820/2840 USB video capture devices Copyright (C) 2005 Markus Rechberger - Ludovico Cavedon - Mauro Carvalho Chehab + Ludovico Cavedon + Mauro Carvalho Chehab Based on the em2800 driver from Sascha Sommer @@ -42,9 +42,9 @@ #define EM2820_VERSION_CODE KERNEL_VERSION(0, 0, 1) #define em2820_videodbg(fmt, arg...) do {\ - if (video_debug) \ - printk(KERN_INFO "%s %s :"fmt, \ - dev->name, __FUNCTION__ , ##arg); } while (0) + if (video_debug) \ + printk(KERN_INFO "%s %s :"fmt, \ + dev->name, __FUNCTION__ , ##arg); } while (0) MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/media/video/em28xx/em28xx.h b/drivers/media/video/em28xx/em28xx.h index a11df04a8c3d..c48354062eb6 100644 --- a/drivers/media/video/em28xx/em28xx.h +++ b/drivers/media/video/em28xx/em28xx.h @@ -2,8 +2,8 @@ em2820-cards.c - driver for Empia EM2800/EM2820/2840 USB video capture devices Copyright (C) 2005 Markus Rechberger - Ludovico Cavedon - Mauro Carvalho Chehab + Ludovico Cavedon + Mauro Carvalho Chehab Based on the em2800 driver from Sascha Sommer @@ -390,17 +390,17 @@ extern const unsigned int em2820_bcount; /* printk macros */ #define em2820_err(fmt, arg...) do {\ - printk(KERN_ERR fmt , ##arg); } while (0) + printk(KERN_ERR fmt , ##arg); } while (0) #define em2820_errdev(fmt, arg...) do {\ - printk(KERN_ERR "%s: "fmt,\ + printk(KERN_ERR "%s: "fmt,\ dev->name , ##arg); } while (0) #define em2820_info(fmt, arg...) do {\ - printk(KERN_INFO "%s: "fmt,\ + printk(KERN_INFO "%s: "fmt,\ dev->name , ##arg); } while (0) #define em2820_warn(fmt, arg...) do {\ - printk(KERN_WARNING "%s: "fmt,\ + printk(KERN_WARNING "%s: "fmt,\ dev->name , ##arg); } while (0) inline static int em2820_audio_source(struct em2820 *dev, int input) diff --git a/drivers/media/video/ir-kbd-gpio.c b/drivers/media/video/ir-kbd-gpio.c index cc5973950c05..ed81934ef3cd 100644 --- a/drivers/media/video/ir-kbd-gpio.c +++ b/drivers/media/video/ir-kbd-gpio.c @@ -369,14 +369,14 @@ static int ir_probe(struct device *dev) ir->mask_keycode = 0x003e00; ir->mask_keyup = 0x010000; ir->polling = 50; // ms - break; + break; case BTTV_BOARD_PV_BT878P_9B: case BTTV_BOARD_PV_BT878P_PLUS: ir_codes = ir_codes_pixelview; ir->mask_keycode = 0x001f00; ir->mask_keyup = 0x008000; ir->polling = 50; // ms - break; + break; case BTTV_BOARD_WINFAST2000: ir_codes = ir_codes_winfast; diff --git a/drivers/media/video/ir-kbd-i2c.c b/drivers/media/video/ir-kbd-i2c.c index b0facaa40b2f..12f1053137da 100644 --- a/drivers/media/video/ir-kbd-i2c.c +++ b/drivers/media/video/ir-kbd-i2c.c @@ -163,7 +163,7 @@ static int get_key_haup(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { - unsigned char b; + unsigned char b; /* poll IR chip */ if (1 != i2c_master_recv(&ir->c,&b,1)) { @@ -177,7 +177,7 @@ static int get_key_pixelview(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) static int get_key_pv951(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { - unsigned char b; + unsigned char b; /* poll IR chip */ if (1 != i2c_master_recv(&ir->c,&b,1)) { @@ -225,7 +225,7 @@ static int get_key_knc1(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) static int get_key_purpletv(struct IR_i2c *ir, u32 *ir_key, u32 *ir_raw) { - unsigned char b; + unsigned char b; /* poll IR chip */ if (1 != i2c_master_recv(&ir->c,&b,1)) { @@ -287,17 +287,17 @@ static int ir_detach(struct i2c_client *client); static int ir_probe(struct i2c_adapter *adap); static struct i2c_driver driver = { - .name = "ir remote kbd driver", - .id = I2C_DRIVERID_EXP3, /* FIXME */ - .flags = I2C_DF_NOTIFY, - .attach_adapter = ir_probe, - .detach_client = ir_detach, + .name = "ir remote kbd driver", + .id = I2C_DRIVERID_EXP3, /* FIXME */ + .flags = I2C_DF_NOTIFY, + .attach_adapter = ir_probe, + .detach_client = ir_detach, }; static struct i2c_client client_template = { - .name = "unset", - .driver = &driver + .name = "unset", + .driver = &driver }; static int ir_attach(struct i2c_adapter *adap, int addr, @@ -398,7 +398,7 @@ static int ir_attach(struct i2c_adapter *adap, int addr, static int ir_detach(struct i2c_client *client) { - struct IR_i2c *ir = i2c_get_clientdata(client); + struct IR_i2c *ir = i2c_get_clientdata(client); /* kill outstanding polls */ del_timer(&ir->timer); diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index 5573f68ce457..699cea2cc648 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -192,7 +192,7 @@ static int msp3400c_reset(struct i2c_client *client) (2 != i2c_transfer(client->adapter,test,2)) ) { printk(KERN_ERR "msp3400: chip reset failed\n"); return -1; - } + } return 0; } @@ -200,16 +200,16 @@ static int msp3400c_read(struct i2c_client *client, int dev, int addr) { int err,retval; - unsigned char write[3]; - unsigned char read[2]; - struct i2c_msg msgs[2] = { - { client->addr, 0, 3, write }, - { client->addr, I2C_M_RD, 2, read } - }; + unsigned char write[3]; + unsigned char read[2]; + struct i2c_msg msgs[2] = { + { client->addr, 0, 3, write }, + { client->addr, I2C_M_RD, 2, read } + }; - write[0] = dev+1; - write[1] = addr >> 8; - write[2] = addr & 0xff; + write[0] = dev+1; + write[1] = addr >> 8; + write[2] = addr & 0xff; for (err = 0; err < 3;) { if (2 == i2c_transfer(client->adapter,msgs,2)) @@ -236,13 +236,13 @@ static int msp3400c_read(struct i2c_client *client, int dev, int addr) static int msp3400c_write(struct i2c_client *client, int dev, int addr, int val) { int err; - unsigned char buffer[5]; + unsigned char buffer[5]; - buffer[0] = dev; - buffer[1] = addr >> 8; - buffer[2] = addr & 0xff; - buffer[3] = val >> 8; - buffer[4] = val & 0xff; + buffer[0] = dev; + buffer[1] = addr >> 8; + buffer[2] = addr & 0xff; + buffer[3] = val >> 8; + buffer[4] = val & 0xff; dprintk_trace("trace: msp3400c_write(0x%x, 0x%x, 0x%x)\n", dev, addr, val); @@ -812,7 +812,7 @@ static void watch_stereo(struct i2c_client *client) else if (msp->stereo & VIDEO_SOUND_LANG1) msp3400c_setstereo(client, V4L2_TUNER_MODE_LANG1); else - msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); + msp3400c_setstereo(client, V4L2_TUNER_MODE_MONO); } if (once) @@ -1512,21 +1512,21 @@ static struct i2c_client client_template = static int msp_attach(struct i2c_adapter *adap, int addr, int kind) { struct msp3400c *msp; - struct i2c_client *c; + struct i2c_client *c; int (*thread_func)(void *data) = NULL; int i; - client_template.adapter = adap; - client_template.addr = addr; + client_template.adapter = adap; + client_template.addr = addr; - if (-1 == msp3400c_reset(&client_template)) { - dprintk("msp34xx: no chip found\n"); - return -1; - } + if (-1 == msp3400c_reset(&client_template)) { + dprintk("msp34xx: no chip found\n"); + return -1; + } - if (NULL == (c = kmalloc(sizeof(struct i2c_client),GFP_KERNEL))) - return -ENOMEM; - memcpy(c,&client_template,sizeof(struct i2c_client)); + if (NULL == (c = kmalloc(sizeof(struct i2c_client),GFP_KERNEL))) + return -ENOMEM; + memcpy(c,&client_template,sizeof(struct i2c_client)); if (NULL == (msp = kmalloc(sizeof(struct msp3400c),GFP_KERNEL))) { kfree(c); return -ENOMEM; @@ -1618,7 +1618,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) } /* done */ - i2c_attach_client(c); + i2c_attach_client(c); /* update our own array */ for (i = 0; i < MSP3400_MAX; i++) { @@ -1739,7 +1739,7 @@ static void msp_any_set_audmode(struct i2c_client *client, int audmode) static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct msp3400c *msp = i2c_get_clientdata(client); - __u16 *sarg = arg; + __u16 *sarg = arg; int scart = 0; switch (cmd) { @@ -1969,7 +1969,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) } msp_any_detect_stereo(client); - if (msp->audmode == V4L2_TUNER_MODE_STEREO) { + if (msp->audmode == V4L2_TUNER_MODE_STEREO) { a->capability=V4L2_AUDCAP_STEREO; } @@ -2005,7 +2005,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) msp3400c_set_scart(client,scart,0); msp3400c_write(client,I2C_MSP3400C_DFP,0x000d,0x1900); } - if (sarg->capability==V4L2_AUDCAP_STEREO) { + if (sarg->capability==V4L2_AUDCAP_STEREO) { msp->audmode = V4L2_TUNER_MODE_STEREO; } else { msp->audmode &= ~V4L2_TUNER_MODE_STEREO; diff --git a/drivers/media/video/mt20xx.c b/drivers/media/video/mt20xx.c index 972aa5e0aeef..13b61c4dcbf8 100644 --- a/drivers/media/video/mt20xx.c +++ b/drivers/media/video/mt20xx.c @@ -76,17 +76,17 @@ static int mt2032_compute_freq(struct i2c_client *c, unsigned int xogc) //all in Hz { struct tuner *t = i2c_get_clientdata(c); - unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1, + unsigned int fref,lo1,lo1n,lo1a,s,sel,lo1freq, desired_lo1, desired_lo2,lo2,lo2n,lo2a,lo2num,lo2freq; - fref= 5250 *1000; //5.25MHz + fref= 5250 *1000; //5.25MHz desired_lo1=rfin+if1; lo1=(2*(desired_lo1/1000)+(fref/1000)) / (2*fref/1000); - lo1n=lo1/8; - lo1a=lo1-(lo1n*8); + lo1n=lo1/8; + lo1a=lo1-(lo1n*8); - s=rfin/1000/1000+1090; + s=rfin/1000/1000+1090; if(optimize_vco) { if(s>1890) sel=0; @@ -96,34 +96,34 @@ static int mt2032_compute_freq(struct i2c_client *c, else sel=4; // >1090 } else { - if(s>1790) sel=0; // <1958 - else if(s>1617) sel=1; - else if(s>1449) sel=2; - else if(s>1291) sel=3; - else sel=4; // >1090 + if(s>1790) sel=0; // <1958 + else if(s>1617) sel=1; + else if(s>1449) sel=2; + else if(s>1291) sel=3; + else sel=4; // >1090 } *ret_sel=sel; - lo1freq=(lo1a+8*lo1n)*fref; + lo1freq=(lo1a+8*lo1n)*fref; tuner_dbg("mt2032: rfin=%d lo1=%d lo1n=%d lo1a=%d sel=%d, lo1freq=%d\n", rfin,lo1,lo1n,lo1a,sel,lo1freq); - desired_lo2=lo1freq-rfin-if2; - lo2=(desired_lo2)/fref; - lo2n=lo2/8; - lo2a=lo2-(lo2n*8); - lo2num=((desired_lo2/1000)%(fref/1000))* 3780/(fref/1000); //scale to fit in 32bit arith - lo2freq=(lo2a+8*lo2n)*fref + lo2num*(fref/1000)/3780*1000; + desired_lo2=lo1freq-rfin-if2; + lo2=(desired_lo2)/fref; + lo2n=lo2/8; + lo2a=lo2-(lo2n*8); + lo2num=((desired_lo2/1000)%(fref/1000))* 3780/(fref/1000); //scale to fit in 32bit arith + lo2freq=(lo2a+8*lo2n)*fref + lo2num*(fref/1000)/3780*1000; tuner_dbg("mt2032: rfin=%d lo2=%d lo2n=%d lo2a=%d num=%d lo2freq=%d\n", rfin,lo2,lo2n,lo2a,lo2num,lo2freq); - if(lo1a<0 || lo1a>7 || lo1n<17 ||lo1n>48 || lo2a<0 ||lo2a >7 ||lo2n<17 || lo2n>30) { + if(lo1a<0 || lo1a>7 || lo1n<17 ||lo1n>48 || lo2a<0 ||lo2a >7 ||lo2n<17 || lo2n>30) { tuner_info("mt2032: frequency parameters out of range: %d %d %d %d\n", lo1a, lo1n, lo2a,lo2n); - return(-1); - } + return(-1); + } mt2032_spurcheck(c, lo1freq, desired_lo2, spectrum_from, spectrum_to); // should recalculate lo1 (one step up/down) @@ -135,10 +135,10 @@ static int mt2032_compute_freq(struct i2c_client *c, buf[3]=0x0f; //reserved buf[4]=0x1f; buf[5]=(lo2n-1) | (lo2a<<5); - if(rfin >400*1000*1000) - buf[6]=0xe4; - else - buf[6]=0xf4; // set PKEN per rev 1.2 + if(rfin >400*1000*1000) + buf[6]=0xe4; + else + buf[6]=0xf4; // set PKEN per rev 1.2 buf[7]=8+xogc; buf[8]=0xc3; //reserved buf[9]=0x4e; //reserved @@ -168,7 +168,7 @@ static int mt2032_check_lo_lock(struct i2c_client *c) tuner_dbg("mt2032: pll wait 1ms for lock (0x%2x)\n",buf[0]); udelay(1000); } - return lock; + return lock; } static int mt2032_optimize_vco(struct i2c_client *c,int sel,int lock) @@ -202,7 +202,7 @@ static int mt2032_optimize_vco(struct i2c_client *c,int sel,int lock) buf[0]=0x0f; buf[1]=sel; - i2c_master_send(c,buf,2); + i2c_master_send(c,buf,2); lock=mt2032_check_lo_lock(c); return lock; } @@ -219,23 +219,23 @@ static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin, tuner_dbg("mt2032_set_if_freq rfin=%d if1=%d if2=%d from=%d to=%d\n", rfin,if1,if2,from,to); - buf[0]=0; - ret=i2c_master_send(c,buf,1); - i2c_master_recv(c,buf,21); + buf[0]=0; + ret=i2c_master_send(c,buf,1); + i2c_master_recv(c,buf,21); buf[0]=0; ret=mt2032_compute_freq(c,rfin,if1,if2,from,to,&buf[1],&sel,t->xogc); if (ret<0) return; - // send only the relevant registers per Rev. 1.2 - buf[0]=0; - ret=i2c_master_send(c,buf,4); - buf[5]=5; - ret=i2c_master_send(c,buf+5,4); - buf[11]=11; - ret=i2c_master_send(c,buf+11,3); - if(ret!=3) + // send only the relevant registers per Rev. 1.2 + buf[0]=0; + ret=i2c_master_send(c,buf,4); + buf[5]=5; + ret=i2c_master_send(c,buf+5,4); + buf[11]=11; + ret=i2c_master_send(c,buf+11,3); + if(ret!=3) tuner_warn("i2c i/o error: rc == %d (should be 3)\n",ret); // wait for PLLs to lock (per manual), retry LINT if not. @@ -253,7 +253,7 @@ static void mt2032_set_if_freq(struct i2c_client *c, unsigned int rfin, mdelay(10); buf[1]=8+t->xogc; i2c_master_send(c,buf,2); - } + } if (lock!=6) tuner_warn("MT2032 Fatal Error: PLLs didn't lock.\n"); @@ -284,7 +284,7 @@ static void mt2032_set_tv_freq(struct i2c_client *c, unsigned int freq) if2 = 38900*1000; } - mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */, + mt2032_set_if_freq(c, freq*62500 /* freq*1000*1000/16 */, 1090*1000*1000, if2, from, to); } @@ -294,7 +294,7 @@ static void mt2032_set_radio_freq(struct i2c_client *c, unsigned int freq) int if2 = t->radio_if2; // per Manual for FM tuning: first if center freq. 1085 MHz - mt2032_set_if_freq(c, freq * 1000 / 16, + mt2032_set_if_freq(c, freq * 1000 / 16, 1085*1000*1000,if2,if2,if2); } @@ -302,57 +302,57 @@ static void mt2032_set_radio_freq(struct i2c_client *c, unsigned int freq) static int mt2032_init(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); - unsigned char buf[21]; - int ret,xogc,xok=0; + unsigned char buf[21]; + int ret,xogc,xok=0; // Initialize Registers per spec. - buf[1]=2; // Index to register 2 - buf[2]=0xff; - buf[3]=0x0f; - buf[4]=0x1f; - ret=i2c_master_send(c,buf+1,4); - - buf[5]=6; // Index register 6 - buf[6]=0xe4; - buf[7]=0x8f; - buf[8]=0xc3; - buf[9]=0x4e; - buf[10]=0xec; - ret=i2c_master_send(c,buf+5,6); - - buf[12]=13; // Index register 13 - buf[13]=0x32; - ret=i2c_master_send(c,buf+12,2); - - // Adjust XOGC (register 7), wait for XOK - xogc=7; - do { + buf[1]=2; // Index to register 2 + buf[2]=0xff; + buf[3]=0x0f; + buf[4]=0x1f; + ret=i2c_master_send(c,buf+1,4); + + buf[5]=6; // Index register 6 + buf[6]=0xe4; + buf[7]=0x8f; + buf[8]=0xc3; + buf[9]=0x4e; + buf[10]=0xec; + ret=i2c_master_send(c,buf+5,6); + + buf[12]=13; // Index register 13 + buf[13]=0x32; + ret=i2c_master_send(c,buf+12,2); + + // Adjust XOGC (register 7), wait for XOK + xogc=7; + do { + tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07); + mdelay(10); + buf[0]=0x0e; + i2c_master_send(c,buf,1); + i2c_master_recv(c,buf,1); + xok=buf[0]&0x01; + tuner_dbg("mt2032: xok = 0x%02x\n",xok); + if (xok == 1) break; + + xogc--; tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07); - mdelay(10); - buf[0]=0x0e; - i2c_master_send(c,buf,1); - i2c_master_recv(c,buf,1); - xok=buf[0]&0x01; - tuner_dbg("mt2032: xok = 0x%02x\n",xok); - if (xok == 1) break; - - xogc--; - tuner_dbg("mt2032: xogc = 0x%02x\n",xogc&0x07); - if (xogc == 3) { - xogc=4; // min. 4 per spec - break; - } - buf[0]=0x07; - buf[1]=0x88 + xogc; - ret=i2c_master_send(c,buf,2); - if (ret!=2) + if (xogc == 3) { + xogc=4; // min. 4 per spec + break; + } + buf[0]=0x07; + buf[1]=0x88 + xogc; + ret=i2c_master_send(c,buf,2); + if (ret!=2) tuner_warn("i2c i/o error: rc == %d (should be 2)\n",ret); - } while (xok != 1 ); + } while (xok != 1 ); t->xogc=xogc; t->tv_freq = mt2032_set_tv_freq; t->radio_freq = mt2032_set_radio_freq; - return(1); + return(1); } static void mt2050_set_antenna(struct i2c_client *c, unsigned char antenna) @@ -426,7 +426,7 @@ static void mt2050_set_if_freq(struct i2c_client *c,unsigned int freq, unsigned } ret=i2c_master_send(c,buf,6); - if (ret!=6) + if (ret!=6) tuner_warn("i2c i/o error: rc == %d (should be 6)\n",ret); } @@ -437,11 +437,11 @@ static void mt2050_set_tv_freq(struct i2c_client *c, unsigned int freq) if (t->std & V4L2_STD_525_60) { // NTSC - if2 = 45750*1000; - } else { - // PAL - if2 = 38900*1000; - } + if2 = 45750*1000; + } else { + // PAL + if2 = 38900*1000; + } if (V4L2_TUNER_DIGITAL_TV == t->mode) { // DVB (pinnacle 300i) if2 = 36150*1000; @@ -487,7 +487,7 @@ int microtune_init(struct i2c_client *c) { struct tuner *t = i2c_get_clientdata(c); char *name; - unsigned char buf[21]; + unsigned char buf[21]; int company_code; memset(buf,0,sizeof(buf)); @@ -496,17 +496,17 @@ int microtune_init(struct i2c_client *c) t->standby = NULL; name = "unknown"; - i2c_master_send(c,buf,1); - i2c_master_recv(c,buf,21); - if (tuner_debug) { - int i; + i2c_master_send(c,buf,1); + i2c_master_recv(c,buf,21); + if (tuner_debug) { + int i; tuner_dbg("MT20xx hexdump:"); - for(i=0;i<21;i++) { - printk(" %02x",buf[i]); - if(((i+1)%8)==0) printk(" "); - } - printk("\n"); - } + for(i=0;i<21;i++) { + printk(" %02x",buf[i]); + if(((i+1)%8)==0) printk(" "); + } + printk("\n"); + } company_code = buf[0x11] << 8 | buf[0x12]; tuner_info("microtune: companycode=%04x part=%02x rev=%02x\n", company_code,buf[0x13],buf[0x14]); @@ -525,8 +525,8 @@ int microtune_init(struct i2c_client *c) default: tuner_info("microtune %s found, not (yet?) supported, sorry :-/\n", name); - return 0; - } + return 0; + } strlcpy(c->name, name, sizeof(c->name)); tuner_info("microtune %s found, OK\n",name); diff --git a/drivers/media/video/saa711x.c b/drivers/media/video/saa711x.c index 37653ee87235..ed16282fca51 100644 --- a/drivers/media/video/saa711x.c +++ b/drivers/media/video/saa711x.c @@ -464,8 +464,8 @@ saa7113_command (struct i2c_client *client, /* standard i2c insmod options */ static unsigned short normal_i2c[] = { - I2C_SAA7113>>1, /* saa7113 */ - I2C_CLIENT_END + I2C_SAA7113>>1, /* saa7113 */ + I2C_CLIENT_END }; I2C_CLIENT_INSMOD; diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index dac720ea3b06..2bf5cf79eec1 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c @@ -169,31 +169,31 @@ static int saa6752hs_chip_command(struct i2c_client* client, /* execute the command */ switch(command) { - case SAA6752HS_COMMAND_RESET: - buf[0] = 0x00; + case SAA6752HS_COMMAND_RESET: + buf[0] = 0x00; break; case SAA6752HS_COMMAND_STOP: - buf[0] = 0x03; + buf[0] = 0x03; break; case SAA6752HS_COMMAND_START: - buf[0] = 0x02; + buf[0] = 0x02; break; case SAA6752HS_COMMAND_PAUSE: - buf[0] = 0x04; + buf[0] = 0x04; break; case SAA6752HS_COMMAND_RECONFIGURE: buf[0] = 0x05; break; - case SAA6752HS_COMMAND_SLEEP: - buf[0] = 0x06; + case SAA6752HS_COMMAND_SLEEP: + buf[0] = 0x06; break; - case SAA6752HS_COMMAND_RECONFIGURE_FORCE: + case SAA6752HS_COMMAND_RECONFIGURE_FORCE: buf[0] = 0x07; break; @@ -201,13 +201,13 @@ static int saa6752hs_chip_command(struct i2c_client* client, return -EINVAL; } - /* set it and wait for it to be so */ + /* set it and wait for it to be so */ i2c_master_send(client, buf, 1); timeout = jiffies + HZ * 3; for (;;) { /* get the current status */ buf[0] = 0x10; - i2c_master_send(client, buf, 1); + i2c_master_send(client, buf, 1); i2c_master_recv(client, buf, 1); if (!(buf[0] & 0x20)) @@ -223,14 +223,14 @@ static int saa6752hs_chip_command(struct i2c_client* client, /* delay a bit to let encoder settle */ msleep(50); - return status; + return status; } static int saa6752hs_set_bitrate(struct i2c_client* client, struct v4l2_mpeg_compression* params) { - u8 buf[3]; + u8 buf[3]; /* set the bitrate mode */ buf[0] = 0x71; @@ -242,31 +242,31 @@ static int saa6752hs_set_bitrate(struct i2c_client* client, /* set the target bitrate */ buf[0] = 0x80; buf[1] = params->vi_bitrate.target >> 8; - buf[2] = params->vi_bitrate.target & 0xff; + buf[2] = params->vi_bitrate.target & 0xff; i2c_master_send(client, buf, 3); /* set the max bitrate */ buf[0] = 0x81; buf[1] = params->vi_bitrate.max >> 8; - buf[2] = params->vi_bitrate.max & 0xff; + buf[2] = params->vi_bitrate.max & 0xff; i2c_master_send(client, buf, 3); } else { /* set the target bitrate (no max bitrate for CBR) */ - buf[0] = 0x81; + buf[0] = 0x81; buf[1] = params->vi_bitrate.target >> 8; - buf[2] = params->vi_bitrate.target & 0xff; + buf[2] = params->vi_bitrate.target & 0xff; i2c_master_send(client, buf, 3); } /* set the audio bitrate */ - buf[0] = 0x94; + buf[0] = 0x94; buf[1] = (256 == params->au_bitrate.target) ? 0 : 1; i2c_master_send(client, buf, 2); /* set the total bitrate */ buf[0] = 0xb1; - buf[1] = params->st_bitrate.target >> 8; - buf[2] = params->st_bitrate.target & 0xff; + buf[1] = params->st_bitrate.target >> 8; + buf[2] = params->st_bitrate.target & 0xff; i2c_master_send(client, buf, 3); return 0; @@ -386,8 +386,8 @@ static int saa6752hs_init(struct i2c_client* client) buf[1] = 0x01; i2c_master_send(client, buf, 2); - /* set bitrate */ - saa6752hs_set_bitrate(client, &h->params); + /* set bitrate */ + saa6752hs_set_bitrate(client, &h->params); /* Set GOP structure {3, 13} */ buf[0] = 0x72; @@ -426,9 +426,9 @@ static int saa6752hs_init(struct i2c_client* client) localPAT[sizeof(PAT) - 1] = crc & 0xFF; /* compute PMT */ - memcpy(localPMT, PMT, sizeof(PMT)); - localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f); - localPMT[4] = h->params.ts_pid_pmt & 0xff; + memcpy(localPMT, PMT, sizeof(PMT)); + localPMT[3] = 0x40 | ((h->params.ts_pid_pmt >> 8) & 0x0f); + localPMT[4] = h->params.ts_pid_pmt & 0xff; localPMT[15] = 0xE0 | ((h->params.ts_pid_pcr >> 8) & 0x0F); localPMT[16] = h->params.ts_pid_pcr & 0xFF; localPMT[20] = 0xE0 | ((h->params.ts_pid_video >> 8) & 0x0F); @@ -453,7 +453,7 @@ static int saa6752hs_init(struct i2c_client* client) buf[2] = h->params.ts_pid_video & 0xFF; i2c_master_send(client,buf,3); - /* Set PCR PID */ + /* Set PCR PID */ buf[0] = 0xC4; buf[1] = (h->params.ts_pid_pcr >> 8) & 0xFF; buf[2] = h->params.ts_pid_pcr & 0xFF; @@ -467,7 +467,7 @@ static int saa6752hs_init(struct i2c_client* client) buf[0] = 0xa4; buf[1] = 1; i2c_master_send(client, buf, 2); - buf[1] = 0; + buf[1] = 0; i2c_master_send(client, buf, 2); /* start it going */ @@ -510,10 +510,10 @@ static int saa6752hs_attach(struct i2c_adapter *adap, int addr, int kind) { struct saa6752hs_state *h; - printk("saa6752hs: chip found @ 0x%x\n", addr<<1); + printk("saa6752hs: chip found @ 0x%x\n", addr<<1); - if (NULL == (h = kmalloc(sizeof(*h), GFP_KERNEL))) - return -ENOMEM; + if (NULL == (h = kmalloc(sizeof(*h), GFP_KERNEL))) + return -ENOMEM; memset(h,0,sizeof(*h)); h->client = client_template; h->params = param_defaults; @@ -552,7 +552,7 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) struct v4l2_mpeg_compression *params = arg; int err = 0; - switch (cmd) { + switch (cmd) { case VIDIOC_S_MPEGCOMP: if (NULL == params) { /* apply settings and start encoder */ @@ -566,7 +566,7 @@ saa6752hs_command(struct i2c_client *client, unsigned int cmd, void *arg) break; case VIDIOC_G_FMT: { - struct v4l2_format *f = arg; + struct v4l2_format *f = arg; if (h->video_format == SAA6752HS_VF_UNKNOWN) h->video_format = SAA6752HS_VF_D1; diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 465beac941d7..e9ffe8f144ac 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -80,11 +80,11 @@ typedef struct snd_card_saa7134 { spinlock_t mixer_lock; int mixer_volume[MIXER_ADDR_LAST+1][2]; int capture_source[MIXER_ADDR_LAST+1][2]; - struct pci_dev *pci; - struct saa7134_dev *saadev; + struct pci_dev *pci; + struct saa7134_dev *saadev; - unsigned long iobase; - int irq; + unsigned long iobase; + int irq; spinlock_t lock; } snd_card_saa7134_t; @@ -94,7 +94,7 @@ typedef struct snd_card_saa7134 { */ typedef struct snd_card_saa7134_pcm { - struct saa7134_dev *saadev; + struct saa7134_dev *saadev; spinlock_t lock; unsigned int pcm_size; /* buffer size */ @@ -118,9 +118,9 @@ static snd_card_t *snd_saa7134_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR; static void saa7134_dma_stop(struct saa7134_dev *dev) { - dev->oss.dma_blk = -1; - dev->oss.dma_running = 0; - saa7134_set_dmabits(dev); + dev->oss.dma_blk = -1; + dev->oss.dma_running = 0; + saa7134_set_dmabits(dev); } /* @@ -135,9 +135,9 @@ static void saa7134_dma_stop(struct saa7134_dev *dev) static void saa7134_dma_start(struct saa7134_dev *dev) { - dev->oss.dma_blk = 0; - dev->oss.dma_running = 1; - saa7134_set_dmabits(dev); + dev->oss.dma_blk = 0; + dev->oss.dma_running = 1; + saa7134_set_dmabits(dev); } /* @@ -184,28 +184,28 @@ void saa7134_irq_alsa_done(struct saa7134_dev *dev, unsigned long status) goto done; } - /* next block addr */ - next_blk = (dev->oss.dma_blk + 2) % dev->oss.blocks; - saa_writel(reg,next_blk * dev->oss.blksize); - if (alsa_debug > 2) - dprintk("irq: ok, %s, next_blk=%d, addr=%x, blocks=%u, size=%u, read=%u\n", - (status & 0x10000000) ? "even" : "odd ", next_blk, - next_blk * dev->oss.blksize, dev->oss.blocks, dev->oss.blksize, dev->oss.read_count); + /* next block addr */ + next_blk = (dev->oss.dma_blk + 2) % dev->oss.blocks; + saa_writel(reg,next_blk * dev->oss.blksize); + if (alsa_debug > 2) + dprintk("irq: ok, %s, next_blk=%d, addr=%x, blocks=%u, size=%u, read=%u\n", + (status & 0x10000000) ? "even" : "odd ", next_blk, + next_blk * dev->oss.blksize, dev->oss.blocks, dev->oss.blksize, dev->oss.read_count); - /* update status & wake waiting readers */ - dev->oss.dma_blk = (dev->oss.dma_blk + 1) % dev->oss.blocks; - dev->oss.read_count += dev->oss.blksize; + /* update status & wake waiting readers */ + dev->oss.dma_blk = (dev->oss.dma_blk + 1) % dev->oss.blocks; + dev->oss.read_count += dev->oss.blksize; - dev->oss.recording_on = reg; + dev->oss.recording_on = reg; if (dev->oss.read_count >= snd_pcm_lib_period_bytes(dev->oss.substream)) { - spin_unlock(&dev->slock); - snd_pcm_period_elapsed(dev->oss.substream); - spin_lock(&dev->slock); + spin_unlock(&dev->slock); + snd_pcm_period_elapsed(dev->oss.substream); + spin_lock(&dev->slock); } done: - spin_unlock(&dev->slock); + spin_unlock(&dev->slock); } @@ -239,23 +239,23 @@ static int snd_card_saa7134_capture_trigger(snd_pcm_substream_t * substream, static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) { - if (blksize < 0x100) - blksize = 0x100; - if (blksize > 0x10000) - blksize = 0x10000; - - if (blocks < 2) - blocks = 2; - if ((blksize * blocks) > 1024*1024) - blocks = 1024*1024 / blksize; - - dev->oss.blocks = blocks; - dev->oss.blksize = blksize; - dev->oss.bufsize = blksize * blocks; - - dprintk("buffer config: %d blocks / %d bytes, %d kB total\n", - blocks,blksize,blksize * blocks / 1024); - return 0; + if (blksize < 0x100) + blksize = 0x100; + if (blksize > 0x10000) + blksize = 0x10000; + + if (blocks < 2) + blocks = 2; + if ((blksize * blocks) > 1024*1024) + blocks = 1024*1024 / blksize; + + dev->oss.blocks = blocks; + dev->oss.blksize = blksize; + dev->oss.bufsize = blksize * blocks; + + dprintk("buffer config: %d blocks / %d bytes, %d kB total\n", + blocks,blksize,blksize * blocks / 1024); + return 0; } /* @@ -271,16 +271,16 @@ static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) static int dsp_buffer_init(struct saa7134_dev *dev) { - int err; - - if (!dev->oss.bufsize) - BUG(); - videobuf_dma_init(&dev->oss.dma); - err = videobuf_dma_init_kernel(&dev->oss.dma, PCI_DMA_FROMDEVICE, - (dev->oss.bufsize + PAGE_SIZE) >> PAGE_SHIFT); - if (0 != err) - return err; - return 0; + int err; + + if (!dev->oss.bufsize) + BUG(); + videobuf_dma_init(&dev->oss.dma); + err = videobuf_dma_init_kernel(&dev->oss.dma, PCI_DMA_FROMDEVICE, + (dev->oss.bufsize + PAGE_SIZE) >> PAGE_SHIFT); + if (0 != err) + return err; + return 0; } /* @@ -298,18 +298,18 @@ static int dsp_buffer_init(struct saa7134_dev *dev) static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) { snd_pcm_runtime_t *runtime = substream->runtime; - int err, bswap, sign; - u32 fmt, control; - unsigned long flags; + int err, bswap, sign; + u32 fmt, control; + unsigned long flags; snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); - struct saa7134_dev *dev; + struct saa7134_dev *dev; snd_card_saa7134_pcm_t *saapcm = runtime->private_data; unsigned int bps; - unsigned long size; - unsigned count; + unsigned long size; + unsigned count; - size = snd_pcm_lib_buffer_bytes(substream); - count = snd_pcm_lib_period_bytes(substream); + size = snd_pcm_lib_buffer_bytes(substream); + count = snd_pcm_lib_period_bytes(substream); saapcm->saadev->oss.substream = substream; bps = runtime->rate * runtime->channels; @@ -324,123 +324,123 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) dev=saa7134->saadev; - dsp_buffer_conf(dev,saapcm->pcm_count,(saapcm->pcm_size/saapcm->pcm_count)); + dsp_buffer_conf(dev,saapcm->pcm_count,(saapcm->pcm_size/saapcm->pcm_count)); - err = dsp_buffer_init(dev); - if (0 != err) - goto fail2; + err = dsp_buffer_init(dev); + if (0 != err) + goto fail2; - /* prepare buffer */ - if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->oss.dma))) - return err; - if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->oss.pt))) - goto fail1; - if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->oss.pt, - dev->oss.dma.sglist, - dev->oss.dma.sglen, - 0))) - goto fail2; + /* prepare buffer */ + if (0 != (err = videobuf_dma_pci_map(dev->pci,&dev->oss.dma))) + return err; + if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->oss.pt))) + goto fail1; + if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->oss.pt, + dev->oss.dma.sglist, + dev->oss.dma.sglen, + 0))) + goto fail2; - switch (runtime->format) { - case SNDRV_PCM_FORMAT_U8: - case SNDRV_PCM_FORMAT_S8: + switch (runtime->format) { + case SNDRV_PCM_FORMAT_U8: + case SNDRV_PCM_FORMAT_S8: fmt = 0x00; break; - case SNDRV_PCM_FORMAT_U16_LE: - case SNDRV_PCM_FORMAT_U16_BE: - case SNDRV_PCM_FORMAT_S16_LE: - case SNDRV_PCM_FORMAT_S16_BE: + case SNDRV_PCM_FORMAT_U16_LE: + case SNDRV_PCM_FORMAT_U16_BE: + case SNDRV_PCM_FORMAT_S16_LE: + case SNDRV_PCM_FORMAT_S16_BE: fmt = 0x01; break; - default: - err = -EINVAL; - return 1; - } - - switch (runtime->format) { - case SNDRV_PCM_FORMAT_S8: - case SNDRV_PCM_FORMAT_S16_LE: - case SNDRV_PCM_FORMAT_S16_BE: + default: + err = -EINVAL; + return 1; + } + + switch (runtime->format) { + case SNDRV_PCM_FORMAT_S8: + case SNDRV_PCM_FORMAT_S16_LE: + case SNDRV_PCM_FORMAT_S16_BE: sign = 1; break; - default: + default: sign = 0; break; - } + } - switch (runtime->format) { - case SNDRV_PCM_FORMAT_U16_BE: - case SNDRV_PCM_FORMAT_S16_BE: + switch (runtime->format) { + case SNDRV_PCM_FORMAT_U16_BE: + case SNDRV_PCM_FORMAT_S16_BE: bswap = 1; break; - default: + default: bswap = 0; break; - } - - switch (dev->pci->device) { - case PCI_DEVICE_ID_PHILIPS_SAA7134: - if (1 == runtime->channels) - fmt |= (1 << 3); - if (2 == runtime->channels) - fmt |= (3 << 3); - if (sign) - fmt |= 0x04; - - fmt |= (MIXER_ADDR_TVTUNER == dev->oss.input) ? 0xc0 : 0x80; - saa_writeb(SAA7134_NUM_SAMPLES0, ((dev->oss.blksize - 1) & 0x0000ff)); - saa_writeb(SAA7134_NUM_SAMPLES1, ((dev->oss.blksize - 1) & 0x00ff00) >> 8); - saa_writeb(SAA7134_NUM_SAMPLES2, ((dev->oss.blksize - 1) & 0xff0000) >> 16); - saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt); - - break; - case PCI_DEVICE_ID_PHILIPS_SAA7133: - case PCI_DEVICE_ID_PHILIPS_SAA7135: - if (1 == runtime->channels) - fmt |= (1 << 4); - if (2 == runtime->channels) - fmt |= (2 << 4); - if (!sign) - fmt |= 0x04; - saa_writel(SAA7133_NUM_SAMPLES, dev->oss.blksize -1); - saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24)); - //saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210); - break; - } - - dprintk("rec_start: afmt=%d ch=%d => fmt=0x%x swap=%c\n", - runtime->format, runtime->channels, fmt, - bswap ? 'b' : '-'); - /* dma: setup channel 6 (= AUDIO) */ - control = SAA7134_RS_CONTROL_BURST_16 | - SAA7134_RS_CONTROL_ME | - (dev->oss.pt.dma >> 12); - if (bswap) - control |= SAA7134_RS_CONTROL_BSWAP; + } + + switch (dev->pci->device) { + case PCI_DEVICE_ID_PHILIPS_SAA7134: + if (1 == runtime->channels) + fmt |= (1 << 3); + if (2 == runtime->channels) + fmt |= (3 << 3); + if (sign) + fmt |= 0x04; + + fmt |= (MIXER_ADDR_TVTUNER == dev->oss.input) ? 0xc0 : 0x80; + saa_writeb(SAA7134_NUM_SAMPLES0, ((dev->oss.blksize - 1) & 0x0000ff)); + saa_writeb(SAA7134_NUM_SAMPLES1, ((dev->oss.blksize - 1) & 0x00ff00) >> 8); + saa_writeb(SAA7134_NUM_SAMPLES2, ((dev->oss.blksize - 1) & 0xff0000) >> 16); + saa_writeb(SAA7134_AUDIO_FORMAT_CTRL, fmt); + + break; + case PCI_DEVICE_ID_PHILIPS_SAA7133: + case PCI_DEVICE_ID_PHILIPS_SAA7135: + if (1 == runtime->channels) + fmt |= (1 << 4); + if (2 == runtime->channels) + fmt |= (2 << 4); + if (!sign) + fmt |= 0x04; + saa_writel(SAA7133_NUM_SAMPLES, dev->oss.blksize -1); + saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210 | (fmt << 24)); + //saa_writel(SAA7133_AUDIO_CHANNEL, 0x543210); + break; + } + + dprintk("rec_start: afmt=%d ch=%d => fmt=0x%x swap=%c\n", + runtime->format, runtime->channels, fmt, + bswap ? 'b' : '-'); + /* dma: setup channel 6 (= AUDIO) */ + control = SAA7134_RS_CONTROL_BURST_16 | + SAA7134_RS_CONTROL_ME | + (dev->oss.pt.dma >> 12); + if (bswap) + control |= SAA7134_RS_CONTROL_BSWAP; /* I should be able to use runtime->dma_addr in the control - byte, but it doesn't work. So I allocate the DMA using the - V4L functions, and force ALSA to use that as the DMA area */ + byte, but it doesn't work. So I allocate the DMA using the + V4L functions, and force ALSA to use that as the DMA area */ runtime->dma_area = dev->oss.dma.vmalloc; - saa_writel(SAA7134_RS_BA1(6),0); - saa_writel(SAA7134_RS_BA2(6),dev->oss.blksize); - saa_writel(SAA7134_RS_PITCH(6),0); - saa_writel(SAA7134_RS_CONTROL(6),control); + saa_writel(SAA7134_RS_BA1(6),0); + saa_writel(SAA7134_RS_BA2(6),dev->oss.blksize); + saa_writel(SAA7134_RS_PITCH(6),0); + saa_writel(SAA7134_RS_CONTROL(6),control); dev->oss.rate = runtime->rate; - /* start dma */ - spin_lock_irqsave(&dev->slock,flags); - saa7134_dma_start(dev); - spin_unlock_irqrestore(&dev->slock,flags); + /* start dma */ + spin_lock_irqsave(&dev->slock,flags); + saa7134_dma_start(dev); + spin_unlock_irqrestore(&dev->slock,flags); return 0; fail2: - saa7134_pgtable_free(dev->pci,&dev->oss.pt); + saa7134_pgtable_free(dev->pci,&dev->oss.pt); fail1: - videobuf_dma_pci_unmap(dev->pci,&dev->oss.dma); - return err; + videobuf_dma_pci_unmap(dev->pci,&dev->oss.dma); + return err; } @@ -465,10 +465,10 @@ static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * if (dev->oss.read_count) { - dev->oss.read_count -= snd_pcm_lib_period_bytes(substream); - dev->oss.read_offset += snd_pcm_lib_period_bytes(substream); - if (dev->oss.read_offset == dev->oss.bufsize) - dev->oss.read_offset = 0; + dev->oss.read_count -= snd_pcm_lib_period_bytes(substream); + dev->oss.read_offset += snd_pcm_lib_period_bytes(substream); + if (dev->oss.read_offset == dev->oss.bufsize) + dev->oss.read_offset = 0; } return bytes_to_frames(runtime, dev->oss.read_offset); @@ -480,9 +480,9 @@ static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * static snd_pcm_hardware_t snd_card_saa7134_capture = { - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), + .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID), .formats = USE_FORMATS, .rates = USE_RATE, .rate_min = USE_RATE_MIN, @@ -550,16 +550,16 @@ static int snd_card_saa7134_hw_free(snd_pcm_substream_t * substream) static int dsp_buffer_free(struct saa7134_dev *dev) { - if (!dev->oss.blksize) - BUG(); + if (!dev->oss.blksize) + BUG(); - videobuf_dma_free(&dev->oss.dma); + videobuf_dma_free(&dev->oss.dma); - dev->oss.blocks = 0; - dev->oss.blksize = 0; - dev->oss.bufsize = 0; + dev->oss.blocks = 0; + dev->oss.blksize = 0; + dev->oss.bufsize = 0; - return 0; + return 0; } /* @@ -574,21 +574,21 @@ static int dsp_buffer_free(struct saa7134_dev *dev) static int snd_card_saa7134_capture_close(snd_pcm_substream_t * substream) { - snd_card_saa7134_t *chip = snd_pcm_substream_chip(substream); + snd_card_saa7134_t *chip = snd_pcm_substream_chip(substream); struct saa7134_dev *dev = chip->saadev; - unsigned long flags; + unsigned long flags; - /* stop dma */ - spin_lock_irqsave(&dev->slock,flags); - saa7134_dma_stop(dev); - spin_unlock_irqrestore(&dev->slock,flags); + /* stop dma */ + spin_lock_irqsave(&dev->slock,flags); + saa7134_dma_stop(dev); + spin_unlock_irqrestore(&dev->slock,flags); - /* unlock buffer */ - saa7134_pgtable_free(dev->pci,&dev->oss.pt); - videobuf_dma_pci_unmap(dev->pci,&dev->oss.dma); + /* unlock buffer */ + saa7134_pgtable_free(dev->pci,&dev->oss.pt); + videobuf_dma_pci_unmap(dev->pci,&dev->oss.dma); - dsp_buffer_free(dev); - return 0; + dsp_buffer_free(dev); + return 0; } /* @@ -605,18 +605,18 @@ static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) { snd_pcm_runtime_t *runtime = substream->runtime; snd_card_saa7134_pcm_t *saapcm; - snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); - struct saa7134_dev *dev = saa7134->saadev; + snd_card_saa7134_t *saa7134 = snd_pcm_substream_chip(substream); + struct saa7134_dev *dev = saa7134->saadev; int err; down(&dev->oss.lock); - dev->oss.afmt = SNDRV_PCM_FORMAT_U8; - dev->oss.channels = 2; - dev->oss.read_count = 0; - dev->oss.read_offset = 0; + dev->oss.afmt = SNDRV_PCM_FORMAT_U8; + dev->oss.channels = 2; + dev->oss.read_count = 0; + dev->oss.read_offset = 0; - up(&dev->oss.lock); + up(&dev->oss.lock); saapcm = kcalloc(1, sizeof(*saapcm), GFP_KERNEL); if (saapcm == NULL) @@ -630,8 +630,8 @@ static int snd_card_saa7134_capture_open(snd_pcm_substream_t * substream) runtime->private_free = snd_card_saa7134_runtime_free; runtime->hw = snd_card_saa7134_capture; - if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) - return err; + if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0) + return err; return 0; } @@ -723,7 +723,7 @@ static int snd_saa7134_volume_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ right = 20; spin_lock_irqsave(&chip->mixer_lock, flags); change = chip->mixer_volume[addr][0] != left || - chip->mixer_volume[addr][1] != right; + chip->mixer_volume[addr][1] != right; chip->mixer_volume[addr][0] = left; chip->mixer_volume[addr][1] = right; spin_unlock_irqrestore(&chip->mixer_lock, flags); @@ -764,7 +764,7 @@ static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ unsigned long flags; int change, addr = kcontrol->private_value; int left, right; - u32 anabar, xbarin; + u32 anabar, xbarin; int analog_io, rate; struct saa7134_dev *dev; @@ -775,7 +775,7 @@ static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ spin_lock_irqsave(&chip->mixer_lock, flags); change = chip->capture_source[addr][0] != left || - chip->capture_source[addr][1] != right; + chip->capture_source[addr][1] != right; chip->capture_source[addr][0] = left; chip->capture_source[addr][1] = right; dev->oss.input=addr; @@ -783,57 +783,57 @@ static int snd_saa7134_capsrc_put(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_ if (change) { - switch (dev->pci->device) { + switch (dev->pci->device) { case PCI_DEVICE_ID_PHILIPS_SAA7134: - switch (addr) { - case MIXER_ADDR_TVTUNER: - saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0xc0); - saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, 0x00); - break; - case MIXER_ADDR_LINE1: - case MIXER_ADDR_LINE2: - analog_io = (MIXER_ADDR_LINE1 == addr) ? 0x00 : 0x08; - rate = (32000 == dev->oss.rate) ? 0x01 : 0x03; - saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, analog_io); - saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0x80); - saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, rate); - break; - } - - break; + switch (addr) { + case MIXER_ADDR_TVTUNER: + saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0xc0); + saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, 0x00); + break; + case MIXER_ADDR_LINE1: + case MIXER_ADDR_LINE2: + analog_io = (MIXER_ADDR_LINE1 == addr) ? 0x00 : 0x08; + rate = (32000 == dev->oss.rate) ? 0x01 : 0x03; + saa_andorb(SAA7134_ANALOG_IO_SELECT, 0x08, analog_io); + saa_andorb(SAA7134_AUDIO_FORMAT_CTRL, 0xc0, 0x80); + saa_andorb(SAA7134_SIF_SAMPLE_FREQ, 0x03, rate); + break; + } + + break; case PCI_DEVICE_ID_PHILIPS_SAA7133: case PCI_DEVICE_ID_PHILIPS_SAA7135: - xbarin = 0x03; // adc + xbarin = 0x03; // adc anabar = 0; - switch (addr) { - case MIXER_ADDR_TVTUNER: - xbarin = 0; // Demodulator - anabar = 2; // DACs - break; - case MIXER_ADDR_LINE1: - anabar = 0; // aux1, aux1 - break; - case MIXER_ADDR_LINE2: - anabar = 9; // aux2, aux2 - break; - } + switch (addr) { + case MIXER_ADDR_TVTUNER: + xbarin = 0; // Demodulator + anabar = 2; // DACs + break; + case MIXER_ADDR_LINE1: + anabar = 0; // aux1, aux1 + break; + case MIXER_ADDR_LINE2: + anabar = 9; // aux2, aux2 + break; + } /* output xbar always main channel */ - saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL1, 0xbbbb10); + saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL1, 0xbbbb10); if (left || right) { // We've got data, turn the input on - //saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL2, 0x101010); - saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, xbarin); - saa_writel(SAA7133_ANALOG_IO_SELECT, anabar); + //saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL2, 0x101010); + saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, xbarin); + saa_writel(SAA7133_ANALOG_IO_SELECT, anabar); } else { - //saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL2, 0x101010); - saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, 0); - saa_writel(SAA7133_ANALOG_IO_SELECT, 0); + //saa_dsp_writel(dev, SAA7133_DIGITAL_OUTPUT_SEL2, 0x101010); + saa_dsp_writel(dev, SAA7133_DIGITAL_INPUT_XBAR1, 0); + saa_writel(SAA7133_ANALOG_IO_SELECT, 0); } break; } - } + } return change; } @@ -878,8 +878,8 @@ static int snd_saa7134_free(snd_card_saa7134_t *chip) static int snd_saa7134_dev_free(snd_device_t *device) { - snd_card_saa7134_t *chip = device->device_data; - return snd_saa7134_free(chip); + snd_card_saa7134_t *chip = device->device_data; + return snd_saa7134_free(chip); } /* @@ -896,12 +896,12 @@ int alsa_card_saa7134_create(struct saa7134_dev *saadev, unsigned int devicenum) snd_card_t *card; snd_card_saa7134_t *chip; int err; - static snd_device_ops_t ops = { - .dev_free = snd_saa7134_dev_free, - }; + static snd_device_ops_t ops = { + .dev_free = snd_saa7134_dev_free, + }; - if (dev >= SNDRV_CARDS) - return -ENODEV; + if (dev >= SNDRV_CARDS) + return -ENODEV; if (!enable[dev]) return -ENODEV; @@ -918,24 +918,24 @@ int alsa_card_saa7134_create(struct saa7134_dev *saadev, unsigned int devicenum) /* Card "creation" */ chip = kcalloc(1, sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - return -ENOMEM; - } + if (chip == NULL) { + return -ENOMEM; + } - spin_lock_init(&chip->lock); + spin_lock_init(&chip->lock); - chip->saadev = saadev; + chip->saadev = saadev; - chip->card = card; + chip->card = card; - chip->pci = saadev->pci; - chip->irq = saadev->pci->irq; - chip->iobase = pci_resource_start(saadev->pci, 0); + chip->pci = saadev->pci; + chip->irq = saadev->pci->irq; + chip->iobase = pci_resource_start(saadev->pci, 0); - if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { - snd_saa7134_free(chip); - return err; - } + if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) { + snd_saa7134_free(chip); + return err; + } if ((err = snd_card_saa7134_new_mixer(chip)) < 0) goto __nodev; @@ -943,15 +943,15 @@ int alsa_card_saa7134_create(struct saa7134_dev *saadev, unsigned int devicenum) if ((err = snd_card_saa7134_pcm(chip, 0)) < 0) goto __nodev; - spin_lock_init(&chip->mixer_lock); + spin_lock_init(&chip->mixer_lock); snd_card_set_dev(card, &chip->pci->dev); /* End of "creation" */ strcpy(card->shortname, "SAA7134"); - sprintf(card->longname, "%s at 0x%lx irq %d", - chip->saadev->name, chip->iobase, chip->irq); + sprintf(card->longname, "%s at 0x%lx irq %d", + chip->saadev->name, chip->iobase, chip->irq); if ((err = snd_card_register(card)) == 0) { snd_saa7134_cards[dev] = card; @@ -966,8 +966,8 @@ __nodev: void alsa_card_saa7134_exit(void) { - int idx; - for (idx = 0; idx < SNDRV_CARDS; idx++) { - snd_card_free(snd_saa7134_cards[idx]); + int idx; + for (idx = 0; idx < SNDRV_CARDS; idx++) { + snd_card_free(snd_saa7134_cards[idx]); } } diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 17b0549f2e1b..a60d49af341d 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -2114,16 +2114,16 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_BEHOLD_409FM] = { - /* , Sergey */ - .name = "Beholder BeholdTV 409 FM", - .audio_clock = 0x00187de7, - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .inputs = {{ - .name = name_tv, + /* , Sergey */ + .name = "Beholder BeholdTV 409 FM", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .inputs = {{ + .name = name_tv, .vmux = 3, .amux = TV, .tv = 1, @@ -2131,60 +2131,60 @@ struct saa7134_board saa7134_boards[] = { .name = name_comp1, .vmux = 1, .amux = LINE1, - },{ - .name = name_svideo, + },{ + .name = name_svideo, .vmux = 8, .amux = LINE1, - }}, - .radio = { - .name = name_radio, + }}, + .radio = { + .name = name_radio, .amux = LINE2, - }, - }, - [SAA7134_BOARD_GOTVIEW_7135] = { + }, + }, + [SAA7134_BOARD_GOTVIEW_7135] = { /* Mike Baikov */ /* Andrey Cvetcov */ - .name = "GoTView 7135 PCI", - .audio_clock = 0x00187de7, - .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .tda9887_conf = TDA9887_PRESENT, - .gpiomask = 0x00200003, - .inputs = {{ - .name = name_tv, - .vmux = 1, - .amux = TV, - .tv = 1, - .gpio = 0x00200003, - },{ - .name = name_tv_mono, - .vmux = 1, - .amux = LINE2, - .gpio = 0x00200003, - },{ - .name = name_comp1, - .vmux = 3, - .amux = LINE1, - .gpio = 0x00200003, - },{ - .name = name_svideo, - .vmux = 8, - .amux = LINE1, - .gpio = 0x00200003, - }}, - .radio = { - .name = name_radio, - .amux = LINE2, - .gpio = 0x00200003, - }, - .mute = { - .name = name_mute, - .amux = TV, - .gpio = 0x00200003, - }, - }, + .name = "GoTView 7135 PCI", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00200003, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + .gpio = 0x00200003, + },{ + .name = name_tv_mono, + .vmux = 1, + .amux = LINE2, + .gpio = 0x00200003, + },{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + .gpio = 0x00200003, + },{ + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + .gpio = 0x00200003, + }}, + .radio = { + .name = name_radio, + .amux = LINE2, + .gpio = 0x00200003, + }, + .mute = { + .name = name_mute, + .amux = TV, + .gpio = 0x00200003, + }, + }, [SAA7134_BOARD_PHILIPS_EUROPA] = { .name = "Philips EUROPA V3 reference design", .audio_clock = 0x00187de7, @@ -2251,78 +2251,78 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, }}, }, - [SAA7134_BOARD_RTD_VFG7350] = { - .name = "RTD Embedded Technologies VFG7350", - .audio_clock = 0x00200000, - .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .inputs = {{ - .name = "Composite 0", - .vmux = 0, - .amux = LINE1, - },{ - .name = "Composite 1", - .vmux = 1, - .amux = LINE2, - },{ - .name = "Composite 2", - .vmux = 2, - .amux = LINE1, - },{ - .name = "Composite 3", - .vmux = 3, - .amux = LINE2, - },{ - .name = "S-Video 0", - .vmux = 8, - .amux = LINE1, - },{ - .name = "S-Video 1", - .vmux = 9, - .amux = LINE2, - }}, - .mpeg = SAA7134_MPEG_EMPRESS, - .video_out = CCIR656, + [SAA7134_BOARD_RTD_VFG7350] = { + .name = "RTD Embedded Technologies VFG7350", + .audio_clock = 0x00200000, + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .inputs = {{ + .name = "Composite 0", + .vmux = 0, + .amux = LINE1, + },{ + .name = "Composite 1", + .vmux = 1, + .amux = LINE2, + },{ + .name = "Composite 2", + .vmux = 2, + .amux = LINE1, + },{ + .name = "Composite 3", + .vmux = 3, + .amux = LINE2, + },{ + .name = "S-Video 0", + .vmux = 8, + .amux = LINE1, + },{ + .name = "S-Video 1", + .vmux = 9, + .amux = LINE2, + }}, + .mpeg = SAA7134_MPEG_EMPRESS, + .video_out = CCIR656, .vid_port_opts = ( SET_T_CODE_POLARITY_NON_INVERTED | SET_CLOCK_NOT_DELAYED | SET_CLOCK_INVERTED | SET_VSYNC_OFF ), - }, - [SAA7134_BOARD_RTD_VFG7330] = { - .name = "RTD Embedded Technologies VFG7330", - .audio_clock = 0x00200000, - .tuner_type = TUNER_ABSENT, - .radio_type = UNSET, - .tuner_addr = ADDR_UNSET, - .radio_addr = ADDR_UNSET, - .inputs = {{ - .name = "Composite 0", - .vmux = 0, - .amux = LINE1, - },{ - .name = "Composite 1", - .vmux = 1, - .amux = LINE2, - },{ - .name = "Composite 2", - .vmux = 2, - .amux = LINE1, - },{ - .name = "Composite 3", - .vmux = 3, - .amux = LINE2, - },{ - .name = "S-Video 0", - .vmux = 8, - .amux = LINE1, - },{ - .name = "S-Video 1", - .vmux = 9, - .amux = LINE2, - }}, - }, + }, + [SAA7134_BOARD_RTD_VFG7330] = { + .name = "RTD Embedded Technologies VFG7330", + .audio_clock = 0x00200000, + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .inputs = {{ + .name = "Composite 0", + .vmux = 0, + .amux = LINE1, + },{ + .name = "Composite 1", + .vmux = 1, + .amux = LINE2, + },{ + .name = "Composite 2", + .vmux = 2, + .amux = LINE1, + },{ + .name = "Composite 3", + .vmux = 3, + .amux = LINE2, + },{ + .name = "S-Video 0", + .vmux = 8, + .amux = LINE1, + },{ + .name = "S-Video 1", + .vmux = 9, + .amux = LINE2, + }}, + }, [SAA7134_BOARD_FLYTVPLATINUM_MINI2] = { .name = "LifeView FlyTV Platinum Mini2", .audio_clock = 0x00200000, @@ -2760,55 +2760,55 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x0000, /* It shouldn't break anything, since subdevice id seems unique */ .subdevice = 0x4091, .driver_data = SAA7134_BOARD_BEHOLD_409FM, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x5456, /* GoTView */ - .subdevice = 0x7135, - .driver_data = SAA7134_BOARD_GOTVIEW_7135, - },{ + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x5456, /* GoTView */ + .subdevice = 0x7135, + .driver_data = SAA7134_BOARD_GOTVIEW_7135, + },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, .subvendor = PCI_VENDOR_ID_PHILIPS, .subdevice = 0x2004, .driver_data = SAA7134_BOARD_PHILIPS_EUROPA, - },{ + },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, .subvendor = 0x185b, .subdevice = 0xc900, .driver_data = SAA7134_BOARD_VIDEOMATE_DVBT_300, - },{ + },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, .subvendor = 0x185b, .subdevice = 0xc901, .driver_data = SAA7134_BOARD_VIDEOMATE_DVBT_200, },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1435, - .subdevice = 0x7350, - .driver_data = SAA7134_BOARD_RTD_VFG7350, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1435, - .subdevice = 0x7330, - .driver_data = SAA7134_BOARD_RTD_VFG7330, - },{ - .vendor = PCI_VENDOR_ID_PHILIPS, - .device = PCI_DEVICE_ID_PHILIPS_SAA7133, - .subvendor = 0x1461, - .subdevice = 0x1044, - .driver_data = SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180, - },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1435, + .subdevice = 0x7350, + .driver_data = SAA7134_BOARD_RTD_VFG7350, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1435, + .subdevice = 0x7330, + .driver_data = SAA7134_BOARD_RTD_VFG7330, + },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1461, + .subdevice = 0x1044, + .driver_data = SAA7134_BOARD_AVERMEDIA_AVERTVHD_A180, + },{ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7133, .subvendor = 0x1131, .subdevice = 0x4ee9, .driver_data = SAA7134_BOARD_MONSTERTV_MOBILE, - },{ + },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -3051,7 +3051,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) case SAA7134_BOARD_VIDEOMATE_DVBT_300: /* The Philips EUROPA based hybrid boards have the tuner connected through * the channel decoder. We have to make it transparent to find it - */ + */ { struct tuner_setup tun_setup; u8 data[] = { 0x07, 0x02}; @@ -3063,7 +3063,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) tun_setup.addr = dev->tuner_addr; saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup); - } + } break; } return 0; diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 907dbd4de7c9..afa0cfce6578 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -201,10 +201,10 @@ static int pending_call(struct notifier_block *self, unsigned long state, if (module != THIS_MODULE || state != MODULE_STATE_LIVE) return NOTIFY_DONE; - if (need_empress) - request_module("saa7134-empress"); - if (need_dvb) - request_module("saa7134-dvb"); + if (need_empress) + request_module("saa7134-empress"); + if (need_dvb) + request_module("saa7134-dvb"); return NOTIFY_DONE; } @@ -279,8 +279,8 @@ unsigned long saa7134_buffer_base(struct saa7134_buf *buf) int saa7134_pgtable_alloc(struct pci_dev *pci, struct saa7134_pgtable *pt) { - __le32 *cpu; - dma_addr_t dma_addr; + __le32 *cpu; + dma_addr_t dma_addr; cpu = pci_alloc_consistent(pci, SAA7134_PGTABLE_SIZE, &dma_addr); if (NULL == cpu) @@ -440,7 +440,7 @@ int saa7134_set_dmabits(struct saa7134_dev *dev) ctrl |= SAA7134_MAIN_CTRL_TE0; irq |= SAA7134_IRQ1_INTE_RA0_1 | SAA7134_IRQ1_INTE_RA0_0; - cap = dev->video_q.curr->vb.field; + cap = dev->video_q.curr->vb.field; } /* video capture -- dma 1+2 (planar modes) */ @@ -646,7 +646,7 @@ static int saa7134_hwinit1(struct saa7134_dev *dev) saa_writel(SAA7134_IRQ1, 0); saa_writel(SAA7134_IRQ2, 0); - init_MUTEX(&dev->lock); + init_MUTEX(&dev->lock); spin_lock_init(&dev->slock); saa7134_track_gpio(dev,"pre-init"); @@ -704,7 +704,7 @@ static int saa7134_hwinit2(struct saa7134_dev *dev) saa7134_tvaudio_init2(dev); /* enable IRQ's */ - irq2_mask = + irq2_mask = SAA7134_IRQ2_INTE_DEC3 | SAA7134_IRQ2_INTE_DEC2 | SAA7134_IRQ2_INTE_DEC1 | @@ -889,8 +889,8 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, /* print pci info */ pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &dev->pci_rev); - pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); - printk(KERN_INFO "%s: found at %s, rev: %d, irq: %d, " + pci_read_config_byte(pci_dev, PCI_LATENCY_TIMER, &dev->pci_lat); + printk(KERN_INFO "%s: found at %s, rev: %d, irq: %d, " "latency: %d, mmio: 0x%lx\n", dev->name, pci_name(pci_dev), dev->pci_rev, pci_dev->irq, dev->pci_lat,pci_resource_start(pci_dev,0)); @@ -914,7 +914,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, dev->tda9887_conf = saa7134_boards[dev->board].tda9887_conf; if (UNSET != tuner[dev->nr]) dev->tuner_type = tuner[dev->nr]; - printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", + printk(KERN_INFO "%s: subsystem: %04x:%04x, board: %s [card=%d,%s]\n", dev->name,pci_dev->subsystem_vendor, pci_dev->subsystem_device,saa7134_boards[dev->board].name, dev->board, card[dev->nr] == dev->board ? @@ -964,12 +964,12 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, request_module("tuner"); if (dev->tda9887_conf) request_module("tda9887"); - if (card_is_empress(dev)) { + if (card_is_empress(dev)) { request_module("saa6752hs"); request_module_depend("saa7134-empress",&need_empress); } - if (card_is_dvb(dev)) + if (card_is_dvb(dev)) request_module_depend("saa7134-dvb",&need_dvb); v4l2_prio_init(&dev->prio); @@ -1078,7 +1078,7 @@ static int __devinit saa7134_initdev(struct pci_dev *pci_dev, static void __devexit saa7134_finidev(struct pci_dev *pci_dev) { - struct saa7134_dev *dev = pci_get_drvdata(pci_dev); + struct saa7134_dev *dev = pci_get_drvdata(pci_dev); struct list_head *item; struct saa7134_mpeg_ops *mops; @@ -1173,10 +1173,10 @@ EXPORT_SYMBOL(saa7134_ts_unregister); /* ----------------------------------------------------------- */ static struct pci_driver saa7134_pci_driver = { - .name = "saa7134", - .id_table = saa7134_pci_tbl, - .probe = saa7134_initdev, - .remove = __devexit_p(saa7134_finidev), + .name = "saa7134", + .id_table = saa7134_pci_tbl, + .probe = saa7134_initdev, + .remove = __devexit_p(saa7134_finidev), }; static int saa7134_init(void) diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 87641f7e4322..5aadd44c2fa2 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -547,7 +547,7 @@ static int philips_tda827x_pll_set(struct dvb_frontend *fe, struct dvb_frontend_ u8 tuner_buf[14]; struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf, - .len = sizeof(tuner_buf) }; + .len = sizeof(tuner_buf) }; int i, tuner_freq, if_freq; u32 N; switch (params->u.ofdm.bandwidth) { @@ -606,7 +606,7 @@ static void philips_tda827x_pll_sleep(struct dvb_frontend *fe) struct saa7134_dev *dev = fe->dvb->priv; static u8 tda827x_sleep[] = { 0x30, 0xd0}; struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tda827x_sleep, - .len = sizeof(tda827x_sleep) }; + .len = sizeof(tda827x_sleep) }; i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); } diff --git a/drivers/media/video/saa7134/saa7134-empress.c b/drivers/media/video/saa7134/saa7134-empress.c index 77b627eb6483..e9ec69efb4c9 100644 --- a/drivers/media/video/saa7134/saa7134-empress.c +++ b/drivers/media/video/saa7134/saa7134-empress.c @@ -55,7 +55,7 @@ static void ts_reset_encoder(struct saa7134_dev* dev) saa_writeb(SAA7134_SPECIAL_MODE, 0x00); msleep(10); - saa_writeb(SAA7134_SPECIAL_MODE, 0x01); + saa_writeb(SAA7134_SPECIAL_MODE, 0x01); msleep(100); dev->empress_started = 0; } @@ -65,7 +65,7 @@ static int ts_init_encoder(struct saa7134_dev* dev) ts_reset_encoder(dev); saa7134_i2c_call_clients(dev, VIDIOC_S_MPEGCOMP, NULL); dev->empress_started = 1; - return 0; + return 0; } /* ------------------------------------------------------------------ */ @@ -169,7 +169,7 @@ static int ts_do_ioctl(struct inode *inode, struct file *file, struct v4l2_capability *cap = arg; memset(cap,0,sizeof(*cap)); - strcpy(cap->driver, "saa7134"); + strcpy(cap->driver, "saa7134"); strlcpy(cap->card, saa7134_boards[dev->board].name, sizeof(cap->card)); sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); diff --git a/drivers/media/video/saa7134/saa7134-i2c.c b/drivers/media/video/saa7134/saa7134-i2c.c index 711aa8e85fac..2577d03485b8 100644 --- a/drivers/media/video/saa7134/saa7134-i2c.c +++ b/drivers/media/video/saa7134/saa7134-i2c.c @@ -239,7 +239,7 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap, unsigned char data; int addr,rc,i,byte; - status = i2c_get_status(dev); + status = i2c_get_status(dev); if (!i2c_is_idle(status)) if (!i2c_reset(dev)) return -EIO; @@ -296,7 +296,7 @@ static int saa7134_i2c_xfer(struct i2c_adapter *i2c_adap, rc = -EIO; if (!i2c_is_busy_wait(dev)) goto err; - status = i2c_get_status(dev); + status = i2c_get_status(dev); if (i2c_is_error(status)) goto err; /* ensure that the bus is idle for at least one bit slot */ @@ -348,12 +348,12 @@ static int attach_inform(struct i2c_client *client) client->driver->command(client, TUNER_SET_TYPE_ADDR, &tun_setup); } - } + } if (tuner != UNSET) { - tun_setup.type = tuner; - tun_setup.addr = saa7134_boards[dev->board].tuner_addr; + tun_setup.type = tuner; + tun_setup.addr = saa7134_boards[dev->board].tuner_addr; if ((tun_setup.addr == ADDR_UNSET)||(tun_setup.addr == client->addr)) { @@ -361,11 +361,11 @@ static int attach_inform(struct i2c_client *client) client->driver->command(client,TUNER_SET_TYPE_ADDR, &tun_setup); } - } + } client->driver->command(client, TDA9887_SET_CONFIG, &conf); - return 0; + return 0; } static struct i2c_algorithm saa7134_algo = { diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 9dc41c1427a8..7ce0459989b5 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -114,24 +114,24 @@ static IR_KEYTAB_TYPE cinergy_codes[IR_KEYTAB_SIZE] = { /* Alfons Geser * updates from Job D. R. Borges */ static IR_KEYTAB_TYPE eztv_codes[IR_KEYTAB_SIZE] = { - [ 18 ] = KEY_POWER, - [ 1 ] = KEY_TV, // DVR - [ 21 ] = KEY_DVD, // DVD - [ 23 ] = KEY_AUDIO, // music - // DVR mode / DVD mode / music mode - - [ 27 ] = KEY_MUTE, // mute - [ 2 ] = KEY_LANGUAGE, // MTS/SAP / audio / autoseek - [ 30 ] = KEY_SUBTITLE, // closed captioning / subtitle / seek - [ 22 ] = KEY_ZOOM, // full screen - [ 28 ] = KEY_VIDEO, // video source / eject / delall - [ 29 ] = KEY_RESTART, // playback / angle / del - [ 47 ] = KEY_SEARCH, // scan / menu / playlist - [ 48 ] = KEY_CHANNEL, // CH surfing / bookmark / memo - - [ 49 ] = KEY_HELP, // help - [ 50 ] = KEY_MODE, // num/memo - [ 51 ] = KEY_ESC, // cancel + [ 18 ] = KEY_POWER, + [ 1 ] = KEY_TV, // DVR + [ 21 ] = KEY_DVD, // DVD + [ 23 ] = KEY_AUDIO, // music + // DVR mode / DVD mode / music mode + + [ 27 ] = KEY_MUTE, // mute + [ 2 ] = KEY_LANGUAGE, // MTS/SAP / audio / autoseek + [ 30 ] = KEY_SUBTITLE, // closed captioning / subtitle / seek + [ 22 ] = KEY_ZOOM, // full screen + [ 28 ] = KEY_VIDEO, // video source / eject / delall + [ 29 ] = KEY_RESTART, // playback / angle / del + [ 47 ] = KEY_SEARCH, // scan / menu / playlist + [ 48 ] = KEY_CHANNEL, // CH surfing / bookmark / memo + + [ 49 ] = KEY_HELP, // help + [ 50 ] = KEY_MODE, // num/memo + [ 51 ] = KEY_ESC, // cancel [ 12 ] = KEY_UP, // up [ 16 ] = KEY_DOWN, // down @@ -148,24 +148,24 @@ static IR_KEYTAB_TYPE eztv_codes[IR_KEYTAB_SIZE] = { [ 45 ] = KEY_PLAY, // play [ 46 ] = KEY_SHUFFLE, // snapshot / shuffle - [ 0 ] = KEY_KP0, - [ 5 ] = KEY_KP1, - [ 6 ] = KEY_KP2, - [ 7 ] = KEY_KP3, - [ 9 ] = KEY_KP4, - [ 10 ] = KEY_KP5, - [ 11 ] = KEY_KP6, - [ 13 ] = KEY_KP7, - [ 14 ] = KEY_KP8, - [ 15 ] = KEY_KP9, - - [ 42 ] = KEY_VOLUMEUP, - [ 17 ] = KEY_VOLUMEDOWN, - [ 24 ] = KEY_CHANNELUP, // CH.tracking up - [ 25 ] = KEY_CHANNELDOWN, // CH.tracking down - - [ 19 ] = KEY_KPENTER, // enter - [ 33 ] = KEY_KPDOT, // . (decimal dot) + [ 0 ] = KEY_KP0, + [ 5 ] = KEY_KP1, + [ 6 ] = KEY_KP2, + [ 7 ] = KEY_KP3, + [ 9 ] = KEY_KP4, + [ 10 ] = KEY_KP5, + [ 11 ] = KEY_KP6, + [ 13 ] = KEY_KP7, + [ 14 ] = KEY_KP8, + [ 15 ] = KEY_KP9, + + [ 42 ] = KEY_VOLUMEUP, + [ 17 ] = KEY_VOLUMEDOWN, + [ 24 ] = KEY_CHANNELUP, // CH.tracking up + [ 25 ] = KEY_CHANNELDOWN, // CH.tracking down + + [ 19 ] = KEY_KPENTER, // enter + [ 33 ] = KEY_KPDOT, // . (decimal dot) }; static IR_KEYTAB_TYPE avacssmart_codes[IR_KEYTAB_SIZE] = { @@ -455,13 +455,13 @@ static int build_key(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPMODE3,SAA7134_GPIO_GPRESCAN); gpio = saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2); - if (ir->polling) { - if (ir->last_gpio == gpio) - return 0; - ir->last_gpio = gpio; - } + if (ir->polling) { + if (ir->last_gpio == gpio) + return 0; + ir->last_gpio = gpio; + } - data = ir_extract_bits(gpio, ir->mask_keycode); + data = ir_extract_bits(gpio, ir->mask_keycode); dprintk("build_key gpio=0x%x mask=0x%x data=%d\n", gpio, ir->mask_keycode, data); @@ -478,9 +478,9 @@ static int build_key(struct saa7134_dev *dev) void saa7134_input_irq(struct saa7134_dev *dev) { - struct saa7134_ir *ir = dev->remote; + struct saa7134_ir *ir = dev->remote; - if (!ir->polling) + if (!ir->polling) build_key(dev); } @@ -515,7 +515,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) switch (dev->board) { case SAA7134_BOARD_FLYVIDEO2000: case SAA7134_BOARD_FLYVIDEO3000: - case SAA7134_BOARD_FLYTVPLATINUM_FM: + case SAA7134_BOARD_FLYTVPLATINUM_FM: case SAA7134_BOARD_FLYTVPLATINUM_MINI2: ir_codes = flyvideo_codes; mask_keycode = 0xEC00000; @@ -557,7 +557,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) saa_setb(SAA7134_GPIO_GPMODE0, 0x4); saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4); break; - case SAA7134_BOARD_KWORLD_TERMINATOR: + case SAA7134_BOARD_KWORLD_TERMINATOR: ir_codes = avacssmart_codes; mask_keycode = 0x00001f; mask_keyup = 0x000060; @@ -571,7 +571,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keyup = 0x004000; polling = 50; // ms break; - case SAA7134_BOARD_GOTVIEW_7135: + case SAA7134_BOARD_GOTVIEW_7135: ir_codes = gotview7135_codes; mask_keycode = 0x0003EC; mask_keyup = 0x008000; @@ -585,8 +585,8 @@ int saa7134_input_init1(struct saa7134_dev *dev) mask_keyup = 0x400000; polling = 50; // ms break; - case SAA7134_BOARD_VIDEOMATE_DVBT_300: - case SAA7134_BOARD_VIDEOMATE_DVBT_200: + case SAA7134_BOARD_VIDEOMATE_DVBT_300: + case SAA7134_BOARD_VIDEOMATE_DVBT_200: ir_codes = videomate_tv_pvr_codes; mask_keycode = 0x003F00; mask_keyup = 0x040000; @@ -610,7 +610,7 @@ int saa7134_input_init1(struct saa7134_dev *dev) ir->mask_keycode = mask_keycode; ir->mask_keydown = mask_keydown; ir->mask_keyup = mask_keyup; - ir->polling = polling; + ir->polling = polling; /* init input device */ snprintf(ir->name, sizeof(ir->name), "saa7134 IR (%s)", diff --git a/drivers/media/video/saa7134/saa7134-oss.c b/drivers/media/video/saa7134/saa7134-oss.c index b1dcb4d10788..f1b0e0d93d7b 100644 --- a/drivers/media/video/saa7134/saa7134-oss.c +++ b/drivers/media/video/saa7134/saa7134-oss.c @@ -64,7 +64,7 @@ static int dsp_buffer_conf(struct saa7134_dev *dev, int blksize, int blocks) dev->oss.bufsize = blksize * blocks; dprintk("buffer config: %d blocks / %d bytes, %d kB total\n", - blocks,blksize,blksize * blocks / 1024); + blocks,blksize,blksize * blocks / 1024); return 0; } @@ -371,20 +371,20 @@ static int dsp_ioctl(struct inode *inode, struct file *file, if (oss_debug > 1) saa7134_print_ioctl(dev->name,cmd); - switch (cmd) { - case OSS_GETVERSION: - return put_user(SOUND_VERSION, p); - case SNDCTL_DSP_GETCAPS: + switch (cmd) { + case OSS_GETVERSION: + return put_user(SOUND_VERSION, p); + case SNDCTL_DSP_GETCAPS: return 0; - case SNDCTL_DSP_SPEED: + case SNDCTL_DSP_SPEED: if (get_user(val, p)) return -EFAULT; /* fall through */ - case SOUND_PCM_READ_RATE: + case SOUND_PCM_READ_RATE: return put_user(dev->oss.rate, p); - case SNDCTL_DSP_STEREO: + case SNDCTL_DSP_STEREO: if (get_user(val, p)) return -EFAULT; down(&dev->oss.lock); @@ -396,7 +396,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file, up(&dev->oss.lock); return put_user(dev->oss.channels-1, p); - case SNDCTL_DSP_CHANNELS: + case SNDCTL_DSP_CHANNELS: if (get_user(val, p)) return -EFAULT; if (val != 1 && val != 2) @@ -409,15 +409,15 @@ static int dsp_ioctl(struct inode *inode, struct file *file, } up(&dev->oss.lock); /* fall through */ - case SOUND_PCM_READ_CHANNELS: + case SOUND_PCM_READ_CHANNELS: return put_user(dev->oss.channels, p); - case SNDCTL_DSP_GETFMTS: /* Returns a mask */ + case SNDCTL_DSP_GETFMTS: /* Returns a mask */ return put_user(AFMT_U8 | AFMT_S8 | AFMT_U16_LE | AFMT_U16_BE | AFMT_S16_LE | AFMT_S16_BE, p); - case SNDCTL_DSP_SETFMT: /* Selects ONE fmt */ + case SNDCTL_DSP_SETFMT: /* Selects ONE fmt */ if (get_user(val, p)) return -EFAULT; switch (val) { @@ -442,7 +442,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file, return -EINVAL; } - case SOUND_PCM_READ_BITS: + case SOUND_PCM_READ_BITS: switch (dev->oss.afmt) { case AFMT_U8: case AFMT_S8: @@ -456,20 +456,20 @@ static int dsp_ioctl(struct inode *inode, struct file *file, return -EINVAL; } - case SNDCTL_DSP_NONBLOCK: - file->f_flags |= O_NONBLOCK; - return 0; + case SNDCTL_DSP_NONBLOCK: + file->f_flags |= O_NONBLOCK; + return 0; - case SNDCTL_DSP_RESET: + case SNDCTL_DSP_RESET: down(&dev->oss.lock); if (dev->oss.recording_on) dsp_rec_stop(dev); up(&dev->oss.lock); return 0; - case SNDCTL_DSP_GETBLKSIZE: + case SNDCTL_DSP_GETBLKSIZE: return put_user(dev->oss.blksize, p); - case SNDCTL_DSP_SETFRAGMENT: + case SNDCTL_DSP_SETFRAGMENT: if (get_user(val, p)) return -EFAULT; if (dev->oss.recording_on) @@ -480,7 +480,7 @@ static int dsp_ioctl(struct inode *inode, struct file *file, dsp_buffer_init(dev); return 0; - case SNDCTL_DSP_SYNC: + case SNDCTL_DSP_SYNC: /* NOP */ return 0; @@ -563,7 +563,7 @@ mixer_recsrc_7133(struct saa7134_dev *dev) switch (dev->oss.input) { case TV: xbarin = 0; // Demodulator - anabar = 2; // DACs + anabar = 2; // DACs break; case LINE1: anabar = 0; // aux1, aux1 @@ -667,28 +667,28 @@ static int mixer_ioctl(struct inode *inode, struct file *file, if (oss_debug > 1) saa7134_print_ioctl(dev->name,cmd); - switch (cmd) { - case OSS_GETVERSION: - return put_user(SOUND_VERSION, p); + switch (cmd) { + case OSS_GETVERSION: + return put_user(SOUND_VERSION, p); case SOUND_MIXER_INFO: { mixer_info info; memset(&info,0,sizeof(info)); - strlcpy(info.id, "TV audio", sizeof(info.id)); - strlcpy(info.name, dev->name, sizeof(info.name)); - info.modify_counter = dev->oss.count; - if (copy_to_user(argp, &info, sizeof(info))) - return -EFAULT; + strlcpy(info.id, "TV audio", sizeof(info.id)); + strlcpy(info.name, dev->name, sizeof(info.name)); + info.modify_counter = dev->oss.count; + if (copy_to_user(argp, &info, sizeof(info))) + return -EFAULT; return 0; } case SOUND_OLD_MIXER_INFO: { _old_mixer_info info; memset(&info,0,sizeof(info)); - strlcpy(info.id, "TV audio", sizeof(info.id)); - strlcpy(info.name, dev->name, sizeof(info.name)); - if (copy_to_user(argp, &info, sizeof(info))) - return -EFAULT; + strlcpy(info.id, "TV audio", sizeof(info.id)); + strlcpy(info.name, dev->name, sizeof(info.name)); + if (copy_to_user(argp, &info, sizeof(info))) + return -EFAULT; return 0; } case MIXER_READ(SOUND_MIXER_CAPS): @@ -771,7 +771,7 @@ struct file_operations saa7134_mixer_fops = { int saa7134_oss_init1(struct saa7134_dev *dev) { /* general */ - init_MUTEX(&dev->oss.lock); + init_MUTEX(&dev->oss.lock); init_waitqueue_head(&dev->oss.wq); switch (dev->pci->device) { diff --git a/drivers/media/video/saa7134/saa7134-reg.h b/drivers/media/video/saa7134/saa7134-reg.h index 58c521fade85..ac6431ba4fc3 100644 --- a/drivers/media/video/saa7134/saa7134-reg.h +++ b/drivers/media/video/saa7134/saa7134-reg.h @@ -27,7 +27,7 @@ /* DMA channels, n = 0 ... 6 */ #define SAA7134_RS_BA1(n) ((0x200 >> 2) + 4*n) -#define SAA7134_RS_BA2(n) ((0x204 >> 2) + 4*n) +#define SAA7134_RS_BA2(n) ((0x204 >> 2) + 4*n) #define SAA7134_RS_PITCH(n) ((0x208 >> 2) + 4*n) #define SAA7134_RS_CONTROL(n) ((0x20c >> 2) + 4*n) #define SAA7134_RS_CONTROL_WSWAP (0x01 << 25) @@ -53,14 +53,14 @@ /* main control */ #define SAA7134_MAIN_CTRL (0x2a8 >> 2) -#define SAA7134_MAIN_CTRL_VPLLE (1 << 15) -#define SAA7134_MAIN_CTRL_APLLE (1 << 14) -#define SAA7134_MAIN_CTRL_EXOSC (1 << 13) -#define SAA7134_MAIN_CTRL_EVFE1 (1 << 12) -#define SAA7134_MAIN_CTRL_EVFE2 (1 << 11) -#define SAA7134_MAIN_CTRL_ESFE (1 << 10) -#define SAA7134_MAIN_CTRL_EBADC (1 << 9) -#define SAA7134_MAIN_CTRL_EBDAC (1 << 8) +#define SAA7134_MAIN_CTRL_VPLLE (1 << 15) +#define SAA7134_MAIN_CTRL_APLLE (1 << 14) +#define SAA7134_MAIN_CTRL_EXOSC (1 << 13) +#define SAA7134_MAIN_CTRL_EVFE1 (1 << 12) +#define SAA7134_MAIN_CTRL_EVFE2 (1 << 11) +#define SAA7134_MAIN_CTRL_ESFE (1 << 10) +#define SAA7134_MAIN_CTRL_EBADC (1 << 9) +#define SAA7134_MAIN_CTRL_EBDAC (1 << 8) #define SAA7134_MAIN_CTRL_TE6 (1 << 6) #define SAA7134_MAIN_CTRL_TE5 (1 << 5) #define SAA7134_MAIN_CTRL_TE4 (1 << 4) diff --git a/drivers/media/video/saa7134/saa7134-ts.c b/drivers/media/video/saa7134/saa7134-ts.c index cdfd69873ba9..470903e2f5e5 100644 --- a/drivers/media/video/saa7134/saa7134-ts.c +++ b/drivers/media/video/saa7134/saa7134-ts.c @@ -111,8 +111,8 @@ static int buffer_prepare(struct videobuf_queue *q, struct videobuf_buffer *vb, /* dma: setup channel 5 (= TS) */ control = SAA7134_RS_CONTROL_BURST_16 | - SAA7134_RS_CONTROL_ME | - (buf->pt->dma >> 12); + SAA7134_RS_CONTROL_ME | + (buf->pt->dma >> 12); saa_writeb(SAA7134_TS_DMA0, ((lines-1)&0xff)); saa_writeb(SAA7134_TS_DMA1, (((lines-1)>>8)&0xff)); diff --git a/drivers/media/video/saa7134/saa7134-tvaudio.c b/drivers/media/video/saa7134/saa7134-tvaudio.c index fdca6c563b96..3daf1b597958 100644 --- a/drivers/media/video/saa7134/saa7134-tvaudio.c +++ b/drivers/media/video/saa7134/saa7134-tvaudio.c @@ -246,7 +246,7 @@ static void mute_input_7134(struct saa7134_dev *dev) if (PCI_DEVICE_ID_PHILIPS_SAA7134 == dev->pci->device) /* 7134 mute */ saa_writeb(SAA7134_AUDIO_MUTE_CTRL, mute ? - SAA7134_MUTE_MASK | + SAA7134_MUTE_MASK | SAA7134_MUTE_ANALOG | SAA7134_MUTE_I2S : SAA7134_MUTE_MASK); @@ -761,17 +761,17 @@ static int mute_input_7133(struct saa7134_dev *dev) /* switch gpio-connected external audio mux */ - if (0 != card(dev).gpiomask) { - mask = card(dev).gpiomask; + if (0 != card(dev).gpiomask) { + mask = card(dev).gpiomask; if (card(dev).mute.name && dev->ctl_mute) in = &card(dev).mute; else in = dev->input; - saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, mask, mask); - saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, in->gpio); - saa7134_track_gpio(dev,in->name); + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, mask, mask); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, mask, in->gpio); + saa7134_track_gpio(dev,in->name); } return 0; diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index cd5545b2d60b..86db7fb96efd 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -310,12 +310,12 @@ static struct saa7134_tvnorm tvnorms[] = { .h_start = 0, .h_stop = 719, - .video_v_start = 23, - .video_v_stop = 262, - .vbi_v_start_0 = 10, - .vbi_v_stop_0 = 21, - .vbi_v_start_1 = 273, - .src_timing = 7, + .video_v_start = 23, + .video_v_stop = 262, + .vbi_v_start_0 = 10, + .vbi_v_stop_0 = 21, + .vbi_v_start_1 = 273, + .src_timing = 7, .sync_control = 0x18, .luma_control = 0x40, @@ -659,7 +659,7 @@ static void set_size(struct saa7134_dev *dev, int task, prescale = 1; xscale = 1024 * dev->crop_current.width / prescale / width; yscale = 512 * div * dev->crop_current.height / height; - dprintk("prescale=%d xscale=%d yscale=%d\n",prescale,xscale,yscale); + dprintk("prescale=%d xscale=%d yscale=%d\n",prescale,xscale,yscale); set_h_prescale(dev,task,prescale); saa_writeb(SAA7134_H_SCALE_INC1(task), xscale & 0xff); saa_writeb(SAA7134_H_SCALE_INC2(task), xscale >> 8); @@ -789,20 +789,20 @@ static int verify_preview(struct saa7134_dev *dev, struct v4l2_window *win) maxh = dev->crop_current.height; if (V4L2_FIELD_ANY == field) { - field = (win->w.height > maxh/2) - ? V4L2_FIELD_INTERLACED - : V4L2_FIELD_TOP; - } - switch (field) { - case V4L2_FIELD_TOP: - case V4L2_FIELD_BOTTOM: - maxh = maxh / 2; - break; - case V4L2_FIELD_INTERLACED: - break; - default: - return -EINVAL; - } + field = (win->w.height > maxh/2) + ? V4L2_FIELD_INTERLACED + : V4L2_FIELD_TOP; + } + switch (field) { + case V4L2_FIELD_TOP: + case V4L2_FIELD_BOTTOM: + maxh = maxh / 2; + break; + case V4L2_FIELD_INTERLACED: + break; + default: + return -EINVAL; + } win->field = field; if (win->w.width > maxw) @@ -1343,13 +1343,13 @@ video_poll(struct file *file, struct poll_table_struct *wait) if (res_locked(fh->dev,RESOURCE_VIDEO)) { up(&fh->cap.lock); return POLLERR; - } - if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field)) { - up(&fh->cap.lock); - return POLLERR; - } - fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf); - fh->cap.read_off = 0; + } + if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field)) { + up(&fh->cap.lock); + return POLLERR; + } + fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf); + fh->cap.read_off = 0; } up(&fh->cap.lock); buf = fh->cap.read_buf; @@ -1706,7 +1706,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, unsigned int tuner_type = dev->tuner_type; memset(cap,0,sizeof(*cap)); - strcpy(cap->driver, "saa7134"); + strcpy(cap->driver, "saa7134"); strlcpy(cap->card, saa7134_boards[dev->board].name, sizeof(cap->card)); sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); @@ -1934,26 +1934,26 @@ static int video_do_ioctl(struct inode *inode, struct file *file, } case VIDIOC_S_AUDIO: return 0; - case VIDIOC_G_PARM: - { - struct v4l2_captureparm *parm = arg; - memset(parm,0,sizeof(*parm)); - return 0; - } - - case VIDIOC_G_PRIORITY: - { - enum v4l2_priority *p = arg; - - *p = v4l2_prio_max(&dev->prio); - return 0; - } - case VIDIOC_S_PRIORITY: - { - enum v4l2_priority *prio = arg; - - return v4l2_prio_change(&dev->prio, &fh->prio, *prio); - } + case VIDIOC_G_PARM: + { + struct v4l2_captureparm *parm = arg; + memset(parm,0,sizeof(*parm)); + return 0; + } + + case VIDIOC_G_PRIORITY: + { + enum v4l2_priority *p = arg; + + *p = v4l2_prio_max(&dev->prio); + return 0; + } + case VIDIOC_S_PRIORITY: + { + enum v4l2_priority *prio = arg; + + return v4l2_prio_change(&dev->prio, &fh->prio, *prio); + } /* --- preview ioctls ---------------------------------------- */ case VIDIOC_ENUM_FMT: @@ -2102,7 +2102,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, { int res = saa7134_resource(fh); - if (!res_get(dev,fh,res)) + if (!res_get(dev,fh,res)) return -EBUSY; return videobuf_streamon(saa7134_queue(fh)); } @@ -2144,7 +2144,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, struct v4l2_capability *cap = arg; memset(cap,0,sizeof(*cap)); - strcpy(cap->driver, "saa7134"); + strcpy(cap->driver, "saa7134"); strlcpy(cap->card, saa7134_boards[dev->board].name, sizeof(cap->card)); sprintf(cap->bus_info,"PCI:%s",pci_name(dev->pci)); @@ -2275,7 +2275,7 @@ struct video_device saa7134_video_template = { .name = "saa7134-video", .type = VID_TYPE_CAPTURE|VID_TYPE_TUNER|VID_TYPE_OVERLAY| - VID_TYPE_CLIPPING|VID_TYPE_SCALES, + VID_TYPE_CLIPPING|VID_TYPE_SCALES, .hardware = 0, .fops = &video_fops, .minor = -1, @@ -2322,7 +2322,7 @@ int saa7134_video_init1(struct saa7134_dev *dev) dev->tda9887_conf |= TDA9887_AUTOMUTE; dev->automute = 0; - INIT_LIST_HEAD(&dev->video_q.queue); + INIT_LIST_HEAD(&dev->video_q.queue); init_timer(&dev->video_q.timeout); dev->video_q.timeout.function = saa7134_buffer_timeout; dev->video_q.timeout.data = (unsigned long)(&dev->video_q); diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 99bbdcf727c3..064c2f7a8c12 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -346,7 +346,7 @@ struct saa7134_fh { /* oss dsp status */ struct saa7134_oss { - struct semaphore lock; + struct semaphore lock; int minor_mixer; int minor_dsp; unsigned int users_dsp; @@ -384,9 +384,9 @@ struct saa7134_ir { u32 mask_keycode; u32 mask_keydown; u32 mask_keyup; - int polling; - u32 last_gpio; - struct timer_list timer; + int polling; + u32 last_gpio; + struct timer_list timer; }; /* ts/mpeg status */ @@ -409,8 +409,8 @@ struct saa7134_mpeg_ops { /* global device status */ struct saa7134_dev { struct list_head devlist; - struct semaphore lock; - spinlock_t slock; + struct semaphore lock; + spinlock_t slock; #ifdef VIDIOC_G_PRIORITY struct v4l2_prio_state prio; #endif diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c index 255b6088ebf9..14cf1d357c3b 100644 --- a/drivers/media/video/tda7432.c +++ b/drivers/media/video/tda7432.c @@ -310,9 +310,9 @@ static int tda7432_attach(struct i2c_adapter *adap, int addr, int kind) memset(t,0,sizeof *t); client = &t->c; - memcpy(client,&client_template,sizeof(struct i2c_client)); - client->adapter = adap; - client->addr = addr; + memcpy(client,&client_template,sizeof(struct i2c_client)); + client->adapter = adap; + client->addr = addr; i2c_set_clientdata(client, t); do_tda7432_init(client); @@ -472,7 +472,7 @@ static int tda7432_command(struct i2c_client *client, } } - t->muted=(va->flags & VIDEO_AUDIO_MUTE); + t->muted=(va->flags & VIDEO_AUDIO_MUTE); if (t->muted) { /* Mute & update balance*/ @@ -503,12 +503,12 @@ static int tda7432_command(struct i2c_client *client, static struct i2c_driver driver = { .owner = THIS_MODULE, - .name = "i2c tda7432 driver", + .name = "i2c tda7432 driver", .id = I2C_DRIVERID_TDA7432, - .flags = I2C_DF_NOTIFY, + .flags = I2C_DF_NOTIFY, .attach_adapter = tda7432_probe, - .detach_client = tda7432_detach, - .command = tda7432_command, + .detach_client = tda7432_detach, + .command = tda7432_command, }; static struct i2c_client client_template = diff --git a/drivers/media/video/tda8290.c b/drivers/media/video/tda8290.c index 1e2acc4abbe6..e2027dada5d1 100644 --- a/drivers/media/video/tda8290.c +++ b/drivers/media/video/tda8290.c @@ -48,7 +48,7 @@ static struct freq_entry div_table[] = { { 0x1C34, 3 }, { 0x0D34, 2 }, { 0x067B, 1 }, - { 0x0000, 0 }, + { 0x0000, 0 }, }; static struct freq_entry agc_table[] = { diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c index 7e3dcdb262b0..5a9faefc3640 100644 --- a/drivers/media/video/tda9875.c +++ b/drivers/media/video/tda9875.c @@ -126,20 +126,20 @@ static int tda9875_write(struct i2c_client *client, int subaddr, unsigned char v static int i2c_read_register(struct i2c_adapter *adap, int addr, int reg) { - unsigned char write[1]; - unsigned char read[1]; - struct i2c_msg msgs[2] = { - { addr, 0, 1, write }, - { addr, I2C_M_RD, 1, read } - }; - write[0] = reg; - - if (2 != i2c_transfer(adap,msgs,2)) { - printk(KERN_WARNING "tda9875: I/O error (read2)\n"); - return -1; - } - dprintk("tda9875: chip_read2: reg%d=0x%x\n",reg,read[0]); - return read[0]; + unsigned char write[1]; + unsigned char read[1]; + struct i2c_msg msgs[2] = { + { addr, 0, 1, write }, + { addr, I2C_M_RD, 1, read } + }; + write[0] = reg; + + if (2 != i2c_transfer(adap,msgs,2)) { + printk(KERN_WARNING "tda9875: I/O error (read2)\n"); + return -1; + } + dprintk("tda9875: chip_read2: reg%d=0x%x\n",reg,read[0]); + return read[0]; } static void tda9875_set(struct i2c_client *client) @@ -184,7 +184,7 @@ static void do_tda9875_init(struct i2c_client *client) tda9875_write(client, TDA9875_DACOS, 0x02 ); /* sig DAC i/o(in:nicam)*/ tda9875_write(client, TDA9875_ADCIS, 0x6f ); /* sig ADC input(in:mono)*/ tda9875_write(client, TDA9875_LOSR, 0x00 ); /* line out (in:mono)*/ - tda9875_write(client, TDA9875_AER, 0x00 ); /*06 Effect (AVL+PSEUDO) */ + tda9875_write(client, TDA9875_AER, 0x00 ); /*06 Effect (AVL+PSEUDO) */ tda9875_write(client, TDA9875_MCS, 0x44 ); /* Main ch select (DAC) */ tda9875_write(client, TDA9875_MVL, 0x03 ); /* Vol Main left 10dB */ tda9875_write(client, TDA9875_MVR, 0x03 ); /* Vol Main right 10dB*/ @@ -200,7 +200,7 @@ static void do_tda9875_init(struct i2c_client *client) t->mode=AUDIO_UNMUTE; t->lvol=t->rvol =0; /* 0dB */ - t->bass=0; /* 0dB */ + t->bass=0; /* 0dB */ t->treble=0; /* 0dB */ tda9875_set(client); @@ -239,9 +239,9 @@ static int tda9875_attach(struct i2c_adapter *adap, int addr, int kind) memset(t,0,sizeof *t); client = &t->c; - memcpy(client,&client_template,sizeof(struct i2c_client)); - client->adapter = adap; - client->addr = addr; + memcpy(client,&client_template,sizeof(struct i2c_client)); + client->adapter = adap; + client->addr = addr; i2c_set_clientdata(client, t); if(!tda9875_checkit(adap,addr)) { @@ -287,7 +287,7 @@ static int tda9875_command(struct i2c_client *client, dprintk("In tda9875_command...\n"); switch (cmd) { - /* --- v4l ioctls --- */ + /* --- v4l ioctls --- */ /* take care: bttv does userspace copying, we'll get a kernel pointer here... */ case VIDIOCGAUDIO: @@ -355,7 +355,7 @@ static int tda9875_command(struct i2c_client *client, //printk("tda9875 bal:%04x vol:%04x bass:%04x treble:%04x\n",va->balance,va->volume,va->bass,va->treble); - tda9875_set(client); + tda9875_set(client); break; @@ -374,18 +374,18 @@ static int tda9875_command(struct i2c_client *client, static struct i2c_driver driver = { .owner = THIS_MODULE, - .name = "i2c tda9875 driver", - .id = I2C_DRIVERID_TDA9875, - .flags = I2C_DF_NOTIFY, + .name = "i2c tda9875 driver", + .id = I2C_DRIVERID_TDA9875, + .flags = I2C_DF_NOTIFY, .attach_adapter = tda9875_probe, - .detach_client = tda9875_detach, - .command = tda9875_command, + .detach_client = tda9875_detach, + .command = tda9875_command, }; static struct i2c_client client_template = { - .name = "tda9875", - .driver = &driver, + .name = "tda9875", + .driver = &driver, }; static int __init tda9875_init(void) diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 6d2914f738f2..9d6b6f57abcd 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -46,11 +46,11 @@ MODULE_LICENSE("GPL"); #define UNSET (-1U) #define tda9887_info(fmt, arg...) do {\ printk(KERN_INFO "%s %d-%04x: " fmt, t->client.name, \ - i2c_adapter_id(t->client.adapter), t->client.addr , ##arg); } while (0) + i2c_adapter_id(t->client.adapter), t->client.addr , ##arg); } while (0) #define tda9887_dbg(fmt, arg...) do {\ if (debug) \ - printk(KERN_INFO "%s %d-%04x: " fmt, t->client.name, \ - i2c_adapter_id(t->client.adapter), t->client.addr , ##arg); } while (0) + printk(KERN_INFO "%s %d-%04x: " fmt, t->client.name, \ + i2c_adapter_id(t->client.adapter), t->client.addr , ##arg); } while (0) struct tda9887 { struct i2c_client client; @@ -484,11 +484,11 @@ static int tda9887_set_pinnacle(struct tda9887 *t, char *buf) } } if (t->std & V4L2_STD_525_60) { - if ((5 == t->pinnacle_id) || (6 == t->pinnacle_id)) { + if ((5 == t->pinnacle_id) || (6 == t->pinnacle_id)) { bCarrierMode = cIntercarrier; } else { bCarrierMode = cQSS; - } + } } if (bCarrierMode != UNSET) { @@ -568,8 +568,8 @@ static int tda9887_status(struct tda9887 *t) int rc; memset(buf,0,sizeof(buf)); - if (1 != (rc = i2c_master_recv(&t->client,buf,1))) - tda9887_info("i2c i/o error: rc == %d (should be 1)\n",rc); + if (1 != (rc = i2c_master_recv(&t->client,buf,1))) + tda9887_info("i2c i/o error: rc == %d (should be 1)\n",rc); dump_read_message(t, buf); return 0; } @@ -600,8 +600,8 @@ static int tda9887_configure(struct tda9887 *t) if (debug > 1) dump_write_message(t, t->data); - if (4 != (rc = i2c_master_send(&t->client,t->data,4))) - tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc); + if (4 != (rc = i2c_master_send(&t->client,t->data,4))) + tda9887_info("i2c i/o error: rc == %d (should be 4)\n",rc); if (debug > 2) { msleep_interruptible(1000); @@ -616,11 +616,11 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind) { struct tda9887 *t; - client_template.adapter = adap; - client_template.addr = addr; + client_template.adapter = adap; + client_template.addr = addr; - if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL))) - return -ENOMEM; + if (NULL == (t = kmalloc(sizeof(*t), GFP_KERNEL))) + return -ENOMEM; memset(t,0,sizeof(*t)); t->client = client_template; @@ -628,7 +628,7 @@ static int tda9887_attach(struct i2c_adapter *adap, int addr, int kind) t->pinnacle_id = UNSET; t->radio_mode = V4L2_TUNER_MODE_STEREO; - tda9887_info("chip found @ 0x%x (%s)\n", addr<<1, adap->name); + tda9887_info("chip found @ 0x%x (%s)\n", addr<<1, adap->name); i2c_set_clientdata(&t->client, t); i2c_attach_client(&t->client); @@ -663,18 +663,18 @@ static int tda9887_detach(struct i2c_client *client) } #define SWITCH_V4L2 if (!t->using_v4l2 && debug) \ - tda9887_info("switching to v4l2\n"); \ - t->using_v4l2 = 1; + tda9887_info("switching to v4l2\n"); \ + t->using_v4l2 = 1; #define CHECK_V4L2 if (t->using_v4l2) { if (debug) \ tda9887_info("ignore v4l1 call\n"); \ - return 0; } + return 0; } static int tda9887_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct tda9887 *t = i2c_get_clientdata(client); - switch (cmd) { + switch (cmd) { /* --- configuration --- */ case AUDC_SET_RADIO: diff --git a/drivers/media/video/tea5767.c b/drivers/media/video/tea5767.c index 38bf50943798..a9375ef05de1 100644 --- a/drivers/media/video/tea5767.c +++ b/drivers/media/video/tea5767.c @@ -117,10 +117,10 @@ #define TEA5767_RESERVED_MASK 0xff enum tea5767_xtal_freq { - TEA5767_LOW_LO_32768 = 0, - TEA5767_HIGH_LO_32768 = 1, - TEA5767_LOW_LO_13MHz = 2, - TEA5767_HIGH_LO_13MHz = 3, + TEA5767_LOW_LO_32768 = 0, + TEA5767_HIGH_LO_32768 = 1, + TEA5767_LOW_LO_13MHz = 2, + TEA5767_HIGH_LO_13MHz = 3, }; diff --git a/drivers/media/video/tuner-core.c b/drivers/media/video/tuner-core.c index 44fa1423c1a9..e677869afcf3 100644 --- a/drivers/media/video/tuner-core.c +++ b/drivers/media/video/tuner-core.c @@ -432,23 +432,23 @@ static int tuner_detach(struct i2c_client *client) static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, char *cmd) { - if (mode == t->mode) - return 0; - - t->mode = mode; - - if (check_mode(t, cmd) == EINVAL) { - t->mode = T_STANDBY; - if (t->standby) - t->standby (client); - return EINVAL; - } - return 0; + if (mode == t->mode) + return 0; + + t->mode = mode; + + if (check_mode(t, cmd) == EINVAL) { + t->mode = T_STANDBY; + if (t->standby) + t->standby (client); + return EINVAL; + } + return 0; } #define switch_v4l2() if (!t->using_v4l2) \ - tuner_dbg("switching to v4l2\n"); \ - t->using_v4l2 = 1; + tuner_dbg("switching to v4l2\n"); \ + t->using_v4l2 = 1; static inline int check_v4l2(struct tuner *t) { @@ -623,7 +623,7 @@ static int tuner_command(struct i2c_client *client, unsigned int cmd, void *arg) switch_v4l2(); if (V4L2_TUNER_RADIO == f->type && V4L2_TUNER_RADIO != t->mode) { - if (set_mode (client, t, f->type, "VIDIOC_S_FREQUENCY") + if (set_mode (client, t, f->type, "VIDIOC_S_FREQUENCY") == EINVAL) return 0; } diff --git a/drivers/media/video/tuner-simple.c b/drivers/media/video/tuner-simple.c index e67d9e77c755..84338f1e3038 100644 --- a/drivers/media/video/tuner-simple.c +++ b/drivers/media/video/tuner-simple.c @@ -102,7 +102,7 @@ struct tunertype */ static struct tunertype tuners[] = { /* 0-9 */ - { "Temic PAL (4002 FH5)", TEMIC, PAL, + { "Temic PAL (4002 FH5)", TEMIC, PAL, 16*140.25,16*463.25,0x02,0x04,0x01,0x8e,623}, { "Philips PAL_I (FI1246 and compatibles)", Philips, PAL_I, 16*140.25,16*463.25,0xa0,0x90,0x30,0x8e,623}, @@ -118,41 +118,41 @@ static struct tunertype tuners[] = { 16*157.25,16*463.25,0x02,0x04,0x01,0x8e,732}, { "Temic PAL_I (4062 FY5)", TEMIC, PAL_I, 16*170.00,16*450.00,0x02,0x04,0x01,0x8e,623}, - { "Temic NTSC (4036 FY5)", TEMIC, NTSC, + { "Temic NTSC (4036 FY5)", TEMIC, NTSC, 16*157.25,16*463.25,0xa0,0x90,0x30,0x8e,732}, - { "Alps HSBH1", TEMIC, NTSC, + { "Alps HSBH1", TEMIC, NTSC, 16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732}, /* 10-19 */ - { "Alps TSBE1", TEMIC, PAL, + { "Alps TSBE1", TEMIC, PAL, 16*137.25,16*385.25,0x01,0x02,0x08,0x8e,732}, - { "Alps TSBB5", Alps, PAL_I, /* tested (UK UHF) with Modulartech MM205 */ + { "Alps TSBB5", Alps, PAL_I, /* tested (UK UHF) with Modulartech MM205 */ 16*133.25,16*351.25,0x01,0x02,0x08,0x8e,632}, - { "Alps TSBE5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */ + { "Alps TSBE5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */ 16*133.25,16*351.25,0x01,0x02,0x08,0x8e,622}, - { "Alps TSBC5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */ + { "Alps TSBC5", Alps, PAL, /* untested - data sheet guess. Only IF differs. */ 16*133.25,16*351.25,0x01,0x02,0x08,0x8e,608}, { "Temic PAL_BG (4006FH5)", TEMIC, PAL, 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, - { "Alps TSCH6", Alps, NTSC, - 16*137.25,16*385.25,0x14,0x12,0x11,0x8e,732}, - { "Temic PAL_DK (4016 FY5)", TEMIC, PAL, - 16*168.25,16*456.25,0xa0,0x90,0x30,0x8e,623}, - { "Philips NTSC_M (MK2)", Philips, NTSC, - 16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732}, - { "Temic PAL_I (4066 FY5)", TEMIC, PAL_I, - 16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623}, - { "Temic PAL* auto (4006 FN5)", TEMIC, PAL, - 16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623}, + { "Alps TSCH6", Alps, NTSC, + 16*137.25,16*385.25,0x14,0x12,0x11,0x8e,732}, + { "Temic PAL_DK (4016 FY5)", TEMIC, PAL, + 16*168.25,16*456.25,0xa0,0x90,0x30,0x8e,623}, + { "Philips NTSC_M (MK2)", Philips, NTSC, + 16*160.00,16*454.00,0xa0,0x90,0x30,0x8e,732}, + { "Temic PAL_I (4066 FY5)", TEMIC, PAL_I, + 16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623}, + { "Temic PAL* auto (4006 FN5)", TEMIC, PAL, + 16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623}, /* 20-29 */ - { "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)", TEMIC, PAL, - 16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623}, - { "Temic NTSC (4039 FR5)", TEMIC, NTSC, - 16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732}, - { "Temic PAL/SECAM multi (4046 FM5)", TEMIC, PAL, - 16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623}, - { "Philips PAL_DK (FI1256 and compatibles)", Philips, PAL, + { "Temic PAL_BG (4009 FR5) or PAL_I (4069 FR5)", TEMIC, PAL, + 16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623}, + { "Temic NTSC (4039 FR5)", TEMIC, NTSC, + 16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732}, + { "Temic PAL/SECAM multi (4046 FM5)", TEMIC, PAL, + 16*169.00, 16*454.00, 0xa0,0x90,0x30,0x8e,623}, + { "Philips PAL_DK (FI1256 and compatibles)", Philips, PAL, 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, { "Philips PAL/SECAM multi (FQ1216ME)", Philips, PAL, 16*170.00,16*450.00,0xa0,0x90,0x30,0x8e,623}, @@ -173,21 +173,21 @@ static struct tunertype tuners[] = { { "SHARP NTSC_JP (2U5JF5540)", SHARP, NTSC, /* 940=16*58.75 NTSC@Japan */ 16*137.25,16*317.25,0x01,0x02,0x08,0x8e,940 }, { "Samsung PAL TCPM9091PD27", Samsung, PAL, /* from sourceforge v3tv */ - 16*169,16*464,0xA0,0x90,0x30,0x8e,623}, + 16*169,16*464,0xA0,0x90,0x30,0x8e,623}, { "MT20xx universal", Microtune, PAL|NTSC, /* see mt20xx.c for details */ }, { "Temic PAL_BG (4106 FH5)", TEMIC, PAL, - 16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623}, + 16*141.00, 16*464.00, 0xa0,0x90,0x30,0x8e,623}, { "Temic PAL_DK/SECAM_L (4012 FY5)", TEMIC, PAL, - 16*140.25, 16*463.25, 0x02,0x04,0x01,0x8e,623}, + 16*140.25, 16*463.25, 0x02,0x04,0x01,0x8e,623}, { "Temic NTSC (4136 FY5)", TEMIC, NTSC, - 16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732}, - { "LG PAL (newer TAPC series)", LGINNOTEK, PAL, - 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,623}, + 16*158.00, 16*453.00, 0xa0,0x90,0x30,0x8e,732}, + { "LG PAL (newer TAPC series)", LGINNOTEK, PAL, + 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,623}, { "Philips PAL/SECAM multi (FM1216ME MK3)", Philips, PAL, 16*158.00,16*442.00,0x01,0x02,0x04,0x8e,623 }, { "LG NTSC (newer TAPC series)", LGINNOTEK, NTSC, - 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,732}, + 16*170.00, 16*450.00, 0x01,0x02,0x08,0x8e,732}, /* 40-49 */ { "HITACHI V7-J180AT", HITACHI, NTSC, @@ -196,24 +196,24 @@ static struct tunertype tuners[] = { 16*140.25,16*463.25,0x01,0xc2,0xcf,0x8e,623}, { "Philips 1236D ATSC/NTSC daul in", Philips, ATSC, 16*157.25,16*454.00,0xa0,0x90,0x30,0x8e,732}, - { "Philips NTSC MK3 (FM1236MK3 or FM1236/F)", Philips, NTSC, - 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732}, - { "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)", Philips, NTSC, - 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732}, + { "Philips NTSC MK3 (FM1236MK3 or FM1236/F)", Philips, NTSC, + 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732}, + { "Philips 4 in 1 (ATI TV Wonder Pro/Conexant)", Philips, NTSC, + 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732}, { "Microtune 4049 FM5", Microtune, PAL, 16*141.00,16*464.00,0xa0,0x90,0x30,0x8e,623}, { "Panasonic VP27s/ENGE4324D", Panasonic, NTSC, 16*160.00,16*454.00,0x01,0x02,0x08,0xce,940}, - { "LG NTSC (TAPE series)", LGINNOTEK, NTSC, - 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 }, - { "Tenna TNF 8831 BGFF)", Philips, PAL, - 16*161.25,16*463.25,0xa0,0x90,0x30,0x8e,623}, + { "LG NTSC (TAPE series)", LGINNOTEK, NTSC, + 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,732 }, + { "Tenna TNF 8831 BGFF)", Philips, PAL, + 16*161.25,16*463.25,0xa0,0x90,0x30,0x8e,623}, { "Microtune 4042 FI5 ATSC/NTSC dual in", Microtune, NTSC, 16*162.00,16*457.00,0xa2,0x94,0x31,0x8e,732}, /* 50-59 */ - { "TCL 2002N", TCL, NTSC, - 16*172.00,16*448.00,0x01,0x02,0x08,0x8e,732}, + { "TCL 2002N", TCL, NTSC, + 16*172.00,16*448.00,0x01,0x02,0x08,0x8e,732}, { "Philips PAL/SECAM_D (FM 1256 I-H3)", Philips, PAL, 16*160.00,16*442.00,0x01,0x02,0x04,0x8e,623 }, { "Thomson DDT 7610 (ATSC/NTSC)", THOMSON, ATSC, @@ -223,7 +223,7 @@ static struct tunertype tuners[] = { { "tda8290+75", Philips, PAL|NTSC, /* see tda8290.c for details */ }, { "TCL 2002MB", TCL, PAL, - 16*170.00, 16*450.00, 0x01,0x02,0x08,0xce,623}, + 16*170.00, 16*450.00, 0x01,0x02,0x08,0xce,623}, { "Philips PAL/SECAM multi (FQ1216AME MK4)", Philips, PAL, 16*160.00,16*442.00,0x01,0x02,0x04,0xce,623 }, { "Philips FQ1236A MK4", Philips, NTSC, @@ -237,16 +237,16 @@ static struct tunertype tuners[] = { { "Thomson DDT 7611 (ATSC/NTSC)", THOMSON, ATSC, 16*157.25,16*454.00,0x39,0x3a,0x3c,0x8e,732}, { "Tena TNF9533-D/IF/TNF9533-B/DF", Philips, PAL, - 16*160.25,16*464.25,0x01,0x02,0x04,0x8e,623}, + 16*160.25,16*464.25,0x01,0x02,0x04,0x8e,623}, { "Philips TEA5767HN FM Radio", Philips, RADIO, - /* see tea5767.c for details */}, + /* see tea5767.c for details */}, { "Philips FMD1216ME MK3 Hybrid Tuner", Philips, PAL, 16*160.00,16*442.00,0x51,0x52,0x54,0x86,623 }, { "LG TDVS-H062F/TUA6034", LGINNOTEK, ATSC, 16*160.00,16*455.00,0x01,0x02,0x04,0x8e,732}, { "Ymec TVF66T5-B/DFF", Philips, PAL, - 16*160.25,16*464.25,0x01,0x02,0x08,0x8e,623}, - { "LG NTSC (TALN mini series)", LGINNOTEK, NTSC, + 16*160.25,16*464.25,0x01,0x02,0x08,0x8e,623}, + { "LG NTSC (TALN mini series)", LGINNOTEK, NTSC, 16*137.25,16*373.25,0x01,0x02,0x08,0x8e,732 }, { "Philips TD1316 Hybrid Tuner", Philips, PAL, 16*160.00,16*442.00,0xa1,0xa2,0xa4,0xc8,623 }, @@ -281,7 +281,7 @@ static int tuner_stereo(struct i2c_client *c) status = tuner_getstatus (c); switch (t->type) { - case TUNER_PHILIPS_FM1216ME_MK3: + case TUNER_PHILIPS_FM1216ME_MK3: case TUNER_PHILIPS_FM1236_MK3: case TUNER_PHILIPS_FM1256_IH3: stereo = ((status & TUNER_SIGNAL) == TUNER_STEREO_MK3); @@ -302,7 +302,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) u8 config; u16 div; struct tunertype *tun; - unsigned char buffer[4]; + unsigned char buffer[4]; int rc; tun = &tuners[t->type]; @@ -419,7 +419,7 @@ static void default_set_tv_freq(struct i2c_client *c, unsigned int freq) tuner_dbg("tv 0x%02x 0x%02x 0x%02x 0x%02x\n", buffer[0],buffer[1],buffer[2],buffer[3]); - if (4 != (rc = i2c_master_send(c,buffer,4))) + if (4 != (rc = i2c_master_send(c,buffer,4))) tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); if (t->type == TUNER_MICROTUNE_4042FI5) { @@ -458,7 +458,7 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) { struct tunertype *tun; struct tuner *t = i2c_get_clientdata(c); - unsigned char buffer[4]; + unsigned char buffer[4]; unsigned div; int rc; @@ -491,13 +491,13 @@ static void default_set_radio_freq(struct i2c_client *c, unsigned int freq) buffer[3] = 0xa4; break; } - buffer[0] = (div>>8) & 0x7f; - buffer[1] = div & 0xff; + buffer[0] = (div>>8) & 0x7f; + buffer[1] = div & 0xff; tuner_dbg("radio 0x%02x 0x%02x 0x%02x 0x%02x\n", buffer[0],buffer[1],buffer[2],buffer[3]); - if (4 != (rc = i2c_master_send(c,buffer,4))) + if (4 != (rc = i2c_master_send(c,buffer,4))) tuner_warn("i2c i/o error: rc == %d (should be 4)\n",rc); } diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 1c31ef52f863..e1639a24f77f 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -458,8 +458,8 @@ static void tda9840_setmode(struct CHIPSTATE *chip, int mode) #define TDA9855_LOUD 1<<5 /* Loudness, 1==off */ #define TDA9855_SUR 1<<3 /* Surround / Subwoofer 1==.5(L-R) 0==.5(L+R) */ /* Bits 0 to 3 select various combinations - * of line in and line out, only the - * interesting ones are defined */ + * of line in and line out, only the + * interesting ones are defined */ #define TDA9855_EXT 1<<2 /* Selects inputs LIR and LIL. Pins 41 & 12 */ #define TDA9855_INT 0 /* Selects inputs LOR and LOL. (internal) */ @@ -1028,7 +1028,7 @@ static int tda9874a_initialize(struct CHIPSTATE *chip) #define TEA6300_TR 0x03 /* treble */ #define TEA6300_FA 0x04 /* fader control */ #define TEA6300_S 0x05 /* switch register */ - /* values for those registers: */ + /* values for those registers: */ #define TEA6300_S_SA 0x01 /* stereo A input */ #define TEA6300_S_SB 0x02 /* stereo B */ #define TEA6300_S_SC 0x04 /* stereo C */ @@ -1042,7 +1042,7 @@ static int tda9874a_initialize(struct CHIPSTATE *chip) #define TEA6320_BA 0x05 /* bass (0-4) */ #define TEA6320_TR 0x06 /* treble (0-4) */ #define TEA6320_S 0x07 /* switch register */ - /* values for those registers: */ + /* values for those registers: */ #define TEA6320_S_SA 0x07 /* stereo A input */ #define TEA6320_S_SB 0x06 /* stereo B */ #define TEA6320_S_SC 0x05 /* stereo C */ @@ -1082,7 +1082,7 @@ static int tea6320_initialize(struct CHIPSTATE * chip) #define TDA8425_BA 0x02 /* bass */ #define TDA8425_TR 0x03 /* treble */ #define TDA8425_S1 0x08 /* switch functions */ - /* values for those registers: */ + /* values for those registers: */ #define TDA8425_S1_OFF 0xEE /* audio off (mute on) */ #define TDA8425_S1_CH1 0xCE /* audio channel 1 (mute off) - "linear stereo" mode */ #define TDA8425_S1_CH2 0xCF /* audio channel 2 (mute off) - "linear stereo" mode */ @@ -1148,7 +1148,7 @@ static void tda8425_setmode(struct CHIPSTATE *chip, int mode) /* bit definition of the RESET register, I2C data. */ #define PIC16C54_MISC_RESET_REMOTE_CTL 0x01 /* bit 0, Reset to receive the key */ - /* code of remote controller */ + /* code of remote controller */ #define PIC16C54_MISC_MTS_MAIN 0x02 /* bit 1 */ #define PIC16C54_MISC_MTS_SAP 0x04 /* bit 2 */ #define PIC16C54_MISC_MTS_BOTH 0x08 /* bit 3 */ @@ -1281,7 +1281,7 @@ static struct CHIPDESC chiplist[] = { .setmode = tda9840_setmode, .checkmode = generic_checkmode, - .init = { 2, { TDA9840_TEST, TDA9840_TEST_INT1SN + .init = { 2, { TDA9840_TEST, TDA9840_TEST_INT1SN /* ,TDA9840_SW, TDA9840_MONO */} } }, { @@ -1467,7 +1467,7 @@ static struct CHIPDESC chiplist[] = { .setmode = ta8874z_setmode, .checkmode = generic_checkmode, - .init = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}}, + .init = {2, { TA8874Z_MONO_SET, TA8874Z_SEPARATION_DEFAULT}}, }, { .name = NULL } /* EOF */ }; @@ -1486,8 +1486,8 @@ static int chip_attach(struct i2c_adapter *adap, int addr, int kind) return -ENOMEM; memset(chip,0,sizeof(*chip)); memcpy(&chip->c,&client_template,sizeof(struct i2c_client)); - chip->c.adapter = adap; - chip->c.addr = addr; + chip->c.adapter = adap; + chip->c.addr = addr; i2c_set_clientdata(&chip->c, chip); /* find description for the chip */ diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index ee605712bf19..68128e04dacc 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -6,12 +6,12 @@ * which are: Copyright (C) 1996,97,98 Ralph Metzler (rjkm@thp.uni-koeln.de) - & Marcus Metzler (mocm@thp.uni-koeln.de) + & Marcus Metzler (mocm@thp.uni-koeln.de) (c) 1999-2001 Gerd Knorr * Adjustments to fit a more general model and all bugs: - Copyright (C) 2003 John Klar + Copyright (C) 2003 John Klar * 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 @@ -54,14 +54,14 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)"); #define tveeprom_info(fmt, arg...) do {\ printk(KERN_INFO "tveeprom %d-%04x: " fmt, \ - c->adapter->nr, c->addr , ##arg); } while (0) + c->adapter->nr, c->addr , ##arg); } while (0) #define tveeprom_warn(fmt, arg...) do {\ printk(KERN_WARNING "tveeprom %d-%04x: " fmt, \ - c->adapter->nr, c->addr , ##arg); } while (0) + c->adapter->nr, c->addr , ##arg); } while (0) #define tveeprom_dbg(fmt, arg...) do {\ if (debug) \ - printk(KERN_INFO "tveeprom %d-%04x: " fmt, \ - c->adapter->nr, c->addr , ##arg); } while (0) + printk(KERN_INFO "tveeprom %d-%04x: " fmt, \ + c->adapter->nr, c->addr , ##arg); } while (0) /* ----------------------------------------------------------------------- */ @@ -294,7 +294,7 @@ static const char *decoderIC[] = { static int hasRadioTuner(int tunerType) { - switch (tunerType) { + switch (tunerType) { case 18: //PNPEnv_TUNER_FR1236_MK2: case 23: //PNPEnv_TUNER_FM1236: case 38: //PNPEnv_TUNER_FMR1236: @@ -326,12 +326,12 @@ static int hasRadioTuner(int tunerType) case 89: //PNPEnv_TUNER_TCL_MFPE05_2: case 92: //PNPEnv_TUNER_PHILIPS_FQ1236A_MK4: return 1; - } - return 0; + } + return 0; } void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, - unsigned char *eeprom_data) + unsigned char *eeprom_data) { /* ---------------------------------------------- ** The hauppauge eeprom format is tagged diff --git a/drivers/media/video/tvmixer.c b/drivers/media/video/tvmixer.c index d86e08ebddfc..8318bd1aad00 100644 --- a/drivers/media/video/tvmixer.c +++ b/drivers/media/video/tvmixer.c @@ -79,7 +79,7 @@ static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cm { struct video_audio va; int left,right,ret,val = 0; - struct TVMIXER *mix = file->private_data; + struct TVMIXER *mix = file->private_data; struct i2c_client *client = mix->dev; void __user *argp = (void __user *)arg; int __user *p = argp; @@ -87,25 +87,25 @@ static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cm if (NULL == client) return -ENODEV; - if (cmd == SOUND_MIXER_INFO) { - mixer_info info; - strlcpy(info.id, "tv card", sizeof(info.id)); - strlcpy(info.name, client->name, sizeof(info.name)); - info.modify_counter = 42 /* FIXME */; - if (copy_to_user(argp, &info, sizeof(info))) - return -EFAULT; - return 0; - } - if (cmd == SOUND_OLD_MIXER_INFO) { - _old_mixer_info info; - strlcpy(info.id, "tv card", sizeof(info.id)); - strlcpy(info.name, client->name, sizeof(info.name)); - if (copy_to_user(argp, &info, sizeof(info))) - return -EFAULT; - return 0; - } - if (cmd == OSS_GETVERSION) - return put_user(SOUND_VERSION, p); + if (cmd == SOUND_MIXER_INFO) { + mixer_info info; + strlcpy(info.id, "tv card", sizeof(info.id)); + strlcpy(info.name, client->name, sizeof(info.name)); + info.modify_counter = 42 /* FIXME */; + if (copy_to_user(argp, &info, sizeof(info))) + return -EFAULT; + return 0; + } + if (cmd == SOUND_OLD_MIXER_INFO) { + _old_mixer_info info; + strlcpy(info.id, "tv card", sizeof(info.id)); + strlcpy(info.name, client->name, sizeof(info.name)); + if (copy_to_user(argp, &info, sizeof(info))) + return -EFAULT; + return 0; + } + if (cmd == OSS_GETVERSION) + return put_user(SOUND_VERSION, p); if (_SIOC_DIR(cmd) & _SIOC_WRITE) if (get_user(val, p)) @@ -181,8 +181,8 @@ static int tvmixer_ioctl(struct inode *inode, struct file *file, unsigned int cm static int tvmixer_open(struct inode *inode, struct file *file) { - int i, minor = iminor(inode); - struct TVMIXER *mix = NULL; + int i, minor = iminor(inode); + struct TVMIXER *mix = NULL; struct i2c_client *client = NULL; for (i = 0; i < DEV_MAX; i++) { @@ -204,7 +204,7 @@ static int tvmixer_open(struct inode *inode, struct file *file) #endif if (client->adapter->owner) try_module_get(client->adapter->owner); - return 0; + return 0; } static int tvmixer_release(struct inode *inode, struct file *file) @@ -231,15 +231,15 @@ static struct i2c_driver driver = { .owner = THIS_MODULE, #endif .name = "tv card mixer driver", - .id = I2C_DRIVERID_TVMIXER, + .id = I2C_DRIVERID_TVMIXER, #ifdef I2C_DF_DUMMY .flags = I2C_DF_DUMMY, #else .flags = I2C_DF_NOTIFY, - .detach_adapter = tvmixer_adapters, + .detach_adapter = tvmixer_adapters, #endif - .attach_adapter = tvmixer_adapters, - .detach_client = tvmixer_clients, + .attach_adapter = tvmixer_adapters, + .detach_client = tvmixer_clients, }; static struct file_operations tvmixer_fops = { diff --git a/drivers/media/video/v4l1-compat.c b/drivers/media/video/v4l1-compat.c index 88beb5a3be15..4134549d11a8 100644 --- a/drivers/media/video/v4l1-compat.c +++ b/drivers/media/video/v4l1-compat.c @@ -960,7 +960,7 @@ v4l_compat_translate_ioctl(struct inode *inode, fmt->start[1] = fmt2->fmt.vbi.start[1]; fmt->count[1] = fmt2->fmt.vbi.count[1]; fmt->flags = fmt2->fmt.vbi.flags & 0x03; - break; + break; } case VIDIOCSVBIFMT: { diff --git a/drivers/media/video/video-buf.c b/drivers/media/video/video-buf.c index 574b8e36f3c6..acfd3a103f35 100644 --- a/drivers/media/video/video-buf.c +++ b/drivers/media/video/video-buf.c @@ -147,7 +147,7 @@ int videobuf_dma_init_user(struct videobuf_dmabuf *dma, int direction, data,size,dma->nr_pages); down_read(¤t->mm->mmap_sem); - err = get_user_pages(current,current->mm, + err = get_user_pages(current,current->mm, data & PAGE_MASK, dma->nr_pages, rw == READ, 1, /* force */ dma->pages, NULL); @@ -750,9 +750,9 @@ videobuf_read_zerocopy(struct videobuf_queue *q, char __user *data, { enum v4l2_field field; unsigned long flags; - int retval; + int retval; - /* setup stuff */ + /* setup stuff */ retval = -ENOMEM; q->read_buf = videobuf_alloc(q->msize); if (NULL == q->read_buf) @@ -760,18 +760,18 @@ videobuf_read_zerocopy(struct videobuf_queue *q, char __user *data, q->read_buf->memory = V4L2_MEMORY_USERPTR; q->read_buf->baddr = (unsigned long)data; - q->read_buf->bsize = count; + q->read_buf->bsize = count; field = videobuf_next_field(q); retval = q->ops->buf_prepare(q,q->read_buf,field); if (0 != retval) goto done; - /* start capture & wait */ + /* start capture & wait */ spin_lock_irqsave(q->irqlock,flags); q->ops->buf_queue(q,q->read_buf); spin_unlock_irqrestore(q->irqlock,flags); - retval = videobuf_waiton(q->read_buf,0,0); - if (0 == retval) { + retval = videobuf_waiton(q->read_buf,0,0); + if (0 == retval) { videobuf_dma_pci_sync(q->pci,&q->read_buf->dma); if (STATE_ERROR == q->read_buf->state) retval = -EIO; @@ -828,7 +828,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, } /* wait until capture is done */ - retval = videobuf_waiton(q->read_buf, nonblocking, 1); + retval = videobuf_waiton(q->read_buf, nonblocking, 1); if (0 != retval) goto done; videobuf_dma_pci_sync(q->pci,&q->read_buf->dma); @@ -1096,7 +1096,7 @@ videobuf_vm_nopage(struct vm_area_struct *vma, unsigned long vaddr, dprintk(3,"nopage: fault @ %08lx [vma %08lx-%08lx]\n", vaddr,vma->vm_start,vma->vm_end); - if (vaddr > vma->vm_end) + if (vaddr > vma->vm_end) return NOPAGE_SIGBUS; page = alloc_page(GFP_USER); if (!page) diff --git a/drivers/media/video/wm8775.c b/drivers/media/video/wm8775.c index 8200f3dad0c6..5bd592673b94 100644 --- a/drivers/media/video/wm8775.c +++ b/drivers/media/video/wm8775.c @@ -36,10 +36,10 @@ MODULE_LICENSE("GPL"); #define wm8775_err(fmt, arg...) do { \ printk(KERN_ERR "%s %d-%04x: " fmt, client->driver->name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) + i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) #define wm8775_info(fmt, arg...) do { \ printk(KERN_INFO "%s %d-%04x: " fmt, client->driver->name, \ - i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) + i2c_adapter_id(client->adapter), client->addr , ## arg); } while (0) static unsigned short normal_i2c[] = { 0x36 >> 1, I2C_CLIENT_END }; diff --git a/include/linux/videodev.h b/include/linux/videodev.h index 1cc8c31b7988..22e6e4bad7b8 100644 --- a/include/linux/videodev.h +++ b/include/linux/videodev.h @@ -202,9 +202,9 @@ struct video_audio #define VIDEO_SOUND_STEREO 2 #define VIDEO_SOUND_LANG1 4 #define VIDEO_SOUND_LANG2 8 - __u16 mode; - __u16 balance; /* Stereo balance */ - __u16 step; /* Step actual volume uses */ + __u16 mode; + __u16 balance; /* Stereo balance */ + __u16 step; /* Step actual volume uses */ }; struct video_clip diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 27979003db44..a9a0999be702 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -24,7 +24,7 @@ /* Four-character-code (FOURCC) */ #define v4l2_fourcc(a,b,c,d)\ - (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24)) + (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24)) /* * E N U M S @@ -154,20 +154,20 @@ struct v4l2_capability }; /* Values for 'capabilities' field */ -#define V4L2_CAP_VIDEO_CAPTURE 0x00000001 /* Is a video capture device */ -#define V4L2_CAP_VIDEO_OUTPUT 0x00000002 /* Is a video output device */ -#define V4L2_CAP_VIDEO_OVERLAY 0x00000004 /* Can do video overlay */ -#define V4L2_CAP_VBI_CAPTURE 0x00000010 /* Is a raw VBI capture device */ -#define V4L2_CAP_VBI_OUTPUT 0x00000020 /* Is a raw VBI output device */ +#define V4L2_CAP_VIDEO_CAPTURE 0x00000001 /* Is a video capture device */ +#define V4L2_CAP_VIDEO_OUTPUT 0x00000002 /* Is a video output device */ +#define V4L2_CAP_VIDEO_OVERLAY 0x00000004 /* Can do video overlay */ +#define V4L2_CAP_VBI_CAPTURE 0x00000010 /* Is a raw VBI capture device */ +#define V4L2_CAP_VBI_OUTPUT 0x00000020 /* Is a raw VBI output device */ #if 1 #define V4L2_CAP_SLICED_VBI_CAPTURE 0x00000040 /* Is a sliced VBI capture device */ #define V4L2_CAP_SLICED_VBI_OUTPUT 0x00000080 /* Is a sliced VBI output device */ #endif -#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */ +#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */ -#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */ -#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */ -#define V4L2_CAP_RADIO 0x00040000 /* is a radio device */ +#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */ +#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */ +#define V4L2_CAP_RADIO 0x00040000 /* is a radio device */ #define V4L2_CAP_READWRITE 0x01000000 /* read/write systemcalls */ #define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */ @@ -179,13 +179,13 @@ struct v4l2_capability struct v4l2_pix_format { - __u32 width; - __u32 height; - __u32 pixelformat; + __u32 width; + __u32 height; + __u32 pixelformat; enum v4l2_field field; __u32 bytesperline; /* for padding, zero if unused */ - __u32 sizeimage; - enum v4l2_colorspace colorspace; + __u32 sizeimage; + enum v4l2_colorspace colorspace; __u32 priv; /* private data, depends on pixelformat */ }; @@ -238,12 +238,12 @@ struct v4l2_pix_format */ struct v4l2_fmtdesc { - __u32 index; /* Format number */ + __u32 index; /* Format number */ enum v4l2_buf_type type; /* buffer type */ __u32 flags; - __u8 description[32]; /* Description string */ - __u32 pixelformat; /* Format fourcc */ - __u32 reserved[4]; + __u8 description[32]; /* Description string */ + __u32 pixelformat; /* Format fourcc */ + __u32 reserved[4]; }; #define V4L2_FMT_FLAG_COMPRESSED 0x0001 @@ -393,7 +393,7 @@ struct v4l2_jpegcompression #define V4L2_JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ #define V4L2_JPEG_MARKER_COM (1<<6) /* Comment segment */ #define V4L2_JPEG_MARKER_APP (1<<7) /* App segment, driver will - * allways use APP0 */ + * allways use APP0 */ }; @@ -402,10 +402,10 @@ struct v4l2_jpegcompression */ struct v4l2_requestbuffers { - __u32 count; + __u32 count; enum v4l2_buf_type type; enum v4l2_memory memory; - __u32 reserved[2]; + __u32 reserved[2]; }; struct v4l2_buffer @@ -511,9 +511,9 @@ struct v4l2_outputparm struct v4l2_cropcap { enum v4l2_buf_type type; - struct v4l2_rect bounds; - struct v4l2_rect defrect; - struct v4l2_fract pixelaspect; + struct v4l2_rect bounds; + struct v4l2_rect defrect; + struct v4l2_fract pixelaspect; }; struct v4l2_crop { @@ -587,7 +587,7 @@ typedef __u64 v4l2_std_id; V4L2_STD_PAL_Nc |\ V4L2_STD_SECAM) #define V4L2_STD_ATSC (V4L2_STD_ATSC_8_VSB |\ - V4L2_STD_ATSC_16_VSB) + V4L2_STD_ATSC_16_VSB) #define V4L2_STD_UNKNOWN 0 #define V4L2_STD_ALL (V4L2_STD_525_60 |\ @@ -595,7 +595,7 @@ typedef __u64 v4l2_std_id; struct v4l2_standard { - __u32 index; + __u32 index; v4l2_std_id id; __u8 name[24]; struct v4l2_fract frameperiod; /* Frames, not fields */ @@ -610,9 +610,9 @@ struct v4l2_standard struct v4l2_input { __u32 index; /* Which input */ - __u8 name[32]; /* Label */ + __u8 name[32]; /* Label */ __u32 type; /* Type of input */ - __u32 audioset; /* Associated audios (bitfield) */ + __u32 audioset; /* Associated audios (bitfield) */ __u32 tuner; /* Associated tuner */ v4l2_std_id std; __u32 status; @@ -647,9 +647,9 @@ struct v4l2_input struct v4l2_output { __u32 index; /* Which output */ - __u8 name[32]; /* Label */ + __u8 name[32]; /* Label */ __u32 type; /* Type of output */ - __u32 audioset; /* Associated audios (bitfield) */ + __u32 audioset; /* Associated audios (bitfield) */ __u32 modulator; /* Associated modulator */ v4l2_std_id std; __u32 reserved[4]; @@ -671,12 +671,12 @@ struct v4l2_control /* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */ struct v4l2_queryctrl { - __u32 id; + __u32 id; enum v4l2_ctrl_type type; __u8 name[32]; /* Whatever */ __s32 minimum; /* Note signedness */ __s32 maximum; - __s32 step; + __s32 step; __s32 default_value; __u32 flags; __u32 reserved[2]; @@ -779,10 +779,10 @@ struct v4l2_modulator struct v4l2_frequency { - __u32 tuner; + __u32 tuner; enum v4l2_tuner_type type; - __u32 frequency; - __u32 reserved[8]; + __u32 frequency; + __u32 reserved[8]; }; /* @@ -846,14 +846,14 @@ struct v4l2_vbi_format struct v4l2_sliced_vbi_format { - __u16 service_set; - /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field - service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field - (equals frame lines 313-336 for 625 line video - standards, 263-286 for 525 line standards) */ - __u16 service_lines[2][24]; - __u32 io_size; - __u32 reserved[2]; /* must be zero */ + __u16 service_set; + /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field + service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field + (equals frame lines 313-336 for 625 line video + standards, 263-286 for 525 line standards) */ + __u16 service_lines[2][24]; + __u32 io_size; + __u32 reserved[2]; /* must be zero */ }; #define V4L2_SLICED_TELETEXT_B (0x0001) @@ -866,22 +866,22 @@ struct v4l2_sliced_vbi_format struct v4l2_sliced_vbi_cap { - __u16 service_set; - /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field - service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field - (equals frame lines 313-336 for 625 line video - standards, 263-286 for 525 line standards) */ - __u16 service_lines[2][24]; - __u32 reserved[4]; /* must be 0 */ + __u16 service_set; + /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field + service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field + (equals frame lines 313-336 for 625 line video + standards, 263-286 for 525 line standards) */ + __u16 service_lines[2][24]; + __u32 reserved[4]; /* must be 0 */ }; struct v4l2_sliced_vbi_data { - __u32 id; - __u32 field; /* 0: first field, 1: second field */ - __u32 line; /* 1-23 */ - __u32 reserved; /* must be 0 */ - __u8 data[48]; + __u32 id; + __u32 field; /* 0: first field, 1: second field */ + __u32 line; /* 1-23 */ + __u32 reserved; /* must be 0 */ + __u8 data[48]; }; #endif @@ -896,9 +896,9 @@ struct v4l2_format enum v4l2_buf_type type; union { - struct v4l2_pix_format pix; // V4L2_BUF_TYPE_VIDEO_CAPTURE - struct v4l2_window win; // V4L2_BUF_TYPE_VIDEO_OVERLAY - struct v4l2_vbi_format vbi; // V4L2_BUF_TYPE_VBI_CAPTURE + struct v4l2_pix_format pix; // V4L2_BUF_TYPE_VIDEO_CAPTURE + struct v4l2_window win; // V4L2_BUF_TYPE_VIDEO_OVERLAY + struct v4l2_vbi_format vbi; // V4L2_BUF_TYPE_VBI_CAPTURE #if 1 struct v4l2_sliced_vbi_format sliced; // V4L2_BUF_TYPE_SLICED_VBI_CAPTURE #endif diff --git a/include/media/audiochip.h b/include/media/audiochip.h index dd1e484e86d3..b7d4b0930408 100644 --- a/include/media/audiochip.h +++ b/include/media/audiochip.h @@ -10,13 +10,13 @@ enum audiochip { /* Provided by video chip */ AUDIO_CHIP_INTERNAL, /* Provided by tvaudio.c */ - AUDIO_CHIP_TDA8425, - AUDIO_CHIP_TEA6300, - AUDIO_CHIP_TEA6420, - AUDIO_CHIP_TDA9840, - AUDIO_CHIP_TDA985X, - AUDIO_CHIP_TDA9874, - AUDIO_CHIP_PIC16C54, + AUDIO_CHIP_TDA8425, + AUDIO_CHIP_TEA6300, + AUDIO_CHIP_TEA6420, + AUDIO_CHIP_TDA9840, + AUDIO_CHIP_TDA985X, + AUDIO_CHIP_TDA9874, + AUDIO_CHIP_PIC16C54, /* Provided by msp3400.c */ AUDIO_CHIP_MSP34XX }; diff --git a/include/media/tuner.h b/include/media/tuner.h index 81025323267f..94a9511479a1 100644 --- a/include/media/tuner.h +++ b/include/media/tuner.h @@ -215,14 +215,14 @@ extern int tea5767_autodetection(struct i2c_client *c); #define tuner_warn(fmt, arg...) do {\ printk(KERN_WARNING "%s %d-%04x: " fmt, t->i2c.driver->name, \ - t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0) + t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0) #define tuner_info(fmt, arg...) do {\ printk(KERN_INFO "%s %d-%04x: " fmt, t->i2c.driver->name, \ - t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0) + t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0) #define tuner_dbg(fmt, arg...) do {\ if (tuner_debug) \ - printk(KERN_DEBUG "%s %d-%04x: " fmt, t->i2c.driver->name, \ - t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0) + printk(KERN_DEBUG "%s %d-%04x: " fmt, t->i2c.driver->name, \ + t->i2c.adapter->nr, t->i2c.addr , ##arg); } while (0) #endif /* __KERNEL__ */ diff --git a/include/media/video-buf.h b/include/media/video-buf.h index ae8d7a000440..ee8eb15c0ea6 100644 --- a/include/media/video-buf.h +++ b/include/media/video-buf.h @@ -177,7 +177,7 @@ struct videobuf_queue_ops { }; struct videobuf_queue { - struct semaphore lock; + struct semaphore lock; spinlock_t *irqlock; struct pci_dev *pci; -- cgit v1.2.3 From f2421ca3383ed35bc634aa29416a3229dc603fa4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:45 -0800 Subject: [PATCH] v4l: 801: whitespaces cleanups - Whitespaces Cleanups. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/video4linux/lifeview.txt | 6 +++--- drivers/media/video/bttv-cards.c | 4 ++-- drivers/media/video/bttv-risc.c | 4 ++-- drivers/media/video/cx88/cx88-core.c | 4 ++-- drivers/media/video/cx88/cx88-dvb.c | 2 +- drivers/media/video/saa7134/saa7134-alsa.c | 12 ++++++------ drivers/media/video/saa7134/saa7134-dvb.c | 4 ++-- drivers/media/video/saa7134/saa7134-input.c | 2 +- drivers/media/video/saa7134/saa7134-video.c | 4 ++-- drivers/media/video/tvaudio.c | 8 ++++---- drivers/media/video/tveeprom.c | 2 +- include/linux/videodev2.h | 10 +++++----- 12 files changed, 31 insertions(+), 31 deletions(-) (limited to 'include/linux') diff --git a/Documentation/video4linux/lifeview.txt b/Documentation/video4linux/lifeview.txt index f66320bd7b67..05f9eb57aac9 100644 --- a/Documentation/video4linux/lifeview.txt +++ b/Documentation/video4linux/lifeview.txt @@ -28,9 +28,9 @@ saa7134: /* GP17 Strap "GP7"=High */ /* GP16 Strap "GP6"=High - 0=Radio 1=TV - Drives SA630D ENCH1 and HEF4052 A1 pins - to do FM radio through SIF input */ + 0=Radio 1=TV + Drives SA630D ENCH1 and HEF4052 A1 pins + to do FM radio through SIF input */ /* GP15 nc */ /* GP14 nc */ /* GP13 nc */ diff --git a/drivers/media/video/bttv-cards.c b/drivers/media/video/bttv-cards.c index 92bb515fbe4d..695a67e9edd7 100644 --- a/drivers/media/video/bttv-cards.c +++ b/drivers/media/video/bttv-cards.c @@ -3585,7 +3585,7 @@ static void __devinit osprey_eeprom(struct bttv *btv) for(i = 0; i<14; i++) checksum += ee[i+offset]; checksum = ~checksum; /* no idea why */ if ((((checksum>>8)&0x0FF) == ee[offset+14]) && - ((checksum & 0x0FF) == ee[offset+15])) { + ((checksum & 0x0FF) == ee[offset+15])) { break; } } @@ -4420,7 +4420,7 @@ windvr_audio(struct bttv *btv, struct video_audio *v, int set) if (val) { gpio_bits(0x140000, val); if (bttv_gpio) - bttv_gpio_tracking(btv,"windvr"); + bttv_gpio_tracking(btv,"windvr"); } } else { v->mode = VIDEO_SOUND_MONO | VIDEO_SOUND_STEREO | diff --git a/drivers/media/video/bttv-risc.c b/drivers/media/video/bttv-risc.c index 3028862934dd..b40e9734bf08 100644 --- a/drivers/media/video/bttv-risc.c +++ b/drivers/media/video/bttv-risc.c @@ -88,9 +88,9 @@ bttv_risc_packed(struct bttv *btv, struct btcx_riscmem *risc, offset = 0; sg++; while (todo > sg_dma_len(sg)) { - *(rp++)=cpu_to_le32(BT848_RISC_WRITE| + *(rp++)=cpu_to_le32(BT848_RISC_WRITE| sg_dma_len(sg)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)); + *(rp++)=cpu_to_le32(sg_dma_address(sg)); todo -= sg_dma_len(sg); sg++; } diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index f01a631d0c00..eb806af17182 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -166,9 +166,9 @@ static u32* cx88_risc_field(u32 *rp, struct scatterlist *sglist, offset = 0; sg++; while (todo > sg_dma_len(sg)) { - *(rp++)=cpu_to_le32(RISC_WRITE| + *(rp++)=cpu_to_le32(RISC_WRITE| sg_dma_len(sg)); - *(rp++)=cpu_to_le32(sg_dma_address(sg)); + *(rp++)=cpu_to_le32(sg_dma_address(sg)); todo -= sg_dma_len(sg); sg++; } diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 3be601cfc99b..a7a077196fc9 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -128,7 +128,7 @@ static int dntv_live_dvbt_demod_init(struct dvb_frontend* fe) static u8 reset [] = { 0x50, 0x80 }; static u8 adc_ctl_1_cfg [] = { 0x8E, 0x40 }; static u8 agc_cfg [] = { 0x67, 0x10, 0x23, 0x00, 0xFF, 0xFF, - 0x00, 0xFF, 0x00, 0x40, 0x40 }; + 0x00, 0xFF, 0x00, 0x40, 0x40 }; static u8 dntv_extra[] = { 0xB5, 0x7A }; static u8 capt_range_cfg[] = { 0x75, 0x32 }; diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index e9ffe8f144ac..e7c3691fc500 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -277,7 +277,7 @@ static int dsp_buffer_init(struct saa7134_dev *dev) BUG(); videobuf_dma_init(&dev->oss.dma); err = videobuf_dma_init_kernel(&dev->oss.dma, PCI_DMA_FROMDEVICE, - (dev->oss.bufsize + PAGE_SIZE) >> PAGE_SHIFT); + (dev->oss.bufsize + PAGE_SIZE) >> PAGE_SHIFT); if (0 != err) return err; return 0; @@ -336,9 +336,9 @@ static int snd_card_saa7134_capture_prepare(snd_pcm_substream_t * substream) if (0 != (err = saa7134_pgtable_alloc(dev->pci,&dev->oss.pt))) goto fail1; if (0 != (err = saa7134_pgtable_build(dev->pci,&dev->oss.pt, - dev->oss.dma.sglist, - dev->oss.dma.sglen, - 0))) + dev->oss.dma.sglist, + dev->oss.dma.sglen, + 0))) goto fail2; @@ -481,8 +481,8 @@ static snd_pcm_uframes_t snd_card_saa7134_capture_pointer(snd_pcm_substream_t * static snd_pcm_hardware_t snd_card_saa7134_capture = { .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID), .formats = USE_FORMATS, .rates = USE_RATE, .rate_min = USE_RATE_MIN, diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 5aadd44c2fa2..342891d431a8 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -547,7 +547,7 @@ static int philips_tda827x_pll_set(struct dvb_frontend *fe, struct dvb_frontend_ u8 tuner_buf[14]; struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tuner_buf, - .len = sizeof(tuner_buf) }; + .len = sizeof(tuner_buf) }; int i, tuner_freq, if_freq; u32 N; switch (params->u.ofdm.bandwidth) { @@ -606,7 +606,7 @@ static void philips_tda827x_pll_sleep(struct dvb_frontend *fe) struct saa7134_dev *dev = fe->dvb->priv; static u8 tda827x_sleep[] = { 0x30, 0xd0}; struct i2c_msg tuner_msg = {.addr = 0x60,.flags = 0,.buf = tda827x_sleep, - .len = sizeof(tda827x_sleep) }; + .len = sizeof(tda827x_sleep) }; i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); } diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 7ce0459989b5..f99dbb729555 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -118,7 +118,7 @@ static IR_KEYTAB_TYPE eztv_codes[IR_KEYTAB_SIZE] = { [ 1 ] = KEY_TV, // DVR [ 21 ] = KEY_DVD, // DVD [ 23 ] = KEY_AUDIO, // music - // DVR mode / DVD mode / music mode + // DVR mode / DVD mode / music mode [ 27 ] = KEY_MUTE, // mute [ 2 ] = KEY_LANGUAGE, // MTS/SAP / audio / autoseek diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index 86db7fb96efd..caeb47c68b8b 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -1345,8 +1345,8 @@ video_poll(struct file *file, struct poll_table_struct *wait) return POLLERR; } if (0 != fh->cap.ops->buf_prepare(&fh->cap,fh->cap.read_buf,fh->cap.field)) { - up(&fh->cap.lock); - return POLLERR; + up(&fh->cap.lock); + return POLLERR; } fh->cap.ops->buf_queue(&fh->cap,fh->cap.read_buf); fh->cap.read_off = 0; diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index e1639a24f77f..75901b030730 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -1028,7 +1028,7 @@ static int tda9874a_initialize(struct CHIPSTATE *chip) #define TEA6300_TR 0x03 /* treble */ #define TEA6300_FA 0x04 /* fader control */ #define TEA6300_S 0x05 /* switch register */ - /* values for those registers: */ + /* values for those registers: */ #define TEA6300_S_SA 0x01 /* stereo A input */ #define TEA6300_S_SB 0x02 /* stereo B */ #define TEA6300_S_SC 0x04 /* stereo C */ @@ -1042,7 +1042,7 @@ static int tda9874a_initialize(struct CHIPSTATE *chip) #define TEA6320_BA 0x05 /* bass (0-4) */ #define TEA6320_TR 0x06 /* treble (0-4) */ #define TEA6320_S 0x07 /* switch register */ - /* values for those registers: */ + /* values for those registers: */ #define TEA6320_S_SA 0x07 /* stereo A input */ #define TEA6320_S_SB 0x06 /* stereo B */ #define TEA6320_S_SC 0x05 /* stereo C */ @@ -1082,7 +1082,7 @@ static int tea6320_initialize(struct CHIPSTATE * chip) #define TDA8425_BA 0x02 /* bass */ #define TDA8425_TR 0x03 /* treble */ #define TDA8425_S1 0x08 /* switch functions */ - /* values for those registers: */ + /* values for those registers: */ #define TDA8425_S1_OFF 0xEE /* audio off (mute on) */ #define TDA8425_S1_CH1 0xCE /* audio channel 1 (mute off) - "linear stereo" mode */ #define TDA8425_S1_CH2 0xCF /* audio channel 2 (mute off) - "linear stereo" mode */ @@ -1148,7 +1148,7 @@ static void tda8425_setmode(struct CHIPSTATE *chip, int mode) /* bit definition of the RESET register, I2C data. */ #define PIC16C54_MISC_RESET_REMOTE_CTL 0x01 /* bit 0, Reset to receive the key */ - /* code of remote controller */ + /* code of remote controller */ #define PIC16C54_MISC_MTS_MAIN 0x02 /* bit 1 */ #define PIC16C54_MISC_MTS_SAP 0x04 /* bit 2 */ #define PIC16C54_MISC_MTS_BOTH 0x08 /* bit 3 */ diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 68128e04dacc..d83a33618119 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -331,7 +331,7 @@ static int hasRadioTuner(int tunerType) } void tveeprom_hauppauge_analog(struct i2c_client *c, struct tveeprom *tvee, - unsigned char *eeprom_data) + unsigned char *eeprom_data) { /* ---------------------------------------------- ** The hauppauge eeprom format is tagged diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index a9a0999be702..090091560c36 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -393,7 +393,7 @@ struct v4l2_jpegcompression #define V4L2_JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ #define V4L2_JPEG_MARKER_COM (1<<6) /* Comment segment */ #define V4L2_JPEG_MARKER_APP (1<<7) /* App segment, driver will - * allways use APP0 */ + * allways use APP0 */ }; @@ -849,8 +849,8 @@ struct v4l2_sliced_vbi_format __u16 service_set; /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field - (equals frame lines 313-336 for 625 line video - standards, 263-286 for 525 line standards) */ + (equals frame lines 313-336 for 625 line video + standards, 263-286 for 525 line standards) */ __u16 service_lines[2][24]; __u32 io_size; __u32 reserved[2]; /* must be zero */ @@ -869,8 +869,8 @@ struct v4l2_sliced_vbi_cap __u16 service_set; /* service_lines[0][...] specifies lines 0-23 (1-23 used) of the first field service_lines[1][...] specifies lines 0-23 (1-23 used) of the second field - (equals frame lines 313-336 for 625 line video - standards, 263-286 for 525 line standards) */ + (equals frame lines 313-336 for 625 line video + standards, 263-286 for 525 line standards) */ __u16 service_lines[2][24]; __u32 reserved[4]; /* must be 0 */ }; -- cgit v1.2.3 From 79436633dbced18aa348f8669ef507109f851303 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:49 -0800 Subject: [PATCH] v4l: 809: some changes to allow compiling cx88 and saa7134 - Some changes to allow compiling cx88 and saa7134 without V4L1 support. - This patch will help obsoleting V4L1 API. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/cx88/cx88-video.c | 9 +++- drivers/media/video/saa7134/saa7134-video.c | 6 ++- drivers/media/video/saa7134/saa7134.h | 2 +- include/linux/videodev.h | 74 +--------------------------- include/linux/videodev2.h | 76 +++++++++++++++++++++++++++++ include/media/video-buf.h | 2 +- 6 files changed, 92 insertions(+), 77 deletions(-) (limited to 'include/linux') diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index f22ccb65de1c..cedd1d79ac13 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -34,6 +34,9 @@ #include "cx88.h" +/* Include V4L1 specific functions. Should be removed soon */ +#include + MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards"); MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); @@ -1187,7 +1190,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, struct v4l2_format *f = arg; return cx8800_try_fmt(dev,fh,f); } - +#ifdef HAVE_V4L1 /* --- streaming capture ------------------------------------- */ case VIDIOCGMBUF: { @@ -1213,6 +1216,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, } return 0; } +#endif case VIDIOC_REQBUFS: return videobuf_reqbufs(get_queue(fh), arg); @@ -1244,7 +1248,6 @@ static int video_do_ioctl(struct inode *inode, struct file *file, res_free(dev,fh,res); return 0; } - default: return cx88_do_ioctl( inode, file, fh->radio, core, cmd, arg, video_do_ioctl ); } @@ -1537,6 +1540,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, *id = 0; return 0; } +#ifdef HAVE_V4L1 case VIDIOCSTUNER: { struct video_tuner *v = arg; @@ -1547,6 +1551,7 @@ static int radio_do_ioctl(struct inode *inode, struct file *file, cx88_call_i2c_clients(core,VIDIOCSTUNER,v); return 0; } +#endif case VIDIOC_S_TUNER: { struct v4l2_tuner *t = arg; diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index caeb47c68b8b..632ebe8724ec 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -30,6 +30,9 @@ #include "saa7134-reg.h" #include "saa7134.h" +/* Include V4L1 specific functions. Should be removed soon */ +#include + /* ------------------------------------------------------------------ */ static unsigned int video_debug = 0; @@ -2060,7 +2063,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, struct v4l2_format *f = arg; return saa7134_try_fmt(dev,fh,f); } - +#ifdef HAVE_V4L1 case VIDIOCGMBUF: { struct video_mbuf *mbuf = arg; @@ -2085,6 +2088,7 @@ static int video_do_ioctl(struct inode *inode, struct file *file, } return 0; } +#endif case VIDIOC_REQBUFS: return videobuf_reqbufs(saa7134_queue(fh),arg); diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 064c2f7a8c12..cd28a6a7b972 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -24,7 +24,7 @@ #include #include -#include +#include #include #include #include diff --git a/include/linux/videodev.h b/include/linux/videodev.h index 22e6e4bad7b8..23276cede540 100644 --- a/include/linux/videodev.h +++ b/include/linux/videodev.h @@ -1,57 +1,16 @@ #ifndef __LINUX_VIDEODEV_H #define __LINUX_VIDEODEV_H -#include #include -#define HAVE_V4L2 1 +#define HAVE_V4L1 1 + #include #ifdef __KERNEL__ -#include #include -#include - -struct video_device -{ - /* device info */ - struct device *dev; - char name[32]; - int type; /* v4l1 */ - int type2; /* v4l2 */ - int hardware; - int minor; - - /* device ops + callbacks */ - struct file_operations *fops; - void (*release)(struct video_device *vfd); - - - /* obsolete -- fops->owner is used instead */ - struct module *owner; - /* dev->driver_data will be used instead some day. - * Use the video_{get|set}_drvdata() helper functions, - * so the switch over will be transparent for you. - * Or use {pci|usb}_{get|set}_drvdata() directly. */ - void *priv; - - /* for videodev.c intenal usage -- please don't touch */ - int users; /* video_exclusive_{open|close} ... */ - struct semaphore lock; /* ... helper function uses these */ - char devfs_name[64]; /* devfs */ - struct class_device class_dev; /* sysfs */ -}; - -#define VIDEO_MAJOR 81 - -#define VFL_TYPE_GRABBER 0 -#define VFL_TYPE_VBI 1 -#define VFL_TYPE_RADIO 2 -#define VFL_TYPE_VTX 3 -extern int video_register_device(struct video_device *, int type, int nr); -extern void video_unregister_device(struct video_device *); extern struct video_device* video_devdata(struct file*); #define to_video_device(cd) container_of(cd, struct video_device, class_dev) @@ -68,11 +27,6 @@ video_device_remove_file(struct video_device *vfd, class_device_remove_file(&vfd->class_dev, attr); } -/* helper functions to alloc / release struct video_device, the - later can be used for video_device->release() */ -struct video_device *video_device_alloc(void); -void video_device_release(struct video_device *vfd); - /* helper functions to access driver private data. */ static inline void *video_get_drvdata(struct video_device *dev) { @@ -86,27 +40,8 @@ static inline void video_set_drvdata(struct video_device *dev, void *data) extern int video_exclusive_open(struct inode *inode, struct file *file); extern int video_exclusive_release(struct inode *inode, struct file *file); -extern int video_usercopy(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg, - int (*func)(struct inode *inode, struct file *file, - unsigned int cmd, void *arg)); #endif /* __KERNEL__ */ -#define VID_TYPE_CAPTURE 1 /* Can capture */ -#define VID_TYPE_TUNER 2 /* Can tune */ -#define VID_TYPE_TELETEXT 4 /* Does teletext */ -#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */ -#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */ -#define VID_TYPE_CLIPPING 32 /* Can clip */ -#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */ -#define VID_TYPE_SCALES 128 /* Scalable */ -#define VID_TYPE_MONOCHROME 256 /* Monochrome only */ -#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */ -#define VID_TYPE_MPEG_DECODER 1024 /* Can decode MPEG streams */ -#define VID_TYPE_MPEG_ENCODER 2048 /* Can encode MPEG streams */ -#define VID_TYPE_MJPEG_DECODER 4096 /* Can decode MJPEG streams */ -#define VID_TYPE_MJPEG_ENCODER 8192 /* Can encode MJPEG streams */ - struct video_capability { char name[32]; @@ -260,9 +195,6 @@ struct video_key __u32 flags; }; - -#define VIDEO_MAX_FRAME 32 - struct video_mbuf { int size; /* Total memory to map */ @@ -270,10 +202,8 @@ struct video_mbuf int offsets[VIDEO_MAX_FRAME]; }; - #define VIDEO_NO_UNIT (-1) - struct video_unit { int video; /* Video minor */ diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 090091560c36..df0f9a24944a 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -18,6 +18,82 @@ #endif #include /* need __user */ +#include +#include + +#define HAVE_V4L2 1 + +/* + * Common stuff for both V4L1 and V4L2 + * Moved from videodev.h + */ + +#define VIDEO_MAX_FRAME 32 + +#define VFL_TYPE_GRABBER 0 +#define VFL_TYPE_VBI 1 +#define VFL_TYPE_RADIO 2 +#define VFL_TYPE_VTX 3 + +struct video_device +{ + /* device info */ + struct device *dev; + char name[32]; + int type; /* v4l1 */ + int type2; /* v4l2 */ + int hardware; + int minor; + + /* device ops + callbacks */ + struct file_operations *fops; + void (*release)(struct video_device *vfd); + + + /* obsolete -- fops->owner is used instead */ + struct module *owner; + /* dev->driver_data will be used instead some day. + * Use the video_{get|set}_drvdata() helper functions, + * so the switch over will be transparent for you. + * Or use {pci|usb}_{get|set}_drvdata() directly. */ + void *priv; + + /* for videodev.c intenal usage -- please don't touch */ + int users; /* video_exclusive_{open|close} ... */ + struct semaphore lock; /* ... helper function uses these */ + char devfs_name[64]; /* devfs */ + struct class_device class_dev; /* sysfs */ +}; + +#define VIDEO_MAJOR 81 + +#define VID_TYPE_CAPTURE 1 /* Can capture */ +#define VID_TYPE_TUNER 2 /* Can tune */ +#define VID_TYPE_TELETEXT 4 /* Does teletext */ +#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */ +#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */ +#define VID_TYPE_CLIPPING 32 /* Can clip */ +#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */ +#define VID_TYPE_SCALES 128 /* Scalable */ +#define VID_TYPE_MONOCHROME 256 /* Monochrome only */ +#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */ +#define VID_TYPE_MPEG_DECODER 1024 /* Can decode MPEG streams */ +#define VID_TYPE_MPEG_ENCODER 2048 /* Can encode MPEG streams */ +#define VID_TYPE_MJPEG_DECODER 4096 /* Can decode MJPEG streams */ +#define VID_TYPE_MJPEG_ENCODER 8192 /* Can encode MJPEG streams */ + +extern int video_register_device(struct video_device *, int type, int nr); +extern void video_unregister_device(struct video_device *); +extern int video_usercopy(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg, + int (*func)(struct inode *inode, struct file *file, + unsigned int cmd, void *arg)); + +/* helper functions to alloc / release struct video_device, the + later can be used for video_device->release() */ +struct video_device *video_device_alloc(void); +void video_device_release(struct video_device *vfd); + /* * M I S C E L L A N E O U S */ diff --git a/include/media/video-buf.h b/include/media/video-buf.h index ee8eb15c0ea6..8ecfd78e0027 100644 --- a/include/media/video-buf.h +++ b/include/media/video-buf.h @@ -17,7 +17,7 @@ * (at your option) any later version. */ -#include +#include #define UNSET (-1U) -- cgit v1.2.3 From 1a9ca74d22065355d61bb6395590378040e7366d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:37:54 -0800 Subject: [PATCH] v4l: 815: commented obsoleted stuff at videodev headers - Commented obsoleted stuff at videodev headers. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-video.c | 1 - include/linux/videodev.h | 10 ---------- include/linux/videodev2.h | 7 ------- 3 files changed, 18 deletions(-) (limited to 'include/linux') diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 16a6d2da7391..06644e230b47 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1671,7 +1671,6 @@ static int em2820_init_dev(struct em2820 **devhandle, struct usb_device *udev, return -ENOMEM; } - dev->vdev->owner = THIS_MODULE; dev->vdev->type = VID_TYPE_CAPTURE; if (dev->has_tuner) dev->vdev->type |= VID_TYPE_TUNER; diff --git a/include/linux/videodev.h b/include/linux/videodev.h index 23276cede540..392592a040c5 100644 --- a/include/linux/videodev.h +++ b/include/linux/videodev.h @@ -27,16 +27,6 @@ video_device_remove_file(struct video_device *vfd, class_device_remove_file(&vfd->class_dev, attr); } -/* helper functions to access driver private data. */ -static inline void *video_get_drvdata(struct video_device *dev) -{ - return dev->priv; -} - -static inline void video_set_drvdata(struct video_device *dev, void *data) -{ - dev->priv = data; -} extern int video_exclusive_open(struct inode *inode, struct file *file); extern int video_exclusive_release(struct inode *inode, struct file *file); diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index df0f9a24944a..65829a510aca 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -50,13 +50,6 @@ struct video_device void (*release)(struct video_device *vfd); - /* obsolete -- fops->owner is used instead */ - struct module *owner; - /* dev->driver_data will be used instead some day. - * Use the video_{get|set}_drvdata() helper functions, - * so the switch over will be transparent for you. - * Or use {pci|usb}_{get|set}_drvdata() directly. */ - void *priv; /* for videodev.c intenal usage -- please don't touch */ int users; /* video_exclusive_{open|close} ... */ -- cgit v1.2.3 From f958b68d40b870f5a0d1582f094bc93a53af7cd7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:01 -0800 Subject: [PATCH] v4l: 829: fixed user mode compiling - Fixed user mode compiling. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/videodev.h | 12 ++++++++++++ include/linux/videodev2.h | 18 ++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/videodev.h b/include/linux/videodev.h index 392592a040c5..91140091ced2 100644 --- a/include/linux/videodev.h +++ b/include/linux/videodev.h @@ -27,6 +27,18 @@ video_device_remove_file(struct video_device *vfd, class_device_remove_file(&vfd->class_dev, attr); } +#if OBSOLETE_OWNER /* to be removed in 2.6.15 */ +/* helper functions to access driver private data. */ +static inline void *video_get_drvdata(struct video_device *dev) +{ + return dev->priv; +} + +static inline void video_set_drvdata(struct video_device *dev, void *data) +{ + dev->priv = data; +} +#endif extern int video_exclusive_open(struct inode *inode, struct file *file); extern int video_exclusive_release(struct inode *inode, struct file *file); diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 65829a510aca..cbe15edbe668 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -15,12 +15,13 @@ */ #ifdef __KERNEL__ #include /* need struct timeval */ +#include +#include #endif #include /* need __user */ -#include -#include +#define OBSOLETE_OWNER 1 /* It will be removed for 2.6.15 */ #define HAVE_V4L2 1 /* @@ -30,6 +31,8 @@ #define VIDEO_MAX_FRAME 32 +#ifdef __KERNEL__ + #define VFL_TYPE_GRABBER 0 #define VFL_TYPE_VBI 1 #define VFL_TYPE_RADIO 2 @@ -50,6 +53,15 @@ struct video_device void (*release)(struct video_device *vfd); +#if OBSOLETE_OWNER /* to be removed in 2.6.15 */ + /* obsolete -- fops->owner is used instead */ + struct module *owner; + /* dev->driver_data will be used instead some day. + * Use the video_{get|set}_drvdata() helper functions, + * so the switch over will be transparent for you. + * Or use {pci|usb}_{get|set}_drvdata() directly. */ + void *priv; +#endif /* for videodev.c intenal usage -- please don't touch */ int users; /* video_exclusive_{open|close} ... */ @@ -87,6 +99,8 @@ extern int video_usercopy(struct inode *inode, struct file *file, struct video_device *video_device_alloc(void); void video_device_release(struct video_device *vfd); +#endif + /* * M I S C E L L A N E O U S */ -- cgit v1.2.3 From c12097fd9adb07810fb28f70df5462c0603463cc Mon Sep 17 00:00:00 2001 From: Michael Schimek Date: Tue, 8 Nov 2005 21:38:24 -0800 Subject: [PATCH] v4l: 876: moved some user defines to be out of kernel define - Moved some user defines to be out of __KERNEL__ define. Signed-off-by: Michael Schimek Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/videodev2.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'include/linux') diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index cbe15edbe668..e8a0d22df54f 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -31,6 +31,21 @@ #define VIDEO_MAX_FRAME 32 +#define VID_TYPE_CAPTURE 1 /* Can capture */ +#define VID_TYPE_TUNER 2 /* Can tune */ +#define VID_TYPE_TELETEXT 4 /* Does teletext */ +#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */ +#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */ +#define VID_TYPE_CLIPPING 32 /* Can clip */ +#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */ +#define VID_TYPE_SCALES 128 /* Scalable */ +#define VID_TYPE_MONOCHROME 256 /* Monochrome only */ +#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */ +#define VID_TYPE_MPEG_DECODER 1024 /* Can decode MPEG streams */ +#define VID_TYPE_MPEG_ENCODER 2048 /* Can encode MPEG streams */ +#define VID_TYPE_MJPEG_DECODER 4096 /* Can decode MJPEG streams */ +#define VID_TYPE_MJPEG_ENCODER 8192 /* Can encode MJPEG streams */ + #ifdef __KERNEL__ #define VFL_TYPE_GRABBER 0 @@ -72,21 +87,6 @@ struct video_device #define VIDEO_MAJOR 81 -#define VID_TYPE_CAPTURE 1 /* Can capture */ -#define VID_TYPE_TUNER 2 /* Can tune */ -#define VID_TYPE_TELETEXT 4 /* Does teletext */ -#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */ -#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */ -#define VID_TYPE_CLIPPING 32 /* Can clip */ -#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */ -#define VID_TYPE_SCALES 128 /* Scalable */ -#define VID_TYPE_MONOCHROME 256 /* Monochrome only */ -#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */ -#define VID_TYPE_MPEG_DECODER 1024 /* Can decode MPEG streams */ -#define VID_TYPE_MPEG_ENCODER 2048 /* Can encode MPEG streams */ -#define VID_TYPE_MJPEG_DECODER 4096 /* Can decode MJPEG streams */ -#define VID_TYPE_MJPEG_ENCODER 8192 /* Can encode MJPEG streams */ - extern int video_register_device(struct video_device *, int type, int nr); extern void video_unregister_device(struct video_device *); extern int video_usercopy(struct inode *inode, struct file *file, -- cgit v1.2.3 From e0ec29b7e5aa1f4f1ff73ebd3003336dbe83e174 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 8 Nov 2005 21:38:26 -0800 Subject: [PATCH] v4l: 885: second round of i2c ids redefinition cleanup - Second round of i2c IDs redefinition cleanup. Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/bt832.c | 1 - drivers/media/video/msp3400.c | 1 - drivers/media/video/saa6588.c | 1 - drivers/media/video/saa7134/saa6752hs.c | 1 - drivers/media/video/saa7134/saa7134.h | 1 - drivers/media/video/tda7432.c | 1 - drivers/media/video/tda9875.c | 1 - drivers/media/video/tda9887.c | 1 - drivers/media/video/tvaudio.c | 3 +-- drivers/media/video/tveeprom.c | 4 ---- include/linux/i2c-id.h | 11 +++++++---- 11 files changed, 8 insertions(+), 18 deletions(-) (limited to 'include/linux') diff --git a/drivers/media/video/bt832.c b/drivers/media/video/bt832.c index 3e42493a4e0a..e4063950ae57 100644 --- a/drivers/media/video/bt832.c +++ b/drivers/media/video/bt832.c @@ -32,7 +32,6 @@ #include #include -#include #include "bttv.h" #include "bt832.h" diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index ba2c95842fba..d603229c9f2f 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -54,7 +54,6 @@ #include #include -#include #include "msp3400.h" #define OPMODE_AUTO -1 diff --git a/drivers/media/video/saa6588.c b/drivers/media/video/saa6588.c index 5252a4ca3fd1..23ea548a71e0 100644 --- a/drivers/media/video/saa6588.c +++ b/drivers/media/video/saa6588.c @@ -31,7 +31,6 @@ #include #include -#include #include "rds.h" diff --git a/drivers/media/video/saa7134/saa6752hs.c b/drivers/media/video/saa7134/saa6752hs.c index 2bf5cf79eec1..cdd1ed9c8065 100644 --- a/drivers/media/video/saa7134/saa6752hs.c +++ b/drivers/media/video/saa7134/saa6752hs.c @@ -13,7 +13,6 @@ #include #include -#include #define MPEG_VIDEO_TARGET_BITRATE_MAX 27000 #define MPEG_VIDEO_MAX_BITRATE_MAX 27000 diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 1365f1f32fee..4273ded9d174 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -34,7 +34,6 @@ #include #include -#include #include #include #include diff --git a/drivers/media/video/tda7432.c b/drivers/media/video/tda7432.c index 14cf1d357c3b..d32737dd2142 100644 --- a/drivers/media/video/tda7432.c +++ b/drivers/media/video/tda7432.c @@ -50,7 +50,6 @@ #include "bttv.h" #include -#include #ifndef VIDEO_AUDIO_BALANCE # define VIDEO_AUDIO_BALANCE 32 diff --git a/drivers/media/video/tda9875.c b/drivers/media/video/tda9875.c index 5a9faefc3640..a5e37dc91f39 100644 --- a/drivers/media/video/tda9875.c +++ b/drivers/media/video/tda9875.c @@ -32,7 +32,6 @@ #include "bttv.h" #include -#include static int debug; /* insmod parameter */ module_param(debug, int, S_IRUGO | S_IWUSR); diff --git a/drivers/media/video/tda9887.c b/drivers/media/video/tda9887.c index 9d6b6f57abcd..4249127c0a1d 100644 --- a/drivers/media/video/tda9887.c +++ b/drivers/media/video/tda9887.c @@ -11,7 +11,6 @@ #include #include -#include /* Chips: TDA9885 (PAL, NTSC) diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 75901b030730..c31bf28b73fe 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -31,7 +31,6 @@ #include #include -#include #include "tvaudio.h" @@ -1438,7 +1437,7 @@ static struct CHIPDESC chiplist[] = { }, { .name = "pic16c54 (PV951)", - .id = I2C_DRIVERID_PIC16C54_PV951, + .id = I2C_DRIVERID_PIC16C54_PV9, .insmodopt = &pic16c54, .addr_lo = I2C_PIC16C54 >> 1, .addr_hi = I2C_PIC16C54>> 1, diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index d83a33618119..72e8741e8b59 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -658,10 +658,6 @@ EXPORT_SYMBOL(tveeprom_read); /* run, just call the exported tveeprom_* directly, there is no point in */ /* using the indirect way via i2c_driver->command() */ -#ifndef I2C_DRIVERID_TVEEPROM -# define I2C_DRIVERID_TVEEPROM I2C_DRIVERID_EXP2 -#endif - static unsigned short normal_i2c[] = { 0xa0 >> 1, I2C_CLIENT_END, diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index 1ce4b54caa21..815675f1e349 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h @@ -27,10 +27,10 @@ * ---- Driver types ----------------------------------------------------- * device id name + number function description, i2c address(es) * - * Range 1000-1999 range is defined in sensors/sensors.h - * Range 0x100 - 0x1ff is for V4L2 Common Components + * Range 1000-1999 range is defined in sensors/sensors.h + * Range 0x100 - 0x1ff is for V4L2 Common Components * Range 0xf000 - 0xffff is reserved for local experimentation, and should - * never be used in official drivers + * never be used in official drivers */ #define I2C_DRIVERID_MSP3400 1 @@ -99,6 +99,9 @@ #define I2C_DRIVERID_MAX6900 63 /* MAX6900 real-time clock */ #define I2C_DRIVERID_SAA7114H 64 /* video decoder */ #define I2C_DRIVERID_DS1374 65 /* DS1374 real time clock */ +#define I2C_DRIVERID_TDA9874 66 /* TV sound decoder */ +#define I2C_DRIVERID_SAA6752HS 67 /* MPEG2 encoder */ +#define I2C_DRIVERID_TVEEPROM 68 /* TV EEPROM */ #define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */ @@ -111,7 +114,7 @@ #define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */ #define I2C_DRIVERID_ALERT 903 /* SMBus Alert Responder Client */ -/* IDs -- Use DRIVERIDs 1000-1999 for sensors. +/* IDs -- Use DRIVERIDs 1000-1999 for sensors. These were originally in sensors.h in the lm_sensors package */ #define I2C_DRIVERID_LM78 1002 #define I2C_DRIVERID_LM75 1003 -- cgit v1.2.3 From c3b3924ea0843d6956e5f87c3a4be09f460fe923 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:29 -0800 Subject: [PATCH] v4l: 887: i2c id h updated to reflect the newer drivers - I2c-id.h Updated to reflect the newer drivers. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/i2c-id.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h index 815675f1e349..74abaecdb572 100644 --- a/include/linux/i2c-id.h +++ b/include/linux/i2c-id.h @@ -102,7 +102,11 @@ #define I2C_DRIVERID_TDA9874 66 /* TV sound decoder */ #define I2C_DRIVERID_SAA6752HS 67 /* MPEG2 encoder */ #define I2C_DRIVERID_TVEEPROM 68 /* TV EEPROM */ - +#define I2C_DRIVERID_WM8775 69 /* wm8775 audio processor */ +#define I2C_DRIVERID_CS53L32A 70 /* cs53l32a audio processor */ +#define I2C_DRIVERID_CX25840 71 /* cx2584x video encoder */ +#define I2C_DRIVERID_SAA7127 72 /* saa7124 video encoder */ +#define I2C_DRIVERID_SAA711X 73 /* saa711x video encoders */ #define I2C_DRIVERID_EXP0 0xF0 /* experimental use id's */ #define I2C_DRIVERID_EXP1 0xF1 @@ -193,6 +197,7 @@ #define I2C_HW_B_NVIDIA 0x01001c /* nvidia framebuffer driver */ #define I2C_HW_B_SAVAGE 0x01001d /* savage framebuffer driver */ #define I2C_HW_B_RADEON 0x01001e /* radeon framebuffer driver */ +#define I2C_HW_B_EM28XX 0x01001f /* em28xx video capture cards */ /* --- PCF 8584 based algorithms */ #define I2C_HW_P_LP 0x020000 /* Parallel port interface */ -- cgit v1.2.3 From eac94356c8f9f7d3854ed0290a406b13bfe8df4c Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 8 Nov 2005 21:38:43 -0800 Subject: [PATCH] V4L: 907: em28xx cleanups and fixes - Em28xx cleanups and fixes. - Some cleanups and audio amux adjust. - em28xx will allways try, by default, the biggest size alt. - Fixes audio mux code. - Fixes some logs. - Adds support for digital output for WinTV USB2 board. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/em28xx/em28xx-cards.c | 15 ++-- drivers/media/video/em28xx/em28xx-core.c | 17 +--- drivers/media/video/em28xx/em28xx-video.c | 107 +++++++++++----------- drivers/media/video/msp3400.c | 142 +++++++++++++++++++++++++++--- include/linux/videodev2.h | 1 + 5 files changed, 201 insertions(+), 81 deletions(-) (limited to 'include/linux') diff --git a/drivers/media/video/em28xx/em28xx-cards.c b/drivers/media/video/em28xx/em28xx-cards.c index 49107fd0c0d3..57779e63f35d 100644 --- a/drivers/media/video/em28xx/em28xx-cards.c +++ b/drivers/media/video/em28xx/em28xx-cards.c @@ -128,7 +128,7 @@ struct em28xx_board em28xx_boards[] = { .input = {{ .type = EM28XX_VMUX_TELEVISION, .vmux = 0, - .amux = 0, + .amux = 6, },{ .type = EM28XX_VMUX_SVIDEO, .vmux = 2, @@ -261,9 +261,11 @@ void em28xx_card_setup(struct em28xx *dev) /* request some modules */ if (dev->model == EM2820_BOARD_HAUPPAUGE_WINTV_USB_2) { struct tveeprom tv; + struct v4l2_audioout ao; #ifdef CONFIG_MODULES request_module("tveeprom"); request_module("ir-kbd-i2c"); + request_module("msp3400"); #endif /* Call first TVeeprom */ @@ -273,10 +275,13 @@ void em28xx_card_setup(struct em28xx *dev) dev->tuner_type= tv.tuner_type; if (tv.audio_processor == AUDIO_CHIP_MSP34XX) { dev->has_msp34xx=1; - } else dev->has_msp34xx=0; - em28xx_write_regs_req(dev,0x06,0x00,"\x40",1);// Serial Bus Frequency Select Register - em28xx_write_regs_req(dev,0x0f,0x00,"\x87",1);// XCLK Frequency Select Register - em28xx_write_regs_req(dev,0x88,0x0d,"\xd0",1); + memset (&ao,0,sizeof(ao)); + + ao.index=2; + ao.mode=V4L2_AUDMODE_32BITS; + em28xx_i2c_call_clients(dev, VIDIOC_S_AUDOUT, &ao); + } else + dev->has_msp34xx=0; } } diff --git a/drivers/media/video/em28xx/em28xx-core.c b/drivers/media/video/em28xx/em28xx-core.c index 045547e17656..5cc850666fd7 100644 --- a/drivers/media/video/em28xx/em28xx-core.c +++ b/drivers/media/video/em28xx/em28xx-core.c @@ -797,20 +797,9 @@ int em28xx_set_alternate(struct em28xx *dev) dev->alt = alt; if (dev->alt == 0) { int i; - if(dev->is_em2800){ /* always use the max packet size for em2800 based devices */ - for(i=0;i< EM28XX_MAX_ALT; i++) - if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->alt]) - dev->alt=i; - }else{ - unsigned int min_pkt_size = dev->field_size / 137; /* FIXME: empiric magic number */ - em28xx_coredbg("minimum isoc packet size: %u", min_pkt_size); - dev->alt = 7; - for (i = 1; i < EM28XX_MAX_ALT; i += 2) /* FIXME: skip even alternate: why do they not work? */ - if (dev->alt_max_pkt_size[i] >= min_pkt_size) { - dev->alt = i; - break; - } - } + for(i=0;i< EM28XX_MAX_ALT; i++) + if(dev->alt_max_pkt_size[i]>dev->alt_max_pkt_size[dev->alt]) + dev->alt=i; } if (dev->alt != prev_alt) { diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index 54f21242ccbf..0bbfce03172d 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -277,6 +277,35 @@ static void em28xx_empty_framequeues(struct em28xx *dev) } } +static void video_mux(struct em28xx *dev, int index) +{ + int input, ainput; + + input = INPUT(index)->vmux; + dev->ctl_input = index; + dev->ctl_ainput = INPUT(index)->amux; + + em28xx_i2c_call_clients(dev, DECODER_SET_INPUT, &input); + + + em28xx_videodbg("Setting input index=%d, vmux=%d, amux=%d\n",index,input,dev->ctl_ainput); + + if (dev->has_msp34xx) { + em28xx_i2c_call_clients(dev, VIDIOC_S_AUDIO, &dev->ctl_ainput); + ainput = EM28XX_AUDIO_SRC_TUNER; + em28xx_audio_source(dev, ainput); + } else { + switch (dev->ctl_ainput) { + case 0: + ainput = EM28XX_AUDIO_SRC_TUNER; + break; + default: + ainput = EM28XX_AUDIO_SRC_LINE; + } + em28xx_audio_source(dev, ainput); + } +} + /* * em28xx_v4l2_open() * inits the device and starts isoc transfer @@ -298,7 +327,7 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) filp->private_data=dev; - em28xx_videodbg("users=%d", dev->users); + em28xx_videodbg("users=%d\n", dev->users); if (!down_read_trylock(&em28xx_disconnect)) return -ERESTARTSYS; @@ -352,6 +381,8 @@ static int em28xx_v4l2_open(struct inode *inode, struct file *filp) dev->state |= DEV_INITIALIZED; + video_mux(dev, 0); + err: up(&dev->lock); up_read(&em28xx_disconnect); @@ -386,7 +417,7 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp) int errCode; struct em28xx *dev=filp->private_data; - em28xx_videodbg("users=%d", dev->users); + em28xx_videodbg("users=%d\n", dev->users); down(&dev->lock); @@ -404,7 +435,7 @@ static int em28xx_v4l2_close(struct inode *inode, struct file *filp) /* set alternate 0 */ dev->alt = 0; - em28xx_videodbg("setting alternate 0"); + em28xx_videodbg("setting alternate 0\n"); errCode = usb_set_interface(dev->udev, 0, 0); if (errCode < 0) { em28xx_errdev ("cannot change alternate number to 0 (error=%i)\n", @@ -434,20 +465,20 @@ em28xx_v4l2_read(struct file *filp, char __user * buf, size_t count, return -ERESTARTSYS; if (dev->state & DEV_DISCONNECTED) { - em28xx_videodbg("device not present"); + em28xx_videodbg("device not present\n"); up(&dev->fileop_lock); return -ENODEV; } if (dev->state & DEV_MISCONFIGURED) { - em28xx_videodbg("device misconfigured; close and open it again"); + em28xx_videodbg("device misconfigured; close and open it again\n"); up(&dev->fileop_lock); return -EIO; } if (dev->io == IO_MMAP) { em28xx_videodbg ("IO method is set to mmap; close and open" - " the device again to choose the read method"); + " the device again to choose the read method\n"); up(&dev->fileop_lock); return -EINVAL; } @@ -524,9 +555,9 @@ static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table * wait) return POLLERR; if (dev->state & DEV_DISCONNECTED) { - em28xx_videodbg("device not present"); + em28xx_videodbg("device not present\n"); } else if (dev->state & DEV_MISCONFIGURED) { - em28xx_videodbg("device is misconfigured; close and open it again"); + em28xx_videodbg("device is misconfigured; close and open it again\n"); } else { if (dev->io == IO_NONE) { if (!em28xx_request_buffers @@ -595,14 +626,14 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) return -ERESTARTSYS; if (dev->state & DEV_DISCONNECTED) { - em28xx_videodbg("mmap: device not present"); + em28xx_videodbg("mmap: device not present\n"); up(&dev->fileop_lock); return -ENODEV; } if (dev->state & DEV_MISCONFIGURED) { em28xx_videodbg ("mmap: Device is misconfigured; close and " - "open it again"); + "open it again\n"); up(&dev->fileop_lock); return -EIO; } @@ -618,7 +649,7 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) break; } if (i == dev->num_frames) { - em28xx_videodbg("mmap: user supplied mapping address is out of range"); + em28xx_videodbg("mmap: user supplied mapping address is out of range\n"); up(&dev->fileop_lock); return -EINVAL; } @@ -632,7 +663,7 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma) page = vmalloc_to_pfn((void *)pos); if (remap_pfn_range(vma, start, page, PAGE_SIZE, vma->vm_page_prot)) { - em28xx_videodbg("mmap: rename page map failed"); + em28xx_videodbg("mmap: rename page map failed\n"); up(&dev->fileop_lock); return -EAGAIN; } @@ -749,7 +780,7 @@ static int em28xx_stream_interrupt(struct em28xx *dev) else if (ret) { dev->state |= DEV_MISCONFIGURED; em28xx_videodbg("device is misconfigured; close and " - "open /dev/video%d again", dev->vdev->minor); + "open /dev/video%d again\n", dev->vdev->minor); return ret; } @@ -800,28 +831,6 @@ static int em28xx_set_norm(struct em28xx *dev, int width, int height) return 0; } -static void video_mux(struct em28xx *dev, int index) -{ - int input, ainput; - - input = INPUT(index)->vmux; - dev->ctl_input = index; - - em28xx_i2c_call_clients(dev, DECODER_SET_INPUT, &input); - - dev->ctl_ainput = INPUT(index)->amux; - - switch (dev->ctl_ainput) { - case 0: - ainput = EM28XX_AUDIO_SRC_TUNER; - break; - default: - ainput = EM28XX_AUDIO_SRC_LINE; - } - - em28xx_audio_source(dev, ainput); -} - /* * em28xx_v4l2_do_ioctl() * This function is _not_ called directly, but from @@ -1062,7 +1071,7 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, t->signal = (status & DECODER_STATUS_GOOD) != 0 ? 0xffff : 0; - em28xx_videodbg("VIDIO_G_TUNER: signal=%x, afc=%x", t->signal, + em28xx_videodbg("VIDIO_G_TUNER: signal=%x, afc=%x\n", t->signal, t->afc); return 0; } @@ -1146,7 +1155,7 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, dev->stream = STREAM_ON; /* FIXME: Start video capture here? */ - em28xx_videodbg("VIDIOC_STREAMON: starting stream"); + em28xx_videodbg("VIDIOC_STREAMON: starting stream\n"); return 0; } @@ -1160,7 +1169,7 @@ static int em28xx_do_ioctl(struct inode *inode, struct file *filp, return -EINVAL; if (dev->stream == STREAM_ON) { - em28xx_videodbg ("VIDIOC_STREAMOFF: interrupting stream"); + em28xx_videodbg ("VIDIOC_STREAMOFF: interrupting stream\n"); if ((ret = em28xx_stream_interrupt(dev))) return ret; } @@ -1234,7 +1243,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, { struct v4l2_format *format = arg; - em28xx_videodbg("VIDIOC_G_FMT: type=%s", + em28xx_videodbg("VIDIOC_G_FMT: type=%s\n", format->type == V4L2_BUF_TYPE_VIDEO_CAPTURE ? "V4L2_BUF_TYPE_VIDEO_CAPTURE" : format->type == @@ -1253,7 +1262,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; format->fmt.pix.field = dev->interlaced ? V4L2_FIELD_INTERLACED : V4L2_FIELD_TOP; /* FIXME: TOP? NONE? BOTTOM? ALTENATE? */ - em28xx_videodbg("VIDIOC_G_FMT: %dx%d", dev->width, + em28xx_videodbg("VIDIOC_G_FMT: %dx%d\n", dev->width, dev->height); return 0; } @@ -1274,7 +1283,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, /* int both_fields; */ - em28xx_videodbg("%s: type=%s", + em28xx_videodbg("%s: type=%s\n", cmd == VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" : "VIDIOC_S_FMT", @@ -1288,7 +1297,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) return -EINVAL; - em28xx_videodbg("%s: requested %dx%d", + em28xx_videodbg("%s: requested %dx%d\n", cmd == VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" : "VIDIOC_S_FMT", format->fmt.pix.width, @@ -1347,7 +1356,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, format->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M; format->fmt.pix.field = V4L2_FIELD_INTERLACED; - em28xx_videodbg("%s: returned %dx%d (%d, %d)", + em28xx_videodbg("%s: returned %dx%d (%d, %d)\n", cmd == VIDIOC_TRY_FMT ? "VIDIOC_TRY_FMT" : "VIDIOC_S_FMT", format->fmt.pix.width, @@ -1359,13 +1368,13 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, for (i = 0; i < dev->num_frames; i++) if (dev->frame[i].vma_use_count) { em28xx_videodbg("VIDIOC_S_FMT failed. " - "Unmap the buffers first."); + "Unmap the buffers first.\n"); return -EINVAL; } /* stop io in case it is already in progress */ if (dev->stream == STREAM_ON) { - em28xx_videodbg("VIDIOC_SET_FMT: interupting stream"); + em28xx_videodbg("VIDIOC_SET_FMT: interupting stream\n"); if ((ret = em28xx_stream_interrupt(dev))) return ret; } @@ -1405,18 +1414,18 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, if (dev->io == IO_READ) { em28xx_videodbg ("method is set to read;" " close and open the device again to" - " choose the mmap I/O method"); + " choose the mmap I/O method\n"); return -EINVAL; } for (i = 0; i < dev->num_frames; i++) if (dev->frame[i].vma_use_count) { - em28xx_videodbg ("VIDIOC_REQBUFS failed; previous buffers are still mapped"); + em28xx_videodbg ("VIDIOC_REQBUFS failed; previous buffers are still mapped\n"); return -EINVAL; } if (dev->stream == STREAM_ON) { - em28xx_videodbg("VIDIOC_REQBUFS: interrupting stream"); + em28xx_videodbg("VIDIOC_REQBUFS: interrupting stream\n"); if ((ret = em28xx_stream_interrupt(dev))) return ret; } @@ -1430,7 +1439,7 @@ static int em28xx_video_do_ioctl(struct inode *inode, struct file *filp, dev->frame_current = NULL; - em28xx_videodbg ("VIDIOC_REQBUFS: setting io method to mmap: num bufs %i", + em28xx_videodbg ("VIDIOC_REQBUFS: setting io method to mmap: num bufs %i\n", rb->count); dev->io = rb->count ? IO_MMAP : IO_NONE; return 0; diff --git a/drivers/media/video/msp3400.c b/drivers/media/video/msp3400.c index d603229c9f2f..b599f0554fb7 100644 --- a/drivers/media/video/msp3400.c +++ b/drivers/media/video/msp3400.c @@ -90,6 +90,8 @@ struct msp3400c { int stereo; int nicam_on; int acb; + int in_scart; + int i2s_mode; int main, second; /* sound carrier */ int input; int source; /* see msp34xxg_set_source */ @@ -364,12 +366,40 @@ static struct CARRIER_DETECT carrier_detect_65[] = { #define CARRIER_COUNT(x) (sizeof(x)/sizeof(struct CARRIER_DETECT)) -/* ----------------------------------------------------------------------- */ +/* ----------------------------------------------------------------------- * + * bits 9 8 5 - SCART DSP input Select: + * 0 0 0 - SCART 1 to DSP input (reset position) + * 0 1 0 - MONO to DSP input + * 1 0 0 - SCART 2 to DSP input + * 1 1 1 - Mute DSP input + * + * bits 11 10 6 - SCART 1 Output Select: + * 0 0 0 - undefined (reset position) + * 0 1 0 - SCART 2 Input to SCART 1 Output (for devices with 2 SCARTS) + * 1 0 0 - MONO input to SCART 1 Output + * 1 1 0 - SCART 1 DA to SCART 1 Output + * 0 0 1 - SCART 2 DA to SCART 1 Output + * 0 1 1 - SCART 1 Input to SCART 1 Output + * 1 1 1 - Mute SCART 1 Output + * + * bits 13 12 7 - SCART 2 Output Select (for devices with 2 Output SCART): + * 0 0 0 - SCART 1 DA to SCART 2 Output (reset position) + * 0 1 0 - SCART 1 Input to SCART 2 Output + * 1 0 0 - MONO input to SCART 2 Output + * 0 0 1 - SCART 2 DA to SCART 2 Output + * 0 1 1 - SCART 2 Input to SCART 2 Output + * 1 1 0 - Mute SCART 2 Output + * + * Bits 4 to 0 should be zero. + * ----------------------------------------------------------------------- */ static int scarts[3][9] = { /* MASK IN1 IN2 IN1_DA IN2_DA IN3 IN4 MONO MUTE */ + /* SCART DSP Input select */ { 0x0320, 0x0000, 0x0200, -1, -1, 0x0300, 0x0020, 0x0100, 0x0320 }, + /* SCART1 Output select */ { 0x0c40, 0x0440, 0x0400, 0x0c00, 0x0040, 0x0000, 0x0840, 0x0800, 0x0c40 }, + /* SCART2 Output select */ { 0x3080, 0x1000, 0x1080, 0x0000, 0x0080, 0x2080, 0x3080, 0x2000, 0x3000 }, }; @@ -381,13 +411,23 @@ static void msp3400c_set_scart(struct i2c_client *client, int in, int out) { struct msp3400c *msp = i2c_get_clientdata(client); - if (-1 == scarts[out][in]) - return; + msp->in_scart=in; + + if (in<=2) { + if (-1 == scarts[out][in]) + return; + + msp->acb &= ~scarts[out][SCART_MASK]; + msp->acb |= scarts[out][in]; + } else + msp->acb = 0xf60; /* Mute Input and SCART 1 Output */ + + dprintk("msp34xx: scart switch: %s => %d (ACB=0x%04x)\n", + scart_names[in], out, msp->acb); + msp3400c_write(client,I2C_MSP3400C_DFP, 0x13, msp->acb); - dprintk("msp34xx: scart switch: %s => %d\n", scart_names[in], out); - msp->acb &= ~scarts[out][SCART_MASK]; - msp->acb |= scarts[out][in]; - msp3400c_write(client,I2C_MSP3400C_DFP, 0x0013, msp->acb); + /* Sets I2S speed 0 = 1.024 Mbps, 1 = 2.048 Mbps */ + msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode); } /* ------------------------------------------------------------------------ */ @@ -1235,7 +1275,8 @@ static int msp3410d_thread(void *data) msp3400c_setbass(client, msp->bass); msp3400c_settreble(client, msp->treble); msp3400c_setvolume(client, msp->muted, msp->left, msp->right); - msp3400c_write(client, I2C_MSP3400C_DFP, 0x0013, msp->acb); + msp3400c_write(client, I2C_MSP3400C_DFP, 0x13, msp->acb); + msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode); msp3400c_restore_dfp(client); /* monitor tv audio mode */ @@ -1275,6 +1316,8 @@ static int msp34xxg_reset(struct i2c_client *client) 0x0f20 /* mute DSP input, mute SCART 1 */)) return -1; + msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode); + /* step-by-step initialisation, as described in the manual */ modus = msp34xx_modus(msp->norm); std = msp34xx_standard(msp->norm); @@ -1371,6 +1414,8 @@ static int msp34xxg_thread(void *data) 0x13, /* ACB */ msp->acb)) return -1; + + msp3400c_write(client,I2C_MSP3400C_DEM, 0x40, msp->i2s_mode); } dprintk("msp34xxg: thread: exit\n"); return 0; @@ -1539,6 +1584,7 @@ static int msp_attach(struct i2c_adapter *adap, int addr, int kind) msp->treble = 32768; msp->input = -1; msp->muted = 0; + msp->i2s_mode = 0; for (i = 0; i < DFP_COUNT; i++) msp->dfp_regs[i] = -1; @@ -1735,6 +1781,7 @@ static void msp_any_set_audmode(struct i2c_client *client, int audmode) } } + static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) { struct msp3400c *msp = i2c_get_clientdata(client); @@ -1745,6 +1792,7 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) case AUDC_SET_INPUT: dprintk("msp34xx: AUDC_SET_INPUT(%d)\n",*sarg); + if (*sarg == msp->input) break; msp->input = *sarg; @@ -1923,6 +1971,16 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) break; } + /* msp34xx specific */ + case MSP_SET_MATRIX: + { + struct msp_matrix *mspm = arg; + + dprintk("msp34xx: MSP_SET_MATRIX\n"); + msp3400c_set_scart(client, mspm->input, mspm->output); + break; + } + /* --- v4l2 ioctls --- */ case VIDIOC_S_STD: { @@ -1941,6 +1999,33 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) return 0; } + case VIDIOC_ENUMINPUT: + { + struct v4l2_input *i = arg; + + if (i->index != 0) + return -EINVAL; + + i->type = V4L2_INPUT_TYPE_TUNER; + switch (i->index) { + case AUDIO_RADIO: + strcpy(i->name,"Radio"); + break; + case AUDIO_EXTERN_1: + strcpy(i->name,"Extern 1"); + break; + case AUDIO_EXTERN_2: + strcpy(i->name,"Extern 2"); + break; + case AUDIO_TUNER: + strcpy(i->name,"Television"); + break; + default: + return -EINVAL; + } + return 0; + } + case VIDIOC_G_AUDIO: { struct v4l2_audio *a = arg; @@ -2032,13 +2117,44 @@ static int msp_command(struct i2c_client *client, unsigned int cmd, void *arg) break; } - /* msp34xx specific */ - case MSP_SET_MATRIX: + case VIDIOC_G_AUDOUT: { - struct msp_matrix *mspm = arg; + struct v4l2_audioout *a=(struct v4l2_audioout *)arg; + + memset(a,0,sizeof(*a)); + + switch (a->index) { + case 0: + strcpy(a->name,"Scart1 Out"); + break; + case 1: + strcpy(a->name,"Scart2 Out"); + break; + case 2: + strcpy(a->name,"I2S Out"); + break; + default: + return -EINVAL; + } + break; + + } + case VIDIOC_S_AUDOUT: + { + struct v4l2_audioout *a=(struct v4l2_audioout *)arg; + + if (a->index<0||a->index>2) + return -EINVAL; + + if (a->index==2) { + if (a->mode == V4L2_AUDMODE_32BITS) + msp->i2s_mode=1; + else + msp->i2s_mode=0; + } +printk("Setting audio out on msp34xx to input %i, mode %i\n",a->index,msp->i2s_mode); + msp3400c_set_scart(client,msp->in_scart,a->index); - dprintk("msp34xx: MSP_SET_MATRIX\n"); - msp3400c_set_scart(client, mspm->input, mspm->output); break; } diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index e8a0d22df54f..67c61b4bf2e7 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -885,6 +885,7 @@ struct v4l2_audio /* Flags for the 'mode' field */ #define V4L2_AUDMODE_AVL 0x00001 +#define V4L2_AUDMODE_32BITS 0x00002 struct v4l2_audioout { -- cgit v1.2.3 From f1bcef8874ab33b1e517b79a9b9df7309a996877 Mon Sep 17 00:00:00 2001 From: Tyler Trafford Date: Tue, 8 Nov 2005 21:38:46 -0800 Subject: [PATCH] V4L: 911: added support for ntsc 4.43 video standard Added support for NTSC 4.43 video standard. Signed-off-by: Tyler Trafford Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/media/video/saa7134/saa7134-dvb.c | 2 +- include/linux/videodev2.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 4cd3db492456..e016480c3468 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -749,7 +749,7 @@ static void philips_tda827xa_pll_sleep(u8 addr, struct dvb_frontend *fe) struct saa7134_dev *dev = fe->dvb->priv; static u8 tda827xa_sleep[] = { 0x30, 0x90}; struct i2c_msg tuner_msg = {.addr = addr,.flags = 0,.buf = tda827xa_sleep, - .len = sizeof(tda827xa_sleep) }; + .len = sizeof(tda827xa_sleep) }; i2c_transfer(&dev->i2c_adap, &tuner_msg, 1); } diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index 67c61b4bf2e7..a114fff6568b 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -627,6 +627,7 @@ typedef __u64 v4l2_std_id; #define V4L2_STD_NTSC_M ((v4l2_std_id)0x00001000) #define V4L2_STD_NTSC_M_JP ((v4l2_std_id)0x00002000) +#define V4L2_STD_NTSC_443 ((v4l2_std_id)0x00004000) #define V4L2_STD_SECAM_B ((v4l2_std_id)0x00010000) #define V4L2_STD_SECAM_D ((v4l2_std_id)0x00020000) @@ -664,7 +665,8 @@ typedef __u64 v4l2_std_id; #define V4L2_STD_525_60 (V4L2_STD_PAL_M |\ V4L2_STD_PAL_60 |\ - V4L2_STD_NTSC) + V4L2_STD_NTSC |\ + V4L2_STD_NTSC_443) #define V4L2_STD_625_50 (V4L2_STD_PAL |\ V4L2_STD_PAL_N |\ V4L2_STD_PAL_Nc |\ -- cgit v1.2.3 From e4fc27618b75234b721c4a13d0e0d9d07e75e641 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Tue, 8 Nov 2005 21:39:09 -0800 Subject: [PATCH] fbcon: Console Rotation - Prepare fbcon for console rotation This patch series implements generic code to rotate the console at 90, 180, and 270 degrees. The implementation is completely done in the framebuffer console level, thus no changes to the framebuffer layer or to the drivers are needed. Console rotation is required by some Sharp-based devices where the natural orientation of the display is not at 0 degrees. Also, users that have displays that can pivot will benefit by having a console in portrait mode if they so desire. The choice to implement the code in the console layer rather than in the framebuffer layer is due to the following reasons: - it's fast - it does not require driver changes - it can coexist with devices that can rotate the display at the hardware level - it complements graphics applications that can do display rotation The changes to core fbcon are minimal-- recognition of the console rotation angle so it can swap directions, origins and axes (xres vs yres, xpanstep vs ypanstep, xoffset vs yoffset, etc) and storage of the rotation angle per display. The bulk of the code that does the actual drawing to the screen are placed in separate files. Each angle of rotation has separate methods (bmove, clear, putcs, cursor, update_start which is derived from update_var, and clear_margins). To mimimize processing time, the fontdata are pre-rotated at each console switch (only if the font or the angle has changed). The option can be compiled out (CONFIG_FRAMEBUFFER_CONSOLE_ROTATION = n) if rotation is not needed. Choosing the rotation angle can be done in several ways: 1. boot option fbcon=rotate:n, where n = 0 - normal n = 1 - 90 degrees (clockwise) n = 2 - 180 degrees (upside down) n = 3 - 270 degrees (counterclockwise) 2. echo n > /sys/class/graphics/fb[num]/con_rotate where n is the same as described above. It sets the angle of rotation of the current console 3 echo n > /sys/class/graphics/fb[num]/con_rotate_all where n is the same as described above. Globally sets the angle of rotation. GOTCHAS: The option, especially at angles of 90 and 270 degrees, will exercise the least used code of drivers. Namely, at these angles, panning is done in the x-axis, so it can reveal bugs in the driver if xpanstep is set incorrectly. A workaround is to set xpanstep = 0. Secondly, at these angles, the framebuffer memory access can be unaligned if (fontheight * bpp) % 32 ~= 0 which can reveal bugs in the drivers imageblit, fillrect and copyarea functions. (I think cfbfillrect may have this buglet). A workaround is to use a standard 8x16 font. Speed: The scrolling speed difference between 0 and 180 degrees is minimal, somewhere areound 1-2%. At 90 or 270 degress, speed drops down to a vicinity of 30-40%. This is understandable because the blit direction is across the framebuffer "direction." Scrolling will be helped at these angles if xpanstep is not equal to zero, use of 8x16 fonts, and setting xres_virtual >= xres * 2. Note: The code is tested on little-endian only, so I don't know if it will work in big-endian. Please let me know, it will take only less than a minute of your time. This patch prepares fbcon for console rotation and contains the following changes: - add rotate field in struct fbcon_ops to keep fbcon's current rotation angle - add con_rotate field in struct display to store per-display rotation angle - create a private copy of the current var to fbcon. This will prevent fbcon from directly manipulating info->var, especially the fields xoffset, yoffset and vmode. - add ability to swap pertinent axes (xres, yres; xpanstep, ypanstep; etc) depending on the rotation angle - change global update_var() (function that sets the screen start address) as an fbcon method update_start. This is required because the axes, start offset, and/or direction can be reversed depending on the rotation angle. - add fbcon method rotate_font() which will rotate each character bitmap to the correct angle of rotation. - add fbcon boot option 'rotate' to select the angle of rotation at bootime. Currently does nothing until all patches are applied. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/Kconfig | 10 ++ drivers/video/console/bitblit.c | 46 +++---- drivers/video/console/fbcon.c | 285 +++++++++++++++++++++++++-------------- drivers/video/console/fbcon.h | 58 +++++++- drivers/video/console/tileblit.c | 13 ++ include/linux/fb.h | 12 +- 6 files changed, 286 insertions(+), 138 deletions(-) (limited to 'include/linux') diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index fadf7c5d216e..94c5f1392cce 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -101,6 +101,16 @@ config FRAMEBUFFER_CONSOLE help Low-level framebuffer-based console driver. +config FRAMEBUFFER_CONSOLE_ROTATION + bool "Framebuffer Console Rotation" + depends on FRAMEBUFFER_CONSOLE + help + Enable display rotation for the framebuffer console. This is done + in software and may be significantly slower than a normally oriented + display. Note that the rotation is done at the console level only + such that other users of the framebuffer will remain normally + oriented. + config STI_CONSOLE tristate "STI text console" depends on PARISC diff --git a/drivers/video/console/bitblit.c b/drivers/video/console/bitblit.c index 67857b3cfc8b..e65fc3ef7630 100644 --- a/drivers/video/console/bitblit.c +++ b/drivers/video/console/bitblit.c @@ -22,35 +22,6 @@ /* * Accelerated handlers. */ -#define FBCON_ATTRIBUTE_UNDERLINE 1 -#define FBCON_ATTRIBUTE_REVERSE 2 -#define FBCON_ATTRIBUTE_BOLD 4 - -static inline int real_y(struct display *p, int ypos) -{ - int rows = p->vrows; - - ypos += p->yscroll; - return ypos < rows ? ypos : ypos - rows; -} - - -static inline int get_attribute(struct fb_info *info, u16 c) -{ - int attribute = 0; - - if (fb_get_color_depth(&info->var, &info->fix) == 1) { - if (attr_underline(c)) - attribute |= FBCON_ATTRIBUTE_UNDERLINE; - if (attr_reverse(c)) - attribute |= FBCON_ATTRIBUTE_REVERSE; - if (attr_bold(c)) - attribute |= FBCON_ATTRIBUTE_BOLD; - } - - return attribute; -} - static inline void update_attr(u8 *dst, u8 *src, int attribute, struct vc_data *vc) { @@ -418,6 +389,18 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, ops->cursor_reset = 0; } +static int bit_update_start(struct fb_info *info) +{ + struct fbcon_ops *ops = info->fbcon_par; + int err; + + err = fb_pan_display(info, &ops->var); + ops->var.xoffset = info->var.xoffset; + ops->var.yoffset = info->var.yoffset; + ops->var.vmode = info->var.vmode; + return err; +} + void fbcon_set_bitops(struct fbcon_ops *ops) { ops->bmove = bit_bmove; @@ -425,6 +408,11 @@ void fbcon_set_bitops(struct fbcon_ops *ops) ops->putcs = bit_putcs; ops->clear_margins = bit_clear_margins; ops->cursor = bit_cursor; + ops->update_start = bit_update_start; + ops->rotate_font = NULL; + + if (ops->rotate) + fbcon_set_rotate(ops); } EXPORT_SYMBOL(fbcon_set_bitops); diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 3cf1b61ff1f8..b5d678c73252 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -107,6 +107,8 @@ enum { }; struct display fb_display[MAX_NR_CONSOLES]; +EXPORT_SYMBOL(fb_display); + static signed char con2fb_map[MAX_NR_CONSOLES]; static signed char con2fb_map_boot[MAX_NR_CONSOLES]; static int logo_height; @@ -130,6 +132,9 @@ static char fontname[40]; /* current fb_info */ static int info_idx = -1; +/* console rotation */ +static int rotate; + static const struct consw fb_con; #define CM_SOFTBACK (8) @@ -176,7 +181,6 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines); /* * Internal routines */ -static __inline__ int real_y(struct display *p, int ypos); static __inline__ void ywrap_up(struct vc_data *vc, int count); static __inline__ void ywrap_down(struct vc_data *vc, int count); static __inline__ void ypan_up(struct vc_data *vc, int count); @@ -203,6 +207,13 @@ static irqreturn_t fb_vbl_detect(int irq, void *dummy, struct pt_regs *fp) } #endif +static inline void fbcon_set_rotation(struct fb_info *info, struct display *p) +{ + struct fbcon_ops *ops = info->fbcon_par; + + ops->rotate = FB_ROTATE_UR; +} + static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info) { struct fbcon_ops *ops = info->fbcon_par; @@ -422,6 +433,14 @@ static int __init fb_console_setup(char *this_opt) last_fb_vc = simple_strtoul(options, &options, 10) - 1; fbcon_is_default = 0; } + + if (!strncmp(options, "rotate:", 7)) { + options += 7; + if (*options) + rotate = simple_strtoul(options, &options, 0); + if (rotate > 3) + rotate = 0; + } } return 0; } @@ -558,16 +577,24 @@ static void set_blitting_type(struct vc_data *vc, struct fb_info *info, if ((info->flags & FBINFO_MISC_TILEBLITTING)) fbcon_set_tileops(vc, info, p, ops); - else + else { + struct display *disp; + + disp = (p) ? p : &fb_display[vc->vc_num]; + fbcon_set_rotation(info, disp); fbcon_set_bitops(ops); + } } #else static void set_blitting_type(struct vc_data *vc, struct fb_info *info, struct display *p) { struct fbcon_ops *ops = info->fbcon_par; + struct display *disp; info->flags &= ~FBINFO_MISC_TILEBLITTING; + disp = (p) ? p : &fb_display[vc->vc_num]; + fbcon_set_rotation(info, disp); fbcon_set_bitops(ops); } #endif /* CONFIG_MISC_TILEBLITTING */ @@ -627,6 +654,7 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo, fbcon_del_cursor_timer(oldinfo); kfree(ops->cursor_state.mask); kfree(ops->cursor_data); + kfree(ops->fontbuffer); kfree(oldinfo->fbcon_par); oldinfo->fbcon_par = NULL; module_put(oldinfo->fbops->owner); @@ -827,7 +855,9 @@ static const char *fbcon_startup(void) memset(ops, 0, sizeof(struct fbcon_ops)); ops->currcon = -1; ops->graphics = 1; + ops->cur_rotate = -1; info->fbcon_par = ops; + p->con_rotate = rotate; set_blitting_type(vc, info, NULL); if (info->fix.type != FB_TYPE_TEXT) { @@ -866,8 +896,10 @@ static const char *fbcon_startup(void) vc->vc_font.charcount = 256; /* FIXME Need to support more fonts */ } - cols = info->var.xres / vc->vc_font.width; - rows = info->var.yres / vc->vc_font.height; + cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols /= vc->vc_font.width; + rows /= vc->vc_font.height; vc_resize(vc, cols, rows); DPRINTK("mode: %s\n", info->fix.id); @@ -953,8 +985,6 @@ static void fbcon_init(struct vc_data *vc, int init) (info->fix.type == FB_TYPE_TEXT)) logo = 0; - info->var.xoffset = info->var.yoffset = p->yscroll = 0; /* reset wrap/pan */ - if (var_to_display(p, &info->var, info)) return; @@ -986,13 +1016,18 @@ static void fbcon_init(struct vc_data *vc, int init) if (!*vc->vc_uni_pagedir_loc) con_copy_unimap(vc, svc); + ops = info->fbcon_par; + p->con_rotate = rotate; + set_blitting_type(vc, info, NULL); + cols = vc->vc_cols; rows = vc->vc_rows; - new_cols = info->var.xres / vc->vc_font.width; - new_rows = info->var.yres / vc->vc_font.height; + new_cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + new_rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + new_cols /= vc->vc_font.width; + new_rows /= vc->vc_font.height; vc_resize(vc, new_cols, new_rows); - ops = info->fbcon_par; /* * We must always set the mode. The mode of the previous console * driver could be in the same resolution but we are using different @@ -1030,6 +1065,12 @@ static void fbcon_init(struct vc_data *vc, int init) if (vc == svc && softback_buf) fbcon_update_softback(vc); + + if (ops->rotate_font && ops->rotate_font(info, vc, p)) { + ops->rotate = FB_ROTATE_UR; + set_blitting_type(vc, info, p); + } + } static void fbcon_deinit(struct vc_data *vc) @@ -1066,15 +1107,6 @@ static void fbcon_deinit(struct vc_data *vc) * restriction is simplicity & efficiency at the moment. */ -static __inline__ int real_y(struct display *p, int ypos) -{ - int rows = p->vrows; - - ypos += p->yscroll; - return ypos < rows ? ypos : ypos - rows; -} - - static void fbcon_clear(struct vc_data *vc, int sy, int sx, int height, int width) { @@ -1162,13 +1194,6 @@ static int scrollback_phys_max = 0; static int scrollback_max = 0; static int scrollback_current = 0; -static int update_var(int con, struct fb_info *info) -{ - if (con == ((struct fbcon_ops *)info->fbcon_par)->currcon) - return fb_pan_display(info, &info->var); - return 0; -} - /* * If no vc is existent yet, just set struct display */ @@ -1178,7 +1203,6 @@ static void fbcon_preset_disp(struct fb_info *info, struct fb_var_screeninfo *va struct display *p = &fb_display[unit]; struct display *t = &fb_display[fg_console]; - var->xoffset = var->yoffset = p->yscroll = 0; if (var_to_display(p, var, info)) return; @@ -1194,9 +1218,9 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, struct display *p = &fb_display[vc->vc_num], *t; struct vc_data **default_mode = vc->vc_display_fg; struct vc_data *svc = *default_mode; + struct fbcon_ops *ops = info->fbcon_par; int rows, cols, charcnt = 256; - var->xoffset = var->yoffset = p->yscroll = 0; if (var_to_display(p, var, info)) return; t = &fb_display[svc->vc_num]; @@ -1213,9 +1237,10 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, var->activate = FB_ACTIVATE_NOW; info->var.activate = var->activate; - info->var.yoffset = info->var.xoffset = 0; + var->yoffset = info->var.yoffset; + var->xoffset = info->var.xoffset; fb_set_var(info, var); - + ops->var = info->var; vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1); vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; if (charcnt == 256) { @@ -1231,9 +1256,12 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, if (!*vc->vc_uni_pagedir_loc) con_copy_unimap(vc, svc); - cols = var->xres / vc->vc_font.width; - rows = var->yres / vc->vc_font.height; + cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols /= vc->vc_font.width; + rows /= vc->vc_font.height; vc_resize(vc, cols, rows); + if (CON_IS_VISIBLE(vc)) { update_screen(vc); if (softback_buf) @@ -1244,15 +1272,16 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, static __inline__ void ywrap_up(struct vc_data *vc, int count) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; p->yscroll += count; if (p->yscroll >= p->vrows) /* Deal with wrap */ p->yscroll -= p->vrows; - info->var.xoffset = 0; - info->var.yoffset = p->yscroll * vc->vc_font.height; - info->var.vmode |= FB_VMODE_YWRAP; - update_var(vc->vc_num, info); + ops->var.xoffset = 0; + ops->var.yoffset = p->yscroll * vc->vc_font.height; + ops->var.vmode |= FB_VMODE_YWRAP; + ops->update_start(info); scrollback_max += count; if (scrollback_max > scrollback_phys_max) scrollback_max = scrollback_phys_max; @@ -1262,15 +1291,16 @@ static __inline__ void ywrap_up(struct vc_data *vc, int count) static __inline__ void ywrap_down(struct vc_data *vc, int count) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; p->yscroll -= count; if (p->yscroll < 0) /* Deal with wrap */ p->yscroll += p->vrows; - info->var.xoffset = 0; - info->var.yoffset = p->yscroll * vc->vc_font.height; - info->var.vmode |= FB_VMODE_YWRAP; - update_var(vc->vc_num, info); + ops->var.xoffset = 0; + ops->var.yoffset = p->yscroll * vc->vc_font.height; + ops->var.vmode |= FB_VMODE_YWRAP; + ops->update_start(info); scrollback_max -= count; if (scrollback_max < 0) scrollback_max = 0; @@ -1289,10 +1319,11 @@ static __inline__ void ypan_up(struct vc_data *vc, int count) 0, 0, 0, vc->vc_rows, vc->vc_cols); p->yscroll -= p->vrows - vc->vc_rows; } - info->var.xoffset = 0; - info->var.yoffset = p->yscroll * vc->vc_font.height; - info->var.vmode &= ~FB_VMODE_YWRAP; - update_var(vc->vc_num, info); + + ops->var.xoffset = 0; + ops->var.yoffset = p->yscroll * vc->vc_font.height; + ops->var.vmode &= ~FB_VMODE_YWRAP; + ops->update_start(info); fbcon_clear_margins(vc, 1); scrollback_max += count; if (scrollback_max > scrollback_phys_max) @@ -1303,6 +1334,7 @@ static __inline__ void ypan_up(struct vc_data *vc, int count) static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; int redraw = 0; @@ -1312,12 +1344,13 @@ static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count) redraw = 1; } - info->var.xoffset = 0; - info->var.yoffset = p->yscroll * vc->vc_font.height; - info->var.vmode &= ~FB_VMODE_YWRAP; if (redraw) fbcon_redraw_move(vc, p, t + count, vc->vc_rows - count, t); - update_var(vc->vc_num, info); + + ops->var.xoffset = 0; + ops->var.yoffset = p->yscroll * vc->vc_font.height; + ops->var.vmode &= ~FB_VMODE_YWRAP; + ops->update_start(info); fbcon_clear_margins(vc, 1); scrollback_max += count; if (scrollback_max > scrollback_phys_max) @@ -1337,10 +1370,11 @@ static __inline__ void ypan_down(struct vc_data *vc, int count) 0, vc->vc_rows, vc->vc_cols); p->yscroll += p->vrows - vc->vc_rows; } - info->var.xoffset = 0; - info->var.yoffset = p->yscroll * vc->vc_font.height; - info->var.vmode &= ~FB_VMODE_YWRAP; - update_var(vc->vc_num, info); + + ops->var.xoffset = 0; + ops->var.yoffset = p->yscroll * vc->vc_font.height; + ops->var.vmode &= ~FB_VMODE_YWRAP; + ops->update_start(info); fbcon_clear_margins(vc, 1); scrollback_max -= count; if (scrollback_max < 0) @@ -1351,6 +1385,7 @@ static __inline__ void ypan_down(struct vc_data *vc, int count) static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; int redraw = 0; @@ -1359,12 +1394,14 @@ static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count) p->yscroll += p->vrows - vc->vc_rows; redraw = 1; } - info->var.xoffset = 0; - info->var.yoffset = p->yscroll * vc->vc_font.height; - info->var.vmode &= ~FB_VMODE_YWRAP; + if (redraw) fbcon_redraw_move(vc, p, t, vc->vc_rows - count, t + count); - update_var(vc->vc_num, info); + + ops->var.xoffset = 0; + ops->var.yoffset = p->yscroll * vc->vc_font.height; + ops->var.vmode &= ~FB_VMODE_YWRAP; + ops->update_start(info); fbcon_clear_margins(vc, 1); scrollback_max -= count; if (scrollback_max < 0) @@ -1838,31 +1875,41 @@ static void fbcon_bmove_rec(struct vc_data *vc, struct display *p, int sy, int s height, width); } -static __inline__ void updatescrollmode(struct display *p, struct fb_info *info, +static __inline__ void updatescrollmode(struct display *p, + struct fb_info *info, struct vc_data *vc) { + struct fbcon_ops *ops = info->fbcon_par; int fh = vc->vc_font.height; int cap = info->flags; - int good_pan = (cap & FBINFO_HWACCEL_YPAN) - && divides(info->fix.ypanstep, vc->vc_font.height) - && info->var.yres_virtual > info->var.yres; - int good_wrap = (cap & FBINFO_HWACCEL_YWRAP) - && divides(info->fix.ywrapstep, vc->vc_font.height) - && divides(vc->vc_font.height, info->var.yres_virtual); + u16 t = 0; + int ypan = FBCON_SWAP(ops->rotate, info->fix.ypanstep, + info->fix.xpanstep); + int ywrap = FBCON_SWAP(ops->rotate, info->fix.ywrapstep, t); + int yres = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + int vyres = FBCON_SWAP(ops->rotate, info->var.yres_virtual, + info->var.xres_virtual); + int good_pan = (cap & FBINFO_HWACCEL_YPAN) && + divides(ypan, vc->vc_font.height) && vyres > yres; + int good_wrap = (cap & FBINFO_HWACCEL_YWRAP) && + divides(ywrap, vc->vc_font.height) && + divides(vc->vc_font.height, vyres); int reading_fast = cap & FBINFO_READS_FAST; - int fast_copyarea = (cap & FBINFO_HWACCEL_COPYAREA) && !(cap & FBINFO_HWACCEL_DISABLED); - int fast_imageblit = (cap & FBINFO_HWACCEL_IMAGEBLIT) && !(cap & FBINFO_HWACCEL_DISABLED); - - p->vrows = info->var.yres_virtual/fh; - if (info->var.yres > (fh * (vc->vc_rows + 1))) - p->vrows -= (info->var.yres - (fh * vc->vc_rows)) / fh; - if ((info->var.yres % fh) && (info->var.yres_virtual % fh < - info->var.yres % fh)) + int fast_copyarea = (cap & FBINFO_HWACCEL_COPYAREA) && + !(cap & FBINFO_HWACCEL_DISABLED); + int fast_imageblit = (cap & FBINFO_HWACCEL_IMAGEBLIT) && + !(cap & FBINFO_HWACCEL_DISABLED); + + p->vrows = vyres/fh; + if (yres > (fh * (vc->vc_rows + 1))) + p->vrows -= (yres - (fh * vc->vc_rows)) / fh; + if ((yres % fh) && (vyres % fh < yres % fh)) p->vrows--; if (good_wrap || good_pan) { if (reading_fast || fast_copyarea) - p->scrollmode = good_wrap ? SCROLL_WRAP_MOVE : SCROLL_PAN_MOVE; + p->scrollmode = good_wrap ? + SCROLL_WRAP_MOVE : SCROLL_PAN_MOVE; else p->scrollmode = good_wrap ? SCROLL_REDRAW : SCROLL_PAN_REDRAW; @@ -1878,17 +1925,23 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, unsigned int height) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; struct fb_var_screeninfo var = info->var; - int x_diff, y_diff; - int fw = vc->vc_font.width; - int fh = vc->vc_font.height; - - var.xres = width * fw; - var.yres = height * fh; + int x_diff, y_diff, virt_w, virt_h, virt_fw, virt_fh; + + virt_w = FBCON_SWAP(ops->rotate, width, height); + virt_h = FBCON_SWAP(ops->rotate, height, width); + virt_fw = FBCON_SWAP(ops->rotate, vc->vc_font.width, + vc->vc_font.height); + virt_fh = FBCON_SWAP(ops->rotate, vc->vc_font.height, + vc->vc_font.width); + var.xres = virt_w * virt_fw; + var.yres = virt_h * virt_fh; x_diff = info->var.xres - var.xres; y_diff = info->var.yres - var.yres; - if (x_diff < 0 || x_diff > fw || (y_diff < 0 || y_diff > fh)) { + if (x_diff < 0 || x_diff > virt_fw || + y_diff < 0 || y_diff > virt_fh) { struct fb_videomode *mode; DPRINTK("attempting resize %ix%i\n", var.xres, var.yres); @@ -1898,7 +1951,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, display_to_var(&var, p); fb_videomode_to_var(&var, mode); - if (width > var.xres/fw || height > var.yres/fh) + if (virt_w > var.xres/virt_fw || virt_h > var.yres/virt_fh) return -EINVAL; DPRINTK("resize now %ix%i\n", var.xres, var.yres); @@ -1908,6 +1961,7 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, fb_set_var(info, &var); } var_to_display(p, &info->var, info); + ops->var = info->var; } updatescrollmode(p, info, vc); return 0; @@ -1916,11 +1970,13 @@ static int fbcon_resize(struct vc_data *vc, unsigned int width, static int fbcon_switch(struct vc_data *vc) { struct fb_info *info, *old_info = NULL; + struct fbcon_ops *ops; struct display *p = &fb_display[vc->vc_num]; struct fb_var_screeninfo var; int i, prev_console; info = registered_fb[con2fb_map[vc->vc_num]]; + ops = info->fbcon_par; if (softback_top) { if (softback_lines) @@ -1939,7 +1995,7 @@ static int fbcon_switch(struct vc_data *vc) logo_shown = FBCON_LOGO_CANSHOW; } - prev_console = ((struct fbcon_ops *)info->fbcon_par)->currcon; + prev_console = ops->currcon; if (prev_console != -1) old_info = registered_fb[con2fb_map[prev_console]]; /* @@ -1952,9 +2008,9 @@ static int fbcon_switch(struct vc_data *vc) */ for (i = 0; i < FB_MAX; i++) { if (registered_fb[i] != NULL && registered_fb[i]->fbcon_par) { - struct fbcon_ops *ops = registered_fb[i]->fbcon_par; + struct fbcon_ops *o = registered_fb[i]->fbcon_par; - ops->currcon = vc->vc_num; + o->currcon = vc->vc_num; } } memset(&var, 0, sizeof(struct fb_var_screeninfo)); @@ -1966,8 +2022,11 @@ static int fbcon_switch(struct vc_data *vc) * in fb_set_var() */ info->var.activate = var.activate; - info->var.yoffset = info->var.xoffset = p->yscroll = 0; + var.yoffset = info->var.yoffset; + var.xoffset = info->var.xoffset; + var.vmode = info->var.vmode; fb_set_var(info, &var); + ops->var = info->var; if (old_info != NULL && old_info != info) { if (info->fbops->fb_set_par) @@ -1977,7 +2036,12 @@ static int fbcon_switch(struct vc_data *vc) } set_blitting_type(vc, info, p); - ((struct fbcon_ops *)info->fbcon_par)->cursor_reset = 1; + ops->cursor_reset = 1; + + if (ops->rotate_font && ops->rotate_font(info, vc, p)) { + ops->rotate = FB_ROTATE_UR; + set_blitting_type(vc, info, p); + } vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1); vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800; @@ -1997,10 +2061,11 @@ static int fbcon_switch(struct vc_data *vc) scrollback_phys_max = 0; break; } + scrollback_max = 0; scrollback_current = 0; - - update_var(vc->vc_num, info); + ops->var.xoffset = ops->var.yoffset = p->yscroll = 0; + ops->update_start(info); fbcon_set_palette(vc, color_table); fbcon_clear_margins(vc, 0); @@ -2047,6 +2112,7 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch) var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE; fb_set_var(info, &var); ops->graphics = 0; + ops->var = info->var; } } @@ -2135,6 +2201,7 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, const u8 * data, int userfont) { struct fb_info *info = registered_fb[con2fb_map[vc->vc_num]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[vc->vc_num]; int resize; int cnt; @@ -2214,9 +2281,13 @@ static int fbcon_do_set_font(struct vc_data *vc, int w, int h, } if (resize) { - /* reset wrap/pan */ - info->var.xoffset = info->var.yoffset = p->yscroll = 0; - vc_resize(vc, info->var.xres / w, info->var.yres / h); + int cols, rows; + + cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols /= w; + rows /= h; + vc_resize(vc, cols, rows); if (CON_IS_VISIBLE(vc) && softback_buf) fbcon_update_softback(vc); } else if (CON_IS_VISIBLE(vc) @@ -2444,6 +2515,7 @@ static void fbcon_invert_region(struct vc_data *vc, u16 * p, int cnt) static int fbcon_scrolldelta(struct vc_data *vc, int lines) { struct fb_info *info = registered_fb[con2fb_map[fg_console]]; + struct fbcon_ops *ops = info->fbcon_par; struct display *p = &fb_display[fg_console]; int offset, limit, scrollback_old; @@ -2520,9 +2592,11 @@ static int fbcon_scrolldelta(struct vc_data *vc, int lines) offset += limit; else if (offset >= limit) offset -= limit; - info->var.xoffset = 0; - info->var.yoffset = offset * vc->vc_font.height; - update_var(vc->vc_num, info); + + ops->var.xoffset = 0; + ops->var.yoffset = offset * vc->vc_font.height; + ops->update_start(info); + if (!scrollback_current) fbcon_cursor(vc, CM_DRAW); return 0; @@ -2570,22 +2644,25 @@ static void fbcon_modechanged(struct fb_info *info) if (!ops || ops->currcon < 0) return; vc = vc_cons[ops->currcon].d; - if (vc->vc_mode != KD_TEXT || registered_fb[con2fb_map[ops->currcon]] != info) + if (vc->vc_mode != KD_TEXT || + registered_fb[con2fb_map[ops->currcon]] != info) return; p = &fb_display[vc->vc_num]; - - info->var.xoffset = info->var.yoffset = p->yscroll = 0; + set_blitting_type(vc, info, p); if (CON_IS_VISIBLE(vc)) { var_to_display(p, &info->var, info); - cols = info->var.xres / vc->vc_font.width; - rows = info->var.yres / vc->vc_font.height; + cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols /= vc->vc_font.width; + rows /= vc->vc_font.height; vc_resize(vc, cols, rows); updatescrollmode(p, info, vc); scrollback_max = 0; scrollback_current = 0; - update_var(vc->vc_num, info); + ops->var.xoffset = ops->var.yoffset = p->yscroll = 0; + ops->update_start(info); fbcon_set_palette(vc, color_table); update_screen(vc); if (softback_buf) @@ -2610,18 +2687,20 @@ static void fbcon_set_all_vcs(struct fb_info *info) continue; p = &fb_display[vc->vc_num]; - - info->var.xoffset = info->var.yoffset = p->yscroll = 0; + set_blitting_type(vc, info, p); var_to_display(p, &info->var, info); - cols = info->var.xres / vc->vc_font.width; - rows = info->var.yres / vc->vc_font.height; + cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres); + rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres); + cols /= vc->vc_font.width; + rows /= vc->vc_font.height; vc_resize(vc, cols, rows); if (CON_IS_VISIBLE(vc)) { updatescrollmode(p, info, vc); scrollback_max = 0; scrollback_current = 0; - update_var(vc->vc_num, info); + ops->var.xoffset = ops->var.yoffset = p->yscroll = 0; + ops->update_start(info); fbcon_set_palette(vc, color_table); update_screen(vc); if (softback_buf) diff --git a/drivers/video/console/fbcon.h b/drivers/video/console/fbcon.h index b68e0e2c2d16..846a5a4e736c 100644 --- a/drivers/video/console/fbcon.h +++ b/drivers/video/console/fbcon.h @@ -27,15 +27,15 @@ */ struct display { - /* Filled in by the frame buffer device */ - u_short inverse; /* != 0 text black on white as default */ /* Filled in by the low-level console driver */ const u_char *fontdata; int userfont; /* != 0 if fontdata kmalloc()ed */ u_short scrollmode; /* Scroll Method */ + u_short inverse; /* != 0 text black on white as default */ short yscroll; /* Hardware scrolling */ int vrows; /* number of virtual rows */ int cursor_shape; + int con_rotate; u32 xres_virtual; u32 yres_virtual; u32 height; @@ -52,6 +52,8 @@ struct display { struct fb_videomode *mode; }; +extern struct display fb_display[]; + struct fbcon_ops { void (*bmove)(struct vc_data *vc, struct fb_info *info, int sy, int sx, int dy, int dx, int height, int width); @@ -63,8 +65,12 @@ struct fbcon_ops { void (*clear_margins)(struct vc_data *vc, struct fb_info *info, int bottom_only); void (*cursor)(struct vc_data *vc, struct fb_info *info, - struct display *p, int mode, int softback_lines, int fg, int bg); - + struct display *p, int mode, int softback_lines, + int fg, int bg); + int (*update_start)(struct fb_info *info); + int (*rotate_font)(struct fb_info *info, struct vc_data *vc, + struct display *p); + struct fb_var_screeninfo var; /* copy of the current fb_var_screeninfo */ struct timer_list cursor_timer; /* Cursor timer */ struct fb_cursor cursor_state; int currcon; /* Current VC. */ @@ -73,7 +79,12 @@ struct fbcon_ops { int blank_state; int graphics; int flags; + int rotate; + int cur_rotate; char *cursor_data; + u8 *fontbuffer; + u8 *fontdata; + u32 fd_size; }; /* * Attribute Decoding @@ -168,4 +179,43 @@ extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info, #endif extern void fbcon_set_bitops(struct fbcon_ops *ops); extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor); + +#define FBCON_ATTRIBUTE_UNDERLINE 1 +#define FBCON_ATTRIBUTE_REVERSE 2 +#define FBCON_ATTRIBUTE_BOLD 4 + +static inline int real_y(struct display *p, int ypos) +{ + int rows = p->vrows; + + ypos += p->yscroll; + return ypos < rows ? ypos : ypos - rows; +} + + +static inline int get_attribute(struct fb_info *info, u16 c) +{ + int attribute = 0; + + if (fb_get_color_depth(&info->var, &info->fix) == 1) { + if (attr_underline(c)) + attribute |= FBCON_ATTRIBUTE_UNDERLINE; + if (attr_reverse(c)) + attribute |= FBCON_ATTRIBUTE_REVERSE; + if (attr_bold(c)) + attribute |= FBCON_ATTRIBUTE_BOLD; + } + + return attribute; +} + +#define FBCON_SWAP(i,r,v) ({ \ + typeof(r) _r = (r); \ + typeof(v) _v = (v); \ + (void) (&_r == &_v); \ + (i == FB_ROTATE_UR || i == FB_ROTATE_UD) ? _r : _v; }) + +#define fbcon_set_rotate(x) do {} while(0) + #endif /* _VIDEO_FBCON_H */ + diff --git a/drivers/video/console/tileblit.c b/drivers/video/console/tileblit.c index 7f76e2c6a4a1..cb25324a5635 100644 --- a/drivers/video/console/tileblit.c +++ b/drivers/video/console/tileblit.c @@ -118,6 +118,18 @@ static void tile_cursor(struct vc_data *vc, struct fb_info *info, info->tileops->fb_tilecursor(info, &cursor); } +static int tile_update_start(struct fb_info *info) +{ + struct fbcon_ops *ops = info->fbcon_par; + int err; + + err = fb_pan_display(info, &ops->var); + ops->var.xoffset = info->var.xoffset; + ops->var.yoffset = info->var.yoffset; + ops->var.vmode = info->var.vmode; + return err; +} + void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info, struct display *p, struct fbcon_ops *ops) { @@ -128,6 +140,7 @@ void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info, ops->putcs = tile_putcs; ops->clear_margins = tile_clear_margins; ops->cursor = tile_cursor; + ops->update_start = tile_update_start; if (p) { map.width = vc->vc_font.width; diff --git a/include/linux/fb.h b/include/linux/fb.h index e7ff98e395f6..51791dc5d4dc 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -201,6 +201,14 @@ struct fb_bitfield { #define FB_VMODE_SMOOTH_XPAN 512 /* smooth xpan possible (internally used) */ #define FB_VMODE_CONUPDATE 512 /* don't update x/yoffset */ +/* + * Display rotation support + */ +#define FB_ROTATE_UR 0 +#define FB_ROTATE_CW 1 +#define FB_ROTATE_UD 2 +#define FB_ROTATE_CCW 3 + #define PICOS2KHZ(a) (1000000000UL/(a)) #define KHZ2PICOS(a) (1000000000UL/(a)) @@ -489,9 +497,9 @@ struct fb_cursor_user { #define FB_EVENT_MODE_DELETE 0x04 /* A driver registered itself */ #define FB_EVENT_FB_REGISTERED 0x05 -/* get console to framebuffer mapping */ +/* CONSOLE-SPECIFIC: get console to framebuffer mapping */ #define FB_EVENT_GET_CONSOLE_MAP 0x06 -/* set console to framebuffer mapping */ +/* CONSOLE-SPECIFIC: set console to framebuffer mapping */ #define FB_EVENT_SET_CONSOLE_MAP 0x07 /* A display blank is requested */ #define FB_EVENT_BLANK 0x08 -- cgit v1.2.3 From 9c44e5f6c211a9b7313ded897f3135ef7d9ad3e2 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Tue, 8 Nov 2005 21:39:10 -0800 Subject: [PATCH] fbcon: Console Rotation - Add support to rotate the logo Add support for rotating and positioning of the logo. Rotation and position depends on 'int rotate' parameter added to fb_prepare_logo() and fb_show_logo(). Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/fbcon.c | 5 +- drivers/video/fbmem.c | 130 +++++++++++++++++++++++++++++++++++++----- include/linux/fb.h | 4 +- 3 files changed, 122 insertions(+), 17 deletions(-) (limited to 'include/linux') diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index b5d678c73252..26935e231a1d 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -499,6 +499,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, int cols, int rows, int new_cols, int new_rows) { /* Need to make room for the logo */ + struct fbcon_ops *ops = info->fbcon_par; int cnt, erase = vc->vc_video_erase_char, step; unsigned short *save = NULL, *r, *q; @@ -508,7 +509,7 @@ static void fbcon_prepare_logo(struct vc_data *vc, struct fb_info *info, */ if (fb_get_color_depth(&info->var, &info->fix) == 1) erase &= ~0x400; - logo_height = fb_prepare_logo(info); + logo_height = fb_prepare_logo(info, ops->rotate); logo_lines = (logo_height + vc->vc_font.height - 1) / vc->vc_font.height; q = (unsigned short *) (vc->vc_origin + @@ -2073,7 +2074,7 @@ static int fbcon_switch(struct vc_data *vc) logo_shown = fg_console; /* This is protected above by initmem_freed */ - fb_show_logo(info); + fb_show_logo(info, ops->rotate); update_region(vc, vc->vc_origin + vc->vc_size_row * vc->vc_top, vc->vc_size_row * (vc->vc_bottom - diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index e2667ddab3f1..7a2a8fa50b3b 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -323,9 +323,103 @@ static struct logo_data { const struct linux_logo *logo; } fb_logo; -int fb_prepare_logo(struct fb_info *info) +static void fb_rotate_logo_ud(const u8 *in, u8 *out, u32 width, u32 height) +{ + u32 size = width * height, i; + + out += size - 1; + + for (i = size; i--; ) + *out-- = *in++; +} + +static void fb_rotate_logo_cw(const u8 *in, u8 *out, u32 width, u32 height) +{ + int i, j, w = width - 1; + + for (i = 0; i < height; i++) + for (j = 0; j < width; j++) + out[height * j + w - i] = *in++; +} + +static void fb_rotate_logo_ccw(const u8 *in, u8 *out, u32 width, u32 height) +{ + int i, j, w = width - 1; + + for (i = 0; i < height; i++) + for (j = 0; j < width; j++) + out[height * (w - j) + i] = *in++; +} + +static void fb_rotate_logo(struct fb_info *info, u8 *dst, + struct fb_image *image, int rotate) +{ + u32 tmp; + + if (rotate == FB_ROTATE_UD) { + image->dx = info->var.xres - image->width; + image->dy = info->var.yres - image->height; + fb_rotate_logo_ud(image->data, dst, image->width, + image->height); + } else if (rotate == FB_ROTATE_CW) { + tmp = image->width; + image->width = image->height; + image->height = tmp; + image->dx = info->var.xres - image->height; + fb_rotate_logo_cw(image->data, dst, image->width, + image->height); + } else if (rotate == FB_ROTATE_CCW) { + tmp = image->width; + image->width = image->height; + image->height = tmp; + image->dy = info->var.yres - image->width; + fb_rotate_logo_ccw(image->data, dst, image->width, + image->height); + } + + image->data = dst; +} + +static void fb_do_show_logo(struct fb_info *info, struct fb_image *image, + int rotate) +{ + int x; + + if (rotate == FB_ROTATE_UR) { + for (x = 0; x < num_online_cpus() && + x * (fb_logo.logo->width + 8) <= + info->var.xres - fb_logo.logo->width; x++) { + info->fbops->fb_imageblit(info, image); + image->dx += fb_logo.logo->width + 8; + } + } else if (rotate == FB_ROTATE_UD) { + for (x = 0; x < num_online_cpus() && + x * (fb_logo.logo->width + 8) <= + info->var.xres - fb_logo.logo->width; x++) { + info->fbops->fb_imageblit(info, image); + image->dx -= fb_logo.logo->width + 8; + } + } else if (rotate == FB_ROTATE_CW) { + for (x = 0; x < num_online_cpus() && + x * (fb_logo.logo->width + 8) <= + info->var.yres - fb_logo.logo->width; x++) { + info->fbops->fb_imageblit(info, image); + image->dy += fb_logo.logo->width + 8; + } + } else if (rotate == FB_ROTATE_CCW) { + for (x = 0; x < num_online_cpus() && + x * (fb_logo.logo->width + 8) <= + info->var.yres - fb_logo.logo->width; x++) { + info->fbops->fb_imageblit(info, image); + image->dy -= fb_logo.logo->width + 8; + } + } +} + +int fb_prepare_logo(struct fb_info *info, int rotate) { int depth = fb_get_color_depth(&info->var, &info->fix); + int yres; memset(&fb_logo, 0, sizeof(struct logo_data)); @@ -358,10 +452,16 @@ int fb_prepare_logo(struct fb_info *info) /* Return if no suitable logo was found */ fb_logo.logo = fb_find_logo(depth); - if (!fb_logo.logo || fb_logo.logo->height > info->var.yres) { + if (rotate == FB_ROTATE_UR || rotate == FB_ROTATE_UD) + yres = info->var.yres; + else + yres = info->var.xres; + + if (fb_logo.logo && fb_logo.logo->height > yres) { fb_logo.logo = NULL; return 0; } + /* What depth we asked for might be different from what we get */ if (fb_logo.logo->type == LINUX_LOGO_CLUT224) fb_logo.depth = 8; @@ -372,12 +472,11 @@ int fb_prepare_logo(struct fb_info *info) return fb_logo.logo->height; } -int fb_show_logo(struct fb_info *info) +int fb_show_logo(struct fb_info *info, int rotate) { u32 *palette = NULL, *saved_pseudo_palette = NULL; - unsigned char *logo_new = NULL; + unsigned char *logo_new = NULL, *logo_rotate = NULL; struct fb_image image; - int x; /* Return if the frame buffer is not mapped or suspended */ if (fb_logo.logo == NULL || info->state != FBINFO_STATE_RUNNING) @@ -417,25 +516,30 @@ int fb_show_logo(struct fb_info *info) fb_set_logo(info, fb_logo.logo, logo_new, fb_logo.depth); } + image.dx = 0; + image.dy = 0; image.width = fb_logo.logo->width; image.height = fb_logo.logo->height; - image.dy = 0; - for (x = 0; x < num_online_cpus() * (fb_logo.logo->width + 8) && - x <= info->var.xres-fb_logo.logo->width; x += (fb_logo.logo->width + 8)) { - image.dx = x; - info->fbops->fb_imageblit(info, &image); + if (rotate) { + logo_rotate = kmalloc(fb_logo.logo->width * + fb_logo.logo->height, GFP_KERNEL); + if (logo_rotate) + fb_rotate_logo(info, logo_rotate, &image, rotate); } - + + fb_do_show_logo(info, &image, rotate); + kfree(palette); if (saved_pseudo_palette != NULL) info->pseudo_palette = saved_pseudo_palette; kfree(logo_new); + kfree(logo_rotate); return fb_logo.logo->height; } #else -int fb_prepare_logo(struct fb_info *info) { return 0; } -int fb_show_logo(struct fb_info *info) { return 0; } +int fb_prepare_logo(struct fb_info *info, int rotate) { return 0; } +int fb_show_logo(struct fb_info *info, int rotate) { return 0; } #endif /* CONFIG_LOGO */ static int fbmem_read_proc(char *buf, char **start, off_t offset, diff --git a/include/linux/fb.h b/include/linux/fb.h index 51791dc5d4dc..357dd3a0a01e 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -825,8 +825,8 @@ extern void cfb_imageblit(struct fb_info *info, const struct fb_image *image); /* drivers/video/fbmem.c */ extern int register_framebuffer(struct fb_info *fb_info); extern int unregister_framebuffer(struct fb_info *fb_info); -extern int fb_prepare_logo(struct fb_info *fb_info); -extern int fb_show_logo(struct fb_info *fb_info); +extern int fb_prepare_logo(struct fb_info *fb_info, int rotate); +extern int fb_show_logo(struct fb_info *fb_info, int rotate); extern char* fb_get_buffer_offset(struct fb_info *info, struct fb_pixmap *buf, u32 size); extern void fb_pad_unaligned_buffer(u8 *dst, u32 d_pitch, u8 *src, u32 idx, u32 height, u32 shift_high, u32 shift_low, u32 mod); -- cgit v1.2.3 From a812c94b94e3db76d1af68208fb3edef69070401 Mon Sep 17 00:00:00 2001 From: "Antonino A. Daplas" Date: Tue, 8 Nov 2005 21:39:15 -0800 Subject: [PATCH] fbcon: Console Rotation - Add ability to control rotation via sysfs Add ability to set rotation via sysfs. The attributes are located in /sys/class/graphics/fb[n] and accepts 0 - unrotated; 1 - clockwise; 2 - upside down; 3 - counterclockwise. The attributes are: con_rotate (r/w) - set rotation of the active console con_rotate_all (w) - set rotation of all consoles rotate (r/w) - set rotation of the framebuffer, if supported. Currently, none of the drivers support this. This is probably temporary, since con_rotate and con_rotate_all are console-specific and has no business being under the fb device. However, until the console layer acquires it's own sysfs class, these attributes will temporarily reside here. Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/console/fbcon.c | 72 +++++++++++++++++++++++++++++++++++++++++++ drivers/video/fbmem.c | 22 +++++++++++++ drivers/video/fbsysfs.c | 67 ++++++++++++++++++++++++++++++++++++++++ include/linux/fb.h | 7 +++++ 4 files changed, 168 insertions(+) (limited to 'include/linux') diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index e829ba18e0a5..e7802ffe549a 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c @@ -193,6 +193,8 @@ static void fbcon_preset_disp(struct fb_info *info, struct fb_var_screeninfo *va int unit); static void fbcon_redraw_move(struct vc_data *vc, struct display *p, int line, int count, int dy); +static void fbcon_modechanged(struct fb_info *info); +static void fbcon_set_all_vcs(struct fb_info *info); #ifdef CONFIG_MAC /* @@ -218,6 +220,51 @@ static inline void fbcon_set_rotation(struct fb_info *info, struct display *p) else ops->rotate = 0; } + +static void fbcon_rotate(struct fb_info *info, u32 rotate) +{ + struct fbcon_ops *ops= info->fbcon_par; + struct fb_info *fb_info; + + if (!ops || ops->currcon == -1) + return; + + fb_info = registered_fb[con2fb_map[ops->currcon]]; + + if (info == fb_info) { + struct display *p = &fb_display[ops->currcon]; + + if (rotate < 4) + p->con_rotate = rotate; + else + p->con_rotate = 0; + + fbcon_modechanged(info); + } +} + +static void fbcon_rotate_all(struct fb_info *info, u32 rotate) +{ + struct fbcon_ops *ops = info->fbcon_par; + struct vc_data *vc; + struct display *p; + int i; + + if (!ops || ops->currcon < 0 || rotate > 3) + return; + + for (i = 0; i < MAX_NR_CONSOLES; i++) { + vc = vc_cons[i].d; + if (!vc || vc->vc_mode != KD_TEXT || + registered_fb[con2fb_map[i]] != info) + continue; + + p = &fb_display[vc->vc_num]; + p->con_rotate = rotate; + } + + fbcon_set_all_vcs(info); +} #else static inline void fbcon_set_rotation(struct fb_info *info, struct display *p) { @@ -225,8 +272,25 @@ static inline void fbcon_set_rotation(struct fb_info *info, struct display *p) ops->rotate = FB_ROTATE_UR; } + +static void fbcon_rotate(struct fb_info *info, u32 rotate) +{ + return; +} + +static void fbcon_rotate_all(struct fb_info *info, u32 rotate) +{ + return; +} #endif /* CONFIG_FRAMEBUFFER_CONSOLE_ROTATION */ +static int fbcon_get_rotate(struct fb_info *info) +{ + struct fbcon_ops *ops = info->fbcon_par; + + return (ops) ? ops->rotate : 0; +} + static inline int fbcon_is_inactive(struct vc_data *vc, struct fb_info *info) { struct fbcon_ops *ops = info->fbcon_par; @@ -2864,6 +2928,14 @@ static int fbcon_event_notify(struct notifier_block *self, case FB_EVENT_NEW_MODELIST: fbcon_new_modelist(info); break; + case FB_EVENT_SET_CON_ROTATE: + fbcon_rotate(info, *(int *)event->data); + break; + case FB_EVENT_GET_CON_ROTATE: + ret = fbcon_get_rotate(info); + break; + case FB_EVENT_SET_CON_ROTATE_ALL: + fbcon_rotate_all(info, *(int *)event->data); } return ret; diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 7a2a8fa50b3b..81b6cd23ea1d 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1319,6 +1319,28 @@ int fb_new_modelist(struct fb_info *info) return err; } +/** + * fb_con_duit - user<->fbcon passthrough + * @info: struct fb_info + * @event: notification event to be passed to fbcon + * @data: private data + * + * DESCRIPTION + * This function is an fbcon-user event passing channel + * which bypasses fbdev. This is hopefully temporary + * until a user interface for fbcon is created + */ +int fb_con_duit(struct fb_info *info, int event, void *data) +{ + struct fb_event evnt; + + evnt.info = info; + evnt.data = data; + + return notifier_call_chain(&fb_notifier_list, event, &evnt); +} +EXPORT_SYMBOL(fb_con_duit); + static char *video_options[FB_MAX]; static int ofonly; diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index 007c8e9b2b39..08dac9580d15 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c @@ -213,6 +213,70 @@ static ssize_t show_bpp(struct class_device *class_device, char *buf) return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.bits_per_pixel); } +static ssize_t store_rotate(struct class_device *class_device, const char *buf, + size_t count) +{ + struct fb_info *fb_info = class_get_devdata(class_device); + struct fb_var_screeninfo var; + char **last = NULL; + int err; + + var = fb_info->var; + var.rotate = simple_strtoul(buf, last, 0); + + if ((err = activate(fb_info, &var))) + return err; + + return count; +} + + +static ssize_t show_rotate(struct class_device *class_device, char *buf) +{ + struct fb_info *fb_info = class_get_devdata(class_device); + + return snprintf(buf, PAGE_SIZE, "%d\n", fb_info->var.rotate); +} + +static ssize_t store_con_rotate(struct class_device *class_device, + const char *buf, size_t count) +{ + struct fb_info *fb_info = class_get_devdata(class_device); + int rotate; + char **last = NULL; + + acquire_console_sem(); + rotate = simple_strtoul(buf, last, 0); + fb_con_duit(fb_info, FB_EVENT_SET_CON_ROTATE, &rotate); + release_console_sem(); + return count; +} + +static ssize_t store_con_rotate_all(struct class_device *class_device, + const char *buf, size_t count) +{ + struct fb_info *fb_info = class_get_devdata(class_device); + int rotate; + char **last = NULL; + + acquire_console_sem(); + rotate = simple_strtoul(buf, last, 0); + fb_con_duit(fb_info, FB_EVENT_SET_CON_ROTATE_ALL, &rotate); + release_console_sem(); + return count; +} + +static ssize_t show_con_rotate(struct class_device *class_device, char *buf) +{ + struct fb_info *fb_info = class_get_devdata(class_device); + int rotate; + + acquire_console_sem(); + rotate = fb_con_duit(fb_info, FB_EVENT_GET_CON_ROTATE, NULL); + release_console_sem(); + return snprintf(buf, PAGE_SIZE, "%d\n", rotate); +} + static ssize_t store_virtual(struct class_device *class_device, const char * buf, size_t count) { @@ -440,6 +504,9 @@ static struct class_device_attribute class_device_attrs[] = { __ATTR(virtual_size, S_IRUGO|S_IWUSR, show_virtual, store_virtual), __ATTR(name, S_IRUGO, show_name, NULL), __ATTR(stride, S_IRUGO, show_stride, NULL), + __ATTR(rotate, S_IRUGO|S_IWUSR, show_rotate, store_rotate), + __ATTR(con_rotate, S_IRUGO|S_IWUSR, show_con_rotate, store_con_rotate), + __ATTR(con_rotate_all, S_IWUSR, NULL, store_con_rotate_all), }; int fb_init_class_device(struct fb_info *fb_info) diff --git a/include/linux/fb.h b/include/linux/fb.h index 357dd3a0a01e..04a58f33ec53 100644 --- a/include/linux/fb.h +++ b/include/linux/fb.h @@ -508,6 +508,12 @@ struct fb_cursor_user { /* The resolution of the passed in fb_info about to change and all vc's should be changed */ #define FB_EVENT_MODE_CHANGE_ALL 0x0A +/* CONSOLE-SPECIFIC: set console rotation */ +#define FB_EVENT_SET_CON_ROTATE 0x0B +/* CONSOLE-SPECIFIC: get console rotation */ +#define FB_EVENT_GET_CON_ROTATE 0x0C +/* CONSOLE-SPECIFIC: rotate all consoles */ +#define FB_EVENT_SET_CON_ROTATE_ALL 0x0D struct fb_event { struct fb_info *info; @@ -836,6 +842,7 @@ extern int fb_get_color_depth(struct fb_var_screeninfo *var, struct fb_fix_screeninfo *fix); extern int fb_get_options(char *name, char **option); extern int fb_new_modelist(struct fb_info *info); +extern int fb_con_duit(struct fb_info *info, int event, void *data); extern struct fb_info *registered_fb[FB_MAX]; extern int num_registered_fb; -- cgit v1.2.3 From c7f82d9c49e763f40f7ea7126a2c9f067bfde71f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 8 Nov 2005 21:39:19 -0800 Subject: [PATCH] fbdev: move ioctl32 code to fbmem.c The frame buffer layer already had some code dealing with compat ioctls, this patch moves over the remaining code from fs/compat_ioctl.c Signed-off-by: Arnd Bergmann Signed-off-by: Antonino Daplas Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/fbmem.c | 147 +++++++++++++++++++++++++++++++++++++++++-- fs/compat_ioctl.c | 143 ----------------------------------------- include/linux/compat_ioctl.h | 7 --- 3 files changed, 142 insertions(+), 155 deletions(-) (limited to 'include/linux') diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 81b6cd23ea1d..9f180096c896 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -14,6 +14,7 @@ #include #include +#include #include #include #include @@ -933,18 +934,154 @@ fb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, } #ifdef CONFIG_COMPAT +struct fb_fix_screeninfo32 { + char id[16]; + compat_caddr_t smem_start; + u32 smem_len; + u32 type; + u32 type_aux; + u32 visual; + u16 xpanstep; + u16 ypanstep; + u16 ywrapstep; + u32 line_length; + compat_caddr_t mmio_start; + u32 mmio_len; + u32 accel; + u16 reserved[3]; +}; + +struct fb_cmap32 { + u32 start; + u32 len; + compat_caddr_t red; + compat_caddr_t green; + compat_caddr_t blue; + compat_caddr_t transp; +}; + +static int fb_getput_cmap(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct fb_cmap_user __user *cmap; + struct fb_cmap32 __user *cmap32; + __u32 data; + int err; + + cmap = compat_alloc_user_space(sizeof(*cmap)); + cmap32 = compat_ptr(arg); + + if (copy_in_user(&cmap->start, &cmap32->start, 2 * sizeof(__u32))) + return -EFAULT; + + if (get_user(data, &cmap32->red) || + put_user(compat_ptr(data), &cmap->red) || + get_user(data, &cmap32->green) || + put_user(compat_ptr(data), &cmap->green) || + get_user(data, &cmap32->blue) || + put_user(compat_ptr(data), &cmap->blue) || + get_user(data, &cmap32->transp) || + put_user(compat_ptr(data), &cmap->transp)) + return -EFAULT; + + err = fb_ioctl(inode, file, cmd, (unsigned long) cmap); + + if (!err) { + if (copy_in_user(&cmap32->start, + &cmap->start, + 2 * sizeof(__u32))) + err = -EFAULT; + } + return err; +} + +static int do_fscreeninfo_to_user(struct fb_fix_screeninfo *fix, + struct fb_fix_screeninfo32 __user *fix32) +{ + __u32 data; + int err; + + err = copy_to_user(&fix32->id, &fix->id, sizeof(fix32->id)); + + data = (__u32) (unsigned long) fix->smem_start; + err |= put_user(data, &fix32->smem_start); + + err |= put_user(fix->smem_len, &fix32->smem_len); + err |= put_user(fix->type, &fix32->type); + err |= put_user(fix->type_aux, &fix32->type_aux); + err |= put_user(fix->visual, &fix32->visual); + err |= put_user(fix->xpanstep, &fix32->xpanstep); + err |= put_user(fix->ypanstep, &fix32->ypanstep); + err |= put_user(fix->ywrapstep, &fix32->ywrapstep); + err |= put_user(fix->line_length, &fix32->line_length); + + data = (__u32) (unsigned long) fix->mmio_start; + err |= put_user(data, &fix32->mmio_start); + + err |= put_user(fix->mmio_len, &fix32->mmio_len); + err |= put_user(fix->accel, &fix32->accel); + err |= copy_to_user(fix32->reserved, fix->reserved, + sizeof(fix->reserved)); + + return err; +} + +static int fb_get_fscreeninfo(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + mm_segment_t old_fs; + struct fb_fix_screeninfo fix; + struct fb_fix_screeninfo32 __user *fix32; + int err; + + fix32 = compat_ptr(arg); + + old_fs = get_fs(); + set_fs(KERNEL_DS); + err = fb_ioctl(inode, file, cmd, (unsigned long) &fix); + set_fs(old_fs); + + if (!err) + err = do_fscreeninfo_to_user(&fix, fix32); + + return err; +} + static long fb_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - int fbidx = iminor(file->f_dentry->d_inode); + struct inode *inode = file->f_dentry->d_inode; + int fbidx = iminor(inode); struct fb_info *info = registered_fb[fbidx]; struct fb_ops *fb = info->fbops; - long ret; + long ret = -ENOIOCTLCMD; - if (fb->fb_compat_ioctl == NULL) - return -ENOIOCTLCMD; lock_kernel(); - ret = fb->fb_compat_ioctl(file, cmd, arg, info); + switch(cmd) { + case FBIOGET_VSCREENINFO: + case FBIOPUT_VSCREENINFO: + case FBIOPAN_DISPLAY: + case FBIOGET_CON2FBMAP: + case FBIOPUT_CON2FBMAP: + arg = (unsigned long) compat_ptr(arg); + case FBIOBLANK: + ret = fb_ioctl(inode, file, cmd, arg); + break; + + case FBIOGET_FSCREENINFO: + ret = fb_get_fscreeninfo(inode, file, cmd, arg); + break; + + case FBIOGETCMAP: + case FBIOPUTCMAP: + ret = fb_getput_cmap(inode, file, cmd, arg); + break; + + default: + if (fb->fb_compat_ioctl) + ret = fb->fb_compat_ioctl(file, cmd, arg, info); + break; + } unlock_kernel(); return ret; } diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 71c9d45c0624..26300fccb4fc 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c @@ -840,146 +840,6 @@ static int hdio_getgeo(unsigned int fd, unsigned int cmd, unsigned long arg) return err ? -EFAULT : 0; } -struct fb_fix_screeninfo32 { - char id[16]; - compat_caddr_t smem_start; - u32 smem_len; - u32 type; - u32 type_aux; - u32 visual; - u16 xpanstep; - u16 ypanstep; - u16 ywrapstep; - u32 line_length; - compat_caddr_t mmio_start; - u32 mmio_len; - u32 accel; - u16 reserved[3]; -}; - -struct fb_cmap32 { - u32 start; - u32 len; - compat_caddr_t red; - compat_caddr_t green; - compat_caddr_t blue; - compat_caddr_t transp; -}; - -static int fb_getput_cmap(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - struct fb_cmap_user __user *cmap; - struct fb_cmap32 __user *cmap32; - __u32 data; - int err; - - cmap = compat_alloc_user_space(sizeof(*cmap)); - cmap32 = compat_ptr(arg); - - if (copy_in_user(&cmap->start, &cmap32->start, 2 * sizeof(__u32))) - return -EFAULT; - - if (get_user(data, &cmap32->red) || - put_user(compat_ptr(data), &cmap->red) || - get_user(data, &cmap32->green) || - put_user(compat_ptr(data), &cmap->green) || - get_user(data, &cmap32->blue) || - put_user(compat_ptr(data), &cmap->blue) || - get_user(data, &cmap32->transp) || - put_user(compat_ptr(data), &cmap->transp)) - return -EFAULT; - - err = sys_ioctl(fd, cmd, (unsigned long) cmap); - - if (!err) { - if (copy_in_user(&cmap32->start, - &cmap->start, - 2 * sizeof(__u32))) - err = -EFAULT; - } - return err; -} - -static int do_fscreeninfo_to_user(struct fb_fix_screeninfo *fix, - struct fb_fix_screeninfo32 __user *fix32) -{ - __u32 data; - int err; - - err = copy_to_user(&fix32->id, &fix->id, sizeof(fix32->id)); - - data = (__u32) (unsigned long) fix->smem_start; - err |= put_user(data, &fix32->smem_start); - - err |= put_user(fix->smem_len, &fix32->smem_len); - err |= put_user(fix->type, &fix32->type); - err |= put_user(fix->type_aux, &fix32->type_aux); - err |= put_user(fix->visual, &fix32->visual); - err |= put_user(fix->xpanstep, &fix32->xpanstep); - err |= put_user(fix->ypanstep, &fix32->ypanstep); - err |= put_user(fix->ywrapstep, &fix32->ywrapstep); - err |= put_user(fix->line_length, &fix32->line_length); - - data = (__u32) (unsigned long) fix->mmio_start; - err |= put_user(data, &fix32->mmio_start); - - err |= put_user(fix->mmio_len, &fix32->mmio_len); - err |= put_user(fix->accel, &fix32->accel); - err |= copy_to_user(fix32->reserved, fix->reserved, - sizeof(fix->reserved)); - - return err; -} - -static int fb_get_fscreeninfo(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - mm_segment_t old_fs; - struct fb_fix_screeninfo fix; - struct fb_fix_screeninfo32 __user *fix32; - int err; - - fix32 = compat_ptr(arg); - - old_fs = get_fs(); - set_fs(KERNEL_DS); - err = sys_ioctl(fd, cmd, (unsigned long) &fix); - set_fs(old_fs); - - if (!err) - err = do_fscreeninfo_to_user(&fix, fix32); - - return err; -} - -static int fb_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) -{ - int err; - - switch (cmd) { - case FBIOGET_FSCREENINFO: - err = fb_get_fscreeninfo(fd,cmd, arg); - break; - - case FBIOGETCMAP: - case FBIOPUTCMAP: - err = fb_getput_cmap(fd, cmd, arg); - break; - - default: - do { - static int count; - if (++count <= 20) - printk("%s: Unknown fb ioctl cmd fd(%d) " - "cmd(%08x) arg(%08lx)\n", - __FUNCTION__, fd, cmd, arg); - } while(0); - err = -ENOSYS; - break; - }; - - return err; -} - static int hdio_ioctl_trans(unsigned int fd, unsigned int cmd, unsigned long arg) { mm_segment_t old_fs = get_fs(); @@ -2953,10 +2813,7 @@ HANDLE_IOCTL(BLKGETSIZE, w_long) HANDLE_IOCTL(0x1260, broken_blkgetsize) HANDLE_IOCTL(BLKFRAGET, w_long) HANDLE_IOCTL(BLKSECTGET, w_long) -HANDLE_IOCTL(FBIOGET_FSCREENINFO, fb_ioctl_trans) HANDLE_IOCTL(BLKPG, blkpg_ioctl_trans) -HANDLE_IOCTL(FBIOGETCMAP, fb_ioctl_trans) -HANDLE_IOCTL(FBIOPUTCMAP, fb_ioctl_trans) HANDLE_IOCTL(HDIO_GET_KEEPSETTINGS, hdio_ioctl_trans) HANDLE_IOCTL(HDIO_GET_UNMASKINTR, hdio_ioctl_trans) HANDLE_IOCTL(HDIO_GET_DMA, hdio_ioctl_trans) diff --git a/include/linux/compat_ioctl.h b/include/linux/compat_ioctl.h index 4c63c2963019..2209ad3499a3 100644 --- a/include/linux/compat_ioctl.h +++ b/include/linux/compat_ioctl.h @@ -56,13 +56,6 @@ ULONG_IOCTL(TIOCSCTTY) COMPATIBLE_IOCTL(TIOCGPTN) COMPATIBLE_IOCTL(TIOCSPTLCK) COMPATIBLE_IOCTL(TIOCSERGETLSR) -/* Big F */ -COMPATIBLE_IOCTL(FBIOBLANK) -COMPATIBLE_IOCTL(FBIOGET_VSCREENINFO) -COMPATIBLE_IOCTL(FBIOPUT_VSCREENINFO) -COMPATIBLE_IOCTL(FBIOPAN_DISPLAY) -COMPATIBLE_IOCTL(FBIOGET_CON2FBMAP) -COMPATIBLE_IOCTL(FBIOPUT_CON2FBMAP) /* Little f */ COMPATIBLE_IOCTL(FIOCLEX) COMPATIBLE_IOCTL(FIONCLEX) -- cgit v1.2.3 From 4e5314b56a7ea11c7a5f2b8418992b2f49648a25 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2005 21:39:22 -0800 Subject: [PATCH] md: better handling of readerrors with raid5. This patch changes the behaviour of raid5 when it gets a read error. Instead of just failing the device, it tried to find out what should have been there, and writes it over the bad block. For some media-errors, this has a reasonable chance of fixing the error. If the write succeeds, and a subsequent read succeeds as well, raid5 decided the address is OK and conitnues. Instead of failing a drive on read-error, we attempt to re-write the block, and then re-read. If that all works, we allow the device to remain in the array. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/raid5.c | 61 ++++++++++++++++++++++++++++++++++++++++++---- include/linux/raid/raid5.h | 2 ++ 2 files changed, 58 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 1223e98ecd70..8cf1ae8b8a71 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -349,7 +349,7 @@ static void shrink_stripes(raid5_conf_t *conf) conf->slab_cache = NULL; } -static int raid5_end_read_request (struct bio * bi, unsigned int bytes_done, +static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done, int error) { struct stripe_head *sh = bi->bi_private; @@ -401,10 +401,27 @@ static int raid5_end_read_request (struct bio * bi, unsigned int bytes_done, } #else set_bit(R5_UPTODATE, &sh->dev[i].flags); -#endif +#endif + if (test_bit(R5_ReadError, &sh->dev[i].flags)) { + printk("R5: read error corrected!!\n"); + clear_bit(R5_ReadError, &sh->dev[i].flags); + clear_bit(R5_ReWrite, &sh->dev[i].flags); + } } else { - md_error(conf->mddev, conf->disks[i].rdev); clear_bit(R5_UPTODATE, &sh->dev[i].flags); + if (conf->mddev->degraded) { + printk("R5: read error not correctable.\n"); + clear_bit(R5_ReadError, &sh->dev[i].flags); + clear_bit(R5_ReWrite, &sh->dev[i].flags); + md_error(conf->mddev, conf->disks[i].rdev); + } else if (test_bit(R5_ReWrite, &sh->dev[i].flags)) { + /* Oh, no!!! */ + printk("R5: read error NOT corrected!!\n"); + clear_bit(R5_ReadError, &sh->dev[i].flags); + clear_bit(R5_ReWrite, &sh->dev[i].flags); + md_error(conf->mddev, conf->disks[i].rdev); + } else + set_bit(R5_ReadError, &sh->dev[i].flags); } rdev_dec_pending(conf->disks[i].rdev, conf->mddev); #if 0 @@ -966,6 +983,12 @@ static void handle_stripe(struct stripe_head *sh) if (dev->written) written++; rdev = conf->disks[i].rdev; /* FIXME, should I be looking rdev */ if (!rdev || !rdev->in_sync) { + /* The ReadError flag wil just be confusing now */ + clear_bit(R5_ReadError, &dev->flags); + clear_bit(R5_ReWrite, &dev->flags); + } + if (!rdev || !rdev->in_sync + || test_bit(R5_ReadError, &dev->flags)) { failed++; failed_num = i; } else @@ -980,6 +1003,14 @@ static void handle_stripe(struct stripe_head *sh) if (failed > 1 && to_read+to_write+written) { for (i=disks; i--; ) { int bitmap_end = 0; + + if (test_bit(R5_ReadError, &sh->dev[i].flags)) { + mdk_rdev_t *rdev = conf->disks[i].rdev; + if (rdev && rdev->in_sync) + /* multiple read failures in one stripe */ + md_error(conf->mddev, rdev); + } + spin_lock_irq(&conf->device_lock); /* fail all writes first */ bi = sh->dev[i].towrite; @@ -1015,7 +1046,8 @@ static void handle_stripe(struct stripe_head *sh) } /* fail any reads if this device is non-operational */ - if (!test_bit(R5_Insync, &sh->dev[i].flags)) { + if (!test_bit(R5_Insync, &sh->dev[i].flags) || + test_bit(R5_ReadError, &sh->dev[i].flags)) { bi = sh->dev[i].toread; sh->dev[i].toread = NULL; if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags)) @@ -1274,7 +1306,26 @@ static void handle_stripe(struct stripe_head *sh) md_done_sync(conf->mddev, STRIPE_SECTORS,1); clear_bit(STRIPE_SYNCING, &sh->state); } - + + /* If the failed drive is just a ReadError, then we might need to progress + * the repair/check process + */ + if (failed == 1 && test_bit(R5_ReadError, &sh->dev[failed_num].flags) + && !test_bit(R5_LOCKED, &sh->dev[failed_num].flags) + && test_bit(R5_UPTODATE, &sh->dev[failed_num].flags) + ) { + dev = &sh->dev[failed_num]; + if (!test_bit(R5_ReWrite, &dev->flags)) { + set_bit(R5_Wantwrite, &dev->flags); + set_bit(R5_ReWrite, &dev->flags); + set_bit(R5_LOCKED, &dev->flags); + } else { + /* let's read it back */ + set_bit(R5_Wantread, &dev->flags); + set_bit(R5_LOCKED, &dev->flags); + } + } + spin_unlock(&sh->lock); while ((bi=return_bi)) { diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h index 176fc653c284..f025ba6fb14c 100644 --- a/include/linux/raid/raid5.h +++ b/include/linux/raid/raid5.h @@ -154,6 +154,8 @@ struct stripe_head { #define R5_Wantwrite 5 #define R5_Syncio 6 /* this io need to be accounted as resync io */ #define R5_Overlap 7 /* There is a pending overlapping request on this block */ +#define R5_ReadError 8 /* seen a read error here recently */ +#define R5_ReWrite 9 /* have tried to over-write the readerror */ /* * Write method -- cgit v1.2.3 From eae1701fbd264cfc7efbaf7cd4cd999760070e27 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2005 21:39:23 -0800 Subject: [PATCH] md: initial sysfs support for md Start using kobjects in mddevs, and provide a couple of simple attributes (level and disks). Attributes live in /sys/block/mdX/md/attr-name Signed-off-by: Neil Brown Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++- include/linux/raid/md_k.h | 2 ++ 2 files changed, 87 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/drivers/md/md.c b/drivers/md/md.c index 9ecf51ee596f..a68ad8547325 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -181,7 +181,7 @@ static void mddev_put(mddev_t *mddev) if (!mddev->raid_disks && list_empty(&mddev->disks)) { list_del(&mddev->all_mddevs); blk_put_queue(mddev->queue); - kfree(mddev); + kobject_unregister(&mddev->kobj); } spin_unlock(&all_mddevs_lock); } @@ -1551,6 +1551,85 @@ static void analyze_sbs(mddev_t * mddev) } +struct md_sysfs_entry { + struct attribute attr; + ssize_t (*show)(mddev_t *, char *); + ssize_t (*store)(mddev_t *, const char *, size_t); +}; + +static ssize_t +md_show_level(mddev_t *mddev, char *page) +{ + mdk_personality_t *p = mddev->pers; + if (p == NULL) + return 0; + if (mddev->level >= 0) + return sprintf(page, "RAID-%d\n", mddev->level); + else + return sprintf(page, "%s\n", p->name); +} + +static struct md_sysfs_entry md_level = { + .attr = {.name = "level", .mode = S_IRUGO }, + .show = md_show_level, +}; + +static ssize_t +md_show_rdisks(mddev_t *mddev, char *page) +{ + return sprintf(page, "%d\n", mddev->raid_disks); +} + +static struct md_sysfs_entry md_raid_disks = { + .attr = {.name = "raid_disks", .mode = S_IRUGO }, + .show = md_show_rdisks, +}; + +static struct attribute *md_default_attrs[] = { + &md_level.attr, + &md_raid_disks.attr, + NULL, +}; + +static ssize_t +md_attr_show(struct kobject *kobj, struct attribute *attr, char *page) +{ + struct md_sysfs_entry *entry = container_of(attr, struct md_sysfs_entry, attr); + mddev_t *mddev = container_of(kobj, struct mddev_s, kobj); + + if (!entry->show) + return -EIO; + return entry->show(mddev, page); +} + +static ssize_t +md_attr_store(struct kobject *kobj, struct attribute *attr, + const char *page, size_t length) +{ + struct md_sysfs_entry *entry = container_of(attr, struct md_sysfs_entry, attr); + mddev_t *mddev = container_of(kobj, struct mddev_s, kobj); + + if (!entry->store) + return -EIO; + return entry->store(mddev, page, length); +} + +static void md_free(struct kobject *ko) +{ + mddev_t *mddev = container_of(ko, mddev_t, kobj); + kfree(mddev); +} + +static struct sysfs_ops md_sysfs_ops = { + .show = md_attr_show, + .store = md_attr_store, +}; +static struct kobj_type md_ktype = { + .release = md_free, + .sysfs_ops = &md_sysfs_ops, + .default_attrs = md_default_attrs, +}; + int mdp_major = 0; static struct kobject *md_probe(dev_t dev, int *part, void *data) @@ -1592,6 +1671,11 @@ static struct kobject *md_probe(dev_t dev, int *part, void *data) add_disk(disk); mddev->gendisk = disk; up(&disks_sem); + mddev->kobj.parent = kobject_get(&disk->kobj); + mddev->kobj.k_name = NULL; + snprintf(mddev->kobj.name, KOBJ_NAME_LEN, "%s", "md"); + mddev->kobj.ktype = &md_ktype; + kobject_register(&mddev->kobj); return NULL; } diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index ebce949b1443..a9b0e47a3d04 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -148,6 +148,8 @@ struct mddev_s struct gendisk *gendisk; + struct kobject kobj; + /* Superblock information */ int major_version, minor_version, -- cgit v1.2.3 From 86e6ffdd243a06663713e637ee683fb27dce8e0c Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2005 21:39:24 -0800 Subject: [PATCH] md: extend md sysfs support to component devices. Each device in an md array how has a corresponding /sys/block/mdX/md/devNN/ directory which can contain attributes. Currently there is only 'state' which summarises the state, nd 'super' which has a copy of the superblock, and 'block' which is a symlink to the block device. Also, /sys/block/mdX/md/rdNN represents slot 'NN' in the array, and is a symlink to the relevant 'devNN'. Obviously spare devices do not have a slot in the array, and so don't have such a symlink. Signed-off-by: Neil Brown Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 168 +++++++++++++++++++++++++++++++++++++++++++--- include/linux/raid/md_k.h | 2 + 2 files changed, 162 insertions(+), 8 deletions(-) (limited to 'include/linux') diff --git a/drivers/md/md.c b/drivers/md/md.c index a68ad8547325..74520b50c307 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -711,6 +711,7 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) */ int i; int active=0, working=0,failed=0,spare=0,nr_disks=0; + unsigned int fixdesc=0; rdev->sb_size = MD_SB_BYTES; @@ -758,16 +759,28 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) sb->disks[0].state = (1<raid_disk >= 0 && rdev2->in_sync && !rdev2->faulty) - rdev2->desc_nr = rdev2->raid_disk; + desc_nr = rdev2->raid_disk; else - rdev2->desc_nr = next_spare++; + desc_nr = next_spare++; + if (desc_nr != rdev2->desc_nr) { + fixdesc |= (1 << desc_nr); + rdev2->desc_nr = desc_nr; + if (rdev2->raid_disk >= 0) { + char nm[20]; + sprintf(nm, "rd%d", rdev2->raid_disk); + sysfs_remove_link(&mddev->kobj, nm); + } + sysfs_remove_link(&rdev2->kobj, "block"); + kobject_del(&rdev2->kobj); + } d = &sb->disks[rdev2->desc_nr]; nr_disks++; d->number = rdev2->desc_nr; d->major = MAJOR(rdev2->bdev->bd_dev); d->minor = MINOR(rdev2->bdev->bd_dev); - if (rdev2->raid_disk >= 0 && rdev->in_sync && !rdev2->faulty) + if (rdev2->raid_disk >= 0 && rdev2->in_sync && !rdev2->faulty) d->raid_disk = rdev2->raid_disk; else d->raid_disk = rdev2->desc_nr; /* compatibility */ @@ -787,7 +800,22 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) if (test_bit(WriteMostly, &rdev2->flags)) d->state |= (1<desc_nr)) { + snprintf(rdev2->kobj.name, KOBJ_NAME_LEN, "dev%d", + rdev2->desc_nr); + kobject_add(&rdev2->kobj); + sysfs_create_link(&rdev2->kobj, + &rdev2->bdev->bd_disk->kobj, + "block"); + if (rdev2->raid_disk >= 0) { + char nm[20]; + sprintf(nm, "rd%d", rdev2->raid_disk); + sysfs_create_link(&mddev->kobj, + &rdev2->kobj, nm); + } + } /* now set the "removed" and "faulty" bits on any missing devices */ for (i=0 ; i < mddev->raid_disks ; i++) { mdp_disk_t *d = &sb->disks[i]; @@ -1147,6 +1175,13 @@ static int bind_rdev_to_array(mdk_rdev_t * rdev, mddev_t * mddev) list_add(&rdev->same_set, &mddev->disks); rdev->mddev = mddev; printk(KERN_INFO "md: bind<%s>\n", bdevname(rdev->bdev,b)); + + rdev->kobj.k_name = NULL; + snprintf(rdev->kobj.name, KOBJ_NAME_LEN, "dev%d", rdev->desc_nr); + rdev->kobj.parent = kobject_get(&mddev->kobj); + kobject_add(&rdev->kobj); + + sysfs_create_link(&rdev->kobj, &rdev->bdev->bd_disk->kobj, "block"); return 0; } @@ -1160,6 +1195,8 @@ static void unbind_rdev_from_array(mdk_rdev_t * rdev) list_del_init(&rdev->same_set); printk(KERN_INFO "md: unbind<%s>\n", bdevname(rdev->bdev,b)); rdev->mddev = NULL; + sysfs_remove_link(&rdev->kobj, "block"); + kobject_del(&rdev->kobj); } /* @@ -1215,7 +1252,7 @@ static void export_rdev(mdk_rdev_t * rdev) md_autodetect_dev(rdev->bdev->bd_dev); #endif unlock_rdev(rdev); - kfree(rdev); + kobject_put(&rdev->kobj); } static void kick_rdev_from_array(mdk_rdev_t * rdev) @@ -1414,6 +1451,94 @@ repeat: } +struct rdev_sysfs_entry { + struct attribute attr; + ssize_t (*show)(mdk_rdev_t *, char *); + ssize_t (*store)(mdk_rdev_t *, const char *, size_t); +}; + +static ssize_t +rdev_show_state(mdk_rdev_t *rdev, char *page) +{ + char *sep = ""; + int len=0; + + if (rdev->faulty) { + len+= sprintf(page+len, "%sfaulty",sep); + sep = ","; + } + if (rdev->in_sync) { + len += sprintf(page+len, "%sin_sync",sep); + sep = ","; + } + if (!rdev->faulty && !rdev->in_sync) { + len += sprintf(page+len, "%sspare", sep); + sep = ","; + } + return len+sprintf(page+len, "\n"); +} + +static struct rdev_sysfs_entry rdev_state = { + .attr = {.name = "state", .mode = S_IRUGO }, + .show = rdev_show_state, +}; + +static ssize_t +rdev_show_super(mdk_rdev_t *rdev, char *page) +{ + if (rdev->sb_loaded && rdev->sb_size) { + memcpy(page, page_address(rdev->sb_page), rdev->sb_size); + return rdev->sb_size; + } else + return 0; +} +static struct rdev_sysfs_entry rdev_super = { + .attr = {.name = "super", .mode = S_IRUGO }, + .show = rdev_show_super, +}; +static struct attribute *rdev_default_attrs[] = { + &rdev_state.attr, + &rdev_super.attr, + NULL, +}; +static ssize_t +rdev_attr_show(struct kobject *kobj, struct attribute *attr, char *page) +{ + struct rdev_sysfs_entry *entry = container_of(attr, struct rdev_sysfs_entry, attr); + mdk_rdev_t *rdev = container_of(kobj, mdk_rdev_t, kobj); + + if (!entry->show) + return -EIO; + return entry->show(rdev, page); +} + +static ssize_t +rdev_attr_store(struct kobject *kobj, struct attribute *attr, + const char *page, size_t length) +{ + struct rdev_sysfs_entry *entry = container_of(attr, struct rdev_sysfs_entry, attr); + mdk_rdev_t *rdev = container_of(kobj, mdk_rdev_t, kobj); + + if (!entry->store) + return -EIO; + return entry->store(rdev, page, length); +} + +static void rdev_free(struct kobject *ko) +{ + mdk_rdev_t *rdev = container_of(ko, mdk_rdev_t, kobj); + kfree(rdev); +} +static struct sysfs_ops rdev_sysfs_ops = { + .show = rdev_attr_show, + .store = rdev_attr_store, +}; +static struct kobj_type rdev_ktype = { + .release = rdev_free, + .sysfs_ops = &rdev_sysfs_ops, + .default_attrs = rdev_default_attrs, +}; + /* * Import a device. If 'super_format' >= 0, then sanity check the superblock * @@ -1445,6 +1570,10 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi if (err) goto abort_free; + rdev->kobj.parent = NULL; + rdev->kobj.ktype = &rdev_ktype; + kobject_init(&rdev->kobj); + rdev->desc_nr = -1; rdev->faulty = 0; rdev->in_sync = 0; @@ -1820,6 +1949,13 @@ static int do_md_run(mddev_t * mddev) mddev->safemode_timer.data = (unsigned long) mddev; mddev->safemode_delay = (20 * HZ)/1000 +1; /* 20 msec delay */ mddev->in_sync = 1; + + ITERATE_RDEV(mddev,rdev,tmp) + if (rdev->raid_disk >= 0) { + char nm[20]; + sprintf(nm, "rd%d", rdev->raid_disk); + sysfs_create_link(&mddev->kobj, &rdev->kobj, nm); + } set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); md_wakeup_thread(mddev->thread); @@ -1941,9 +2077,18 @@ static int do_md_stop(mddev_t * mddev, int ro) * Free resources if final stop */ if (!ro) { + mdk_rdev_t *rdev; + struct list_head *tmp; struct gendisk *disk; printk(KERN_INFO "md: %s stopped.\n", mdname(mddev)); + ITERATE_RDEV(mddev,rdev,tmp) + if (rdev->raid_disk >= 0) { + char nm[20]; + sprintf(nm, "rd%d", rdev->raid_disk); + sysfs_remove_link(&mddev->kobj, nm); + } + export_array(mddev); mddev->array_size = 0; @@ -3962,17 +4107,24 @@ void md_check_recovery(mddev_t *mddev) if (rdev->raid_disk >= 0 && (rdev->faulty || ! rdev->in_sync) && atomic_read(&rdev->nr_pending)==0) { - if (mddev->pers->hot_remove_disk(mddev, rdev->raid_disk)==0) + if (mddev->pers->hot_remove_disk(mddev, rdev->raid_disk)==0) { + char nm[20]; + sprintf(nm,"rd%d", rdev->raid_disk); + sysfs_remove_link(&mddev->kobj, nm); rdev->raid_disk = -1; + } } if (mddev->degraded) { ITERATE_RDEV(mddev,rdev,rtmp) if (rdev->raid_disk < 0 && !rdev->faulty) { - if (mddev->pers->hot_add_disk(mddev,rdev)) + if (mddev->pers->hot_add_disk(mddev,rdev)) { + char nm[20]; + sprintf(nm, "rd%d", rdev->raid_disk); + sysfs_create_link(&mddev->kobj, &rdev->kobj, nm); spares++; - else + } else break; } } diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index a9b0e47a3d04..d1dad32ebe07 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -105,6 +105,8 @@ struct mdk_rdev_s int sb_size; /* bytes in the superblock */ int preferred_minor; /* autorun support */ + struct kobject kobj; + /* A device can be in one of three states based on two flags: * Not working: faulty==1 in_sync==0 * Fully working: faulty==0 in_sync==1 -- cgit v1.2.3 From 3f294f4fb6f2ba887b717674da26c21f3d57f3fc Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2005 21:39:25 -0800 Subject: [PATCH] md: add kobject/sysfs support to raid5 /sys/block/mdX/md/raid5/ contains raid5-related attributes. Currently stripe_cache_size is number of entries in stripe cache, and is settable. stripe_cache_active is number of active entries, and in only readable. Signed-off-by: Neil Brown Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/raid5.c | 183 +++++++++++++++++++++++++++++++++++++-------- include/linux/raid/raid5.h | 1 + 2 files changed, 152 insertions(+), 32 deletions(-) (limited to 'include/linux') diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 8cf1ae8b8a71..121fbaa9ed59 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -293,9 +293,31 @@ static struct stripe_head *get_active_stripe(raid5_conf_t *conf, sector_t sector return sh; } -static int grow_stripes(raid5_conf_t *conf, int num) +static int grow_one_stripe(raid5_conf_t *conf) { struct stripe_head *sh; + sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL); + if (!sh) + return 0; + memset(sh, 0, sizeof(*sh) + (conf->raid_disks-1)*sizeof(struct r5dev)); + sh->raid_conf = conf; + spin_lock_init(&sh->lock); + + if (grow_buffers(sh, conf->raid_disks)) { + shrink_buffers(sh, conf->raid_disks); + kmem_cache_free(conf->slab_cache, sh); + return 0; + } + /* we just created an active stripe so... */ + atomic_set(&sh->count, 1); + atomic_inc(&conf->active_stripes); + INIT_LIST_HEAD(&sh->lru); + release_stripe(sh); + return 1; +} + +static int grow_stripes(raid5_conf_t *conf, int num) +{ kmem_cache_t *sc; int devs = conf->raid_disks; @@ -308,43 +330,34 @@ static int grow_stripes(raid5_conf_t *conf, int num) return 1; conf->slab_cache = sc; while (num--) { - sh = kmem_cache_alloc(sc, GFP_KERNEL); - if (!sh) - return 1; - memset(sh, 0, sizeof(*sh) + (devs-1)*sizeof(struct r5dev)); - sh->raid_conf = conf; - spin_lock_init(&sh->lock); - - if (grow_buffers(sh, conf->raid_disks)) { - shrink_buffers(sh, conf->raid_disks); - kmem_cache_free(sc, sh); + if (!grow_one_stripe(conf)) return 1; - } - /* we just created an active stripe so... */ - atomic_set(&sh->count, 1); - atomic_inc(&conf->active_stripes); - INIT_LIST_HEAD(&sh->lru); - release_stripe(sh); } return 0; } -static void shrink_stripes(raid5_conf_t *conf) +static int drop_one_stripe(raid5_conf_t *conf) { struct stripe_head *sh; - while (1) { - spin_lock_irq(&conf->device_lock); - sh = get_free_stripe(conf); - spin_unlock_irq(&conf->device_lock); - if (!sh) - break; - if (atomic_read(&sh->count)) - BUG(); - shrink_buffers(sh, conf->raid_disks); - kmem_cache_free(conf->slab_cache, sh); - atomic_dec(&conf->active_stripes); - } + spin_lock_irq(&conf->device_lock); + sh = get_free_stripe(conf); + spin_unlock_irq(&conf->device_lock); + if (!sh) + return 0; + if (atomic_read(&sh->count)) + BUG(); + shrink_buffers(sh, conf->raid_disks); + kmem_cache_free(conf->slab_cache, sh); + atomic_dec(&conf->active_stripes); + return 1; +} + +static void shrink_stripes(raid5_conf_t *conf) +{ + while (drop_one_stripe(conf)) + ; + kmem_cache_destroy(conf->slab_cache); conf->slab_cache = NULL; } @@ -1714,6 +1727,108 @@ static void raid5d (mddev_t *mddev) PRINTK("--- raid5d inactive\n"); } +struct raid5_sysfs_entry { + struct attribute attr; + ssize_t (*show)(raid5_conf_t *, char *); + ssize_t (*store)(raid5_conf_t *, const char *, ssize_t); +}; + +static ssize_t +raid5_show_stripe_cache_size(raid5_conf_t *conf, char *page) +{ + return sprintf(page, "%d\n", conf->max_nr_stripes); +} + +static ssize_t +raid5_store_stripe_cache_size(raid5_conf_t *conf, const char *page, ssize_t len) +{ + char *end; + int new; + if (len >= PAGE_SIZE) + return -EINVAL; + + new = simple_strtoul(page, &end, 10); + if (!*page || (*end && *end != '\n') ) + return -EINVAL; + if (new <= 16 || new > 32768) + return -EINVAL; + while (new < conf->max_nr_stripes) { + if (drop_one_stripe(conf)) + conf->max_nr_stripes--; + else + break; + } + while (new > conf->max_nr_stripes) { + if (grow_one_stripe(conf)) + conf->max_nr_stripes++; + else break; + } + return len; +} +static struct raid5_sysfs_entry raid5_stripecache_size = { + .attr = {.name = "stripe_cache_size", .mode = S_IRUGO | S_IWUSR }, + .show = raid5_show_stripe_cache_size, + .store = raid5_store_stripe_cache_size, +}; + +static ssize_t +raid5_show_stripe_cache_active(raid5_conf_t *conf, char *page) +{ + return sprintf(page, "%d\n", atomic_read(&conf->active_stripes)); +} + +static struct raid5_sysfs_entry raid5_stripecache_active = { + .attr = {.name = "stripe_cache_active", .mode = S_IRUGO}, + .show = raid5_show_stripe_cache_active, +}; + +static struct attribute *raid5_default_attrs[] = { + &raid5_stripecache_size.attr, + &raid5_stripecache_active.attr, + NULL, +}; + +static ssize_t +raid5_attr_show(struct kobject *kobj, struct attribute *attr, char *page) +{ + struct raid5_sysfs_entry *entry = container_of(attr, struct raid5_sysfs_entry, attr); + raid5_conf_t *conf = container_of(kobj, raid5_conf_t, kobj); + + if (!entry->show) + return -EIO; + return entry->show(conf, page); +} + +static ssize_t +raid5_attr_store(struct kobject *kobj, struct attribute *attr, + const char *page, size_t length) +{ + struct raid5_sysfs_entry *entry = container_of(attr, struct raid5_sysfs_entry, attr); + raid5_conf_t *conf = container_of(kobj, raid5_conf_t, kobj); + + if (!entry->store) + return -EIO; + return entry->store(conf, page, length); +} + +static void raid5_free(struct kobject *ko) +{ + raid5_conf_t *conf = container_of(ko, raid5_conf_t, kobj); + kfree(conf); +} + + +static struct sysfs_ops raid5_sysfs_ops = { + .show = raid5_attr_show, + .store = raid5_attr_store, +}; + +static struct kobj_type raid5_ktype = { + .release = raid5_free, + .sysfs_ops = &raid5_sysfs_ops, + .default_attrs = raid5_default_attrs, +}; + static int run(mddev_t *mddev) { raid5_conf_t *conf; @@ -1855,6 +1970,10 @@ memory = conf->max_nr_stripes * (sizeof(struct stripe_head) + } /* Ok, everything is just fine now */ + conf->kobj.parent = kobject_get(&mddev->kobj); + strcpy(conf->kobj.name, "raid5"); + conf->kobj.ktype = &raid5_ktype; + kobject_register(&conf->kobj); if (mddev->bitmap) mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ; @@ -1879,7 +1998,7 @@ abort: -static int stop (mddev_t *mddev) +static int stop(mddev_t *mddev) { raid5_conf_t *conf = (raid5_conf_t *) mddev->private; @@ -1888,7 +2007,7 @@ static int stop (mddev_t *mddev) shrink_stripes(conf); free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER); blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ - kfree(conf); + kobject_unregister(&conf->kobj); mddev->private = NULL; return 0; } diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h index f025ba6fb14c..5f4e945c8083 100644 --- a/include/linux/raid/raid5.h +++ b/include/linux/raid/raid5.h @@ -228,6 +228,7 @@ struct raid5_private_data { * Cleared when a sync completes. */ + struct kobject kobj; /* * Free stripes pool */ -- cgit v1.2.3 From 24dd469d728dae07f40c5d79ea6dedd38cdf1a30 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2005 21:39:26 -0800 Subject: [PATCH] md: allow a manual resync with md You can trigger a 'check' with echo check > /sys/block/mdX/md/scan_mode or a check-and-repair errors with echo repair > /sys/block/mdX/md/scan_mode and read the current state from the same file. Note: personalities need to know the different between 'check' and 'repair', but don't yet. Until they do, 'check' will be the same as 'repair' and will just do a normal resync pass. Signed-off-by: Neil Brown Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 77 +++++++++++++++++++++++++++++++++++++++++------ include/linux/raid/md_k.h | 4 +++ 2 files changed, 72 insertions(+), 9 deletions(-) (limited to 'include/linux') diff --git a/drivers/md/md.c b/drivers/md/md.c index 74520b50c307..37400873b879 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1714,9 +1714,60 @@ static struct md_sysfs_entry md_raid_disks = { .show = md_show_rdisks, }; +static ssize_t +md_show_scan(mddev_t *mddev, char *page) +{ + char *type = "none"; + if (mddev->recovery & + ((1<recovery & (1<recovery)) + type = "resync"; + else if (test_bit(MD_RECOVERY_CHECK, &mddev->recovery)) + type = "check"; + else + type = "repair"; + } else + type = "recover"; + } + return sprintf(page, "%s\n", type); +} + +static ssize_t +md_store_scan(mddev_t *mddev, const char *page, size_t len) +{ + int canscan=0; + if (mddev->recovery & + ((1<reconfig_sem); + if (mddev->pers && mddev->pers->sync_request) + canscan=1; + up(&mddev->reconfig_sem); + if (!canscan) + return -EINVAL; + + if (strcmp(page, "check")==0 || strcmp(page, "check\n")==0) + set_bit(MD_RECOVERY_CHECK, &mddev->recovery); + else if (strcmp(page, "repair")!=0 && strcmp(page, "repair\n")!=0) + return -EINVAL; + set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery); + set_bit(MD_RECOVERY_SYNC, &mddev->recovery); + set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + md_wakeup_thread(mddev->thread); + return len; +} + +static struct md_sysfs_entry md_scan_mode = { + .attr = {.name = "scan_mode", .mode = S_IRUGO|S_IWUSR }, + .show = md_show_scan, + .store = md_store_scan, +}; + static struct attribute *md_default_attrs[] = { &md_level.attr, &md_raid_disks.attr, + &md_scan_mode.attr, NULL, }; @@ -3855,7 +3906,8 @@ static void md_do_sync(mddev_t *mddev) is_mddev_idle(mddev); /* this also initializes IO event counters */ /* we don't use the checkpoint if there's a bitmap */ - if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && !mddev->bitmap) + if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery) && !mddev->bitmap + && ! test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) j = mddev->recovery_cp; else j = 0; @@ -4093,9 +4145,13 @@ void md_check_recovery(mddev_t *mddev) set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); goto unlock; } - if (mddev->recovery) - /* probably just the RECOVERY_NEEDED flag */ - mddev->recovery = 0; + /* Clear some bits that don't mean anything, but + * might be left set + */ + clear_bit(MD_RECOVERY_NEEDED, &mddev->recovery); + clear_bit(MD_RECOVERY_ERR, &mddev->recovery); + clear_bit(MD_RECOVERY_INTR, &mddev->recovery); + clear_bit(MD_RECOVERY_DONE, &mddev->recovery); /* no recovery is running. * remove any failed drives, then @@ -4129,14 +4185,17 @@ void md_check_recovery(mddev_t *mddev) } } - if (!spares && (mddev->recovery_cp == MaxSector )) { - /* nothing we can do ... */ + if (spares) { + clear_bit(MD_RECOVERY_SYNC, &mddev->recovery); + clear_bit(MD_RECOVERY_CHECK, &mddev->recovery); + } else if (mddev->recovery_cp < MaxSector) { + set_bit(MD_RECOVERY_SYNC, &mddev->recovery); + } else if (!test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) + /* nothing to be done ... */ goto unlock; - } + if (mddev->pers->sync_request) { set_bit(MD_RECOVERY_RUNNING, &mddev->recovery); - if (!spares) - set_bit(MD_RECOVERY_SYNC, &mddev->recovery); if (spares && mddev->bitmap && ! mddev->bitmap->file) { /* We are adding a device or devices to an array * which has the bitmap stored on all devices. diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index d1dad32ebe07..efd04dca0abd 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -182,6 +182,8 @@ struct mddev_s * ERR: and IO error was detected - abort the resync/recovery * INTR: someone requested a (clean) early abort. * DONE: thread is done and is waiting to be reaped + * REQUEST: user-space has requested a sync (used with SYNC) + * CHECK: user-space request for for check-only, no repair */ #define MD_RECOVERY_RUNNING 0 #define MD_RECOVERY_SYNC 1 @@ -189,6 +191,8 @@ struct mddev_s #define MD_RECOVERY_INTR 3 #define MD_RECOVERY_DONE 4 #define MD_RECOVERY_NEEDED 5 +#define MD_RECOVERY_REQUESTED 6 +#define MD_RECOVERY_CHECK 7 unsigned long recovery; int in_sync; /* know to not need resync */ -- cgit v1.2.3 From 9d88883e68f404d5581bd391713ceef470ea53a9 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2005 21:39:26 -0800 Subject: [PATCH] md: teach raid5 the difference between 'check' and 'repair'. With this, raid5 can be asked to check parity without repairing it. It also keeps a count of the number of incorrect parity blocks found (mismatches) and reports them through sysfs. Signed-off-by: Neil Brown Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 18 ++++++++++++++++-- drivers/md/raid5.c | 5 +++++ include/linux/raid/md_k.h | 4 ++++ 3 files changed, 25 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/drivers/md/md.c b/drivers/md/md.c index 37400873b879..e58d61d9f31b 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1758,16 +1758,29 @@ md_store_scan(mddev_t *mddev, const char *page, size_t len) return len; } +static ssize_t +md_show_mismatch(mddev_t *mddev, char *page) +{ + return sprintf(page, "%llu\n", + (unsigned long long) mddev->resync_mismatches); +} + static struct md_sysfs_entry md_scan_mode = { .attr = {.name = "scan_mode", .mode = S_IRUGO|S_IWUSR }, .show = md_show_scan, .store = md_store_scan, }; +static struct md_sysfs_entry md_mismatches = { + .attr = {.name = "mismatch_cnt", .mode = S_IRUGO }, + .show = md_show_mismatch, +}; + static struct attribute *md_default_attrs[] = { &md_level.attr, &md_raid_disks.attr, &md_scan_mode.attr, + &md_mismatches.attr, NULL, }; @@ -3888,12 +3901,13 @@ static void md_do_sync(mddev_t *mddev) } } while (mddev->curr_resync < 2); - if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) + if (test_bit(MD_RECOVERY_SYNC, &mddev->recovery)) { /* resync follows the size requested by the personality, * which defaults to physical size, but can be virtual size */ max_sectors = mddev->resync_max_sectors; - else + mddev->resync_mismatches = 0; + } else /* recovery follows the physical size of devices */ max_sectors = mddev->size << 1; diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 121fbaa9ed59..ce154553aca5 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1292,6 +1292,11 @@ static void handle_stripe(struct stripe_head *sh) !memcmp(pagea, pagea+4, STRIPE_SIZE-4)) { /* parity is correct (on disc, not in buffer any more) */ set_bit(STRIPE_INSYNC, &sh->state); + } else { + conf->mddev->resync_mismatches += STRIPE_SECTORS; + if (test_bit(MD_RECOVERY_CHECK, &conf->mddev->recovery)) + /* don't try to repair!! */ + set_bit(STRIPE_INSYNC, &sh->state); } } if (!test_bit(STRIPE_INSYNC, &sh->state)) { diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index efd04dca0abd..cb8b44d1588b 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -175,6 +175,10 @@ struct mddev_s sector_t resync_mark_cnt;/* blocks written at resync_mark */ sector_t resync_max_sectors; /* may be set by personality */ + + sector_t resync_mismatches; /* count of sectors where + * parity/replica mismatch found + */ /* recovery/resync flags * NEEDED: we might need to start a resync/recover * RUNNING: a thread is running, or about to be started -- cgit v1.2.3 From 007583c9253fed363a0bd71b039e9b40a0f6855e Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2005 21:39:30 -0800 Subject: [PATCH] md: change raid5 sysfs attribute to not create a new directory There isn't really a need for raid5 attributes to be an a subdirectory, so this patch moves them from /sys/block/mdX/md/raid5/attribute to /sys/block/mdX/md/attribute This suggests that all md personalities should co-operate about namespace usage, but that shouldn't be a problem. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 6 ---- drivers/md/raid5.c | 72 ++++++++++------------------------------------ include/linux/raid/md_k.h | 7 +++++ include/linux/raid/raid5.h | 1 - 4 files changed, 22 insertions(+), 64 deletions(-) (limited to 'include/linux') diff --git a/drivers/md/md.c b/drivers/md/md.c index 013f2f27589c..3db5c3513072 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1683,12 +1683,6 @@ static void analyze_sbs(mddev_t * mddev) } -struct md_sysfs_entry { - struct attribute attr; - ssize_t (*show)(mddev_t *, char *); - ssize_t (*store)(mddev_t *, const char *, size_t); -}; - static ssize_t md_show_level(mddev_t *mddev, char *page) { diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 246c9b1cc4a3..08a1620b9f8c 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -1732,21 +1732,17 @@ static void raid5d (mddev_t *mddev) PRINTK("--- raid5d inactive\n"); } -struct raid5_sysfs_entry { - struct attribute attr; - ssize_t (*show)(raid5_conf_t *, char *); - ssize_t (*store)(raid5_conf_t *, const char *, ssize_t); -}; - static ssize_t -raid5_show_stripe_cache_size(raid5_conf_t *conf, char *page) +raid5_show_stripe_cache_size(mddev_t *mddev, char *page) { + raid5_conf_t *conf = mddev_to_conf(mddev); return sprintf(page, "%d\n", conf->max_nr_stripes); } static ssize_t -raid5_store_stripe_cache_size(raid5_conf_t *conf, const char *page, ssize_t len) +raid5_store_stripe_cache_size(mddev_t *mddev, const char *page, size_t len) { + raid5_conf_t *conf = mddev_to_conf(mddev); char *end; int new; if (len >= PAGE_SIZE) @@ -1770,68 +1766,33 @@ raid5_store_stripe_cache_size(raid5_conf_t *conf, const char *page, ssize_t len) } return len; } -static struct raid5_sysfs_entry raid5_stripecache_size = { + +static struct md_sysfs_entry raid5_stripecache_size = { .attr = {.name = "stripe_cache_size", .mode = S_IRUGO | S_IWUSR }, .show = raid5_show_stripe_cache_size, .store = raid5_store_stripe_cache_size, }; static ssize_t -raid5_show_stripe_cache_active(raid5_conf_t *conf, char *page) +raid5_show_stripe_cache_active(mddev_t *mddev, char *page) { + raid5_conf_t *conf = mddev_to_conf(mddev); return sprintf(page, "%d\n", atomic_read(&conf->active_stripes)); } -static struct raid5_sysfs_entry raid5_stripecache_active = { +static struct md_sysfs_entry raid5_stripecache_active = { .attr = {.name = "stripe_cache_active", .mode = S_IRUGO}, .show = raid5_show_stripe_cache_active, }; -static struct attribute *raid5_default_attrs[] = { +static struct attribute *raid5_attrs[] = { &raid5_stripecache_size.attr, &raid5_stripecache_active.attr, NULL, }; - -static ssize_t -raid5_attr_show(struct kobject *kobj, struct attribute *attr, char *page) -{ - struct raid5_sysfs_entry *entry = container_of(attr, struct raid5_sysfs_entry, attr); - raid5_conf_t *conf = container_of(kobj, raid5_conf_t, kobj); - - if (!entry->show) - return -EIO; - return entry->show(conf, page); -} - -static ssize_t -raid5_attr_store(struct kobject *kobj, struct attribute *attr, - const char *page, size_t length) -{ - struct raid5_sysfs_entry *entry = container_of(attr, struct raid5_sysfs_entry, attr); - raid5_conf_t *conf = container_of(kobj, raid5_conf_t, kobj); - - if (!entry->store) - return -EIO; - return entry->store(conf, page, length); -} - -static void raid5_free(struct kobject *ko) -{ - raid5_conf_t *conf = container_of(ko, raid5_conf_t, kobj); - kfree(conf); -} - - -static struct sysfs_ops raid5_sysfs_ops = { - .show = raid5_attr_show, - .store = raid5_attr_store, -}; - -static struct kobj_type raid5_ktype = { - .release = raid5_free, - .sysfs_ops = &raid5_sysfs_ops, - .default_attrs = raid5_default_attrs, +static struct attribute_group raid5_attrs_group = { + .name = NULL, + .attrs = raid5_attrs, }; static int run(mddev_t *mddev) @@ -1975,10 +1936,7 @@ memory = conf->max_nr_stripes * (sizeof(struct stripe_head) + } /* Ok, everything is just fine now */ - conf->kobj.parent = &mddev->kobj; - strcpy(conf->kobj.name, "raid5"); - conf->kobj.ktype = &raid5_ktype; - kobject_register(&conf->kobj); + sysfs_create_group(&mddev->kobj, &raid5_attrs_group); if (mddev->bitmap) mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ; @@ -2012,7 +1970,7 @@ static int stop(mddev_t *mddev) shrink_stripes(conf); free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER); blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ - kobject_unregister(&conf->kobj); + sysfs_remove_group(&mddev->kobj, &raid5_attrs_group); mddev->private = NULL; return 0; } diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index cb8b44d1588b..4169c11e5451 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -282,6 +282,13 @@ struct mdk_personality_s }; +struct md_sysfs_entry { + struct attribute attr; + ssize_t (*show)(mddev_t *, char *); + ssize_t (*store)(mddev_t *, const char *, size_t); +}; + + static inline char * mdname (mddev_t * mddev) { return mddev->gendisk ? mddev->gendisk->disk_name : "mdX"; diff --git a/include/linux/raid/raid5.h b/include/linux/raid/raid5.h index 5f4e945c8083..f025ba6fb14c 100644 --- a/include/linux/raid/raid5.h +++ b/include/linux/raid/raid5.h @@ -228,7 +228,6 @@ struct raid5_private_data { * Cleared when a sync completes. */ - struct kobject kobj; /* * Free stripes pool */ -- cgit v1.2.3 From ba22dcbf106338a5c46d6979f9b19564faae3d49 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2005 21:39:31 -0800 Subject: [PATCH] md: improvements to raid5 handling of read errors Two refinements to the 'attempt-overwrite-on-read-error' mechanism. 1/ If the array is read-only, don't attempt an over-write. 2/ If there are more than max_nr_stripes read errors on a device with no success, fail the drive. This will make sure a dead drive will be eventually kicked even when we aren't trying to rewrite (which would normally kick a dead drive more quickly. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 1 + drivers/md/raid5.c | 25 +++++++++++++++++-------- include/linux/raid/md_k.h | 3 +++ 3 files changed, 21 insertions(+), 8 deletions(-) (limited to 'include/linux') diff --git a/drivers/md/md.c b/drivers/md/md.c index 3db5c3513072..3fb80397f8aa 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -1582,6 +1582,7 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi rdev->in_sync = 0; rdev->data_offset = 0; atomic_set(&rdev->nr_pending, 0); + atomic_set(&rdev->read_errors, 0); size = rdev->bdev->bd_inode->i_size >> BLOCK_SIZE_BITS; if (!size) { diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 08a1620b9f8c..77610b98d4e0 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -420,21 +420,29 @@ static int raid5_end_read_request(struct bio * bi, unsigned int bytes_done, clear_bit(R5_ReadError, &sh->dev[i].flags); clear_bit(R5_ReWrite, &sh->dev[i].flags); } + if (atomic_read(&conf->disks[i].rdev->read_errors)) + atomic_set(&conf->disks[i].rdev->read_errors, 0); } else { + int retry = 0; clear_bit(R5_UPTODATE, &sh->dev[i].flags); - if (conf->mddev->degraded) { + atomic_inc(&conf->disks[i].rdev->read_errors); + if (conf->mddev->degraded) printk("R5: read error not correctable.\n"); - clear_bit(R5_ReadError, &sh->dev[i].flags); - clear_bit(R5_ReWrite, &sh->dev[i].flags); - md_error(conf->mddev, conf->disks[i].rdev); - } else if (test_bit(R5_ReWrite, &sh->dev[i].flags)) { + else if (test_bit(R5_ReWrite, &sh->dev[i].flags)) /* Oh, no!!! */ printk("R5: read error NOT corrected!!\n"); + else if (atomic_read(&conf->disks[i].rdev->read_errors) + > conf->max_nr_stripes) + printk("raid5: Too many read errors, failing device.\n"); + else + retry = 1; + if (retry) + set_bit(R5_ReadError, &sh->dev[i].flags); + else { clear_bit(R5_ReadError, &sh->dev[i].flags); clear_bit(R5_ReWrite, &sh->dev[i].flags); md_error(conf->mddev, conf->disks[i].rdev); - } else - set_bit(R5_ReadError, &sh->dev[i].flags); + } } rdev_dec_pending(conf->disks[i].rdev, conf->mddev); #if 0 @@ -1328,7 +1336,8 @@ static void handle_stripe(struct stripe_head *sh) /* If the failed drive is just a ReadError, then we might need to progress * the repair/check process */ - if (failed == 1 && test_bit(R5_ReadError, &sh->dev[failed_num].flags) + if (failed == 1 && ! conf->mddev->ro && + test_bit(R5_ReadError, &sh->dev[failed_num].flags) && !test_bit(R5_LOCKED, &sh->dev[failed_num].flags) && test_bit(R5_UPTODATE, &sh->dev[failed_num].flags) ) { diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index 4169c11e5451..200c69e34fc0 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -134,6 +134,9 @@ struct mdk_rdev_s * only maintained for arrays that * support hot removal */ + atomic_t read_errors; /* number of consecutive read errors that + * we have tried to ignore. + */ }; typedef struct mdk_personality_s mdk_personality_t; -- cgit v1.2.3 From b2d444d7ad975d555bb919601bcdc0e58975a40e Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2005 21:39:31 -0800 Subject: [PATCH] md: convert 'faulty' and 'in_sync' fields to bits in 'flags' field This has the advantage of removing the confusion caused by 'rdev_t' and 'mddev_t' both having 'in_sync' fields. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/bitmap.c | 6 ++-- drivers/md/md.c | 92 +++++++++++++++++++++++------------------------ drivers/md/multipath.c | 23 ++++++------ drivers/md/raid1.c | 52 +++++++++++++-------------- drivers/md/raid10.c | 41 ++++++++++----------- drivers/md/raid5.c | 36 +++++++++---------- drivers/md/raid6main.c | 32 ++++++++--------- include/linux/raid/md_k.h | 8 ++--- 8 files changed, 146 insertions(+), 144 deletions(-) (limited to 'include/linux') diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index e59694bc5758..c5fa4c2a5af1 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -271,7 +271,8 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, unsigned long inde return ERR_PTR(-ENOMEM); ITERATE_RDEV(mddev, rdev, tmp) { - if (! rdev->in_sync || rdev->faulty) + if (! test_bit(In_sync, &rdev->flags) + || test_bit(Faulty, &rdev->flags)) continue; target = (rdev->sb_offset << 1) + offset + index * (PAGE_SIZE/512); @@ -291,7 +292,8 @@ static int write_sb_page(mddev_t *mddev, long offset, struct page *page, int wai struct list_head *tmp; ITERATE_RDEV(mddev, rdev, tmp) - if (rdev->in_sync && !rdev->faulty) + if (test_bit(In_sync, &rdev->flags) + && !test_bit(Faulty, &rdev->flags)) md_super_write(mddev, rdev, (rdev->sb_offset<<1) + offset + page->index * (PAGE_SIZE/512), diff --git a/drivers/md/md.c b/drivers/md/md.c index 3fb80397f8aa..9dfa063d1c6a 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -610,7 +610,7 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev) mdp_super_t *sb = (mdp_super_t *)page_address(rdev->sb_page); rdev->raid_disk = -1; - rdev->in_sync = 0; + rdev->flags = 0; if (mddev->raid_disks == 0) { mddev->major_version = 0; mddev->minor_version = sb->minor_version; @@ -671,21 +671,19 @@ static int super_90_validate(mddev_t *mddev, mdk_rdev_t *rdev) return 0; if (mddev->level != LEVEL_MULTIPATH) { - rdev->faulty = 0; - rdev->flags = 0; desc = sb->disks + rdev->desc_nr; if (desc->state & (1<faulty = 1; + set_bit(Faulty, &rdev->flags); else if (desc->state & (1<raid_disk < mddev->raid_disks) { - rdev->in_sync = 1; + set_bit(In_sync, &rdev->flags); rdev->raid_disk = desc->raid_disk; } if (desc->state & (1<flags); } else /* MULTIPATH are always insync */ - rdev->in_sync = 1; + set_bit(In_sync, &rdev->flags); return 0; } @@ -761,7 +759,8 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) ITERATE_RDEV(mddev,rdev2,tmp) { mdp_disk_t *d; int desc_nr; - if (rdev2->raid_disk >= 0 && rdev2->in_sync && !rdev2->faulty) + if (rdev2->raid_disk >= 0 && test_bit(In_sync, &rdev2->flags) + && !test_bit(Faulty, &rdev2->flags)) desc_nr = rdev2->raid_disk; else desc_nr = next_spare++; @@ -780,14 +779,15 @@ static void super_90_sync(mddev_t *mddev, mdk_rdev_t *rdev) d->number = rdev2->desc_nr; d->major = MAJOR(rdev2->bdev->bd_dev); d->minor = MINOR(rdev2->bdev->bd_dev); - if (rdev2->raid_disk >= 0 && rdev2->in_sync && !rdev2->faulty) + if (rdev2->raid_disk >= 0 && test_bit(In_sync, &rdev2->flags) + && !test_bit(Faulty, &rdev2->flags)) d->raid_disk = rdev2->raid_disk; else d->raid_disk = rdev2->desc_nr; /* compatibility */ - if (rdev2->faulty) { + if (test_bit(Faulty, &rdev2->flags)) { d->state = (1<in_sync) { + } else if (test_bit(In_sync, &rdev2->flags)) { d->state = (1<state |= (1<sb_page); rdev->raid_disk = -1; - rdev->in_sync = 0; + rdev->flags = 0; if (mddev->raid_disks == 0) { mddev->major_version = 1; mddev->patch_version = 0; @@ -1027,22 +1027,19 @@ static int super_1_validate(mddev_t *mddev, mdk_rdev_t *rdev) role = le16_to_cpu(sb->dev_roles[rdev->desc_nr]); switch(role) { case 0xffff: /* spare */ - rdev->faulty = 0; break; case 0xfffe: /* faulty */ - rdev->faulty = 1; + set_bit(Faulty, &rdev->flags); break; default: - rdev->in_sync = 1; - rdev->faulty = 0; + set_bit(In_sync, &rdev->flags); rdev->raid_disk = role; break; } - rdev->flags = 0; if (sb->devflags & WriteMostly1) set_bit(WriteMostly, &rdev->flags); } else /* MULTIPATH are always insync */ - rdev->in_sync = 1; + set_bit(In_sync, &rdev->flags); return 0; } @@ -1086,9 +1083,9 @@ static void super_1_sync(mddev_t *mddev, mdk_rdev_t *rdev) ITERATE_RDEV(mddev,rdev2,tmp) { i = rdev2->desc_nr; - if (rdev2->faulty) + if (test_bit(Faulty, &rdev2->flags)) sb->dev_roles[i] = cpu_to_le16(0xfffe); - else if (rdev2->in_sync) + else if (test_bit(In_sync, &rdev2->flags)) sb->dev_roles[i] = cpu_to_le16(rdev2->raid_disk); else sb->dev_roles[i] = cpu_to_le16(0xffff); @@ -1327,7 +1324,8 @@ static void print_rdev(mdk_rdev_t *rdev) char b[BDEVNAME_SIZE]; printk(KERN_INFO "md: rdev %s, SZ:%08llu F:%d S:%d DN:%u\n", bdevname(rdev->bdev,b), (unsigned long long)rdev->size, - rdev->faulty, rdev->in_sync, rdev->desc_nr); + test_bit(Faulty, &rdev->flags), test_bit(In_sync, &rdev->flags), + rdev->desc_nr); if (rdev->sb_loaded) { printk(KERN_INFO "md: rdev superblock:\n"); print_sb((mdp_super_t*)page_address(rdev->sb_page)); @@ -1421,11 +1419,11 @@ repeat: ITERATE_RDEV(mddev,rdev,tmp) { char b[BDEVNAME_SIZE]; dprintk(KERN_INFO "md: "); - if (rdev->faulty) + if (test_bit(Faulty, &rdev->flags)) dprintk("(skipping faulty "); dprintk("%s ", bdevname(rdev->bdev,b)); - if (!rdev->faulty) { + if (!test_bit(Faulty, &rdev->flags)) { md_super_write(mddev,rdev, rdev->sb_offset<<1, rdev->sb_size, rdev->sb_page); @@ -1466,15 +1464,16 @@ rdev_show_state(mdk_rdev_t *rdev, char *page) char *sep = ""; int len=0; - if (rdev->faulty) { + if (test_bit(Faulty, &rdev->flags)) { len+= sprintf(page+len, "%sfaulty",sep); sep = ","; } - if (rdev->in_sync) { + if (test_bit(In_sync, &rdev->flags)) { len += sprintf(page+len, "%sin_sync",sep); sep = ","; } - if (!rdev->faulty && !rdev->in_sync) { + if (!test_bit(Faulty, &rdev->flags) && + !test_bit(In_sync, &rdev->flags)) { len += sprintf(page+len, "%sspare", sep); sep = ","; } @@ -1578,8 +1577,7 @@ static mdk_rdev_t *md_import_device(dev_t newdev, int super_format, int super_mi kobject_init(&rdev->kobj); rdev->desc_nr = -1; - rdev->faulty = 0; - rdev->in_sync = 0; + rdev->flags = 0; rdev->data_offset = 0; atomic_set(&rdev->nr_pending, 0); atomic_set(&rdev->read_errors, 0); @@ -1670,7 +1668,7 @@ static void analyze_sbs(mddev_t * mddev) if (mddev->level == LEVEL_MULTIPATH) { rdev->desc_nr = i++; rdev->raid_disk = rdev->desc_nr; - rdev->in_sync = 1; + set_bit(In_sync, &rdev->flags); } } @@ -1939,7 +1937,7 @@ static int do_md_run(mddev_t * mddev) /* devices must have minimum size of one chunk */ ITERATE_RDEV(mddev,rdev,tmp) { - if (rdev->faulty) + if (test_bit(Faulty, &rdev->flags)) continue; if (rdev->size < chunk_size / 1024) { printk(KERN_WARNING @@ -1967,7 +1965,7 @@ static int do_md_run(mddev_t * mddev) * Also find largest hardsector size */ ITERATE_RDEV(mddev,rdev,tmp) { - if (rdev->faulty) + if (test_bit(Faulty, &rdev->flags)) continue; sync_blockdev(rdev->bdev); invalidate_bdev(rdev->bdev, 0); @@ -2304,7 +2302,7 @@ static int autostart_array(dev_t startdev) return err; } - if (start_rdev->faulty) { + if (test_bit(Faulty, &start_rdev->flags)) { printk(KERN_WARNING "md: can not autostart based on faulty %s!\n", bdevname(start_rdev->bdev,b)); @@ -2363,11 +2361,11 @@ static int get_array_info(mddev_t * mddev, void __user * arg) nr=working=active=failed=spare=0; ITERATE_RDEV(mddev,rdev,tmp) { nr++; - if (rdev->faulty) + if (test_bit(Faulty, &rdev->flags)) failed++; else { working++; - if (rdev->in_sync) + if (test_bit(In_sync, &rdev->flags)) active++; else spare++; @@ -2458,9 +2456,9 @@ static int get_disk_info(mddev_t * mddev, void __user * arg) info.minor = MINOR(rdev->bdev->bd_dev); info.raid_disk = rdev->raid_disk; info.state = 0; - if (rdev->faulty) + if (test_bit(Faulty, &rdev->flags)) info.state |= (1<in_sync) { + else if (test_bit(In_sync, &rdev->flags)) { info.state |= (1<saved_raid_disk = rdev->raid_disk; - rdev->in_sync = 0; /* just to be sure */ + clear_bit(In_sync, &rdev->flags); /* just to be sure */ if (info->state & (1<flags); @@ -2591,11 +2589,11 @@ static int add_new_disk(mddev_t * mddev, mdu_disk_info_t *info) else rdev->raid_disk = -1; - rdev->faulty = 0; + rdev->flags = 0; + if (rdev->raid_disk < mddev->raid_disks) - rdev->in_sync = (info->state & (1<in_sync = 0; + if (info->state & (1<flags); if (info->state & (1<flags); @@ -2694,14 +2692,14 @@ static int hot_add_disk(mddev_t * mddev, dev_t dev) goto abort_export; } - if (rdev->faulty) { + if (test_bit(Faulty, &rdev->flags)) { printk(KERN_WARNING "md: can not hot-add faulty %s disk to %s!\n", bdevname(rdev->bdev,b), mdname(mddev)); err = -EINVAL; goto abort_export; } - rdev->in_sync = 0; + clear_bit(In_sync, &rdev->flags); rdev->desc_nr = -1; bind_rdev_to_array(rdev, mddev); @@ -3428,7 +3426,7 @@ void md_error(mddev_t *mddev, mdk_rdev_t *rdev) return; } - if (!rdev || rdev->faulty) + if (!rdev || test_bit(Faulty, &rdev->flags)) return; /* dprintk("md_error dev:%s, rdev:(%d:%d), (caller: %p,%p,%p,%p).\n", @@ -3626,7 +3624,7 @@ static int md_seq_show(struct seq_file *seq, void *v) bdevname(rdev->bdev,b), rdev->desc_nr); if (test_bit(WriteMostly, &rdev->flags)) seq_printf(seq, "(W)"); - if (rdev->faulty) { + if (test_bit(Faulty, &rdev->flags)) { seq_printf(seq, "(F)"); continue; } else if (rdev->raid_disk < 0) @@ -4174,7 +4172,7 @@ void md_check_recovery(mddev_t *mddev) */ ITERATE_RDEV(mddev,rdev,rtmp) if (rdev->raid_disk >= 0 && - (rdev->faulty || ! rdev->in_sync) && + (test_bit(Faulty, &rdev->flags) || ! test_bit(In_sync, &rdev->flags)) && atomic_read(&rdev->nr_pending)==0) { if (mddev->pers->hot_remove_disk(mddev, rdev->raid_disk)==0) { char nm[20]; @@ -4187,7 +4185,7 @@ void md_check_recovery(mddev_t *mddev) if (mddev->degraded) { ITERATE_RDEV(mddev,rdev,rtmp) if (rdev->raid_disk < 0 - && !rdev->faulty) { + && !test_bit(Faulty, &rdev->flags)) { if (mddev->pers->hot_add_disk(mddev,rdev)) { char nm[20]; sprintf(nm, "rd%d", rdev->raid_disk); @@ -4347,7 +4345,7 @@ static void autostart_arrays(int part) if (IS_ERR(rdev)) continue; - if (rdev->faulty) { + if (test_bit(Faulty, &rdev->flags)) { MD_BUG(); continue; } diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index ae2c5fd6105d..145cdc5ad008 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c @@ -64,7 +64,7 @@ static int multipath_map (multipath_conf_t *conf) rcu_read_lock(); for (i = 0; i < disks; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->multipaths[i].rdev); - if (rdev && rdev->in_sync) { + if (rdev && test_bit(In_sync, &rdev->flags)) { atomic_inc(&rdev->nr_pending); rcu_read_unlock(); return i; @@ -140,7 +140,8 @@ static void unplug_slaves(mddev_t *mddev) rcu_read_lock(); for (i=0; iraid_disks; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->multipaths[i].rdev); - if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) { + if (rdev && !test_bit(Faulty, &rdev->flags) + && atomic_read(&rdev->nr_pending)) { request_queue_t *r_queue = bdev_get_queue(rdev->bdev); atomic_inc(&rdev->nr_pending); @@ -211,7 +212,7 @@ static void multipath_status (struct seq_file *seq, mddev_t *mddev) for (i = 0; i < conf->raid_disks; i++) seq_printf (seq, "%s", conf->multipaths[i].rdev && - conf->multipaths[i].rdev->in_sync ? "U" : "_"); + test_bit(In_sync, &conf->multipaths[i].rdev->flags) ? "U" : "_"); seq_printf (seq, "]"); } @@ -225,7 +226,7 @@ static int multipath_issue_flush(request_queue_t *q, struct gendisk *disk, rcu_read_lock(); for (i=0; iraid_disks && ret == 0; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->multipaths[i].rdev); - if (rdev && !rdev->faulty) { + if (rdev && !test_bit(Faulty, &rdev->flags)) { struct block_device *bdev = rdev->bdev; request_queue_t *r_queue = bdev_get_queue(bdev); @@ -265,10 +266,10 @@ static void multipath_error (mddev_t *mddev, mdk_rdev_t *rdev) /* * Mark disk as unusable */ - if (!rdev->faulty) { + if (!test_bit(Faulty, &rdev->flags)) { char b[BDEVNAME_SIZE]; - rdev->in_sync = 0; - rdev->faulty = 1; + clear_bit(In_sync, &rdev->flags); + set_bit(Faulty, &rdev->flags); mddev->sb_dirty = 1; conf->working_disks--; printk(KERN_ALERT "multipath: IO failure on %s," @@ -298,7 +299,7 @@ static void print_multipath_conf (multipath_conf_t *conf) tmp = conf->multipaths + i; if (tmp->rdev) printk(" disk%d, o:%d, dev:%s\n", - i,!tmp->rdev->faulty, + i,!test_bit(Faulty, &tmp->rdev->flags), bdevname(tmp->rdev->bdev,b)); } } @@ -330,7 +331,7 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) conf->working_disks++; rdev->raid_disk = path; - rdev->in_sync = 1; + set_bit(In_sync, &rdev->flags); rcu_assign_pointer(p->rdev, rdev); found = 1; } @@ -350,7 +351,7 @@ static int multipath_remove_disk(mddev_t *mddev, int number) rdev = p->rdev; if (rdev) { - if (rdev->in_sync || + if (test_bit(In_sync, &rdev->flags) || atomic_read(&rdev->nr_pending)) { printk(KERN_ERR "hot-remove-disk, slot %d is identified" " but is still operational!\n", number); err = -EBUSY; @@ -482,7 +483,7 @@ static int multipath_run (mddev_t *mddev) mddev->queue->max_sectors > (PAGE_SIZE>>9)) blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); - if (!rdev->faulty) + if (!test_bit(Faulty, &rdev->flags)) conf->working_disks++; } diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index f12fc288f25d..fb6b866c28f5 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -417,11 +417,11 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) new_disk = 0; for (rdev = rcu_dereference(conf->mirrors[new_disk].rdev); - !rdev || !rdev->in_sync + !rdev || !test_bit(In_sync, &rdev->flags) || test_bit(WriteMostly, &rdev->flags); rdev = rcu_dereference(conf->mirrors[++new_disk].rdev)) { - if (rdev && rdev->in_sync) + if (rdev && test_bit(In_sync, &rdev->flags)) wonly_disk = new_disk; if (new_disk == conf->raid_disks - 1) { @@ -435,11 +435,11 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) /* make sure the disk is operational */ for (rdev = rcu_dereference(conf->mirrors[new_disk].rdev); - !rdev || !rdev->in_sync || + !rdev || !test_bit(In_sync, &rdev->flags) || test_bit(WriteMostly, &rdev->flags); rdev = rcu_dereference(conf->mirrors[new_disk].rdev)) { - if (rdev && rdev->in_sync) + if (rdev && test_bit(In_sync, &rdev->flags)) wonly_disk = new_disk; if (new_disk <= 0) @@ -477,7 +477,7 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) rdev = rcu_dereference(conf->mirrors[disk].rdev); if (!rdev || - !rdev->in_sync || + !test_bit(In_sync, &rdev->flags) || test_bit(WriteMostly, &rdev->flags)) continue; @@ -500,7 +500,7 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) if (!rdev) goto retry; atomic_inc(&rdev->nr_pending); - if (!rdev->in_sync) { + if (!test_bit(In_sync, &rdev->flags)) { /* cannot risk returning a device that failed * before we inc'ed nr_pending */ @@ -523,7 +523,7 @@ static void unplug_slaves(mddev_t *mddev) rcu_read_lock(); for (i=0; iraid_disks; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); - if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) { + if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) { request_queue_t *r_queue = bdev_get_queue(rdev->bdev); atomic_inc(&rdev->nr_pending); @@ -557,7 +557,7 @@ static int raid1_issue_flush(request_queue_t *q, struct gendisk *disk, rcu_read_lock(); for (i=0; iraid_disks && ret == 0; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); - if (rdev && !rdev->faulty) { + if (rdev && !test_bit(Faulty, &rdev->flags)) { struct block_device *bdev = rdev->bdev; request_queue_t *r_queue = bdev_get_queue(bdev); @@ -729,9 +729,9 @@ static int make_request(request_queue_t *q, struct bio * bio) rcu_read_lock(); for (i = 0; i < disks; i++) { if ((rdev=rcu_dereference(conf->mirrors[i].rdev)) != NULL && - !rdev->faulty) { + !test_bit(Faulty, &rdev->flags)) { atomic_inc(&rdev->nr_pending); - if (rdev->faulty) { + if (test_bit(Faulty, &rdev->flags)) { atomic_dec(&rdev->nr_pending); r1_bio->bios[i] = NULL; } else @@ -824,7 +824,7 @@ static void status(struct seq_file *seq, mddev_t *mddev) for (i = 0; i < conf->raid_disks; i++) seq_printf(seq, "%s", conf->mirrors[i].rdev && - conf->mirrors[i].rdev->in_sync ? "U" : "_"); + test_bit(In_sync, &conf->mirrors[i].rdev->flags) ? "U" : "_"); seq_printf(seq, "]"); } @@ -840,14 +840,14 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) * next level up know. * else mark the drive as failed */ - if (rdev->in_sync + if (test_bit(In_sync, &rdev->flags) && conf->working_disks == 1) /* * Don't fail the drive, act as though we were just a * normal single drive */ return; - if (rdev->in_sync) { + if (test_bit(In_sync, &rdev->flags)) { mddev->degraded++; conf->working_disks--; /* @@ -855,8 +855,8 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) */ set_bit(MD_RECOVERY_ERR, &mddev->recovery); } - rdev->in_sync = 0; - rdev->faulty = 1; + clear_bit(In_sync, &rdev->flags); + set_bit(Faulty, &rdev->flags); mddev->sb_dirty = 1; printk(KERN_ALERT "raid1: Disk failure on %s, disabling device. \n" " Operation continuing on %d devices\n", @@ -881,7 +881,7 @@ static void print_conf(conf_t *conf) tmp = conf->mirrors + i; if (tmp->rdev) printk(" disk %d, wo:%d, o:%d, dev:%s\n", - i, !tmp->rdev->in_sync, !tmp->rdev->faulty, + i, !test_bit(In_sync, &tmp->rdev->flags), !test_bit(Faulty, &tmp->rdev->flags), bdevname(tmp->rdev->bdev,b)); } } @@ -913,11 +913,11 @@ static int raid1_spare_active(mddev_t *mddev) for (i = 0; i < conf->raid_disks; i++) { tmp = conf->mirrors + i; if (tmp->rdev - && !tmp->rdev->faulty - && !tmp->rdev->in_sync) { + && !test_bit(Faulty, &tmp->rdev->flags) + && !test_bit(In_sync, &tmp->rdev->flags)) { conf->working_disks++; mddev->degraded--; - tmp->rdev->in_sync = 1; + set_bit(In_sync, &tmp->rdev->flags); } } @@ -972,7 +972,7 @@ static int raid1_remove_disk(mddev_t *mddev, int number) print_conf(conf); rdev = p->rdev; if (rdev) { - if (rdev->in_sync || + if (test_bit(In_sync, &rdev->flags) || atomic_read(&rdev->nr_pending)) { err = -EBUSY; goto abort; @@ -1282,11 +1282,11 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i /* make sure disk is operational */ wonly = disk; while (conf->mirrors[disk].rdev == NULL || - !conf->mirrors[disk].rdev->in_sync || + !test_bit(In_sync, &conf->mirrors[disk].rdev->flags) || test_bit(WriteMostly, &conf->mirrors[disk].rdev->flags) ) { if (conf->mirrors[disk].rdev && - conf->mirrors[disk].rdev->in_sync) + test_bit(In_sync, &conf->mirrors[disk].rdev->flags)) wonly = disk; if (disk <= 0) disk = conf->raid_disks; @@ -1333,10 +1333,10 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i bio->bi_rw = READ; bio->bi_end_io = end_sync_read; } else if (conf->mirrors[i].rdev == NULL || - conf->mirrors[i].rdev->faulty) { + test_bit(Faulty, &conf->mirrors[i].rdev->flags)) { still_degraded = 1; continue; - } else if (!conf->mirrors[i].rdev->in_sync || + } else if (!test_bit(In_sync, &conf->mirrors[i].rdev->flags) || sector_nr + RESYNC_SECTORS > mddev->recovery_cp) { bio->bi_rw = WRITE; bio->bi_end_io = end_sync_write; @@ -1478,7 +1478,7 @@ static int run(mddev_t *mddev) blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); disk->head_position = 0; - if (!rdev->faulty && rdev->in_sync) + if (!test_bit(Faulty, &rdev->flags) && test_bit(In_sync, &rdev->flags)) conf->working_disks++; } conf->raid_disks = mddev->raid_disks; @@ -1518,7 +1518,7 @@ static int run(mddev_t *mddev) */ for (j = 0; j < conf->raid_disks && (!conf->mirrors[j].rdev || - !conf->mirrors[j].rdev->in_sync) ; j++) + !test_bit(In_sync, &conf->mirrors[j].rdev->flags)) ; j++) /* nothing */; conf->last_used = j; diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 26114f40bde6..867f06ae33d9 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c @@ -512,7 +512,7 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio) disk = r10_bio->devs[slot].devnum; while ((rdev = rcu_dereference(conf->mirrors[disk].rdev)) == NULL || - !rdev->in_sync) { + !test_bit(In_sync, &rdev->flags)) { slot++; if (slot == conf->copies) { slot = 0; @@ -529,7 +529,7 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio) slot = 0; disk = r10_bio->devs[slot].devnum; while ((rdev=rcu_dereference(conf->mirrors[disk].rdev)) == NULL || - !rdev->in_sync) { + !test_bit(In_sync, &rdev->flags)) { slot ++; if (slot == conf->copies) { disk = -1; @@ -549,7 +549,7 @@ static int read_balance(conf_t *conf, r10bio_t *r10_bio) if ((rdev=rcu_dereference(conf->mirrors[ndisk].rdev)) == NULL || - !rdev->in_sync) + !test_bit(In_sync, &rdev->flags)) continue; if (!atomic_read(&rdev->nr_pending)) { @@ -585,7 +585,7 @@ static void unplug_slaves(mddev_t *mddev) rcu_read_lock(); for (i=0; iraid_disks; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); - if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) { + if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) { request_queue_t *r_queue = bdev_get_queue(rdev->bdev); atomic_inc(&rdev->nr_pending); @@ -616,7 +616,7 @@ static int raid10_issue_flush(request_queue_t *q, struct gendisk *disk, rcu_read_lock(); for (i=0; iraid_disks && ret == 0; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); - if (rdev && !rdev->faulty) { + if (rdev && !test_bit(Faulty, &rdev->flags)) { struct block_device *bdev = rdev->bdev; request_queue_t *r_queue = bdev_get_queue(bdev); @@ -771,7 +771,7 @@ static int make_request(request_queue_t *q, struct bio * bio) int d = r10_bio->devs[i].devnum; mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[d].rdev); if (rdev && - !rdev->faulty) { + !test_bit(Faulty, &rdev->flags)) { atomic_inc(&rdev->nr_pending); r10_bio->devs[i].bio = bio; } else @@ -826,7 +826,7 @@ static void status(struct seq_file *seq, mddev_t *mddev) for (i = 0; i < conf->raid_disks; i++) seq_printf(seq, "%s", conf->mirrors[i].rdev && - conf->mirrors[i].rdev->in_sync ? "U" : "_"); + test_bit(In_sync, &conf->mirrors[i].rdev->flags) ? "U" : "_"); seq_printf(seq, "]"); } @@ -841,7 +841,7 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) * next level up know. * else mark the drive as failed */ - if (rdev->in_sync + if (test_bit(In_sync, &rdev->flags) && conf->working_disks == 1) /* * Don't fail the drive, just return an IO error. @@ -851,7 +851,7 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) * really dead" tests... */ return; - if (rdev->in_sync) { + if (test_bit(In_sync, &rdev->flags)) { mddev->degraded++; conf->working_disks--; /* @@ -859,8 +859,8 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) */ set_bit(MD_RECOVERY_ERR, &mddev->recovery); } - rdev->in_sync = 0; - rdev->faulty = 1; + clear_bit(In_sync, &rdev->flags); + set_bit(Faulty, &rdev->flags); mddev->sb_dirty = 1; printk(KERN_ALERT "raid10: Disk failure on %s, disabling device. \n" " Operation continuing on %d devices\n", @@ -885,7 +885,8 @@ static void print_conf(conf_t *conf) tmp = conf->mirrors + i; if (tmp->rdev) printk(" disk %d, wo:%d, o:%d, dev:%s\n", - i, !tmp->rdev->in_sync, !tmp->rdev->faulty, + i, !test_bit(In_sync, &tmp->rdev->flags), + !test_bit(Faulty, &tmp->rdev->flags), bdevname(tmp->rdev->bdev,b)); } } @@ -938,11 +939,11 @@ static int raid10_spare_active(mddev_t *mddev) for (i = 0; i < conf->raid_disks; i++) { tmp = conf->mirrors + i; if (tmp->rdev - && !tmp->rdev->faulty - && !tmp->rdev->in_sync) { + && !test_bit(Faulty, &tmp->rdev->flags) + && !test_bit(In_sync, &tmp->rdev->flags)) { conf->working_disks++; mddev->degraded--; - tmp->rdev->in_sync = 1; + set_bit(In_sync, &tmp->rdev->flags); } } @@ -1000,7 +1001,7 @@ static int raid10_remove_disk(mddev_t *mddev, int number) print_conf(conf); rdev = p->rdev; if (rdev) { - if (rdev->in_sync || + if (test_bit(In_sync, &rdev->flags) || atomic_read(&rdev->nr_pending)) { err = -EBUSY; goto abort; @@ -1416,7 +1417,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i for (i=0 ; iraid_disks; i++) if (conf->mirrors[i].rdev && - !conf->mirrors[i].rdev->in_sync) { + !test_bit(In_sync, &conf->mirrors[i].rdev->flags)) { /* want to reconstruct this device */ r10bio_t *rb2 = r10_bio; @@ -1437,7 +1438,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i for (j=0; jcopies;j++) { int d = r10_bio->devs[j].devnum; if (conf->mirrors[d].rdev && - conf->mirrors[d].rdev->in_sync) { + test_bit(In_sync, &conf->mirrors[d].rdev->flags)) { /* This is where we read from */ bio = r10_bio->devs[0].bio; bio->bi_next = biolist; @@ -1513,7 +1514,7 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i bio = r10_bio->devs[i].bio; bio->bi_end_io = NULL; if (conf->mirrors[d].rdev == NULL || - conf->mirrors[d].rdev->faulty) + test_bit(Faulty, &conf->mirrors[d].rdev->flags)) continue; atomic_inc(&conf->mirrors[d].rdev->nr_pending); atomic_inc(&r10_bio->remaining); @@ -1699,7 +1700,7 @@ static int run(mddev_t *mddev) mddev->queue->max_sectors = (PAGE_SIZE>>9); disk->head_position = 0; - if (!rdev->faulty && rdev->in_sync) + if (!test_bit(Faulty, &rdev->flags) && test_bit(In_sync, &rdev->flags)) conf->working_disks++; } conf->raid_disks = mddev->raid_disks; diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 77610b98d4e0..d1c488b008af 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c @@ -525,19 +525,19 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) raid5_conf_t *conf = (raid5_conf_t *) mddev->private; PRINTK("raid5: error called\n"); - if (!rdev->faulty) { + if (!test_bit(Faulty, &rdev->flags)) { mddev->sb_dirty = 1; - if (rdev->in_sync) { + if (test_bit(In_sync, &rdev->flags)) { conf->working_disks--; mddev->degraded++; conf->failed_disks++; - rdev->in_sync = 0; + clear_bit(In_sync, &rdev->flags); /* * if recovery was running, make sure it aborts. */ set_bit(MD_RECOVERY_ERR, &mddev->recovery); } - rdev->faulty = 1; + set_bit(Faulty, &rdev->flags); printk (KERN_ALERT "raid5: Disk failure on %s, disabling device." " Operation continuing on %d devices\n", @@ -1003,12 +1003,12 @@ static void handle_stripe(struct stripe_head *sh) } if (dev->written) written++; rdev = conf->disks[i].rdev; /* FIXME, should I be looking rdev */ - if (!rdev || !rdev->in_sync) { + if (!rdev || !test_bit(In_sync, &rdev->flags)) { /* The ReadError flag wil just be confusing now */ clear_bit(R5_ReadError, &dev->flags); clear_bit(R5_ReWrite, &dev->flags); } - if (!rdev || !rdev->in_sync + if (!rdev || !test_bit(In_sync, &rdev->flags) || test_bit(R5_ReadError, &dev->flags)) { failed++; failed_num = i; @@ -1027,7 +1027,7 @@ static void handle_stripe(struct stripe_head *sh) if (test_bit(R5_ReadError, &sh->dev[i].flags)) { mdk_rdev_t *rdev = conf->disks[i].rdev; - if (rdev && rdev->in_sync) + if (rdev && test_bit(In_sync, &rdev->flags)) /* multiple read failures in one stripe */ md_error(conf->mddev, rdev); } @@ -1384,7 +1384,7 @@ static void handle_stripe(struct stripe_head *sh) rcu_read_lock(); rdev = rcu_dereference(conf->disks[i].rdev); - if (rdev && rdev->faulty) + if (rdev && test_bit(Faulty, &rdev->flags)) rdev = NULL; if (rdev) atomic_inc(&rdev->nr_pending); @@ -1458,7 +1458,7 @@ static void unplug_slaves(mddev_t *mddev) rcu_read_lock(); for (i=0; iraid_disks; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev); - if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) { + if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) { request_queue_t *r_queue = bdev_get_queue(rdev->bdev); atomic_inc(&rdev->nr_pending); @@ -1503,7 +1503,7 @@ static int raid5_issue_flush(request_queue_t *q, struct gendisk *disk, rcu_read_lock(); for (i=0; iraid_disks && ret == 0; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev); - if (rdev && !rdev->faulty) { + if (rdev && !test_bit(Faulty, &rdev->flags)) { struct block_device *bdev = rdev->bdev; request_queue_t *r_queue = bdev_get_queue(bdev); @@ -1850,7 +1850,7 @@ static int run(mddev_t *mddev) disk->rdev = rdev; - if (rdev->in_sync) { + if (test_bit(In_sync, &rdev->flags)) { char b[BDEVNAME_SIZE]; printk(KERN_INFO "raid5: device %s operational as raid" " disk %d\n", bdevname(rdev->bdev,b), @@ -2029,7 +2029,7 @@ static void status (struct seq_file *seq, mddev_t *mddev) for (i = 0; i < conf->raid_disks; i++) seq_printf (seq, "%s", conf->disks[i].rdev && - conf->disks[i].rdev->in_sync ? "U" : "_"); + test_bit(In_sync, &conf->disks[i].rdev->flags) ? "U" : "_"); seq_printf (seq, "]"); #if RAID5_DEBUG #define D(x) \ @@ -2056,7 +2056,7 @@ static void print_raid5_conf (raid5_conf_t *conf) tmp = conf->disks + i; if (tmp->rdev) printk(" disk %d, o:%d, dev:%s\n", - i, !tmp->rdev->faulty, + i, !test_bit(Faulty, &tmp->rdev->flags), bdevname(tmp->rdev->bdev,b)); } } @@ -2070,12 +2070,12 @@ static int raid5_spare_active(mddev_t *mddev) for (i = 0; i < conf->raid_disks; i++) { tmp = conf->disks + i; if (tmp->rdev - && !tmp->rdev->faulty - && !tmp->rdev->in_sync) { + && !test_bit(Faulty, &tmp->rdev->flags) + && !test_bit(In_sync, &tmp->rdev->flags)) { mddev->degraded--; conf->failed_disks--; conf->working_disks++; - tmp->rdev->in_sync = 1; + set_bit(In_sync, &tmp->rdev->flags); } } print_raid5_conf(conf); @@ -2092,7 +2092,7 @@ static int raid5_remove_disk(mddev_t *mddev, int number) print_raid5_conf(conf); rdev = p->rdev; if (rdev) { - if (rdev->in_sync || + if (test_bit(In_sync, &rdev->flags) || atomic_read(&rdev->nr_pending)) { err = -EBUSY; goto abort; @@ -2127,7 +2127,7 @@ static int raid5_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) */ for (disk=0; disk < mddev->raid_disks; disk++) if ((p=conf->disks + disk)->rdev == NULL) { - rdev->in_sync = 0; + clear_bit(In_sync, &rdev->flags); rdev->raid_disk = disk; found = 1; if (rdev->saved_raid_disk != disk) diff --git a/drivers/md/raid6main.c b/drivers/md/raid6main.c index 84f3ee01e4c8..eae5a35629c5 100644 --- a/drivers/md/raid6main.c +++ b/drivers/md/raid6main.c @@ -507,19 +507,19 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) raid6_conf_t *conf = (raid6_conf_t *) mddev->private; PRINTK("raid6: error called\n"); - if (!rdev->faulty) { + if (!test_bit(Faulty, &rdev->flags)) { mddev->sb_dirty = 1; - if (rdev->in_sync) { + if (test_bit(In_sync, &rdev->flags)) { conf->working_disks--; mddev->degraded++; conf->failed_disks++; - rdev->in_sync = 0; + clear_bit(In_sync, &rdev->flags); /* * if recovery was running, make sure it aborts. */ set_bit(MD_RECOVERY_ERR, &mddev->recovery); } - rdev->faulty = 1; + set_bit(Faulty, &rdev->flags); printk (KERN_ALERT "raid6: Disk failure on %s, disabling device." " Operation continuing on %d devices\n", @@ -1071,7 +1071,7 @@ static void handle_stripe(struct stripe_head *sh) } if (dev->written) written++; rdev = conf->disks[i].rdev; /* FIXME, should I be looking rdev */ - if (!rdev || !rdev->in_sync) { + if (!rdev || !test_bit(In_sync, &rdev->flags)) { if ( failed < 2 ) failed_num[failed] = i; failed++; @@ -1465,7 +1465,7 @@ static void handle_stripe(struct stripe_head *sh) rcu_read_lock(); rdev = rcu_dereference(conf->disks[i].rdev); - if (rdev && rdev->faulty) + if (rdev && test_bit(Faulty, &rdev->flags)) rdev = NULL; if (rdev) atomic_inc(&rdev->nr_pending); @@ -1539,7 +1539,7 @@ static void unplug_slaves(mddev_t *mddev) rcu_read_lock(); for (i=0; iraid_disks; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev); - if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) { + if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) { request_queue_t *r_queue = bdev_get_queue(rdev->bdev); atomic_inc(&rdev->nr_pending); @@ -1584,7 +1584,7 @@ static int raid6_issue_flush(request_queue_t *q, struct gendisk *disk, rcu_read_lock(); for (i=0; iraid_disks && ret == 0; i++) { mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev); - if (rdev && !rdev->faulty) { + if (rdev && !test_bit(Faulty, &rdev->flags)) { struct block_device *bdev = rdev->bdev; request_queue_t *r_queue = bdev_get_queue(bdev); @@ -1868,7 +1868,7 @@ static int run(mddev_t *mddev) disk->rdev = rdev; - if (rdev->in_sync) { + if (test_bit(In_sync, &rdev->flags)) { char b[BDEVNAME_SIZE]; printk(KERN_INFO "raid6: device %s operational as raid" " disk %d\n", bdevname(rdev->bdev,b), @@ -2052,7 +2052,7 @@ static void status (struct seq_file *seq, mddev_t *mddev) for (i = 0; i < conf->raid_disks; i++) seq_printf (seq, "%s", conf->disks[i].rdev && - conf->disks[i].rdev->in_sync ? "U" : "_"); + test_bit(In_sync, &conf->disks[i].rdev->flags) ? "U" : "_"); seq_printf (seq, "]"); #if RAID6_DUMPSTATE seq_printf (seq, "\n"); @@ -2078,7 +2078,7 @@ static void print_raid6_conf (raid6_conf_t *conf) tmp = conf->disks + i; if (tmp->rdev) printk(" disk %d, o:%d, dev:%s\n", - i, !tmp->rdev->faulty, + i, !test_bit(Faulty, &tmp->rdev->flags), bdevname(tmp->rdev->bdev,b)); } } @@ -2092,12 +2092,12 @@ static int raid6_spare_active(mddev_t *mddev) for (i = 0; i < conf->raid_disks; i++) { tmp = conf->disks + i; if (tmp->rdev - && !tmp->rdev->faulty - && !tmp->rdev->in_sync) { + && !test_bit(Faulty, &tmp->rdev->flags) + && !test_bit(In_sync, &tmp->rdev->flags)) { mddev->degraded--; conf->failed_disks--; conf->working_disks++; - tmp->rdev->in_sync = 1; + set_bit(In_sync, &tmp->rdev->flags); } } print_raid6_conf(conf); @@ -2114,7 +2114,7 @@ static int raid6_remove_disk(mddev_t *mddev, int number) print_raid6_conf(conf); rdev = p->rdev; if (rdev) { - if (rdev->in_sync || + if (test_bit(In_sync, &rdev->flags) || atomic_read(&rdev->nr_pending)) { err = -EBUSY; goto abort; @@ -2149,7 +2149,7 @@ static int raid6_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) */ for (disk=0; disk < mddev->raid_disks; disk++) if ((p=conf->disks + disk)->rdev == NULL) { - rdev->in_sync = 0; + clear_bit(In_sync, &rdev->flags); rdev->raid_disk = disk; found = 1; if (rdev->saved_raid_disk != disk) diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index 200c69e34fc0..11629f92180a 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -117,10 +117,10 @@ struct mdk_rdev_s * It can never have faulty==1, in_sync==1 * This reduces the burden of testing multiple flags in many cases */ - int faulty; /* if faulty do not issue IO requests */ - int in_sync; /* device is a full member of the array */ - unsigned long flags; /* Should include faulty and in_sync here. */ + unsigned long flags; +#define Faulty 1 /* device is known to have a fault */ +#define In_sync 2 /* device is in_sync with rest of array */ #define WriteMostly 4 /* Avoid reading if at all possible */ int desc_nr; /* descriptor index in the superblock */ @@ -247,7 +247,7 @@ struct mddev_s static inline void rdev_dec_pending(mdk_rdev_t *rdev, mddev_t *mddev) { - int faulty = rdev->faulty; + int faulty = test_bit(Faulty, &rdev->flags); if (atomic_dec_and_test(&rdev->nr_pending) && faulty) set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); } -- cgit v1.2.3 From bd926c63b7a6843d3ce2728396c0891e54fce5c4 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2005 21:39:32 -0800 Subject: [PATCH] md: make md on-disk bitmaps not host-endian Current bitmaps use set_bit et.al and so are host-endian, which means not-portable. Oops. Define a new version number (4) for which bitmaps are little-endian. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/bitmap.c | 22 ++++++++++++++++++---- drivers/md/md.c | 2 +- include/linux/raid/bitmap.h | 11 +++++++++-- include/linux/raid/md.h | 4 +++- 4 files changed, 31 insertions(+), 8 deletions(-) (limited to 'include/linux') diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index c5fa4c2a5af1..220273e81ed6 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -482,7 +482,8 @@ static int bitmap_read_sb(struct bitmap *bitmap) /* verify that the bitmap-specific fields are valid */ if (sb->magic != cpu_to_le32(BITMAP_MAGIC)) reason = "bad magic"; - else if (sb->version != cpu_to_le32(BITMAP_MAJOR)) + else if (le32_to_cpu(sb->version) < BITMAP_MAJOR_LO || + le32_to_cpu(sb->version) > BITMAP_MAJOR_HI) reason = "unrecognized superblock version"; else if (chunksize < 512 || chunksize > (1024 * 1024 * 4)) reason = "bitmap chunksize out of range (512B - 4MB)"; @@ -527,6 +528,8 @@ success: bitmap->daemon_lastrun = jiffies; bitmap->max_write_behind = write_behind; bitmap->flags |= sb->state; + if (le32_to_cpu(sb->version) == BITMAP_MAJOR_HOSTENDIAN) + bitmap->flags |= BITMAP_HOSTENDIAN; bitmap->events_cleared = le64_to_cpu(sb->events_cleared); if (sb->state & BITMAP_STALE) bitmap->events_cleared = bitmap->mddev->events; @@ -764,7 +767,10 @@ static void bitmap_file_set_bit(struct bitmap *bitmap, sector_t block) /* set the bit */ kaddr = kmap_atomic(page, KM_USER0); - set_bit(bit, kaddr); + if (bitmap->flags & BITMAP_HOSTENDIAN) + set_bit(bit, kaddr); + else + ext2_set_bit(bit, kaddr); kunmap_atomic(kaddr, KM_USER0); PRINTK("set file bit %lu page %lu\n", bit, page->index); @@ -891,6 +897,7 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) oldindex = ~0L; for (i = 0; i < chunks; i++) { + int b; index = file_page_index(i); bit = file_page_offset(i); if (index != oldindex) { /* this is a new page, read it in */ @@ -939,7 +946,11 @@ static int bitmap_init_from_disk(struct bitmap *bitmap, sector_t start) bitmap->filemap[bitmap->file_pages++] = page; } - if (test_bit(bit, page_address(page))) { + if (bitmap->flags & BITMAP_HOSTENDIAN) + b = test_bit(bit, page_address(page)); + else + b = ext2_test_bit(bit, page_address(page)); + if (b) { /* if the disk bit is set, set the memory bit */ bitmap_set_memory_bits(bitmap, i << CHUNK_BLOCK_SHIFT(bitmap), ((i+1) << (CHUNK_BLOCK_SHIFT(bitmap)) >= start) @@ -1097,7 +1108,10 @@ int bitmap_daemon_work(struct bitmap *bitmap) -1); /* clear the bit */ - clear_bit(file_page_offset(j), page_address(page)); + if (bitmap->flags & BITMAP_HOSTENDIAN) + clear_bit(file_page_offset(j), page_address(page)); + else + ext2_clear_bit(file_page_offset(j), page_address(page)); } } spin_unlock_irqrestore(&bitmap->lock, flags); diff --git a/drivers/md/md.c b/drivers/md/md.c index 9dfa063d1c6a..caa4add00c1b 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -4281,7 +4281,7 @@ static int __init md_init(void) " MD_SB_DISKS=%d\n", MD_MAJOR_VERSION, MD_MINOR_VERSION, MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MD_SB_DISKS); - printk(KERN_INFO "md: bitmap version %d.%d\n", BITMAP_MAJOR, + printk(KERN_INFO "md: bitmap version %d.%d\n", BITMAP_MAJOR_HI, BITMAP_MINOR); if (register_blkdev(MAJOR_NR, "md")) diff --git a/include/linux/raid/bitmap.h b/include/linux/raid/bitmap.h index 9de99198caf1..899437802aea 100644 --- a/include/linux/raid/bitmap.h +++ b/include/linux/raid/bitmap.h @@ -6,7 +6,13 @@ #ifndef BITMAP_H #define BITMAP_H 1 -#define BITMAP_MAJOR 3 +#define BITMAP_MAJOR_LO 3 +/* version 4 insists the bitmap is in little-endian order + * with version 3, it is host-endian which is non-portable + */ +#define BITMAP_MAJOR_HI 4 +#define BITMAP_MAJOR_HOSTENDIAN 3 + #define BITMAP_MINOR 39 /* @@ -133,7 +139,8 @@ typedef __u16 bitmap_counter_t; /* use these for bitmap->flags and bitmap->sb->state bit-fields */ enum bitmap_state { BITMAP_ACTIVE = 0x001, /* the bitmap is in use */ - BITMAP_STALE = 0x002 /* the bitmap file is out of date or had -EIO */ + BITMAP_STALE = 0x002, /* the bitmap file is out of date or had -EIO */ + BITMAP_HOSTENDIAN = 0x8000, }; /* the superblock at the front of the bitmap file -- little endian */ diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h index ffa316ce4dc8..91467a3c4a52 100644 --- a/include/linux/raid/md.h +++ b/include/linux/raid/md.h @@ -66,8 +66,10 @@ * and major_version/minor_version accordingly * >=2 means that Internal bitmaps are supported by setting MD_SB_BITMAP_PRESENT * in the super status byte + * >=3 means that bitmap superblock version 4 is supported, which uses + * little-ending representation rather than host-endian */ -#define MD_PATCHLEVEL_VERSION 2 +#define MD_PATCHLEVEL_VERSION 3 extern int register_md_personality (int p_num, mdk_personality_t *p); extern int unregister_md_personality (int p_num); -- cgit v1.2.3 From a9701a30470856408d08657eb1bd7ae29a146190 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2005 21:39:34 -0800 Subject: [PATCH] md: support BIO_RW_BARRIER for md/raid1 We can only accept BARRIER requests if all slaves handle barriers, and that can, of course, change with time.... So we keep track of whether the whole array seems safe for barriers, and also whether each individual rdev handles barriers. We initially assumes barriers are OK. When writing the superblock we try a barrier, and if that fails, we flag things for no-barriers. This will usually clear the flags fairly quickly. If writing the superblock finds that BIO_RW_BARRIER is -ENOTSUPP, we need to resubmit, so introduce function "md_super_wait" which waits for requests to finish, and retries ENOTSUPP requests without the barrier flag. When writing the real raid1, write requests which were BIO_RW_BARRIER but which aresn't supported need to be retried. So raid1d is enhanced to do this, and when any bio write completes (i.e. no retry needed) we remove it from the r1bio, so that devices needing retry are easy to find. We should hardly ever get -ENOTSUPP errors when writing data to the raid. It should only happen if: 1/ the device used to support BARRIER, but now doesn't. Few devices change like this, though raid1 can! or 2/ the array has no persistent superblock, so there was no opportunity to pre-test for barriers when writing the superblock. Signed-off-by: Neil Brown Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/bitmap.c | 5 +- drivers/md/md.c | 99 +++++++++++++++++++++++++++------ drivers/md/raid1.c | 134 +++++++++++++++++++++++++++++++-------------- include/linux/raid/md.h | 1 + include/linux/raid/md_k.h | 8 +++ include/linux/raid/raid1.h | 4 +- 6 files changed, 189 insertions(+), 62 deletions(-) (limited to 'include/linux') diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 220273e81ed6..51315302a85e 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c @@ -301,7 +301,7 @@ static int write_sb_page(mddev_t *mddev, long offset, struct page *page, int wai page); if (wait) - wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0); + md_super_wait(mddev); return 0; } @@ -828,8 +828,7 @@ int bitmap_unplug(struct bitmap *bitmap) wake_up_process(bitmap->writeback_daemon->tsk)); spin_unlock_irq(&bitmap->write_lock); } else - wait_event(bitmap->mddev->sb_wait, - atomic_read(&bitmap->mddev->pending_writes)==0); + md_super_wait(bitmap->mddev); } return 0; } diff --git a/drivers/md/md.c b/drivers/md/md.c index caa4add00c1b..199016932de5 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -330,18 +330,46 @@ static void free_disk_sb(mdk_rdev_t * rdev) static int super_written(struct bio *bio, unsigned int bytes_done, int error) { mdk_rdev_t *rdev = bio->bi_private; + mddev_t *mddev = rdev->mddev; if (bio->bi_size) return 1; if (error || !test_bit(BIO_UPTODATE, &bio->bi_flags)) - md_error(rdev->mddev, rdev); + md_error(mddev, rdev); - if (atomic_dec_and_test(&rdev->mddev->pending_writes)) - wake_up(&rdev->mddev->sb_wait); + if (atomic_dec_and_test(&mddev->pending_writes)) + wake_up(&mddev->sb_wait); bio_put(bio); return 0; } +static int super_written_barrier(struct bio *bio, unsigned int bytes_done, int error) +{ + struct bio *bio2 = bio->bi_private; + mdk_rdev_t *rdev = bio2->bi_private; + mddev_t *mddev = rdev->mddev; + if (bio->bi_size) + return 1; + + if (!test_bit(BIO_UPTODATE, &bio->bi_flags) && + error == -EOPNOTSUPP) { + unsigned long flags; + /* barriers don't appear to be supported :-( */ + set_bit(BarriersNotsupp, &rdev->flags); + mddev->barriers_work = 0; + spin_lock_irqsave(&mddev->write_lock, flags); + bio2->bi_next = mddev->biolist; + mddev->biolist = bio2; + spin_unlock_irqrestore(&mddev->write_lock, flags); + wake_up(&mddev->sb_wait); + bio_put(bio); + return 0; + } + bio_put(bio2); + bio->bi_private = rdev; + return super_written(bio, bytes_done, error); +} + void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev, sector_t sector, int size, struct page *page) { @@ -350,16 +378,54 @@ void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev, * and decrement it on completion, waking up sb_wait * if zero is reached. * If an error occurred, call md_error + * + * As we might need to resubmit the request if BIO_RW_BARRIER + * causes ENOTSUPP, we allocate a spare bio... */ struct bio *bio = bio_alloc(GFP_NOIO, 1); + int rw = (1<bi_bdev = rdev->bdev; bio->bi_sector = sector; bio_add_page(bio, page, size, 0); bio->bi_private = rdev; bio->bi_end_io = super_written; + bio->bi_rw = rw; + atomic_inc(&mddev->pending_writes); - submit_bio((1<flags)) { + struct bio *rbio; + rw |= (1<bi_private = bio; + rbio->bi_end_io = super_written_barrier; + submit_bio(rw, rbio); + } else + submit_bio(rw, bio); +} + +void md_super_wait(mddev_t *mddev) +{ + /* wait for all superblock writes that were scheduled to complete. + * if any had to be retried (due to BARRIER problems), retry them + */ + DEFINE_WAIT(wq); + for(;;) { + prepare_to_wait(&mddev->sb_wait, &wq, TASK_UNINTERRUPTIBLE); + if (atomic_read(&mddev->pending_writes)==0) + break; + while (mddev->biolist) { + struct bio *bio; + spin_lock_irq(&mddev->write_lock); + bio = mddev->biolist; + mddev->biolist = bio->bi_next ; + bio->bi_next = NULL; + spin_unlock_irq(&mddev->write_lock); + submit_bio(bio->bi_rw, bio); + } + schedule(); + } + finish_wait(&mddev->sb_wait, &wq); } static int bi_complete(struct bio *bio, unsigned int bytes_done, int error) @@ -1382,7 +1448,7 @@ static void md_update_sb(mddev_t * mddev) int sync_req; repeat: - spin_lock(&mddev->write_lock); + spin_lock_irq(&mddev->write_lock); sync_req = mddev->in_sync; mddev->utime = get_seconds(); mddev->events ++; @@ -1405,11 +1471,11 @@ repeat: */ if (!mddev->persistent) { mddev->sb_dirty = 0; - spin_unlock(&mddev->write_lock); + spin_unlock_irq(&mddev->write_lock); wake_up(&mddev->sb_wait); return; } - spin_unlock(&mddev->write_lock); + spin_unlock_irq(&mddev->write_lock); dprintk(KERN_INFO "md: updating %s RAID superblock on device (in sync %d)\n", @@ -1437,17 +1503,17 @@ repeat: /* only need to write one superblock... */ break; } - wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0); + md_super_wait(mddev); /* if there was a failure, sb_dirty was set to 1, and we re-write super */ - spin_lock(&mddev->write_lock); + spin_lock_irq(&mddev->write_lock); if (mddev->in_sync != sync_req|| mddev->sb_dirty == 1) { /* have to write it out again */ - spin_unlock(&mddev->write_lock); + spin_unlock_irq(&mddev->write_lock); goto repeat; } mddev->sb_dirty = 0; - spin_unlock(&mddev->write_lock); + spin_unlock_irq(&mddev->write_lock); wake_up(&mddev->sb_wait); } @@ -1989,6 +2055,7 @@ static int do_md_run(mddev_t * mddev) mddev->recovery = 0; mddev->resync_max_sectors = mddev->size << 1; /* may be over-ridden by personality */ + mddev->barriers_work = 1; /* before we start the array running, initialise the bitmap */ err = bitmap_create(mddev); @@ -2107,7 +2174,7 @@ static int do_md_stop(mddev_t * mddev, int ro) mddev->ro = 1; } else { bitmap_flush(mddev); - wait_event(mddev->sb_wait, atomic_read(&mddev->pending_writes)==0); + md_super_wait(mddev); if (mddev->ro) set_disk_ro(disk, 0); blk_queue_make_request(mddev->queue, md_fail_request); @@ -3796,13 +3863,13 @@ void md_write_start(mddev_t *mddev, struct bio *bi) atomic_inc(&mddev->writes_pending); if (mddev->in_sync) { - spin_lock(&mddev->write_lock); + spin_lock_irq(&mddev->write_lock); if (mddev->in_sync) { mddev->in_sync = 0; mddev->sb_dirty = 1; md_wakeup_thread(mddev->thread); } - spin_unlock(&mddev->write_lock); + spin_unlock_irq(&mddev->write_lock); } wait_event(mddev->sb_wait, mddev->sb_dirty==0); } @@ -4112,7 +4179,7 @@ void md_check_recovery(mddev_t *mddev) if (mddev_trylock(mddev)==0) { int spares =0; - spin_lock(&mddev->write_lock); + spin_lock_irq(&mddev->write_lock); if (mddev->safemode && !atomic_read(&mddev->writes_pending) && !mddev->in_sync && mddev->recovery_cp == MaxSector) { mddev->in_sync = 1; @@ -4120,7 +4187,7 @@ void md_check_recovery(mddev_t *mddev) } if (mddev->safemode == 1) mddev->safemode = 0; - spin_unlock(&mddev->write_lock); + spin_unlock_irq(&mddev->write_lock); if (mddev->sb_dirty) md_update_sb(mddev); diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index fb6b866c28f5..1cbf51fbd43f 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c @@ -301,7 +301,7 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int { int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); - int mirror, behind; + int mirror, behind = test_bit(R1BIO_BehindIO, &r1_bio->state); conf_t *conf = mddev_to_conf(r1_bio->mddev); if (bio->bi_size) @@ -311,47 +311,54 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int if (r1_bio->bios[mirror] == bio) break; - /* - * this branch is our 'one mirror IO has finished' event handler: - */ - if (!uptodate) { - md_error(r1_bio->mddev, conf->mirrors[mirror].rdev); - /* an I/O failed, we can't clear the bitmap */ - set_bit(R1BIO_Degraded, &r1_bio->state); - } else + if (error == -ENOTSUPP && test_bit(R1BIO_Barrier, &r1_bio->state)) { + set_bit(BarriersNotsupp, &conf->mirrors[mirror].rdev->flags); + set_bit(R1BIO_BarrierRetry, &r1_bio->state); + r1_bio->mddev->barriers_work = 0; + } else { /* - * Set R1BIO_Uptodate in our master bio, so that - * we will return a good error code for to the higher - * levels even if IO on some other mirrored buffer fails. - * - * The 'master' represents the composite IO operation to - * user-side. So if something waits for IO, then it will - * wait for the 'master' bio. + * this branch is our 'one mirror IO has finished' event handler: */ - set_bit(R1BIO_Uptodate, &r1_bio->state); - - update_head_pos(mirror, r1_bio); - - behind = test_bit(R1BIO_BehindIO, &r1_bio->state); - if (behind) { - if (test_bit(WriteMostly, &conf->mirrors[mirror].rdev->flags)) - atomic_dec(&r1_bio->behind_remaining); - - /* In behind mode, we ACK the master bio once the I/O has safely - * reached all non-writemostly disks. Setting the Returned bit - * ensures that this gets done only once -- we don't ever want to - * return -EIO here, instead we'll wait */ - - if (atomic_read(&r1_bio->behind_remaining) >= (atomic_read(&r1_bio->remaining)-1) && - test_bit(R1BIO_Uptodate, &r1_bio->state)) { - /* Maybe we can return now */ - if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) { - struct bio *mbio = r1_bio->master_bio; - PRINTK(KERN_DEBUG "raid1: behind end write sectors %llu-%llu\n", - (unsigned long long) mbio->bi_sector, - (unsigned long long) mbio->bi_sector + - (mbio->bi_size >> 9) - 1); - bio_endio(mbio, mbio->bi_size, 0); + r1_bio->bios[mirror] = NULL; + bio_put(bio); + if (!uptodate) { + md_error(r1_bio->mddev, conf->mirrors[mirror].rdev); + /* an I/O failed, we can't clear the bitmap */ + set_bit(R1BIO_Degraded, &r1_bio->state); + } else + /* + * Set R1BIO_Uptodate in our master bio, so that + * we will return a good error code for to the higher + * levels even if IO on some other mirrored buffer fails. + * + * The 'master' represents the composite IO operation to + * user-side. So if something waits for IO, then it will + * wait for the 'master' bio. + */ + set_bit(R1BIO_Uptodate, &r1_bio->state); + + update_head_pos(mirror, r1_bio); + + if (behind) { + if (test_bit(WriteMostly, &conf->mirrors[mirror].rdev->flags)) + atomic_dec(&r1_bio->behind_remaining); + + /* In behind mode, we ACK the master bio once the I/O has safely + * reached all non-writemostly disks. Setting the Returned bit + * ensures that this gets done only once -- we don't ever want to + * return -EIO here, instead we'll wait */ + + if (atomic_read(&r1_bio->behind_remaining) >= (atomic_read(&r1_bio->remaining)-1) && + test_bit(R1BIO_Uptodate, &r1_bio->state)) { + /* Maybe we can return now */ + if (!test_and_set_bit(R1BIO_Returned, &r1_bio->state)) { + struct bio *mbio = r1_bio->master_bio; + PRINTK(KERN_DEBUG "raid1: behind end write sectors %llu-%llu\n", + (unsigned long long) mbio->bi_sector, + (unsigned long long) mbio->bi_sector + + (mbio->bi_size >> 9) - 1); + bio_endio(mbio, mbio->bi_size, 0); + } } } } @@ -361,8 +368,16 @@ static int raid1_end_write_request(struct bio *bio, unsigned int bytes_done, int * already. */ if (atomic_dec_and_test(&r1_bio->remaining)) { + if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) { + reschedule_retry(r1_bio); + /* Don't dec_pending yet, we want to hold + * the reference over the retry + */ + return 0; + } if (test_bit(R1BIO_BehindIO, &r1_bio->state)) { /* free extra copy of the data pages */ +/* FIXME bio has been freed!!! */ int i = bio->bi_vcnt; while (i--) __free_page(bio->bi_io_vec[i].bv_page); @@ -648,8 +663,9 @@ static int make_request(request_queue_t *q, struct bio * bio) struct bio_list bl; struct page **behind_pages = NULL; const int rw = bio_data_dir(bio); + int do_barriers; - if (unlikely(bio_barrier(bio))) { + if (unlikely(!mddev->barriers_work && bio_barrier(bio))) { bio_endio(bio, bio->bi_size, -EOPNOTSUPP); return 0; } @@ -759,6 +775,10 @@ static int make_request(request_queue_t *q, struct bio * bio) atomic_set(&r1_bio->remaining, 0); atomic_set(&r1_bio->behind_remaining, 0); + do_barriers = bio->bi_rw & BIO_RW_BARRIER; + if (do_barriers) + set_bit(R1BIO_Barrier, &r1_bio->state); + bio_list_init(&bl); for (i = 0; i < disks; i++) { struct bio *mbio; @@ -771,7 +791,7 @@ static int make_request(request_queue_t *q, struct bio * bio) mbio->bi_sector = r1_bio->sector + conf->mirrors[i].rdev->data_offset; mbio->bi_bdev = conf->mirrors[i].rdev->bdev; mbio->bi_end_io = raid1_end_write_request; - mbio->bi_rw = WRITE; + mbio->bi_rw = WRITE | do_barriers; mbio->bi_private = r1_bio; if (behind_pages) { @@ -1153,6 +1173,36 @@ static void raid1d(mddev_t *mddev) if (test_bit(R1BIO_IsSync, &r1_bio->state)) { sync_request_write(mddev, r1_bio); unplug = 1; + } else if (test_bit(R1BIO_BarrierRetry, &r1_bio->state)) { + /* some requests in the r1bio were BIO_RW_BARRIER + * requests which failed with -ENOTSUPP. Hohumm.. + * Better resubmit without the barrier. + * We know which devices to resubmit for, because + * all others have had their bios[] entry cleared. + */ + int i; + clear_bit(R1BIO_BarrierRetry, &r1_bio->state); + clear_bit(R1BIO_Barrier, &r1_bio->state); + for (i=0; i < conf->raid_disks; i++) + if (r1_bio->bios[i]) { + struct bio_vec *bvec; + int j; + + bio = bio_clone(r1_bio->master_bio, GFP_NOIO); + /* copy pages from the failed bio, as + * this might be a write-behind device */ + __bio_for_each_segment(bvec, bio, j, 0) + bvec->bv_page = bio_iovec_idx(r1_bio->bios[i], j)->bv_page; + bio_put(r1_bio->bios[i]); + bio->bi_sector = r1_bio->sector + + conf->mirrors[i].rdev->data_offset; + bio->bi_bdev = conf->mirrors[i].rdev->bdev; + bio->bi_end_io = raid1_end_write_request; + bio->bi_rw = WRITE; + bio->bi_private = r1_bio; + r1_bio->bios[i] = bio; + generic_make_request(bio); + } } else { int disk; bio = r1_bio->bios[r1_bio->read_disk]; diff --git a/include/linux/raid/md.h b/include/linux/raid/md.h index 91467a3c4a52..13e7c4b62367 100644 --- a/include/linux/raid/md.h +++ b/include/linux/raid/md.h @@ -89,6 +89,7 @@ extern void md_print_devices (void); extern void md_super_write(mddev_t *mddev, mdk_rdev_t *rdev, sector_t sector, int size, struct page *page); +extern void md_super_wait(mddev_t *mddev); extern int sync_page_io(struct block_device *bdev, sector_t sector, int size, struct page *page, int rw); diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index 11629f92180a..d5854c2b2721 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -122,6 +122,7 @@ struct mdk_rdev_s #define Faulty 1 /* device is known to have a fault */ #define In_sync 2 /* device is in_sync with rest of array */ #define WriteMostly 4 /* Avoid reading if at all possible */ +#define BarriersNotsupp 5 /* BIO_RW_BARRIER is not supported */ int desc_nr; /* descriptor index in the superblock */ int raid_disk; /* role of device in array */ @@ -210,6 +211,13 @@ struct mddev_s int degraded; /* whether md should consider * adding a spare */ + int barriers_work; /* initialised to true, cleared as soon + * as a barrier request to slave + * fails. Only supported + */ + struct bio *biolist; /* bios that need to be retried + * because BIO_RW_BARRIER is not supported + */ atomic_t recovery_active; /* blocks scheduled, but not written */ wait_queue_head_t recovery_wait; diff --git a/include/linux/raid/raid1.h b/include/linux/raid/raid1.h index 60e19b667548..292b98f2b408 100644 --- a/include/linux/raid/raid1.h +++ b/include/linux/raid/raid1.h @@ -110,7 +110,9 @@ struct r1bio_s { #define R1BIO_Uptodate 0 #define R1BIO_IsSync 1 #define R1BIO_Degraded 2 -#define R1BIO_BehindIO 3 +#define R1BIO_BehindIO 3 +#define R1BIO_Barrier 4 +#define R1BIO_BarrierRetry 5 /* For write-behind requests, we call bi_end_io when * the last non-write-behind device completes, providing * any write was successful. Otherwise we call when -- cgit v1.2.3 From 787453c2397edcc3261efebb661739acd8c38547 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Tue, 8 Nov 2005 21:39:43 -0800 Subject: [PATCH] md: complete conversion of md to use kthreads There are a few loose ends following the conversion of md to use kthreads: - Some fields in mdk_thread_t that aren't needed (kthreads does it's own completion and manages it's own name). - thread->run is now never NULL, so no need to check - Some tests for signal_pending that aren't needed (As we don't use signals to stop threads any more) - Some flush_signals are not needed - Some waits are interruptible and don't need to be. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 33 ++++++++++----------------------- include/linux/raid/md_k.h | 2 -- 2 files changed, 10 insertions(+), 25 deletions(-) (limited to 'include/linux') diff --git a/drivers/md/md.c b/drivers/md/md.c index 25f2bbfe6a2b..097ae1b5484b 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -3424,21 +3424,17 @@ static int md_thread(void * arg) */ allow_signal(SIGKILL); - complete(thread->event); while (!kthread_should_stop()) { - void (*run)(mddev_t *); - wait_event_interruptible_timeout(thread->wqueue, - test_bit(THREAD_WAKEUP, &thread->flags) - || kthread_should_stop(), - thread->timeout); + wait_event_timeout(thread->wqueue, + test_bit(THREAD_WAKEUP, &thread->flags) + || kthread_should_stop(), + thread->timeout); try_to_freeze(); clear_bit(THREAD_WAKEUP, &thread->flags); - run = thread->run; - if (run) - run(thread->mddev); + thread->run(thread->mddev); } return 0; @@ -3457,7 +3453,6 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev, const char *name) { mdk_thread_t *thread; - struct completion event; thread = kmalloc(sizeof(mdk_thread_t), GFP_KERNEL); if (!thread) @@ -3466,18 +3461,14 @@ mdk_thread_t *md_register_thread(void (*run) (mddev_t *), mddev_t *mddev, memset(thread, 0, sizeof(mdk_thread_t)); init_waitqueue_head(&thread->wqueue); - init_completion(&event); - thread->event = &event; thread->run = run; thread->mddev = mddev; - thread->name = name; thread->timeout = MAX_SCHEDULE_TIMEOUT; thread->tsk = kthread_run(md_thread, thread, name, mdname(thread->mddev)); if (IS_ERR(thread->tsk)) { kfree(thread); return NULL; } - wait_for_completion(&event); return thread; } @@ -3941,9 +3932,7 @@ static void md_do_sync(mddev_t *mddev) mddev->curr_resync = 2; try_again: - if (signal_pending(current) || - kthread_should_stop()) { - flush_signals(current); + if (kthread_should_stop()) { set_bit(MD_RECOVERY_INTR, &mddev->recovery); goto skip; } @@ -3963,9 +3952,8 @@ static void md_do_sync(mddev_t *mddev) * time 'round when curr_resync == 2 */ continue; - prepare_to_wait(&resync_wait, &wq, TASK_INTERRUPTIBLE); - if (!signal_pending(current) && - !kthread_should_stop() && + prepare_to_wait(&resync_wait, &wq, TASK_UNINTERRUPTIBLE); + if (!kthread_should_stop() && mddev2->curr_resync >= mddev->curr_resync) { printk(KERN_INFO "md: delaying resync of %s" " until %s has finished resync (they" @@ -4074,13 +4062,12 @@ static void md_do_sync(mddev_t *mddev) } - if (signal_pending(current) || kthread_should_stop()) { + if (kthread_should_stop()) { /* * got a signal, exit. */ printk(KERN_INFO "md: md_do_sync() got signal ... exiting\n"); - flush_signals(current); set_bit(MD_RECOVERY_INTR, &mddev->recovery); goto out; } @@ -4102,7 +4089,7 @@ static void md_do_sync(mddev_t *mddev) if (currspeed > sysctl_speed_limit_min) { if ((currspeed > sysctl_speed_limit_max) || !is_mddev_idle(mddev)) { - msleep_interruptible(250); + msleep(250); goto repeat; } } diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index d5854c2b2721..46629a275ba9 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -334,10 +334,8 @@ typedef struct mdk_thread_s { mddev_t *mddev; wait_queue_head_t wqueue; unsigned long flags; - struct completion *event; struct task_struct *tsk; unsigned long timeout; - const char *name; } mdk_thread_t; #define THREAD_WAKEUP 0 -- cgit v1.2.3 From a2506c04322ca266fe2f9bd7d02a67b1972da611 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 9 Nov 2005 12:59:13 -0800 Subject: [NETFILTER] nfnetlink: nfattr_parse() can never fail, make it void nfattr_parse (and thus nfattr_parse_nested) always returns success. So we can make them 'void' and remove all the checking at the caller side. Based on original patch by Pablo Neira Ayuso Signed-off-by: Harald Welte Signed-off-by: David S. Miller --- include/linux/netfilter/nfnetlink.h | 2 +- net/ipv4/netfilter/ip_conntrack_netlink.c | 45 +++++------------------------ net/ipv4/netfilter/ip_conntrack_proto_tcp.c | 6 +--- net/netfilter/nfnetlink.c | 4 +-- 4 files changed, 11 insertions(+), 46 deletions(-) (limited to 'include/linux') diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h index f08e870100f4..72975fa8795d 100644 --- a/include/linux/netfilter/nfnetlink.h +++ b/include/linux/netfilter/nfnetlink.h @@ -146,7 +146,7 @@ extern void nfnl_unlock(void); extern int nfnetlink_subsys_register(struct nfnetlink_subsystem *n); extern int nfnetlink_subsys_unregister(struct nfnetlink_subsystem *n); -extern int nfattr_parse(struct nfattr *tb[], int maxattr, +extern void nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len); #define nfattr_parse_nested(tb, max, nfa) \ diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index 02f303cf201e..838262e17376 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -482,9 +482,7 @@ ctnetlink_parse_tuple_ip(struct nfattr *attr, struct ip_conntrack_tuple *tuple) DEBUGP("entered %s\n", __FUNCTION__); - - if (nfattr_parse_nested(tb, CTA_IP_MAX, attr) < 0) - goto nfattr_failure; + nfattr_parse_nested(tb, CTA_IP_MAX, attr); if (nfattr_bad_size(tb, CTA_IP_MAX, cta_min_ip)) return -EINVAL; @@ -500,9 +498,6 @@ ctnetlink_parse_tuple_ip(struct nfattr *attr, struct ip_conntrack_tuple *tuple) DEBUGP("leaving\n"); return 0; - -nfattr_failure: - return -1; } static const int cta_min_proto[CTA_PROTO_MAX] = { @@ -524,8 +519,7 @@ ctnetlink_parse_tuple_proto(struct nfattr *attr, DEBUGP("entered %s\n", __FUNCTION__); - if (nfattr_parse_nested(tb, CTA_PROTO_MAX, attr) < 0) - goto nfattr_failure; + nfattr_parse_nested(tb, CTA_PROTO_MAX, attr); if (nfattr_bad_size(tb, CTA_PROTO_MAX, cta_min_proto)) return -EINVAL; @@ -542,9 +536,6 @@ ctnetlink_parse_tuple_proto(struct nfattr *attr, } return ret; - -nfattr_failure: - return -1; } static inline int @@ -558,8 +549,7 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct ip_conntrack_tuple *tuple, memset(tuple, 0, sizeof(*tuple)); - if (nfattr_parse_nested(tb, CTA_TUPLE_MAX, cda[type-1]) < 0) - goto nfattr_failure; + nfattr_parse_nested(tb, CTA_TUPLE_MAX, cda[type-1]); if (!tb[CTA_TUPLE_IP-1]) return -EINVAL; @@ -586,9 +576,6 @@ ctnetlink_parse_tuple(struct nfattr *cda[], struct ip_conntrack_tuple *tuple, DEBUGP("leaving\n"); return 0; - -nfattr_failure: - return -1; } #ifdef CONFIG_IP_NF_NAT_NEEDED @@ -606,11 +593,10 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr, DEBUGP("entered %s\n", __FUNCTION__); - if (nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr) < 0) - goto nfattr_failure; + nfattr_parse_nested(tb, CTA_PROTONAT_MAX, attr); if (nfattr_bad_size(tb, CTA_PROTONAT_MAX, cta_min_protonat)) - goto nfattr_failure; + return -1; npt = ip_nat_proto_find_get(ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum); if (!npt) @@ -629,9 +615,6 @@ static int ctnetlink_parse_nat_proto(struct nfattr *attr, DEBUGP("leaving\n"); return 0; - -nfattr_failure: - return -1; } static inline int @@ -645,8 +628,7 @@ ctnetlink_parse_nat(struct nfattr *cda[], memset(range, 0, sizeof(*range)); - if (nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]) < 0) - goto nfattr_failure; + nfattr_parse_nested(tb, CTA_NAT_MAX, cda[CTA_NAT-1]); if (tb[CTA_NAT_MINIP-1]) range->min_ip = *(u_int32_t *)NFA_DATA(tb[CTA_NAT_MINIP-1]); @@ -668,9 +650,6 @@ ctnetlink_parse_nat(struct nfattr *cda[], DEBUGP("leaving\n"); return 0; - -nfattr_failure: - return -1; } #endif @@ -681,8 +660,7 @@ ctnetlink_parse_help(struct nfattr *attr, char **helper_name) DEBUGP("entered %s\n", __FUNCTION__); - if (nfattr_parse_nested(tb, CTA_HELP_MAX, attr) < 0) - goto nfattr_failure; + nfattr_parse_nested(tb, CTA_HELP_MAX, attr); if (!tb[CTA_HELP_NAME-1]) return -EINVAL; @@ -690,9 +668,6 @@ ctnetlink_parse_help(struct nfattr *attr, char **helper_name) *helper_name = NFA_DATA(tb[CTA_HELP_NAME-1]); return 0; - -nfattr_failure: - return -1; } static int @@ -960,8 +935,7 @@ ctnetlink_change_protoinfo(struct ip_conntrack *ct, struct nfattr *cda[]) u_int16_t npt = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.dst.protonum; int err = 0; - if (nfattr_parse_nested(tb, CTA_PROTOINFO_MAX, attr) < 0) - goto nfattr_failure; + nfattr_parse_nested(tb, CTA_PROTOINFO_MAX, attr); proto = ip_conntrack_proto_find_get(npt); if (!proto) @@ -972,9 +946,6 @@ ctnetlink_change_protoinfo(struct ip_conntrack *ct, struct nfattr *cda[]) ip_conntrack_proto_put(proto); return err; - -nfattr_failure: - return -ENOMEM; } static int diff --git a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c index d6701cafbcc2..6ea4b22ff28d 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_tcp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_tcp.c @@ -362,8 +362,7 @@ static int nfattr_to_tcp(struct nfattr *cda[], struct ip_conntrack *ct) struct nfattr *attr = cda[CTA_PROTOINFO_TCP-1]; struct nfattr *tb[CTA_PROTOINFO_TCP_MAX]; - if (nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr) < 0) - goto nfattr_failure; + nfattr_parse_nested(tb, CTA_PROTOINFO_TCP_MAX, attr); if (!tb[CTA_PROTOINFO_TCP_STATE-1]) return -EINVAL; @@ -374,9 +373,6 @@ static int nfattr_to_tcp(struct nfattr *cda[], struct ip_conntrack *ct) write_unlock_bh(&tcp_lock); return 0; - -nfattr_failure: - return -1; } #endif diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 4bc27a6334c1..f8bd7c7e7921 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -128,7 +128,7 @@ void __nfa_fill(struct sk_buff *skb, int attrtype, int attrlen, memset(NFA_DATA(nfa) + attrlen, 0, NFA_ALIGN(size) - size); } -int nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len) +void nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len) { memset(tb, 0, sizeof(struct nfattr *) * maxattr); @@ -138,8 +138,6 @@ int nfattr_parse(struct nfattr *tb[], int maxattr, struct nfattr *nfa, int len) tb[flavor-1] = nfa; nfa = NFA_NEXT(nfa, len); } - - return 0; } /** -- cgit v1.2.3