]> git.neil.brown.name Git - history.git/commitdiff
Import 1.1.39 1.1.39
authorLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:36 +0000 (15:09 -0500)
committerLinus Torvalds <torvalds@linuxfoundation.org>
Fri, 23 Nov 2007 20:09:36 +0000 (15:09 -0500)
16 files changed:
Makefile
drivers/block/README.hd
drivers/block/blk.h
drivers/block/hd.c
drivers/block/ramdisk.c
drivers/net/plip.c
drivers/scsi/Makefile
drivers/scsi/st.c
fs/super.c
include/linux/fs.h
include/linux/hdreg.h
include/linux/scsicam.h [new file with mode: 0644]
init/main.c
kernel/ptrace.c
net/inet/skbuff.c
net/inet/tcp.c

index 48bd87b891bc51511234197357af5c014ca9f523..fa4d8b58f1126d8f3f21f21eb4c42edcce598475 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 1
 PATCHLEVEL = 1
-SUBLEVEL = 38
+SUBLEVEL = 39
 
 all:   Version zImage
 
index eca1d24d12fd1ea2488c9ac0973e9a1e8ce714c0..162928178b5dc563ae3f56895e9d1b943d159d78 100644 (file)
@@ -1,159 +1,8 @@
-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
index 86e996c82ab34b19b4004e313a83b890748f1b1d..a8657b2b9fffe95115238e0a6d6cd2508efaa29b 100644 (file)
@@ -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
 
index 70c06e9a3ac2627fd595988aa5b0c9a22b348b12..3b76c22358362ea36055e9dfc699223d9652dd9f 100644 (file)
  *
  *  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,42 +657,45 @@ repeat:
 #endif
        if (!unmask_intr[dev])
                cli();
-       if (reset) {
-               int i;
-
-               for (i=0; i < NR_HD; i++)
-                       recalibrate[i] = 1;
-               cli(); /* better play it safe, as resets are the last resort */
-               reset_hd();
-               return;
-       }
-       if (recalibrate[dev]) {
-               recalibrate[dev] = 0;
-               hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
-               if (reset)
-                       goto repeat;
-               return;
-       }       
-       if (!identified[dev]) {
-               identified[dev]  = 1;
-               unmask_intr[dev] = DEFAULT_UNMASK_INTR;
-               mult_req[dev]    = DEFAULT_MULT_COUNT;
-               hd_out(dev,0,0,0,0,WIN_IDENTIFY,&identify_intr);
-               if (reset)
-                       goto repeat;
-               return;
-       }
-       if (mult_req[dev] != mult_count[dev]) {
-               hd_out(dev,mult_req[dev],0,0,0,WIN_SETMULT,&set_multmode_intr);
-               if (reset)
+       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++)
+                               special_op[i] = recalibrate[i] = 1;
+                       cli(); /* better play it safe, as resets are the last resort */
+                       reset_hd();
+                       return;
+               }
+               if (recalibrate[dev]) {
+                       recalibrate[dev] = 0;
+                       hd_out(dev,hd_info[dev].sect,0,0,0,WIN_RESTORE,&recal_intr);
+                       if (reset)
+                               goto repeat;
+                       return;
+               }       
+               if (!identified[dev]) {
+                       identified[dev]  = 1;
+                       unmask_intr[dev] = DEFAULT_UNMASK_INTR;
+                       mult_req[dev]    = DEFAULT_MULT_COUNT;
+                       hd_out(dev,0,0,0,0,WIN_IDENTIFY,&identify_intr);
+                       if (reset)
+                               goto repeat;
+                       return;
+               }
+               if (mult_req[dev] != mult_count[dev]) {
+                       hd_out(dev,mult_req[dev],0,0,0,WIN_SETMULT,&set_multmode_intr);
+                       if (reset)
+                               goto repeat;
+                       return;
+               }
+               if (hd_info[dev].head > 16) {
+                       printk ("hd%c: cannot handle device with more than 16 heads - giving up\n", dev+'a');
+                       end_request(0);
                        goto repeat;
-               return;
-       }
-       if (hd_info[dev].head > 16) {
-               printk ("hd%c: cannot handle device with more than 16 heads - giving up\n", dev+'a');
-               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)) {
index 90d4f64723673666355be2e1608d89c8bf330156..a3ac8f2483a073c88131d7f3f2b1aadd96cf567a 100644 (file)
@@ -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();
index 7004e0f7eb965338fd2a4acae249045c6291ab1e..0bea83c59ab00ebe58ffeefc96bd842727bcffe6 100644 (file)
@@ -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;
 
index 7dbf1f08d40e4156fffa17e2cecffbce13a00d65..e4d9b7878f105898fd40811025b1ad72b024ae4f 100644 (file)
@@ -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
index 1f94bfe1450bc0d51450a80c603589c8b40a8466..8e2007c55114ae3f9b8bb86a1a2abbb401f2c9d1 100644 (file)
@@ -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;
index e7902c55b51ab8110ee0a366b43e63f120139e9d..3ffc728f833b3b6bb8fa0aba13e20951a5781264 100644 (file)
@@ -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)
index 06c5ebd8a16bb25bd8659518d6dca2bf74dcb07b..4f23bf5fb0bd8ae87bac810807ed60d4badf0962 100644 (file)
@@ -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 */
 
index 0b35fefd0fbb3cf4f5d4cb85790cf4245c424148..fe300dc92ad25ba79e8a2a809f7c74480e4281a6 100644 (file)
@@ -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 */
+};
diff --git a/include/linux/scsicam.h b/include/linux/scsicam.h
new file mode 100644 (file)
index 0000000..d78dc71
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * 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 */
index 2e7cb65e799296d817c8db1a2520ae353854aa22..6fca1d694fd851909470ad7cbb45b2cef86328ca 100644 (file)
@@ -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;
index 2d2aa9427e043a6da5d401e05890b5f91587ff9f..44aa5c2def4d7c2cd68284b65c8e117940e5903c 100644 (file)
@@ -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)
index 1116d558c7b461b2f8185d0bdfd61fe09adcc910..8702993c0495af82b510e50be9c1b1cf58a372a6 100644 (file)
@@ -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;
 }
        
index 04932324ab8a2ff31847e792a9968d937b432151..6926ac36cbca57bba3e31c1df02d7620edeb4ea0 100644 (file)
@@ -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) 
                {