Commit 2cfdbda0 authored by Linus Torvalds's avatar Linus Torvalds

Import 1.1.39

parent e19a1bdb
VERSION = 1
PATCHLEVEL = 1
SUBLEVEL = 38
SUBLEVEL = 39
all: Version zImage
......
IDE Performance Enhancements Version 2.1
============================ ===========
This hard disk driver (hd.c) includes support for IDE Multiple Mode
and IRQ-unmasking during I/O (both disabled by default), as well as
support for drives where the BIOS reports "more than 16 heads".
What's new in version 2.1:
-- Support added for E-IDE BIOSs, for systems with IDE drives
that "have more than 16 logical heads" (according the BIOS).
-- the HDIO_SETUNMASKINTR and HDIO_SETMULTCOUNT now permit
only the superuser to change settings, and no longer permit
minor device numbers to be used.
The hdparm.c program for controlling various features is now packaged
separately. Look for it on your favorite linux FTP site.
This version of hd.c includes support for two optional features:
(1) The disk I/O routines can now run with interrupts unmasked
most of the time, making them much friendlier to high
speed serial ports and other system activity.
(2) Support is included for IDE "Multiple Sector Mode", the use
of which can reduce disk I/O kernel overhead by 10-30%
on many systems, with a corresponding 10-20% increase in
data throughput.
By default, both features are DISABLED, for compatibility with
systems on which they may cause troubles.
The IRQ unmasking has been known to CORRUPT FILESYSTEMS in the
past on systems with strange hard drives. Backup before trying!
It works on most systems, but use at your own risk!!
Drives which support "Multiple Sector Mode" are identified by the
kernel at boot time, and a message is displayed indicating the
largest possible setting for "MaxMult" (max sector count for
"Multiple Sector Mode").
For more detailed boot-time information about your drive, change
the definition of VERBOSE_DRIVE_INFO from 0 to 1 near the top
of hd.c and rebuild/reinstall the kernel.
Some drives (mostly older CONNER drives) do not implement multiple mode
correctly, and data corruption may occur.. but if you wait long enough
the error recovery logic *should* be able to recover eventually.
I recommend using settings of 8, 16, or 32. Many drives also support
non-powers of two, but other drives do not -- try strange values at
your own risk!
To try this out more safely, mount the drive's partitions read-only
before using hdparm (see below) for the first time. If it doesn't
work, email me (mlord@bnr.ca) with the drive name as displayed at
boot time, so I can warn others and possibly add a hook to the code.
To enable the features, a small program is included below: hdparm.c
This one is *different* from previous versions -- be sure to recompile it!
Compile this using cc -O -o /usr/bin/hdparm hdparm.c
and then use it to enable/disable the new features, as follows:
To turn on 16-sector multiple mode, with interrupt unmasking:
hdparm /dev/hda 16 1
To view the current settings:
hdparm /dev/hda
If you have more than one drive, a separate command would need to be issued for the second drive as well, using the same or different
settings as desired:
hdparm /dev/hdb 16 1
To turn off both features on the first drive, use:
hdparm /dev/hda 0 0
To benchmark the performance difference, try:
hdparm /dev/hda 0 0
sync
time dd if=/dev/hda of=/dev/null bs=1024k count=30
time dd if=/dev/hda of=/dev/null bs=1024k count=30
time dd if=/dev/hda of=/dev/null bs=1024k count=30
hdparm /dev/hda 16 1
sync
time dd if=/dev/hda of=/dev/null bs=1024k count=30
time dd if=/dev/hda of=/dev/null bs=1024k count=30
time dd if=/dev/hda of=/dev/null bs=1024k count=30
This gives before and after views. Compare the total elapsed times,
as well as the percent of CPU used in each case. Run several trials
to ensure/verify consistent results. Some drives are actually *slower*
with multiple mode enabled, but those are very rare indeed. Most systems
experience a 10-30% increase in throughput, with a corresponding 5-50%
decrease in kernel/system CPU usage.
If you are using linux kernel 1.1.4 or higher (with the "cluster" code),
then you may not notice a big difference with the above tests. However,
I have noticed that the iozone benchmark program does seem to work fairly
reliably under kernels with the "cluster" code, so you could try that
instead (under older kernels, iozone seems to give wildly varying results
from trial to trial, at least on my system).
To have your favorite settings installed automatically at boot time,
place the hdparm command(s) into the /etc/rc.d/rc.local file.
Alternatively, one could modify the DEFAULTs near the top of hd.c
and rebuild and install the new kernel.
Enjoy,
mlord@bnr.ca
**** CUT HERE for hdparm.c ****
/* make using: cc -O -o /usr/bin/hdparm hdparm.c */
#include <linux/hdreg.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
/* extern int hd_ioctl(struct inode * inode, struct file * file,
* unsigned int cmd, unsigned long arg);
*/
void main (int argc, char *argv[])
{
int fd, mrc, irc;
static long mcount, irqmode;
if (argc != 4 && argc != 2) {
fprintf(stderr,"Usage: %s <device>"
" [<MultModeCount:0-64> <unmask:0/1>]\n", *argv);
exit (1);
}
fd = open (*++argv, O_RDONLY);
if (fd < 0) {
printf ("open failed - '%s' - %d\n", *argv, fd);
exit(1);
}
if (argc == 4) {
mcount = atoi(*++argv);
mrc = ioctl (fd, HDIO_SETMULTCOUNT, &mcount);
/* note that the new mcount does not take effect
until the next disk I/O operation, so if we were
to query it before then, the old value will show.
Also, the drive may reject the new value, which will
result in multiple mode being turned OFF completely! */
irqmode = atoi(*++argv);
irc = ioctl (fd, HDIO_SETUNMASKINTR, &irqmode);
}
else {
mrc = ioctl (fd, HDIO_GETMULTCOUNT, &mcount);
irc = ioctl (fd, HDIO_GETUNMASKINTR, &irqmode);
}
printf("MultModeCount=%d, rc=%d\n", mcount, mrc);
printf("unmask=%d, rc=%d\n", irqmode, irc);
}
-mlord@bnr.ca
......@@ -95,10 +95,10 @@ extern int ramdisk_size;
extern unsigned long xd_init(unsigned long mem_start, unsigned long mem_end);
#define RO_IOCTLS(dev,where) \
case BLKROSET: if (!suser()) return -EPERM; \
case BLKROSET: if (!suser()) return -EACCES; \
set_device_ro((dev),get_fs_long((long *) (where))); return 0; \
case BLKROGET: { int __err = verify_area(VERIFY_WRITE, (void *) (where), sizeof(long)); \
if (!__err) put_fs_long(is_read_only(dev),(long *) (where)); return __err; }
if (!__err) put_fs_long(0!=is_read_only(dev),(long *) (where)); return __err; }
#ifdef MAJOR_NR
......
......@@ -17,13 +17,12 @@
*
* IDE IRQ-unmask & drive-id & multiple-mode code added by Mark Lord.
*
* Support for E-IDE BIOS drive geometry translation added by Mark Lord.
* -- hd.c no longer chokes on E-IDE drives with "more than 16 heads".
* Support for BIOS drive geometry translation added by Mark Lord.
* -- hd.c no longer chokes on drives with "more than 16 heads".
*/
#define DEFAULT_MULT_COUNT 0 /* set to 0 to disable multiple mode at boot */
#define DEFAULT_UNMASK_INTR 0 /* set to 0 to *NOT* unmask irq's more often */
#define VERBOSE_DRIVE_INFO 0 /* set to 1 for more drive info at boot time */
#include <asm/irq.h>
#include <linux/errno.h>
......@@ -35,6 +34,7 @@
#include <linux/hdreg.h>
#include <linux/genhd.h>
#include <linux/config.h>
#include <linux/malloc.h>
#define REALLY_SLOW_IO
#include <asm/system.h>
......@@ -64,7 +64,8 @@ static inline unsigned char CMOS_READ(unsigned char addr)
static void recal_intr(void);
static void bad_rw_intr(void);
static char recalibrate[ MAX_HD ] = { 0, };
static char recalibrate[MAX_HD] = { 0, };
static char special_op[MAX_HD] = { 0, };
static int access_count[MAX_HD] = {0, };
static char busy[MAX_HD] = {0, };
static struct wait_queue * busy_wait = NULL;
......@@ -82,6 +83,8 @@ unsigned long last_req, read_timer();
struct hd_i_struct {
unsigned int head,sect,cyl,wpcom,lzone,ctl;
};
static struct hd_driveid *hd_ident_info[MAX_HD];
#ifdef HD_TYPE
static struct hd_i_struct hd_info[] = { HD_TYPE };
struct hd_i_struct bios_info[] = { HD_TYPE };
......@@ -195,11 +198,13 @@ static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
{
unsigned short port;
#ifdef DEBUG
if (drive>1 || head>15) {
printk("bad drive mapping, trying to access drive=%d, cyl=%d, head=%d, sect=%d\n",
drive, cyl, head, sect);
panic("harddisk driver problem");
}
#endif
#if (HD_DELAY > 0)
while (read_timer() - last_req < HD_DELAY)
/* nothing */;
......@@ -207,7 +212,7 @@ static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect,
if (reset)
return;
if (!controller_ready(drive, head)) {
reset = 1;
special_op[drive] += reset = 1;
return;
}
SET_INTR(intr_addr);
......@@ -230,7 +235,7 @@ static unsigned int mult_req [MAX_HD] = {0,}; /* requested MultMode count
static unsigned int mult_count [MAX_HD] = {0,}; /* currently enabled MultMode count */
static struct request WCURRENT;
static void rawstring (char *prefix, char *s, int n)
static void rawstring (char *prefix, unsigned char *s, int n)
{
if (prefix)
printk(prefix);
......@@ -243,78 +248,20 @@ static void rawstring (char *prefix, char *s, int n)
}
}
#if VERBOSE_DRIVE_INFO
char *cfg_str[] =
{ "", " HardSect", " SoftSect", " NotMFM", " HdSw>15uSec", " SpinMotCtl",
" Fixed", " Removeable", " DTR<=5Mbs", " DTR>5Mbs", " DTR>10Mbs",
" RotSpdTol>.5%", " dStbOff", " TrkOff", " FmtGapReq", "",
};
char *ioready[] = {"no", "?", "yes", "on/off"};
char *SlowMedFast[] = {"slow", "medium", "fast"};
char *BuffType[] = {"?", "1Sect", "DualPort", "DualPortCache"};
#define YN(b) (((b)==0)?"no":"yes")
static void dmpstr (char *prefix, unsigned int i, char *s[], unsigned int maxi)
{
printk(prefix);
printk( (i > maxi) ? "?" : s[i] );
}
static void dump_identity (unsigned int dev, unsigned short ib[])
{
int i;
char dashes[] = "\n+-------------------------------------------------------------------+\n";
printk (dashes);
printk ("hd%c: Drive Identification Info:\n", dev+'a');
rawstring (" Model=",(char *)&ib[27],40);
rawstring (", FwRev=",(char *)&ib[23],8);
rawstring (", SerialNo=",(char *)&ib[10],20);
printk ("\n Config={");
for (i=0; i<=15; i++) if (ib[0] & (1<<i)) printk (cfg_str[i]);
printk (" }\n");
printk (" Default CHS=%d/%d/%d, TrkSize=%d, SectSize=%d, ECCbytes=%d\n",
ib[1],ib[3],ib[6],ib[4],ib[5], ib[22]);
dmpstr (" BuffType=",ib[20],BuffType,3);
ib[47] &= 0xFF;
printk (", BuffSize=%dKB, MaxMultSect=%d\n", ib[21]/2, ib[47]);
printk (" Features: DblWordIO=%s, IORDY=%s, LBA=%s, DMA=%s",
YN(ib[48]&1),ioready[(ib[49]&0xC00)>>10],YN(ib[49]&0x200),YN(ib[49]&0x100));
dmpstr (", tPIO=",ib[51]>>8,SlowMedFast,2);
if (ib[49]&0x100 && (ib[53]&1))
dmpstr (", tDMA=",ib[52]>>8,SlowMedFast,2);
printk ("\n (%s): Current CHS=%d/%d/%d, TotSect=%d",
(((ib[53]&1)==0)?"maybe":"valid"),
ib[54],ib[55],ib[56],*(int *)&ib[57]);
if (ib[49]&0x200)
printk (", MaxLBAsect=%d", *(int *)&ib[60]);
printk("\n CurMultSect=%d%s",ib[59]&0xFF,(ib[59]&0x100)?"":"?");
if (ib[49]&0x100)
printk (", DMA-1w=%04X, DMA-mw=%04X", ib[62], ib[63]);
printk ("%s\n",dashes);
}
#endif /* VERBOSE_DRIVE_INFO */
static void identify_intr(void)
{
unsigned int dev = DEVICE_NR(CURRENT->dev);
unsigned short ib[64], stat = inb_p(HD_STATUS);
unsigned short stat = inb_p(HD_STATUS);
struct hd_driveid id;
if (unmask_intr[dev])
sti();
if (stat & (BUSY_STAT|ERR_STAT))
printk (" hd%c: multiple mode not supported\n", dev+'a');
printk (" hd%c: identity unknown\n", dev+'a');
else {
insw(HD_DATA,(char *)ib,64); /* get first 128 ID bytes */
#if VERBOSE_DRIVE_INFO
dump_identity(dev, ib);
#endif
printk (" hd%c: ", dev+'a');
rawstring(NULL, (char *)&ib[27], 40);
max_mult[dev] = ib[47] & 0xff;
if (ib[53]&1 && ib[54] && ib[55] && ib[56]) {
insw(HD_DATA, (char *)&id, sizeof(id)/2); /* get ID bytes */
max_mult[dev] = id.max_multsect;
if ((id.cur_valid&1) && id.cur_cyls && id.cur_heads && (id.cur_heads <= 16) && id.cur_sectors) {
/*
* Extract the physical drive geometry for our use.
* Note that we purposely do *not* update the bios_info.
......@@ -322,16 +269,23 @@ static void identify_intr(void)
* still have the same logical view as the BIOS does,
* which keeps the partition table from being screwed.
*/
hd_info[dev].cyl = ib[54];
hd_info[dev].head = ib[55];
hd_info[dev].sect = ib[56];
hd_info[dev].cyl = id.cur_cyls;
hd_info[dev].head = id.cur_heads;
hd_info[dev].sect = id.cur_sectors;
}
printk (" (%dMB IDE w/%dKB Cache, MaxMult=%d, CHS=%d/%d/%d)\n",
ib[1]*ib[3]*ib[6] / 2048, ib[21]>>1, max_mult[dev],
hd_info[dev].cyl, hd_info[dev].head, hd_info[dev].sect);
insw(HD_DATA,(char *)ib,64); /* flush remaining 384 ID bytes */
insw(HD_DATA,(char *)ib,64);
insw(HD_DATA,(char *)ib,64);
printk (" hd%c: ", dev+'a');
rawstring(NULL, id.model, sizeof(id.model));
printk (", %dMB w/%dKB Cache, CHS=%d/%d/%d, MaxMult=%d\n",
id.cyls*id.heads*id.sectors/2048, id.buf_size/2,
hd_info[dev].cyl, hd_info[dev].head, hd_info[dev].sect, id.max_multsect);
/* save drive info for later query via HDIO_GETIDENTITY */
if (NULL != (hd_ident_info[dev] = kmalloc(sizeof(id),GFP_ATOMIC)))
*hd_ident_info[dev] = id;
/* flush remaining 384 (reserved/undefined) ID bytes: */
insw(HD_DATA,(char *)&id,sizeof(id)/2);
insw(HD_DATA,(char *)&id,sizeof(id)/2);
insw(HD_DATA,(char *)&id,sizeof(id)/2);
}
hd_request();
return;
......@@ -443,11 +397,11 @@ static void bad_rw_intr(void)
dev = MINOR(CURRENT->dev) >> 6;
if (++CURRENT->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) {
end_request(0);
recalibrate[dev] = 1;
special_op[dev] += recalibrate[dev] = 1;
} else if (CURRENT->errors % RESET_FREQ == 0)
reset = 1;
special_op[dev] += reset = 1;
else if ((hd_error & TRK0_ERR) || CURRENT->errors % RECAL_FREQ == 0)
recalibrate[dev] = 1;
special_op[dev] += recalibrate[dev] = 1;
/* Otherwise just retry */
}
......@@ -644,7 +598,7 @@ static void hd_times_out(void)
{
DEVICE_INTR = NULL;
sti();
reset = 1;
special_op [DEVICE_NR(CURRENT->dev)] += reset = 1;
if (!CURRENT)
return;
printk(KERN_DEBUG "HD timeout\n");
......@@ -703,11 +657,12 @@ static void hd_request(void)
#endif
if (!unmask_intr[dev])
cli();
if (special_op[dev]) { /* we use "special_op" to reduce overhead on r/w */
if (reset) {
int i;
for (i=0; i < NR_HD; i++)
recalibrate[i] = 1;
special_op[i] = recalibrate[i] = 1;
cli(); /* better play it safe, as resets are the last resort */
reset_hd();
return;
......@@ -739,6 +694,8 @@ static void hd_request(void)
end_request(0);
goto repeat;
}
--special_op[dev];
} /* special_op[dev] */
if (CURRENT->cmd == READ) {
unsigned int cmd = mult_count[dev] > 1 ? WIN_MULTREAD : WIN_READ;
hd_out(dev,nsect,sec,head,cyl,cmd,&read_intr);
......@@ -792,7 +749,7 @@ static int hd_ioctl(struct inode * inode, struct file * file,
struct hd_geometry *loc = (struct hd_geometry *) arg;
int dev, err;
if (!inode)
if ((!inode) || (!inode->i_rdev))
return -EINVAL;
dev = MINOR(inode->i_rdev) >> 6;
if (dev >= NR_HD)
......@@ -814,21 +771,25 @@ static int hd_ioctl(struct inode * inode, struct file * file,
return 0;
case BLKRASET:
if(!suser()) return -EACCES;
if(!inode->i_rdev) return -EINVAL;
if(arg > 0xff) return -EINVAL;
read_ahead[MAJOR(inode->i_rdev)] = arg;
return 0;
case BLKRAGET:
if (!arg) return -EINVAL;
err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
if (err)
return err;
put_fs_long(read_ahead[MAJOR(inode->i_rdev)],(long *) arg);
return 0;
case BLKGETSIZE: /* Return device size */
if (!arg) return -EINVAL;
err = verify_area(VERIFY_WRITE, (long *) arg, sizeof(long));
if (err)
return err;
put_fs_long(hd[MINOR(inode->i_rdev)].nr_sects,
(long *) arg);
put_fs_long(hd[MINOR(inode->i_rdev)].nr_sects, (long *) arg);
return 0;
case BLKFLSBUF:
if(!suser()) return -EACCES;
if(!inode->i_rdev) return -EINVAL;
fsync_dev(inode->i_rdev);
invalidate_buffers(inode->i_rdev);
return 0;
......@@ -838,8 +799,8 @@ static int hd_ioctl(struct inode * inode, struct file * file,
case HDIO_SETUNMASKINTR:
if (!suser()) return -EACCES;
if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
if (!arg) return -EINVAL;
if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
err = verify_area(VERIFY_READ, (long *) arg, sizeof(long));
if (err)
return err;
......@@ -876,15 +837,25 @@ static int hd_ioctl(struct inode * inode, struct file * file,
cli(); /* a prior request might still be in progress */
if (arg > max_mult[dev])
err = -EINVAL; /* out of range for device */
else if (mult_req[dev] != mult_count[dev])
else if (mult_req[dev] != mult_count[dev]) {
++special_op[dev];
err = -EBUSY; /* busy, try again */
else {
} else {
mult_req[dev] = arg;
++special_op[dev];
err = 0;
}
restore_flags(flags);
return err;
}
case HDIO_GETIDENTITY:
if (!arg) return -EINVAL;
if (MINOR(inode->i_rdev) & 0x3F) return -EINVAL;
if (hd_ident_info[dev] == NULL) return -ENOMSG;
err = verify_area(VERIFY_WRITE, (char *) arg, sizeof(struct hd_driveid));
if (err)
return err;
memcpy_tofs((char *)arg, (char *) hd_ident_info[dev], sizeof(struct hd_driveid));
RO_IOCTLS(inode->i_rdev,arg);
default:
......@@ -1031,6 +1002,8 @@ static void hd_geninit(void)
}
hd[i<<6].nr_sects = bios_info[i].head *
bios_info[i].sect * bios_info[i].cyl;
hd_ident_info[i] = NULL;
special_op[i] = 1;
}
if (NR_HD) {
if (irqaction(HD_IRQ,&hd_sigaction)) {
......
......@@ -186,7 +186,7 @@ void rd_load(void)
/* ugly, ugly */
if (floppy_grab_irq_and_dma()) {
printk("Unable to gram floppy IRQ/DMA for loading ramdisk image\n");
printk("Unable to grab floppy IRQ/DMA for loading ramdisk image\n");
return;
}
do_load();
......
......@@ -774,6 +774,7 @@ plip_send(struct device *dev, enum plip_nibble_state *ns_p, unsigned char data)
break;
if (--cx == 0) /* time out */
return 1;
udelay(PLIP_DELAY_UNIT);
}
outb(0x10 | (data >> 4), PAR_DATA(dev));
*ns_p = PLIP_NST_2;
......@@ -788,6 +789,7 @@ plip_send(struct device *dev, enum plip_nibble_state *ns_p, unsigned char data)
break;
if (--cx == 0) /* time out */
return 1;
udelay(PLIP_DELAY_UNIT);
}
return 0;
......
......@@ -87,10 +87,10 @@ SCSI_OBJS := $(SCSI_OBJS) g_NCR5380.o
SCSI_SRCS := $(SCSI_SRCS) g_NCR5380.c
endif
#ifdef CONFIG_SCSI_NCR53C7xx
ifdef CONFIG_SCSI_NCR53C7xx
SCSI_OBJS := $(SCSI_OBJS) 53c7,8xx.o
SCSI_SRCS := $(SCSI_SRCS) 53c7,8xx.c
#endif
endif
ifdef CONFIG_SCSI_PAS16
SCSI_OBJS := $(SCSI_OBJS) pas16.o
......
......@@ -1712,7 +1712,7 @@ static int st_detect(Scsi_Device * SDp){
if(SDp->type != TYPE_TAPE) return 0;
printk("Detected scsi tape st%d at scsi%d, id %d, lun %d\n",
++st_template.dev_noticed,
st_template.dev_noticed++,
SDp->host->host_no , SDp->id, SDp->lun);
return 1;
......
......@@ -650,7 +650,7 @@ void mount_root(void)
wait_for_keypress();
/* ugly, ugly */
if (floppy_grab_irq_and_dma())
printk("Unable to gram floppy IRQ/DMA for mounting root floppy\n");
printk("Unable to grab floppy IRQ/DMA for mounting root floppy\n");
}
for (fs_type = file_systems ; fs_type ; fs_type = fs_type->next) {
if (!fs_type->requires_dev)
......
......@@ -105,6 +105,7 @@ extern unsigned long name_cache_init(unsigned long start, unsigned long end);
#define BLKGETSIZE 4704 /* return device size */
#define BLKFLSBUF 4705 /* flush buffer cache */
#define BLKRASET 4706 /* Set read ahead for block device */
#define BLKRAGET 4707 /* get current read ahead setting */
/* These are a few other constants only used by scsi devices */
......
......@@ -72,4 +72,49 @@ struct hd_geometry {
#define HDIO_GETMULTCOUNT 0x304
#define HDIO_SETMULTCOUNT 0x305
#define HDIO_SETFEATURE 0x306
#define HDIO_GETIDENTITY 0x307
#endif
/* structure returned by HDIO_GETIDENTITY, as per ASC X3T9.2 rev 4a */
struct hd_driveid {
unsigned short config; /* lots of obsolete bit flags */
unsigned short cyls; /* "physical" cyls */
unsigned short reserved0; /* reserved */
unsigned short heads; /* "physical" heads */
unsigned short track_bytes; /* unformatted bytes per track */
unsigned short sector_bytes; /* unformatted bytes per sector */
unsigned short sectors; /* "physical" sectors per track */
unsigned short vendor0; /* vendor unique */
unsigned short vendor1; /* vendor unique */
unsigned short vendor2; /* vendor unique */
unsigned char serial_no[20]; /* big_endian; 0 = not_specified */
unsigned short buf_type;
unsigned short buf_size; /* 512 byte increments; 0 = not_specified */
unsigned short ecc_bytes; /* for r/w long cmds; 0 = not_specified */
unsigned char fw_rev[8]; /* big_endian; 0 = not_specified */
unsigned char model[40]; /* big_endian; 0 = not_specified */
unsigned char max_multsect; /* 0=not_implemented */
unsigned char vendor3; /* vendor unique */
unsigned short dword_io; /* 0=not_implemented; 1=implemented */
unsigned char vendor4; /* vendor unique */
unsigned char capability; /* bit0:DMA, bit1:LBA */
unsigned short reserved1; /* reserved */
unsigned char vendor5; /* vendor unique */
unsigned char tPIO; /* 0=slow, 1=medium, 2=fast */
unsigned char vendor6; /* vendor unique */
unsigned char tDMA; /* 0=slow, 1=medium, 2=fast */
unsigned short cur_valid; /* when (bit0==1) use logical geom */
unsigned short cur_cyls; /* logical cylinders */
unsigned short cur_heads; /* logical heads */
unsigned short cur_sectors; /* logical sectors per track */
unsigned short cur_capacity0; /* logical total sectors on drive */
unsigned short cur_capacity1; /* (2 words, misaligned int) */
unsigned char multsect; /* current multiple sector count */
unsigned char multsect_valid; /* when (bit0==1) multsect is ok */
unsigned int lba_capacity; /* total number of sectors */
unsigned short dma_1word; /* single-word dma info */
unsigned short dma_mword; /* multiple-word dma info */
/* unsigned short reserved2[64];*/ /* reserved */
/* unsigned short vendor7 [32];*/ /* vendor unique */
/* unsigned short reserved3[96];*/ /* reserved */
};
/*
* scsicam.h - SCSI CAM support functions, use for HDIO_GETGEO, etc.
*
* Copyright 1993, 1994 Drew Eckhardt
* Visionary Computing
* (Unix and Linux consulting and custom programming)
* drew@Colorado.EDU
* +1 (303) 786-7975
*
* For more information, please consult the SCSI-CAM draft.
*/
#ifndef SCSICAM_H
#define SCSICAM_H
extern int scsicam_bios_param (Disk *disk, int dev, int *ip);
#endif /* def SCSICAM_H */
......@@ -98,6 +98,7 @@ extern void sound_setup(char *str, int *ints);
#ifdef CONFIG_SBPCD
extern void sbpcd_setup(char *str, int *ints);
#endif CONFIG_SBPCD
void ramdisk_setup(char *str, int *ints);
#ifdef CONFIG_SYSVIPC
extern void ipc_init(void);
......@@ -175,6 +176,7 @@ struct {
void (*setup_func)(char *, int *);
} bootsetups[] = {
{ "reserve=", reserve_setup },
{ "ramdisk=", ramdisk_setup },
#ifdef CONFIG_INET
{ "ether=", eth_setup },
#endif
......@@ -221,6 +223,12 @@ struct {
{ 0, 0 }
};
void ramdisk_setup(char *str, int *ints)
{
if (ints[0] > 0 && ints[1] >= 0)
ramdisk_size = ints[1];
}
int checksetup(char *line)
{
int i = 0;
......
......@@ -291,8 +291,11 @@ asmlinkage int sys_ptrace(long request, long pid, long addr, long data)
if (request == PTRACE_ATTACH) {
if (child == current)
return -EPERM;
if ((!child->dumpable || (current->uid != child->euid) ||
(current->gid != child->egid)) && !suser())
if ((!child->dumpable ||
(current->uid != child->euid) ||
(current->uid != child->uid) ||
(current->gid != child->egid) ||
(current->gid != child->gid)) && !suser())
return -EPERM;
/* the same process cannot be attached many times */
if (child->flags & PF_PTRACED)
......
......@@ -525,6 +525,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, int priority)
n->tries=0;
n->lock=0;
n->users=0;
n->pkt_type=skb->pkt_type;
return n;
}
......
......@@ -299,7 +299,7 @@ void tcp_err(int err, unsigned char *header, unsigned long daddr,
* until we time out, or the user gives up.
*/
if (icmp_err_convert[err & 0xff].fatal)
if (icmp_err_convert[err & 0xff].fatal || sk->state == TCP_SYN_SENT)
{
if (sk->state == TCP_SYN_SENT)
{
......
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