Commit 6444d1a1 authored by Linus Torvalds's avatar Linus Torvalds

Merge http://gkernel.bkbits.net/vm-2.5

into penguin.transmeta.com:/home/penguin/torvalds/repositories/kernel/linux
parents 531d56ec 61d292a7
......@@ -1154,6 +1154,17 @@ CONFIG_NATSEMI
More specific information and updates are available from
<http://www.scyld.com/network/natsemi.html>.
CONFIG_NATSEMI_CABLE_MAGIC
Some systems see lots of errors with NatSemi ethernet controllers
on certain cables. If you are seeing lots of errors, try turning
this option on. Some boards have incorrect values for supporting
resistors that can cause this change to break. If you turn this
option on and your network suddenly stops working, turn this
option off.
Say N unless you are certain you need this option.
Vendors should not enable this option by default.
CONFIG_SK_G16
If you have a network (Ethernet) card of this type, say Y and read
the Ethernet-HOWTO, available from
......
......@@ -171,6 +171,9 @@ if [ "$CONFIG_NET_ETHERNET" = "y" ]; then
dep_tristate ' Mylex EISA LNE390A/B support (EXPERIMENTAL)' CONFIG_LNE390 $CONFIG_EISA $CONFIG_EXPERIMENTAL
dep_tristate ' Myson MTD-8xx PCI Ethernet support' CONFIG_FEALNX $CONFIG_PCI
dep_tristate ' National Semiconductor DP8381x series PCI Ethernet support' CONFIG_NATSEMI $CONFIG_PCI
if [ "$CONFIG_NATSEMI" = "y" -o "$CONFIG_NATSEMI" = "m" ]; then
bool ' NatSemi workaround for high errors' CONFIG_NATSEMI_CABLE_MAGIC
fi
dep_tristate ' PCI NE2000 and clones support (see help)' CONFIG_NE2K_PCI $CONFIG_PCI
dep_tristate ' Novell/Eagle/Microdyne NE3210 EISA support (EXPERIMENTAL)' CONFIG_NE3210 $CONFIG_EISA $CONFIG_EXPERIMENTAL
dep_tristate ' Racal-Interlan EISA ES3210 support (EXPERIMENTAL)' CONFIG_ES3210 $CONFIG_EISA $CONFIG_EXPERIMENTAL
......
......@@ -991,6 +991,11 @@ speedo_open(struct net_device *dev)
if ((sp->phy[0] & 0x8000) == 0)
sp->advertising = mdio_read(ioaddr, sp->phy[0] & 0x1f, 4);
if (mdio_read(ioaddr, sp->phy[0] & 0x1f, MII_BMSR) & BMSR_LSTATUS)
netif_carrier_on(dev);
else
netif_carrier_off(dev);
if (speedo_debug > 2) {
printk(KERN_DEBUG "%s: Done speedo_open(), status %8.8x.\n",
dev->name, inw(ioaddr + SCBStatus));
......@@ -1102,7 +1107,7 @@ static void speedo_timer(unsigned long data)
/* Clear sticky bit. */
mdio_read(ioaddr, phy_num, 1);
/* If link beat has returned... */
if (mdio_read(ioaddr, phy_num, 1) & 0x0004)
if (mdio_read(ioaddr, phy_num, MII_BMSR) & BMSR_LSTATUS)
netif_carrier_on(dev);
else
netif_carrier_off(dev);
......
......@@ -394,7 +394,11 @@ enum register_offsets {
SDCFG = 0xF8
};
/* the values for the 'magic' registers above (PGSEL=1) */
#ifdef CONFIG_NATSEMI_CABLE_MAGIC
#define PMDCSR_VAL 0x1898
#else
#define PMDCSR_VAL 0x189C
#endif
#define TSTDAT_VAL 0x0
#define DSPCFG_VAL 0x5040
#define SDCFG_VAL 0x008c
......@@ -1511,7 +1515,7 @@ static void intr_handler(int irq, void *dev_instance, struct pt_regs *rgs)
if (intr_status == 0)
break;
if (intr_status & (IntrRxDone | IntrRxIntr))
if (intr_status & (IntrRxDone | IntrRxIntr | RxStatusFIFOOver | IntrRxErr | IntrRxOverrun ))
netdev_rx(dev);
if (intr_status & (IntrTxDone | IntrTxIntr | IntrTxIdle | IntrTxErr) ) {
......
......@@ -65,15 +65,15 @@ static struct net_device *pcnet32_dev;
static const int max_interrupt_work = 80;
static const int rx_copybreak = 200;
#define PORT_AUI 0x00
#define PORT_10BT 0x01
#define PORT_GPSI 0x02
#define PORT_MII 0x03
#define PCNET32_PORT_AUI 0x00
#define PCNET32_PORT_10BT 0x01
#define PCNET32_PORT_GPSI 0x02
#define PCNET32_PORT_MII 0x03
#define PORT_PORTSEL 0x03
#define PORT_ASEL 0x04
#define PORT_100 0x40
#define PORT_FD 0x80
#define PCNET32_PORT_PORTSEL 0x03
#define PCNET32_PORT_ASEL 0x04
#define PCNET32_PORT_100 0x40
#define PCNET32_PORT_FD 0x80
#define PCNET32_DMA_MASK 0xffffffff
......@@ -82,22 +82,22 @@ static const int rx_copybreak = 200;
* to internal options
*/
static unsigned char options_mapping[] = {
PORT_ASEL, /* 0 Auto-select */
PORT_AUI, /* 1 BNC/AUI */
PORT_AUI, /* 2 AUI/BNC */
PORT_ASEL, /* 3 not supported */
PORT_10BT | PORT_FD, /* 4 10baseT-FD */
PORT_ASEL, /* 5 not supported */
PORT_ASEL, /* 6 not supported */
PORT_ASEL, /* 7 not supported */
PORT_ASEL, /* 8 not supported */
PORT_MII, /* 9 MII 10baseT */
PORT_MII | PORT_FD, /* 10 MII 10baseT-FD */
PORT_MII, /* 11 MII (autosel) */
PORT_10BT, /* 12 10BaseT */
PORT_MII | PORT_100, /* 13 MII 100BaseTx */
PORT_MII | PORT_100 | PORT_FD, /* 14 MII 100BaseTx-FD */
PORT_ASEL /* 15 not supported */
PCNET32_PORT_ASEL, /* 0 Auto-select */
PCNET32_PORT_AUI, /* 1 BNC/AUI */
PCNET32_PORT_AUI, /* 2 AUI/BNC */
PCNET32_PORT_ASEL, /* 3 not supported */
PCNET32_PORT_10BT | PCNET32_PORT_FD, /* 4 10baseT-FD */
PCNET32_PORT_ASEL, /* 5 not supported */
PCNET32_PORT_ASEL, /* 6 not supported */
PCNET32_PORT_ASEL, /* 7 not supported */
PCNET32_PORT_ASEL, /* 8 not supported */
PCNET32_PORT_MII, /* 9 MII 10baseT */
PCNET32_PORT_MII | PCNET32_PORT_FD, /* 10 MII 10baseT-FD */
PCNET32_PORT_MII, /* 11 MII (autosel) */
PCNET32_PORT_10BT, /* 12 10BaseT */
PCNET32_PORT_MII | PCNET32_PORT_100, /* 13 MII 100BaseTx */
PCNET32_PORT_MII | PCNET32_PORT_100 | PCNET32_PORT_FD, /* 14 MII 100BaseTx-FD */
PCNET32_PORT_ASEL /* 15 not supported */
};
#define MAX_UNITS 8
......@@ -709,12 +709,12 @@ pcnet32_probe1(unsigned long ioaddr, unsigned char irq_line, int shared, int car
lp->ltint = ltint;
lp->mii = mii;
if (options[card_idx] > sizeof (options_mapping))
lp->options = PORT_ASEL;
lp->options = PCNET32_PORT_ASEL;
else
lp->options = options_mapping[options[card_idx]];
if (fdx && !(lp->options & PORT_ASEL) && full_duplex[card_idx])
lp->options |= PORT_FD;
if (fdx && !(lp->options & PCNET32_PORT_ASEL) && full_duplex[card_idx])
lp->options |= PCNET32_PORT_FD;
if (a == NULL) {
printk(KERN_ERR "pcnet32: No access methods\n");
......@@ -726,7 +726,7 @@ pcnet32_probe1(unsigned long ioaddr, unsigned char irq_line, int shared, int car
/* detect special T1/E1 WAN card by checking for MAC address */
if (dev->dev_addr[0] == 0x00 && dev->dev_addr[1] == 0xe0 && dev->dev_addr[2] == 0x75)
lp->options = PORT_FD | PORT_GPSI;
lp->options = PCNET32_PORT_FD | PCNET32_PORT_GPSI;
lp->init_block.mode = le16_to_cpu(0x0003); /* Disable Rx and Tx. */
lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);
......@@ -829,16 +829,16 @@ pcnet32_open(struct net_device *dev)
/* set/reset autoselect bit */
val = lp->a.read_bcr (ioaddr, 2) & ~2;
if (lp->options & PORT_ASEL)
if (lp->options & PCNET32_PORT_ASEL)
val |= 2;
lp->a.write_bcr (ioaddr, 2, val);
/* handle full duplex setting */
if (lp->full_duplex) {
val = lp->a.read_bcr (ioaddr, 9) & ~3;
if (lp->options & PORT_FD) {
if (lp->options & PCNET32_PORT_FD) {
val |= 1;
if (lp->options == (PORT_FD | PORT_AUI))
if (lp->options == (PCNET32_PORT_FD | PCNET32_PORT_AUI))
val |= 2;
}
lp->a.write_bcr (ioaddr, 9, val);
......@@ -846,19 +846,19 @@ pcnet32_open(struct net_device *dev)
/* set/reset GPSI bit in test register */
val = lp->a.read_csr (ioaddr, 124) & ~0x10;
if ((lp->options & PORT_PORTSEL) == PORT_GPSI)
if ((lp->options & PCNET32_PORT_PORTSEL) == PCNET32_PORT_GPSI)
val |= 0x10;
lp->a.write_csr (ioaddr, 124, val);
if (lp->mii && !(lp->options & PORT_ASEL)) {
if (lp->mii && !(lp->options & PCNET32_PORT_ASEL)) {
val = lp->a.read_bcr (ioaddr, 32) & ~0x38; /* disable Auto Negotiation, set 10Mpbs, HD */
if (lp->options & PORT_FD)
if (lp->options & PCNET32_PORT_FD)
val |= 0x10;
if (lp->options & PORT_100)
if (lp->options & PCNET32_PORT_100)
val |= 0x08;
lp->a.write_bcr (ioaddr, 32, val);
} else {
if (lp->options & PORT_ASEL) { /* enable auto negotiate, setup, disable fd */
if (lp->options & PCNET32_PORT_ASEL) { /* enable auto negotiate, setup, disable fd */
val = lp->a.read_bcr(ioaddr, 32) & ~0x98;
val |= 0x20;
lp->a.write_bcr(ioaddr, 32, val);
......@@ -878,7 +878,7 @@ pcnet32_open(struct net_device *dev)
lp->a.write_csr (ioaddr, 5, val);
}
lp->init_block.mode = le16_to_cpu((lp->options & PORT_PORTSEL) << 7);
lp->init_block.mode = le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);
lp->init_block.filter[0] = 0x00000000;
lp->init_block.filter[1] = 0x00000000;
if (pcnet32_init_ring(dev))
......@@ -1465,9 +1465,9 @@ static void pcnet32_set_multicast_list(struct net_device *dev)
if (dev->flags&IFF_PROMISC) {
/* Log any net taps. */
printk(KERN_INFO "%s: Promiscuous mode enabled.\n", dev->name);
lp->init_block.mode = le16_to_cpu(0x8000 | (lp->options & PORT_PORTSEL) << 7);
lp->init_block.mode = le16_to_cpu(0x8000 | (lp->options & PCNET32_PORT_PORTSEL) << 7);
} else {
lp->init_block.mode = le16_to_cpu((lp->options & PORT_PORTSEL) << 7);
lp->init_block.mode = le16_to_cpu((lp->options & PCNET32_PORT_PORTSEL) << 7);
pcnet32_load_multicast (dev);
}
......
......@@ -39,8 +39,13 @@ void t21142_timer(unsigned long data)
printk(KERN_INFO"%s: 21143 negotiation status %8.8x, %s.\n",
dev->name, csr12, medianame[dev->if_port]);
if (tulip_media_cap[dev->if_port] & MediaIsMII) {
tulip_check_duplex(dev);
if (tulip_check_duplex(dev) < 0) {
netif_carrier_off(dev);
next_tick = 3*HZ;
} else {
netif_carrier_on(dev);
next_tick = 60*HZ;
}
} else if (tp->nwayset) {
/* Don't screw up a negotiated session! */
if (tulip_debug > 1)
......
2002-01-28 Stefan Rompf <srompf@isg.de>,
Jeff Garzik <jgarzik@mandrakesoft.com>
* 21142.c (t21142_timer): Use return value of
tulip_check_duplex() to indicate to system whether or not
carrier is present. Use carrier presence/absence to determine
when next the 21142 media timer should check for link beat.
* timer (tulip_timer): Un-comment-out calls to
netif_carrier_{on,off}, as there is now value in
reporting link beta information to userspace.
2002-01-28 Pavel Roskin <proski@gnu.org>
* tulip_core.c (tulip_init_one): Use tp->eeprom instead of
allocating a buffer for EEPROM copy on the stack.
* tulip_core.c: Add support for Conexant RS7112 (a.k.a. CN7112)
chip.
* tulip.h: Likewise. Increase EEPROM_SIZE to 512 bytes to
accomodate EEPROM on Conexant RS7112.
2002-02-07 Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>
* tulip_core (tulip_pci_tbl[]):
......
......@@ -83,10 +83,10 @@ void tulip_timer(unsigned long data)
medianame[mleaf->media & MEDIA_MASK]);
if ((p[2] & 0x61) == 0x01) /* Bogus Znyx board. */
goto actually_mii;
/* netif_carrier_on(dev); */
netif_carrier_on(dev);
break;
}
/* netif_carrier_off(dev); */
netif_carrier_off(dev);
if (tp->medialock)
break;
select_next_media:
......@@ -110,11 +110,13 @@ void tulip_timer(unsigned long data)
}
case 1: case 3: /* 21140, 21142 MII */
actually_mii:
if (tulip_check_duplex(dev) < 0)
{ /* netif_carrier_off(dev); */ }
else
{ /* netif_carrier_on(dev); */ }
if (tulip_check_duplex(dev) < 0) {
netif_carrier_off(dev);
next_tick = 3*HZ;
} else {
netif_carrier_on(dev);
next_tick = 60*HZ;
}
break;
case 2: /* 21142 serial block has no link beat. */
default:
......
......@@ -84,6 +84,7 @@ enum chips {
COMPEX9881,
I21145,
DM910X,
CONEXANT,
};
......@@ -290,7 +291,7 @@ enum t21143_csr6_bits {
#define DESC_RING_WRAP 0x02000000
#define EEPROM_SIZE 128 /* 2 << EEPROM_ADDRLEN */
#define EEPROM_SIZE 512 /* 2 << EEPROM_ADDRLEN */
#define RUN_AT(x) (jiffies + (x))
......
......@@ -15,8 +15,8 @@
*/
#define DRV_NAME "tulip"
#define DRV_VERSION "1.1.0"
#define DRV_RELDATE "Dec 11, 2001"
#define DRV_VERSION "1.1.11"
#define DRV_RELDATE "Feb 08, 2002"
#include <linux/config.h>
#include <linux/module.h>
......@@ -185,6 +185,10 @@ struct tulip_chip_table tulip_tbl[] = {
{ "Davicom DM9102/DM9102A", 128, 0x0001ebef,
HAS_MII | HAS_MEDIA_TABLE | CSR12_IN_SROM | HAS_ACPI,
tulip_timer },
/* RS7112 */
{ "Conexant LANfinity", 256, 0x0001ebef,
HAS_MII | HAS_ACPI, tulip_timer },
};
......@@ -212,6 +216,7 @@ static struct pci_device_id tulip_pci_tbl[] __devinitdata = {
{ 0x1113, 0x1216, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x1113, 0x1217, PCI_ANY_ID, PCI_ANY_ID, 0, 0, MX98715 },
{ 0x1113, 0x9511, PCI_ANY_ID, PCI_ANY_ID, 0, 0, COMET },
{ 0x14f1, 0x1803, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CONEXANT },
{ } /* terminate list */
};
MODULE_DEVICE_TABLE(pci, tulip_pci_tbl);
......@@ -418,7 +423,7 @@ static void tulip_up(struct net_device *dev)
tp->csr6 = 0x01a80200;
outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80);
outl(0x11000 | inw(ioaddr + 0xa0), ioaddr + 0xa0);
} else if (tp->chip_id == COMET) {
} else if (tp->chip_id == COMET || tp->chip_id == CONEXANT) {
/* Enable automatic Tx underrun recovery. */
outl(inl(ioaddr + 0x88) | 1, ioaddr + 0x88);
dev->if_port = tp->mii_cnt ? 11 : 0;
......@@ -1254,7 +1259,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
u8 chip_rev;
int i, irq;
unsigned short sum;
u8 ee_data[EEPROM_SIZE];
unsigned char *ee_data;
struct net_device *dev;
long ioaddr;
static int board_idx = -1;
......@@ -1431,6 +1436,7 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
be polled, waiting for the value to be read bit serially from the
EEPROM.
*/
ee_data = tp->eeprom;
sum = 0;
if (chip_idx == LC82C168) {
for (i = 0; i < 3; i++) {
......@@ -1453,17 +1459,22 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
int sa_offset = 0;
int ee_addr_size = tulip_read_eeprom(ioaddr, 0xff, 8) & 0x40000 ? 8 : 6;
for (i = 0; i < sizeof(ee_data)/2; i++)
for (i = 0; i < sizeof(tp->eeprom)/2; i++)
((u16 *)ee_data)[i] =
le16_to_cpu(tulip_read_eeprom(ioaddr, i, ee_addr_size));
/* DEC now has a specification (see Notes) but early board makers
just put the address in the first EEPROM locations. */
/* This does memcmp(eedata, eedata+16, 8) */
/* This does memcmp(ee_data, ee_data+16, 8) */
for (i = 0; i < 8; i ++)
if (ee_data[i] != ee_data[16+i])
sa_offset = 20;
if (ee_data[0] == 0xff && ee_data[1] == 0xff && ee_data[2] == 0) {
if (chip_idx == CONEXANT) {
/* Check that the tuple type and length is correct. */
if (ee_data[0x198] == 0x04 && ee_data[0x199] == 6)
sa_offset = 0x19A;
} else if (ee_data[0] == 0xff && ee_data[1] == 0xff &&
ee_data[2] == 0) {
sa_offset = 2; /* Grrr, damn Matrox boards. */
multiport_cnt = 4;
}
......@@ -1556,8 +1567,6 @@ static int __devinit tulip_init_one (struct pci_dev *pdev,
}
if (tp->flags & HAS_MEDIA_TABLE) {
memcpy(tp->eeprom, ee_data, sizeof(tp->eeprom));
sprintf(dev->name, "tulip%d", board_idx); /* hack */
tulip_parse_eeprom(dev);
strcpy(dev->name, "eth%d"); /* un-hack */
......
......@@ -347,7 +347,7 @@ struct netdev_private {
struct w840_rx_desc *rx_ring;
dma_addr_t rx_addr[RX_RING_SIZE];
struct w840_tx_desc *tx_ring;
dma_addr_t tx_addr[RX_RING_SIZE];
dma_addr_t tx_addr[TX_RING_SIZE];
dma_addr_t ring_dma_addr;
/* The addresses of receive-in-place skbuffs. */
struct sk_buff* rx_skbuff[RX_RING_SIZE];
......
......@@ -32,10 +32,9 @@
typedef struct svc_client svc_client;
typedef struct svc_export svc_export;
static svc_export * exp_find(svc_client *clp, kdev_t dev);
static svc_export * exp_parent(svc_client *clp, kdev_t dev,
static svc_export * exp_parent(svc_client *clp, struct super_block *sb,
struct dentry *dentry);
static svc_export * exp_child(svc_client *clp, kdev_t dev,
static svc_export * exp_child(svc_client *clp, struct super_block *sb,
struct dentry *dentry);
static void exp_unexport_all(svc_client *clp);
static void exp_do_unexport(svc_export *unexp);
......@@ -66,40 +65,37 @@ static int want_lock;
static int hash_count;
static DECLARE_WAIT_QUEUE_HEAD( hash_wait );
/*
* Find a client's export for a device.
* Find the client's export entry matching xdev/xino.
*/
static inline svc_export *
exp_find(svc_client *clp, kdev_t dev)
svc_export *
exp_get(svc_client *clp, kdev_t dev, ino_t ino)
{
svc_export * exp;
exp = clp->cl_export[EXPORT_HASH(dev)];
while (exp && !kdev_same(exp->ex_dev, dev))
exp = exp->ex_next;
if (!clp)
return NULL;
for (exp = clp->cl_export[EXPORT_HASH(dev)]; exp; exp = exp->ex_next) {
if (exp->ex_ino == ino && kdev_same(exp->ex_dev, dev))
break;
}
return exp;
}
/*
* Find the client's export entry matching xdev/xino.
*/
svc_export *
exp_get(svc_client *clp, kdev_t dev, ino_t ino)
exp_get_by_name(svc_client *clp, struct vfsmount *mnt, struct dentry *dentry)
{
svc_export * exp;
int hash = EXPORT_HASH(mnt->mnt_sb->s_dev);
svc_export *exp;
if (!clp)
return NULL;
exp = clp->cl_export[EXPORT_HASH(dev)];
if (exp)
do {
if (exp->ex_ino == ino && kdev_same(exp->ex_dev, dev))
goto out;
} while (NULL != (exp = exp->ex_next));
exp = NULL;
out:
for (exp = clp->cl_export[hash]; exp; exp = exp->ex_next) {
if (exp->ex_dentry == dentry && exp->ex_mnt == mnt)
break;
}
return exp;
}
......@@ -107,14 +103,14 @@ exp_get(svc_client *clp, kdev_t dev, ino_t ino)
* Find the export entry for a given dentry. <gam3@acm.org>
*/
static svc_export *
exp_parent(svc_client *clp, kdev_t dev, struct dentry *dentry)
exp_parent(svc_client *clp, struct super_block *sb, struct dentry *dentry)
{
svc_export *exp;
if (clp == NULL)
return NULL;
for (exp = clp->cl_export[EXPORT_HASH(dev)]; exp; exp = exp->ex_next)
for (exp = clp->cl_export[EXPORT_HASH(sb->s_dev)]; exp; exp = exp->ex_next)
if (is_subdir(dentry, exp->ex_dentry))
break;
return exp;
......@@ -126,14 +122,14 @@ exp_parent(svc_client *clp, kdev_t dev, struct dentry *dentry)
* <gam3@acm.org>
*/
static svc_export *
exp_child(svc_client *clp, kdev_t dev, struct dentry *dentry)
exp_child(svc_client *clp, struct super_block *sb, struct dentry *dentry)
{
svc_export *exp;
if (clp == NULL)
return NULL;
for (exp = clp->cl_export[EXPORT_HASH(dev)]; exp; exp = exp->ex_next) {
for (exp = clp->cl_export[EXPORT_HASH(sb->s_dev)]; exp; exp = exp->ex_next) {
struct dentry *ndentry = exp->ex_dentry;
if (ndentry && is_subdir(ndentry->d_parent, dentry))
break;
......@@ -221,12 +217,12 @@ exp_export(struct nfsctl_export *nxp)
goto finish;
}
if ((parent = exp_child(clp, dev, nd.dentry)) != NULL) {
if ((parent = exp_child(clp, inode->i_sb, nd.dentry)) != NULL) {
dprintk("exp_export: export not valid (Rule 3).\n");
goto finish;
}
/* Is this is a sub-export, must be a proper subset of FS */
if ((parent = exp_parent(clp, dev, nd.dentry)) != NULL) {
if ((parent = exp_parent(clp, inode->i_sb, nd.dentry)) != NULL) {
dprintk("exp_export: sub-export not valid (Rule 2).\n");
goto finish;
}
......@@ -380,55 +376,34 @@ exp_unexport(struct nfsctl_export *nxp)
* since its harder to fool a kernel module than a user space program.
*/
int
exp_rootfh(struct svc_client *clp, kdev_t dev, ino_t ino,
char *path, struct knfsd_fh *f, int maxsize)
exp_rootfh(struct svc_client *clp, char *path, struct knfsd_fh *f, int maxsize)
{
struct svc_export *exp;
struct nameidata nd;
struct inode *inode;
struct svc_fh fh;
kdev_t dev;
int err;
err = -EPERM;
if (path) {
/* NB: we probably ought to check that it's NUL-terminated */
if (path_init(path, LOOKUP_POSITIVE, &nd) &&
path_walk(path, &nd)) {
printk("nfsd: exp_rootfh path not found %s", path);
return err;
}
dev = nd.dentry->d_inode->i_dev;
ino = nd.dentry->d_inode->i_ino;
inode = nd.dentry->d_inode;
dev = inode->i_dev;
dprintk("nfsd: exp_rootfh(%s [%p] %s:%02x:%02x/%ld)\n",
path, nd.dentry, clp->cl_ident,
major(dev), minor(dev), (long) ino);
exp = exp_parent(clp, dev, nd.dentry);
} else {
dprintk("nfsd: exp_rootfh(%s:%02x:%02x/%ld)\n",
clp->cl_ident, major(dev), minor(dev), (long) ino);
if ((exp = exp_get(clp, dev, ino))) {
nd.mnt = mntget(exp->ex_mnt);
nd.dentry = dget(exp->ex_dentry);
}
}
major(dev), minor(dev), (long) inode->i_ino);
exp = exp_parent(clp, inode->i_sb, nd.dentry);
if (!exp) {
dprintk("nfsd: exp_rootfh export not found.\n");
goto out;
}
inode = nd.dentry->d_inode;
if (!inode) {
printk("exp_rootfh: Aieee, NULL d_inode\n");
goto out;
}
if (!kdev_same(inode->i_dev, dev) || inode->i_ino != ino) {
printk("exp_rootfh: Aieee, ino/dev mismatch\n");
printk("exp_rootfh: arg[dev(%02x:%02x):ino(%ld)]"
" inode[dev(%02x:%02x):ino(%ld)]\n",
major(dev), minor(dev), (long) ino,
major(inode->i_dev), minor(inode->i_dev), (long) inode->i_ino);
}
/*
* fh must be initialized before calling fh_compose
*/
......
......@@ -37,7 +37,6 @@ static int nfsctl_addclient(struct nfsctl_client *data);
static int nfsctl_delclient(struct nfsctl_client *data);
static int nfsctl_export(struct nfsctl_export *data);
static int nfsctl_unexport(struct nfsctl_export *data);
static int nfsctl_getfh(struct nfsctl_fhparm *, __u8 *);
static int nfsctl_getfd(struct nfsctl_fdparm *, __u8 *);
static int nfsctl_getfs(struct nfsctl_fsparm *, struct knfsd_fh *);
#ifdef notyet
......@@ -125,7 +124,7 @@ nfsctl_getfs(struct nfsctl_fsparm *data, struct knfsd_fh *res)
if (!(clp = exp_getclient(sin)))
err = -EPERM;
else
err = exp_rootfh(clp, NODEV, 0, data->gd_path, res, data->gd_maxlen);
err = exp_rootfh(clp, data->gd_path, res, data->gd_maxlen);
exp_unlock();
return err;
}
......@@ -148,40 +147,7 @@ nfsctl_getfd(struct nfsctl_fdparm *data, __u8 *res)
if (!(clp = exp_getclient(sin)))
err = -EPERM;
else
err = exp_rootfh(clp, NODEV, 0, data->gd_path, &fh, NFS_FHSIZE);
exp_unlock();
if (err == 0) {
if (fh.fh_size > NFS_FHSIZE)
err = -EINVAL;
else {
memset(res,0, NFS_FHSIZE);
memcpy(res, &fh.fh_base, fh.fh_size);
}
}
return err;
}
static inline int
nfsctl_getfh(struct nfsctl_fhparm *data, __u8 *res)
{
struct sockaddr_in *sin;
struct svc_client *clp;
int err = 0;
struct knfsd_fh fh;
if (data->gf_addr.sa_family != AF_INET)
return -EPROTONOSUPPORT;
if (data->gf_version < 2 || data->gf_version > NFSSVC_MAXVERS)
return -EINVAL;
sin = (struct sockaddr_in *)&data->gf_addr;
exp_readlock();
if (!(clp = exp_getclient(sin)))
err = -EPERM;
else
err = exp_rootfh(clp, to_kdev_t(data->gf_dev), data->gf_ino, NULL, &fh, NFS_FHSIZE);
err = exp_rootfh(clp, data->gd_path, &fh, NFS_FHSIZE);
exp_unlock();
if (err == 0) {
......@@ -277,9 +243,6 @@ asmlinkage handle_sys_nfsservctl(int cmd, void *opaque_argp, void *opaque_resp)
err = nfsctl_ugidupdate(&arg->ca_umap);
break;
#endif
case NFSCTL_GETFH:
err = nfsctl_getfh(&arg->ca_getfh, res->cr_getfh);
break;
case NFSCTL_GETFD:
err = nfsctl_getfd(&arg->ca_getfd, res->cr_getfh);
break;
......
......@@ -114,13 +114,12 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
if (isdotent(name, len)) {
if (len==1)
dentry = dget(dparent);
else { /* must be ".." */
/* checking mountpoint crossing is very different when stepping up */
if (dparent == exp->ex_dentry) {
if (!EX_CROSSMNT(exp))
else if (dparent != exp->ex_dentry)
dentry = dget(dparent->d_parent);
else if (!EX_CROSSMNT(exp))
dentry = dget(dparent); /* .. == . just like at / */
else
{
else {
/* checking mountpoint crossing is very different when stepping up */
struct svc_export *exp2 = NULL;
struct dentry *dp;
struct vfsmount *mnt = mntget(exp->ex_mnt);
......@@ -130,10 +129,9 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
dp = dget(dentry->d_parent);
dput(dentry);
dentry = dp;
for ( ; exp2 == NULL && dp->d_parent != dp;
dp=dp->d_parent)
exp2 = exp_get(exp->ex_client, dp->d_inode->i_dev, dp->d_inode->i_ino);
if (exp2==NULL) {
for ( ; !exp2 && dp->d_parent != dp; dp=dp->d_parent)
exp2 = exp_get_by_name(exp->ex_client, mnt, dp);
if (!exp2) {
dput(dentry);
dentry = dget(dparent);
} else {
......@@ -141,9 +139,6 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
}
mntput(mnt);
}
} else
dentry = dget(dparent->d_parent);
}
} else {
fh_lock(fhp);
dentry = lookup_one_len(name, dparent, len);
......@@ -159,9 +154,7 @@ nfsd_lookup(struct svc_rqst *rqstp, struct svc_fh *fhp, const char *name,
struct dentry *mounts = dget(dentry);
while (follow_down(&mnt,&mounts)&&d_mountpoint(mounts))
;
exp2 = exp_get(rqstp->rq_client,
mounts->d_inode->i_dev,
mounts->d_inode->i_ino);
exp2 = exp_get_by_name(rqstp->rq_client, mnt, mounts);
if (exp2 && EX_CROSSMNT(exp2)) {
/* successfully crossed mount point */
exp = exp2;
......@@ -591,6 +584,7 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
mm_segment_t oldfs;
int err;
struct file file;
struct inode *inode;
err = nfsd_open(rqstp, fhp, S_IFREG, MAY_READ, &file);
if (err)
......@@ -598,14 +592,15 @@ nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset,
err = nfserr_perm;
if (!file.f_op->read)
goto out_close;
inode = file.f_dentry->d_inode;
#ifdef MSNFS
if ((fhp->fh_export->ex_flags & NFSEXP_MSNFS) &&
(!lock_may_read(file.f_dentry->d_inode, offset, *count)))
(!lock_may_read(inode, offset, *count)))
goto out_close;
#endif
/* Get readahead parameters */
ra = nfsd_get_raparms(fhp->fh_export->ex_dev, fhp->fh_dentry->d_inode->i_ino);
ra = nfsd_get_raparms(inode->i_dev, inode->i_ino);
if (ra) {
file.f_reada = ra->p_reada;
file.f_ramax = ra->p_ramax;
......
......@@ -1003,8 +1003,7 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry)
ei = PROC_I(inode);
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
inode->i_ino = fake_ino(0, PROC_PID_INO);
ei->file = NULL;
ei->task = NULL;
ei->pde = NULL;
inode->i_mode = S_IFLNK|S_IRWXUGO;
inode->i_uid = inode->i_gid = 0;
inode->i_size = 64;
......
......@@ -90,7 +90,10 @@ void exp_unlock(void);
struct svc_client * exp_getclient(struct sockaddr_in *sin);
void exp_putclient(struct svc_client *clp);
struct svc_export * exp_get(struct svc_client *clp, kdev_t dev, ino_t ino);
int exp_rootfh(struct svc_client *, kdev_t, ino_t,
struct svc_export * exp_get_by_name(struct svc_client *clp,
struct vfsmount *mnt,
struct dentry *dentry);
int exp_rootfh(struct svc_client *,
char *path, struct knfsd_fh *, int maxsize);
int nfserrno(int errno);
void exp_nlmdetach(void);
......
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