Commit 286d075e authored by Linus Torvalds's avatar Linus Torvalds

- Jaroslav Kysela: ymfpci driver

- Linus: get rid of bogus MS_INVALIDATE semantics
- Linus: final part of the PageDirty() saga
- Rusty Russell: 4-way SMP iptables fix
- Al Viro: oops - bad ext2 inode dirty block bug
parent 971c8cf0
...@@ -143,6 +143,9 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then ...@@ -143,6 +143,9 @@ if [ "$CONFIG_SOUND_OSS" = "y" -o "$CONFIG_SOUND_OSS" = "m" ]; then
dep_tristate ' Yamaha OPL3-SA1 audio controller' CONFIG_SOUND_OPL3SA1 $CONFIG_SOUND_OSS dep_tristate ' Yamaha OPL3-SA1 audio controller' CONFIG_SOUND_OPL3SA1 $CONFIG_SOUND_OSS
dep_tristate ' Yamaha OPL3-SA2, SA3, and SAx based PnP cards' CONFIG_SOUND_OPL3SA2 $CONFIG_SOUND_OSS dep_tristate ' Yamaha OPL3-SA2, SA3, and SAx based PnP cards' CONFIG_SOUND_OPL3SA2 $CONFIG_SOUND_OSS
dep_tristate ' Yamaha PCI legacy mode support' CONFIG_SOUND_YMPCI $CONFIG_SOUND_OSS $CONFIG_PCI dep_tristate ' Yamaha PCI legacy mode support' CONFIG_SOUND_YMPCI $CONFIG_SOUND_OSS $CONFIG_PCI
if [ "$CONFIG_SOUND_YMPCI" = "n" ]; then
dep_tristate 'Yamaha PCI native mode support (EXPERIMENTAL)' CONFIG_SOUND_YMFPCI $CONFIG_SOUND_OSS
fi
dep_tristate ' 6850 UART support' CONFIG_SOUND_UART6850 $CONFIG_SOUND_OSS dep_tristate ' 6850 UART support' CONFIG_SOUND_UART6850 $CONFIG_SOUND_OSS
dep_tristate ' Gallant Audio Cards (SC-6000 and SC-6600 based)' CONFIG_SOUND_AEDSP16 $CONFIG_SOUND_OSS dep_tristate ' Gallant Audio Cards (SC-6000 and SC-6600 based)' CONFIG_SOUND_AEDSP16 $CONFIG_SOUND_OSS
......
...@@ -67,6 +67,7 @@ obj-$(CONFIG_SOUND_AWE32_SYNTH) += awe_wave.o ...@@ -67,6 +67,7 @@ obj-$(CONFIG_SOUND_AWE32_SYNTH) += awe_wave.o
obj-$(CONFIG_SOUND_VIA82CXXX) += via82cxxx_audio.o ac97_codec.o obj-$(CONFIG_SOUND_VIA82CXXX) += via82cxxx_audio.o ac97_codec.o
obj-$(CONFIG_SOUND_YMPCI) += ymf_sb.o sb_lib.o uart401.o obj-$(CONFIG_SOUND_YMPCI) += ymf_sb.o sb_lib.o uart401.o
obj-$(CONFIG_SOUND_YMFPCI) += ymfpci.o ac97_codec.o
obj-$(CONFIG_SOUND_MSNDCLAS) += msnd.o msnd_classic.o obj-$(CONFIG_SOUND_MSNDCLAS) += msnd.o msnd_classic.o
obj-$(CONFIG_SOUND_MSNDPIN) += msnd.o msnd_pinnacle.o obj-$(CONFIG_SOUND_MSNDPIN) += msnd.o msnd_pinnacle.o
obj-$(CONFIG_SOUND_VWSND) += vwsnd.o obj-$(CONFIG_SOUND_VWSND) += vwsnd.o
......
This diff is collapsed.
#ifndef __YMFPCI_H
#define __YMFPCI_H
/*
* Copyright (c) by Jaroslav Kysela <perex@suse.cz>
* Definitions for Yahama YMF724/740/744/754 chips
*
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*
* Direct registers
*/
/* #define YMFREG(codec, reg) (codec->port + YDSXGR_##reg) */
#define YDSXGR_INTFLAG 0x0004
#define YDSXGR_ACTIVITY 0x0006
#define YDSXGR_GLOBALCTRL 0x0008
#define YDSXGR_ZVCTRL 0x000A
#define YDSXGR_TIMERCTRL 0x0010
#define YDSXGR_TIMERCTRL_TEN 0x0001
#define YDSXGR_TIMERCTRL_TIEN 0x0002
#define YDSXGR_TIMERCOUNT 0x0012
#define YDSXGR_SPDIFOUTCTRL 0x0018
#define YDSXGR_SPDIFOUTSTATUS 0x001C
#define YDSXGR_EEPROMCTRL 0x0020
#define YDSXGR_SPDIFINCTRL 0x0034
#define YDSXGR_SPDIFINSTATUS 0x0038
#define YDSXGR_DSPPROGRAMDL 0x0048
#define YDSXGR_DLCNTRL 0x004C
#define YDSXGR_GPIOININTFLAG 0x0050
#define YDSXGR_GPIOININTENABLE 0x0052
#define YDSXGR_GPIOINSTATUS 0x0054
#define YDSXGR_GPIOOUTCTRL 0x0056
#define YDSXGR_GPIOFUNCENABLE 0x0058
#define YDSXGR_GPIOTYPECONFIG 0x005A
#define YDSXGR_AC97CMDDATA 0x0060
#define YDSXGR_AC97CMDADR 0x0062
#define YDSXGR_PRISTATUSDATA 0x0064
#define YDSXGR_PRISTATUSADR 0x0066
#define YDSXGR_SECSTATUSDATA 0x0068
#define YDSXGR_SECSTATUSADR 0x006A
#define YDSXGR_SECCONFIG 0x0070
#define YDSXGR_LEGACYOUTVOL 0x0080
#define YDSXGR_LEGACYOUTVOLL 0x0080
#define YDSXGR_LEGACYOUTVOLR 0x0082
#define YDSXGR_NATIVEDACOUTVOL 0x0084
#define YDSXGR_NATIVEDACOUTVOLL 0x0084
#define YDSXGR_NATIVEDACOUTVOLR 0x0086
#define YDSXGR_SPDIFOUTVOL 0x0088
#define YDSXGR_SPDIFOUTVOLL 0x0088
#define YDSXGR_SPDIFOUTVOLR 0x008A
#define YDSXGR_AC3OUTVOL 0x008C
#define YDSXGR_AC3OUTVOLL 0x008C
#define YDSXGR_AC3OUTVOLR 0x008E
#define YDSXGR_PRIADCOUTVOL 0x0090
#define YDSXGR_PRIADCOUTVOLL 0x0090
#define YDSXGR_PRIADCOUTVOLR 0x0092
#define YDSXGR_LEGACYLOOPVOL 0x0094
#define YDSXGR_LEGACYLOOPVOLL 0x0094
#define YDSXGR_LEGACYLOOPVOLR 0x0096
#define YDSXGR_NATIVEDACLOOPVOL 0x0098
#define YDSXGR_NATIVEDACLOOPVOLL 0x0098
#define YDSXGR_NATIVEDACLOOPVOLR 0x009A
#define YDSXGR_SPDIFLOOPVOL 0x009C
#define YDSXGR_SPDIFLOOPVOLL 0x009E
#define YDSXGR_SPDIFLOOPVOLR 0x009E
#define YDSXGR_AC3LOOPVOL 0x00A0
#define YDSXGR_AC3LOOPVOLL 0x00A0
#define YDSXGR_AC3LOOPVOLR 0x00A2
#define YDSXGR_PRIADCLOOPVOL 0x00A4
#define YDSXGR_PRIADCLOOPVOLL 0x00A4
#define YDSXGR_PRIADCLOOPVOLR 0x00A6
#define YDSXGR_NATIVEADCINVOL 0x00A8
#define YDSXGR_NATIVEADCINVOLL 0x00A8
#define YDSXGR_NATIVEADCINVOLR 0x00AA
#define YDSXGR_NATIVEDACINVOL 0x00AC
#define YDSXGR_NATIVEDACINVOLL 0x00AC
#define YDSXGR_NATIVEDACINVOLR 0x00AE
#define YDSXGR_BUF441OUTVOL 0x00B0
#define YDSXGR_BUF441OUTVOLL 0x00B0
#define YDSXGR_BUF441OUTVOLR 0x00B2
#define YDSXGR_BUF441LOOPVOL 0x00B4
#define YDSXGR_BUF441LOOPVOLL 0x00B4
#define YDSXGR_BUF441LOOPVOLR 0x00B6
#define YDSXGR_SPDIFOUTVOL2 0x00B8
#define YDSXGR_SPDIFOUTVOL2L 0x00B8
#define YDSXGR_SPDIFOUTVOL2R 0x00BA
#define YDSXGR_SPDIFLOOPVOL2 0x00BC
#define YDSXGR_SPDIFLOOPVOL2L 0x00BC
#define YDSXGR_SPDIFLOOPVOL2R 0x00BE
#define YDSXGR_ADCSLOTSR 0x00C0
#define YDSXGR_RECSLOTSR 0x00C4
#define YDSXGR_ADCFORMAT 0x00C8
#define YDSXGR_RECFORMAT 0x00CC
#define YDSXGR_P44SLOTSR 0x00D0
#define YDSXGR_STATUS 0x0100
#define YDSXGR_CTRLSELECT 0x0104
#define YDSXGR_MODE 0x0108
#define YDSXGR_SAMPLECOUNT 0x010C
#define YDSXGR_NUMOFSAMPLES 0x0110
#define YDSXGR_CONFIG 0x0114
#define YDSXGR_PLAYCTRLSIZE 0x0140
#define YDSXGR_RECCTRLSIZE 0x0144
#define YDSXGR_EFFCTRLSIZE 0x0148
#define YDSXGR_WORKSIZE 0x014C
#define YDSXGR_MAPOFREC 0x0150
#define YDSXGR_MAPOFEFFECT 0x0154
#define YDSXGR_PLAYCTRLBASE 0x0158
#define YDSXGR_RECCTRLBASE 0x015C
#define YDSXGR_EFFCTRLBASE 0x0160
#define YDSXGR_WORKBASE 0x0164
#define YDSXGR_DSPINSTRAM 0x1000
#define YDSXGR_CTRLINSTRAM 0x4000
#define YDSXG_AC97READCMD 0x8000
#define YDSXG_AC97WRITECMD 0x0000
#define PCIR_DSXGCTRL 0x48
#define YDSXG_DSPLENGTH 0x0080
#define YDSXG_CTRLLENGTH 0x3000
#define YDSXG_DEFAULT_WORK_SIZE 0x0400
#define YDSXG_PLAYBACK_VOICES 64
#define YDSXG_CAPTURE_VOICES 2
#define YDSXG_EFFECT_VOICES 5
/* maxinum number of AC97 codecs connected, AC97 2.0 defined 4 */
#define NR_AC97 2
#define YMF_SAMPF 256 /* Samples per frame @48000 */
/*
* The slot/voice control bank (2 of these per voice)
*/
typedef struct stru_ymfpci_playback_bank {
u32 format;
u32 loop_default;
u32 base; /* 32-bit address */
u32 loop_start; /* 32-bit offset */
u32 loop_end; /* 32-bit offset */
u32 loop_frac; /* 8-bit fraction - loop_start */
u32 delta_end; /* pitch delta end */
u32 lpfK_end;
u32 eg_gain_end;
u32 left_gain_end;
u32 right_gain_end;
u32 eff1_gain_end;
u32 eff2_gain_end;
u32 eff3_gain_end;
u32 lpfQ;
u32 status; /* P3: Always 0 for some reason. */
u32 num_of_frames;
u32 loop_count;
u32 start; /* P3: J. reads this to know where chip is. */
u32 start_frac;
u32 delta;
u32 lpfK;
u32 eg_gain;
u32 left_gain;
u32 right_gain;
u32 eff1_gain;
u32 eff2_gain;
u32 eff3_gain;
u32 lpfD1;
u32 lpfD2;
} ymfpci_playback_bank_t;
typedef struct stru_ymfpci_capture_bank {
u32 base; /* 32-bit address */
u32 loop_end; /* 32-bit offset */
u32 start; /* 32-bit offset */
u32 num_of_loops; /* counter */
} ymfpci_capture_bank_t;
typedef struct stru_ymfpci_effect_bank {
u32 base; /* 32-bit address */
u32 loop_end; /* 32-bit offset */
u32 start; /* 32-bit offset */
u32 temp;
} ymfpci_effect_bank_t;
typedef struct stru_ymfpci_voice ymfpci_voice_t;
typedef struct ymf_pcm ymfpci_pcm_t;
/*
* Throughout the code Yaroslav names YMF unit pointer "codec"
* even though it does not correspond to any codec. Must be historic.
* We replace it with "unit" over time.
* AC97 parts use "codec" to denote a codec, naturally.
*/
typedef struct ymf_unit ymfpci_t;
typedef enum {
YMFPCI_PCM,
YMFPCI_SYNTH,
YMFPCI_MIDI
} ymfpci_voice_type_t;
struct stru_ymfpci_voice {
ymfpci_t *codec;
int number;
int use: 1,
pcm: 1,
synth: 1,
midi: 1;
ymfpci_playback_bank_t *bank;
void (*interrupt)(ymfpci_t *codec, ymfpci_voice_t *voice);
ymfpci_pcm_t *ypcm;
};
typedef enum {
PLAYBACK_VOICE,
CAPTURE_REC,
CAPTURE_AC97,
EFFECT_DRY_LEFT,
EFFECT_DRY_RIGHT,
EFFECT_EFF1,
EFFECT_EFF2,
EFFECT_EFF3
} ymfpci_pcm_type_t;
struct ymf_pcm {
ymfpci_t *codec;
ymfpci_pcm_type_t type;
struct ymf_state *state;
ymfpci_voice_t *voices[2]; /* playback only */
int running; // +
int spdif;
};
struct ymf_unit {
unsigned int device_id; /* PCI device ID */
unsigned int rev; /* PCI revision */
unsigned long reg_area_phys;
unsigned long reg_area_virt;
void *work_ptr; // +
unsigned int bank_size_playback;
unsigned int bank_size_capture;
unsigned int bank_size_effect;
unsigned int work_size;
void *bank_base_playback; // +
void *bank_base_capture; // +
void *bank_base_effect; // +
void *work_base; // +
u32 *ctrl_playback;
ymfpci_playback_bank_t *bank_playback[YDSXG_PLAYBACK_VOICES][2];
ymfpci_capture_bank_t *bank_capture[YDSXG_CAPTURE_VOICES][2];
ymfpci_effect_bank_t *bank_effect[YDSXG_EFFECT_VOICES][2];
int start_count;
u32 active_bank;
ymfpci_voice_t voices[64];
struct ac97_codec *ac97_codec[NR_AC97];
u16 ac97_features;
struct pci_dev *pci;
int irq;
int inst; /* Unit number (instance) */
spinlock_t reg_lock;
spinlock_t voice_lock;
/* soundcore stuff */
int dev_audio;
ymfpci_t *next; // *
struct ymf_state *states[1]; // *
/* ypcm may be the same thing as state, but not for record, effects. */
};
/*
* "Software" or virtual channel, an instance of opened /dev/dsp.
*/
struct ymf_dmabuf {
/* OSS buffer management stuff */
void *rawbuf;
unsigned buforder;
unsigned numfrag;
unsigned fragshift;
/* our buffer acts like a circular ring */
unsigned hwptr; /* where dma last started */
unsigned swptr; /* where driver last clear/filled */
int count; /* fill count */
unsigned total_bytes; /* total bytes dmaed by hardware */
unsigned error; /* number of over/underruns */
wait_queue_head_t wait; /* put process on wait queue when no more space in buffer */
/* redundant, but makes calculations easier */
unsigned fragsize;
unsigned dmasize; /* Total rawbuf[] size */
unsigned fragsamples;
/* OSS stuff */
unsigned mapped:1;
unsigned ready:1;
unsigned ossfragshift;
int ossmaxfrags;
unsigned subdivision;
};
struct ymf_pcm_format {
int format; /* OSS format */
int rate; /* rate in Hz */
int voices; /* number of voices */
int shift; /* redundant, computed from the above */
};
struct ymf_state {
struct ymf_unit *unit; /* backpointer */
/* single open lock mechanism, only used for recording */
struct semaphore open_sem;
wait_queue_head_t open_wait;
/* virtual channel number */
int virt; // * unused a.t.m.
struct ymf_pcm ypcm; // *
struct ymf_dmabuf dmabuf; // *
struct ymf_pcm_format format; // *
};
#endif /* __YMFPCI_H */
This diff is collapsed.
...@@ -53,7 +53,7 @@ adfs_get_block(struct inode *inode, long block, struct buffer_head *bh, int crea ...@@ -53,7 +53,7 @@ adfs_get_block(struct inode *inode, long block, struct buffer_head *bh, int crea
return 0; return 0;
} }
static int adfs_writepage(struct file *file, struct page *page) static int adfs_writepage(struct page *page)
{ {
return block_write_full_page(page, adfs_get_block); return block_write_full_page(page, adfs_get_block);
} }
......
...@@ -338,7 +338,7 @@ static int affs_get_block(struct inode *inode, long block, struct buffer_head *b ...@@ -338,7 +338,7 @@ static int affs_get_block(struct inode *inode, long block, struct buffer_head *b
} }
static int affs_writepage(struct file *file, struct page *page) static int affs_writepage(struct page *page)
{ {
return block_write_full_page(page,affs_get_block); return block_write_full_page(page,affs_get_block);
} }
......
...@@ -135,7 +135,7 @@ static int bfs_get_block(struct inode * inode, long block, ...@@ -135,7 +135,7 @@ static int bfs_get_block(struct inode * inode, long block,
return err; return err;
} }
static int bfs_writepage(struct file *file, struct page *page) static int bfs_writepage(struct page *page)
{ {
return block_write_full_page(page, bfs_get_block); return block_write_full_page(page, bfs_get_block);
} }
......
...@@ -1583,9 +1583,11 @@ static void unmap_underlying_metadata(struct buffer_head * bh) ...@@ -1583,9 +1583,11 @@ static void unmap_underlying_metadata(struct buffer_head * bh)
*/ */
static int __block_write_full_page(struct inode *inode, struct page *page, get_block_t *get_block) static int __block_write_full_page(struct inode *inode, struct page *page, get_block_t *get_block)
{ {
int err, i, need_balance_dirty = 0; int err, i;
unsigned long block; unsigned long block;
struct buffer_head *bh, *head; struct buffer_head *bh, *head;
struct buffer_head *arr[MAX_BUF_PER_PAGE];
int nr = 0;
if (!PageLocked(page)) if (!PageLocked(page))
BUG(); BUG();
...@@ -1607,7 +1609,6 @@ static int __block_write_full_page(struct inode *inode, struct page *page, get_b ...@@ -1607,7 +1609,6 @@ static int __block_write_full_page(struct inode *inode, struct page *page, get_b
* Leave it to the low-level FS to make all those * Leave it to the low-level FS to make all those
* decisions (block #0 may actually be a valid block) * decisions (block #0 may actually be a valid block)
*/ */
bh->b_end_io = end_buffer_io_sync;
if (!buffer_mapped(bh)) { if (!buffer_mapped(bh)) {
err = get_block(inode, block, bh, 1); err = get_block(inode, block, bh, 1);
if (err) if (err)
...@@ -1616,22 +1617,27 @@ static int __block_write_full_page(struct inode *inode, struct page *page, get_b ...@@ -1616,22 +1617,27 @@ static int __block_write_full_page(struct inode *inode, struct page *page, get_b
unmap_underlying_metadata(bh); unmap_underlying_metadata(bh);
} }
set_bit(BH_Uptodate, &bh->b_state); set_bit(BH_Uptodate, &bh->b_state);
if (!atomic_set_buffer_dirty(bh)) { set_bit(BH_Dirty, &bh->b_state);
buffer_insert_inode_queue(bh, inode); bh->b_end_io = end_buffer_io_async;
__mark_dirty(bh); atomic_inc(&bh->b_count);
need_balance_dirty = 1; arr[nr++] = bh;
}
bh = bh->b_this_page; bh = bh->b_this_page;
block++; block++;
} while (bh != head); } while (bh != head);
if (need_balance_dirty) if (nr) {
balance_dirty(bh->b_dev); ll_rw_block(WRITE, nr, arr);
} else {
UnlockPage(page);
}
SetPageUptodate(page); SetPageUptodate(page);
return 0; return 0;
out: out:
if (nr) {
ll_rw_block(WRITE, nr, arr);
} else {
UnlockPage(page);
}
ClearPageUptodate(page); ClearPageUptodate(page);
return err; return err;
} }
...@@ -2021,8 +2027,11 @@ int block_write_full_page(struct page *page, get_block_t *get_block) ...@@ -2021,8 +2027,11 @@ int block_write_full_page(struct page *page, get_block_t *get_block)
/* things got complicated... */ /* things got complicated... */
offset = inode->i_size & (PAGE_CACHE_SIZE-1); offset = inode->i_size & (PAGE_CACHE_SIZE-1);
/* OK, are we completely out? */ /* OK, are we completely out? */
if (page->index >= end_index+1 || !offset) if (page->index >= end_index+1 || !offset) {
UnlockPage(page);
return -EIO; return -EIO;
}
/* Sigh... will have to work, then... */ /* Sigh... will have to work, then... */
err = __block_prepare_write(inode, page, 0, offset, get_block); err = __block_prepare_write(inode, page, 0, offset, get_block);
if (!err) { if (!err) {
...@@ -2031,6 +2040,7 @@ int block_write_full_page(struct page *page, get_block_t *get_block) ...@@ -2031,6 +2040,7 @@ int block_write_full_page(struct page *page, get_block_t *get_block)
__block_commit_write(inode,page,0,offset); __block_commit_write(inode,page,0,offset);
done: done:
kunmap(page); kunmap(page);
UnlockPage(page);
return err; return err;
} }
ClearPageUptodate(page); ClearPageUptodate(page);
......
...@@ -650,7 +650,7 @@ struct buffer_head * ext2_bread (struct inode * inode, int block, ...@@ -650,7 +650,7 @@ struct buffer_head * ext2_bread (struct inode * inode, int block,
return NULL; return NULL;
} }
static int ext2_writepage(struct file *file, struct page *page) static int ext2_writepage(struct page *page)
{ {
return block_write_full_page(page,ext2_get_block); return block_write_full_page(page,ext2_get_block);
} }
...@@ -1208,7 +1208,7 @@ static int ext2_update_inode(struct inode * inode, int do_sync) ...@@ -1208,7 +1208,7 @@ static int ext2_update_inode(struct inode * inode, int do_sync)
raw_inode->i_block[0] = cpu_to_le32(kdev_t_to_nr(inode->i_rdev)); raw_inode->i_block[0] = cpu_to_le32(kdev_t_to_nr(inode->i_rdev));
else for (block = 0; block < EXT2_N_BLOCKS; block++) else for (block = 0; block < EXT2_N_BLOCKS; block++)
raw_inode->i_block[block] = inode->u.ext2_i.i_data[block]; raw_inode->i_block[block] = inode->u.ext2_i.i_data[block];
mark_buffer_dirty_inode(bh, inode); mark_buffer_dirty(bh);
if (do_sync) { if (do_sync) {
ll_rw_block (WRITE, 1, &bh); ll_rw_block (WRITE, 1, &bh);
wait_on_buffer (bh); wait_on_buffer (bh);
......
...@@ -735,7 +735,7 @@ static int is_exec(char *extension) ...@@ -735,7 +735,7 @@ static int is_exec(char *extension)
return 0; return 0;
} }
static int fat_writepage(struct file *file, struct page *page) static int fat_writepage(struct page *page)
{ {
return block_write_full_page(page,fat_get_block); return block_write_full_page(page,fat_get_block);
} }
......
...@@ -220,7 +220,7 @@ int hfs_notify_change_hdr(struct dentry *dentry, struct iattr * attr) ...@@ -220,7 +220,7 @@ int hfs_notify_change_hdr(struct dentry *dentry, struct iattr * attr)
return __hfs_notify_change(dentry, attr, HFS_HDR); return __hfs_notify_change(dentry, attr, HFS_HDR);
} }
static int hfs_writepage(struct file *file, struct page *page) static int hfs_writepage(struct page *page)
{ {
return block_write_full_page(page,hfs_get_block); return block_write_full_page(page,hfs_get_block);
} }
......
...@@ -93,7 +93,7 @@ int hpfs_get_block(struct inode *inode, long iblock, struct buffer_head *bh_resu ...@@ -93,7 +93,7 @@ int hpfs_get_block(struct inode *inode, long iblock, struct buffer_head *bh_resu
return 0; return 0;
} }
static int hpfs_writepage(struct file *file, struct page *page) static int hpfs_writepage(struct page *page)
{ {
return block_write_full_page(page,hpfs_get_block); return block_write_full_page(page,hpfs_get_block);
} }
......
...@@ -396,7 +396,7 @@ struct buffer_head * minix_bread(struct inode * inode, int block, int create) ...@@ -396,7 +396,7 @@ struct buffer_head * minix_bread(struct inode * inode, int block, int create)
return NULL; return NULL;
} }
static int minix_writepage(struct file *file, struct page *page) static int minix_writepage(struct page *page)
{ {
return block_write_full_page(page,minix_get_block); return block_write_full_page(page,minix_get_block);
} }
......
...@@ -250,20 +250,17 @@ nfs_writepage_async(struct file *file, struct inode *inode, struct page *page, ...@@ -250,20 +250,17 @@ nfs_writepage_async(struct file *file, struct inode *inode, struct page *page,
* Write an mmapped page to the server. * Write an mmapped page to the server.
*/ */
int int
nfs_writepage(struct file *file, struct page *page) nfs_writepage(struct page *page)
{ {
struct inode *inode; struct inode *inode;
unsigned long end_index; unsigned long end_index;
unsigned offset = PAGE_CACHE_SIZE; unsigned offset = PAGE_CACHE_SIZE;
int err; int err;
if (!file) {
struct address_space *mapping = page->mapping; struct address_space *mapping = page->mapping;
if (!mapping) if (!mapping)
BUG(); BUG();
inode = (struct inode *)mapping->host; inode = (struct inode *)mapping->host;
} else
inode = file->f_dentry->d_inode;
if (!inode) if (!inode)
BUG(); BUG();
end_index = inode->i_size >> PAGE_CACHE_SHIFT; end_index = inode->i_size >> PAGE_CACHE_SHIFT;
...@@ -276,21 +273,25 @@ nfs_writepage(struct file *file, struct page *page) ...@@ -276,21 +273,25 @@ nfs_writepage(struct file *file, struct page *page)
goto do_it; goto do_it;
/* things got complicated... */ /* things got complicated... */
offset = inode->i_size & (PAGE_CACHE_SIZE-1); offset = inode->i_size & (PAGE_CACHE_SIZE-1);
/* OK, are we completely out? */ /* OK, are we completely out? */
err = -EIO;
if (page->index >= end_index+1 || !offset) if (page->index >= end_index+1 || !offset)
return -EIO; goto out;
do_it: do_it:
if (!PageError(page) && NFS_SERVER(inode)->rsize >= PAGE_CACHE_SIZE) { if (!PageError(page) && NFS_SERVER(inode)->rsize >= PAGE_CACHE_SIZE) {
err = nfs_writepage_async(file, inode, page, 0, offset); err = nfs_writepage_async(NULL, inode, page, 0, offset);
if (err >= 0) if (err >= 0)
goto out_ok; goto out_ok;
} }
err = nfs_writepage_sync(file, inode, page, 0, offset); err = nfs_writepage_sync(NULL, inode, page, 0, offset);
if ( err == offset) if ( err == offset) {
goto out_ok; out_ok:
err = 0;
}
out:
UnlockPage(page);
return err; return err;
out_ok:
return 0;
} }
/* /*
......
...@@ -590,7 +590,7 @@ static struct inode_operations ntfs_dir_inode_operations = { ...@@ -590,7 +590,7 @@ static struct inode_operations ntfs_dir_inode_operations = {
}; };
/* /*
static int ntfs_writepage(struct file *file, struct page *page) static int ntfs_writepage(struct page *page)
{ {
return block_write_full_page(page,ntfs_get_block); return block_write_full_page(page,ntfs_get_block);
} }
......
...@@ -415,7 +415,7 @@ static void qnx4_put_super(struct super_block *sb) ...@@ -415,7 +415,7 @@ static void qnx4_put_super(struct super_block *sb)
return; return;
} }
static int qnx4_writepage(struct file *file, struct page *page) static int qnx4_writepage(struct page *page)
{ {
return block_write_full_page(page,qnx4_get_block); return block_write_full_page(page,qnx4_get_block);
} }
......
...@@ -78,7 +78,7 @@ static int ramfs_readpage(struct file *file, struct page * page) ...@@ -78,7 +78,7 @@ static int ramfs_readpage(struct file *file, struct page * page)
* Writing: just make sure the page gets marked dirty, so that * Writing: just make sure the page gets marked dirty, so that
* the page stealer won't grab it. * the page stealer won't grab it.
*/ */
static int ramfs_writepage(struct file *file, struct page *page) static int ramfs_writepage(struct page *page)
{ {
SetPageDirty(page); SetPageDirty(page);
return 0; return 0;
......
...@@ -916,7 +916,7 @@ struct buffer_head *sysv_file_bread(struct inode *inode, int block, int create) ...@@ -916,7 +916,7 @@ struct buffer_head *sysv_file_bread(struct inode *inode, int block, int create)
return NULL; return NULL;
} }
static int sysv_writepage(struct file *file, struct page *page) static int sysv_writepage(struct page *page)
{ {
return block_write_full_page(page,sysv_get_block); return block_write_full_page(page,sysv_get_block);
} }
......
...@@ -67,7 +67,7 @@ static int udf_adinicb_readpage(struct file *file, struct page * page) ...@@ -67,7 +67,7 @@ static int udf_adinicb_readpage(struct file *file, struct page * page)
return 0; return 0;
} }
static int udf_adinicb_writepage(struct file *file, struct page *page) static int udf_adinicb_writepage(struct page *page)
{ {
struct inode *inode = (struct inode *)page->mapping->host; struct inode *inode = (struct inode *)page->mapping->host;
......
...@@ -125,7 +125,7 @@ void udf_discard_prealloc(struct inode * inode) ...@@ -125,7 +125,7 @@ void udf_discard_prealloc(struct inode * inode)
udf_trunc(inode); udf_trunc(inode);
} }
static int udf_writepage(struct file *file, struct page *page) static int udf_writepage(struct page *page)
{ {
return block_write_full_page(page, udf_get_block); return block_write_full_page(page, udf_get_block);
} }
......
...@@ -518,7 +518,7 @@ struct buffer_head * ufs_bread (struct inode * inode, unsigned fragment, ...@@ -518,7 +518,7 @@ struct buffer_head * ufs_bread (struct inode * inode, unsigned fragment,
return NULL; return NULL;
} }
static int ufs_writepage(struct file *file, struct page *page) static int ufs_writepage(struct page *page)
{ {
return block_write_full_page(page,ufs_getfrag_block); return block_write_full_page(page,ufs_getfrag_block);
} }
......
...@@ -352,7 +352,7 @@ struct page; ...@@ -352,7 +352,7 @@ struct page;
struct address_space; struct address_space;
struct address_space_operations { struct address_space_operations {
int (*writepage)(struct file *, struct page *); int (*writepage)(struct page *);
int (*readpage)(struct file *, struct page *); int (*readpage)(struct file *, struct page *);
int (*sync_page)(struct page *); int (*sync_page)(struct page *);
int (*prepare_write)(struct file *, struct page *, unsigned, unsigned); int (*prepare_write)(struct file *, struct page *, unsigned, unsigned);
......
...@@ -204,7 +204,7 @@ typedef struct page { ...@@ -204,7 +204,7 @@ typedef struct page {
*/ */
#define UnlockPage(page) do { \ #define UnlockPage(page) do { \
smp_mb__before_clear_bit(); \ smp_mb__before_clear_bit(); \
clear_bit(PG_locked, &(page)->flags); \ if (!test_and_clear_bit(PG_locked, &(page)->flags)) BUG(); \
smp_mb__after_clear_bit(); \ smp_mb__after_clear_bit(); \
if (waitqueue_active(&page->wait)) \ if (waitqueue_active(&page->wait)) \
wake_up(&page->wait); \ wake_up(&page->wait); \
......
...@@ -192,7 +192,7 @@ extern void nfs_complete_unlink(struct dentry *); ...@@ -192,7 +192,7 @@ extern void nfs_complete_unlink(struct dentry *);
/* /*
* linux/fs/nfs/write.c * linux/fs/nfs/write.c
*/ */
extern int nfs_writepage(struct file *file, struct page *); extern int nfs_writepage(struct page *);
extern int nfs_flush_incompatible(struct file *file, struct page *page); extern int nfs_flush_incompatible(struct file *file, struct page *page);
extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int); extern int nfs_updatepage(struct file *, struct page *, unsigned int, unsigned int);
/* /*
......
...@@ -1469,15 +1469,15 @@ struct page * filemap_nopage(struct vm_area_struct * area, ...@@ -1469,15 +1469,15 @@ struct page * filemap_nopage(struct vm_area_struct * area,
* The "mapping" test takes care of somebody having truncated the * The "mapping" test takes care of somebody having truncated the
* page and thus made this write-page a no-op.. * page and thus made this write-page a no-op..
*/ */
static int filemap_write_page(struct file *file, static int filemap_write_page(struct page * page, int wait)
struct page * page,
int wait)
{ {
struct address_space * mapping = page->mapping; struct address_space * mapping = page->mapping;
int error = 0; int error = 0;
if (mapping) if (mapping && mapping->a_ops->writepage) {
error = mapping->a_ops->writepage(file, page); ClearPageDirty(page);
error = mapping->a_ops->writepage(page);
}
return error; return error;
} }
...@@ -1490,11 +1490,8 @@ static int filemap_write_page(struct file *file, ...@@ -1490,11 +1490,8 @@ static int filemap_write_page(struct file *file,
extern void wakeup_bdflush(int); extern void wakeup_bdflush(int);
int filemap_swapout(struct page * page, struct file *file) int filemap_swapout(struct page * page, struct file *file)
{ {
int error; SetPageDirty(page);
return 0;
error = filemap_write_page(file, page, 0);
wakeup_bdflush(0);
return error;
} }
/* Called with mm->page_table_lock held to protect against other /* Called with mm->page_table_lock held to protect against other
...@@ -1503,56 +1500,26 @@ int filemap_swapout(struct page * page, struct file *file) ...@@ -1503,56 +1500,26 @@ int filemap_swapout(struct page * page, struct file *file)
static inline int filemap_sync_pte(pte_t * ptep, struct vm_area_struct *vma, static inline int filemap_sync_pte(pte_t * ptep, struct vm_area_struct *vma,
unsigned long address, unsigned int flags) unsigned long address, unsigned int flags)
{ {
unsigned long pgoff;
pte_t pte; pte_t pte;
struct page *page; struct page *page;
int error; int error;
pte = *ptep; pte = *ptep;
if (!(flags & MS_INVALIDATE)) {
if (!pte_present(pte)) if (!pte_present(pte))
goto out; goto out;
if (!ptep_test_and_clear_dirty(ptep)) if (!ptep_test_and_clear_dirty(ptep))
goto out; goto out;
flush_page_to_ram(pte_page(pte)); flush_page_to_ram(pte_page(pte));
flush_cache_page(vma, address); flush_cache_page(vma, address);
flush_tlb_page(vma, address); flush_tlb_page(vma, address);
page = pte_page(pte); page = pte_page(pte);
page_cache_get(page); page_cache_get(page);
} else {
if (pte_none(pte))
goto out;
flush_cache_page(vma, address);
pte = ptep_get_and_clear(ptep);
flush_tlb_page(vma, address);
if (!pte_present(pte)) {
spin_unlock(&vma->vm_mm->page_table_lock); spin_unlock(&vma->vm_mm->page_table_lock);
swap_free(pte_to_swp_entry(pte));
spin_lock(&vma->vm_mm->page_table_lock);
goto out;
}
page = pte_page(pte);
if (!pte_dirty(pte) || flags == MS_INVALIDATE) {
page_cache_free(page);
goto out;
}
}
pgoff = (address - vma->vm_start) >> PAGE_CACHE_SHIFT;
pgoff += vma->vm_pgoff;
if (page->index != pgoff) {
printk("weirdness: pgoff=%lu index=%lu address=%lu vm_start=%lu vm_pgoff=%lu\n",
pgoff, page->index, address, vma->vm_start, vma->vm_pgoff);
}
spin_unlock(&vma->vm_mm->page_table_lock);
lock_page(page); lock_page(page);
error = filemap_write_page(page, 1);
error = filemap_write_page(vma->vm_file, page, 1);
UnlockPage(page);
page_cache_free(page); page_cache_free(page);
spin_lock(&vma->vm_mm->page_table_lock); spin_lock(&vma->vm_mm->page_table_lock);
...@@ -1650,21 +1617,12 @@ int filemap_sync(struct vm_area_struct * vma, unsigned long address, ...@@ -1650,21 +1617,12 @@ int filemap_sync(struct vm_area_struct * vma, unsigned long address,
return error; return error;
} }
/*
* This handles (potentially partial) area unmaps..
*/
static void filemap_unmap(struct vm_area_struct *vma, unsigned long start, size_t len)
{
filemap_sync(vma, start, len, MS_ASYNC);
}
/* /*
* Shared mappings need to be able to do the right thing at * Shared mappings need to be able to do the right thing at
* close/unmap/sync. They will also use the private file as * close/unmap/sync. They will also use the private file as
* backing-store for swapping.. * backing-store for swapping..
*/ */
static struct vm_operations_struct file_shared_mmap = { static struct vm_operations_struct file_shared_mmap = {
unmap: filemap_unmap, /* unmap - we need to sync the pages */
sync: filemap_sync, sync: filemap_sync,
nopage: filemap_nopage, nopage: filemap_nopage,
swapout: filemap_swapout, swapout: filemap_swapout,
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
#include <asm/pgtable.h> #include <asm/pgtable.h>
static int swap_writepage(struct file *file, struct page *page) static int swap_writepage(struct page *page)
{ {
rw_swap_page(WRITE, page, 0); rw_swap_page(WRITE, page, 0);
return 0; return 0;
......
...@@ -602,7 +602,7 @@ int page_launder(int gfp_mask, int sync) ...@@ -602,7 +602,7 @@ int page_launder(int gfp_mask, int sync)
* last copy.. * last copy..
*/ */
if (PageDirty(page)) { if (PageDirty(page)) {
int (*writepage)(struct file *, struct page *) = page->mapping->a_ops->writepage; int (*writepage)(struct page *) = page->mapping->a_ops->writepage;
if (!writepage) if (!writepage)
goto page_active; goto page_active;
...@@ -619,12 +619,12 @@ int page_launder(int gfp_mask, int sync) ...@@ -619,12 +619,12 @@ int page_launder(int gfp_mask, int sync)
page_cache_get(page); page_cache_get(page);
spin_unlock(&pagemap_lru_lock); spin_unlock(&pagemap_lru_lock);
writepage(NULL, page); writepage(page);
UnlockPage(page);
page_cache_release(page); page_cache_release(page);
/* And re-start the thing.. */ /* And re-start the thing.. */
goto dirty_page_rescan; spin_lock(&pagemap_lru_lock);
continue;
} }
/* /*
......
...@@ -89,10 +89,8 @@ struct ipt_table_info ...@@ -89,10 +89,8 @@ struct ipt_table_info
unsigned int hook_entry[NF_IP_NUMHOOKS]; unsigned int hook_entry[NF_IP_NUMHOOKS];
unsigned int underflow[NF_IP_NUMHOOKS]; unsigned int underflow[NF_IP_NUMHOOKS];
char padding[SMP_ALIGN((NF_IP_NUMHOOKS*2+2)*sizeof(unsigned int))];
/* ipt_entry tables: one per CPU */ /* ipt_entry tables: one per CPU */
char entries[0]; char entries[0] __attribute__((aligned(SMP_CACHE_BYTES)));
}; };
static LIST_HEAD(ipt_target); static LIST_HEAD(ipt_target);
...@@ -101,7 +99,7 @@ static LIST_HEAD(ipt_tables); ...@@ -101,7 +99,7 @@ static LIST_HEAD(ipt_tables);
#define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0) #define ADD_COUNTER(c,b,p) do { (c).bcnt += (b); (c).pcnt += (p); } while(0)
#ifdef CONFIG_SMP #ifdef CONFIG_SMP
#define TABLE_OFFSET(t,p) (SMP_ALIGN((t)->size)*cpu_number_map(p)) #define TABLE_OFFSET(t,p) (SMP_ALIGN((t)->size)*(p))
#else #else
#define TABLE_OFFSET(t,p) 0 #define TABLE_OFFSET(t,p) 0
#endif #endif
...@@ -283,7 +281,8 @@ ipt_do_table(struct sk_buff **pskb, ...@@ -283,7 +281,8 @@ ipt_do_table(struct sk_buff **pskb,
read_lock_bh(&table->lock); read_lock_bh(&table->lock);
IP_NF_ASSERT(table->valid_hooks & (1 << hook)); IP_NF_ASSERT(table->valid_hooks & (1 << hook));
table_base = (void *)table->private->entries table_base = (void *)table->private->entries
+ TABLE_OFFSET(table->private, smp_processor_id()); + TABLE_OFFSET(table->private,
cpu_number_map(smp_processor_id()));
e = get_entry(table_base, table->private->hook_entry[hook]); e = get_entry(table_base, table->private->hook_entry[hook]);
#ifdef CONFIG_NETFILTER_DEBUG #ifdef CONFIG_NETFILTER_DEBUG
...@@ -860,7 +859,7 @@ translate_table(const char *name, ...@@ -860,7 +859,7 @@ translate_table(const char *name,
/* And one copy for every other CPU */ /* And one copy for every other CPU */
for (i = 1; i < smp_num_cpus; i++) { for (i = 1; i < smp_num_cpus; i++) {
memcpy(newinfo->entries + SMP_ALIGN(newinfo->size*i), memcpy(newinfo->entries + SMP_ALIGN(newinfo->size)*i,
newinfo->entries, newinfo->entries,
SMP_ALIGN(newinfo->size)); SMP_ALIGN(newinfo->size));
} }
...@@ -1359,7 +1358,7 @@ int ipt_register_table(struct ipt_table *table) ...@@ -1359,7 +1358,7 @@ int ipt_register_table(struct ipt_table *table)
int ret; int ret;
struct ipt_table_info *newinfo; struct ipt_table_info *newinfo;
static struct ipt_table_info bootstrap static struct ipt_table_info bootstrap
= { 0, 0, { 0 }, { 0 }, { }, { } }; = { 0, 0, { 0 }, { 0 }, { } };
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
newinfo = vmalloc(sizeof(struct ipt_table_info) newinfo = vmalloc(sizeof(struct ipt_table_info)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment