Automatic merge of master.kernel.org:/home/rmk/linux-2.6-arm
authorLinus Torvalds <torvalds@ppc970.osdl.org>
Wed, 8 Jun 2005 14:57:17 +0000 (07:57 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Wed, 8 Jun 2005 14:57:17 +0000 (07:57 -0700)
114 files changed:
Documentation/DocBook/libata.tmpl
Makefile
arch/ia64/ia32/sys_ia32.c
arch/ia64/kernel/mca.c
arch/m68knommu/kernel/process.c
arch/ppc/kernel/cputable.c
arch/ppc/kernel/misc.S
arch/ppc64/kernel/entry.S
arch/ppc64/kernel/head.S
arch/ppc64/kernel/iSeries_setup.c
arch/ppc64/kernel/idle.c
arch/ppc64/kernel/process.c
arch/ppc64/kernel/prom_init.c
arch/ppc64/kernel/setup.c
arch/ppc64/kernel/smp.c
arch/ppc64/kernel/sysfs.c
arch/s390/appldata/appldata_base.c
arch/s390/appldata/appldata_mem.c
arch/s390/appldata/appldata_net_sum.c
arch/s390/appldata/appldata_os.c
arch/s390/kernel/ptrace.c
arch/s390/mm/fault.c
arch/sparc64/kernel/pci_iommu.c
arch/sparc64/kernel/pci_psycho.c
arch/sparc64/kernel/pci_sabre.c
arch/sparc64/kernel/pci_schizo.c
arch/sparc64/kernel/sbus.c
drivers/atm/Makefile
drivers/atm/fore200e.c
drivers/atm/he.c
drivers/atm/nicstar.c
drivers/atm/zatm.c
drivers/block/ub.c
drivers/char/agp/agp.h
drivers/char/agp/ali-agp.c
drivers/char/agp/amd-k7-agp.c
drivers/char/agp/amd64-agp.c
drivers/char/agp/ati-agp.c
drivers/char/agp/backend.c
drivers/char/agp/efficeon-agp.c
drivers/char/agp/generic.c
drivers/char/agp/hp-agp.c
drivers/char/agp/i460-agp.c
drivers/char/agp/intel-agp.c
drivers/char/agp/sgi-agp.c
drivers/char/agp/sworks-agp.c
drivers/char/agp/uninorth-agp.c
drivers/char/mxser.c
drivers/input/keyboard/atkbd.c
drivers/net/hamradio/baycom_epp.c
drivers/net/pcmcia/3c574_cs.c
drivers/net/r8169.c
drivers/net/shaper.c
drivers/net/tg3.c
drivers/pci/pci.ids
drivers/pci/quirks.c
drivers/scsi/ata_piix.c
drivers/scsi/libata-core.c
drivers/scsi/libata-scsi.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/scsi_scan.c
drivers/serial/vr41xx_siu.c
drivers/usb/core/sysfs.c
drivers/usb/input/hid-core.c
drivers/usb/media/pwc/ChangeLog [deleted file]
drivers/usb/net/usbnet.c
drivers/usb/serial/Kconfig
drivers/usb/serial/Makefile
drivers/usb/serial/cp2101.c
drivers/usb/serial/option.c [new file with mode: 0644]
drivers/usb/storage/unusual_devs.h
fs/binfmt_flat.c
fs/cifs/README
fs/cifs/cifsproto.h
fs/cifs/cifssmb.c
fs/cifs/dir.c
fs/cifs/inode.c
fs/cifs/misc.c
fs/jbd/checkpoint.c
fs/mpage.c
fs/namei.c
fs/nfs/dir.c
include/asm-alpha/agp.h
include/asm-h8300/kmap_types.h
include/asm-h8300/mman.h
include/asm-i386/agp.h
include/asm-i386/mach-numaq/mach_ipi.h
include/asm-ia64/agp.h
include/asm-ppc/agp.h
include/asm-ppc/sigcontext.h
include/asm-ppc64/agp.h
include/asm-ppc64/processor.h
include/asm-ppc64/thread_info.h
include/asm-s390/user.h
include/asm-sparc64/agp.h
include/asm-sparc64/iommu.h
include/asm-sparc64/pbm.h
include/asm-x86_64/agp.h
include/linux/acpi.h
include/linux/if_shaper.h
include/linux/libata.h
include/linux/netdevice.h
include/linux/pci_ids.h
include/linux/usb.h
mm/filemap.c
net/core/ethtool.c
net/ipv4/esp4.c
net/ipv4/ipvs/Makefile
net/ipv4/ipvs/ip_vs_proto.c
net/ipv4/ipvs/ip_vs_proto_icmp.c [deleted file]
net/ipv4/netfilter/ip_queue.c
net/ipv4/udp.c
net/ipv6/ipv6_syms.c
net/sched/sch_dsmark.c

index cf2fce7707da202e7f408f40929dde7255cf742e..6df1dfd18b651fce1224fe0e127cf7e777981d34 100644 (file)
@@ -14,7 +14,7 @@
   </authorgroup>
 
   <copyright>
-   <year>2003</year>
+   <year>2003-2005</year>
    <holder>Jeff Garzik</holder>
   </copyright>
 
 
 <toc></toc>
 
-  <chapter id="libataThanks">
-     <title>Thanks</title>
+  <chapter id="libataIntroduction">
+     <title>Introduction</title>
   <para>
-  The bulk of the ATA knowledge comes thanks to long conversations with
-  Andre Hedrick (www.linux-ide.org).
+  libATA is a library used inside the Linux kernel to support ATA host
+  controllers and devices.  libATA provides an ATA driver API, class
+  transports for ATA and ATAPI devices, and SCSI&lt;-&gt;ATA translation
+  for ATA devices according to the T10 SAT specification.
   </para>
   <para>
-  Thanks to Alan Cox for pointing out similarities 
-  between SATA and SCSI, and in general for motivation to hack on
-  libata.
-  </para>
-  <para>
-  libata's device detection
-  method, ata_pio_devchk, and in general all the early probing was
-  based on extensive study of Hale Landis's probe/reset code in his
-  ATADRVR driver (www.ata-atapi.com).
+  This Guide documents the libATA driver API, library functions, library
+  internals, and a couple sample ATA low-level drivers.
   </para>
   </chapter>
 
   <chapter id="libataDriverApi">
      <title>libata Driver API</title>
+     <para>
+     struct ata_port_operations is defined for every low-level libata
+     hardware driver, and it controls how the low-level driver
+     interfaces with the ATA and SCSI layers.
+     </para>
+     <para>
+     FIS-based drivers will hook into the system with ->qc_prep() and
+     ->qc_issue() high-level hooks.  Hardware which behaves in a manner
+     similar to PCI IDE hardware may utilize several generic helpers,
+     defining at a bare minimum the bus I/O addresses of the ATA shadow
+     register blocks.
+     </para>
      <sect1>
         <title>struct ata_port_operations</title>
 
+       <sect2><title>Disable ATA port</title>
        <programlisting>
 void (*port_disable) (struct ata_port *);
        </programlisting>
@@ -78,6 +86,9 @@ void (*port_disable) (struct ata_port *);
        unplug).
        </para>
 
+       </sect2>
+
+       <sect2><title>Post-IDENTIFY device configuration</title>
        <programlisting>
 void (*dev_config) (struct ata_port *, struct ata_device *);
        </programlisting>
@@ -88,6 +99,9 @@ void (*dev_config) (struct ata_port *, struct ata_device *);
        issue of SET FEATURES - XFER MODE, and prior to operation.
        </para>
 
+       </sect2>
+
+       <sect2><title>Set PIO/DMA mode</title>
        <programlisting>
 void (*set_piomode) (struct ata_port *, struct ata_device *);
 void (*set_dmamode) (struct ata_port *, struct ata_device *);
@@ -108,6 +122,9 @@ void (*post_set_mode) (struct ata_port *ap);
        ->set_dma_mode() is only called if DMA is possible.
        </para>
 
+       </sect2>
+
+       <sect2><title>Taskfile read/write</title>
        <programlisting>
 void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf);
 void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
@@ -120,6 +137,9 @@ void (*tf_read) (struct ata_port *ap, struct ata_taskfile *tf);
        taskfile register values.
        </para>
 
+       </sect2>
+
+       <sect2><title>ATA command execute</title>
        <programlisting>
 void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
        </programlisting>
@@ -129,17 +149,37 @@ void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
        ->tf_load(), to be initiated in hardware.
        </para>
 
+       </sect2>
+
+       <sect2><title>Per-cmd ATAPI DMA capabilities filter</title>
+       <programlisting>
+int (*check_atapi_dma) (struct ata_queued_cmd *qc);
+       </programlisting>
+
+       <para>
+Allow low-level driver to filter ATA PACKET commands, returning a status
+indicating whether or not it is OK to use DMA for the supplied PACKET
+command.
+       </para>
+
+       </sect2>
+
+       <sect2><title>Read specific ATA shadow registers</title>
        <programlisting>
 u8   (*check_status)(struct ata_port *ap);
-void (*dev_select)(struct ata_port *ap, unsigned int device);
+u8   (*check_altstatus)(struct ata_port *ap);
+u8   (*check_err)(struct ata_port *ap);
        </programlisting>
 
        <para>
-       Reads the Status ATA shadow register from hardware.  On some
-       hardware, this has the side effect of clearing the interrupt
-       condition.
+       Reads the Status/AltStatus/Error ATA shadow register from
+       hardware.  On some hardware, reading the Status register has
+       the side effect of clearing the interrupt condition.
        </para>
 
+       </sect2>
+
+       <sect2><title>Select ATA device on bus</title>
        <programlisting>
 void (*dev_select)(struct ata_port *ap, unsigned int device);
        </programlisting>
@@ -147,9 +187,13 @@ void (*dev_select)(struct ata_port *ap, unsigned int device);
        <para>
        Issues the low-level hardware command(s) that causes one of N
        hardware devices to be considered 'selected' (active and
-       available for use) on the ATA bus.
+       available for use) on the ATA bus.  This generally has no
+meaning on FIS-based devices.
        </para>
 
+       </sect2>
+
+       <sect2><title>Reset ATA bus</title>
        <programlisting>
 void (*phy_reset) (struct ata_port *ap);
        </programlisting>
@@ -162,17 +206,31 @@ void (*phy_reset) (struct ata_port *ap);
        functions ata_bus_reset() or sata_phy_reset() for this hook.
        </para>
 
+       </sect2>
+
+       <sect2><title>Control PCI IDE BMDMA engine</title>
        <programlisting>
 void (*bmdma_setup) (struct ata_queued_cmd *qc);
 void (*bmdma_start) (struct ata_queued_cmd *qc);
+void (*bmdma_stop) (struct ata_port *ap);
+u8   (*bmdma_status) (struct ata_port *ap);
        </programlisting>
 
        <para>
-       When setting up an IDE BMDMA transaction, these hooks arm
-       (->bmdma_setup) and fire (->bmdma_start) the hardware's DMA
-       engine.
+When setting up an IDE BMDMA transaction, these hooks arm
+(->bmdma_setup), fire (->bmdma_start), and halt (->bmdma_stop)
+the hardware's DMA engine.  ->bmdma_status is used to read the standard
+PCI IDE DMA Status register.
        </para>
 
+       <para>
+These hooks are typically either no-ops, or simply not implemented, in
+FIS-based drivers.
+       </para>
+
+       </sect2>
+
+       <sect2><title>High-level taskfile hooks</title>
        <programlisting>
 void (*qc_prep) (struct ata_queued_cmd *qc);
 int (*qc_issue) (struct ata_queued_cmd *qc);
@@ -190,20 +248,26 @@ int (*qc_issue) (struct ata_queued_cmd *qc);
        ->qc_issue is used to make a command active, once the hardware
        and S/G tables have been prepared.  IDE BMDMA drivers use the
        helper function ata_qc_issue_prot() for taskfile protocol-based
-       dispatch.  More advanced drivers roll their own ->qc_issue
-       implementation, using this as the "issue new ATA command to
-       hardware" hook.
+       dispatch.  More advanced drivers implement their own ->qc_issue.
        </para>
 
+       </sect2>
+
+       <sect2><title>Timeout (error) handling</title>
        <programlisting>
 void (*eng_timeout) (struct ata_port *ap);
        </programlisting>
 
        <para>
-       This is a high level error handling function, called from the
-       error handling thread, when a command times out.
+This is a high level error handling function, called from the
+error handling thread, when a command times out.  Most newer
+hardware will implement its own error handling code here.  IDE BMDMA
+drivers may use the helper function ata_eng_timeout().
        </para>
 
+       </sect2>
+
+       <sect2><title>Hardware interrupt handling</title>
        <programlisting>
 irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
 void (*irq_clear) (struct ata_port *);
@@ -216,6 +280,9 @@ void (*irq_clear) (struct ata_port *);
        is quiet.
        </para>
 
+       </sect2>
+
+       <sect2><title>SATA phy read/write</title>
        <programlisting>
 u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg);
 void (*scr_write) (struct ata_port *ap, unsigned int sc_reg,
@@ -227,6 +294,9 @@ void (*scr_write) (struct ata_port *ap, unsigned int sc_reg,
        if ->phy_reset hook called the sata_phy_reset() helper function.
        </para>
 
+       </sect2>
+
+       <sect2><title>Init and shutdown</title>
        <programlisting>
 int (*port_start) (struct ata_port *ap);
 void (*port_stop) (struct ata_port *ap);
@@ -240,15 +310,17 @@ void (*host_stop) (struct ata_host_set *host_set);
        tasks.  
        </para>
        <para>
-       ->host_stop() is called when the rmmod or hot unplug process
-       begins.  The hook must stop all hardware interrupts, DMA
-       engines, etc.
-       </para>
-       <para>
        ->port_stop() is called after ->host_stop().  It's sole function
        is to release DMA/memory resources, now that they are no longer
        actively being used.
        </para>
+       <para>
+       ->host_stop() is called after all ->port_stop() calls
+have completed.  The hook must finalize hardware shutdown, release DMA
+and other resources, etc.
+       </para>
+
+       </sect2>
 
      </sect1>
   </chapter>
@@ -279,4 +351,24 @@ void (*host_stop) (struct ata_host_set *host_set);
 !Idrivers/scsi/sata_sil.c
   </chapter>
 
+  <chapter id="libataThanks">
+     <title>Thanks</title>
+  <para>
+  The bulk of the ATA knowledge comes thanks to long conversations with
+  Andre Hedrick (www.linux-ide.org), and long hours pondering the ATA
+  and SCSI specifications.
+  </para>
+  <para>
+  Thanks to Alan Cox for pointing out similarities 
+  between SATA and SCSI, and in general for motivation to hack on
+  libata.
+  </para>
+  <para>
+  libata's device detection
+  method, ata_pio_devchk, and in general all the early probing was
+  based on extensive study of Hale Landis's probe/reset code in his
+  ATADRVR driver (www.ata-atapi.com).
+  </para>
+  </chapter>
+
 </book>
index c11a317ea910df5c8456de992ae8f932a102b12b..9e005e18c71c4b7adc83a200e1ae10782c751920 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 12
-EXTRAVERSION =-rc5
+EXTRAVERSION =-rc6
 NAME=Woozy Numbat
 
 # *DOCUMENTATION*
index 247a21c64aea33bb41ad5aa591323abcfb81aaaf..c1e20d65dd6cb4688391f928f43445aea644b66b 100644 (file)
@@ -2427,7 +2427,7 @@ sys32_epoll_wait(int epfd, struct epoll_event32 __user * events, int maxevents,
 {
        struct epoll_event *events64 = NULL;
        mm_segment_t old_fs = get_fs();
-       int error, numevents, size;
+       int numevents, size;
        int evt_idx;
        int do_free_pages = 0;
 
index 2c75741dcc66004e908dd792df6418aba9d61953..736e328b5e612865d1173d84ff054dc21bbbfde9 100644 (file)
@@ -1103,8 +1103,6 @@ ia64_mca_cpe_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs)
        return IRQ_HANDLED;
 }
 
-#endif /* CONFIG_ACPI */
-
 /*
  *  ia64_mca_cpe_poll
  *
@@ -1122,6 +1120,8 @@ ia64_mca_cpe_poll (unsigned long dummy)
        platform_send_ipi(first_cpu(cpu_online_map), IA64_CPEP_VECTOR, IA64_IPI_DM_INT, 0);
 }
 
+#endif /* CONFIG_ACPI */
+
 /*
  * C portion of the OS INIT handler
  *
index 2b6c9d32b7a6267754ab11b202317755a825a0b5..c4a33f265dc07e53577350d5366b3a936c8bc665 100644 (file)
@@ -45,11 +45,13 @@ asmlinkage void ret_from_fork(void);
  */
 void default_idle(void)
 {
-       while(1) {
-               if (need_resched())
-                       __asm__("stop #0x2000" : : : "cc");
-               schedule();
+       local_irq_disable();
+       while (!need_resched()) {
+               /* This stop will re-enable interrupts */
+               __asm__("stop #0x2000" : : : "cc");
+               local_irq_disable();
        }
+       local_irq_enable();
 }
 
 void (*idle)(void) = default_idle;
@@ -63,7 +65,12 @@ void (*idle)(void) = default_idle;
 void cpu_idle(void)
 {
        /* endless idle loop with no priority at all */
-       idle();
+       while (1) {
+               idle();
+               preempt_enable_no_resched();
+               schedule();
+               preempt_disable();
+       }
 }
 
 void machine_restart(char * __unused)
index 8aa5e8c69009b43c89415b3ec643ad808ea41596..d44b7dc5390a0d64e7f58e3b71d70969de57c922 100644 (file)
@@ -838,6 +838,17 @@ struct cpu_spec    cpu_specs[] = {
                .icache_bsize           = 32,
                .dcache_bsize           = 32,
        },
+       {       /* 405EP */
+               .pvr_mask               = 0xffff0000,
+               .pvr_value              = 0x51210000,
+               .cpu_name               = "405EP",
+               .cpu_features           = CPU_FTR_SPLIT_ID_CACHE |
+                       CPU_FTR_USE_TB,
+               .cpu_user_features      = PPC_FEATURE_32 |
+                       PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
+               .icache_bsize           = 32,
+               .dcache_bsize           = 32,
+       },
 
 #endif /* CONFIG_40x */
 #ifdef CONFIG_44x
index e4f1615ec13f42eb034426443d881e2db0534d47..7329ef177a18c36c4f068d2a09dad48d34fce92e 100644 (file)
@@ -619,7 +619,7 @@ _GLOBAL(flush_instruction_cache)
 _GLOBAL(flush_icache_range)
 BEGIN_FTR_SECTION
        blr                             /* for 601, do nothing */
-END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE)
+END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
        li      r5,L1_CACHE_LINE_SIZE-1
        andc    r3,r3,r5
        subf    r4,r3,r4
@@ -736,7 +736,7 @@ _GLOBAL(flush_dcache_all)
 _GLOBAL(__flush_dcache_icache)
 BEGIN_FTR_SECTION
        blr                                     /* for 601, do nothing */
-END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE)
+END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
        rlwinm  r3,r3,0,0,19                    /* Get page base address */
        li      r4,4096/L1_CACHE_LINE_SIZE      /* Number of lines in a page */
        mtctr   r4
@@ -764,7 +764,7 @@ END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE)
 _GLOBAL(__flush_dcache_icache_phys)
 BEGIN_FTR_SECTION
        blr                                     /* for 601, do nothing */
-END_FTR_SECTION_IFSET(PPC_FEATURE_UNIFIED_CACHE)
+END_FTR_SECTION_IFCLR(CPU_FTR_SPLIT_ID_CACHE)
        mfmsr   r10
        rlwinm  r0,r10,0,28,26                  /* clear DR */
        mtmsr   r0
index d3604056e1a9c53d2407243ecb44aa282609363c..b61572eb2a7130d7a46924f8412024b9879286e7 100644 (file)
@@ -436,15 +436,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
        REST_8GPRS(14, r1)
        REST_10GPRS(22, r1)
 
-#ifdef CONFIG_PPC_ISERIES
-       clrrdi  r7,r1,THREAD_SHIFT      /* get current_thread_info() */
-       ld      r7,TI_FLAGS(r7)         /* Get run light flag */
-       mfspr   r9,CTRLF
-       srdi    r7,r7,TIF_RUN_LIGHT
-       insrdi  r9,r7,1,63              /* Insert run light into CTRL */
-       mtspr   CTRLT,r9
-#endif
-
        /* convert old thread to its task_struct for return value */
        addi    r3,r3,-THREAD
        ld      r7,_NIP(r1)     /* Return to _switch caller in new task */
index 92a744c31ab183b2aec6e4532a593cef614bba13..346dbf606b5dd910e1a3609d315d96a1a830fa00 100644 (file)
@@ -626,10 +626,10 @@ system_reset_iSeries:
        lhz     r24,PACAPACAINDEX(r13)  /* Get processor # */
        cmpwi   0,r24,0                 /* Are we processor 0? */
        beq     .__start_initialization_iSeries /* Start up the first processor */
-       mfspr   r4,CTRLF
-       li      r5,RUNLATCH             /* Turn off the run light */
+       mfspr   r4,SPRN_CTRLF
+       li      r5,CTRL_RUNLATCH        /* Turn off the run light */
        andc    r4,r4,r5
-       mtspr   CTRLT,r4
+       mtspr   SPRN_CTRLT,r4
 
 1:
        HMT_LOW
@@ -2082,9 +2082,9 @@ _GLOBAL(hmt_start_secondary)
        mfspr   r4, HID0
        ori     r4, r4, 0x1
        mtspr   HID0, r4
-       mfspr   r4, CTRLF
+       mfspr   r4, SPRN_CTRLF
        oris    r4, r4, 0x40
-       mtspr   CTRLT, r4
+       mtspr   SPRN_CTRLT, r4
        blr
 #endif
 
index da20120f22617515f554e405d9eaa744288aca57..6d06eb550a3fb839077953caab8d6f82d96afe8a 100644 (file)
@@ -852,6 +852,28 @@ static int __init iSeries_src_init(void)
 
 late_initcall(iSeries_src_init);
 
+static int set_spread_lpevents(char *str)
+{
+       unsigned long i;
+       unsigned long val = simple_strtoul(str, NULL, 0);
+
+       /*
+        * The parameter is the number of processors to share in processing
+        * lp events.
+        */
+       if (( val > 0) && (val <= NR_CPUS)) {
+               for (i = 1; i < val; ++i)
+                       paca[i].lpqueue_ptr = paca[0].lpqueue_ptr;
+
+               printk("lpevent processing spread over %ld processors\n", val);
+       } else {
+               printk("invalid spread_lpevents %ld\n", val);
+       }
+
+       return 1;
+}
+__setup("spread_lpevents=", set_spread_lpevents);
+
 void __init iSeries_early_setup(void)
 {
        iSeries_fixup_klimit();
index 6abc621d3ba0ca1fd2f52b934d83faaae4d8d81e..f24ce2b872004ae4feb1f419eddb3c0866c1c440 100644 (file)
@@ -75,13 +75,9 @@ static int iSeries_idle(void)
 {
        struct paca_struct *lpaca;
        long oldval;
-       unsigned long CTRL;
 
        /* ensure iSeries run light will be out when idle */
-       clear_thread_flag(TIF_RUN_LIGHT);
-       CTRL = mfspr(CTRLF);
-       CTRL &= ~RUNLATCH;
-       mtspr(CTRLT, CTRL);
+       ppc64_runlatch_off();
 
        lpaca = get_paca();
 
@@ -111,7 +107,9 @@ static int iSeries_idle(void)
                        }
                }
 
+               ppc64_runlatch_on();
                schedule();
+               ppc64_runlatch_off();
        }
 
        return 0;
index 8b06861227385709431ace73498417c448b10e5d..cdfecbeb331f58d586edd4b85aa58212f859d872 100644 (file)
@@ -378,9 +378,6 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
                childregs->gpr[1] = sp + sizeof(struct pt_regs);
                p->thread.regs = NULL;  /* no user register state */
                clear_ti_thread_flag(p->thread_info, TIF_32BIT);
-#ifdef CONFIG_PPC_ISERIES
-               set_ti_thread_flag(p->thread_info, TIF_RUN_LIGHT);
-#endif
        } else {
                childregs->gpr[1] = usp;
                p->thread.regs = childregs;
index 3de950de3671d293fc0e9d6a74bf8b0059b0d06f..b7683abfbe6a5f71e8031610ef8cb67dd14a07bd 100644 (file)
@@ -211,13 +211,23 @@ struct {
  */
 #define ADDR(x)                (u32) ((unsigned long)(x) - offset)
 
+/*
+ * Error results ... some OF calls will return "-1" on error, some
+ * will return 0, some will return either. To simplify, here are
+ * macros to use with any ihandle or phandle return value to check if
+ * it is valid
+ */
+
+#define PROM_ERROR             (-1u)
+#define PHANDLE_VALID(p)       ((p) != 0 && (p) != PROM_ERROR)
+#define IHANDLE_VALID(i)       ((i) != 0 && (i) != PROM_ERROR)
+
+
 /* This is the one and *ONLY* place where we actually call open
  * firmware from, since we need to make sure we're running in 32b
  * mode when we do.  We switch back to 64b mode upon return.
  */
 
-#define PROM_ERROR     (-1)
-
 static int __init call_prom(const char *service, int nargs, int nret, ...)
 {
        int i;
@@ -587,14 +597,13 @@ static void __init prom_send_capabilities(void)
 {
        unsigned long offset = reloc_offset();
        ihandle elfloader;
-       int ret;
 
        elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader"));
        if (elfloader == 0) {
                prom_printf("couldn't open /packages/elf-loader\n");
                return;
        }
-       ret = call_prom("call-method", 3, 1, ADDR("process-elf-header"),
+       call_prom("call-method", 3, 1, ADDR("process-elf-header"),
                        elfloader, ADDR(&fake_elf));
        call_prom("close", 1, 0, elfloader);
 }
@@ -646,7 +655,7 @@ static unsigned long __init alloc_up(unsigned long size, unsigned long align)
            base = _ALIGN_UP(base + 0x100000, align)) {
                prom_debug("    trying: 0x%x\n\r", base);
                addr = (unsigned long)prom_claim(base, size, 0);
-               if ((int)addr != PROM_ERROR)
+               if (addr != PROM_ERROR)
                        break;
                addr = 0;
                if (align == 0)
@@ -708,7 +717,7 @@ static unsigned long __init alloc_down(unsigned long size, unsigned long align,
        for(; base > RELOC(alloc_bottom); base = _ALIGN_DOWN(base - 0x100000, align))  {
                prom_debug("    trying: 0x%x\n\r", base);
                addr = (unsigned long)prom_claim(base, size, 0);
-               if ((int)addr != PROM_ERROR)
+               if (addr != PROM_ERROR)
                        break;
                addr = 0;
        }
@@ -902,18 +911,19 @@ static void __init prom_instantiate_rtas(void)
 {
        unsigned long offset = reloc_offset();
        struct prom_t *_prom = PTRRELOC(&prom);
-       phandle prom_rtas, rtas_node;
+       phandle rtas_node;
+       ihandle rtas_inst;
        u32 base, entry = 0;
        u32 size = 0;
 
        prom_debug("prom_instantiate_rtas: start...\n");
 
-       prom_rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
-       prom_debug("prom_rtas: %x\n", prom_rtas);
-       if (prom_rtas == (phandle) -1)
+       rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas"));
+       prom_debug("rtas_node: %x\n", rtas_node);
+       if (!PHANDLE_VALID(rtas_node))
                return;
 
-       prom_getprop(prom_rtas, "rtas-size", &size, sizeof(size));
+       prom_getprop(rtas_node, "rtas-size", &size, sizeof(size));
        if (size == 0)
                return;
 
@@ -922,14 +932,18 @@ static void __init prom_instantiate_rtas(void)
                prom_printf("RTAS allocation failed !\n");
                return;
        }
-       prom_printf("instantiating rtas at 0x%x", base);
 
-       rtas_node = call_prom("open", 1, 1, ADDR("/rtas"));
-       prom_printf("...");
+       rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
+       if (!IHANDLE_VALID(rtas_inst)) {
+               prom_printf("opening rtas package failed");
+               return;
+       }
+
+       prom_printf("instantiating rtas at 0x%x ...", base);
 
        if (call_prom("call-method", 3, 2,
                      ADDR("instantiate-rtas"),
-                     rtas_node, base) != PROM_ERROR) {
+                     rtas_inst, base) != PROM_ERROR) {
                entry = (long)_prom->args.rets[1];
        }
        if (entry == 0) {
@@ -940,8 +954,8 @@ static void __init prom_instantiate_rtas(void)
 
        reserve_mem(base, size);
 
-       prom_setprop(prom_rtas, "linux,rtas-base", &base, sizeof(base));
-       prom_setprop(prom_rtas, "linux,rtas-entry", &entry, sizeof(entry));
+       prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base));
+       prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry));
 
        prom_debug("rtas base     = 0x%x\n", base);
        prom_debug("rtas entry    = 0x%x\n", entry);
@@ -1062,7 +1076,7 @@ static void __init prom_initialize_tce_table(void)
 
                prom_printf("opening PHB %s", path);
                phb_node = call_prom("open", 1, 1, path);
-               if ( (long)phb_node <= 0)
+               if (phb_node == 0)
                        prom_printf("... failed\n");
                else
                        prom_printf("... done\n");
@@ -1279,12 +1293,12 @@ static void __init prom_init_client_services(unsigned long pp)
 
        /* get a handle for the stdout device */
        _prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));
-       if ((long)_prom->chosen <= 0)
+       if (!PHANDLE_VALID(_prom->chosen))
                prom_panic("cannot find chosen"); /* msg won't be printed :( */
 
        /* get device tree root */
        _prom->root = call_prom("finddevice", 1, 1, ADDR("/"));
-       if ((long)_prom->root <= 0)
+       if (!PHANDLE_VALID(_prom->root))
                prom_panic("cannot find device tree root"); /* msg won't be printed :( */
 }
 
@@ -1356,9 +1370,8 @@ static int __init prom_find_machine_type(void)
        }
        /* Default to pSeries. We need to know if we are running LPAR */
        rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
-       if (rtas != (phandle) -1) {
-               unsigned long x;
-               x = prom_getproplen(rtas, "ibm,hypertas-functions");
+       if (PHANDLE_VALID(rtas)) {
+               int x = prom_getproplen(rtas, "ibm,hypertas-functions");
                if (x != PROM_ERROR) {
                        prom_printf("Hypertas detected, assuming LPAR !\n");
                        return PLATFORM_PSERIES_LPAR;
@@ -1426,12 +1439,13 @@ static void __init prom_check_displays(void)
                 * leave some room at the end of the path for appending extra
                 * arguments
                 */
-               if (call_prom("package-to-path", 3, 1, node, path, PROM_SCRATCH_SIZE-10) < 0)
+               if (call_prom("package-to-path", 3, 1, node, path,
+                             PROM_SCRATCH_SIZE-10) == PROM_ERROR)
                        continue;
                prom_printf("found display   : %s, opening ... ", path);
                
                ih = call_prom("open", 1, 1, path);
-               if (ih == (ihandle)0 || ih == (ihandle)-1) {
+               if (ih == 0) {
                        prom_printf("failed\n");
                        continue;
                }
@@ -1514,6 +1528,12 @@ static unsigned long __init dt_find_string(char *str)
        return 0;
 }
 
+/*
+ * The Open Firmware 1275 specification states properties must be 31 bytes or
+ * less, however not all firmwares obey this. Make it 64 bytes to be safe.
+ */
+#define MAX_PROPERTY_NAME 64
+
 static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
                                         unsigned long *mem_end)
 {
@@ -1527,10 +1547,12 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
        /* get and store all property names */
        prev_name = RELOC("");
        for (;;) {
-               
-               /* 32 is max len of name including nul. */
-               namep = make_room(mem_start, mem_end, 32, 1);
-               if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0) {
+               int rc;
+
+               /* 64 is max len of name including nul. */
+               namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
+               rc = call_prom("nextprop", 3, 1, node, prev_name, namep);
+               if (rc != 1) {
                        /* No more nodes: unwind alloc */
                        *mem_start = (unsigned long)namep;
                        break;
@@ -1555,12 +1577,6 @@ static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
        }
 }
 
-/*
- * The Open Firmware 1275 specification states properties must be 31 bytes or
- * less, however not all firmwares obey this. Make it 64 bytes to be safe.
- */
-#define MAX_PROPERTY_NAME 64
-
 static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
                                        unsigned long *mem_end)
 {
@@ -1607,7 +1623,10 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
        prev_name = RELOC("");
        sstart = (char *)RELOC(dt_string_start);
        for (;;) {
-               if (call_prom("nextprop", 3, 1, node, prev_name, pname) <= 0)
+               int rc;
+
+               rc = call_prom("nextprop", 3, 1, node, prev_name, pname);
+               if (rc != 1)
                        break;
 
                /* find string offset */
@@ -1623,7 +1642,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
                l = call_prom("getproplen", 2, 1, node, pname);
 
                /* sanity checks */
-               if (l < 0)
+               if (l == PROM_ERROR)
                        continue;
                if (l > MAX_PROPERTY_LENGTH) {
                        prom_printf("WARNING: ignoring large property ");
@@ -1771,17 +1790,18 @@ static void __init fixup_device_tree(void)
 
        /* Some G5s have a missing interrupt definition, fix it up here */
        u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));
-       if ((long)u3 <= 0)
+       if (!PHANDLE_VALID(u3))
                return;
        i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));
-       if ((long)i2c <= 0)
+       if (!PHANDLE_VALID(i2c))
                return;
        mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));
-       if ((long)mpic <= 0)
+       if (!PHANDLE_VALID(mpic))
                return;
 
        /* check if proper rev of u3 */
-       if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev)) <= 0)
+       if (prom_getprop(u3, "device-rev", &u3_rev, sizeof(u3_rev))
+           == PROM_ERROR)
                return;
        if (u3_rev != 0x35)
                return;
index 21c57f539c29305b1bf7ecef8c8a7a5b72a33046..dce198d39328aefd6541efef430f6a6e71d9ca4f 100644 (file)
@@ -103,11 +103,6 @@ extern void unflatten_device_tree(void);
 
 extern void smp_release_cpus(void);
 
-unsigned long decr_overclock = 1;
-unsigned long decr_overclock_proc0 = 1;
-unsigned long decr_overclock_set = 0;
-unsigned long decr_overclock_proc0_set = 0;
-
 int have_of = 1;
 int boot_cpuid = 0;
 int boot_cpuid_phys = 0;
@@ -1120,64 +1115,15 @@ void ppc64_dump_msg(unsigned int src, const char *msg)
        printk("[dump]%04x %s\n", src, msg);
 }
 
-int set_spread_lpevents( char * str )
-{
-       /* The parameter is the number of processors to share in processing lp events */
-       unsigned long i;
-       unsigned long val = simple_strtoul( str, NULL, 0 );
-       if ( ( val > 0 ) && ( val <= NR_CPUS ) ) {
-               for ( i=1; i<val; ++i )
-                       paca[i].lpqueue_ptr = paca[0].lpqueue_ptr;
-               printk("lpevent processing spread over %ld processors\n", val);
-       }
-       else
-               printk("invalid spreaqd_lpevents %ld\n", val);
-       return 1;
-}      
-
 /* This should only be called on processor 0 during calibrate decr */
 void setup_default_decr(void)
 {
        struct paca_struct *lpaca = get_paca();
 
-       if ( decr_overclock_set && !decr_overclock_proc0_set )
-               decr_overclock_proc0 = decr_overclock;
-
-       lpaca->default_decr = tb_ticks_per_jiffy / decr_overclock_proc0;        
+       lpaca->default_decr = tb_ticks_per_jiffy;
        lpaca->next_jiffy_update_tb = get_tb() + tb_ticks_per_jiffy;
 }
 
-int set_decr_overclock_proc0( char * str )
-{
-       unsigned long val = simple_strtoul( str, NULL, 0 );
-       if ( ( val >= 1 ) && ( val <= 48 ) ) {
-               decr_overclock_proc0_set = 1;
-               decr_overclock_proc0 = val;
-               printk("proc 0 decrementer overclock factor of %ld\n", val);
-       }
-       else
-               printk("invalid proc 0 decrementer overclock factor of %ld\n", val);
-       return 1;
-}
-
-int set_decr_overclock( char * str )
-{
-       unsigned long val = simple_strtoul( str, NULL, 0 );
-       if ( ( val >= 1 ) && ( val <= 48 ) ) {
-               decr_overclock_set = 1;
-               decr_overclock = val;
-               printk("decrementer overclock factor of %ld\n", val);
-       }
-       else
-               printk("invalid decrementer overclock factor of %ld\n", val);
-       return 1;
-
-}
-
-__setup("spread_lpevents=", set_spread_lpevents );
-__setup("decr_overclock_proc0=", set_decr_overclock_proc0 );
-__setup("decr_overclock=", set_decr_overclock );
-
 #ifndef CONFIG_PPC_ISERIES
 /*
  * This function can be used by platforms to "find" legacy serial ports.
index 3b906cd940378086b84d18f2d0b71c70a33308cc..9ef5d36d6b253d38127cc026554e2d0e698f87d5 100644 (file)
@@ -334,7 +334,6 @@ void smp_call_function_interrupt(void)
        }
 }
 
-extern unsigned long decr_overclock;
 extern struct gettimeofday_struct do_gtod;
 
 struct thread_info *current_set[NR_CPUS];
@@ -491,7 +490,7 @@ int __devinit __cpu_up(unsigned int cpu)
        if (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu))
                return -EINVAL;
 
-       paca[cpu].default_decr = tb_ticks_per_jiffy / decr_overclock;
+       paca[cpu].default_decr = tb_ticks_per_jiffy;
 
        if (!cpu_has_feature(CPU_FTR_SLB)) {
                void *tmp;
index 0925694c3ce5e7873438ae300075a80d648e7657..c8fa6569b2fd789fc3476a3c5ab86c3bf6b3c203 100644 (file)
@@ -113,7 +113,6 @@ void ppc64_enable_pmcs(void)
 #ifdef CONFIG_PPC_PSERIES
        unsigned long set, reset;
        int ret;
-       unsigned int ctrl;
 #endif /* CONFIG_PPC_PSERIES */
 
        /* Only need to enable them once */
@@ -167,11 +166,8 @@ void ppc64_enable_pmcs(void)
         * On SMT machines we have to set the run latch in the ctrl register
         * in order to make PMC6 spin.
         */
-       if (cpu_has_feature(CPU_FTR_SMT)) {
-               ctrl = mfspr(CTRLF);
-               ctrl |= RUNLATCH;
-               mtspr(CTRLT, ctrl);
-       }
+       if (cpu_has_feature(CPU_FTR_SMT))
+               ppc64_runlatch_on();
 #endif /* CONFIG_PPC_PSERIES */
 }
 
index 01ae1964c938cd828379dc594087299309531725..c067435bae4506130b9dd05cbf4e6a30078000a1 100644 (file)
@@ -28,6 +28,7 @@
 //#include <linux/kernel_stat.h>
 #include <linux/notifier.h>
 #include <linux/cpu.h>
+#include <linux/workqueue.h>
 
 #include "appldata.h"
 
@@ -133,9 +134,12 @@ static int appldata_interval = APPLDATA_CPU_INTERVAL;
 static int appldata_timer_active;
 
 /*
- * Tasklet
+ * Work queue
  */
-static struct tasklet_struct appldata_tasklet_struct;
+static struct workqueue_struct *appldata_wq;
+static void appldata_work_fn(void *data);
+static DECLARE_WORK(appldata_work, appldata_work_fn, NULL);
+
 
 /*
  * Ops list
@@ -144,11 +148,11 @@ static DEFINE_SPINLOCK(appldata_ops_lock);
 static LIST_HEAD(appldata_ops_list);
 
 
-/************************* timer, tasklet, DIAG ******************************/
+/*************************** timer, work, DIAG *******************************/
 /*
  * appldata_timer_function()
  *
- * schedule tasklet and reschedule timer
+ * schedule work and reschedule timer
  */
 static void appldata_timer_function(unsigned long data, struct pt_regs *regs)
 {
@@ -157,22 +161,22 @@ static void appldata_timer_function(unsigned long data, struct pt_regs *regs)
                atomic_read(&appldata_expire_count));
        if (atomic_dec_and_test(&appldata_expire_count)) {
                atomic_set(&appldata_expire_count, num_online_cpus());
-               tasklet_schedule((struct tasklet_struct *) data);
+               queue_work(appldata_wq, (struct work_struct *) data);
        }
 }
 
 /*
- * appldata_tasklet_function()
+ * appldata_work_fn()
  *
  * call data gathering function for each (active) module
  */
-static void appldata_tasklet_function(unsigned long data)
+static void appldata_work_fn(void *data)
 {
        struct list_head *lh;
        struct appldata_ops *ops;
        int i;
 
-       P_DEBUG("  -= Tasklet =-\n");
+       P_DEBUG("  -= Work Queue =-\n");
        i = 0;
        spin_lock(&appldata_ops_lock);
        list_for_each(lh, &appldata_ops_list) {
@@ -231,7 +235,7 @@ static int appldata_diag(char record_nr, u16 function, unsigned long buffer,
                        : "=d" (ry) : "d" (&(appldata_parameter_list)) : "cc");
        return (int) ry;
 }
-/********************** timer, tasklet, DIAG <END> ***************************/
+/************************ timer, work, DIAG <END> ****************************/
 
 
 /****************************** /proc stuff **********************************/
@@ -411,7 +415,7 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp,
        struct list_head *lh;
 
        found = 0;
-       spin_lock_bh(&appldata_ops_lock);
+       spin_lock(&appldata_ops_lock);
        list_for_each(lh, &appldata_ops_list) {
                tmp_ops = list_entry(lh, struct appldata_ops, list);
                if (&tmp_ops->ctl_table[2] == ctl) {
@@ -419,15 +423,15 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp,
                }
        }
        if (!found) {
-               spin_unlock_bh(&appldata_ops_lock);
+               spin_unlock(&appldata_ops_lock);
                return -ENODEV;
        }
        ops = ctl->data;
        if (!try_module_get(ops->owner)) {      // protect this function
-               spin_unlock_bh(&appldata_ops_lock);
+               spin_unlock(&appldata_ops_lock);
                return -ENODEV;
        }
-       spin_unlock_bh(&appldata_ops_lock);
+       spin_unlock(&appldata_ops_lock);
 
        if (!*lenp || *ppos) {
                *lenp = 0;
@@ -451,10 +455,11 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp,
                return -EFAULT;
        }
 
-       spin_lock_bh(&appldata_ops_lock);
+       spin_lock(&appldata_ops_lock);
        if ((buf[0] == '1') && (ops->active == 0)) {
-               if (!try_module_get(ops->owner)) {      // protect tasklet
-                       spin_unlock_bh(&appldata_ops_lock);
+               // protect work queue callback
+               if (!try_module_get(ops->owner)) {
+                       spin_unlock(&appldata_ops_lock);
                        module_put(ops->owner);
                        return -ENODEV;
                }
@@ -485,7 +490,7 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp,
                }
                module_put(ops->owner);
        }
-       spin_unlock_bh(&appldata_ops_lock);
+       spin_unlock(&appldata_ops_lock);
 out:
        *lenp = len;
        *ppos += len;
@@ -529,7 +534,7 @@ int appldata_register_ops(struct appldata_ops *ops)
        }
        memset(ops->ctl_table, 0, 4*sizeof(struct ctl_table));
 
-       spin_lock_bh(&appldata_ops_lock);
+       spin_lock(&appldata_ops_lock);
        list_for_each(lh, &appldata_ops_list) {
                tmp_ops = list_entry(lh, struct appldata_ops, list);
                P_DEBUG("register_ops loop: %i) name = %s, ctl = %i\n",
@@ -541,18 +546,18 @@ int appldata_register_ops(struct appldata_ops *ops)
                                APPLDATA_PROC_NAME_LENGTH) == 0) {
                        P_ERROR("Name \"%s\" already registered!\n", ops->name);
                        kfree(ops->ctl_table);
-                       spin_unlock_bh(&appldata_ops_lock);
+                       spin_unlock(&appldata_ops_lock);
                        return -EBUSY;
                }
                if (tmp_ops->ctl_nr == ops->ctl_nr) {
                        P_ERROR("ctl_nr %i already registered!\n", ops->ctl_nr);
                        kfree(ops->ctl_table);
-                       spin_unlock_bh(&appldata_ops_lock);
+                       spin_unlock(&appldata_ops_lock);
                        return -EBUSY;
                }
        }
        list_add(&ops->list, &appldata_ops_list);
-       spin_unlock_bh(&appldata_ops_lock);
+       spin_unlock(&appldata_ops_lock);
 
        ops->ctl_table[0].ctl_name = CTL_APPLDATA;
        ops->ctl_table[0].procname = appldata_proc_name;
@@ -583,12 +588,12 @@ int appldata_register_ops(struct appldata_ops *ops)
  */
 void appldata_unregister_ops(struct appldata_ops *ops)
 {
-       spin_lock_bh(&appldata_ops_lock);
+       spin_lock(&appldata_ops_lock);
        unregister_sysctl_table(ops->sysctl_header);
        list_del(&ops->list);
        kfree(ops->ctl_table);
        ops->ctl_table = NULL;
-       spin_unlock_bh(&appldata_ops_lock);
+       spin_unlock(&appldata_ops_lock);
        P_INFO("%s-ops unregistered!\n", ops->name);
 }
 /********************** module-ops management <END> **************************/
@@ -602,7 +607,7 @@ appldata_online_cpu(int cpu)
        init_virt_timer(&per_cpu(appldata_timer, cpu));
        per_cpu(appldata_timer, cpu).function = appldata_timer_function;
        per_cpu(appldata_timer, cpu).data = (unsigned long)
-               &appldata_tasklet_struct;
+               &appldata_work;
        atomic_inc(&appldata_expire_count);
        spin_lock(&appldata_timer_lock);
        __appldata_vtimer_setup(APPLDATA_MOD_TIMER);
@@ -615,7 +620,7 @@ appldata_offline_cpu(int cpu)
        del_virt_timer(&per_cpu(appldata_timer, cpu));
        if (atomic_dec_and_test(&appldata_expire_count)) {
                atomic_set(&appldata_expire_count, num_online_cpus());
-               tasklet_schedule(&appldata_tasklet_struct);
+               queue_work(appldata_wq, &appldata_work);
        }
        spin_lock(&appldata_timer_lock);
        __appldata_vtimer_setup(APPLDATA_MOD_TIMER);
@@ -648,7 +653,7 @@ static struct notifier_block __devinitdata appldata_nb = {
 /*
  * appldata_init()
  *
- * init timer and tasklet, register /proc entries
+ * init timer, register /proc entries
  */
 static int __init appldata_init(void)
 {
@@ -657,6 +662,12 @@ static int __init appldata_init(void)
        P_DEBUG("sizeof(parameter_list) = %lu\n",
                sizeof(struct appldata_parameter_list));
 
+       appldata_wq = create_singlethread_workqueue("appldata");
+       if (!appldata_wq) {
+               P_ERROR("Could not create work queue\n");
+               return -ENOMEM;
+       }
+
        for_each_online_cpu(i)
                appldata_online_cpu(i);
 
@@ -670,7 +681,6 @@ static int __init appldata_init(void)
        appldata_table[1].de->owner = THIS_MODULE;
 #endif
 
-       tasklet_init(&appldata_tasklet_struct, appldata_tasklet_function, 0);
        P_DEBUG("Base interface initialized.\n");
        return 0;
 }
@@ -678,7 +688,7 @@ static int __init appldata_init(void)
 /*
  * appldata_exit()
  *
- * stop timer and tasklet, unregister /proc entries
+ * stop timer, unregister /proc entries
  */
 static void __exit appldata_exit(void)
 {
@@ -690,7 +700,7 @@ static void __exit appldata_exit(void)
        /*
         * ops list should be empty, but just in case something went wrong...
         */
-       spin_lock_bh(&appldata_ops_lock);
+       spin_lock(&appldata_ops_lock);
        list_for_each(lh, &appldata_ops_list) {
                ops = list_entry(lh, struct appldata_ops, list);
                rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC,
@@ -700,7 +710,7 @@ static void __exit appldata_exit(void)
                                "return code: %d\n", ops->name, rc);
                }
        }
-       spin_unlock_bh(&appldata_ops_lock);
+       spin_unlock(&appldata_ops_lock);
 
        for_each_online_cpu(i)
                appldata_offline_cpu(i);
@@ -709,7 +719,7 @@ static void __exit appldata_exit(void)
 
        unregister_sysctl_table(appldata_sysctl_header);
 
-       tasklet_kill(&appldata_tasklet_struct);
+       destroy_workqueue(appldata_wq);
        P_DEBUG("... module unloaded!\n");
 }
 /**************************** init / exit <END> ******************************/
index 462ee9a84e7655fb39403fdcc4ff2ba83e33823b..f0e2fbed3d4cf86a8000ec212e435546098507fc 100644 (file)
@@ -68,7 +68,7 @@ struct appldata_mem_data {
        u64 pgmajfault;         /* page faults (major only) */
 // <-- New in 2.6
 
-} appldata_mem_data;
+} __attribute__((packed)) appldata_mem_data;
 
 
 static inline void appldata_debug_print(struct appldata_mem_data *mem_data)
index dd61638d3027c6eddcaa0bf8bfd5e1d8d2477541..2a4c7432db4ac2960cde34ee6033671fe171cfc5 100644 (file)
@@ -57,7 +57,7 @@ struct appldata_net_sum_data {
        u64 rx_dropped;         /* no space in linux buffers     */
        u64 tx_dropped;         /* no space available in linux   */
        u64 collisions;         /* collisions while transmitting */
-} appldata_net_sum_data;
+} __attribute__((packed)) appldata_net_sum_data;
 
 
 static inline void appldata_print_debug(struct appldata_net_sum_data *net_data)
index b83f074845514ad409f8c5da3e57cf3a2c2b8459..e0a476bf4fd644691bf5b50e93db05a2367b59bd 100644 (file)
@@ -49,7 +49,7 @@ struct appldata_os_per_cpu {
        u32 per_cpu_softirq;    /* ... spent in softirqs            */
        u32 per_cpu_iowait;     /* ... spent while waiting for I/O  */
 // <-- New in 2.6
-};
+} __attribute__((packed));
 
 struct appldata_os_data {
        u64 timestamp;
@@ -75,7 +75,7 @@ struct appldata_os_data {
 
        /* per cpu data */
        struct appldata_os_per_cpu os_cpu[0];
-};
+} __attribute__((packed));
 
 static struct appldata_os_data *appldata_os_data;
 
index 26889366929a1ac3d9162a2ba357dd837a143877..06afa3103ace75143d44258c215cc9c3d1a7fb00 100644 (file)
@@ -40,6 +40,7 @@
 #include <asm/pgalloc.h>
 #include <asm/system.h>
 #include <asm/uaccess.h>
+#include <asm/unistd.h>
 
 #ifdef CONFIG_S390_SUPPORT
 #include "compat_ptrace.h"
@@ -130,13 +131,19 @@ static int
 peek_user(struct task_struct *child, addr_t addr, addr_t data)
 {
        struct user *dummy = NULL;
-       addr_t offset, tmp;
+       addr_t offset, tmp, mask;
 
        /*
         * Stupid gdb peeks/pokes the access registers in 64 bit with
         * an alignment of 4. Programmers from hell...
         */
-       if ((addr & 3) || addr > sizeof(struct user) - __ADDR_MASK)
+       mask = __ADDR_MASK;
+#ifdef CONFIG_ARCH_S390X
+       if (addr >= (addr_t) &dummy->regs.acrs &&
+           addr < (addr_t) &dummy->regs.orig_gpr2)
+               mask = 3;
+#endif
+       if ((addr & mask) || addr > sizeof(struct user) - __ADDR_MASK)
                return -EIO;
 
        if (addr < (addr_t) &dummy->regs.acrs) {
@@ -153,6 +160,16 @@ peek_user(struct task_struct *child, addr_t addr, addr_t data)
                 * access registers are stored in the thread structure
                 */
                offset = addr - (addr_t) &dummy->regs.acrs;
+#ifdef CONFIG_ARCH_S390X
+               /*
+                * Very special case: old & broken 64 bit gdb reading
+                * from acrs[15]. Result is a 64 bit value. Read the
+                * 32 bit acrs[15] value and shift it by 32. Sick...
+                */
+               if (addr == (addr_t) &dummy->regs.acrs[15])
+                       tmp = ((unsigned long) child->thread.acrs[15]) << 32;
+               else
+#endif
                tmp = *(addr_t *)((addr_t) &child->thread.acrs + offset);
 
        } else if (addr == (addr_t) &dummy->regs.orig_gpr2) {
@@ -167,6 +184,9 @@ peek_user(struct task_struct *child, addr_t addr, addr_t data)
                 */
                offset = addr - (addr_t) &dummy->regs.fp_regs;
                tmp = *(addr_t *)((addr_t) &child->thread.fp_regs + offset);
+               if (addr == (addr_t) &dummy->regs.fp_regs.fpc)
+                       tmp &= (unsigned long) FPC_VALID_MASK
+                               << (BITS_PER_LONG - 32);
 
        } else if (addr < (addr_t) (&dummy->regs.per_info + 1)) {
                /*
@@ -191,13 +211,19 @@ static int
 poke_user(struct task_struct *child, addr_t addr, addr_t data)
 {
        struct user *dummy = NULL;
-       addr_t offset;
+       addr_t offset, mask;
 
        /*
         * Stupid gdb peeks/pokes the access registers in 64 bit with
         * an alignment of 4. Programmers from hell indeed...
         */
-       if ((addr & 3) || addr > sizeof(struct user) - __ADDR_MASK)
+       mask = __ADDR_MASK;
+#ifdef CONFIG_ARCH_S390X
+       if (addr >= (addr_t) &dummy->regs.acrs &&
+           addr < (addr_t) &dummy->regs.orig_gpr2)
+               mask = 3;
+#endif
+       if ((addr & mask) || addr > sizeof(struct user) - __ADDR_MASK)
                return -EIO;
 
        if (addr < (addr_t) &dummy->regs.acrs) {
@@ -224,6 +250,17 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data)
                 * access registers are stored in the thread structure
                 */
                offset = addr - (addr_t) &dummy->regs.acrs;
+#ifdef CONFIG_ARCH_S390X
+               /*
+                * Very special case: old & broken 64 bit gdb writing
+                * to acrs[15] with a 64 bit value. Ignore the lower
+                * half of the value and write the upper 32 bit to
+                * acrs[15]. Sick...
+                */
+               if (addr == (addr_t) &dummy->regs.acrs[15])
+                       child->thread.acrs[15] = (unsigned int) (data >> 32);
+               else
+#endif
                *(addr_t *)((addr_t) &child->thread.acrs + offset) = data;
 
        } else if (addr == (addr_t) &dummy->regs.orig_gpr2) {
@@ -237,7 +274,8 @@ poke_user(struct task_struct *child, addr_t addr, addr_t data)
                 * floating point regs. are stored in the thread structure
                 */
                if (addr == (addr_t) &dummy->regs.fp_regs.fpc &&
-                   (data & ~FPC_VALID_MASK) != 0)
+                   (data & ~((unsigned long) FPC_VALID_MASK
+                             << (BITS_PER_LONG - 32))) != 0)
                        return -EINVAL;
                offset = addr - (addr_t) &dummy->regs.fp_regs;
                *(addr_t *)((addr_t) &child->thread.fp_regs + offset) = data;
@@ -722,6 +760,13 @@ syscall_trace(struct pt_regs *regs, int entryexit)
        ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
                                 ? 0x80 : 0));
 
+       /*
+        * If the debuffer has set an invalid system call number,
+        * we prepare to skip the system call restart handling.
+        */
+       if (!entryexit && regs->gprs[2] >= NR_syscalls)
+               regs->trap = -1;
+
        /*
         * this isn't the same as continuing with a signal, but it will do
         * for normal use.  strace only continues with a signal if the
index 80306bc8c799b7c7e8c98d819806a78a1a7eb951..75fde949d12570a68d1a5aaa228fc946fccc0c4b 100644 (file)
@@ -207,7 +207,7 @@ do_exception(struct pt_regs *regs, unsigned long error_code, int is_protection)
         * we are not in an interrupt and that there is a 
         * user context.
         */
-        if (user_address == 0 || in_interrupt() || !mm)
+        if (user_address == 0 || in_atomic() || !mm)
                 goto no_context;
 
        /*
index 33ca56c90da2637a6e233535239d74131c1b5455..2803bc7c2c798af12fc0d57b701991bc51727995 100644 (file)
@@ -196,6 +196,34 @@ static iopte_t *alloc_consistent_cluster(struct pci_iommu *iommu, unsigned long
        return NULL;
 }
 
+static int iommu_alloc_ctx(struct pci_iommu *iommu)
+{
+       int lowest = iommu->ctx_lowest_free;
+       int sz = IOMMU_NUM_CTXS - lowest;
+       int n = find_next_zero_bit(iommu->ctx_bitmap, sz, lowest);
+
+       if (unlikely(n == sz)) {
+               n = find_next_zero_bit(iommu->ctx_bitmap, lowest, 1);
+               if (unlikely(n == lowest)) {
+                       printk(KERN_WARNING "IOMMU: Ran out of contexts.\n");
+                       n = 0;
+               }
+       }
+       if (n)
+               __set_bit(n, iommu->ctx_bitmap);
+
+       return n;
+}
+
+static inline void iommu_free_ctx(struct pci_iommu *iommu, int ctx)
+{
+       if (likely(ctx)) {
+               __clear_bit(ctx, iommu->ctx_bitmap);
+               if (ctx < iommu->ctx_lowest_free)
+                       iommu->ctx_lowest_free = ctx;
+       }
+}
+
 /* Allocate and map kernel buffer of size SIZE using consistent mode
  * DMA for PCI device PDEV.  Return non-NULL cpu-side address if
  * successful and set *DMA_ADDRP to the PCI side dma address.
@@ -236,7 +264,7 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_ad
        npages = size >> IO_PAGE_SHIFT;
        ctx = 0;
        if (iommu->iommu_ctxflush)
-               ctx = iommu->iommu_cur_ctx++;
+               ctx = iommu_alloc_ctx(iommu);
        first_page = __pa(first_page);
        while (npages--) {
                iopte_val(*iopte) = (IOPTE_CONSISTENT(ctx) |
@@ -317,6 +345,8 @@ void pci_free_consistent(struct pci_dev *pdev, size_t size, void *cpu, dma_addr_
                }
        }
 
+       iommu_free_ctx(iommu, ctx);
+
        spin_unlock_irqrestore(&iommu->lock, flags);
 
        order = get_order(size);
@@ -360,7 +390,7 @@ dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr, size_t sz, int direct
        base_paddr = __pa(oaddr & IO_PAGE_MASK);
        ctx = 0;
        if (iommu->iommu_ctxflush)
-               ctx = iommu->iommu_cur_ctx++;
+               ctx = iommu_alloc_ctx(iommu);
        if (strbuf->strbuf_enabled)
                iopte_protection = IOPTE_STREAMING(ctx);
        else
@@ -380,39 +410,53 @@ bad:
        return PCI_DMA_ERROR_CODE;
 }
 
-static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages)
+static void pci_strbuf_flush(struct pci_strbuf *strbuf, struct pci_iommu *iommu, u32 vaddr, unsigned long ctx, unsigned long npages, int direction)
 {
        int limit;
 
-       PCI_STC_FLUSHFLAG_INIT(strbuf);
        if (strbuf->strbuf_ctxflush &&
            iommu->iommu_ctxflush) {
                unsigned long matchreg, flushreg;
+               u64 val;
 
                flushreg = strbuf->strbuf_ctxflush;
                matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
 
-               limit = 100000;
                pci_iommu_write(flushreg, ctx);
-               for(;;) {
-                       if (((long)pci_iommu_read(matchreg)) >= 0L)
-                               break;
-                       limit--;
-                       if (!limit)
-                               break;
-                       udelay(1);
+               val = pci_iommu_read(matchreg);
+               val &= 0xffff;
+               if (!val)
+                       goto do_flush_sync;
+
+               while (val) {
+                       if (val & 0x1)
+                               pci_iommu_write(flushreg, ctx);
+                       val >>= 1;
                }
-               if (!limit)
+               val = pci_iommu_read(matchreg);
+               if (unlikely(val)) {
                        printk(KERN_WARNING "pci_strbuf_flush: ctx flush "
-                              "timeout vaddr[%08x] ctx[%lx]\n",
-                              vaddr, ctx);
+                              "timeout matchreg[%lx] ctx[%lx]\n",
+                              val, ctx);
+                       goto do_page_flush;
+               }
        } else {
                unsigned long i;
 
+       do_page_flush:
                for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE)
                        pci_iommu_write(strbuf->strbuf_pflush, vaddr);
        }
 
+do_flush_sync:
+       /* If the device could not have possibly put dirty data into
+        * the streaming cache, no flush-flag synchronization needs
+        * to be performed.
+        */
+       if (direction == PCI_DMA_TODEVICE)
+               return;
+
+       PCI_STC_FLUSHFLAG_INIT(strbuf);
        pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
        (void) pci_iommu_read(iommu->write_complete_reg);
 
@@ -466,7 +510,7 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int
 
        /* Step 1: Kick data out of streaming buffers if necessary. */
        if (strbuf->strbuf_enabled)
-               pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages);
+               pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
 
        /* Step 2: Clear out first TSB entry. */
        iopte_make_dummy(iommu, base);
@@ -474,6 +518,8 @@ void pci_unmap_single(struct pci_dev *pdev, dma_addr_t bus_addr, size_t sz, int
        free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base,
                               npages, ctx);
 
+       iommu_free_ctx(iommu, ctx);
+
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
@@ -613,7 +659,7 @@ int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int
        /* Step 4: Choose a context if necessary. */
        ctx = 0;
        if (iommu->iommu_ctxflush)
-               ctx = iommu->iommu_cur_ctx++;
+               ctx = iommu_alloc_ctx(iommu);
 
        /* Step 5: Create the mappings. */
        if (strbuf->strbuf_enabled)
@@ -678,7 +724,7 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems,
 
        /* Step 1: Kick data out of streaming buffers if necessary. */
        if (strbuf->strbuf_enabled)
-               pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages);
+               pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
 
        /* Step 2: Clear out first TSB entry. */
        iopte_make_dummy(iommu, base);
@@ -686,6 +732,8 @@ void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems,
        free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base,
                               npages, ctx);
 
+       iommu_free_ctx(iommu, ctx);
+
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
@@ -724,7 +772,7 @@ void pci_dma_sync_single_for_cpu(struct pci_dev *pdev, dma_addr_t bus_addr, size
        }
 
        /* Step 2: Kick data out of streaming buffers. */
-       pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages);
+       pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
 
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
@@ -768,7 +816,7 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev, struct scatterlist *sglist, i
        i--;
        npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length)
                  - bus_addr) >> IO_PAGE_SHIFT;
-       pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages);
+       pci_strbuf_flush(strbuf, iommu, bus_addr, ctx, npages, direction);
 
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
index 3567fa879e1fe7a900e545704ad97593d01cc820..534320ef0db2a43992ac6341df4c444d9ccc2182 100644 (file)
@@ -1212,7 +1212,7 @@ static void __init psycho_iommu_init(struct pci_controller_info *p)
 
        /* Setup initial software IOMMU state. */
        spin_lock_init(&iommu->lock);
-       iommu->iommu_cur_ctx = 0;
+       iommu->ctx_lowest_free = 1;
 
        /* Register addresses. */
        iommu->iommu_control  = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL;
index 5525d1ec4af883884404d13b17ddc6deda8379f5..53d333b4a4e809f7ebf48231c46bb5e65af86ec3 100644 (file)
@@ -1265,7 +1265,7 @@ static void __init sabre_iommu_init(struct pci_controller_info *p,
 
        /* Setup initial software IOMMU state. */
        spin_lock_init(&iommu->lock);
-       iommu->iommu_cur_ctx = 0;
+       iommu->ctx_lowest_free = 1;
 
        /* Register addresses. */
        iommu->iommu_control  = p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL;
index e93fcadc37229f99221d1e7781941e5f00ddf0b1..5753175b94e6c91da7eb7ad91fcf197585bf3c98 100644 (file)
@@ -1753,7 +1753,7 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
 
        /* Setup initial software IOMMU state. */
        spin_lock_init(&iommu->lock);
-       iommu->iommu_cur_ctx = 0;
+       iommu->ctx_lowest_free = 1;
 
        /* Register addresses, SCHIZO has iommu ctx flushing. */
        iommu->iommu_control  = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL;
index 76ea6455433f1a7aa89005190b4fe60d56d3aea3..89f5e019f24c02ade1ed11ab0c6ed721de1b4bfd 100644 (file)
@@ -117,17 +117,25 @@ static void iommu_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages
 
 #define STRBUF_TAG_VALID       0x02UL
 
-static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages)
+static void sbus_strbuf_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages, int direction)
 {
        unsigned long n;
        int limit;
 
-       iommu->strbuf_flushflag = 0UL;
        n = npages;
        while (n--)
                upa_writeq(base + (n << IO_PAGE_SHIFT),
                           iommu->strbuf_regs + STRBUF_PFLUSH);
 
+       /* If the device could not have possibly put dirty data into
+        * the streaming cache, no flush-flag synchronization needs
+        * to be performed.
+        */
+       if (direction == SBUS_DMA_TODEVICE)
+               return;
+
+       iommu->strbuf_flushflag = 0UL;
+
        /* Whoopee cushion! */
        upa_writeq(__pa(&iommu->strbuf_flushflag),
                   iommu->strbuf_regs + STRBUF_FSYNC);
@@ -421,7 +429,7 @@ void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t dma_addr, size_t size,
 
        spin_lock_irqsave(&iommu->lock, flags);
        free_streaming_cluster(iommu, dma_base, size >> IO_PAGE_SHIFT);
-       sbus_strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT);
+       sbus_strbuf_flush(iommu, dma_base, size >> IO_PAGE_SHIFT, direction);
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
@@ -584,7 +592,7 @@ void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int nents, int
        iommu = sdev->bus->iommu;
        spin_lock_irqsave(&iommu->lock, flags);
        free_streaming_cluster(iommu, dvma_base, size >> IO_PAGE_SHIFT);
-       sbus_strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT);
+       sbus_strbuf_flush(iommu, dvma_base, size >> IO_PAGE_SHIFT, direction);
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
@@ -596,7 +604,7 @@ void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, dma_addr_t base, size_t
        size = (IO_PAGE_ALIGN(base + size) - (base & IO_PAGE_MASK));
 
        spin_lock_irqsave(&iommu->lock, flags);
-       sbus_strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT);
+       sbus_strbuf_flush(iommu, base & IO_PAGE_MASK, size >> IO_PAGE_SHIFT, direction);
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
@@ -620,7 +628,7 @@ void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, struct scatterlist *sg, int
        size = IO_PAGE_ALIGN(sg[i].dma_address + sg[i].dma_length) - base;
 
        spin_lock_irqsave(&iommu->lock, flags);
-       sbus_strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT);
+       sbus_strbuf_flush(iommu, base, size >> IO_PAGE_SHIFT, direction);
        spin_unlock_irqrestore(&iommu->lock, flags);
 }
 
index d1dcd8eae3c901c3bacb00f08875ebb770141e44..5b77188527a9ad91f8d3f70691ba9c2d4393f4a1 100644 (file)
@@ -39,7 +39,8 @@ ifeq ($(CONFIG_ATM_FORE200E_PCA),y)
   fore_200e-objs               += fore200e_pca_fw.o
   # guess the target endianess to choose the right PCA-200E firmware image
   ifeq ($(CONFIG_ATM_FORE200E_PCA_DEFAULT_FW),y)
-    CONFIG_ATM_FORE200E_PCA_FW = $(shell if test -n "`$(CC) -E -dM $(src)/../../include/asm/byteorder.h | grep ' __LITTLE_ENDIAN '`"; then echo $(obj)/pca200e.bin; else echo $(obj)/pca200e_ecd.bin2; fi)
+    byteorder.h                        := include$(if $(patsubst $(srctree),,$(objtree)),2)/asm/byteorder.h
+    CONFIG_ATM_FORE200E_PCA_FW := $(obj)/pca200e$(if $(shell $(CC) -E -dM $(byteorder.h) | grep ' __LITTLE_ENDIAN '),.bin,_ecd.bin2)
   endif
 endif
 
index 9e65bfb85ba325285f299dcaf82388146bcafebb..5f702199543ac043eec3905b6231e119e421ba7c 100644 (file)
@@ -383,8 +383,7 @@ fore200e_shutdown(struct fore200e* fore200e)
     switch(fore200e->state) {
 
     case FORE200E_STATE_COMPLETE:
-       if (fore200e->stats)
-           kfree(fore200e->stats);
+       kfree(fore200e->stats);
 
     case FORE200E_STATE_IRQ:
        free_irq(fore200e->irq, fore200e->atm_dev);
@@ -963,8 +962,7 @@ fore200e_tx_irq(struct fore200e* fore200e)
                entry, txq->tail, entry->vc_map, entry->skb);
 
        /* free copy of misaligned data */
-       if (entry->data)
-           kfree(entry->data);
+       kfree(entry->data);
        
        /* remove DMA mapping */
        fore200e->bus->dma_unmap(fore200e, entry->tpd->tsd[ 0 ].buffer, entry->tpd->tsd[ 0 ].length,
index 3022c548a132317e4b8c9334b0cd520b63bde32e..df2c83fd5496015ac64025ea9762e90e80c5093f 100644 (file)
@@ -412,8 +412,7 @@ he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
 init_one_failure:
        if (atm_dev)
                atm_dev_deregister(atm_dev);
-       if (he_dev)
-               kfree(he_dev);
+       kfree(he_dev);
        pci_disable_device(pci_dev);
        return err;
 }
@@ -2534,8 +2533,7 @@ he_open(struct atm_vcc *vcc)
 open_failed:
 
        if (err) {
-               if (he_vcc)
-                       kfree(he_vcc);
+               kfree(he_vcc);
                clear_bit(ATM_VF_ADDR, &vcc->flags);
        }
        else
index 85bf5c8442b000917465b56fb9ce12d2b0e68a14..b2a7b754fd1403a4c7dbd4ffe5ab47cd3de70b5e 100644 (file)
@@ -676,10 +676,10 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev)
    PRINTK("nicstar%d: RSQ base at 0x%x.\n", i, (u32) card->rsq.base);
       
    /* Initialize SCQ0, the only VBR SCQ used */
-   card->scq1 = (scq_info *) NULL;
-   card->scq2 = (scq_info *) NULL;
+   card->scq1 = NULL;
+   card->scq2 = NULL;
    card->scq0 = get_scq(VBR_SCQSIZE, NS_VRSCD0);
-   if (card->scq0 == (scq_info *) NULL)
+   if (card->scq0 == NULL)
    {
       printk("nicstar%d: can't get SCQ0.\n", i);
       error = 12;
@@ -993,24 +993,24 @@ static scq_info *get_scq(int size, u32 scd)
    int i;
 
    if (size != VBR_SCQSIZE && size != CBR_SCQSIZE)
-      return (scq_info *) NULL;
+      return NULL;
 
    scq = (scq_info *) kmalloc(sizeof(scq_info), GFP_KERNEL);
-   if (scq == (scq_info *) NULL)
-      return (scq_info *) NULL;
+   if (scq == NULL)
+      return NULL;
    scq->org = kmalloc(2 * size, GFP_KERNEL);
    if (scq->org == NULL)
    {
       kfree(scq);
-      return (scq_info *) NULL;
+      return NULL;
    }
    scq->skb = (struct sk_buff **) kmalloc(sizeof(struct sk_buff *) *
                                           (size / NS_SCQE_SIZE), GFP_KERNEL);
-   if (scq->skb == (struct sk_buff **) NULL)
+   if (scq->skb == NULL)
    {
       kfree(scq->org);
       kfree(scq);
-      return (scq_info *) NULL;
+      return NULL;
    }
    scq->num_entries = size / NS_SCQE_SIZE;
    scq->base = (ns_scqe *) ALIGN_ADDRESS(scq->org, size);
@@ -1498,7 +1498,7 @@ static int ns_open(struct atm_vcc *vcc)
          vc->cbr_scd = NS_FRSCD + frscdi * NS_FRSCD_SIZE;
 
          scq = get_scq(CBR_SCQSIZE, vc->cbr_scd);
-         if (scq == (scq_info *) NULL)
+         if (scq == NULL)
          {
             PRINTK("nicstar%d: can't get fixed rate SCQ.\n", card->index);
             card->scd2vc[frscdi] = NULL;
index 47a800519ad01ed87638b329f1fd4a1213c6a641..8d5e65cb975528203ebb5b951044d9eaf73c91ad 100644 (file)
@@ -902,7 +902,7 @@ static void close_tx(struct atm_vcc *vcc)
                zatm_dev->tx_bw += vcc->qos.txtp.min_pcr;
                dealloc_shaper(vcc->dev,zatm_vcc->shaper);
        }
-       if (zatm_vcc->ring) kfree(zatm_vcc->ring);
+       kfree(zatm_vcc->ring);
 }
 
 
@@ -1339,12 +1339,9 @@ static int __init zatm_start(struct atm_dev *dev)
        return 0;
     out:
        for (i = 0; i < NR_MBX; i++)
-               if (zatm_dev->mbx_start[i] != 0)
-                       kfree((void *) zatm_dev->mbx_start[i]);
-       if (zatm_dev->rx_map != NULL)
-               kfree(zatm_dev->rx_map);
-       if (zatm_dev->tx_map != NULL)
-               kfree(zatm_dev->tx_map);
+               kfree(zatm_dev->mbx_start[i]);
+       kfree(zatm_dev->rx_map);
+       kfree(zatm_dev->tx_map);
        free_irq(zatm_dev->irq, dev);
        return error;
 }
index ce42889f98fbdac287a2af1d50a8c66346a5433a..adc4dcc306f4225f850c24cfe4916e60b2b6f372 100644 (file)
@@ -8,13 +8,12 @@
  * and is not licensed separately. See file COPYING for details.
  *
  * TODO (sorted by decreasing priority)
+ *  -- Kill first_open (Al Viro fixed the block layer now)
  *  -- Do resets with usb_device_reset (needs a thread context, use khubd)
  *  -- set readonly flag for CDs, set removable flag for CF readers
  *  -- do inquiry and verify we got a disk and not a tape (for LUN mismatch)
- *  -- support pphaneuf's SDDR-75 with two LUNs (also broken capacity...)
  *  -- special case some senses, e.g. 3a/0 -> no media present, reduce retries
  *  -- verify the 13 conditions and do bulk resets
- *  -- normal pool of commands instead of cmdv[]?
  *  -- kill last_pipe and simply do two-state clearing on both pipes
  *  -- verify protocol (bulk) from USB descriptors (maybe...)
  *  -- highmem and sg
 #define US_SC_SCSI     0x06            /* Transparent */
 
 /*
+ * This many LUNs per USB device.
+ * Every one of them takes a host, see UB_MAX_HOSTS.
  */
+#define UB_MAX_LUNS   4
+
+/*
+ */
+
 #define UB_MINORS_PER_MAJOR    8
 
 #define UB_MAX_CDB_SIZE      16                /* Corresponds to Bulk */
@@ -65,7 +71,7 @@ struct bulk_cb_wrap {
        u32     Tag;                    /* unique per command id */
        __le32  DataTransferLength;     /* size of data */
        u8      Flags;                  /* direction in bit 0 */
-       u8      Lun;                    /* LUN normally 0 */
+       u8      Lun;                    /* LUN */
        u8      Length;                 /* of of the CDB */
        u8      CDB[UB_MAX_CDB_SIZE];   /* max command */
 };
@@ -168,6 +174,7 @@ struct ub_scsi_cmd {
        unsigned int len;               /* Requested length */
        // struct scatterlist sgv[UB_MAX_REQ_SG];
 
+       struct ub_lun *lun;
        void (*done)(struct ub_dev *, struct ub_scsi_cmd *);
        void *back;
 };
@@ -252,25 +259,47 @@ struct ub_scsi_cmd_queue {
 };
 
 /*
- * The UB device instance.
+ * The block device instance (one per LUN).
+ */
+struct ub_lun {
+       struct ub_dev *udev;
+       struct list_head link;
+       struct gendisk *disk;
+       int id;                         /* Host index */
+       int num;                        /* LUN number */
+       char name[16];
+
+       int changed;                    /* Media was changed */
+       int removable;
+       int readonly;
+       int first_open;                 /* Kludge. See ub_bd_open. */
+
+       /* Use Ingo's mempool if or when we have more than one command. */
+       /*
+        * Currently we never need more than one command for the whole device.
+        * However, giving every LUN a command is a cheap and automatic way
+        * to enforce fairness between them.
+        */
+       int cmda[1];
+       struct ub_scsi_cmd cmdv[1];
+
+       struct ub_capacity capacity; 
+};
+
+/*
+ * The USB device instance.
  */
 struct ub_dev {
        spinlock_t lock;
-       int id;                         /* Number among ub's */
        atomic_t poison;                /* The USB device is disconnected */
        int openc;                      /* protected by ub_lock! */
                                        /* kref is too implicit for our taste */
        unsigned int tagcnt;
-       int changed;                    /* Media was changed */
-       int removable;
-       int readonly;
-       int first_open;                 /* Kludge. See ub_bd_open. */
-       char name[8];
+       char name[12];
        struct usb_device *dev;
        struct usb_interface *intf;
 
-       struct ub_capacity capacity; 
-       struct gendisk *disk;
+       struct list_head luns;
 
        unsigned int send_bulk_pipe;    /* cached pipe values */
        unsigned int recv_bulk_pipe;
@@ -279,10 +308,6 @@ struct ub_dev {
 
        struct tasklet_struct tasklet;
 
-       /* XXX Use Ingo's mempool (once we have more than one) */
-       int cmda[1];
-       struct ub_scsi_cmd cmdv[1];
-
        struct ub_scsi_cmd_queue cmd_queue;
        struct ub_scsi_cmd top_rqs_cmd; /* REQUEST SENSE */
        unsigned char top_sense[UB_SENSE_SIZE];
@@ -301,9 +326,9 @@ struct ub_dev {
 /*
  */
 static void ub_cleanup(struct ub_dev *sc);
-static int ub_bd_rq_fn_1(struct ub_dev *sc, struct request *rq);
-static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
-    struct request *rq);
+static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq);
+static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
+    struct ub_scsi_cmd *cmd, struct request *rq);
 static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
     struct request *rq);
 static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
@@ -320,8 +345,10 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
 static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
     int stalled_pipe);
 static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd);
-static int ub_sync_tur(struct ub_dev *sc);
-static int ub_sync_read_cap(struct ub_dev *sc, struct ub_capacity *ret);
+static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun);
+static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
+    struct ub_capacity *ret);
+static int ub_probe_lun(struct ub_dev *sc, int lnum);
 
 /*
  */
@@ -342,6 +369,7 @@ MODULE_DEVICE_TABLE(usb, ub_usb_ids);
  */
 #define UB_MAX_HOSTS  26
 static char ub_hostv[UB_MAX_HOSTS];
+
 static DEFINE_SPINLOCK(ub_lock);       /* Locks globals and ->openc */
 
 /*
@@ -406,6 +434,8 @@ static ssize_t ub_diag_show(struct device *dev, char *page)
 {
        struct usb_interface *intf;
        struct ub_dev *sc;
+       struct list_head *p;
+       struct ub_lun *lun;
        int cnt;
        unsigned long flags;
        int nc, nh;
@@ -421,9 +451,15 @@ static ssize_t ub_diag_show(struct device *dev, char *page)
        spin_lock_irqsave(&sc->lock, flags);
 
        cnt += sprintf(page + cnt,
-           "qlen %d qmax %d changed %d removable %d readonly %d\n",
-           sc->cmd_queue.qlen, sc->cmd_queue.qmax,
-           sc->changed, sc->removable, sc->readonly);
+           "qlen %d qmax %d\n",
+           sc->cmd_queue.qlen, sc->cmd_queue.qmax);
+
+       list_for_each (p, &sc->luns) {
+               lun = list_entry(p, struct ub_lun, link);
+               cnt += sprintf(page + cnt,
+                   "lun %u changed %d removable %d readonly %d\n",
+                   lun->num, lun->changed, lun->removable, lun->readonly);
+       }
 
        if ((nc = sc->tr.cur + 1) == SCMD_TRACE_SZ) nc = 0;
        for (j = 0; j < SCMD_TRACE_SZ; j++) {
@@ -523,53 +559,63 @@ static void ub_put(struct ub_dev *sc)
  */
 static void ub_cleanup(struct ub_dev *sc)
 {
+       struct list_head *p;
+       struct ub_lun *lun;
        request_queue_t *q;
 
-       /* I don't think queue can be NULL. But... Stolen from sx8.c */
-       if ((q = sc->disk->queue) != NULL)
-               blk_cleanup_queue(q);
+       while (!list_empty(&sc->luns)) {
+               p = sc->luns.next;
+               lun = list_entry(p, struct ub_lun, link);
+               list_del(p);
 
-       /*
-        * If we zero disk->private_data BEFORE put_disk, we have to check
-        * for NULL all over the place in open, release, check_media and
-        * revalidate, because the block level semaphore is well inside the
-        * put_disk. But we cannot zero after the call, because *disk is gone.
-        * The sd.c is blatantly racy in this area.
-        */
-       /* disk->private_data = NULL; */
-       put_disk(sc->disk);
-       sc->disk = NULL;
+               /* I don't think queue can be NULL. But... Stolen from sx8.c */
+               if ((q = lun->disk->queue) != NULL)
+                       blk_cleanup_queue(q);
+               /*
+                * If we zero disk->private_data BEFORE put_disk, we have
+                * to check for NULL all over the place in open, release,
+                * check_media and revalidate, because the block level
+                * semaphore is well inside the put_disk.
+                * But we cannot zero after the call, because *disk is gone.
+                * The sd.c is blatantly racy in this area.
+                */
+               /* disk->private_data = NULL; */
+               put_disk(lun->disk);
+               lun->disk = NULL;
+
+               ub_id_put(lun->id);
+               kfree(lun);
+       }
 
-       ub_id_put(sc->id);
        kfree(sc);
 }
 
 /*
  * The "command allocator".
  */
-static struct ub_scsi_cmd *ub_get_cmd(struct ub_dev *sc)
+static struct ub_scsi_cmd *ub_get_cmd(struct ub_lun *lun)
 {
        struct ub_scsi_cmd *ret;
 
-       if (sc->cmda[0])
+       if (lun->cmda[0])
                return NULL;
-       ret = &sc->cmdv[0];
-       sc->cmda[0] = 1;
+       ret = &lun->cmdv[0];
+       lun->cmda[0] = 1;
        return ret;
 }
 
-static void ub_put_cmd(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
+static void ub_put_cmd(struct ub_lun *lun, struct ub_scsi_cmd *cmd)
 {
-       if (cmd != &sc->cmdv[0]) {
+       if (cmd != &lun->cmdv[0]) {
                printk(KERN_WARNING "%s: releasing a foreign cmd %p\n",
-                   sc->name, cmd);
+                   lun->name, cmd);
                return;
        }
-       if (!sc->cmda[0]) {
-               printk(KERN_WARNING "%s: releasing a free cmd\n", sc->name);
+       if (!lun->cmda[0]) {
+               printk(KERN_WARNING "%s: releasing a free cmd\n", lun->name);
                return;
        }
-       sc->cmda[0] = 0;
+       lun->cmda[0] = 0;
 }
 
 /*
@@ -630,29 +676,30 @@ static struct ub_scsi_cmd *ub_cmdq_pop(struct ub_dev *sc)
 
 static void ub_bd_rq_fn(request_queue_t *q)
 {
-       struct ub_dev *sc = q->queuedata;
+       struct ub_lun *lun = q->queuedata;
        struct request *rq;
 
        while ((rq = elv_next_request(q)) != NULL) {
-               if (ub_bd_rq_fn_1(sc, rq) != 0) {
+               if (ub_bd_rq_fn_1(lun, rq) != 0) {
                        blk_stop_queue(q);
                        break;
                }
        }
 }
 
-static int ub_bd_rq_fn_1(struct ub_dev *sc, struct request *rq)
+static int ub_bd_rq_fn_1(struct ub_lun *lun, struct request *rq)
 {
+       struct ub_dev *sc = lun->udev;
        struct ub_scsi_cmd *cmd;
        int rc;
 
-       if (atomic_read(&sc->poison) || sc->changed) {
+       if (atomic_read(&sc->poison) || lun->changed) {
                blkdev_dequeue_request(rq);
                ub_end_rq(rq, 0);
                return 0;
        }
 
-       if ((cmd = ub_get_cmd(sc)) == NULL)
+       if ((cmd = ub_get_cmd(lun)) == NULL)
                return -1;
        memset(cmd, 0, sizeof(struct ub_scsi_cmd));
 
@@ -661,32 +708,30 @@ static int ub_bd_rq_fn_1(struct ub_dev *sc, struct request *rq)
        if (blk_pc_request(rq)) {
                rc = ub_cmd_build_packet(sc, cmd, rq);
        } else {
-               rc = ub_cmd_build_block(sc, cmd, rq);
+               rc = ub_cmd_build_block(sc, lun, cmd, rq);
        }
        if (rc != 0) {
-               ub_put_cmd(sc, cmd);
+               ub_put_cmd(lun, cmd);
                ub_end_rq(rq, 0);
-               blk_start_queue(sc->disk->queue);
                return 0;
        }
-
        cmd->state = UB_CMDST_INIT;
+       cmd->lun = lun;
        cmd->done = ub_rw_cmd_done;
        cmd->back = rq;
 
        cmd->tag = sc->tagcnt++;
        if ((rc = ub_submit_scsi(sc, cmd)) != 0) {
-               ub_put_cmd(sc, cmd);
+               ub_put_cmd(lun, cmd);
                ub_end_rq(rq, 0);
-               blk_start_queue(sc->disk->queue);
                return 0;
        }
 
        return 0;
 }
 
-static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
-    struct request *rq)
+static int ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
+    struct ub_scsi_cmd *cmd, struct request *rq)
 {
        int ub_dir;
 #if 0 /* We use rq->buffer for now */
@@ -707,7 +752,7 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
        sg = &cmd->sgv[0];
        n_elem = blk_rq_map_sg(q, rq, sg);
        if (n_elem <= 0) {
-               ub_put_cmd(sc, cmd);
+               ub_put_cmd(lun, cmd);
                ub_end_rq(rq, 0);
                blk_start_queue(q);
                return 0;               /* request with no s/g entries? */
@@ -716,7 +761,7 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
        if (n_elem != 1) {              /* Paranoia */
                printk(KERN_WARNING "%s: request with %d segments\n",
                    sc->name, n_elem);
-               ub_put_cmd(sc, cmd);
+               ub_put_cmd(lun, cmd);
                ub_end_rq(rq, 0);
                blk_start_queue(q);
                return 0;
@@ -748,8 +793,8 @@ static int ub_cmd_build_block(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
         * The call to blk_queue_hardsect_size() guarantees that request
         * is aligned, but it is given in terms of 512 byte units, always.
         */
-       block = rq->sector >> sc->capacity.bshift;
-       nblks = rq->nr_sectors >> sc->capacity.bshift;
+       block = rq->sector >> lun->capacity.bshift;
+       nblks = rq->nr_sectors >> lun->capacity.bshift;
 
        cmd->cdb[0] = (ub_dir == UB_DIR_READ)? READ_10: WRITE_10;
        /* 10-byte uses 4 bytes of LBA: 2147483648KB, 2097152MB, 2048GB */
@@ -803,7 +848,8 @@ static int ub_cmd_build_packet(struct ub_dev *sc, struct ub_scsi_cmd *cmd,
 static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 {
        struct request *rq = cmd->back;
-       struct gendisk *disk = sc->disk;
+       struct ub_lun *lun = cmd->lun;
+       struct gendisk *disk = lun->disk;
        request_queue_t *q = disk->queue;
        int uptodate;
 
@@ -818,7 +864,7 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
        else
                uptodate = 0;
 
-       ub_put_cmd(sc, cmd);
+       ub_put_cmd(lun, cmd);
        ub_end_rq(rq, uptodate);
        blk_start_queue(q);
 }
@@ -887,7 +933,7 @@ static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
        bcb->Tag = cmd->tag;            /* Endianness is not important */
        bcb->DataTransferLength = cpu_to_le32(cmd->len);
        bcb->Flags = (cmd->dir == UB_DIR_READ) ? 0x80 : 0;
-       bcb->Lun = 0;                   /* No multi-LUN yet */
+       bcb->Lun = (cmd->lun != NULL) ? cmd->lun->num : 0;
        bcb->Length = cmd->cdb_len;
 
        /* copy the command payload */
@@ -1002,9 +1048,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
                         * The control pipe clears itself - nothing to do.
                         * XXX Might try to reset the device here and retry.
                         */
-                       printk(KERN_NOTICE "%s: "
-                           "stall on control pipe for device %u\n",
-                           sc->name, sc->dev->devnum);
+                       printk(KERN_NOTICE "%s: stall on control pipe\n",
+                           sc->name);
                        goto Bad_End;
                }
 
@@ -1025,9 +1070,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
                         * The control pipe clears itself - nothing to do.
                         * XXX Might try to reset the device here and retry.
                         */
-                       printk(KERN_NOTICE "%s: "
-                           "stall on control pipe for device %u\n",
-                           sc->name, sc->dev->devnum);
+                       printk(KERN_NOTICE "%s: stall on control pipe\n",
+                           sc->name);
                        goto Bad_End;
                }
 
@@ -1046,9 +1090,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
                        rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
                        if (rc != 0) {
                                printk(KERN_NOTICE "%s: "
-                                   "unable to submit clear for device %u"
-                                   " (code %d)\n",
-                                   sc->name, sc->dev->devnum, rc);
+                                   "unable to submit clear (%d)\n",
+                                   sc->name, rc);
                                /*
                                 * This is typically ENOMEM or some other such shit.
                                 * Retrying is pointless. Just do Bad End on it...
@@ -1107,9 +1150,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
                        rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
                        if (rc != 0) {
                                printk(KERN_NOTICE "%s: "
-                                   "unable to submit clear for device %u"
-                                   " (code %d)\n",
-                                   sc->name, sc->dev->devnum, rc);
+                                   "unable to submit clear (%d)\n",
+                                   sc->name, rc);
                                /*
                                 * This is typically ENOMEM or some other such shit.
                                 * Retrying is pointless. Just do Bad End on it...
@@ -1140,9 +1182,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
                        rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe);
                        if (rc != 0) {
                                printk(KERN_NOTICE "%s: "
-                                   "unable to submit clear for device %u"
-                                   " (code %d)\n",
-                                   sc->name, sc->dev->devnum, rc);
+                                   "unable to submit clear (%d)\n",
+                                   sc->name, rc);
                                /*
                                 * This is typically ENOMEM or some other such shit.
                                 * Retrying is pointless. Just do Bad End on it...
@@ -1164,9 +1205,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
                         * encounter such a thing, try to read the CSW again.
                         */
                        if (++cmd->stat_count >= 4) {
-                               printk(KERN_NOTICE "%s: "
-                                   "unable to get CSW on device %u\n",
-                                   sc->name, sc->dev->devnum);
+                               printk(KERN_NOTICE "%s: unable to get CSW\n",
+                                   sc->name);
                                goto Bad_End;
                        }
                        __ub_state_stat(sc, cmd);
@@ -1207,10 +1247,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
                         */
                        if (++cmd->stat_count >= 4) {
                                printk(KERN_NOTICE "%s: "
-                                   "tag mismatch orig 0x%x reply 0x%x "
-                                   "on device %u\n",
-                                   sc->name, cmd->tag, bcs->Tag,
-                                   sc->dev->devnum);
+                                   "tag mismatch orig 0x%x reply 0x%x\n",
+                                   sc->name, cmd->tag, bcs->Tag);
                                goto Bad_End;
                        }
                        __ub_state_stat(sc, cmd);
@@ -1244,8 +1282,8 @@ static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 
        } else {
                printk(KERN_WARNING "%s: "
-                   "wrong command state %d on device %u\n",
-                   sc->name, cmd->state, sc->dev->devnum);
+                   "wrong command state %d\n",
+                   sc->name, cmd->state);
                goto Bad_End;
        }
        return;
@@ -1288,7 +1326,6 @@ static void __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 
        if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) {
                /* XXX Clear stalls */
-               printk("%s: CSW #%d submit failed (%d)\n", sc->name, cmd->tag, rc); /* P3 */
                ub_complete(&sc->work_done);
                ub_state_done(sc, cmd, rc);
                return;
@@ -1333,6 +1370,7 @@ static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
        scmd->state = UB_CMDST_INIT;
        scmd->data = sc->top_sense;
        scmd->len = UB_SENSE_SIZE;
+       scmd->lun = cmd->lun;
        scmd->done = ub_top_sense_done;
        scmd->back = cmd;
 
@@ -1411,14 +1449,14 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd)
        }
        if (cmd != scmd->back) {
                printk(KERN_WARNING "%s: "
-                   "sense done for wrong command 0x%x on device %u\n",
-                   sc->name, cmd->tag, sc->dev->devnum);
+                   "sense done for wrong command 0x%x\n",
+                   sc->name, cmd->tag);
                return;
        }
        if (cmd->state != UB_CMDST_SENSE) {
                printk(KERN_WARNING "%s: "
-                   "sense done with bad cmd state %d on device %u\n",
-                   sc->name, cmd->state, sc->dev->devnum);
+                   "sense done with bad cmd state %d\n",
+                   sc->name, cmd->state);
                return;
        }
 
@@ -1429,68 +1467,32 @@ static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd)
        ub_scsi_urb_compl(sc, cmd);
 }
 
-#if 0
-/* Determine what the maximum LUN supported is */
-int usb_stor_Bulk_max_lun(struct us_data *us)
-{
-       int result;
-
-       /* issue the command */
-       result = usb_stor_control_msg(us, us->recv_ctrl_pipe,
-                                US_BULK_GET_MAX_LUN, 
-                                USB_DIR_IN | USB_TYPE_CLASS | 
-                                USB_RECIP_INTERFACE,
-                                0, us->ifnum, us->iobuf, 1, HZ);
-
-       /* 
-        * Some devices (i.e. Iomega Zip100) need this -- apparently
-        * the bulk pipes get STALLed when the GetMaxLUN request is
-        * processed.   This is, in theory, harmless to all other devices
-        * (regardless of if they stall or not).
-        */
-       if (result < 0) {
-               usb_stor_clear_halt(us, us->recv_bulk_pipe);
-               usb_stor_clear_halt(us, us->send_bulk_pipe);
-       }
-
-       US_DEBUGP("GetMaxLUN command result is %d, data is %d\n", 
-                 result, us->iobuf[0]);
-
-       /* if we have a successful request, return the result */
-       if (result == 1)
-               return us->iobuf[0];
-
-       /* return the default -- no LUNs */
-       return 0;
-}
-#endif
-
 /*
  * This is called from a process context.
  */
-static void ub_revalidate(struct ub_dev *sc)
+static void ub_revalidate(struct ub_dev *sc, struct ub_lun *lun)
 {
 
-       sc->readonly = 0;       /* XXX Query this from the device */
+       lun->readonly = 0;      /* XXX Query this from the device */
 
-       sc->capacity.nsec = 0;
-       sc->capacity.bsize = 512;
-       sc->capacity.bshift = 0;
+       lun->capacity.nsec = 0;
+       lun->capacity.bsize = 512;
+       lun->capacity.bshift = 0;
 
-       if (ub_sync_tur(sc) != 0)
+       if (ub_sync_tur(sc, lun) != 0)
                return;                 /* Not ready */
-       sc->changed = 0;
+       lun->changed = 0;
 
-       if (ub_sync_read_cap(sc, &sc->capacity) != 0) {
+       if (ub_sync_read_cap(sc, lun, &lun->capacity) != 0) {
                /*
                 * The retry here means something is wrong, either with the
                 * device, with the transport, or with our code.
                 * We keep this because sd.c has retries for capacity.
                 */
-               if (ub_sync_read_cap(sc, &sc->capacity) != 0) {
-                       sc->capacity.nsec = 0;
-                       sc->capacity.bsize = 512;
-                       sc->capacity.bshift = 0;
+               if (ub_sync_read_cap(sc, lun, &lun->capacity) != 0) {
+                       lun->capacity.nsec = 0;
+                       lun->capacity.bsize = 512;
+                       lun->capacity.bshift = 0;
                }
        }
 }
@@ -1503,12 +1505,15 @@ static void ub_revalidate(struct ub_dev *sc)
 static int ub_bd_open(struct inode *inode, struct file *filp)
 {
        struct gendisk *disk = inode->i_bdev->bd_disk;
+       struct ub_lun *lun;
        struct ub_dev *sc;
        unsigned long flags;
        int rc;
 
-       if ((sc = disk->private_data) == NULL)
+       if ((lun = disk->private_data) == NULL)
                return -ENXIO;
+       sc = lun->udev;
+
        spin_lock_irqsave(&ub_lock, flags);
        if (atomic_read(&sc->poison)) {
                spin_unlock_irqrestore(&ub_lock, flags);
@@ -1529,15 +1534,15 @@ static int ub_bd_open(struct inode *inode, struct file *filp)
         * The bottom line is, Al Viro says that we should not allow
         * bdev->bd_invalidated to be set when doing add_disk no matter what.
         */
-       if (sc->first_open) {
-               if (sc->changed) {
-                       sc->first_open = 0;
+       if (lun->first_open) {
+               lun->first_open = 0;
+               if (lun->changed) {
                        rc = -ENOMEDIUM;
                        goto err_open;
                }
        }
 
-       if (sc->removable || sc->readonly)
+       if (lun->removable || lun->readonly)
                check_disk_change(inode->i_bdev);
 
        /*
@@ -1545,12 +1550,12 @@ static int ub_bd_open(struct inode *inode, struct file *filp)
         * under some pretty murky conditions (a failure of READ CAPACITY).
         * We may need it one day.
         */
-       if (sc->removable && sc->changed && !(filp->f_flags & O_NDELAY)) {
+       if (lun->removable && lun->changed && !(filp->f_flags & O_NDELAY)) {
                rc = -ENOMEDIUM;
                goto err_open;
        }
 
-       if (sc->readonly && (filp->f_mode & FMODE_WRITE)) {
+       if (lun->readonly && (filp->f_mode & FMODE_WRITE)) {
                rc = -EROFS;
                goto err_open;
        }
@@ -1567,7 +1572,8 @@ err_open:
 static int ub_bd_release(struct inode *inode, struct file *filp)
 {
        struct gendisk *disk = inode->i_bdev->bd_disk;
-       struct ub_dev *sc = disk->private_data;
+       struct ub_lun *lun = disk->private_data;
+       struct ub_dev *sc = lun->udev;
 
        ub_put(sc);
        return 0;
@@ -1597,20 +1603,14 @@ static int ub_bd_ioctl(struct inode *inode, struct file *filp,
  */
 static int ub_bd_revalidate(struct gendisk *disk)
 {
-       struct ub_dev *sc = disk->private_data;
-
-       ub_revalidate(sc);
-       /* This is pretty much a long term P3 */
-       if (!atomic_read(&sc->poison)) {                /* Cover sc->dev */
-               printk(KERN_INFO "%s: device %u capacity nsec %ld bsize %u\n",
-                   sc->name, sc->dev->devnum,
-                   sc->capacity.nsec, sc->capacity.bsize);
-       }
+       struct ub_lun *lun = disk->private_data;
+
+       ub_revalidate(lun->udev, lun);
 
        /* XXX Support sector size switching like in sr.c */
-       blk_queue_hardsect_size(disk->queue, sc->capacity.bsize);
-       set_capacity(disk, sc->capacity.nsec);
-       // set_disk_ro(sdkp->disk, sc->readonly);
+       blk_queue_hardsect_size(disk->queue, lun->capacity.bsize);
+       set_capacity(disk, lun->capacity.nsec);
+       // set_disk_ro(sdkp->disk, lun->readonly);
 
        return 0;
 }
@@ -1626,9 +1626,9 @@ static int ub_bd_revalidate(struct gendisk *disk)
  */
 static int ub_bd_media_changed(struct gendisk *disk)
 {
-       struct ub_dev *sc = disk->private_data;
+       struct ub_lun *lun = disk->private_data;
 
-       if (!sc->removable)
+       if (!lun->removable)
                return 0;
 
        /*
@@ -1640,12 +1640,12 @@ static int ub_bd_media_changed(struct gendisk *disk)
         * will fail, then block layer discards the data. Since we never
         * spin drives up, such devices simply cannot be used with ub anyway.
         */
-       if (ub_sync_tur(sc) != 0) {
-               sc->changed = 1;
+       if (ub_sync_tur(lun->udev, lun) != 0) {
+               lun->changed = 1;
                return 1;
        }
 
-       return sc->changed;
+       return lun->changed;
 }
 
 static struct block_device_operations ub_bd_fops = {
@@ -1669,7 +1669,7 @@ static void ub_probe_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
 /*
  * Test if the device has a check condition on it, synchronously.
  */
-static int ub_sync_tur(struct ub_dev *sc)
+static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun)
 {
        struct ub_scsi_cmd *cmd;
        enum { ALLOC_SIZE = sizeof(struct ub_scsi_cmd) };
@@ -1688,6 +1688,7 @@ static int ub_sync_tur(struct ub_dev *sc)
        cmd->cdb_len = 6;
        cmd->dir = UB_DIR_NONE;
        cmd->state = UB_CMDST_INIT;
+       cmd->lun = lun;                 /* This may be NULL, but that's ok */
        cmd->done = ub_probe_done;
        cmd->back = &compl;
 
@@ -1718,7 +1719,8 @@ err_alloc:
 /*
  * Read the SCSI capacity synchronously (for probing).
  */
-static int ub_sync_read_cap(struct ub_dev *sc, struct ub_capacity *ret)
+static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun,
+    struct ub_capacity *ret)
 {
        struct ub_scsi_cmd *cmd;
        char *p;
@@ -1743,6 +1745,7 @@ static int ub_sync_read_cap(struct ub_dev *sc, struct ub_capacity *ret)
        cmd->state = UB_CMDST_INIT;
        cmd->data = p;
        cmd->len = 8;
+       cmd->lun = lun;
        cmd->done = ub_probe_done;
        cmd->back = &compl;
 
@@ -1811,6 +1814,90 @@ static void ub_probe_timeout(unsigned long arg)
        complete(cop);
 }
 
+/*
+ * Get number of LUNs by the way of Bulk GetMaxLUN command.
+ */
+static int ub_sync_getmaxlun(struct ub_dev *sc)
+{
+       int ifnum = sc->intf->cur_altsetting->desc.bInterfaceNumber;
+       unsigned char *p;
+       enum { ALLOC_SIZE = 1 };
+       struct usb_ctrlrequest *cr;
+       struct completion compl;
+       struct timer_list timer;
+       int nluns;
+       int rc;
+
+       init_completion(&compl);
+
+       rc = -ENOMEM;
+       if ((p = kmalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL)
+               goto err_alloc;
+       *p = 55;
+
+       cr = &sc->work_cr;
+       cr->bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE;
+       cr->bRequest = US_BULK_GET_MAX_LUN;
+       cr->wValue = cpu_to_le16(0);
+       cr->wIndex = cpu_to_le16(ifnum);
+       cr->wLength = cpu_to_le16(1);
+
+       usb_fill_control_urb(&sc->work_urb, sc->dev, sc->recv_ctrl_pipe,
+           (unsigned char*) cr, p, 1, ub_probe_urb_complete, &compl);
+       sc->work_urb.transfer_flags = 0;
+       sc->work_urb.actual_length = 0;
+       sc->work_urb.error_count = 0;
+       sc->work_urb.status = 0;
+
+       if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) {
+               if (rc == -EPIPE) {
+                       printk("%s: Stall at GetMaxLUN, using 1 LUN\n",
+                            sc->name); /* P3 */
+               } else {
+                       printk(KERN_WARNING
+                            "%s: Unable to submit GetMaxLUN (%d)\n",
+                            sc->name, rc);
+               }
+               goto err_submit;
+       }
+
+       init_timer(&timer);
+       timer.function = ub_probe_timeout;
+       timer.data = (unsigned long) &compl;
+       timer.expires = jiffies + UB_CTRL_TIMEOUT;
+       add_timer(&timer);
+
+       wait_for_completion(&compl);
+
+       del_timer_sync(&timer);
+       usb_kill_urb(&sc->work_urb);
+
+       if (sc->work_urb.actual_length != 1) {
+               printk("%s: GetMaxLUN returned %d bytes\n", sc->name,
+                   sc->work_urb.actual_length); /* P3 */
+               nluns = 0;
+       } else {
+               if ((nluns = *p) == 55) {
+                       nluns = 0;
+               } else {
+                       /* GetMaxLUN returns the maximum LUN number */
+                       nluns += 1;
+                       if (nluns > UB_MAX_LUNS)
+                               nluns = UB_MAX_LUNS;
+               }
+               printk("%s: GetMaxLUN returned %d, using %d LUNs\n", sc->name,
+                   *p, nluns); /* P3 */
+       }
+
+       kfree(p);
+       return nluns;
+
+err_submit:
+       kfree(p);
+err_alloc:
+       return rc;
+}
+
 /*
  * Clear initial stalls.
  */
@@ -1897,8 +1984,8 @@ static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev,
        }
 
        if (ep_in == NULL || ep_out == NULL) {
-               printk(KERN_NOTICE "%s: device %u failed endpoint check\n",
-                   sc->name, sc->dev->devnum);
+               printk(KERN_NOTICE "%s: failed endpoint check\n",
+                   sc->name);
                return -EIO;
        }
 
@@ -1921,8 +2008,7 @@ static int ub_probe(struct usb_interface *intf,
     const struct usb_device_id *dev_id)
 {
        struct ub_dev *sc;
-       request_queue_t *q;
-       struct gendisk *disk;
+       int nluns;
        int rc;
        int i;
 
@@ -1931,6 +2017,7 @@ static int ub_probe(struct usb_interface *intf,
                goto err_core;
        memset(sc, 0, sizeof(struct ub_dev));
        spin_lock_init(&sc->lock);
+       INIT_LIST_HEAD(&sc->luns);
        usb_init_urb(&sc->work_urb);
        tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc);
        atomic_set(&sc->poison, 0);
@@ -1942,19 +2029,16 @@ static int ub_probe(struct usb_interface *intf,
        ub_init_completion(&sc->work_done);
        sc->work_done.done = 1;         /* A little yuk, but oh well... */
 
-       rc = -ENOSR;
-       if ((sc->id = ub_id_get()) == -1)
-               goto err_id;
-       snprintf(sc->name, 8, DRV_NAME "%c", sc->id + 'a');
-
        sc->dev = interface_to_usbdev(intf);
        sc->intf = intf;
        // sc->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
-
        usb_set_intfdata(intf, sc);
        usb_get_dev(sc->dev);
        // usb_get_intf(sc->intf);      /* Do we need this? */
 
+       snprintf(sc->name, 12, DRV_NAME "(%d.%d)",
+           sc->dev->bus->busnum, sc->dev->devnum);
+
        /* XXX Verify that we can handle the device (from descriptors) */
 
        ub_get_pipes(sc, sc->dev, intf);
@@ -1992,35 +2076,88 @@ static int ub_probe(struct usb_interface *intf,
         * In any case it's not our business how revaliadation is implemented.
         */
        for (i = 0; i < 3; i++) {       /* Retries for benh's key */
-               if ((rc = ub_sync_tur(sc)) <= 0) break;
+               if ((rc = ub_sync_tur(sc, NULL)) <= 0) break;
                if (rc != 0x6) break;
                msleep(10);
        }
 
-       sc->removable = 1;              /* XXX Query this from the device */
-       sc->changed = 1;                /* ub_revalidate clears only */
-       sc->first_open = 1;
+       nluns = 1;
+       for (i = 0; i < 3; i++) {
+               if ((rc = ub_sync_getmaxlun(sc)) < 0) {
+                       /* 
+                        * Some devices (i.e. Iomega Zip100) need this --
+                        * apparently the bulk pipes get STALLed when the
+                        * GetMaxLUN request is processed.
+                        * XXX I have a ZIP-100, verify it does this.
+                        */
+                       if (rc == -EPIPE) {
+                               ub_probe_clear_stall(sc, sc->recv_bulk_pipe);
+                               ub_probe_clear_stall(sc, sc->send_bulk_pipe);
+                       }
+                       break;
+               }
+               if (rc != 0) {
+                       nluns = rc;
+                       break;
+               }
+               mdelay(100);
+       }
 
-       ub_revalidate(sc);
-       /* This is pretty much a long term P3 */
-       printk(KERN_INFO "%s: device %u capacity nsec %ld bsize %u\n",
-           sc->name, sc->dev->devnum, sc->capacity.nsec, sc->capacity.bsize);
+       for (i = 0; i < nluns; i++) {
+               ub_probe_lun(sc, i);
+       }
+       return 0;
+
+       /* device_remove_file(&sc->intf->dev, &dev_attr_diag); */
+err_diag:
+       usb_set_intfdata(intf, NULL);
+       // usb_put_intf(sc->intf);
+       usb_put_dev(sc->dev);
+       kfree(sc);
+err_core:
+       return rc;
+}
+
+static int ub_probe_lun(struct ub_dev *sc, int lnum)
+{
+       struct ub_lun *lun;
+       request_queue_t *q;
+       struct gendisk *disk;
+       int rc;
+
+       rc = -ENOMEM;
+       if ((lun = kmalloc(sizeof(struct ub_lun), GFP_KERNEL)) == NULL)
+               goto err_alloc;
+       memset(lun, 0, sizeof(struct ub_lun));
+       lun->num = lnum;
+
+       rc = -ENOSR;
+       if ((lun->id = ub_id_get()) == -1)
+               goto err_id;
+
+       lun->udev = sc;
+       list_add(&lun->link, &sc->luns);
+
+       snprintf(lun->name, 16, DRV_NAME "%c(%d.%d.%d)",
+           lun->id + 'a', sc->dev->bus->busnum, sc->dev->devnum, lun->num);
+
+       lun->removable = 1;             /* XXX Query this from the device */
+       lun->changed = 1;               /* ub_revalidate clears only */
+       lun->first_open = 1;
+       ub_revalidate(sc, lun);
 
-       /*
-        * Just one disk per sc currently, but maybe more.
-        */
        rc = -ENOMEM;
        if ((disk = alloc_disk(UB_MINORS_PER_MAJOR)) == NULL)
                goto err_diskalloc;
 
-       sc->disk = disk;
-       sprintf(disk->disk_name, DRV_NAME "%c", sc->id + 'a');
-       sprintf(disk->devfs_name, DEVFS_NAME "/%c", sc->id + 'a');
+       lun->disk = disk;
+       sprintf(disk->disk_name, DRV_NAME "%c", lun->id + 'a');
+       sprintf(disk->devfs_name, DEVFS_NAME "/%c", lun->id + 'a');
        disk->major = UB_MAJOR;
-       disk->first_minor = sc->id * UB_MINORS_PER_MAJOR;
+       disk->first_minor = lun->id * UB_MINORS_PER_MAJOR;
        disk->fops = &ub_bd_fops;
-       disk->private_data = sc;
-       disk->driverfs_dev = &intf->dev;
+       disk->private_data = lun;
+       disk->driverfs_dev = &sc->intf->dev;    /* XXX Many to one ok? */
 
        rc = -ENOMEM;
        if ((q = blk_init_queue(ub_bd_rq_fn, &sc->lock)) == NULL)
@@ -2028,28 +2165,17 @@ static int ub_probe(struct usb_interface *intf,
 
        disk->queue = q;
 
-        // blk_queue_bounce_limit(q, hba[i]->pdev->dma_mask);
+       blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH);
        blk_queue_max_hw_segments(q, UB_MAX_REQ_SG);
        blk_queue_max_phys_segments(q, UB_MAX_REQ_SG);
-       // blk_queue_segment_boundary(q, CARM_SG_BOUNDARY);
+       blk_queue_segment_boundary(q, 0xffffffff);      /* Dubious. */
        blk_queue_max_sectors(q, UB_MAX_SECTORS);
-       blk_queue_hardsect_size(q, sc->capacity.bsize);
-
-       /*
-        * This is a serious infraction, caused by a deficiency in the
-        * USB sg interface (usb_sg_wait()). We plan to remove this once
-        * we get mileage on the driver and can justify a change to USB API.
-        * See blk_queue_bounce_limit() to understand this part.
-        *
-        * XXX And I still need to be aware of the DMA mask in the HC.
-        */
-       q->bounce_pfn = blk_max_low_pfn;
-       q->bounce_gfp = GFP_NOIO;
+       blk_queue_hardsect_size(q, lun->capacity.bsize);
 
-       q->queuedata = sc;
+       q->queuedata = lun;
 
-       set_capacity(disk, sc->capacity.nsec);
-       if (sc->removable)
+       set_capacity(disk, lun->capacity.nsec);
+       if (lun->removable)
                disk->flags |= GENHD_FL_REMOVABLE;
 
        add_disk(disk);
@@ -2059,22 +2185,20 @@ static int ub_probe(struct usb_interface *intf,
 err_blkqinit:
        put_disk(disk);
 err_diskalloc:
-       device_remove_file(&sc->intf->dev, &dev_attr_diag);
-err_diag:
-       usb_set_intfdata(intf, NULL);
-       // usb_put_intf(sc->intf);
-       usb_put_dev(sc->dev);
-       ub_id_put(sc->id);
+       list_del(&lun->link);
+       ub_id_put(lun->id);
 err_id:
-       kfree(sc);
-err_core:
+       kfree(lun);
+err_alloc:
        return rc;
 }
 
 static void ub_disconnect(struct usb_interface *intf)
 {
        struct ub_dev *sc = usb_get_intfdata(intf);
-       struct gendisk *disk = sc->disk;
+       struct list_head *p;
+       struct ub_lun *lun;
+       struct gendisk *disk;
        unsigned long flags;
 
        /*
@@ -2124,14 +2248,18 @@ static void ub_disconnect(struct usb_interface *intf)
        /*
         * Unregister the upper layer.
         */
-       if (disk->flags & GENHD_FL_UP)
-               del_gendisk(disk);
-       /*
-        * I wish I could do:
-        *    set_bit(QUEUE_FLAG_DEAD, &q->queue_flags);
-        * As it is, we rely on our internal poisoning and let
-        * the upper levels to spin furiously failing all the I/O.
-        */
+       list_for_each (p, &sc->luns) {
+               lun = list_entry(p, struct ub_lun, link);
+               disk = lun->disk;
+               if (disk->flags & GENHD_FL_UP)
+                       del_gendisk(disk);
+               /*
+                * I wish I could do:
+                *    set_bit(QUEUE_FLAG_DEAD, &q->queue_flags);
+                * As it is, we rely on our internal poisoning and let
+                * the upper levels to spin furiously failing all the I/O.
+                */
+       }
 
        /*
         * Taking a lock on a structure which is about to be freed
@@ -2182,8 +2310,8 @@ static int __init ub_init(void)
 {
        int rc;
 
-       /* P3 */ printk("ub: sizeof ub_scsi_cmd %zu ub_dev %zu\n",
-                       sizeof(struct ub_scsi_cmd), sizeof(struct ub_dev));
+       /* P3 */ printk("ub: sizeof ub_scsi_cmd %zu ub_dev %zu ub_lun %zu\n",
+                       sizeof(struct ub_scsi_cmd), sizeof(struct ub_dev), sizeof(struct ub_lun));
 
        if ((rc = register_blkdev(UB_MAJOR, DRV_NAME)) != 0)
                goto err_regblkdev;
index ad9c11391d81112409b2aaf27549cb5d766e2219..c1fe013c64f34c31c1d9b9cceded9d0d2b51ad08 100644 (file)
@@ -278,6 +278,8 @@ void agp3_generic_cleanup(void);
 #define AGP_GENERIC_SIZES_ENTRIES 11
 extern struct aper_size_info_16 agp3_generic_sizes[];
 
+#define virt_to_gart(x) (phys_to_gart(virt_to_phys(x)))
+#define gart_to_virt(x) (phys_to_virt(gart_to_phys(x)))
 
 extern int agp_off;
 extern int agp_try_unsupported_boot;
index 0212febda654b06da557ec331e3c4c4893c9bfab..9c9c9c2247cecfe8c48d0607e8a5d5a0b5f0921f 100644 (file)
@@ -150,7 +150,7 @@ static void *m1541_alloc_page(struct agp_bridge_data *bridge)
        pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
        pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
                        (((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
-                         virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN ));
+                         virt_to_gart(addr)) | ALI_CACHE_FLUSH_EN ));
        return addr;
 }
 
@@ -174,7 +174,7 @@ static void m1541_destroy_page(void * addr)
        pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp);
        pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL,
                        (((temp & ALI_CACHE_FLUSH_ADDR_MASK) |
-                         virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN));
+                         virt_to_gart(addr)) | ALI_CACHE_FLUSH_EN));
        agp_generic_destroy_page(addr);
 }
 
index e62a3c2c44a9b891c5dcdb2fa002cd0a56276c62..3a41672e4d6682112f19a19ee8ceae2752984be0 100644 (file)
@@ -43,7 +43,7 @@ static int amd_create_page_map(struct amd_page_map *page_map)
 
        SetPageReserved(virt_to_page(page_map->real));
        global_cache_flush();
-       page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
+       page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real),
                                            PAGE_SIZE);
        if (page_map->remapped == NULL) {
                ClearPageReserved(virt_to_page(page_map->real));
@@ -154,7 +154,7 @@ static int amd_create_gatt_table(struct agp_bridge_data *bridge)
 
        agp_bridge->gatt_table_real = (u32 *)page_dir.real;
        agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped;
-       agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
+       agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real);
 
        /* Get the address for the gart region.
         * This is a bus address even on the alpha, b/c its
@@ -167,7 +167,7 @@ static int amd_create_gatt_table(struct agp_bridge_data *bridge)
 
        /* Calculate the agp offset */
        for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
-               writel(virt_to_phys(amd_irongate_private.gatt_pages[i]->real) | 1,
+               writel(virt_to_gart(amd_irongate_private.gatt_pages[i]->real) | 1,
                        page_dir.remapped+GET_PAGE_DIR_OFF(addr));
                readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr));        /* PCI Posting. */
        }
index 399c042f68f04f0634ae7375f3917d1f1475edee..1407945a5892887565219b6594dde1444a6e30ea 100644 (file)
@@ -219,7 +219,7 @@ static struct aper_size_info_32 amd_8151_sizes[7] =
 
 static int amd_8151_configure(void)
 {
-       unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real);
+       unsigned long gatt_bus = virt_to_gart(agp_bridge->gatt_table_real);
 
        /* Configure AGP regs in each x86-64 host bridge. */
        for_each_nb() {
@@ -591,7 +591,7 @@ static void __devexit agp_amd64_remove(struct pci_dev *pdev)
 {
        struct agp_bridge_data *bridge = pci_get_drvdata(pdev);
 
-       release_mem_region(virt_to_phys(bridge->gatt_table_real),
+       release_mem_region(virt_to_gart(bridge->gatt_table_real),
                           amd64_aperture_sizes[bridge->aperture_size_idx].size);
        agp_remove_bridge(bridge);
        agp_put_bridge(bridge);
index a65f8827c2831d40f33e0baf5970211e5bba07d9..e572ced9100aeb8d78fc9bdf5379952ae3ff3905 100644 (file)
@@ -61,7 +61,7 @@ static int ati_create_page_map(ati_page_map *page_map)
 
        SetPageReserved(virt_to_page(page_map->real));
        err = map_page_into_agp(virt_to_page(page_map->real));
-       page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real),
+       page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real),
                                            PAGE_SIZE);
        if (page_map->remapped == NULL || err) {
                ClearPageReserved(virt_to_page(page_map->real));
@@ -343,7 +343,7 @@ static int ati_create_gatt_table(struct agp_bridge_data *bridge)
 
        agp_bridge->gatt_table_real = (u32 *)page_dir.real;
        agp_bridge->gatt_table = (u32 __iomem *) page_dir.remapped;
-       agp_bridge->gatt_bus_addr = virt_to_bus(page_dir.real);
+       agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real);
 
        /* Write out the size register */
        current_size = A_SIZE_LVL2(agp_bridge->current_size);
@@ -373,7 +373,7 @@ static int ati_create_gatt_table(struct agp_bridge_data *bridge)
 
        /* Calculate the agp offset */
        for(i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) {
-               writel(virt_to_bus(ati_generic_private.gatt_pages[i]->real) | 1,
+               writel(virt_to_gart(ati_generic_private.gatt_pages[i]->real) | 1,
                        page_dir.remapped+GET_PAGE_DIR_OFF(addr));
                readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr));        /* PCI Posting. */
        }
index 2f3dfb63bdc6518742ebdbd08e9f88ae800974d8..4d4e602fdc7e7cfa326000b84135583ed866296d 100644 (file)
@@ -148,7 +148,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
                        return -ENOMEM;
                }
 
-               bridge->scratch_page_real = virt_to_phys(addr);
+               bridge->scratch_page_real = virt_to_gart(addr);
                bridge->scratch_page =
                    bridge->driver->mask_memory(bridge, bridge->scratch_page_real, 0);
        }
@@ -189,7 +189,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge)
 err_out:
        if (bridge->driver->needs_scratch_page)
                bridge->driver->agp_destroy_page(
-                               phys_to_virt(bridge->scratch_page_real));
+                               gart_to_virt(bridge->scratch_page_real));
        if (got_gatt)
                bridge->driver->free_gatt_table(bridge);
        if (got_keylist) {
@@ -214,7 +214,7 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge)
        if (bridge->driver->agp_destroy_page &&
            bridge->driver->needs_scratch_page)
                bridge->driver->agp_destroy_page(
-                               phys_to_virt(bridge->scratch_page_real));
+                               gart_to_virt(bridge->scratch_page_real));
 }
 
 /* When we remove the global variable agp_bridge from all drivers
index 1383c3165ea1942143ad8f1fa18872cf78b982d0..ac19fdcd21c1c7583246256edba92157b42d278e 100644 (file)
@@ -219,7 +219,7 @@ static int efficeon_create_gatt_table(struct agp_bridge_data *bridge)
 
                efficeon_private.l1_table[index] = page;
 
-               value = __pa(page) | pati | present | index;
+               value = virt_to_gart(page) | pati | present | index;
 
                pci_write_config_dword(agp_bridge->dev,
                        EFFICEON_ATTPAGE, value);
index c321a924e38a8241e7d9c9cc2e0927a2bfc384ce..f0079e991bdc4ffaf95c787e50bd9618a848e225 100644 (file)
@@ -153,7 +153,7 @@ void agp_free_memory(struct agp_memory *curr)
        }
        if (curr->page_count != 0) {
                for (i = 0; i < curr->page_count; i++) {
-                       curr->bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[i]));
+                       curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i]));
                }
        }
        agp_free_key(curr->key);
@@ -209,7 +209,7 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge,
                        agp_free_memory(new);
                        return NULL;
                }
-               new->memory[i] = virt_to_phys(addr);
+               new->memory[i] = virt_to_gart(addr);
                new->page_count++;
        }
        new->bridge = bridge;
@@ -295,19 +295,6 @@ int agp_num_entries(void)
 EXPORT_SYMBOL_GPL(agp_num_entries);
 
 
-static int check_bridge_mode(struct pci_dev *dev)
-{
-       u32 agp3;
-       u8 cap_ptr;
-
-       cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP);
-       pci_read_config_dword(dev, cap_ptr+AGPSTAT, &agp3);
-       if (agp3 & AGPSTAT_MODE_3_0)
-               return 1;
-       return 0;
-}
-
-
 /**
  *     agp_copy_info  -  copy bridge state information
  *
@@ -328,7 +315,7 @@ int agp_copy_info(struct agp_bridge_data *bridge, struct agp_kern_info *info)
        info->version.minor = bridge->version->minor;
        info->chipset = SUPPORTED;
        info->device = bridge->dev;
-       if (check_bridge_mode(bridge->dev))
+       if (bridge->mode & AGPSTAT_MODE_3_0)
                info->mode = bridge->mode & ~AGP3_RESERVED_MASK;
        else
                info->mode = bridge->mode & ~AGP2_RESERVED_MASK;
@@ -661,7 +648,7 @@ u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 requested_mode
                bridge_agpstat &= ~AGPSTAT_FW;
 
        /* Check to see if we are operating in 3.0 mode */
-       if (check_bridge_mode(agp_bridge->dev))
+       if (agp_bridge->mode & AGPSTAT_MODE_3_0)
                agp_v3_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat);
        else
                agp_v2_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat);
@@ -732,7 +719,7 @@ void agp_generic_enable(struct agp_bridge_data *bridge, u32 requested_mode)
 
        /* Do AGP version specific frobbing. */
        if (bridge->major_version >= 3) {
-               if (check_bridge_mode(bridge->dev)) {
+               if (bridge->mode & AGPSTAT_MODE_3_0) {
                        /* If we have 3.5, we can do the isoch stuff. */
                        if (bridge->minor_version >= 5)
                                agp_3_5_enable(bridge);
@@ -806,8 +793,7 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
                                break;
                        }
 
-                       table = (char *) __get_free_pages(GFP_KERNEL,
-                                                         page_order);
+                       table = alloc_gatt_pages(page_order);
 
                        if (table == NULL) {
                                i++;
@@ -838,7 +824,7 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
                size = ((struct aper_size_info_fixed *) temp)->size;
                page_order = ((struct aper_size_info_fixed *) temp)->page_order;
                num_entries = ((struct aper_size_info_fixed *) temp)->num_entries;
-               table = (char *) __get_free_pages(GFP_KERNEL, page_order);
+               table = alloc_gatt_pages(page_order);
        }
 
        if (table == NULL)
@@ -853,7 +839,7 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
        agp_gatt_table = (void *)table;
 
        bridge->driver->cache_flush();
-       bridge->gatt_table = ioremap_nocache(virt_to_phys(table),
+       bridge->gatt_table = ioremap_nocache(virt_to_gart(table),
                                        (PAGE_SIZE * (1 << page_order)));
        bridge->driver->cache_flush();
 
@@ -861,11 +847,11 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge)
                for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
                        ClearPageReserved(page);
 
-               free_pages((unsigned long) table, page_order);
+               free_gatt_pages(table, page_order);
 
                return -ENOMEM;
        }
-       bridge->gatt_bus_addr = virt_to_phys(bridge->gatt_table_real);
+       bridge->gatt_bus_addr = virt_to_gart(bridge->gatt_table_real);
 
        /* AK: bogus, should encode addresses > 4GB */
        for (i = 0; i < num_entries; i++) {
@@ -919,7 +905,7 @@ int agp_generic_free_gatt_table(struct agp_bridge_data *bridge)
        for (page = virt_to_page(table); page <= virt_to_page(table_end); page++)
                ClearPageReserved(page);
 
-       free_pages((unsigned long) bridge->gatt_table_real, page_order);
+       free_gatt_pages(bridge->gatt_table_real, page_order);
 
        agp_gatt_table = NULL;
        bridge->gatt_table = NULL;
index 6052bfa04c728c5a7373597d81137635a3ed71ac..99762b6c19aea2fdc82119d44f28dde30479f969 100644 (file)
@@ -110,7 +110,7 @@ static int __init hp_zx1_ioc_shared(void)
        hp->gart_size = HP_ZX1_GART_SIZE;
        hp->gatt_entries = hp->gart_size / hp->io_page_size;
 
-       hp->io_pdir = phys_to_virt(readq(hp->ioc_regs+HP_ZX1_PDIR_BASE));
+       hp->io_pdir = gart_to_virt(readq(hp->ioc_regs+HP_ZX1_PDIR_BASE));
        hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)];
 
        if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) {
@@ -248,7 +248,7 @@ hp_zx1_configure (void)
        agp_bridge->mode = readl(hp->lba_regs+hp->lba_cap_offset+PCI_AGP_STATUS);
 
        if (hp->io_pdir_owner) {
-               writel(virt_to_phys(hp->io_pdir), hp->ioc_regs+HP_ZX1_PDIR_BASE);
+               writel(virt_to_gart(hp->io_pdir), hp->ioc_regs+HP_ZX1_PDIR_BASE);
                readl(hp->ioc_regs+HP_ZX1_PDIR_BASE);
                writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG);
                readl(hp->ioc_regs+HP_ZX1_TCNFG);
index adbea896c0d2e73f0ee6ab5d51c40fa17aedf47d..94943298c03eb42056d00ba73875147bd40b7e24 100644 (file)
@@ -372,7 +372,7 @@ static int i460_alloc_large_page (struct lp_desc *lp)
        }
        memset(lp->alloced_map, 0, map_size);
 
-       lp->paddr = virt_to_phys(lpage);
+       lp->paddr = virt_to_gart(lpage);
        lp->refcount = 0;
        atomic_add(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp);
        return 0;
@@ -383,7 +383,7 @@ static void i460_free_large_page (struct lp_desc *lp)
        kfree(lp->alloced_map);
        lp->alloced_map = NULL;
 
-       free_pages((unsigned long) phys_to_virt(lp->paddr), I460_IO_PAGE_SHIFT - PAGE_SHIFT);
+       free_pages((unsigned long) gart_to_virt(lp->paddr), I460_IO_PAGE_SHIFT - PAGE_SHIFT);
        atomic_sub(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp);
 }
 
index 8c7d727432bb5b02c25fa22467de24cbd52ef300..51266d6b4d78af9bf138f52dbbdf6f43413ac0c7 100644 (file)
@@ -286,7 +286,7 @@ static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type)
        if (new == NULL)
                return NULL;
 
-       new->memory[0] = virt_to_phys(addr);
+       new->memory[0] = virt_to_gart(addr);
        if (pg_count == 4) {
                /* kludge to get 4 physical pages for ARGB cursor */
                new->memory[1] = new->memory[0] + PAGE_SIZE;
@@ -329,10 +329,10 @@ static void intel_i810_free_by_type(struct agp_memory *curr)
        agp_free_key(curr->key);
        if(curr->type == AGP_PHYS_MEMORY) {
                if (curr->page_count == 4)
-                       i8xx_destroy_pages(phys_to_virt(curr->memory[0]));
+                       i8xx_destroy_pages(gart_to_virt(curr->memory[0]));
                else
                        agp_bridge->driver->agp_destroy_page(
-                                phys_to_virt(curr->memory[0]));
+                                gart_to_virt(curr->memory[0]));
                vfree(curr->memory);
        }
        kfree(curr);
@@ -418,7 +418,8 @@ static void intel_i830_init_gtt_entries(void)
                case I915_GMCH_GMS_STOLEN_48M:
                        /* Check it's really I915G */
                        if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
-                           agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB)
+                           agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
+                           agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB)
                                gtt_entries = MB(48) - KB(size);
                        else
                                gtt_entries = 0;
@@ -426,7 +427,8 @@ static void intel_i830_init_gtt_entries(void)
                case I915_GMCH_GMS_STOLEN_64M:
                        /* Check it's really I915G */
                        if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB ||
-                           agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB)
+                           agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB ||
+                           agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB)
                                gtt_entries = MB(64) - KB(size);
                        else
                                gtt_entries = 0;
@@ -1662,6 +1664,14 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev,
                }
                name = "915GM";
                break;
+       case PCI_DEVICE_ID_INTEL_82945G_HB:
+               if (find_i830(PCI_DEVICE_ID_INTEL_82945G_IG)) {
+                       bridge->driver = &intel_915_driver;
+               } else {
+                       bridge->driver = &intel_845_driver;
+               }
+               name = "945G";
+               break;
        case PCI_DEVICE_ID_INTEL_7505_0:
                bridge->driver = &intel_7505_driver;
                name = "E7505";
@@ -1801,6 +1811,7 @@ static struct pci_device_id agp_intel_pci_table[] = {
        ID(PCI_DEVICE_ID_INTEL_7205_0),
        ID(PCI_DEVICE_ID_INTEL_82915G_HB),
        ID(PCI_DEVICE_ID_INTEL_82915GM_HB),
+       ID(PCI_DEVICE_ID_INTEL_82945G_HB),
        { }
 };
 
index 4b3eda2679761ff5937ba044b2047422ad8c03ce..d3aa159c9decbfa0ba99e6b42db5aa7f22ac6859 100644 (file)
@@ -133,11 +133,14 @@ static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start,
        off_t j;
        void *temp;
        struct agp_bridge_data *bridge;
+       u64 *table;
 
        bridge = mem->bridge;
        if (!bridge)
                return -EINVAL;
 
+       table = (u64 *)bridge->gatt_table;
+
        temp = bridge->current_size;
 
        switch (bridge->driver->size_type) {
@@ -175,7 +178,7 @@ static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start,
        j = pg_start;
 
        while (j < (pg_start + mem->page_count)) {
-               if (*(bridge->gatt_table + j))
+               if (table[j])
                        return -EBUSY;
                j++;
        }
@@ -186,7 +189,7 @@ static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start,
        }
 
        for (i = 0, j = pg_start; i < mem->page_count; i++, j++) {
-               *(bridge->gatt_table + j) =
+               table[j] =
                    bridge->driver->mask_memory(bridge, mem->memory[i],
                                                mem->type);
        }
@@ -200,6 +203,7 @@ static int sgi_tioca_remove_memory(struct agp_memory *mem, off_t pg_start,
 {
        size_t i;
        struct agp_bridge_data *bridge;
+       u64 *table;
 
        bridge = mem->bridge;
        if (!bridge)
@@ -209,8 +213,10 @@ static int sgi_tioca_remove_memory(struct agp_memory *mem, off_t pg_start,
                return -EINVAL;
        }
 
+       table = (u64 *)bridge->gatt_table;
+
        for (i = pg_start; i < (mem->page_count + pg_start); i++) {
-               *(bridge->gatt_table + i) = 0;
+               table[i] = 0;
        }
 
        bridge->driver->tlb_flush(mem);
index 10c23302dd840d3bcc747c93871b2b1f9cc36209..a9fb12c20eb72e92aa343413094270022a159e47 100644 (file)
@@ -51,7 +51,7 @@ static int serverworks_create_page_map(struct serverworks_page_map *page_map)
        }
        SetPageReserved(virt_to_page(page_map->real));
        global_cache_flush();
-       page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), 
+       page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real),
                                            PAGE_SIZE);
        if (page_map->remapped == NULL) {
                ClearPageReserved(virt_to_page(page_map->real));
@@ -162,7 +162,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge)
        /* Create a fake scratch directory */
        for(i = 0; i < 1024; i++) {
                writel(agp_bridge->scratch_page, serverworks_private.scratch_dir.remapped+i);
-               writel(virt_to_phys(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i);
+               writel(virt_to_gart(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i);
        }
 
        retval = serverworks_create_gatt_pages(value->num_entries / 1024);
@@ -174,7 +174,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge)
 
        agp_bridge->gatt_table_real = (u32 *)page_dir.real;
        agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped;
-       agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real);
+       agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real);
 
        /* Get the address for the gart region.
         * This is a bus address even on the alpha, b/c its
@@ -187,7 +187,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge)
        /* Calculate the agp offset */  
 
        for(i = 0; i < value->num_entries / 1024; i++)
-               writel(virt_to_phys(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i);
+               writel(virt_to_gart(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i);
 
        return 0;
 }
index a673971f2a90309becddc27835d195bd36f30fad..c8255312b8c1f3728fb608928ebf554913cff4d2 100644 (file)
@@ -407,7 +407,7 @@ static int uninorth_create_gatt_table(struct agp_bridge_data *bridge)
 
        bridge->gatt_table_real = (u32 *) table;
        bridge->gatt_table = (u32 *)table;
-       bridge->gatt_bus_addr = virt_to_phys(table);
+       bridge->gatt_bus_addr = virt_to_gart(table);
 
        for (i = 0; i < num_entries; i++)
                bridge->gatt_table[i] = 0;
index 7a245068e3e55e2ba47801ca8ea9fa08f99cf66a..f022f0944434158f31eb3a9b3f0c9da35abadf1b 100644 (file)
@@ -1995,9 +1995,6 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status)
        unsigned char ch, gdl;
        int ignored = 0;
        int cnt = 0;
-       unsigned char *cp;
-       char *fp;
-       int count;
        int recv_room;
        int max = 256;
        unsigned long flags;
@@ -2011,10 +2008,6 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status)
                //return;
        }
 
-       cp = tty->flip.char_buf;
-       fp = tty->flip.flag_buf;
-       count = 0;
-
        // following add by Victor Yu. 09-02-2002
        if (info->IsMoxaMustChipFlag != MOXA_OTHER_UART) {
 
@@ -2041,12 +2034,10 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status)
                }
                while (gdl--) {
                        ch = inb(info->base + UART_RX);
-                       count++;
-                       *cp++ = ch;
-                       *fp++ = 0;
+                       tty_insert_flip_char(tty, ch, 0);
                        cnt++;
                        /*
-                          if((count>=HI_WATER) && (info->stop_rx==0)){
+                          if((cnt>=HI_WATER) && (info->stop_rx==0)){
                           mxser_stoprx(tty);
                           info->stop_rx=1;
                           break;
@@ -2061,7 +2052,7 @@ intr_old:
                if (max-- < 0)
                        break;
                /*
-                  if((count>=HI_WATER) && (info->stop_rx==0)){
+                  if((cnt>=HI_WATER) && (info->stop_rx==0)){
                   mxser_stoprx(tty);
                   info->stop_rx=1;
                   break;
@@ -2078,36 +2069,33 @@ intr_old:
                        if (++ignored > 100)
                                break;
                } else {
-                       count++;
+                       char flag = 0;
                        if (*status & UART_LSR_SPECIAL) {
                                if (*status & UART_LSR_BI) {
-                                       *fp++ = TTY_BREAK;
+                                       flag = TTY_BREAK;
 /* added by casper 1/11/2000 */
                                        info->icount.brk++;
-
 /* */
                                        if (info->flags & ASYNC_SAK)
                                                do_SAK(tty);
                                } else if (*status & UART_LSR_PE) {
-                                       *fp++ = TTY_PARITY;
+                                       flag = TTY_PARITY;
 /* added by casper 1/11/2000 */
                                        info->icount.parity++;
 /* */
                                } else if (*status & UART_LSR_FE) {
-                                       *fp++ = TTY_FRAME;
+                                       flag = TTY_FRAME;
 /* added by casper 1/11/2000 */
                                        info->icount.frame++;
 /* */
                                } else if (*status & UART_LSR_OE) {
-                                       *fp++ = TTY_OVERRUN;
+                                       flag = TTY_OVERRUN;
 /* added by casper 1/11/2000 */
                                        info->icount.overrun++;
 /* */
-                               } else
-                                       *fp++ = 0;
-                       } else
-                               *fp++ = 0;
-                       *cp++ = ch;
+                               }
+                       }
+                       tty_insert_flip_char(tty, ch, flag);
                        cnt++;
                        if (cnt >= recv_room) {
                                if (!info->ldisc_stop_rx) {
@@ -2132,13 +2120,13 @@ intr_old:
                // above add by Victor Yu. 09-02-2002
        } while (*status & UART_LSR_DR);
 
-      end_intr:                // add by Victor Yu. 09-02-2002
+end_intr:              // add by Victor Yu. 09-02-2002
 
        mxvar_log.rxcnt[info->port] += cnt;
        info->mon_data.rxcnt += cnt;
        info->mon_data.up_rxcnt += cnt;
        spin_unlock_irqrestore(&info->slock, flags);
-       
+
        tty_flip_buffer_push(tty);
 }
 
index af0446c6de823d665d4099fb4e7d37be7befe3c2..48fdf1e517cfb07c3771a79f692ca63dd1cdea55 100644 (file)
@@ -54,7 +54,7 @@ static int atkbd_softraw = 1;
 module_param_named(softraw, atkbd_softraw, bool, 0);
 MODULE_PARM_DESC(softraw, "Use software generated rawmode");
 
-static int atkbd_scroll = 1;
+static int atkbd_scroll = 0;
 module_param_named(scroll, atkbd_scroll, bool, 0);
 MODULE_PARM_DESC(scroll, "Enable scroll-wheel on MS Office and similar keyboards");
 
index 1c563f905a5964fb094d40ab6626e4b590a6bcb2..a7f15d9f13e5ccd04faa36b6dda826c20e750fbb 100644 (file)
@@ -374,29 +374,6 @@ static inline void do_kiss_params(struct baycom_state *bc,
 }
 
 /* --------------------------------------------------------------------- */
-/*
- * high performance HDLC encoder
- * yes, it's ugly, but generates pretty good code
- */
-
-#define ENCODEITERA(j)                         \
-({                                             \
-        if (!(notbitstream & (0x1f0 << j)))    \
-                goto stuff##j;                 \
-  encodeend##j:        ;                      \
-})
-
-#define ENCODEITERB(j)                                          \
-({                                                              \
-  stuff##j:                                                     \
-        bitstream &= ~(0x100 << j);                             \
-        bitbuf = (bitbuf & (((2 << j) << numbit) - 1)) |        \
-                ((bitbuf & ~(((2 << j) << numbit) - 1)) << 1);  \
-        numbit++;                                               \
-        notbitstream = ~bitstream;                              \
-        goto encodeend##j;                                      \
-})
-
 
 static void encode_hdlc(struct baycom_state *bc)
 {
@@ -405,6 +382,7 @@ static void encode_hdlc(struct baycom_state *bc)
        int pkt_len;
         unsigned bitstream, notbitstream, bitbuf, numbit, crc;
        unsigned char crcarr[2];
+       int j;
        
        if (bc->hdlctx.bufcnt > 0)
                return;
@@ -429,24 +407,14 @@ static void encode_hdlc(struct baycom_state *bc)
                pkt_len--;
                if (!pkt_len)
                        bp = crcarr;
-               ENCODEITERA(0);
-               ENCODEITERA(1);
-               ENCODEITERA(2);
-               ENCODEITERA(3);
-               ENCODEITERA(4);
-               ENCODEITERA(5);
-               ENCODEITERA(6);
-               ENCODEITERA(7);
-               goto enditer;
-               ENCODEITERB(0);
-               ENCODEITERB(1);
-               ENCODEITERB(2);
-               ENCODEITERB(3);
-               ENCODEITERB(4);
-               ENCODEITERB(5);
-               ENCODEITERB(6);
-               ENCODEITERB(7);
-       enditer:
+               for (j = 0; j < 8; j++)
+                       if (unlikely(!(notbitstream & (0x1f0 << j)))) {
+                               bitstream &= ~(0x100 << j);
+                               bitbuf = (bitbuf & (((2 << j) << numbit) - 1)) |
+                                       ((bitbuf & ~(((2 << j) << numbit) - 1)) << 1);
+                               numbit++;
+                               notbitstream = ~bitstream;
+                       }
                numbit += 8;
                while (numbit >= 8) {
                        *wp++ = bitbuf;
@@ -610,37 +578,6 @@ static void do_rxpacket(struct net_device *dev)
        bc->stats.rx_packets++;
 }
 
-#define DECODEITERA(j)                                                        \
-({                                                                            \
-        if (!(notbitstream & (0x0fc << j)))              /* flag or abort */  \
-                goto flgabrt##j;                                              \
-        if ((bitstream & (0x1f8 << j)) == (0xf8 << j))   /* stuffed bit */    \
-                goto stuff##j;                                                \
-  enditer##j:      ;                                                           \
-})
-
-#define DECODEITERB(j)                                                                 \
-({                                                                                     \
-  flgabrt##j:                                                                          \
-        if (!(notbitstream & (0x1fc << j))) {              /* abort received */        \
-                state = 0;                                                             \
-                goto enditer##j;                                                       \
-        }                                                                              \
-        if ((bitstream & (0x1fe << j)) != (0x0fc << j))   /* flag received */          \
-                goto enditer##j;                                                       \
-        if (state)                                                                     \
-                do_rxpacket(dev);                                                      \
-        bc->hdlcrx.bufcnt = 0;                                                         \
-        bc->hdlcrx.bufptr = bc->hdlcrx.buf;                                            \
-        state = 1;                                                                     \
-        numbits = 7-j;                                                                 \
-        goto enditer##j;                                                               \
-  stuff##j:                                                                            \
-        numbits--;                                                                     \
-        bitbuf = (bitbuf & ((~0xff) << j)) | ((bitbuf & ~((~0xff) << j)) << 1);        \
-        goto enditer##j;                                                               \
-})
-        
 static int receive(struct net_device *dev, int cnt)
 {
        struct baycom_state *bc = netdev_priv(dev);
@@ -649,6 +586,7 @@ static int receive(struct net_device *dev, int cnt)
        unsigned char tmp[128];
         unsigned char *cp;
        int cnt2, ret = 0;
+       int j;
         
         numbits = bc->hdlcrx.numbits;
        state = bc->hdlcrx.state;
@@ -669,24 +607,32 @@ static int receive(struct net_device *dev, int cnt)
                        bitbuf |= (*cp) << 8;
                        numbits += 8;
                        notbitstream = ~bitstream;
-                       DECODEITERA(0);
-                       DECODEITERA(1);
-                       DECODEITERA(2);
-                       DECODEITERA(3);
-                       DECODEITERA(4);
-                       DECODEITERA(5);
-                       DECODEITERA(6);
-                       DECODEITERA(7);
-                       goto enddec;
-                       DECODEITERB(0);
-                       DECODEITERB(1);
-                       DECODEITERB(2);
-                       DECODEITERB(3);
-                       DECODEITERB(4);
-                       DECODEITERB(5);
-                       DECODEITERB(6);
-                       DECODEITERB(7);
-               enddec:
+                       for (j = 0; j < 8; j++) {
+
+                               /* flag or abort */
+                               if (unlikely(!(notbitstream & (0x0fc << j)))) {
+
+                                       /* abort received */
+                                       if (!(notbitstream & (0x1fc << j)))
+                                               state = 0;
+
+                                       /* not flag received */
+                                       else if (!(bitstream & (0x1fe << j)) != (0x0fc << j)) {
+                                               if (state)
+                                                       do_rxpacket(dev);
+                                               bc->hdlcrx.bufcnt = 0;
+                                               bc->hdlcrx.bufptr = bc->hdlcrx.buf;
+                                               state = 1;
+                                               numbits = 7-j;
+                                               }
+                                       }
+
+                               /* stuffed bit */
+                               else if (unlikely((bitstream & (0x1f8 << j)) == (0xf8 << j))) {
+                                       numbits--;
+                                       bitbuf = (bitbuf & ((~0xff) << j)) | ((bitbuf & ~((~0xff) << j)) << 1);
+                                       }
+                               }
                        while (state && numbits >= 8) {
                                if (bc->hdlcrx.bufcnt >= TXBUFFER_SIZE) {
                                        state = 0;
index 41e517114807052707dad7bace8529f7080ba25a..c6e8b25f968529837ec3987baac52e7f55d73dea 100644 (file)
@@ -1274,6 +1274,9 @@ static int el3_close(struct net_device *dev)
                spin_lock_irqsave(&lp->window_lock, flags);
                update_stats(dev);
                spin_unlock_irqrestore(&lp->window_lock, flags);
+
+               /* force interrupts off */
+               outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
        }
 
        link->open--;
index c59507f8a76befe001f1313f55b6780423d1e778..b3768d84474700296bf04aab92513b15f216eddb 100644 (file)
@@ -1585,8 +1585,8 @@ rtl8169_hw_start(struct net_device *dev)
        RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
        RTL_W8(EarlyTxThres, EarlyTxThld);
 
-       /* For gigabit rtl8169, MTU + header + CRC + VLAN */
-       RTL_W16(RxMaxSize, tp->rx_buf_sz);
+       /* Low hurts. Let's disable the filtering. */
+       RTL_W16(RxMaxSize, 16383);
 
        /* Set Rx Config register */
        i = rtl8169_rx_config |
@@ -2127,6 +2127,11 @@ rtl8169_tx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
        }
 }
 
+static inline int rtl8169_fragmented_frame(u32 status)
+{
+       return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag);
+}
+
 static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc)
 {
        u32 opts1 = le32_to_cpu(desc->opts1);
@@ -2177,27 +2182,41 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
 
        while (rx_left > 0) {
                unsigned int entry = cur_rx % NUM_RX_DESC;
+               struct RxDesc *desc = tp->RxDescArray + entry;
                u32 status;
 
                rmb();
-               status = le32_to_cpu(tp->RxDescArray[entry].opts1);
+               status = le32_to_cpu(desc->opts1);
 
                if (status & DescOwn)
                        break;
                if (status & RxRES) {
-                       printk(KERN_INFO "%s: Rx ERROR!!!\n", dev->name);
+                       printk(KERN_INFO "%s: Rx ERROR. status = %08x\n",
+                              dev->name, status);
                        tp->stats.rx_errors++;
                        if (status & (RxRWT | RxRUNT))
                                tp->stats.rx_length_errors++;
                        if (status & RxCRC)
                                tp->stats.rx_crc_errors++;
+                       rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
                } else {
-                       struct RxDesc *desc = tp->RxDescArray + entry;
                        struct sk_buff *skb = tp->Rx_skbuff[entry];
                        int pkt_size = (status & 0x00001FFF) - 4;
                        void (*pci_action)(struct pci_dev *, dma_addr_t,
                                size_t, int) = pci_dma_sync_single_for_device;
 
+                       /*
+                        * The driver does not support incoming fragmented
+                        * frames. They are seen as a symptom of over-mtu
+                        * sized frames.
+                        */
+                       if (unlikely(rtl8169_fragmented_frame(status))) {
+                               tp->stats.rx_dropped++;
+                               tp->stats.rx_length_errors++;
+                               rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
+                               goto move_on;
+                       }
+
                        rtl8169_rx_csum(skb, desc);
                        
                        pci_dma_sync_single_for_cpu(tp->pci_dev,
@@ -2224,7 +2243,7 @@ rtl8169_rx_interrupt(struct net_device *dev, struct rtl8169_private *tp,
                        tp->stats.rx_bytes += pkt_size;
                        tp->stats.rx_packets++;
                }
-               
+move_on:               
                cur_rx++; 
                rx_left--;
        }
index e68cf5fb4920fe70bfbcfb5c43680af523f7e24a..20edeb3457921e5377c68a6e7d69681682fca135 100644 (file)
@@ -100,35 +100,8 @@ static int sh_debug;               /* Debug flag */
 
 #define SHAPER_BANNER  "CymruNet Traffic Shaper BETA 0.04 for Linux 2.1\n"
 
-/*
- *     Locking
- */
-static int shaper_lock(struct shaper *sh)
-{
-       /*
-        *      Lock in an interrupt must fail
-        */
-       while (test_and_set_bit(0, &sh->locked))
-       {
-               if (!in_interrupt())
-                       sleep_on(&sh->wait_queue);
-               else
-                       return 0;
-                       
-       }
-       return 1;
-}
-
 static void shaper_kick(struct shaper *sh);
 
-static void shaper_unlock(struct shaper *sh)
-{
-       clear_bit(0, &sh->locked);
-       wake_up(&sh->wait_queue);
-       shaper_kick(sh);
-}
-
 /*
  *     Compute clocks on a buffer
  */
@@ -157,17 +130,15 @@ static void shaper_setspeed(struct shaper *shaper, int bitspersec)
  *     Throw a frame at a shaper.
  */
   
-static int shaper_qframe(struct shaper *shaper, struct sk_buff *skb)
+
+static int shaper_start_xmit(struct sk_buff *skb, struct net_device *dev)
 {
+       struct shaper *shaper = dev->priv;
        struct sk_buff *ptr;
    
-       /*
-        *      Get ready to work on this shaper. Lock may fail if its
-        *      an interrupt and locked.
-        */
-        
-       if(!shaper_lock(shaper))
-               return -1;
+       if (down_trylock(&shaper->sem))
+               return -1;
+
        ptr=shaper->sendq.prev;
        
        /*
@@ -260,7 +231,8 @@ static int shaper_qframe(struct shaper *shaper, struct sk_buff *skb)
                 dev_kfree_skb(ptr);
                 shaper->stats.collisions++;
        }
-       shaper_unlock(shaper);
+       shaper_kick(shaper);
+       up(&shaper->sem);
        return 0;
 }
 
@@ -297,8 +269,13 @@ static void shaper_queue_xmit(struct shaper *shaper, struct sk_buff *skb)
  
 static void shaper_timer(unsigned long data)
 {
-       struct shaper *sh=(struct shaper *)data;
-       shaper_kick(sh);
+       struct shaper *shaper = (struct shaper *)data;
+
+       if (!down_trylock(&shaper->sem)) {
+               shaper_kick(shaper);
+               up(&shaper->sem);
+       } else
+               mod_timer(&shaper->timer, jiffies);
 }
 
 /*
@@ -310,19 +287,6 @@ static void shaper_kick(struct shaper *shaper)
 {
        struct sk_buff *skb;
        
-       /*
-        *      Shaper unlock will kick
-        */
-        
-       if (test_and_set_bit(0, &shaper->locked))
-       {
-               if(sh_debug)
-                       printk("Shaper locked.\n");
-               mod_timer(&shaper->timer, jiffies);
-               return;
-       }
-
-               
        /*
         *      Walk the list (may be empty)
         */
@@ -364,8 +328,6 @@ static void shaper_kick(struct shaper *shaper)
         
        if(skb!=NULL)
                mod_timer(&shaper->timer, SHAPERCB(skb)->shapeclock);
-
-       clear_bit(0, &shaper->locked);
 }
 
 
@@ -376,14 +338,12 @@ static void shaper_kick(struct shaper *shaper)
 static void shaper_flush(struct shaper *shaper)
 {
        struct sk_buff *skb;
-       if(!shaper_lock(shaper))
-       {
-               printk(KERN_ERR "shaper: shaper_flush() called by an irq!\n");
-               return;
-       }
+
+       down(&shaper->sem);
        while((skb=skb_dequeue(&shaper->sendq))!=NULL)
                dev_kfree_skb(skb);
-       shaper_unlock(shaper);
+       shaper_kick(shaper);
+       up(&shaper->sem);
 }
 
 /*
@@ -426,13 +386,6 @@ static int shaper_close(struct net_device *dev)
  *     ARP and other resolutions and not before.
  */
 
-
-static int shaper_start_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-       struct shaper *sh=dev->priv;
-       return shaper_qframe(sh, skb);
-}
-
 static struct net_device_stats *shaper_get_stats(struct net_device *dev)
 {
        struct shaper *sh=dev->priv;
@@ -623,7 +576,6 @@ static void shaper_init_priv(struct net_device *dev)
        init_timer(&sh->timer);
        sh->timer.function=shaper_timer;
        sh->timer.data=(unsigned long)sh;
-       init_waitqueue_head(&sh->wait_queue);
 }
 
 /*
index fc9b5cd957aa70cfc6c7ca63e1f7c09d960f86de..e944aac258e3090c63b2c483bab9e28dd5cc872f 100644 (file)
@@ -7,7 +7,12 @@
  * Copyright (C) 2005 Broadcom Corporation.
  *
  * Firmware is:
- *     Copyright (C) 2000-2003 Broadcom Corporation.
+ *     Derived from proprietary unpublished source code,
+ *     Copyright (C) 2000-2003 Broadcom Corporation.
+ *
+ *     Permission is hereby granted for the distribution of this firmware
+ *     data in hexadecimal or equivalent format, provided this copyright
+ *     notice is accompanying it.
  */
 
 #include <linux/config.h>
@@ -61,8 +66,8 @@
 
 #define DRV_MODULE_NAME                "tg3"
 #define PFX DRV_MODULE_NAME    ": "
-#define DRV_MODULE_VERSION     "3.29"
-#define DRV_MODULE_RELDATE     "May 23, 2005"
+#define DRV_MODULE_VERSION     "3.30"
+#define DRV_MODULE_RELDATE     "June 6, 2005"
 
 #define TG3_DEF_MAC_MODE       0
 #define TG3_DEF_RX_MODE                0
@@ -8555,6 +8560,16 @@ static void __devinit tg3_get_eeprom_hw_cfg(struct tg3 *tp)
 
                case NIC_SRAM_DATA_CFG_LED_MODE_MAC:
                        tp->led_ctrl = LED_CTRL_MODE_MAC;
+
+                       /* Default to PHY_1_MODE if 0 (MAC_MODE) is
+                        * read on some older 5700/5701 bootcode.
+                        */
+                       if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
+                           ASIC_REV_5700 ||
+                           GET_ASIC_REV(tp->pci_chip_rev_id) ==
+                           ASIC_REV_5701)
+                               tp->led_ctrl = LED_CTRL_MODE_PHY_1;
+
                        break;
 
                case SHASTA_EXT_LED_SHARED:
index 93481b41b613e33b75f1b494074372c80fe299cd..1d2ef1e2ffc6178398c2347b3b4295fee763dda1 100644 (file)
        080f  Sentry5 DDR/SDR RAM Controller
        0811  Sentry5 External Interface Core
        0816  BCM3302 Sentry5 MIPS32 CPU
+       1600  NetXtreme BCM5752 Gigabit Ethernet PCI Express
        1644  NetXtreme BCM5700 Gigabit Ethernet
                1014 0277  Broadcom Vigil B5700 1000Base-T
                1028 00d1  Broadcom BCM5700
index 637e9493034bce2bc6d35e9e43efa14decefe5ad..2194669300bfe5b6e198af9050931f47804afb55 100644 (file)
@@ -459,17 +459,6 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_APIC,
 #endif /* CONFIG_X86_IO_APIC */
 
 
-/*
- * Via 686A/B:  The PCI_INTERRUPT_LINE register for the on-chip
- * devices, USB0/1, AC97, MC97, and ACPI, has an unusual feature:
- * when written, it makes an internal connection to the PIC.
- * For these devices, this register is defined to be 4 bits wide.
- * Normally this is fine.  However for IO-APIC motherboards, or
- * non-x86 architectures (yes Via exists on PPC among other places),
- * we must mask the PCI_INTERRUPT_LINE value versus 0xf to get
- * interrupts delivered properly.
- */
-
 /*
  * FIXME: it is questionable that quirk_via_acpi
  * is needed.  It shows up as an ISA bridge, and does not
@@ -492,28 +481,30 @@ static void __devinit quirk_via_acpi(struct pci_dev *d)
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,    PCI_DEVICE_ID_VIA_82C586_3,     quirk_via_acpi );
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_VIA,    PCI_DEVICE_ID_VIA_82C686_4,     quirk_via_acpi );
 
-static void quirk_via_irqpic(struct pci_dev *dev)
+/*
+ * Via 686A/B:  The PCI_INTERRUPT_LINE register for the on-chip
+ * devices, USB0/1, AC97, MC97, and ACPI, has an unusual feature:
+ * when written, it makes an internal connection to the PIC.
+ * For these devices, this register is defined to be 4 bits wide.
+ * Normally this is fine.  However for IO-APIC motherboards, or
+ * non-x86 architectures (yes Via exists on PPC among other places),
+ * we must mask the PCI_INTERRUPT_LINE value versus 0xf to get
+ * interrupts delivered properly.
+ */
+static void quirk_via_irq(struct pci_dev *dev)
 {
        u8 irq, new_irq;
 
-#ifdef CONFIG_X86_IO_APIC
-       if (nr_ioapics && !skip_ioapic_setup)
-               return;
-#endif
-#ifdef CONFIG_ACPI
-       if (acpi_irq_model != ACPI_IRQ_MODEL_PIC)
-               return;
-#endif
        new_irq = dev->irq & 0xf;
        pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
        if (new_irq != irq) {
-               printk(KERN_INFO "PCI: Via PIC IRQ fixup for %s, from %d to %d\n",
+               printk(KERN_INFO "PCI: Via IRQ fixup for %s, from %d to %d\n",
                        pci_name(dev), irq, new_irq);
                udelay(15);     /* unknown if delay really needed */
                pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq);
        }
 }
-DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irqpic);
+DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_VIA, PCI_ANY_ID, quirk_via_irq);
 
 /*
  * PIIX3 USB: We have to disable USB interrupts that are
index 54c52349adc53297971c6e04067d931aabf3148d..3be546439252332131fac6aca81cbdea71d9934a 100644 (file)
@@ -665,15 +665,6 @@ static int piix_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
        return ata_pci_init_one(pdev, port_info, n_ports);
 }
 
-/**
- *     piix_init -
- *
- *     LOCKING:
- *
- *     RETURNS:
- *
- */
-
 static int __init piix_init(void)
 {
        int rc;
@@ -689,13 +680,6 @@ static int __init piix_init(void)
        return 0;
 }
 
-/**
- *     piix_exit -
- *
- *     LOCKING:
- *
- */
-
 static void __exit piix_exit(void)
 {
        pci_unregister_driver(&piix_pci_driver);
index 30a88f0e7bd61b4c6a1c2f5919da0c4df656e87e..21d194c6ace38b8595b4d6fb6fcfe8fe2cdf341b 100644 (file)
@@ -186,6 +186,28 @@ static void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
        ata_wait_idle(ap);
 }
 
+
+/**
+ *     ata_tf_load - send taskfile registers to host controller
+ *     @ap: Port to which output is sent
+ *     @tf: ATA taskfile register set
+ *
+ *     Outputs ATA taskfile to standard ATA host controller using MMIO
+ *     or PIO as indicated by the ATA_FLAG_MMIO flag.
+ *     Writes the control, feature, nsect, lbal, lbam, and lbah registers.
+ *     Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect,
+ *     hob_lbal, hob_lbam, and hob_lbah.
+ *
+ *     This function waits for idle (!BUSY and !DRQ) after writing
+ *     registers.  If the control register has a new value, this
+ *     function also waits for idle after writing control and before
+ *     writing the remaining registers.
+ *
+ *     May be used as the tf_load() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
 void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
 {
        if (ap->flags & ATA_FLAG_MMIO)
@@ -195,11 +217,11 @@ void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
 }
 
 /**
- *     ata_exec_command - issue ATA command to host controller
+ *     ata_exec_command_pio - issue ATA command to host controller
  *     @ap: port to which command is being issued
  *     @tf: ATA taskfile register set
  *
- *     Issues PIO/MMIO write to ATA command register, with proper
+ *     Issues PIO write to ATA command register, with proper
  *     synchronization with interrupt handler / other threads.
  *
  *     LOCKING:
@@ -235,6 +257,18 @@ static void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
        ata_pause(ap);
 }
 
+
+/**
+ *     ata_exec_command - issue ATA command to host controller
+ *     @ap: port to which command is being issued
+ *     @tf: ATA taskfile register set
+ *
+ *     Issues PIO/MMIO write to ATA command register, with proper
+ *     synchronization with interrupt handler / other threads.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
 void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf)
 {
        if (ap->flags & ATA_FLAG_MMIO)
@@ -305,7 +339,7 @@ void ata_tf_to_host_nolock(struct ata_port *ap, struct ata_taskfile *tf)
 }
 
 /**
- *     ata_tf_read - input device's ATA taskfile shadow registers
+ *     ata_tf_read_pio - input device's ATA taskfile shadow registers
  *     @ap: Port from which input is read
  *     @tf: ATA taskfile register set for storing input
  *
@@ -368,6 +402,23 @@ static void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf)
        }
 }
 
+
+/**
+ *     ata_tf_read - input device's ATA taskfile shadow registers
+ *     @ap: Port from which input is read
+ *     @tf: ATA taskfile register set for storing input
+ *
+ *     Reads ATA taskfile registers for currently-selected device
+ *     into @tf.
+ *
+ *     Reads nsect, lbal, lbam, lbah, and device.  If ATA_TFLAG_LBA48
+ *     is set, also reads the hob registers.
+ *
+ *     May be used as the tf_read() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
 void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
 {
        if (ap->flags & ATA_FLAG_MMIO)
@@ -381,7 +432,7 @@ void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
  *     @ap: port where the device is
  *
  *     Reads ATA taskfile status register for currently-selected device
- *     and return it's value. This also clears pending interrupts
+ *     and return its value. This also clears pending interrupts
  *      from this device
  *
  *     LOCKING:
@@ -397,7 +448,7 @@ static u8 ata_check_status_pio(struct ata_port *ap)
  *     @ap: port where the device is
  *
  *     Reads ATA taskfile status register for currently-selected device
- *     via MMIO and return it's value. This also clears pending interrupts
+ *     via MMIO and return its value. This also clears pending interrupts
  *      from this device
  *
  *     LOCKING:
@@ -408,6 +459,20 @@ static u8 ata_check_status_mmio(struct ata_port *ap)
                return readb((void __iomem *) ap->ioaddr.status_addr);
 }
 
+
+/**
+ *     ata_check_status - Read device status reg & clear interrupt
+ *     @ap: port where the device is
+ *
+ *     Reads ATA taskfile status register for currently-selected device
+ *     and return its value. This also clears pending interrupts
+ *      from this device
+ *
+ *     May be used as the check_status() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
 u8 ata_check_status(struct ata_port *ap)
 {
        if (ap->flags & ATA_FLAG_MMIO)
@@ -415,6 +480,20 @@ u8 ata_check_status(struct ata_port *ap)
        return ata_check_status_pio(ap);
 }
 
+
+/**
+ *     ata_altstatus - Read device alternate status reg
+ *     @ap: port where the device is
+ *
+ *     Reads ATA taskfile alternate status register for
+ *     currently-selected device and return its value.
+ *
+ *     Note: may NOT be used as the check_altstatus() entry in
+ *     ata_port_operations.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
 u8 ata_altstatus(struct ata_port *ap)
 {
        if (ap->ops->check_altstatus)
@@ -425,6 +504,20 @@ u8 ata_altstatus(struct ata_port *ap)
        return inb(ap->ioaddr.altstatus_addr);
 }
 
+
+/**
+ *     ata_chk_err - Read device error reg
+ *     @ap: port where the device is
+ *
+ *     Reads ATA taskfile error register for
+ *     currently-selected device and return its value.
+ *
+ *     Note: may NOT be used as the check_err() entry in
+ *     ata_port_operations.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ */
 u8 ata_chk_err(struct ata_port *ap)
 {
        if (ap->ops->check_err)
@@ -873,10 +966,24 @@ void ata_dev_id_string(u16 *id, unsigned char *s,
        }
 }
 
+
+/**
+ *     ata_noop_dev_select - Select device 0/1 on ATA bus
+ *     @ap: ATA channel to manipulate
+ *     @device: ATA device (numbered from zero) to select
+ *
+ *     This function performs no actual function.
+ *
+ *     May be used as the dev_select() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     caller.
+ */
 void ata_noop_dev_select (struct ata_port *ap, unsigned int device)
 {
 }
 
+
 /**
  *     ata_std_dev_select - Select device 0/1 on ATA bus
  *     @ap: ATA channel to manipulate
@@ -884,7 +991,9 @@ void ata_noop_dev_select (struct ata_port *ap, unsigned int device)
  *
  *     Use the method defined in the ATA specification to
  *     make either device 0, or device 1, active on the
- *     ATA channel.
+ *     ATA channel.  Works with both PIO and MMIO.
+ *
+ *     May be used as the dev_select() entry in ata_port_operations.
  *
  *     LOCKING:
  *     caller.
@@ -1190,7 +1299,12 @@ err_out:
  *     ata_bus_probe - Reset and probe ATA bus
  *     @ap: Bus to probe
  *
+ *     Master ATA bus probing function.  Initiates a hardware-dependent
+ *     bus reset, then attempts to identify any devices found on
+ *     the bus.
+ *
  *     LOCKING:
+ *     PCI/etc. bus probe sem.
  *
  *     RETURNS:
  *     Zero on success, non-zero on error.
@@ -1229,10 +1343,14 @@ err_out:
 }
 
 /**
- *     ata_port_probe -
- *     @ap:
+ *     ata_port_probe - Mark port as enabled
+ *     @ap: Port for which we indicate enablement
  *
- *     LOCKING:
+ *     Modify @ap data structure such that the system
+ *     thinks that the entire port is enabled.
+ *
+ *     LOCKING: host_set lock, or some other form of
+ *     serialization.
  */
 
 void ata_port_probe(struct ata_port *ap)
@@ -1241,10 +1359,15 @@ void ata_port_probe(struct ata_port *ap)
 }
 
 /**
- *     __sata_phy_reset -
- *     @ap:
+ *     __sata_phy_reset - Wake/reset a low-level SATA PHY
+ *     @ap: SATA port associated with target SATA PHY.
+ *
+ *     This function issues commands to standard SATA Sxxx
+ *     PHY registers, to wake up the phy (and device), and
+ *     clear any reset condition.
  *
  *     LOCKING:
+ *     PCI/etc. bus probe sem.
  *
  */
 void __sata_phy_reset(struct ata_port *ap)
@@ -1289,10 +1412,14 @@ void __sata_phy_reset(struct ata_port *ap)
 }
 
 /**
- *     __sata_phy_reset -
- *     @ap:
+ *     sata_phy_reset - Reset SATA bus.
+ *     @ap: SATA port associated with target SATA PHY.
+ *
+ *     This function resets the SATA bus, and then probes
+ *     the bus for devices.
  *
  *     LOCKING:
+ *     PCI/etc. bus probe sem.
  *
  */
 void sata_phy_reset(struct ata_port *ap)
@@ -1304,10 +1431,16 @@ void sata_phy_reset(struct ata_port *ap)
 }
 
 /**
- *     ata_port_disable -
- *     @ap:
+ *     ata_port_disable - Disable port.
+ *     @ap: Port to be disabled.
  *
- *     LOCKING:
+ *     Modify @ap data structure such that the system
+ *     thinks that the entire port is disabled, and should
+ *     never attempt to probe or communicate with devices
+ *     on this port.
+ *
+ *     LOCKING: host_set lock, or some other form of
+ *     serialization.
  */
 
 void ata_port_disable(struct ata_port *ap)
@@ -1416,7 +1549,10 @@ static void ata_host_set_dma(struct ata_port *ap, u8 xfer_mode,
  *     ata_set_mode - Program timings and issue SET FEATURES - XFER
  *     @ap: port on which timings will be programmed
  *
+ *     Set ATA device disk transfer mode (PIO3, UDMA6, etc.).
+ *
  *     LOCKING:
+ *     PCI/etc. bus probe sem.
  *
  */
 static void ata_set_mode(struct ata_port *ap)
@@ -1467,7 +1603,10 @@ err_out:
  *     @tmout_pat: impatience timeout
  *     @tmout: overall timeout
  *
- *     LOCKING:
+ *     Sleep until ATA Status register bit BSY clears,
+ *     or a timeout occurs.
+ *
+ *     LOCKING: None.
  *
  */
 
@@ -1553,10 +1692,14 @@ static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask)
 }
 
 /**
- *     ata_bus_edd -
- *     @ap:
+ *     ata_bus_edd - Issue EXECUTE DEVICE DIAGNOSTIC command.
+ *     @ap: Port to reset and probe
+ *
+ *     Use the EXECUTE DEVICE DIAGNOSTIC command to reset and
+ *     probe the bus.  Not often used these days.
  *
  *     LOCKING:
+ *     PCI/etc. bus probe sem.
  *
  */
 
@@ -1633,8 +1776,8 @@ static unsigned int ata_bus_softreset(struct ata_port *ap,
  *     the device is ATA or ATAPI.
  *
  *     LOCKING:
- *     Inherited from caller.  Some functions called by this function
- *     obtain the host_set lock.
+ *     PCI/etc. bus probe sem.
+ *     Obtains host_set lock.
  *
  *     SIDE EFFECTS:
  *     Sets ATA_FLAG_PORT_DISABLED if bus reset fails.
@@ -1876,7 +2019,11 @@ static int fgb(u32 bitmap)
  *     @xfer_mode_out: (output) SET FEATURES - XFER MODE code
  *     @xfer_shift_out: (output) bit shift that selects this mode
  *
+ *     Based on host and device capabilities, determine the
+ *     maximum transfer mode that is amenable to all.
+ *
  *     LOCKING:
+ *     PCI/etc. bus probe sem.
  *
  *     RETURNS:
  *     Zero on success, negative on error.
@@ -1909,7 +2056,11 @@ static int ata_choose_xfer_mode(struct ata_port *ap,
  *     @ap: Port associated with device @dev
  *     @dev: Device to which command will be sent
  *
+ *     Issue SET FEATURES - XFER MODE command to device @dev
+ *     on port @ap.
+ *
  *     LOCKING:
+ *     PCI/etc. bus probe sem.
  */
 
 static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
@@ -1947,10 +2098,13 @@ static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
 }
 
 /**
- *     ata_sg_clean -
- *     @qc:
+ *     ata_sg_clean - Unmap DMA memory associated with command
+ *     @qc: Command containing DMA memory to be released
+ *
+ *     Unmap all mapped DMA memory associated with this command.
  *
  *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
  */
 
 static void ata_sg_clean(struct ata_queued_cmd *qc)
@@ -1981,7 +2135,11 @@ static void ata_sg_clean(struct ata_queued_cmd *qc)
  *     ata_fill_sg - Fill PCI IDE PRD table
  *     @qc: Metadata associated with taskfile to be transferred
  *
+ *     Fill PCI IDE PRD (scatter-gather) table with segments
+ *     associated with the current disk command.
+ *
  *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
  *
  */
 static void ata_fill_sg(struct ata_queued_cmd *qc)
@@ -2028,7 +2186,13 @@ static void ata_fill_sg(struct ata_queued_cmd *qc)
  *     ata_check_atapi_dma - Check whether ATAPI DMA can be supported
  *     @qc: Metadata associated with taskfile to check
  *
+ *     Allow low-level driver to filter ATA PACKET commands, returning
+ *     a status indicating whether or not it is OK to use DMA for the
+ *     supplied PACKET command.
+ *
  *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ *
  *     RETURNS: 0 when ATAPI DMA can be used
  *               nonzero otherwise
  */
@@ -2046,6 +2210,8 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc)
  *     ata_qc_prep - Prepare taskfile for submission
  *     @qc: Metadata associated with taskfile to be prepared
  *
+ *     Prepare ATA taskfile for submission.
+ *
  *     LOCKING:
  *     spin_lock_irqsave(host_set lock)
  */
@@ -2057,6 +2223,32 @@ void ata_qc_prep(struct ata_queued_cmd *qc)
        ata_fill_sg(qc);
 }
 
+/**
+ *     ata_sg_init_one - Associate command with memory buffer
+ *     @qc: Command to be associated
+ *     @buf: Memory buffer
+ *     @buflen: Length of memory buffer, in bytes.
+ *
+ *     Initialize the data-related elements of queued_cmd @qc
+ *     to point to a single memory buffer, @buf of byte length @buflen.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+
+
+/**
+ *     ata_sg_init_one - Prepare a one-entry scatter-gather list.
+ *     @qc:  Queued command
+ *     @buf:  transfer buffer
+ *     @buflen:  length of buf
+ *
+ *     Builds a single-entry scatter-gather list to initiate a
+ *     transfer utilizing the specified buffer.
+ *
+ *     LOCKING:
+ */
 void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
 {
        struct scatterlist *sg;
@@ -2074,6 +2266,32 @@ void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
        sg->length = buflen;
 }
 
+/**
+ *     ata_sg_init - Associate command with scatter-gather table.
+ *     @qc: Command to be associated
+ *     @sg: Scatter-gather table.
+ *     @n_elem: Number of elements in s/g table.
+ *
+ *     Initialize the data-related elements of queued_cmd @qc
+ *     to point to a scatter-gather table @sg, containing @n_elem
+ *     elements.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
+
+/**
+ *     ata_sg_init - Assign a scatter gather list to a queued command
+ *     @qc:  Queued command
+ *     @sg:  Scatter-gather list
+ *     @n_elem:  length of sg list
+ *
+ *     Attaches a scatter-gather list to a queued command.
+ *
+ *     LOCKING:
+ */
+
 void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
                 unsigned int n_elem)
 {
@@ -2083,14 +2301,16 @@ void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
 }
 
 /**
- *     ata_sg_setup_one -
- *     @qc:
+ *     ata_sg_setup_one - DMA-map the memory buffer associated with a command.
+ *     @qc: Command with memory buffer to be mapped.
+ *
+ *     DMA-map the memory buffer associated with queued_cmd @qc.
  *
  *     LOCKING:
  *     spin_lock_irqsave(host_set lock)
  *
  *     RETURNS:
- *
+ *     Zero on success, negative on error.
  */
 
 static int ata_sg_setup_one(struct ata_queued_cmd *qc)
@@ -2115,13 +2335,16 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc)
 }
 
 /**
- *     ata_sg_setup -
- *     @qc:
+ *     ata_sg_setup - DMA-map the scatter-gather table associated with a command.
+ *     @qc: Command with scatter-gather table to be mapped.
+ *
+ *     DMA-map the scatter-gather table associated with queued_cmd @qc.
  *
  *     LOCKING:
  *     spin_lock_irqsave(host_set lock)
  *
  *     RETURNS:
+ *     Zero on success, negative on error.
  *
  */
 
@@ -2151,6 +2374,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
  *     @ap:
  *
  *     LOCKING:
+ *     None.  (executing in kernel thread context)
  *
  *     RETURNS:
  *
@@ -2198,6 +2422,7 @@ static unsigned long ata_pio_poll(struct ata_port *ap)
  *     @ap:
  *
  *     LOCKING:
+ *     None.  (executing in kernel thread context)
  */
 
 static void ata_pio_complete (struct ata_port *ap)
@@ -2240,6 +2465,18 @@ static void ata_pio_complete (struct ata_port *ap)
        ata_qc_complete(qc, drv_stat);
 }
 
+
+/**
+ *     swap_buf_le16 -
+ *     @buf:  Buffer to swap
+ *     @buf_words:  Number of 16-bit words in buffer.
+ *
+ *     Swap halves of 16-bit words if needed to convert from
+ *     little-endian byte order to native cpu byte order, or
+ *     vice-versa.
+ *
+ *     LOCKING:
+ */
 void swap_buf_le16(u16 *buf, unsigned int buf_words)
 {
 #ifdef __BIG_ENDIAN
@@ -2415,6 +2652,7 @@ err_out:
  *     @ap:
  *
  *     LOCKING:
+ *     None.  (executing in kernel thread context)
  */
 
 static void ata_pio_block(struct ata_port *ap)
@@ -2583,6 +2821,7 @@ static void atapi_request_sense(struct ata_port *ap, struct ata_device *dev,
  *     transaction completed successfully.
  *
  *     LOCKING:
+ *     Inherited from SCSI layer (none, can sleep)
  */
 
 static void ata_qc_timeout(struct ata_queued_cmd *qc)
@@ -2692,6 +2931,7 @@ out:
  *     @dev: Device from whom we request an available command structure
  *
  *     LOCKING:
+ *     None.
  */
 
 static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
@@ -2717,6 +2957,7 @@ static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
  *     @dev: Device from whom we request an available command structure
  *
  *     LOCKING:
+ *     None.
  */
 
 struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
@@ -2781,6 +3022,7 @@ static void __ata_qc_complete(struct ata_queued_cmd *qc)
  *     in case something prevents using it.
  *
  *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
  *
  */
 void ata_qc_free(struct ata_queued_cmd *qc)
@@ -2794,9 +3036,13 @@ void ata_qc_free(struct ata_queued_cmd *qc)
 /**
  *     ata_qc_complete - Complete an active ATA command
  *     @qc: Command to complete
- *     @drv_stat: ATA status register contents
+ *     @drv_stat: ATA Status register contents
+ *
+ *     Indicate to the mid and upper layers that an ATA
+ *     command has completed, with either an ok or not-ok status.
  *
  *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
  *
  */
 
@@ -2892,6 +3138,7 @@ err_out:
        return -1;
 }
 
+
 /**
  *     ata_qc_issue_prot - issue taskfile to device in proto-dependent manner
  *     @qc: command to issue to device
@@ -2901,6 +3148,8 @@ err_out:
  *     classes called "protocols", and issuing each type of protocol
  *     is slightly different.
  *
+ *     May be used as the qc_issue() entry in ata_port_operations.
+ *
  *     LOCKING:
  *     spin_lock_irqsave(host_set lock)
  *
@@ -2958,7 +3207,7 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc)
 }
 
 /**
- *     ata_bmdma_setup - Set up PCI IDE BMDMA transaction
+ *     ata_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction
  *     @qc: Info associated with this ATA transaction.
  *
  *     LOCKING:
@@ -3065,6 +3314,18 @@ static void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
             ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
 }
 
+
+/**
+ *     ata_bmdma_start - Start a PCI IDE BMDMA transaction
+ *     @qc: Info associated with this ATA transaction.
+ *
+ *     Writes the ATA_DMA_START flag to the DMA command register.
+ *
+ *     May be used as the bmdma_start() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
 void ata_bmdma_start(struct ata_queued_cmd *qc)
 {
        if (qc->ap->flags & ATA_FLAG_MMIO)
@@ -3073,6 +3334,20 @@ void ata_bmdma_start(struct ata_queued_cmd *qc)
                ata_bmdma_start_pio(qc);
 }
 
+
+/**
+ *     ata_bmdma_setup - Set up PCI IDE BMDMA transaction
+ *     @qc: Info associated with this ATA transaction.
+ *
+ *     Writes address of PRD table to device's PRD Table Address
+ *     register, sets the DMA control register, and calls
+ *     ops->exec_command() to start the transfer.
+ *
+ *     May be used as the bmdma_setup() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
 void ata_bmdma_setup(struct ata_queued_cmd *qc)
 {
        if (qc->ap->flags & ATA_FLAG_MMIO)
@@ -3081,6 +3356,19 @@ void ata_bmdma_setup(struct ata_queued_cmd *qc)
                ata_bmdma_setup_pio(qc);
 }
 
+
+/**
+ *     ata_bmdma_irq_clear - Clear PCI IDE BMDMA interrupt.
+ *     @ap: Port associated with this ATA transaction.
+ *
+ *     Clear interrupt and error flags in DMA status register.
+ *
+ *     May be used as the irq_clear() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
 void ata_bmdma_irq_clear(struct ata_port *ap)
 {
     if (ap->flags & ATA_FLAG_MMIO) {
@@ -3093,6 +3381,19 @@ void ata_bmdma_irq_clear(struct ata_port *ap)
 
 }
 
+
+/**
+ *     ata_bmdma_status - Read PCI IDE BMDMA status
+ *     @ap: Port associated with this ATA transaction.
+ *
+ *     Read and return BMDMA status register.
+ *
+ *     May be used as the bmdma_status() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
 u8 ata_bmdma_status(struct ata_port *ap)
 {
        u8 host_stat;
@@ -3104,6 +3405,19 @@ u8 ata_bmdma_status(struct ata_port *ap)
        return host_stat;
 }
 
+
+/**
+ *     ata_bmdma_stop - Stop PCI IDE BMDMA transfer
+ *     @ap: Port associated with this ATA transaction.
+ *
+ *     Clears the ATA_DMA_START flag in the dma control register
+ *
+ *     May be used as the bmdma_stop() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host_set lock)
+ */
+
 void ata_bmdma_stop(struct ata_port *ap)
 {
        if (ap->flags & ATA_FLAG_MMIO) {
@@ -3203,13 +3517,18 @@ idle_irq:
 
 /**
  *     ata_interrupt - Default ATA host interrupt handler
- *     @irq: irq line
- *     @dev_instance: pointer to our host information structure
+ *     @irq: irq line (unused)
+ *     @dev_instance: pointer to our ata_host_set information structure
  *     @regs: unused
  *
+ *     Default interrupt handler for PCI IDE devices.  Calls
+ *     ata_host_intr() for each port that is not disabled.
+ *
  *     LOCKING:
+ *     Obtains host_set lock during operation.
  *
  *     RETURNS:
+ *     IRQ_NONE or IRQ_HANDLED.
  *
  */
 
@@ -3302,6 +3621,19 @@ err_out:
        ata_qc_complete(qc, ATA_ERR);
 }
 
+
+/**
+ *     ata_port_start - Set port up for dma.
+ *     @ap: Port to initialize
+ *
+ *     Called just after data structures for each port are
+ *     initialized.  Allocates space for PRD table.
+ *
+ *     May be used as the port_start() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ */
+
 int ata_port_start (struct ata_port *ap)
 {
        struct device *dev = ap->host_set->dev;
@@ -3315,6 +3647,18 @@ int ata_port_start (struct ata_port *ap)
        return 0;
 }
 
+
+/**
+ *     ata_port_stop - Undo ata_port_start()
+ *     @ap: Port to shut down
+ *
+ *     Frees the PRD table.
+ *
+ *     May be used as the port_stop() entry in ata_port_operations.
+ *
+ *     LOCKING:
+ */
+
 void ata_port_stop (struct ata_port *ap)
 {
        struct device *dev = ap->host_set->dev;
@@ -3357,7 +3701,11 @@ static void ata_host_remove(struct ata_port *ap, unsigned int do_unregister)
  *     @ent: Probe information provided by low-level driver
  *     @port_no: Port number associated with this ata_port
  *
+ *     Initialize a new ata_port structure, and its associated
+ *     scsi_host.
+ *
  *     LOCKING:
+ *     Inherited from caller.
  *
  */
 
@@ -3412,9 +3760,13 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
  *     @host_set: Collections of ports to which we add
  *     @port_no: Port number associated with this host
  *
+ *     Attach low-level ATA driver to system.
+ *
  *     LOCKING:
+ *     PCI/etc. bus probe sem.
  *
  *     RETURNS:
+ *     New ata_port on success, for NULL on error.
  *
  */
 
@@ -3447,12 +3799,22 @@ err_out:
 }
 
 /**
- *     ata_device_add -
- *     @ent:
+ *     ata_device_add - Register hardware device with ATA and SCSI layers
+ *     @ent: Probe information describing hardware device to be registered
+ *
+ *     This function processes the information provided in the probe
+ *     information struct @ent, allocates the necessary ATA and SCSI
+ *     host information structures, initializes them, and registers
+ *     everything with requisite kernel subsystems.
+ *
+ *     This function requests irqs, probes the ATA bus, and probes
+ *     the SCSI bus.
  *
  *     LOCKING:
+ *     PCI/etc. bus probe sem.
  *
  *     RETURNS:
+ *     Number of ports registered.  Zero on error (no ports registered).
  *
  */
 
@@ -3604,7 +3966,15 @@ int ata_scsi_release(struct Scsi_Host *host)
 /**
  *     ata_std_ports - initialize ioaddr with standard port offsets.
  *     @ioaddr: IO address structure to be initialized
+ *
+ *     Utility function which initializes data_addr, error_addr,
+ *     feature_addr, nsect_addr, lbal_addr, lbam_addr, lbah_addr,
+ *     device_addr, status_addr, and command_addr to standard offsets
+ *     relative to cmd_addr.
+ *
+ *     Does not set ctl_addr, altstatus_addr, bmdma_addr, or scr_addr.
  */
+
 void ata_std_ports(struct ata_ioports *ioaddr)
 {
        ioaddr->data_addr = ioaddr->cmd_addr + ATA_REG_DATA;
@@ -3646,6 +4016,20 @@ ata_probe_ent_alloc(struct device *dev, struct ata_port_info *port)
        return probe_ent;
 }
 
+
+
+/**
+ *     ata_pci_init_native_mode - Initialize native-mode driver
+ *     @pdev:  pci device to be initialized
+ *     @port:  array[2] of pointers to port info structures.
+ *
+ *     Utility function which allocates and initializes an
+ *     ata_probe_ent structure for a standard dual-port
+ *     PIO-based IDE controller.  The returned ata_probe_ent
+ *     structure can be passed to ata_device_add().  The returned
+ *     ata_probe_ent structure should then be freed with kfree().
+ */
+
 #ifdef CONFIG_PCI
 struct ata_probe_ent *
 ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port)
@@ -3727,10 +4111,19 @@ ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port,
  *     @port_info: Information from low-level host driver
  *     @n_ports: Number of ports attached to host controller
  *
+ *     This is a helper function which can be called from a driver's
+ *     xxx_init_one() probe function if the hardware uses traditional
+ *     IDE taskfile registers.
+ *
+ *     This function calls pci_enable_device(), reserves its register
+ *     regions, sets the dma mask, enables bus master mode, and calls
+ *     ata_device_add()
+ *
  *     LOCKING:
  *     Inherited from PCI layer (may sleep).
  *
  *     RETURNS:
+ *     Zero on success, negative on errno-based value on error.
  *
  */
 
@@ -3949,15 +4342,6 @@ int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits)
 #endif /* CONFIG_PCI */
 
 
-/**
- *     ata_init -
- *
- *     LOCKING:
- *
- *     RETURNS:
- *
- */
-
 static int __init ata_init(void)
 {
        ata_wq = create_workqueue("ata");
index 416ba67ba9ee37b1fa0b7cad9ca0bc431e973017..7a4adc4c8f09d6ef9cdb7460f4e6846d0def4647 100644 (file)
@@ -947,7 +947,7 @@ unsigned int ata_scsiop_inq_83(struct ata_scsi_args *args, u8 *rbuf,
 }
 
 /**
- *     ata_scsiop_noop -
+ *     ata_scsiop_noop - Command handler that simply returns success.
  *     @args: device IDENTIFY data / SCSI command of interest.
  *     @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
  *     @buflen: Response buffer length.
index 579448222d691d77bd656a35fa536d58be3ad417..3c97aa45772dc4aea2b7c4dbd759e76fa46c1745 100644 (file)
@@ -507,6 +507,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
        int ret, i;
        unsigned int id, lun;
        unsigned long serial;
+       unsigned long flags;
 
        if (!CMD_SP(cmd))
                return FAILED;
@@ -519,7 +520,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
 
        /* Check active list for command command. */
        spin_unlock_irq(ha->host->host_lock);
-       spin_lock(&ha->hardware_lock);
+       spin_lock_irqsave(&ha->hardware_lock, flags);
        for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) {
                sp = ha->outstanding_cmds[i];
 
@@ -534,7 +535,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
                    sp->state));
                DEBUG3(qla2x00_print_scsi_cmd(cmd);)
 
-               spin_unlock(&ha->hardware_lock);
+               spin_unlock_irqrestore(&ha->hardware_lock, flags);
                if (qla2x00_abort_command(ha, sp)) {
                        DEBUG2(printk("%s(%ld): abort_command "
                            "mbx failed.\n", __func__, ha->host_no));
@@ -543,20 +544,19 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
                            "mbx success.\n", __func__, ha->host_no));
                        ret = SUCCESS;
                }
-               spin_lock(&ha->hardware_lock);
+               spin_lock_irqsave(&ha->hardware_lock, flags);
 
                break;
        }
+       spin_unlock_irqrestore(&ha->hardware_lock, flags);
 
        /* Wait for the command to be returned. */
        if (ret == SUCCESS) {
-               spin_unlock(&ha->hardware_lock);
                if (qla2x00_eh_wait_on_command(ha, cmd) != QLA_SUCCESS) {
                        qla_printk(KERN_ERR, ha, 
                            "scsi(%ld:%d:%d): Abort handler timed out -- %lx "
                            "%x.\n", ha->host_no, id, lun, serial, ret);
                }
-               spin_lock(&ha->hardware_lock);
        }
        spin_lock_irq(ha->host->host_lock);
 
@@ -588,6 +588,7 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t)
        int     status;
        srb_t           *sp;
        struct scsi_cmnd *cmd;
+       unsigned long flags;
 
        status = 0;
 
@@ -596,11 +597,11 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t)
         * array
         */
        for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
-               spin_lock(&ha->hardware_lock);
+               spin_lock_irqsave(&ha->hardware_lock, flags);
                sp = ha->outstanding_cmds[cnt];
                if (sp) {
                        cmd = sp->cmd;
-                       spin_unlock(&ha->hardware_lock);
+                       spin_unlock_irqrestore(&ha->hardware_lock, flags);
                        if (cmd->device->id == t) {
                                if (!qla2x00_eh_wait_on_command(ha, cmd)) {
                                        status = 1;
@@ -608,7 +609,7 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t)
                                }
                        }
                } else {
-                       spin_unlock(&ha->hardware_lock);
+                       spin_unlock_irqrestore(&ha->hardware_lock, flags);
                }
        }
        return (status);
@@ -740,6 +741,7 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha)
        int     status;
        srb_t           *sp;
        struct scsi_cmnd *cmd;
+       unsigned long flags;
 
        status = 1;
 
@@ -748,17 +750,17 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha)
         * array
         */
        for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
-               spin_lock(&ha->hardware_lock);
+               spin_lock_irqsave(&ha->hardware_lock, flags);
                sp = ha->outstanding_cmds[cnt];
                if (sp) {
                        cmd = sp->cmd;
-                       spin_unlock(&ha->hardware_lock);
+                       spin_unlock_irqrestore(&ha->hardware_lock, flags);
                        status = qla2x00_eh_wait_on_command(ha, cmd);
                        if (status == 0)
                                break;
                }
                else {
-                       spin_unlock(&ha->hardware_lock);
+                       spin_unlock_irqrestore(&ha->hardware_lock, flags);
                }
        }
        return (status);
index cca772624ae701ea8278ce770c10c8617e710c5e..8d0d302844a1d5a5c3a9df8530e1be0974f5c4d6 100644 (file)
@@ -1197,6 +1197,7 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
        if (!starget)
                return ERR_PTR(-ENOMEM);
 
+       get_device(&starget->dev);
        down(&shost->scan_mutex);
        res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
        if (res != SCSI_SCAN_LUN_PRESENT)
index 5d2ceb623e6fcebe34319cac6c4bcd72d2c78739..1f985327b0d485ec8b4648073ef39a80d25d28f1 100644 (file)
@@ -234,7 +234,7 @@ static inline const char *siu_type_name(struct uart_port *port)
                return "DSIU";
        }
 
-       return "unknown";
+       return NULL;
 }
 
 static unsigned int siu_tx_empty(struct uart_port *port)
@@ -482,9 +482,6 @@ static irqreturn_t siu_interrupt(int irq, void *dev_id, struct pt_regs *regs)
        struct uart_port *port;
        uint8_t iir, lsr;
 
-       if (dev_id == NULL)
-               return IRQ_NONE;
-
        port = (struct uart_port *)dev_id;
 
        iir = siu_read(port, UART_IIR);
@@ -507,6 +504,9 @@ static int siu_startup(struct uart_port *port)
 {
        int retval;
 
+       if (port->membase == NULL)
+               return -ENODEV;
+
        siu_clear_fifo(port);
 
        (void)siu_read(port, UART_LSR);
@@ -545,9 +545,6 @@ static void siu_shutdown(struct uart_port *port)
        unsigned long flags;
        uint8_t lcr;
 
-       if (port->membase == NULL)
-               return;
-
        siu_write(port, UART_IER, 0);
 
        spin_lock_irqsave(&port->lock, flags);
@@ -802,53 +799,6 @@ static int siu_init_ports(void)
 
 #ifdef CONFIG_SERIAL_VR41XX_CONSOLE
 
-static void early_set_termios(struct uart_port *port, struct termios *new,
-                              struct termios *old)
-{
-       tcflag_t c_cflag;
-       uint8_t lcr;
-       unsigned int baud, quot;
-
-       c_cflag = new->c_cflag;
-       switch (c_cflag & CSIZE) {
-       case CS5:
-               lcr = UART_LCR_WLEN5;
-               break;
-       case CS6:
-               lcr = UART_LCR_WLEN6;
-               break;
-       case CS7:
-               lcr = UART_LCR_WLEN7;
-               break;
-       default:
-               lcr = UART_LCR_WLEN8;
-               break;
-       }
-
-       if (c_cflag & CSTOPB)
-               lcr |= UART_LCR_STOP;
-       if (c_cflag & PARENB)
-               lcr |= UART_LCR_PARITY;
-       if ((c_cflag & PARODD) != PARODD)
-               lcr |= UART_LCR_EPAR;
-       if (c_cflag & CMSPAR)
-               lcr |= UART_LCR_SPAR;
-
-       baud = uart_get_baud_rate(port, new, old, 0, port->uartclk/16);
-       quot = uart_get_divisor(port, baud);
-
-       siu_write(port, UART_LCR, lcr | UART_LCR_DLAB);
-
-       siu_write(port, UART_DLL, (uint8_t)quot);
-       siu_write(port, UART_DLM, (uint8_t)(quot >> 8));
-
-       siu_write(port, UART_LCR, lcr);
-}
-
-static struct uart_ops early_uart_ops = {
-       .set_termios    = early_set_termios,
-};
-
 #define BOTH_EMPTY     (UART_LSR_TEMT | UART_LSR_THRE)
 
 static void wait_for_xmitr(struct uart_port *port)
@@ -915,7 +865,7 @@ static int siu_console_setup(struct console *con, char *options)
        if (port->membase == NULL) {
                if (port->mapbase == 0)
                        return -ENODEV;
-               port->membase = (unsigned char __iomem *)KSEG1ADDR(port->mapbase);
+               port->membase = ioremap(port->mapbase, siu_port_size(port));
        }
 
        vr41xx_select_siu_interface(SIU_INTERFACE_RS232C);
@@ -949,7 +899,7 @@ static int __devinit siu_console_init(void)
 
        for (i = 0; i < num; i++) {
                port = &siu_uart_ports[i];
-               port->ops = &early_uart_ops;
+               port->ops = &siu_uart_ops;
        }
 
        register_console(&siu_console);
@@ -994,8 +944,10 @@ static int siu_probe(struct device *dev)
                port->dev = dev;
 
                retval = uart_add_one_port(&siu_uart_driver, port);
-               if (retval)
+               if (retval < 0) {
+                       port->dev = NULL;
                        break;
+               }
        }
 
        if (i == 0 && retval < 0) {
index 4ab50009291d91fb1a54be002e6c9064607da6b6..4d0c9e65cd039e87612dedec707b4d0f4baf0675 100644 (file)
@@ -290,32 +290,30 @@ static ssize_t show_modalias(struct device *dev, char *buf)
 {
        struct usb_interface *intf;
        struct usb_device *udev;
+       int len;
 
        intf = to_usb_interface(dev);
        udev = interface_to_usbdev(intf);
-       if (udev->descriptor.bDeviceClass == 0) {
-               struct usb_host_interface *alt = intf->cur_altsetting;
 
-               return sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic%02Xisc%02Xip%02X\n",
+       len = sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic",
                               le16_to_cpu(udev->descriptor.idVendor),
                               le16_to_cpu(udev->descriptor.idProduct),
                               le16_to_cpu(udev->descriptor.bcdDevice),
                               udev->descriptor.bDeviceClass,
                               udev->descriptor.bDeviceSubClass,
-                              udev->descriptor.bDeviceProtocol,
+                              udev->descriptor.bDeviceProtocol);
+       buf += len;
+
+       if (udev->descriptor.bDeviceClass == 0) {
+               struct usb_host_interface *alt = intf->cur_altsetting;
+
+               return len + sprintf(buf, "%02Xisc%02Xip%02X\n",
                               alt->desc.bInterfaceClass,
                               alt->desc.bInterfaceSubClass,
                               alt->desc.bInterfaceProtocol);
        } else {
-               return sprintf(buf, "usb:v%04Xp%04Xd%04Xdc%02Xdsc%02Xdp%02Xic*isc*ip*\n",
-                              le16_to_cpu(udev->descriptor.idVendor),
-                              le16_to_cpu(udev->descriptor.idProduct),
-                              le16_to_cpu(udev->descriptor.bcdDevice),
-                              udev->descriptor.bDeviceClass,
-                              udev->descriptor.bDeviceSubClass,
-                              udev->descriptor.bDeviceProtocol);
+               return len + sprintf(buf, "*isc*ip*\n");
        }
-
 }
 static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
 
index 869ff73690acebf04655691c4edc01a017a6abe4..2d8bd9dcc6edae2b8d1c4ea112f0c5e66cddc149 100644 (file)
@@ -1315,6 +1315,8 @@ void hid_init_reports(struct hid_device *hid)
 #define USB_DEVICE_ID_WACOM_INTUOS2    0x0040
 #define USB_DEVICE_ID_WACOM_VOLITO     0x0060
 #define USB_DEVICE_ID_WACOM_PTU                0x0003
+#define USB_DEVICE_ID_WACOM_INTUOS3    0x00B0
+#define USB_DEVICE_ID_WACOM_CINTIQ     0x003F
 
 #define USB_VENDOR_ID_KBGEAR           0x084e
 #define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001
@@ -1401,6 +1403,7 @@ void hid_init_reports(struct hid_device *hid)
 
 #define USB_VENDOR_ID_DELORME          0x1163
 #define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
+#define USB_DEVICE_ID_DELORME_EM_LT20  0x0200
 
 #define USB_VENDOR_ID_MCC              0x09db
 #define USB_DEVICE_ID_MCC_PMD1024LS    0x0076
@@ -1412,6 +1415,12 @@ void hid_init_reports(struct hid_device *hid)
 #define USB_VENDOR_ID_BTC              0x046e
 #define USB_DEVICE_ID_BTC_KEYBOARD     0x5303
 
+#define USB_VENDOR_ID_VERNIER          0x08f7
+#define USB_DEVICE_ID_VERNIER_LABPRO   0x0001
+#define USB_DEVICE_ID_VERNIER_GOTEMP   0x0002
+#define USB_DEVICE_ID_VERNIER_SKIP     0x0003
+#define USB_DEVICE_ID_VERNIER_CYCLOPS  0x0004
+
 
 /*
  * Alphabetically sorted blacklist by quirk type.
@@ -1437,6 +1446,7 @@ static struct hid_blacklist {
        { USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_HIDCOM, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
@@ -1456,6 +1466,10 @@ static struct hid_blacklist {
        { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 300, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 400, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PENPARTNER, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 1, HID_QUIRK_IGNORE },
@@ -1481,6 +1495,10 @@ static struct hid_blacklist {
        { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS2 + 7, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_VOLITO, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PTU, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 1, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_INTUOS3 + 2, HID_QUIRK_IGNORE },
+       { USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_CINTIQ, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
        { USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
 
diff --git a/drivers/usb/media/pwc/ChangeLog b/drivers/usb/media/pwc/ChangeLog
deleted file mode 100644 (file)
index b2eb71a..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-9.0.2
-
-* Adding #ifdef to compile PWC before and after 2.6.5
-
-9.0.1
-
-9.0
-
-
-8.12
-
-* Implement motorized pan/tilt feature for Logitech QuickCam Orbit/Spere.
-
-8.11.1
-
-* Fix for PCVC720/40, would not be able to set videomode
-* Fix for Samsung MPC models, appearantly they are based on a newer chipset
-
-8.11
-
-* 20 dev_hints (per request)
-* Hot unplugging should be better, no more dangling pointers or memory leaks
-* Added reserved Logitech webcam IDs
-* Device now remembers size & fps between close()/open()
-* Removed palette stuff altogether
-
-8.10.1
-
-* Added IDs for PCVC720K/40 and Creative Labs Webcam Pro
-
-8.10
-
-* Fixed ID for QuickCam Notebook pro
-* Added GREALSIZE ioctl() call
-* Fixed bug in case PWCX was not loaded and invalid size was set
-
-8.9
-
-* Merging with kernel 2.5.49
-* Adding IDs for QuickCam Zoom & QuickCam Notebook
-
-8.8
-
-* Fixing 'leds' parameter
-* Adding IDs for Logitech QuickCam Pro 4000
-* Making URB init/cleanup a little nicer
-
-8.7
-
-* Incorporating changes in ioctl() parameter passing
-* Also changes to URB mechanism
-
-8.6
-
-* Added ID's for Visionite VCS UM100 and UC300
-* Removed YUV420-interlaced palette altogether (was confusing)
-* Removed MIRROR stuff as it didn't work anyway
-* Fixed a problem with the 'leds' parameter (wouldn't blink)
-* Added ioctl()s for advanced features: 'extended' whitebalance ioctl()s,
-  CONTOUR, BACKLIGHT, FLICKER, DYNNOISE.
-* VIDIOCGCAP.name now contains real camera model name instead of
-  'Philips xxx webcam'
-* Added PROBE ioctl (see previous point & API doc)
-
-8.5
-
-* Adding IDs for Creative Labs Webcam 5
-* Adding IDs for SOTEC CMS-001 webcam
-* Solving possible hang in VIDIOCSYNC when unplugging the cam 
-* Forgot to return structure in VIDIOCPWCGAWB, oops
-* Time interval for the LEDs are now in milliseconds
-
-8.4
-
-* Fixing power_save option for Vesta range
-* Handling new error codes in ISOC callback
-* Adding dev_hint module parameter, to specify /dev/videoX device nodes
-
-8.3
-
-* Adding Samsung C10 and C30 cameras
-* Removing palette module parameter
-* Fixed typo in ID of QuickCam 3000 Pro
-* Adding LED settings (blinking while in use) for ToUCam cameras.
-* Turns LED off when camera is not in use.
-
-8.2
-
-* Making module more silent when trace = 0 
-* Adding QuickCam 3000 Pro IDs
-* Chrominance control for the Vesta cameras
-* Hopefully fixed problems on machines with BIGMEM and > 1GB of RAM
-* Included Oliver Neukem's lock_kernel() patch
-* Allocates less memory for image buffers
-* Adds ioctl()s for the whitebalancing
-
-8.1
-
-* Adding support for 750
-* Adding V4L GAUDIO/SAUDIO/UNIT ioctl() calls
-
-8.0
-* 'damage control' after inclusion in 2.4.5.
-* Changed wait-queue mechanism in read/mmap/poll according to the book.
-* Included YUV420P palette.
-* Changed interface to decompressor module.
-* Cleaned up pwc structure a bit.
-
-7.0
-
-* Fixed bug in vcvt_420i_yuyv; extra variables on stack were misaligned.
-* There is now a clear error message when an image size is selected that
-  is only supported using the decompressor, and the decompressor isn't
-  loaded.
-* When the decompressor wasn't loaded, selecting large image size
-  would create skewed or double images.
-
-6.3
-
-* Introduced spinlocks for the buffer pointer manipulation; a number of
-  reports seem to suggest the down()/up() semaphores were the cause of
-  lockups, since they are not suitable for interrupt/user locking.
-* Separated decompressor and core code into 2 modules.
-
-6.2
-
-* Non-integral image sizes are now padded with gray or black.
-* Added SHUTTERSPEED ioctl().
-* Fixed buglet in VIDIOCPWCSAGC; the function would always return an error,
-  even though the call succeeded.
-* Added hotplug support for 2.4.*.
-* Memory: the 645/646 uses less memory now.
-
-6.1
-
-* VIDIOCSPICT returns -EINVAL with invalid palettes.
-* Added saturation control.
-* Split decompressors from rest.
-* Fixed bug that would reset the framerate to the default framerate if 
-  the rate field was set to 0 (which is not what I intended, nl. do not 
-  change the framerate!).
-* VIDIOCPWCSCQUAL (setting compression quality) now takes effect immediately.
-* Workaround for a bug in the 730 sensor.
index 85476e76b244c4b166042dfa5e2bdbad368fdc82..4cbb408af72749b5f2f432c10bac69ebe4e2e1b7 100644 (file)
@@ -2765,7 +2765,7 @@ static int blan_mdlm_bind (struct usbnet *dev, struct usb_interface *intf)
                        }
                        /* expect bcdVersion 1.0, ignore */
                        if (memcmp(&desc->bGUID, blan_guid, 16)
-                                   && memcmp(&desc->bGUID, blan_guid, 16) ) {
+                                   && memcmp(&desc->bGUID, safe_guid, 16) ) {
                                /* hey, this one might _really_ be MDLM! */
                                dev_dbg (&intf->dev, "MDLM guid\n");
                                goto bad_desc;
index bc798edf0358828f83ab486bde704d52f9ee1fbf..9438909e87a52bbd7c4ef625ce2f678403648341 100644 (file)
@@ -455,6 +455,17 @@ config USB_SERIAL_XIRCOM
          To compile this driver as a module, choose M here: the
          module will be called keyspan_pda.
 
+config USB_SERIAL_OPTION
+       tristate "USB Option PCMCIA serial driver"
+       depends on USB_SERIAL && USB_OHCI_HCD && PCCARD
+       help
+         Say Y here if you want to use an Option card. This is a
+         GSM card, controlled by three serial ports which are connected
+         via an OHCI adapter located on a PC card.
+
+         To compile this driver as a module, choose M here: the
+         module will be called option.
+
 config USB_SERIAL_OMNINET
        tristate "USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)"
        depends on USB_SERIAL && EXPERIMENTAL
index d56ff6d86cce220860ae63ca7bfbab532956847b..6c7cdcc99a9e2da387a12a352947a22e7ef08d6b 100644 (file)
@@ -32,6 +32,7 @@ obj-$(CONFIG_USB_SERIAL_KLSI)                 += kl5kusb105.o
 obj-$(CONFIG_USB_SERIAL_KOBIL_SCT)             += kobil_sct.o
 obj-$(CONFIG_USB_SERIAL_MCT_U232)              += mct_u232.o
 obj-$(CONFIG_USB_SERIAL_OMNINET)               += omninet.o
+obj-$(CONFIG_USB_SERIAL_OPTION)                        += option.o
 obj-$(CONFIG_USB_SERIAL_PL2303)                        += pl2303.o
 obj-$(CONFIG_USB_SERIAL_SAFE)                  += safe_serial.o
 obj-$(CONFIG_USB_SERIAL_TI)                    += ti_usb_3410_5052.o
index 7e9bb63eb466d3e09e608b22b4073448845e6802..4ace9964fc6bd36a22c0a82da2fc432be4eef5f7 100644 (file)
@@ -7,6 +7,14 @@
  *     modify it under the terms of the GNU General Public License version
  *     2 as published by the Free Software Foundation.
  *
+ * Support to set flow control line levels using TIOCMGET and TIOCMSET
+ * thanks to Karl Hiramoto karl@hiramoto.org. RTSCTS hardware flow
+ * control thanks to Munir Nassar nassarmu@real-time.com
+ *
+ * Outstanding Issues:
+ *  Buffers are not flushed when the port is opened.
+ *  Multiple calls to write() may fail with "Resource temporarily unavailable"
+ *
  */
 
 #include <linux/config.h>
@@ -24,7 +32,7 @@
 /*
  * Version Information
  */
-#define DRIVER_VERSION "v0.03"
+#define DRIVER_VERSION "v0.04"
 #define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver"
 
 /*
@@ -35,6 +43,9 @@ static void cp2101_cleanup(struct usb_serial_port*);
 static void cp2101_close(struct usb_serial_port*, struct file*);
 static void cp2101_get_termios(struct usb_serial_port*);
 static void cp2101_set_termios(struct usb_serial_port*, struct termios*);
+static int cp2101_tiocmget (struct usb_serial_port *, struct file *);
+static int cp2101_tiocmset (struct usb_serial_port *, struct file *,
+               unsigned int, unsigned int);
 static void cp2101_break_ctl(struct usb_serial_port*, int);
 static int cp2101_startup (struct usb_serial *);
 static void cp2101_shutdown(struct usb_serial*);
@@ -43,9 +54,10 @@ static void cp2101_shutdown(struct usb_serial*);
 static int debug;
 
 static struct usb_device_id id_table [] = {
-       {USB_DEVICE(0x10c4, 0xea60) },  /*Silicon labs factory default*/
-       {USB_DEVICE(0x10ab, 0x10c5) },  /*Siemens MC60 Cable*/
-       { } /* Terminating Entry*/
+       { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
+       { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
+       { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
+       { } /* Terminating Entry */
 };
 
 MODULE_DEVICE_TABLE (usb, id_table);
@@ -70,32 +82,35 @@ static struct usb_serial_device_type cp2101_device = {
        .close                  = cp2101_close,
        .break_ctl              = cp2101_break_ctl,
        .set_termios            = cp2101_set_termios,
+       .tiocmget               = cp2101_tiocmget,
+       .tiocmset               = cp2101_tiocmset,
        .attach                 = cp2101_startup,
        .shutdown               = cp2101_shutdown,
 };
 
-/*Config request types*/
+/* Config request types */
 #define REQTYPE_HOST_TO_DEVICE 0x41
 #define REQTYPE_DEVICE_TO_HOST 0xc1
 
-/*Config SET requests. To GET, add 1 to the request number*/
-#define CP2101_UART            0x00    /*Enable / Disable*/
-#define CP2101_BAUDRATE                0x01    /*(BAUD_RATE_GEN_FREQ / baudrate)*/
-#define CP2101_BITS            0x03    /*0x(0)(data bits)(parity)(stop bits)*/
-#define CP2101_BREAK           0x05    /*On / Off*/
-#define CP2101_DTRRTS          0x07    /*101 / 202  ???*/
-#define CP2101_CONFIG_16       0x13    /*16 bytes of config data ???*/
-#define CP2101_CONFIG_6                0x19    /*6 bytes of config data ???*/
+/* Config SET requests. To GET, add 1 to the request number */
+#define CP2101_UART            0x00    /* Enable / Disable */
+#define CP2101_BAUDRATE                0x01    /* (BAUD_RATE_GEN_FREQ / baudrate) */
+#define CP2101_BITS            0x03    /* 0x(0)(databits)(parity)(stopbits) */
+#define CP2101_BREAK           0x05    /* On / Off */
+#define CP2101_CONTROL         0x07    /* Flow control line states */
+#define CP2101_MODEMCTL                0x13    /* Modem controls */
+#define CP2101_CONFIG_6                0x19    /* 6 bytes of config data ??? */
 
-/*CP2101_UART*/
+/* CP2101_UART */
 #define UART_ENABLE            0x0001
 #define UART_DISABLE           0x0000
 
-/*CP2101_BAUDRATE*/
+/* CP2101_BAUDRATE */
 #define BAUD_RATE_GEN_FREQ     0x384000
 
-/*CP2101_BITS*/
+/* CP2101_BITS */
 #define BITS_DATA_MASK         0X0f00
+#define BITS_DATA_5            0X0500
 #define BITS_DATA_6            0X0600
 #define BITS_DATA_7            0X0700
 #define BITS_DATA_8            0X0800
@@ -112,64 +127,137 @@ static struct usb_serial_device_type cp2101_device = {
 #define BITS_STOP_1            0x0000
 #define BITS_STOP_1_5          0x0001
 #define BITS_STOP_2            0x0002
+
+/* CP2101_BREAK */
 #define BREAK_ON               0x0000
 #define BREAK_OFF              0x0001
 
+/* CP2101_CONTROL */
+#define CONTROL_DTR            0x0001
+#define CONTROL_RTS            0x0002
+#define CONTROL_CTS            0x0010
+#define CONTROL_DSR            0x0020
+#define CONTROL_RING           0x0040
+#define CONTROL_DCD            0x0080
+#define CONTROL_WRITE_DTR      0x0100
+#define CONTROL_WRITE_RTS      0x0200
 
-static int cp2101_get_config(struct usb_serial_port* port, u8 request)
+/*
+ * cp2101_get_config
+ * Reads from the CP2101 configuration registers
+ * 'size' is specified in bytes.
+ * 'data' is a pointer to a pre-allocated array of integers large
+ * enough to hold 'size' bytes (with 4 bytes to each integer)
+ */
+static int cp2101_get_config(struct usb_serial_port* port, u8 request,
+               unsigned int *data, int size)
 {
        struct usb_serial *serial = port->serial;
-       unsigned char buf[4];
-       unsigned int value;
-       int result, i;
+       u32 *buf;
+       int result, i, length;
+
+       /* Number of integers required to contain the array */
+       length = (((size - 1) | 3) + 1)/4;
+
+       buf = kmalloc (length * sizeof(u32), GFP_KERNEL);
+       memset(buf, 0, length * sizeof(u32));
+
+       if (!buf) {
+               dev_err(&port->dev, "%s - out of memory.\n", __FUNCTION__);
+               return -ENOMEM;
+       }
 
-       /*For get requests, the request number must be incremented*/
+       /* For get requests, the request number must be incremented */
        request++;
 
-       /*Issue the request, attempting to read 4 bytes*/
+       /* Issue the request, attempting to read 'size' bytes */
        result = usb_control_msg (serial->dev,usb_rcvctrlpipe (serial->dev, 0),
                                request, REQTYPE_DEVICE_TO_HOST, 0x0000,
-                               0, buf, 4, 300);
+                               0, buf, size, 300);
 
-       if (result < 0) {
-               dev_err(&port->dev, "%s - Unable to send config request, "
-                               "request=0x%x result=%d\n",
-                               __FUNCTION__, request, result);
-               return result;
-       }
+       /* Convert data into an array of integers */
+       for (i=0; i<length; i++)
+               data[i] = le32_to_cpu(buf[i]);
 
-       /*Assemble each byte read into an integer value*/
-       value = 0;
-       for (i=0; i<4 && i<result; i++)
-               value |= (buf[i] << (i * 8));
+       kfree(buf);
 
-       dbg( " %s - request=0x%x result=%d value=0x%x",
-                       __FUNCTION__, request, result, value);
+       if (result != size) {
+               dev_err(&port->dev, "%s - Unable to send config request, "
+                               "request=0x%x size=%d result=%d\n",
+                               __FUNCTION__, request, size, result);
+               return -EPROTO;
+       }
 
-       return value;
+       return 0;
 }
 
-static int cp2101_set_config(struct usb_serial_port* port, u8 request, u16 value)
+/*
+ * cp2101_set_config
+ * Writes to the CP2101 configuration registers
+ * Values less than 16 bits wide are sent directly
+ * 'size' is specified in bytes.
+ */
+static int cp2101_set_config(struct usb_serial_port* port, u8 request,
+               unsigned int *data, int size)
 {
        struct usb_serial *serial = port->serial;
-       int result;
-       result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0),
-                       request, REQTYPE_HOST_TO_DEVICE, value,
-                       0, NULL, 0, 300);
+       u32 *buf;
+       int result, i, length;
 
-       if (result <0) {
-               dev_err(&port->dev, "%s - Unable to send config request, "
-                               "request=0x%x value=0x%x result=%d\n",
-                               __FUNCTION__, request, value, result);
-               return result;
+       /* Number of integers required to contain the array */
+       length = (((size - 1) | 3) + 1)/4;
+
+       buf = kmalloc(length * sizeof(u32), GFP_KERNEL);
+       if (!buf) {
+               dev_err(&port->dev, "%s - out of memory.\n",
+                               __FUNCTION__);
+               return -ENOMEM;
+       }
+
+       /* Array of integers into bytes */
+       for (i = 0; i < length; i++)
+               buf[i] = cpu_to_le32(data[i]);
+
+       if (size > 2) {
+               result = usb_control_msg (serial->dev,
+                               usb_sndctrlpipe(serial->dev, 0),
+                               request, REQTYPE_HOST_TO_DEVICE, 0x0000,
+                               0, buf, size, 300);
+       } else {
+               result = usb_control_msg (serial->dev,
+                               usb_sndctrlpipe(serial->dev, 0),
+                               request, REQTYPE_HOST_TO_DEVICE, data[0],
+                               0, NULL, 0, 300);
        }
 
-       dbg(" %s - request=0x%x value=0x%x result=%d",
-                       __FUNCTION__, request, value, result);
+       kfree(buf);
+
+       if ((size > 2 && result != size) || result < 0) {
+               dev_err(&port->dev, "%s - Unable to send request, "
+                               "request=0x%x size=%d result=%d\n",
+                               __FUNCTION__, request, size, result);
+               return -EPROTO;
+       }
 
+       /* Single data value */
+       result = usb_control_msg (serial->dev,
+                       usb_sndctrlpipe(serial->dev, 0),
+                       request, REQTYPE_HOST_TO_DEVICE, data[0],
+                       0, NULL, 0, 300);
        return 0;
 }
 
+/*
+ * cp2101_set_config_single
+ * Convenience function for calling cp2101_set_config on single data values
+ * without requiring an integer pointer
+ */
+static inline int cp2101_set_config_single(struct usb_serial_port* port,
+               u8 request, unsigned int data)
+{
+       return cp2101_set_config(port, request, &data, 2);
+}
+
 static int cp2101_open (struct usb_serial_port *port, struct file *filp)
 {
        struct usb_serial *serial = port->serial;
@@ -177,7 +265,7 @@ static int cp2101_open (struct usb_serial_port *port, struct file *filp)
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
-       if (cp2101_set_config(port, CP2101_UART, UART_ENABLE)) {
+       if (cp2101_set_config_single(port, CP2101_UART, UART_ENABLE)) {
                dev_err(&port->dev, "%s - Unable to enable UART\n",
                                __FUNCTION__);
                return -EPROTO;
@@ -198,9 +286,12 @@ static int cp2101_open (struct usb_serial_port *port, struct file *filp)
                return result;
        }
 
-       /*Configure the termios structure*/
+       /* Configure the termios structure */
        cp2101_get_termios(port);
 
+       /* Set the DTR and RTS pins low */
+       cp2101_tiocmset(port, NULL, TIOCM_DTR | TIOCM_RTS, 0);
+
        return 0;
 }
 
@@ -228,16 +319,18 @@ static void cp2101_close (struct usb_serial_port *port, struct file * filp)
        usb_kill_urb(port->write_urb);
        usb_kill_urb(port->read_urb);
 
-       cp2101_set_config(port, CP2101_UART, UART_DISABLE);
+       cp2101_set_config_single(port, CP2101_UART, UART_DISABLE);
 }
 
-/* cp2101_get_termios*/
-/* Reads the baud rate, data bits, parity and stop bits from the device*/
-/* Corrects any unsupported values*/
-/* Configures the termios structure to reflect the state of the device*/
+/*
+ * cp2101_get_termios
+ * Reads the baud rate, data bits, parity, stop bits and flow control mode
+ * from the device, corrects any unsupported values, and configures the
+ * termios structure to reflect the state of the device
+ */
 static void cp2101_get_termios (struct usb_serial_port *port)
 {
-       unsigned int cflag;
+       unsigned int cflag, modem_ctl[4];
        int baud;
        int bits;
 
@@ -249,15 +342,16 @@ static void cp2101_get_termios (struct usb_serial_port *port)
        }
        cflag = port->tty->termios->c_cflag;
 
-       baud = cp2101_get_config(port, CP2101_BAUDRATE);
-       /*Convert to baudrate*/
+       cp2101_get_config(port, CP2101_BAUDRATE, &baud, 2);
+       /* Convert to baudrate */
        if (baud)
                baud = BAUD_RATE_GEN_FREQ / baud;
 
        dbg("%s - baud rate = %d", __FUNCTION__, baud);
        cflag &= ~CBAUD;
        switch (baud) {
-               /* The baud rates which are commented out below
+               /*
+                * The baud rates which are commented out below
                 * appear to be supported by the device
                 * but are non-standard
                 */
@@ -284,14 +378,18 @@ static void cp2101_get_termios (struct usb_serial_port *port)
                        dbg("%s - Baud rate is not supported, "
                                        "using 9600 baud", __FUNCTION__);
                        cflag |= B9600;
-                       cp2101_set_config(port, CP2101_BAUDRATE,
+                       cp2101_set_config_single(port, CP2101_BAUDRATE,
                                        (BAUD_RATE_GEN_FREQ/9600));
                        break;
        }
 
-       bits = cp2101_get_config(port, CP2101_BITS);
+       cp2101_get_config(port, CP2101_BITS, &bits, 2);
        cflag &= ~CSIZE;
        switch(bits & BITS_DATA_MASK) {
+               case BITS_DATA_5:
+                       dbg("%s - data bits = 5", __FUNCTION__);
+                       cflag |= CS5;
+                       break;
                case BITS_DATA_6:
                        dbg("%s - data bits = 6", __FUNCTION__);
                        cflag |= CS6;
@@ -310,7 +408,7 @@ static void cp2101_get_termios (struct usb_serial_port *port)
                        cflag |= CS8;
                        bits &= ~BITS_DATA_MASK;
                        bits |= BITS_DATA_8;
-                       cp2101_set_config(port, CP2101_BITS, bits);
+                       cp2101_set_config(port, CP2101_BITS, &bits, 2);
                        break;
                default:
                        dbg("%s - Unknown number of data bits, "
@@ -318,7 +416,7 @@ static void cp2101_get_termios (struct usb_serial_port *port)
                        cflag |= CS8;
                        bits &= ~BITS_DATA_MASK;
                        bits |= BITS_DATA_8;
-                       cp2101_set_config(port, CP2101_BITS, bits);
+                       cp2101_set_config(port, CP2101_BITS, &bits, 2);
                        break;
        }
 
@@ -341,21 +439,21 @@ static void cp2101_get_termios (struct usb_serial_port *port)
                                        "disabling parity)", __FUNCTION__);
                        cflag &= ~PARENB;
                        bits &= ~BITS_PARITY_MASK;
-                       cp2101_set_config(port, CP2101_BITS, bits);
+                       cp2101_set_config(port, CP2101_BITS, &bits, 2);
                        break;
                case BITS_PARITY_SPACE:
                        dbg("%s - parity = SPACE (not supported, "
                                        "disabling parity)", __FUNCTION__);
                        cflag &= ~PARENB;
                        bits &= ~BITS_PARITY_MASK;
-                       cp2101_set_config(port, CP2101_BITS, bits);
+                       cp2101_set_config(port, CP2101_BITS, &bits, 2);
                        break;
                default:
                        dbg("%s - Unknown parity mode, "
                                        "disabling parity", __FUNCTION__);
                        cflag &= ~PARENB;
                        bits &= ~BITS_PARITY_MASK;
-                       cp2101_set_config(port, CP2101_BITS, bits);
+                       cp2101_set_config(port, CP2101_BITS, &bits, 2);
                        break;
        }
 
@@ -366,9 +464,9 @@ static void cp2101_get_termios (struct usb_serial_port *port)
                        break;
                case BITS_STOP_1_5:
                        dbg("%s - stop bits = 1.5 (not supported, "
-                                       "using 1 stop bit", __FUNCTION__);
+                                       "using 1 stop bit)", __FUNCTION__);
                        bits &= ~BITS_STOP_MASK;
-                       cp2101_set_config(port, CP2101_BITS, bits);
+                       cp2101_set_config(port, CP2101_BITS, &bits, 2);
                        break;
                case BITS_STOP_2:
                        dbg("%s - stop bits = 2", __FUNCTION__);
@@ -378,10 +476,19 @@ static void cp2101_get_termios (struct usb_serial_port *port)
                        dbg("%s - Unknown number of stop bits, "
                                        "using 1 stop bit", __FUNCTION__);
                        bits &= ~BITS_STOP_MASK;
-                       cp2101_set_config(port, CP2101_BITS, bits);
+                       cp2101_set_config(port, CP2101_BITS, &bits, 2);
                        break;
        }
 
+       cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16);
+       if (modem_ctl[0] & 0x0008) {
+               dbg("%s - flow control = CRTSCTS", __FUNCTION__);
+               cflag |= CRTSCTS;
+       } else {
+               dbg("%s - flow control = NONE", __FUNCTION__);
+               cflag &= ~CRTSCTS;
+       }
+
        port->tty->termios->c_cflag = cflag;
 }
 
@@ -389,8 +496,8 @@ static void cp2101_set_termios (struct usb_serial_port *port,
                struct termios *old_termios)
 {
        unsigned int cflag, old_cflag=0;
-       int baud=0;
-       int bits;
+       int baud=0, bits;
+       unsigned int modem_ctl[4];
 
        dbg("%s - port %d", __FUNCTION__, port->number);
 
@@ -400,7 +507,7 @@ static void cp2101_set_termios (struct usb_serial_port *port,
        }
        cflag = port->tty->termios->c_cflag;
 
-       /* check that they really want us to change something */
+       /* Check that they really want us to change something */
        if (old_termios) {
                if ((cflag == old_termios->c_cflag) &&
                                (RELEVANT_IFLAG(port->tty->termios->c_iflag)
@@ -415,7 +522,8 @@ static void cp2101_set_termios (struct usb_serial_port *port,
        /* If the baud rate is to be updated*/
        if ((cflag & CBAUD) != (old_cflag & CBAUD)) {
                switch (cflag & CBAUD) {
-                       /* The baud rates which are commented out below
+                       /*
+                        * The baud rates which are commented out below
                         * appear to be supported by the device
                         * but are non-standard
                         */
@@ -448,18 +556,22 @@ static void cp2101_set_termios (struct usb_serial_port *port,
                if (baud) {
                        dbg("%s - Setting baud rate to %d baud", __FUNCTION__,
                                        baud);
-                       if (cp2101_set_config(port, CP2101_BAUDRATE,
+                       if (cp2101_set_config_single(port, CP2101_BAUDRATE,
                                                (BAUD_RATE_GEN_FREQ / baud)))
                                dev_err(&port->dev, "Baud rate requested not "
                                                "supported by device\n");
                }
        }
 
-       /*If the number of