Automatic merge of rsync://rsync.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
This commit is contained in:
commit
3c241f8337
|
@ -14,7 +14,7 @@
|
||||||
</authorgroup>
|
</authorgroup>
|
||||||
|
|
||||||
<copyright>
|
<copyright>
|
||||||
<year>2003</year>
|
<year>2003-2005</year>
|
||||||
<holder>Jeff Garzik</holder>
|
<holder>Jeff Garzik</holder>
|
||||||
</copyright>
|
</copyright>
|
||||||
|
|
||||||
|
@ -44,30 +44,38 @@
|
||||||
|
|
||||||
<toc></toc>
|
<toc></toc>
|
||||||
|
|
||||||
<chapter id="libataThanks">
|
<chapter id="libataIntroduction">
|
||||||
<title>Thanks</title>
|
<title>Introduction</title>
|
||||||
<para>
|
<para>
|
||||||
The bulk of the ATA knowledge comes thanks to long conversations with
|
libATA is a library used inside the Linux kernel to support ATA host
|
||||||
Andre Hedrick (www.linux-ide.org).
|
controllers and devices. libATA provides an ATA driver API, class
|
||||||
|
transports for ATA and ATAPI devices, and SCSI<->ATA translation
|
||||||
|
for ATA devices according to the T10 SAT specification.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
Thanks to Alan Cox for pointing out similarities
|
This Guide documents the libATA driver API, library functions, library
|
||||||
between SATA and SCSI, and in general for motivation to hack on
|
internals, and a couple sample ATA low-level drivers.
|
||||||
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>
|
</para>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
<chapter id="libataDriverApi">
|
<chapter id="libataDriverApi">
|
||||||
<title>libata Driver API</title>
|
<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>
|
<sect1>
|
||||||
<title>struct ata_port_operations</title>
|
<title>struct ata_port_operations</title>
|
||||||
|
|
||||||
|
<sect2><title>Disable ATA port</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
void (*port_disable) (struct ata_port *);
|
void (*port_disable) (struct ata_port *);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
@ -78,6 +86,9 @@ void (*port_disable) (struct ata_port *);
|
||||||
unplug).
|
unplug).
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2><title>Post-IDENTIFY device configuration</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
void (*dev_config) (struct ata_port *, struct ata_device *);
|
void (*dev_config) (struct ata_port *, struct ata_device *);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
@ -88,6 +99,9 @@ void (*dev_config) (struct ata_port *, struct ata_device *);
|
||||||
issue of SET FEATURES - XFER MODE, and prior to operation.
|
issue of SET FEATURES - XFER MODE, and prior to operation.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2><title>Set PIO/DMA mode</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
void (*set_piomode) (struct ata_port *, struct ata_device *);
|
void (*set_piomode) (struct ata_port *, struct ata_device *);
|
||||||
void (*set_dmamode) (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.
|
->set_dma_mode() is only called if DMA is possible.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2><title>Taskfile read/write</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf);
|
void (*tf_load) (struct ata_port *ap, struct ata_taskfile *tf);
|
||||||
void (*tf_read) (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.
|
taskfile register values.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2><title>ATA command execute</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
|
void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
@ -129,17 +149,37 @@ void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
|
||||||
->tf_load(), to be initiated in hardware.
|
->tf_load(), to be initiated in hardware.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2><title>Per-cmd ATAPI DMA capabilities filter</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
u8 (*check_status)(struct ata_port *ap);
|
int (*check_atapi_dma) (struct ata_queued_cmd *qc);
|
||||||
void (*dev_select)(struct ata_port *ap, unsigned int device);
|
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
Reads the Status ATA shadow register from hardware. On some
|
Allow low-level driver to filter ATA PACKET commands, returning a status
|
||||||
hardware, this has the side effect of clearing the interrupt
|
indicating whether or not it is OK to use DMA for the supplied PACKET
|
||||||
condition.
|
command.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2><title>Read specific ATA shadow registers</title>
|
||||||
|
<programlisting>
|
||||||
|
u8 (*check_status)(struct ata_port *ap);
|
||||||
|
u8 (*check_altstatus)(struct ata_port *ap);
|
||||||
|
u8 (*check_err)(struct ata_port *ap);
|
||||||
|
</programlisting>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
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>
|
<programlisting>
|
||||||
void (*dev_select)(struct ata_port *ap, unsigned int device);
|
void (*dev_select)(struct ata_port *ap, unsigned int device);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
@ -147,9 +187,13 @@ void (*dev_select)(struct ata_port *ap, unsigned int device);
|
||||||
<para>
|
<para>
|
||||||
Issues the low-level hardware command(s) that causes one of N
|
Issues the low-level hardware command(s) that causes one of N
|
||||||
hardware devices to be considered 'selected' (active and
|
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>
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2><title>Reset ATA bus</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
void (*phy_reset) (struct ata_port *ap);
|
void (*phy_reset) (struct ata_port *ap);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
@ -162,17 +206,31 @@ void (*phy_reset) (struct ata_port *ap);
|
||||||
functions ata_bus_reset() or sata_phy_reset() for this hook.
|
functions ata_bus_reset() or sata_phy_reset() for this hook.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2><title>Control PCI IDE BMDMA engine</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
void (*bmdma_setup) (struct ata_queued_cmd *qc);
|
void (*bmdma_setup) (struct ata_queued_cmd *qc);
|
||||||
void (*bmdma_start) (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>
|
</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
When setting up an IDE BMDMA transaction, these hooks arm
|
When setting up an IDE BMDMA transaction, these hooks arm
|
||||||
(->bmdma_setup) and fire (->bmdma_start) the hardware's DMA
|
(->bmdma_setup), fire (->bmdma_start), and halt (->bmdma_stop)
|
||||||
engine.
|
the hardware's DMA engine. ->bmdma_status is used to read the standard
|
||||||
|
PCI IDE DMA Status register.
|
||||||
</para>
|
</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>
|
<programlisting>
|
||||||
void (*qc_prep) (struct ata_queued_cmd *qc);
|
void (*qc_prep) (struct ata_queued_cmd *qc);
|
||||||
int (*qc_issue) (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
|
->qc_issue is used to make a command active, once the hardware
|
||||||
and S/G tables have been prepared. IDE BMDMA drivers use the
|
and S/G tables have been prepared. IDE BMDMA drivers use the
|
||||||
helper function ata_qc_issue_prot() for taskfile protocol-based
|
helper function ata_qc_issue_prot() for taskfile protocol-based
|
||||||
dispatch. More advanced drivers roll their own ->qc_issue
|
dispatch. More advanced drivers implement their own ->qc_issue.
|
||||||
implementation, using this as the "issue new ATA command to
|
|
||||||
hardware" hook.
|
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2><title>Timeout (error) handling</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
void (*eng_timeout) (struct ata_port *ap);
|
void (*eng_timeout) (struct ata_port *ap);
|
||||||
</programlisting>
|
</programlisting>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
This is a high level error handling function, called from the
|
This is a high level error handling function, called from the
|
||||||
error handling thread, when a command times out.
|
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>
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2><title>Hardware interrupt handling</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
|
irqreturn_t (*irq_handler)(int, void *, struct pt_regs *);
|
||||||
void (*irq_clear) (struct ata_port *);
|
void (*irq_clear) (struct ata_port *);
|
||||||
|
@ -216,6 +280,9 @@ void (*irq_clear) (struct ata_port *);
|
||||||
is quiet.
|
is quiet.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2><title>SATA phy read/write</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg);
|
u32 (*scr_read) (struct ata_port *ap, unsigned int sc_reg);
|
||||||
void (*scr_write) (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.
|
if ->phy_reset hook called the sata_phy_reset() helper function.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
</sect2>
|
||||||
|
|
||||||
|
<sect2><title>Init and shutdown</title>
|
||||||
<programlisting>
|
<programlisting>
|
||||||
int (*port_start) (struct ata_port *ap);
|
int (*port_start) (struct ata_port *ap);
|
||||||
void (*port_stop) (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.
|
tasks.
|
||||||
</para>
|
</para>
|
||||||
<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
|
->port_stop() is called after ->host_stop(). It's sole function
|
||||||
is to release DMA/memory resources, now that they are no longer
|
is to release DMA/memory resources, now that they are no longer
|
||||||
actively being used.
|
actively being used.
|
||||||
</para>
|
</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>
|
</sect1>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
@ -279,4 +351,24 @@ void (*host_stop) (struct ata_host_set *host_set);
|
||||||
!Idrivers/scsi/sata_sil.c
|
!Idrivers/scsi/sata_sil.c
|
||||||
</chapter>
|
</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>
|
</book>
|
||||||
|
|
|
@ -239,6 +239,12 @@ L: linux-usb-devel@lists.sourceforge.net
|
||||||
W: http://www.linux-usb.org/SpeedTouch/
|
W: http://www.linux-usb.org/SpeedTouch/
|
||||||
S: Maintained
|
S: Maintained
|
||||||
|
|
||||||
|
ALI1563 I2C DRIVER
|
||||||
|
P: Rudolf Marek
|
||||||
|
M: r.marek@sh.cvut.cz
|
||||||
|
L: sensors@stimpy.netroedge.com
|
||||||
|
S: Maintained
|
||||||
|
|
||||||
ALPHA PORT
|
ALPHA PORT
|
||||||
P: Richard Henderson
|
P: Richard Henderson
|
||||||
M: rth@twiddle.net
|
M: rth@twiddle.net
|
||||||
|
|
|
@ -2427,7 +2427,7 @@ sys32_epoll_wait(int epfd, struct epoll_event32 __user * events, int maxevents,
|
||||||
{
|
{
|
||||||
struct epoll_event *events64 = NULL;
|
struct epoll_event *events64 = NULL;
|
||||||
mm_segment_t old_fs = get_fs();
|
mm_segment_t old_fs = get_fs();
|
||||||
int error, numevents, size;
|
int numevents, size;
|
||||||
int evt_idx;
|
int evt_idx;
|
||||||
int do_free_pages = 0;
|
int do_free_pages = 0;
|
||||||
|
|
||||||
|
|
|
@ -1103,8 +1103,6 @@ ia64_mca_cpe_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs)
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_ACPI */
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ia64_mca_cpe_poll
|
* 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);
|
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
|
* C portion of the OS INIT handler
|
||||||
*
|
*
|
||||||
|
|
|
@ -45,11 +45,13 @@ asmlinkage void ret_from_fork(void);
|
||||||
*/
|
*/
|
||||||
void default_idle(void)
|
void default_idle(void)
|
||||||
{
|
{
|
||||||
while(1) {
|
local_irq_disable();
|
||||||
if (need_resched())
|
while (!need_resched()) {
|
||||||
|
/* This stop will re-enable interrupts */
|
||||||
__asm__("stop #0x2000" : : : "cc");
|
__asm__("stop #0x2000" : : : "cc");
|
||||||
schedule();
|
local_irq_disable();
|
||||||
}
|
}
|
||||||
|
local_irq_enable();
|
||||||
}
|
}
|
||||||
|
|
||||||
void (*idle)(void) = default_idle;
|
void (*idle)(void) = default_idle;
|
||||||
|
@ -63,7 +65,12 @@ void (*idle)(void) = default_idle;
|
||||||
void cpu_idle(void)
|
void cpu_idle(void)
|
||||||
{
|
{
|
||||||
/* endless idle loop with no priority at all */
|
/* endless idle loop with no priority at all */
|
||||||
|
while (1) {
|
||||||
idle();
|
idle();
|
||||||
|
preempt_enable_no_resched();
|
||||||
|
schedule();
|
||||||
|
preempt_disable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void machine_restart(char * __unused)
|
void machine_restart(char * __unused)
|
||||||
|
|
|
@ -626,8 +626,18 @@ inspect_node(phandle node, struct device_node *dad,
|
||||||
l = call_prom("package-to-path", 3, 1, node,
|
l = call_prom("package-to-path", 3, 1, node,
|
||||||
mem_start, mem_end - mem_start);
|
mem_start, mem_end - mem_start);
|
||||||
if (l >= 0) {
|
if (l >= 0) {
|
||||||
|
char *p, *ep;
|
||||||
|
|
||||||
np->full_name = PTRUNRELOC((char *) mem_start);
|
np->full_name = PTRUNRELOC((char *) mem_start);
|
||||||
*(char *)(mem_start + l) = 0;
|
*(char *)(mem_start + l) = 0;
|
||||||
|
/* Fixup an Apple bug where they have bogus \0 chars in the
|
||||||
|
* middle of the path in some properties
|
||||||
|
*/
|
||||||
|
for (p = (char *)mem_start, ep = p + l; p < ep; p++)
|
||||||
|
if ((*p) == '\0') {
|
||||||
|
memmove(p, p+1, ep - p);
|
||||||
|
ep--;
|
||||||
|
}
|
||||||
mem_start = ALIGNUL(mem_start + l + 1);
|
mem_start = ALIGNUL(mem_start + l + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -436,15 +436,6 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
|
||||||
REST_8GPRS(14, r1)
|
REST_8GPRS(14, r1)
|
||||||
REST_10GPRS(22, 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 */
|
/* convert old thread to its task_struct for return value */
|
||||||
addi r3,r3,-THREAD
|
addi r3,r3,-THREAD
|
||||||
ld r7,_NIP(r1) /* Return to _switch caller in new task */
|
ld r7,_NIP(r1) /* Return to _switch caller in new task */
|
||||||
|
|
|
@ -626,10 +626,10 @@ system_reset_iSeries:
|
||||||
lhz r24,PACAPACAINDEX(r13) /* Get processor # */
|
lhz r24,PACAPACAINDEX(r13) /* Get processor # */
|
||||||
cmpwi 0,r24,0 /* Are we processor 0? */
|
cmpwi 0,r24,0 /* Are we processor 0? */
|
||||||
beq .__start_initialization_iSeries /* Start up the first processor */
|
beq .__start_initialization_iSeries /* Start up the first processor */
|
||||||
mfspr r4,CTRLF
|
mfspr r4,SPRN_CTRLF
|
||||||
li r5,RUNLATCH /* Turn off the run light */
|
li r5,CTRL_RUNLATCH /* Turn off the run light */
|
||||||
andc r4,r4,r5
|
andc r4,r4,r5
|
||||||
mtspr CTRLT,r4
|
mtspr SPRN_CTRLT,r4
|
||||||
|
|
||||||
1:
|
1:
|
||||||
HMT_LOW
|
HMT_LOW
|
||||||
|
@ -2082,9 +2082,9 @@ _GLOBAL(hmt_start_secondary)
|
||||||
mfspr r4, HID0
|
mfspr r4, HID0
|
||||||
ori r4, r4, 0x1
|
ori r4, r4, 0x1
|
||||||
mtspr HID0, r4
|
mtspr HID0, r4
|
||||||
mfspr r4, CTRLF
|
mfspr r4, SPRN_CTRLF
|
||||||
oris r4, r4, 0x40
|
oris r4, r4, 0x40
|
||||||
mtspr CTRLT, r4
|
mtspr SPRN_CTRLT, r4
|
||||||
blr
|
blr
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -852,6 +852,28 @@ static int __init iSeries_src_init(void)
|
||||||
|
|
||||||
late_initcall(iSeries_src_init);
|
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)
|
void __init iSeries_early_setup(void)
|
||||||
{
|
{
|
||||||
iSeries_fixup_klimit();
|
iSeries_fixup_klimit();
|
||||||
|
|
|
@ -75,13 +75,9 @@ static int iSeries_idle(void)
|
||||||
{
|
{
|
||||||
struct paca_struct *lpaca;
|
struct paca_struct *lpaca;
|
||||||
long oldval;
|
long oldval;
|
||||||
unsigned long CTRL;
|
|
||||||
|
|
||||||
/* ensure iSeries run light will be out when idle */
|
/* ensure iSeries run light will be out when idle */
|
||||||
clear_thread_flag(TIF_RUN_LIGHT);
|
ppc64_runlatch_off();
|
||||||
CTRL = mfspr(CTRLF);
|
|
||||||
CTRL &= ~RUNLATCH;
|
|
||||||
mtspr(CTRLT, CTRL);
|
|
||||||
|
|
||||||
lpaca = get_paca();
|
lpaca = get_paca();
|
||||||
|
|
||||||
|
@ -111,7 +107,9 @@ static int iSeries_idle(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ppc64_runlatch_on();
|
||||||
schedule();
|
schedule();
|
||||||
|
ppc64_runlatch_off();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -47,14 +47,6 @@ static void remove_node_proc_entries(struct device_node *np)
|
||||||
remove_proc_entry(pp->name, np->pde);
|
remove_proc_entry(pp->name, np->pde);
|
||||||
pp = pp->next;
|
pp = pp->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Assuming that symlinks have the same parent directory as
|
|
||||||
* np->pde.
|
|
||||||
*/
|
|
||||||
if (np->name_link)
|
|
||||||
remove_proc_entry(np->name_link->name, parent->pde);
|
|
||||||
if (np->addr_link)
|
|
||||||
remove_proc_entry(np->addr_link->name, parent->pde);
|
|
||||||
if (np->pde)
|
if (np->pde)
|
||||||
remove_proc_entry(np->pde->name, parent->pde);
|
remove_proc_entry(np->pde->name, parent->pde);
|
||||||
}
|
}
|
||||||
|
|
|
@ -378,9 +378,6 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
|
||||||
childregs->gpr[1] = sp + sizeof(struct pt_regs);
|
childregs->gpr[1] = sp + sizeof(struct pt_regs);
|
||||||
p->thread.regs = NULL; /* no user register state */
|
p->thread.regs = NULL; /* no user register state */
|
||||||
clear_ti_thread_flag(p->thread_info, TIF_32BIT);
|
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 {
|
} else {
|
||||||
childregs->gpr[1] = usp;
|
childregs->gpr[1] = usp;
|
||||||
p->thread.regs = childregs;
|
p->thread.regs = childregs;
|
||||||
|
|
|
@ -211,13 +211,23 @@ struct {
|
||||||
*/
|
*/
|
||||||
#define ADDR(x) (u32) ((unsigned long)(x) - offset)
|
#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
|
/* 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
|
* 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.
|
* 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, ...)
|
static int __init call_prom(const char *service, int nargs, int nret, ...)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -587,14 +597,13 @@ static void __init prom_send_capabilities(void)
|
||||||
{
|
{
|
||||||
unsigned long offset = reloc_offset();
|
unsigned long offset = reloc_offset();
|
||||||
ihandle elfloader;
|
ihandle elfloader;
|
||||||
int ret;
|
|
||||||
|
|
||||||
elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader"));
|
elfloader = call_prom("open", 1, 1, ADDR("/packages/elf-loader"));
|
||||||
if (elfloader == 0) {
|
if (elfloader == 0) {
|
||||||
prom_printf("couldn't open /packages/elf-loader\n");
|
prom_printf("couldn't open /packages/elf-loader\n");
|
||||||
return;
|
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));
|
elfloader, ADDR(&fake_elf));
|
||||||
call_prom("close", 1, 0, elfloader);
|
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)) {
|
base = _ALIGN_UP(base + 0x100000, align)) {
|
||||||
prom_debug(" trying: 0x%x\n\r", base);
|
prom_debug(" trying: 0x%x\n\r", base);
|
||||||
addr = (unsigned long)prom_claim(base, size, 0);
|
addr = (unsigned long)prom_claim(base, size, 0);
|
||||||
if ((int)addr != PROM_ERROR)
|
if (addr != PROM_ERROR)
|
||||||
break;
|
break;
|
||||||
addr = 0;
|
addr = 0;
|
||||||
if (align == 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)) {
|
for(; base > RELOC(alloc_bottom); base = _ALIGN_DOWN(base - 0x100000, align)) {
|
||||||
prom_debug(" trying: 0x%x\n\r", base);
|
prom_debug(" trying: 0x%x\n\r", base);
|
||||||
addr = (unsigned long)prom_claim(base, size, 0);
|
addr = (unsigned long)prom_claim(base, size, 0);
|
||||||
if ((int)addr != PROM_ERROR)
|
if (addr != PROM_ERROR)
|
||||||
break;
|
break;
|
||||||
addr = 0;
|
addr = 0;
|
||||||
}
|
}
|
||||||
|
@ -902,18 +911,19 @@ static void __init prom_instantiate_rtas(void)
|
||||||
{
|
{
|
||||||
unsigned long offset = reloc_offset();
|
unsigned long offset = reloc_offset();
|
||||||
struct prom_t *_prom = PTRRELOC(&prom);
|
struct prom_t *_prom = PTRRELOC(&prom);
|
||||||
phandle prom_rtas, rtas_node;
|
phandle rtas_node;
|
||||||
|
ihandle rtas_inst;
|
||||||
u32 base, entry = 0;
|
u32 base, entry = 0;
|
||||||
u32 size = 0;
|
u32 size = 0;
|
||||||
|
|
||||||
prom_debug("prom_instantiate_rtas: start...\n");
|
prom_debug("prom_instantiate_rtas: start...\n");
|
||||||
|
|
||||||
prom_rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
|
rtas_node = call_prom("finddevice", 1, 1, ADDR("/rtas"));
|
||||||
prom_debug("prom_rtas: %x\n", prom_rtas);
|
prom_debug("rtas_node: %x\n", rtas_node);
|
||||||
if (prom_rtas == (phandle) -1)
|
if (!PHANDLE_VALID(rtas_node))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
prom_getprop(prom_rtas, "rtas-size", &size, sizeof(size));
|
prom_getprop(rtas_node, "rtas-size", &size, sizeof(size));
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -922,14 +932,18 @@ static void __init prom_instantiate_rtas(void)
|
||||||
prom_printf("RTAS allocation failed !\n");
|
prom_printf("RTAS allocation failed !\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
prom_printf("instantiating rtas at 0x%x", base);
|
|
||||||
|
|
||||||
rtas_node = call_prom("open", 1, 1, ADDR("/rtas"));
|
rtas_inst = call_prom("open", 1, 1, ADDR("/rtas"));
|
||||||
prom_printf("...");
|
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,
|
if (call_prom("call-method", 3, 2,
|
||||||
ADDR("instantiate-rtas"),
|
ADDR("instantiate-rtas"),
|
||||||
rtas_node, base) != PROM_ERROR) {
|
rtas_inst, base) != PROM_ERROR) {
|
||||||
entry = (long)_prom->args.rets[1];
|
entry = (long)_prom->args.rets[1];
|
||||||
}
|
}
|
||||||
if (entry == 0) {
|
if (entry == 0) {
|
||||||
|
@ -940,8 +954,8 @@ static void __init prom_instantiate_rtas(void)
|
||||||
|
|
||||||
reserve_mem(base, size);
|
reserve_mem(base, size);
|
||||||
|
|
||||||
prom_setprop(prom_rtas, "linux,rtas-base", &base, sizeof(base));
|
prom_setprop(rtas_node, "linux,rtas-base", &base, sizeof(base));
|
||||||
prom_setprop(prom_rtas, "linux,rtas-entry", &entry, sizeof(entry));
|
prom_setprop(rtas_node, "linux,rtas-entry", &entry, sizeof(entry));
|
||||||
|
|
||||||
prom_debug("rtas base = 0x%x\n", base);
|
prom_debug("rtas base = 0x%x\n", base);
|
||||||
prom_debug("rtas entry = 0x%x\n", entry);
|
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);
|
prom_printf("opening PHB %s", path);
|
||||||
phb_node = call_prom("open", 1, 1, path);
|
phb_node = call_prom("open", 1, 1, path);
|
||||||
if ( (long)phb_node <= 0)
|
if (phb_node == 0)
|
||||||
prom_printf("... failed\n");
|
prom_printf("... failed\n");
|
||||||
else
|
else
|
||||||
prom_printf("... done\n");
|
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 */
|
/* get a handle for the stdout device */
|
||||||
_prom->chosen = call_prom("finddevice", 1, 1, ADDR("/chosen"));
|
_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 :( */
|
prom_panic("cannot find chosen"); /* msg won't be printed :( */
|
||||||
|
|
||||||
/* get device tree root */
|
/* get device tree root */
|
||||||
_prom->root = call_prom("finddevice", 1, 1, ADDR("/"));
|
_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 :( */
|
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 */
|
/* Default to pSeries. We need to know if we are running LPAR */
|
||||||
rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
|
rtas = call_prom("finddevice", 1, 1, ADDR("/rtas"));
|
||||||
if (rtas != (phandle) -1) {
|
if (PHANDLE_VALID(rtas)) {
|
||||||
unsigned long x;
|
int x = prom_getproplen(rtas, "ibm,hypertas-functions");
|
||||||
x = prom_getproplen(rtas, "ibm,hypertas-functions");
|
|
||||||
if (x != PROM_ERROR) {
|
if (x != PROM_ERROR) {
|
||||||
prom_printf("Hypertas detected, assuming LPAR !\n");
|
prom_printf("Hypertas detected, assuming LPAR !\n");
|
||||||
return PLATFORM_PSERIES_LPAR;
|
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
|
* leave some room at the end of the path for appending extra
|
||||||
* arguments
|
* 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;
|
continue;
|
||||||
prom_printf("found display : %s, opening ... ", path);
|
prom_printf("found display : %s, opening ... ", path);
|
||||||
|
|
||||||
ih = call_prom("open", 1, 1, path);
|
ih = call_prom("open", 1, 1, path);
|
||||||
if (ih == (ihandle)0 || ih == (ihandle)-1) {
|
if (ih == 0) {
|
||||||
prom_printf("failed\n");
|
prom_printf("failed\n");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1514,6 +1528,12 @@ static unsigned long __init dt_find_string(char *str)
|
||||||
return 0;
|
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,
|
static void __init scan_dt_build_strings(phandle node, unsigned long *mem_start,
|
||||||
unsigned long *mem_end)
|
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 */
|
/* get and store all property names */
|
||||||
prev_name = RELOC("");
|
prev_name = RELOC("");
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
int rc;
|
||||||
|
|
||||||
/* 32 is max len of name including nul. */
|
/* 64 is max len of name including nul. */
|
||||||
namep = make_room(mem_start, mem_end, 32, 1);
|
namep = make_room(mem_start, mem_end, MAX_PROPERTY_NAME, 1);
|
||||||
if (call_prom("nextprop", 3, 1, node, prev_name, namep) <= 0) {
|
rc = call_prom("nextprop", 3, 1, node, prev_name, namep);
|
||||||
|
if (rc != 1) {
|
||||||
/* No more nodes: unwind alloc */
|
/* No more nodes: unwind alloc */
|
||||||
*mem_start = (unsigned long)namep;
|
*mem_start = (unsigned long)namep;
|
||||||
break;
|
break;
|
||||||
|
@ -1555,18 +1577,12 @@ 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,
|
static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
|
||||||
unsigned long *mem_end)
|
unsigned long *mem_end)
|
||||||
{
|
{
|
||||||
int l, align;
|
int l, align;
|
||||||
phandle child;
|
phandle child;
|
||||||
char *namep, *prev_name, *sstart;
|
char *namep, *prev_name, *sstart, *p, *ep;
|
||||||
unsigned long soff;
|
unsigned long soff;
|
||||||
unsigned char *valp;
|
unsigned char *valp;
|
||||||
unsigned long offset = reloc_offset();
|
unsigned long offset = reloc_offset();
|
||||||
|
@ -1588,6 +1604,14 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
|
||||||
call_prom("package-to-path", 3, 1, node, namep, l);
|
call_prom("package-to-path", 3, 1, node, namep, l);
|
||||||
}
|
}
|
||||||
namep[l] = '\0';
|
namep[l] = '\0';
|
||||||
|
/* Fixup an Apple bug where they have bogus \0 chars in the
|
||||||
|
* middle of the path in some properties
|
||||||
|
*/
|
||||||
|
for (p = namep, ep = namep + l; p < ep; p++)
|
||||||
|
if (*p == '\0') {
|
||||||
|
memmove(p, p+1, ep - p);
|
||||||
|
ep--; l--;
|
||||||
|
}
|
||||||
*mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4);
|
*mem_start = _ALIGN(((unsigned long) namep) + strlen(namep) + 1, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1599,7 +1623,10 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
|
||||||
prev_name = RELOC("");
|
prev_name = RELOC("");
|
||||||
sstart = (char *)RELOC(dt_string_start);
|
sstart = (char *)RELOC(dt_string_start);
|
||||||
for (;;) {
|
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;
|
break;
|
||||||
|
|
||||||
/* find string offset */
|
/* find string offset */
|
||||||
|
@ -1615,7 +1642,7 @@ static void __init scan_dt_build_struct(phandle node, unsigned long *mem_start,
|
||||||
l = call_prom("getproplen", 2, 1, node, pname);
|
l = call_prom("getproplen", 2, 1, node, pname);
|
||||||
|
|
||||||
/* sanity checks */
|
/* sanity checks */
|
||||||
if (l < 0)
|
if (l == PROM_ERROR)
|
||||||
continue;
|
continue;
|
||||||
if (l > MAX_PROPERTY_LENGTH) {
|
if (l > MAX_PROPERTY_LENGTH) {
|
||||||
prom_printf("WARNING: ignoring large property ");
|
prom_printf("WARNING: ignoring large property ");
|
||||||
|
@ -1763,17 +1790,18 @@ static void __init fixup_device_tree(void)
|
||||||
|
|
||||||
/* Some G5s have a missing interrupt definition, fix it up here */
|
/* Some G5s have a missing interrupt definition, fix it up here */
|
||||||
u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));
|
u3 = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000"));
|
||||||
if ((long)u3 <= 0)
|
if (!PHANDLE_VALID(u3))
|
||||||
return;
|
return;
|
||||||
i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));
|
i2c = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/i2c@f8001000"));
|
||||||
if ((long)i2c <= 0)
|
if (!PHANDLE_VALID(i2c))
|
||||||
return;
|
return;
|
||||||
mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));
|
mpic = call_prom("finddevice", 1, 1, ADDR("/u3@0,f8000000/mpic@f8040000"));
|
||||||
if ((long)mpic <= 0)
|
if (!PHANDLE_VALID(mpic))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* check if proper rev of u3 */
|
/* 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;
|
return;
|
||||||
if (u3_rev != 0x35)
|
if (u3_rev != 0x35)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -103,11 +103,6 @@ extern void unflatten_device_tree(void);
|
||||||
|
|
||||||
extern void smp_release_cpus(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 have_of = 1;
|
||||||
int boot_cpuid = 0;
|
int boot_cpuid = 0;
|
||||||
int boot_cpuid_phys = 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);
|
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 */
|
/* This should only be called on processor 0 during calibrate decr */
|
||||||
void setup_default_decr(void)
|
void setup_default_decr(void)
|
||||||
{
|
{
|
||||||
struct paca_struct *lpaca = get_paca();
|
struct paca_struct *lpaca = get_paca();
|
||||||
|
|
||||||
if ( decr_overclock_set && !decr_overclock_proc0_set )
|
lpaca->default_decr = tb_ticks_per_jiffy;
|
||||||
decr_overclock_proc0 = decr_overclock;
|
|
||||||
|
|
||||||
lpaca->default_decr = tb_ticks_per_jiffy / decr_overclock_proc0;
|
|
||||||
lpaca->next_jiffy_update_tb = get_tb() + 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
|
#ifndef CONFIG_PPC_ISERIES
|
||||||
/*
|
/*
|
||||||
* This function can be used by platforms to "find" legacy serial ports.
|
* This function can be used by platforms to "find" legacy serial ports.
|
||||||
|
|
|
@ -334,7 +334,6 @@ void smp_call_function_interrupt(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern unsigned long decr_overclock;
|
|
||||||
extern struct gettimeofday_struct do_gtod;
|
extern struct gettimeofday_struct do_gtod;
|
||||||
|
|
||||||
struct thread_info *current_set[NR_CPUS];
|
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))
|
if (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu))
|
||||||
return -EINVAL;
|
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)) {
|
if (!cpu_has_feature(CPU_FTR_SLB)) {
|
||||||
void *tmp;
|
void *tmp;
|
||||||
|
|
|
@ -113,7 +113,6 @@ void ppc64_enable_pmcs(void)
|
||||||
#ifdef CONFIG_PPC_PSERIES
|
#ifdef CONFIG_PPC_PSERIES
|
||||||
unsigned long set, reset;
|
unsigned long set, reset;
|
||||||
int ret;
|
int ret;
|
||||||
unsigned int ctrl;
|
|
||||||
#endif /* CONFIG_PPC_PSERIES */
|
#endif /* CONFIG_PPC_PSERIES */
|
||||||
|
|
||||||
/* Only need to enable them once */
|
/* 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
|
* On SMT machines we have to set the run latch in the ctrl register
|
||||||
* in order to make PMC6 spin.
|
* in order to make PMC6 spin.
|
||||||
*/
|
*/
|
||||||
if (cpu_has_feature(CPU_FTR_SMT)) {
|
if (cpu_has_feature(CPU_FTR_SMT))
|
||||||
ctrl = mfspr(CTRLF);
|
ppc64_runlatch_on();
|
||||||
ctrl |= RUNLATCH;
|
|
||||||
mtspr(CTRLT, ctrl);
|
|
||||||
}
|
|
||||||
#endif /* CONFIG_PPC_PSERIES */
|
#endif /* CONFIG_PPC_PSERIES */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
//#include <linux/kernel_stat.h>
|
//#include <linux/kernel_stat.h>
|
||||||
#include <linux/notifier.h>
|
#include <linux/notifier.h>
|
||||||
#include <linux/cpu.h>
|
#include <linux/cpu.h>
|
||||||
|
#include <linux/workqueue.h>
|
||||||
|
|
||||||
#include "appldata.h"
|
#include "appldata.h"
|
||||||
|
|
||||||
|
@ -133,9 +134,12 @@ static int appldata_interval = APPLDATA_CPU_INTERVAL;
|
||||||
static int appldata_timer_active;
|
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
|
* Ops list
|
||||||
|
@ -144,11 +148,11 @@ static DEFINE_SPINLOCK(appldata_ops_lock);
|
||||||
static LIST_HEAD(appldata_ops_list);
|
static LIST_HEAD(appldata_ops_list);
|
||||||
|
|
||||||
|
|
||||||
/************************* timer, tasklet, DIAG ******************************/
|
/*************************** timer, work, DIAG *******************************/
|
||||||
/*
|
/*
|
||||||
* appldata_timer_function()
|
* 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)
|
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));
|
atomic_read(&appldata_expire_count));
|
||||||
if (atomic_dec_and_test(&appldata_expire_count)) {
|
if (atomic_dec_and_test(&appldata_expire_count)) {
|
||||||
atomic_set(&appldata_expire_count, num_online_cpus());
|
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
|
* 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 list_head *lh;
|
||||||
struct appldata_ops *ops;
|
struct appldata_ops *ops;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
P_DEBUG(" -= Tasklet =-\n");
|
P_DEBUG(" -= Work Queue =-\n");
|
||||||
i = 0;
|
i = 0;
|
||||||
spin_lock(&appldata_ops_lock);
|
spin_lock(&appldata_ops_lock);
|
||||||
list_for_each(lh, &appldata_ops_list) {
|
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");
|
: "=d" (ry) : "d" (&(appldata_parameter_list)) : "cc");
|
||||||
return (int) ry;
|
return (int) ry;
|
||||||
}
|
}
|
||||||
/********************** timer, tasklet, DIAG <END> ***************************/
|
/************************ timer, work, DIAG <END> ****************************/
|
||||||
|
|
||||||
|
|
||||||
/****************************** /proc stuff **********************************/
|
/****************************** /proc stuff **********************************/
|
||||||
|
@ -411,7 +415,7 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp,
|
||||||
struct list_head *lh;
|
struct list_head *lh;
|
||||||
|
|
||||||
found = 0;
|
found = 0;
|
||||||
spin_lock_bh(&appldata_ops_lock);
|
spin_lock(&appldata_ops_lock);
|
||||||
list_for_each(lh, &appldata_ops_list) {
|
list_for_each(lh, &appldata_ops_list) {
|
||||||
tmp_ops = list_entry(lh, struct appldata_ops, list);
|
tmp_ops = list_entry(lh, struct appldata_ops, list);
|
||||||
if (&tmp_ops->ctl_table[2] == ctl) {
|
if (&tmp_ops->ctl_table[2] == ctl) {
|
||||||
|
@ -419,15 +423,15 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
spin_unlock_bh(&appldata_ops_lock);
|
spin_unlock(&appldata_ops_lock);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
ops = ctl->data;
|
ops = ctl->data;
|
||||||
if (!try_module_get(ops->owner)) { // protect this function
|
if (!try_module_get(ops->owner)) { // protect this function
|
||||||
spin_unlock_bh(&appldata_ops_lock);
|
spin_unlock(&appldata_ops_lock);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
spin_unlock_bh(&appldata_ops_lock);
|
spin_unlock(&appldata_ops_lock);
|
||||||
|
|
||||||
if (!*lenp || *ppos) {
|
if (!*lenp || *ppos) {
|
||||||
*lenp = 0;
|
*lenp = 0;
|
||||||
|
@ -451,10 +455,11 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp,
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_lock_bh(&appldata_ops_lock);
|
spin_lock(&appldata_ops_lock);
|
||||||
if ((buf[0] == '1') && (ops->active == 0)) {
|
if ((buf[0] == '1') && (ops->active == 0)) {
|
||||||
if (!try_module_get(ops->owner)) { // protect tasklet
|
// protect work queue callback
|
||||||
spin_unlock_bh(&appldata_ops_lock);
|
if (!try_module_get(ops->owner)) {
|
||||||
|
spin_unlock(&appldata_ops_lock);
|
||||||
module_put(ops->owner);
|
module_put(ops->owner);
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
@ -485,7 +490,7 @@ appldata_generic_handler(ctl_table *ctl, int write, struct file *filp,
|
||||||
}
|
}
|
||||||
module_put(ops->owner);
|
module_put(ops->owner);
|
||||||
}
|
}
|
||||||
spin_unlock_bh(&appldata_ops_lock);
|
spin_unlock(&appldata_ops_lock);
|
||||||
out:
|
out:
|
||||||
*lenp = len;
|
*lenp = len;
|
||||||
*ppos += 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));
|
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) {
|
list_for_each(lh, &appldata_ops_list) {
|
||||||
tmp_ops = list_entry(lh, struct appldata_ops, list);
|
tmp_ops = list_entry(lh, struct appldata_ops, list);
|
||||||
P_DEBUG("register_ops loop: %i) name = %s, ctl = %i\n",
|
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) {
|
APPLDATA_PROC_NAME_LENGTH) == 0) {
|
||||||
P_ERROR("Name \"%s\" already registered!\n", ops->name);
|
P_ERROR("Name \"%s\" already registered!\n", ops->name);
|
||||||
kfree(ops->ctl_table);
|
kfree(ops->ctl_table);
|
||||||
spin_unlock_bh(&appldata_ops_lock);
|
spin_unlock(&appldata_ops_lock);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
if (tmp_ops->ctl_nr == ops->ctl_nr) {
|
if (tmp_ops->ctl_nr == ops->ctl_nr) {
|
||||||
P_ERROR("ctl_nr %i already registered!\n", ops->ctl_nr);
|
P_ERROR("ctl_nr %i already registered!\n", ops->ctl_nr);
|
||||||
kfree(ops->ctl_table);
|
kfree(ops->ctl_table);
|
||||||
spin_unlock_bh(&appldata_ops_lock);
|
spin_unlock(&appldata_ops_lock);
|
||||||
return -EBUSY;
|
return -EBUSY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
list_add(&ops->list, &appldata_ops_list);
|
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].ctl_name = CTL_APPLDATA;
|
||||||
ops->ctl_table[0].procname = appldata_proc_name;
|
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)
|
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);
|
unregister_sysctl_table(ops->sysctl_header);
|
||||||
list_del(&ops->list);
|
list_del(&ops->list);
|
||||||
kfree(ops->ctl_table);
|
kfree(ops->ctl_table);
|
||||||
ops->ctl_table = NULL;
|
ops->ctl_table = NULL;
|
||||||
spin_unlock_bh(&appldata_ops_lock);
|
spin_unlock(&appldata_ops_lock);
|
||||||
P_INFO("%s-ops unregistered!\n", ops->name);
|
P_INFO("%s-ops unregistered!\n", ops->name);
|
||||||
}
|
}
|
||||||
/********************** module-ops management <END> **************************/
|
/********************** module-ops management <END> **************************/
|
||||||
|
@ -602,7 +607,7 @@ appldata_online_cpu(int cpu)
|
||||||
init_virt_timer(&per_cpu(appldata_timer, cpu));
|
init_virt_timer(&per_cpu(appldata_timer, cpu));
|
||||||
per_cpu(appldata_timer, cpu).function = appldata_timer_function;
|
per_cpu(appldata_timer, cpu).function = appldata_timer_function;
|
||||||
per_cpu(appldata_timer, cpu).data = (unsigned long)
|
per_cpu(appldata_timer, cpu).data = (unsigned long)
|
||||||
&appldata_tasklet_struct;
|
&appldata_work;
|
||||||
atomic_inc(&appldata_expire_count);
|
atomic_inc(&appldata_expire_count);
|
||||||
spin_lock(&appldata_timer_lock);
|
spin_lock(&appldata_timer_lock);
|
||||||
__appldata_vtimer_setup(APPLDATA_MOD_TIMER);
|
__appldata_vtimer_setup(APPLDATA_MOD_TIMER);
|
||||||
|
@ -615,7 +620,7 @@ appldata_offline_cpu(int cpu)
|
||||||
del_virt_timer(&per_cpu(appldata_timer, cpu));
|
del_virt_timer(&per_cpu(appldata_timer, cpu));
|
||||||
if (atomic_dec_and_test(&appldata_expire_count)) {
|
if (atomic_dec_and_test(&appldata_expire_count)) {
|
||||||
atomic_set(&appldata_expire_count, num_online_cpus());
|
atomic_set(&appldata_expire_count, num_online_cpus());
|
||||||
tasklet_schedule(&appldata_tasklet_struct);
|
queue_work(appldata_wq, &appldata_work);
|
||||||
}
|
}
|
||||||
spin_lock(&appldata_timer_lock);
|
spin_lock(&appldata_timer_lock);
|
||||||
__appldata_vtimer_setup(APPLDATA_MOD_TIMER);
|
__appldata_vtimer_setup(APPLDATA_MOD_TIMER);
|
||||||
|
@ -648,7 +653,7 @@ static struct notifier_block __devinitdata appldata_nb = {
|
||||||
/*
|
/*
|
||||||
* appldata_init()
|
* appldata_init()
|
||||||
*
|
*
|
||||||
* init timer and tasklet, register /proc entries
|
* init timer, register /proc entries
|
||||||
*/
|
*/
|
||||||
static int __init appldata_init(void)
|
static int __init appldata_init(void)
|
||||||
{
|
{
|
||||||
|
@ -657,6 +662,12 @@ static int __init appldata_init(void)
|
||||||
P_DEBUG("sizeof(parameter_list) = %lu\n",
|
P_DEBUG("sizeof(parameter_list) = %lu\n",
|
||||||
sizeof(struct appldata_parameter_list));
|
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)
|
for_each_online_cpu(i)
|
||||||
appldata_online_cpu(i);
|
appldata_online_cpu(i);
|
||||||
|
|
||||||
|
@ -670,7 +681,6 @@ static int __init appldata_init(void)
|
||||||
appldata_table[1].de->owner = THIS_MODULE;
|
appldata_table[1].de->owner = THIS_MODULE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
tasklet_init(&appldata_tasklet_struct, appldata_tasklet_function, 0);
|
|
||||||
P_DEBUG("Base interface initialized.\n");
|
P_DEBUG("Base interface initialized.\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -678,7 +688,7 @@ static int __init appldata_init(void)
|
||||||
/*
|
/*
|
||||||
* appldata_exit()
|
* appldata_exit()
|
||||||
*
|
*
|
||||||
* stop timer and tasklet, unregister /proc entries
|
* stop timer, unregister /proc entries
|
||||||
*/
|
*/
|
||||||
static void __exit appldata_exit(void)
|
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...
|
* 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) {
|
list_for_each(lh, &appldata_ops_list) {
|
||||||
ops = list_entry(lh, struct appldata_ops, list);
|
ops = list_entry(lh, struct appldata_ops, list);
|
||||||
rc = appldata_diag(ops->record_nr, APPLDATA_STOP_REC,
|
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);
|
"return code: %d\n", ops->name, rc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock_bh(&appldata_ops_lock);
|
spin_unlock(&appldata_ops_lock);
|
||||||
|
|
||||||
for_each_online_cpu(i)
|
for_each_online_cpu(i)
|
||||||
appldata_offline_cpu(i);
|
appldata_offline_cpu(i);
|
||||||
|
@ -709,7 +719,7 @@ static void __exit appldata_exit(void)
|
||||||
|
|
||||||
unregister_sysctl_table(appldata_sysctl_header);
|
unregister_sysctl_table(appldata_sysctl_header);
|
||||||
|
|
||||||
tasklet_kill(&appldata_tasklet_struct);
|
destroy_workqueue(appldata_wq);
|
||||||
P_DEBUG("... module unloaded!\n");
|
P_DEBUG("... module unloaded!\n");
|
||||||
}
|
}
|
||||||
/**************************** init / exit <END> ******************************/
|
/**************************** init / exit <END> ******************************/
|
||||||
|
|
|
@ -68,7 +68,7 @@ struct appldata_mem_data {
|
||||||
u64 pgmajfault; /* page faults (major only) */
|
u64 pgmajfault; /* page faults (major only) */
|
||||||
// <-- New in 2.6
|
// <-- New in 2.6
|
||||||
|
|
||||||
} appldata_mem_data;
|
} __attribute__((packed)) appldata_mem_data;
|
||||||
|
|
||||||
|
|
||||||
static inline void appldata_debug_print(struct appldata_mem_data *mem_data)
|
static inline void appldata_debug_print(struct appldata_mem_data *mem_data)
|
||||||
|
|
|
@ -57,7 +57,7 @@ struct appldata_net_sum_data {
|
||||||
u64 rx_dropped; /* no space in linux buffers */
|
u64 rx_dropped; /* no space in linux buffers */
|
||||||
u64 tx_dropped; /* no space available in linux */
|
u64 tx_dropped; /* no space available in linux */
|
||||||
u64 collisions; /* collisions while transmitting */
|
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)
|
static inline void appldata_print_debug(struct appldata_net_sum_data *net_data)
|
||||||
|
|
|
@ -49,7 +49,7 @@ struct appldata_os_per_cpu {
|
||||||
u32 per_cpu_softirq; /* ... spent in softirqs */
|
u32 per_cpu_softirq; /* ... spent in softirqs */
|
||||||
u32 per_cpu_iowait; /* ... spent while waiting for I/O */
|
u32 per_cpu_iowait; /* ... spent while waiting for I/O */
|
||||||
// <-- New in 2.6
|
// <-- New in 2.6
|
||||||
};
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct appldata_os_data {
|
struct appldata_os_data {
|
||||||
u64 timestamp;
|
u64 timestamp;
|
||||||
|
@ -75,7 +75,7 @@ struct appldata_os_data {
|
||||||
|
|
||||||
/* per cpu data */
|
/* per cpu data */
|
||||||
struct appldata_os_per_cpu os_cpu[0];
|
struct appldata_os_per_cpu os_cpu[0];
|
||||||
};
|
} __attribute__((packed));
|
||||||
|
|
||||||
static struct appldata_os_data *appldata_os_data;
|
static struct appldata_os_data *appldata_os_data;
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include <asm/pgalloc.h>
|
#include <asm/pgalloc.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
|
#include <asm/unistd.h>
|
||||||
|
|
||||||
#ifdef CONFIG_S390_SUPPORT
|
#ifdef CONFIG_S390_SUPPORT
|
||||||
#include "compat_ptrace.h"
|
#include "compat_ptrace.h"
|
||||||
|
@ -130,13 +131,19 @@ static int
|
||||||
peek_user(struct task_struct *child, addr_t addr, addr_t data)
|
peek_user(struct task_struct *child, addr_t addr, addr_t data)
|
||||||
{
|
{
|
||||||
struct user *dummy = NULL;
|
struct user *dummy = NULL;
|
||||||
addr_t offset, tmp;
|
addr_t offset, tmp, mask;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Stupid gdb peeks/pokes the access registers in 64 bit with
|
* Stupid gdb peeks/pokes the access registers in 64 bit with
|
||||||
* an alignment of 4. Programmers from hell...
|
* 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;
|
return -EIO;
|
||||||
|
|
||||||
if (addr < (addr_t) &dummy->regs.acrs) {
|
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
|
* access registers are stored in the thread structure
|
||||||
*/
|
*/
|
||||||
offset = addr - (addr_t) &dummy->regs.acrs;
|
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);
|
tmp = *(addr_t *)((addr_t) &child->thread.acrs + offset);
|
||||||
|
|
||||||
} else if (addr == (addr_t) &dummy->regs.orig_gpr2) {
|
} 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;
|
offset = addr - (addr_t) &dummy->regs.fp_regs;
|
||||||
tmp = *(addr_t *)((addr_t) &child->thread.fp_regs + offset);
|
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)) {
|
} 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)
|
poke_user(struct task_struct *child, addr_t addr, addr_t data)
|
||||||
{
|
{
|
||||||
struct user *dummy = NULL;
|
struct user *dummy = NULL;
|
||||||
addr_t offset;
|
addr_t offset, mask;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Stupid gdb peeks/pokes the access registers in 64 bit with
|
* Stupid gdb peeks/pokes the access registers in 64 bit with
|
||||||
* an alignment of 4. Programmers from hell indeed...
|
* 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;
|
return -EIO;
|
||||||
|
|
||||||
if (addr < (addr_t) &dummy->regs.acrs) {
|
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
|
* access registers are stored in the thread structure
|
||||||
*/
|
*/
|
||||||
offset = addr - (addr_t) &dummy->regs.acrs;
|
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;
|
*(addr_t *)((addr_t) &child->thread.acrs + offset) = data;
|
||||||
|
|
||||||
} else if (addr == (addr_t) &dummy->regs.orig_gpr2) {
|
} 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
|
* floating point regs. are stored in the thread structure
|
||||||
*/
|
*/
|
||||||
if (addr == (addr_t) &dummy->regs.fp_regs.fpc &&
|
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;
|
return -EINVAL;
|
||||||
offset = addr - (addr_t) &dummy->regs.fp_regs;
|
offset = addr - (addr_t) &dummy->regs.fp_regs;
|
||||||
*(addr_t *)((addr_t) &child->thread.fp_regs + offset) = data;
|
*(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)
|
ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
|
||||||
? 0x80 : 0));
|
? 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
|
* 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
|
* for normal use. strace only continues with a signal if the
|
||||||
|
|
|
@ -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
|
* we are not in an interrupt and that there is a
|
||||||
* user context.
|
* user context.
|
||||||
*/
|
*/
|
||||||
if (user_address == 0 || in_interrupt() || !mm)
|
if (user_address == 0 || in_atomic() || !mm)
|
||||||
goto no_context;
|
goto no_context;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -196,6 +196,34 @@ static iopte_t *alloc_consistent_cluster(struct pci_iommu *iommu, unsigned long
|
||||||
return NULL;
|
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
|
/* Allocate and map kernel buffer of size SIZE using consistent mode
|
||||||
* DMA for PCI device PDEV. Return non-NULL cpu-side address if
|
* DMA for PCI device PDEV. Return non-NULL cpu-side address if
|
||||||
* successful and set *DMA_ADDRP to the PCI side dma address.
|
* 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;
|
npages = size >> IO_PAGE_SHIFT;
|
||||||
ctx = 0;
|
ctx = 0;
|
||||||
if (iommu->iommu_ctxflush)
|
if (iommu->iommu_ctxflush)
|
||||||
ctx = iommu->iommu_cur_ctx++;
|
ctx = iommu_alloc_ctx(iommu);
|
||||||
first_page = __pa(first_page);
|
first_page = __pa(first_page);
|
||||||
while (npages--) {
|
while (npages--) {
|
||||||
iopte_val(*iopte) = (IOPTE_CONSISTENT(ctx) |
|
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);
|
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||||
|
|
||||||
order = get_order(size);
|
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);
|
base_paddr = __pa(oaddr & IO_PAGE_MASK);
|
||||||
ctx = 0;
|
ctx = 0;
|
||||||
if (iommu->iommu_ctxflush)
|
if (iommu->iommu_ctxflush)
|
||||||
ctx = iommu->iommu_cur_ctx++;
|
ctx = iommu_alloc_ctx(iommu);
|
||||||
if (strbuf->strbuf_enabled)
|
if (strbuf->strbuf_enabled)
|
||||||
iopte_protection = IOPTE_STREAMING(ctx);
|
iopte_protection = IOPTE_STREAMING(ctx);
|
||||||
else
|
else
|
||||||
|
@ -380,39 +410,53 @@ bad:
|
||||||
return PCI_DMA_ERROR_CODE;
|
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;
|
int limit;
|
||||||
|
|
||||||
PCI_STC_FLUSHFLAG_INIT(strbuf);
|
|
||||||
if (strbuf->strbuf_ctxflush &&
|
if (strbuf->strbuf_ctxflush &&
|
||||||
iommu->iommu_ctxflush) {
|
iommu->iommu_ctxflush) {
|
||||||
unsigned long matchreg, flushreg;
|
unsigned long matchreg, flushreg;
|
||||||
|
u64 val;
|
||||||
|
|
||||||
flushreg = strbuf->strbuf_ctxflush;
|
flushreg = strbuf->strbuf_ctxflush;
|
||||||
matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
|
matchreg = PCI_STC_CTXMATCH_ADDR(strbuf, ctx);
|
||||||
|
|
||||||
limit = 100000;
|
|
||||||
pci_iommu_write(flushreg, ctx);
|
pci_iommu_write(flushreg, ctx);
|
||||||
for(;;) {
|
val = pci_iommu_read(matchreg);
|
||||||
if (((long)pci_iommu_read(matchreg)) >= 0L)
|
val &= 0xffff;
|
||||||
break;
|
if (!val)
|
||||||
limit--;
|
goto do_flush_sync;
|
||||||
if (!limit)
|
|
||||||
break;
|
while (val) {
|
||||||
udelay(1);
|
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 "
|
printk(KERN_WARNING "pci_strbuf_flush: ctx flush "
|
||||||
"timeout vaddr[%08x] ctx[%lx]\n",
|
"timeout matchreg[%lx] ctx[%lx]\n",
|
||||||
vaddr, ctx);
|
val, ctx);
|
||||||
|
goto do_page_flush;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
|
|
||||||
|
do_page_flush:
|
||||||
for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE)
|
for (i = 0; i < npages; i++, vaddr += IO_PAGE_SIZE)
|
||||||
pci_iommu_write(strbuf->strbuf_pflush, vaddr);
|
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);
|
pci_iommu_write(strbuf->strbuf_fsync, strbuf->strbuf_flushflag_pa);
|
||||||
(void) pci_iommu_read(iommu->write_complete_reg);
|
(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. */
|
/* Step 1: Kick data out of streaming buffers if necessary. */
|
||||||
if (strbuf->strbuf_enabled)
|
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. */
|
/* Step 2: Clear out first TSB entry. */
|
||||||
iopte_make_dummy(iommu, base);
|
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,
|
free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base,
|
||||||
npages, ctx);
|
npages, ctx);
|
||||||
|
|
||||||
|
iommu_free_ctx(iommu, ctx);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
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. */
|
/* Step 4: Choose a context if necessary. */
|
||||||
ctx = 0;
|
ctx = 0;
|
||||||
if (iommu->iommu_ctxflush)
|
if (iommu->iommu_ctxflush)
|
||||||
ctx = iommu->iommu_cur_ctx++;
|
ctx = iommu_alloc_ctx(iommu);
|
||||||
|
|
||||||
/* Step 5: Create the mappings. */
|
/* Step 5: Create the mappings. */
|
||||||
if (strbuf->strbuf_enabled)
|
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. */
|
/* Step 1: Kick data out of streaming buffers if necessary. */
|
||||||
if (strbuf->strbuf_enabled)
|
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. */
|
/* Step 2: Clear out first TSB entry. */
|
||||||
iopte_make_dummy(iommu, base);
|
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,
|
free_streaming_cluster(iommu, bus_addr - iommu->page_table_map_base,
|
||||||
npages, ctx);
|
npages, ctx);
|
||||||
|
|
||||||
|
iommu_free_ctx(iommu, ctx);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&iommu->lock, flags);
|
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. */
|
/* 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);
|
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--;
|
i--;
|
||||||
npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length)
|
npages = (IO_PAGE_ALIGN(sglist[i].dma_address + sglist[i].dma_length)
|
||||||
- bus_addr) >> IO_PAGE_SHIFT;
|
- 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);
|
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1212,7 +1212,7 @@ static void __init psycho_iommu_init(struct pci_controller_info *p)
|
||||||
|
|
||||||
/* Setup initial software IOMMU state. */
|
/* Setup initial software IOMMU state. */
|
||||||
spin_lock_init(&iommu->lock);
|
spin_lock_init(&iommu->lock);
|
||||||
iommu->iommu_cur_ctx = 0;
|
iommu->ctx_lowest_free = 1;
|
||||||
|
|
||||||
/* Register addresses. */
|
/* Register addresses. */
|
||||||
iommu->iommu_control = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL;
|
iommu->iommu_control = p->pbm_A.controller_regs + PSYCHO_IOMMU_CONTROL;
|
||||||
|
|
|
@ -1265,7 +1265,7 @@ static void __init sabre_iommu_init(struct pci_controller_info *p,
|
||||||
|
|
||||||
/* Setup initial software IOMMU state. */
|
/* Setup initial software IOMMU state. */
|
||||||
spin_lock_init(&iommu->lock);
|
spin_lock_init(&iommu->lock);
|
||||||
iommu->iommu_cur_ctx = 0;
|
iommu->ctx_lowest_free = 1;
|
||||||
|
|
||||||
/* Register addresses. */
|
/* Register addresses. */
|
||||||
iommu->iommu_control = p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL;
|
iommu->iommu_control = p->pbm_A.controller_regs + SABRE_IOMMU_CONTROL;
|
||||||
|
|
|
@ -1753,7 +1753,7 @@ static void schizo_pbm_iommu_init(struct pci_pbm_info *pbm)
|
||||||
|
|
||||||
/* Setup initial software IOMMU state. */
|
/* Setup initial software IOMMU state. */
|
||||||
spin_lock_init(&iommu->lock);
|
spin_lock_init(&iommu->lock);
|
||||||
iommu->iommu_cur_ctx = 0;
|
iommu->ctx_lowest_free = 1;
|
||||||
|
|
||||||
/* Register addresses, SCHIZO has iommu ctx flushing. */
|
/* Register addresses, SCHIZO has iommu ctx flushing. */
|
||||||
iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL;
|
iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL;
|
||||||
|
|
|
@ -117,17 +117,25 @@ static void iommu_flush(struct sbus_iommu *iommu, u32 base, unsigned long npages
|
||||||
|
|
||||||
#define STRBUF_TAG_VALID 0x02UL
|
#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;
|
unsigned long n;
|
||||||
int limit;
|
int limit;
|
||||||
|
|
||||||
iommu->strbuf_flushflag = 0UL;
|
|
||||||
n = npages;
|
n = npages;
|
||||||
while (n--)
|
while (n--)
|
||||||
upa_writeq(base + (n << IO_PAGE_SHIFT),
|
upa_writeq(base + (n << IO_PAGE_SHIFT),
|
||||||
iommu->strbuf_regs + STRBUF_PFLUSH);
|
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! */
|
/* Whoopee cushion! */
|
||||||
upa_writeq(__pa(&iommu->strbuf_flushflag),
|
upa_writeq(__pa(&iommu->strbuf_flushflag),
|
||||||
iommu->strbuf_regs + STRBUF_FSYNC);
|
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);
|
spin_lock_irqsave(&iommu->lock, flags);
|
||||||
free_streaming_cluster(iommu, dma_base, size >> IO_PAGE_SHIFT);
|
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);
|
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;
|
iommu = sdev->bus->iommu;
|
||||||
spin_lock_irqsave(&iommu->lock, flags);
|
spin_lock_irqsave(&iommu->lock, flags);
|
||||||
free_streaming_cluster(iommu, dvma_base, size >> IO_PAGE_SHIFT);
|
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);
|
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));
|
size = (IO_PAGE_ALIGN(base + size) - (base & IO_PAGE_MASK));
|
||||||
|
|
||||||
spin_lock_irqsave(&iommu->lock, flags);
|
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);
|
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;
|
size = IO_PAGE_ALIGN(sg[i].dma_address + sg[i].dma_length) - base;
|
||||||
|
|
||||||
spin_lock_irqsave(&iommu->lock, flags);
|
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);
|
spin_unlock_irqrestore(&iommu->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,8 @@ ifeq ($(CONFIG_ATM_FORE200E_PCA),y)
|
||||||
fore_200e-objs += fore200e_pca_fw.o
|
fore_200e-objs += fore200e_pca_fw.o
|
||||||
# guess the target endianess to choose the right PCA-200E firmware image
|
# guess the target endianess to choose the right PCA-200E firmware image
|
||||||
ifeq ($(CONFIG_ATM_FORE200E_PCA_DEFAULT_FW),y)
|
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
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -383,7 +383,6 @@ fore200e_shutdown(struct fore200e* fore200e)
|
||||||
switch(fore200e->state) {
|
switch(fore200e->state) {
|
||||||
|
|
||||||
case FORE200E_STATE_COMPLETE:
|
case FORE200E_STATE_COMPLETE:
|
||||||
if (fore200e->stats)
|
|
||||||
kfree(fore200e->stats);
|
kfree(fore200e->stats);
|
||||||
|
|
||||||
case FORE200E_STATE_IRQ:
|
case FORE200E_STATE_IRQ:
|
||||||
|
@ -963,7 +962,6 @@ fore200e_tx_irq(struct fore200e* fore200e)
|
||||||
entry, txq->tail, entry->vc_map, entry->skb);
|
entry, txq->tail, entry->vc_map, entry->skb);
|
||||||
|
|
||||||
/* free copy of misaligned data */
|
/* free copy of misaligned data */
|
||||||
if (entry->data)
|
|
||||||
kfree(entry->data);
|
kfree(entry->data);
|
||||||
|
|
||||||
/* remove DMA mapping */
|
/* remove DMA mapping */
|
||||||
|
|
|
@ -412,7 +412,6 @@ he_init_one(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent)
|
||||||
init_one_failure:
|
init_one_failure:
|
||||||
if (atm_dev)
|
if (atm_dev)
|
||||||
atm_dev_deregister(atm_dev);
|
atm_dev_deregister(atm_dev);
|
||||||
if (he_dev)
|
|
||||||
kfree(he_dev);
|
kfree(he_dev);
|
||||||
pci_disable_device(pci_dev);
|
pci_disable_device(pci_dev);
|
||||||
return err;
|
return err;
|
||||||
|
@ -2534,7 +2533,6 @@ he_open(struct atm_vcc *vcc)
|
||||||
open_failed:
|
open_failed:
|
||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
if (he_vcc)
|
|
||||||
kfree(he_vcc);
|
kfree(he_vcc);
|
||||||
clear_bit(ATM_VF_ADDR, &vcc->flags);
|
clear_bit(ATM_VF_ADDR, &vcc->flags);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
PRINTK("nicstar%d: RSQ base at 0x%x.\n", i, (u32) card->rsq.base);
|
||||||
|
|
||||||
/* Initialize SCQ0, the only VBR SCQ used */
|
/* Initialize SCQ0, the only VBR SCQ used */
|
||||||
card->scq1 = (scq_info *) NULL;
|
card->scq1 = NULL;
|
||||||
card->scq2 = (scq_info *) NULL;
|
card->scq2 = NULL;
|
||||||
card->scq0 = get_scq(VBR_SCQSIZE, NS_VRSCD0);
|
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);
|
printk("nicstar%d: can't get SCQ0.\n", i);
|
||||||
error = 12;
|
error = 12;
|
||||||
|
@ -993,24 +993,24 @@ static scq_info *get_scq(int size, u32 scd)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (size != VBR_SCQSIZE && size != CBR_SCQSIZE)
|
if (size != VBR_SCQSIZE && size != CBR_SCQSIZE)
|
||||||
return (scq_info *) NULL;
|
return NULL;
|
||||||
|
|
||||||
scq = (scq_info *) kmalloc(sizeof(scq_info), GFP_KERNEL);
|
scq = (scq_info *) kmalloc(sizeof(scq_info), GFP_KERNEL);
|
||||||
if (scq == (scq_info *) NULL)
|
if (scq == NULL)
|
||||||
return (scq_info *) NULL;
|
return NULL;
|
||||||
scq->org = kmalloc(2 * size, GFP_KERNEL);
|
scq->org = kmalloc(2 * size, GFP_KERNEL);
|
||||||
if (scq->org == NULL)
|
if (scq->org == NULL)
|
||||||
{
|
{
|
||||||
kfree(scq);
|
kfree(scq);
|
||||||
return (scq_info *) NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
scq->skb = (struct sk_buff **) kmalloc(sizeof(struct sk_buff *) *
|
scq->skb = (struct sk_buff **) kmalloc(sizeof(struct sk_buff *) *
|
||||||
(size / NS_SCQE_SIZE), GFP_KERNEL);
|
(size / NS_SCQE_SIZE), GFP_KERNEL);
|
||||||
if (scq->skb == (struct sk_buff **) NULL)
|
if (scq->skb == NULL)
|
||||||
{
|
{
|
||||||
kfree(scq->org);
|
kfree(scq->org);
|
||||||
kfree(scq);
|
kfree(scq);
|
||||||
return (scq_info *) NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
scq->num_entries = size / NS_SCQE_SIZE;
|
scq->num_entries = size / NS_SCQE_SIZE;
|
||||||
scq->base = (ns_scqe *) ALIGN_ADDRESS(scq->org, 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;
|
vc->cbr_scd = NS_FRSCD + frscdi * NS_FRSCD_SIZE;
|
||||||
|
|
||||||
scq = get_scq(CBR_SCQSIZE, vc->cbr_scd);
|
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);
|
PRINTK("nicstar%d: can't get fixed rate SCQ.\n", card->index);
|
||||||
card->scd2vc[frscdi] = NULL;
|
card->scd2vc[frscdi] = NULL;
|
||||||
|
|
|
@ -902,7 +902,7 @@ static void close_tx(struct atm_vcc *vcc)
|
||||||
zatm_dev->tx_bw += vcc->qos.txtp.min_pcr;
|
zatm_dev->tx_bw += vcc->qos.txtp.min_pcr;
|
||||||
dealloc_shaper(vcc->dev,zatm_vcc->shaper);
|
dealloc_shaper(vcc->dev,zatm_vcc->shaper);
|
||||||
}
|
}
|
||||||
if (zatm_vcc->ring) kfree(zatm_vcc->ring);
|
kfree(zatm_vcc->ring);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1339,11 +1339,8 @@ static int __init zatm_start(struct atm_dev *dev)
|
||||||
return 0;
|
return 0;
|
||||||
out:
|
out:
|
||||||
for (i = 0; i < NR_MBX; i++)
|
for (i = 0; i < NR_MBX; i++)
|
||||||
if (zatm_dev->mbx_start[i] != 0)
|
kfree(zatm_dev->mbx_start[i]);
|
||||||
kfree((void *) zatm_dev->mbx_start[i]);
|
|
||||||
if (zatm_dev->rx_map != NULL)
|
|
||||||
kfree(zatm_dev->rx_map);
|
kfree(zatm_dev->rx_map);
|
||||||
if (zatm_dev->tx_map != NULL)
|
|
||||||
kfree(zatm_dev->tx_map);
|
kfree(zatm_dev->tx_map);
|
||||||
free_irq(zatm_dev->irq, dev);
|
free_irq(zatm_dev->irq, dev);
|
||||||
return error;
|
return error;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,6 +2,7 @@
|
||||||
* i2c-ali1563.c - i2c driver for the ALi 1563 Southbridge
|
* i2c-ali1563.c - i2c driver for the ALi 1563 Southbridge
|
||||||
*
|
*
|
||||||
* Copyright (C) 2004 Patrick Mochel
|
* Copyright (C) 2004 Patrick Mochel
|
||||||
|
* 2005 Rudolf Marek <r.marek@sh.cvut.cz>
|
||||||
*
|
*
|
||||||
* The 1563 southbridge is deceptively similar to the 1533, with a
|
* The 1563 southbridge is deceptively similar to the 1533, with a
|
||||||
* few notable exceptions. One of those happens to be the fact they
|
* few notable exceptions. One of those happens to be the fact they
|
||||||
|
@ -57,10 +58,11 @@
|
||||||
#define HST_CNTL2_BLOCK 0x05
|
#define HST_CNTL2_BLOCK 0x05
|
||||||
|
|
||||||
|
|
||||||
|
#define HST_CNTL2_SIZEMASK 0x38
|
||||||
|
|
||||||
static unsigned short ali1563_smba;
|
static unsigned short ali1563_smba;
|
||||||
|
|
||||||
static int ali1563_transaction(struct i2c_adapter * a)
|
static int ali1563_transaction(struct i2c_adapter * a, int size)
|
||||||
{
|
{
|
||||||
u32 data;
|
u32 data;
|
||||||
int timeout;
|
int timeout;
|
||||||
|
@ -73,7 +75,7 @@ static int ali1563_transaction(struct i2c_adapter * a)
|
||||||
|
|
||||||
data = inb_p(SMB_HST_STS);
|
data = inb_p(SMB_HST_STS);
|
||||||
if (data & HST_STS_BAD) {
|
if (data & HST_STS_BAD) {
|
||||||
dev_warn(&a->dev,"ali1563: Trying to reset busy device\n");
|
dev_err(&a->dev, "ali1563: Trying to reset busy device\n");
|
||||||
outb_p(data | HST_STS_BAD,SMB_HST_STS);
|
outb_p(data | HST_STS_BAD,SMB_HST_STS);
|
||||||
data = inb_p(SMB_HST_STS);
|
data = inb_p(SMB_HST_STS);
|
||||||
if (data & HST_STS_BAD)
|
if (data & HST_STS_BAD)
|
||||||
|
@ -94,19 +96,31 @@ static int ali1563_transaction(struct i2c_adapter * a)
|
||||||
|
|
||||||
if (timeout && !(data & HST_STS_BAD))
|
if (timeout && !(data & HST_STS_BAD))
|
||||||
return 0;
|
return 0;
|
||||||
dev_warn(&a->dev, "SMBus Error: %s%s%s%s%s\n",
|
|
||||||
timeout ? "Timeout " : "",
|
|
||||||
data & HST_STS_FAIL ? "Transaction Failed " : "",
|
|
||||||
data & HST_STS_BUSERR ? "No response or Bus Collision " : "",
|
|
||||||
data & HST_STS_DEVERR ? "Device Error " : "",
|
|
||||||
!(data & HST_STS_DONE) ? "Transaction Never Finished " : "");
|
|
||||||
|
|
||||||
if (!(data & HST_STS_DONE))
|
if (!timeout) {
|
||||||
|
dev_err(&a->dev, "Timeout - Trying to KILL transaction!\n");
|
||||||
/* Issue 'kill' to host controller */
|
/* Issue 'kill' to host controller */
|
||||||
outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2);
|
outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2);
|
||||||
else
|
data = inb_p(SMB_HST_STS);
|
||||||
/* Issue timeout to reset all devices on bus */
|
}
|
||||||
|
|
||||||
|
/* device error - no response, ignore the autodetection case */
|
||||||
|
if ((data & HST_STS_DEVERR) && (size != HST_CNTL2_QUICK)) {
|
||||||
|
dev_err(&a->dev, "Device error!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* bus collision */
|
||||||
|
if (data & HST_STS_BUSERR) {
|
||||||
|
dev_err(&a->dev, "Bus collision!\n");
|
||||||
|
/* Issue timeout, hoping it helps */
|
||||||
outb_p(HST_CNTL1_TIMEOUT,SMB_HST_CNTL1);
|
outb_p(HST_CNTL1_TIMEOUT,SMB_HST_CNTL1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data & HST_STS_FAIL) {
|
||||||
|
dev_err(&a->dev, "Cleaning fail after KILL!\n");
|
||||||
|
outb_p(0x0,SMB_HST_CNTL2);
|
||||||
|
}
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +163,7 @@ static int ali1563_block_start(struct i2c_adapter * a)
|
||||||
|
|
||||||
if (timeout && !(data & HST_STS_BAD))
|
if (timeout && !(data & HST_STS_BAD))
|
||||||
return 0;
|
return 0;
|
||||||
dev_warn(&a->dev, "SMBus Error: %s%s%s%s%s\n",
|
dev_err(&a->dev, "SMBus Error: %s%s%s%s%s\n",
|
||||||
timeout ? "Timeout " : "",
|
timeout ? "Timeout " : "",
|
||||||
data & HST_STS_FAIL ? "Transaction Failed " : "",
|
data & HST_STS_FAIL ? "Transaction Failed " : "",
|
||||||
data & HST_STS_BUSERR ? "No response or Bus Collision " : "",
|
data & HST_STS_BUSERR ? "No response or Bus Collision " : "",
|
||||||
|
@ -242,13 +256,15 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
|
||||||
}
|
}
|
||||||
|
|
||||||
outb_p(((addr & 0x7f) << 1) | (rw & 0x01), SMB_HST_ADD);
|
outb_p(((addr & 0x7f) << 1) | (rw & 0x01), SMB_HST_ADD);
|
||||||
outb_p(inb_p(SMB_HST_CNTL2) | (size << 3), SMB_HST_CNTL2);
|
outb_p((inb_p(SMB_HST_CNTL2) & ~HST_CNTL2_SIZEMASK) | (size << 3), SMB_HST_CNTL2);
|
||||||
|
|
||||||
/* Write the command register */
|
/* Write the command register */
|
||||||
|
|
||||||
switch(size) {
|
switch(size) {
|
||||||
case HST_CNTL2_BYTE:
|
case HST_CNTL2_BYTE:
|
||||||
if (rw== I2C_SMBUS_WRITE)
|
if (rw== I2C_SMBUS_WRITE)
|
||||||
outb_p(cmd, SMB_HST_CMD);
|
/* Beware it uses DAT0 register and not CMD! */
|
||||||
|
outb_p(cmd, SMB_HST_DAT0);
|
||||||
break;
|
break;
|
||||||
case HST_CNTL2_BYTE_DATA:
|
case HST_CNTL2_BYTE_DATA:
|
||||||
outb_p(cmd, SMB_HST_CMD);
|
outb_p(cmd, SMB_HST_CMD);
|
||||||
|
@ -268,7 +284,7 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
|
||||||
goto Done;
|
goto Done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((error = ali1563_transaction(a)))
|
if ((error = ali1563_transaction(a, size)))
|
||||||
goto Done;
|
goto Done;
|
||||||
|
|
||||||
if ((rw == I2C_SMBUS_WRITE) || (size == HST_CNTL2_QUICK))
|
if ((rw == I2C_SMBUS_WRITE) || (size == HST_CNTL2_QUICK))
|
||||||
|
|
|
@ -72,6 +72,7 @@ static struct amd_ide_chip {
|
||||||
{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, 0x50, AMD_UDMA_133 },
|
{ PCI_DEVICE_ID_NVIDIA_NFORCE3S_SATA2, 0x50, AMD_UDMA_133 },
|
||||||
{ PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, 0x50, AMD_UDMA_133 },
|
{ PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, 0x50, AMD_UDMA_133 },
|
||||||
{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, 0x50, AMD_UDMA_133 },
|
{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, 0x50, AMD_UDMA_133 },
|
||||||
|
{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, 0x50, AMD_UDMA_133 },
|
||||||
{ 0 }
|
{ 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -487,6 +488,7 @@ static ide_pci_device_t amd74xx_chipsets[] __devinitdata = {
|
||||||
/* 12 */ DECLARE_NV_DEV("NFORCE3-250-SATA2"),
|
/* 12 */ DECLARE_NV_DEV("NFORCE3-250-SATA2"),
|
||||||
/* 13 */ DECLARE_NV_DEV("NFORCE-CK804"),
|
/* 13 */ DECLARE_NV_DEV("NFORCE-CK804"),
|
||||||
/* 14 */ DECLARE_NV_DEV("NFORCE-MCP04"),
|
/* 14 */ DECLARE_NV_DEV("NFORCE-MCP04"),
|
||||||
|
/* 15 */ DECLARE_NV_DEV("NFORCE-MCP51"),
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||||
|
@ -521,6 +523,7 @@ static struct pci_device_id amd74xx_pci_tbl[] = {
|
||||||
#endif
|
#endif
|
||||||
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13 },
|
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_CK804_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 13 },
|
||||||
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 },
|
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP04_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 14 },
|
||||||
|
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 15 },
|
||||||
{ 0, },
|
{ 0, },
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
|
MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
|
||||||
|
|
|
@ -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)
|
static void encode_hdlc(struct baycom_state *bc)
|
||||||
{
|
{
|
||||||
|
@ -405,6 +382,7 @@ static void encode_hdlc(struct baycom_state *bc)
|
||||||
int pkt_len;
|
int pkt_len;
|
||||||
unsigned bitstream, notbitstream, bitbuf, numbit, crc;
|
unsigned bitstream, notbitstream, bitbuf, numbit, crc;
|
||||||
unsigned char crcarr[2];
|
unsigned char crcarr[2];
|
||||||
|
int j;
|
||||||
|
|
||||||
if (bc->hdlctx.bufcnt > 0)
|
if (bc->hdlctx.bufcnt > 0)
|
||||||
return;
|
return;
|
||||||
|
@ -429,24 +407,14 @@ static void encode_hdlc(struct baycom_state *bc)
|
||||||
pkt_len--;
|
pkt_len--;
|
||||||
if (!pkt_len)
|
if (!pkt_len)
|
||||||
bp = crcarr;
|
bp = crcarr;
|
||||||
ENCODEITERA(0);
|
for (j = 0; j < 8; j++)
|
||||||
ENCODEITERA(1);
|
if (unlikely(!(notbitstream & (0x1f0 << j)))) {
|
||||||
ENCODEITERA(2);
|
bitstream &= ~(0x100 << j);
|
||||||
ENCODEITERA(3);
|
bitbuf = (bitbuf & (((2 << j) << numbit) - 1)) |
|
||||||
ENCODEITERA(4);
|
((bitbuf & ~(((2 << j) << numbit) - 1)) << 1);
|
||||||
ENCODEITERA(5);
|
numbit++;
|
||||||
ENCODEITERA(6);
|
notbitstream = ~bitstream;
|
||||||
ENCODEITERA(7);
|
}
|
||||||
goto enditer;
|
|
||||||
ENCODEITERB(0);
|
|
||||||
ENCODEITERB(1);
|
|
||||||
ENCODEITERB(2);
|
|
||||||
ENCODEITERB(3);
|
|
||||||
ENCODEITERB(4);
|
|
||||||
ENCODEITERB(5);
|
|
||||||
ENCODEITERB(6);
|
|
||||||
ENCODEITERB(7);
|
|
||||||
enditer:
|
|
||||||
numbit += 8;
|
numbit += 8;
|
||||||
while (numbit >= 8) {
|
while (numbit >= 8) {
|
||||||
*wp++ = bitbuf;
|
*wp++ = bitbuf;
|
||||||
|
@ -610,37 +578,6 @@ static void do_rxpacket(struct net_device *dev)
|
||||||
bc->stats.rx_packets++;
|
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)
|
static int receive(struct net_device *dev, int cnt)
|
||||||
{
|
{
|
||||||
struct baycom_state *bc = netdev_priv(dev);
|
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 tmp[128];
|
||||||
unsigned char *cp;
|
unsigned char *cp;
|
||||||
int cnt2, ret = 0;
|
int cnt2, ret = 0;
|
||||||
|
int j;
|
||||||
|
|
||||||
numbits = bc->hdlcrx.numbits;
|
numbits = bc->hdlcrx.numbits;
|
||||||
state = bc->hdlcrx.state;
|
state = bc->hdlcrx.state;
|
||||||
|
@ -669,24 +607,32 @@ static int receive(struct net_device *dev, int cnt)
|
||||||
bitbuf |= (*cp) << 8;
|
bitbuf |= (*cp) << 8;
|
||||||
numbits += 8;
|
numbits += 8;
|
||||||
notbitstream = ~bitstream;
|
notbitstream = ~bitstream;
|
||||||
DECODEITERA(0);
|
for (j = 0; j < 8; j++) {
|
||||||
DECODEITERA(1);
|
|
||||||
DECODEITERA(2);
|
/* flag or abort */
|
||||||
DECODEITERA(3);
|
if (unlikely(!(notbitstream & (0x0fc << j)))) {
|
||||||
DECODEITERA(4);
|
|
||||||
DECODEITERA(5);
|
/* abort received */
|
||||||
DECODEITERA(6);
|
if (!(notbitstream & (0x1fc << j)))
|
||||||
DECODEITERA(7);
|
state = 0;
|
||||||
goto enddec;
|
|
||||||
DECODEITERB(0);
|
/* not flag received */
|
||||||
DECODEITERB(1);
|
else if (!(bitstream & (0x1fe << j)) != (0x0fc << j)) {
|
||||||
DECODEITERB(2);
|
if (state)
|
||||||
DECODEITERB(3);
|
do_rxpacket(dev);
|
||||||
DECODEITERB(4);
|
bc->hdlcrx.bufcnt = 0;
|
||||||
DECODEITERB(5);
|
bc->hdlcrx.bufptr = bc->hdlcrx.buf;
|
||||||
DECODEITERB(6);
|
state = 1;
|
||||||
DECODEITERB(7);
|
numbits = 7-j;
|
||||||
enddec:
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* stuffed bit */
|
||||||
|
else if (unlikely((bitstream & (0x1f8 << j)) == (0xf8 << j))) {
|
||||||
|
numbits--;
|
||||||
|
bitbuf = (bitbuf & ((~0xff) << j)) | ((bitbuf & ~((~0xff) << j)) << 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
while (state && numbits >= 8) {
|
while (state && numbits >= 8) {
|
||||||
if (bc->hdlcrx.bufcnt >= TXBUFFER_SIZE) {
|
if (bc->hdlcrx.bufcnt >= TXBUFFER_SIZE) {
|
||||||
state = 0;
|
state = 0;
|
||||||
|
|
|
@ -1274,6 +1274,9 @@ static int el3_close(struct net_device *dev)
|
||||||
spin_lock_irqsave(&lp->window_lock, flags);
|
spin_lock_irqsave(&lp->window_lock, flags);
|
||||||
update_stats(dev);
|
update_stats(dev);
|
||||||
spin_unlock_irqrestore(&lp->window_lock, flags);
|
spin_unlock_irqrestore(&lp->window_lock, flags);
|
||||||
|
|
||||||
|
/* force interrupts off */
|
||||||
|
outw(SetIntrEnb | 0x0000, ioaddr + EL3_CMD);
|
||||||
}
|
}
|
||||||
|
|
||||||
link->open--;
|
link->open--;
|
||||||
|
|
|
@ -1585,8 +1585,8 @@ rtl8169_hw_start(struct net_device *dev)
|
||||||
RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
|
RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb);
|
||||||
RTL_W8(EarlyTxThres, EarlyTxThld);
|
RTL_W8(EarlyTxThres, EarlyTxThld);
|
||||||
|
|
||||||
/* For gigabit rtl8169, MTU + header + CRC + VLAN */
|
/* Low hurts. Let's disable the filtering. */
|
||||||
RTL_W16(RxMaxSize, tp->rx_buf_sz);
|
RTL_W16(RxMaxSize, 16383);
|
||||||
|
|
||||||
/* Set Rx Config register */
|
/* Set Rx Config register */
|
||||||
i = rtl8169_rx_config |
|
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)
|
static inline void rtl8169_rx_csum(struct sk_buff *skb, struct RxDesc *desc)
|
||||||
{
|
{
|
||||||
u32 opts1 = le32_to_cpu(desc->opts1);
|
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) {
|
while (rx_left > 0) {
|
||||||
unsigned int entry = cur_rx % NUM_RX_DESC;
|
unsigned int entry = cur_rx % NUM_RX_DESC;
|
||||||
|
struct RxDesc *desc = tp->RxDescArray + entry;
|
||||||
u32 status;
|
u32 status;
|
||||||
|
|
||||||
rmb();
|
rmb();
|
||||||
status = le32_to_cpu(tp->RxDescArray[entry].opts1);
|
status = le32_to_cpu(desc->opts1);
|
||||||
|
|
||||||
if (status & DescOwn)
|
if (status & DescOwn)
|
||||||
break;
|
break;
|
||||||
if (status & RxRES) {
|
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++;
|
tp->stats.rx_errors++;
|
||||||
if (status & (RxRWT | RxRUNT))
|
if (status & (RxRWT | RxRUNT))
|
||||||
tp->stats.rx_length_errors++;
|
tp->stats.rx_length_errors++;
|
||||||
if (status & RxCRC)
|
if (status & RxCRC)
|
||||||
tp->stats.rx_crc_errors++;
|
tp->stats.rx_crc_errors++;
|
||||||
|
rtl8169_mark_to_asic(desc, tp->rx_buf_sz);
|
||||||
} else {
|
} else {
|
||||||
struct RxDesc *desc = tp->RxDescArray + entry;
|
|
||||||
struct sk_buff *skb = tp->Rx_skbuff[entry];
|
struct sk_buff *skb = tp->Rx_skbuff[entry];
|
||||||
int pkt_size = (status & 0x00001FFF) - 4;
|
int pkt_size = (status & 0x00001FFF) - 4;
|
||||||
void (*pci_action)(struct pci_dev *, dma_addr_t,
|
void (*pci_action)(struct pci_dev *, dma_addr_t,
|
||||||
size_t, int) = pci_dma_sync_single_for_device;
|
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);
|
rtl8169_rx_csum(skb, desc);
|
||||||
|
|
||||||
pci_dma_sync_single_for_cpu(tp->pci_dev,
|
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_bytes += pkt_size;
|
||||||
tp->stats.rx_packets++;
|
tp->stats.rx_packets++;
|
||||||
}
|
}
|
||||||
|
move_on:
|
||||||
cur_rx++;
|
cur_rx++;
|
||||||
rx_left--;
|
rx_left--;
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,35 +100,8 @@ static int sh_debug; /* Debug flag */
|
||||||
|
|
||||||
#define SHAPER_BANNER "CymruNet Traffic Shaper BETA 0.04 for Linux 2.1\n"
|
#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_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
|
* Compute clocks on a buffer
|
||||||
*/
|
*/
|
||||||
|
@ -157,17 +130,15 @@ static void shaper_setspeed(struct shaper *shaper, int bitspersec)
|
||||||
* Throw a frame at a shaper.
|
* 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;
|
struct sk_buff *ptr;
|
||||||
|
|
||||||
/*
|
if (down_trylock(&shaper->sem))
|
||||||
* Get ready to work on this shaper. Lock may fail if its
|
|
||||||
* an interrupt and locked.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if(!shaper_lock(shaper))
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
ptr=shaper->sendq.prev;
|
ptr=shaper->sendq.prev;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -260,7 +231,8 @@ static int shaper_qframe(struct shaper *shaper, struct sk_buff *skb)
|
||||||
dev_kfree_skb(ptr);
|
dev_kfree_skb(ptr);
|
||||||
shaper->stats.collisions++;
|
shaper->stats.collisions++;
|
||||||
}
|
}
|
||||||
shaper_unlock(shaper);
|
shaper_kick(shaper);
|
||||||
|
up(&shaper->sem);
|
||||||
return 0;
|
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)
|
static void shaper_timer(unsigned long data)
|
||||||
{
|
{
|
||||||
struct shaper *sh=(struct shaper *)data;
|
struct shaper *shaper = (struct shaper *)data;
|
||||||
shaper_kick(sh);
|
|
||||||
|
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;
|
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)
|
* Walk the list (may be empty)
|
||||||
*/
|
*/
|
||||||
|
@ -364,8 +328,6 @@ static void shaper_kick(struct shaper *shaper)
|
||||||
|
|
||||||
if(skb!=NULL)
|
if(skb!=NULL)
|
||||||
mod_timer(&shaper->timer, SHAPERCB(skb)->shapeclock);
|
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)
|
static void shaper_flush(struct shaper *shaper)
|
||||||
{
|
{
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
if(!shaper_lock(shaper))
|
|
||||||
{
|
down(&shaper->sem);
|
||||||
printk(KERN_ERR "shaper: shaper_flush() called by an irq!\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
while((skb=skb_dequeue(&shaper->sendq))!=NULL)
|
while((skb=skb_dequeue(&shaper->sendq))!=NULL)
|
||||||
dev_kfree_skb(skb);
|
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.
|
* 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)
|
static struct net_device_stats *shaper_get_stats(struct net_device *dev)
|
||||||
{
|
{
|
||||||
struct shaper *sh=dev->priv;
|
struct shaper *sh=dev->priv;
|
||||||
|
@ -623,7 +576,6 @@ static void shaper_init_priv(struct net_device *dev)
|
||||||
init_timer(&sh->timer);
|
init_timer(&sh->timer);
|
||||||
sh->timer.function=shaper_timer;
|
sh->timer.function=shaper_timer;
|
||||||
sh->timer.data=(unsigned long)sh;
|
sh->timer.data=(unsigned long)sh;
|
||||||
init_waitqueue_head(&sh->wait_queue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* CompactPCI Hot Plug Driver
|
* CompactPCI Hot Plug Driver
|
||||||
*
|
*
|
||||||
* Copyright (C) 2002 SOMA Networks, Inc.
|
* Copyright (C) 2002,2005 SOMA Networks, Inc.
|
||||||
* Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
|
* Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com)
|
||||||
* Copyright (C) 2001 IBM Corp.
|
* Copyright (C) 2001 IBM Corp.
|
||||||
*
|
*
|
||||||
|
@ -111,10 +111,8 @@ enable_slot(struct hotplug_slot *hotplug_slot)
|
||||||
|
|
||||||
dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name);
|
dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name);
|
||||||
|
|
||||||
if(controller->ops->set_power) {
|
if (controller->ops->set_power)
|
||||||
retval = controller->ops->set_power(slot, 1);
|
retval = controller->ops->set_power(slot, 1);
|
||||||
}
|
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,13 +124,15 @@ disable_slot(struct hotplug_slot *hotplug_slot)
|
||||||
|
|
||||||
dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name);
|
dbg("%s - physical_slot = %s", __FUNCTION__, hotplug_slot->name);
|
||||||
|
|
||||||
|
down_write(&list_rwsem);
|
||||||
|
|
||||||
/* Unconfigure device */
|
/* Unconfigure device */
|
||||||
dbg("%s - unconfiguring slot %s",
|
dbg("%s - unconfiguring slot %s",
|
||||||
__FUNCTION__, slot->hotplug_slot->name);
|
__FUNCTION__, slot->hotplug_slot->name);
|
||||||
if ((retval = cpci_unconfigure_slot(slot))) {
|
if ((retval = cpci_unconfigure_slot(slot))) {
|
||||||
err("%s - could not unconfigure slot %s",
|
err("%s - could not unconfigure slot %s",
|
||||||
__FUNCTION__, slot->hotplug_slot->name);
|
__FUNCTION__, slot->hotplug_slot->name);
|
||||||
return retval;
|
goto disable_error;
|
||||||
}
|
}
|
||||||
dbg("%s - finished unconfiguring slot %s",
|
dbg("%s - finished unconfiguring slot %s",
|
||||||
__FUNCTION__, slot->hotplug_slot->name);
|
__FUNCTION__, slot->hotplug_slot->name);
|
||||||
|
@ -142,21 +142,23 @@ disable_slot(struct hotplug_slot *hotplug_slot)
|
||||||
err("%s - could not clear EXT for slot %s",
|
err("%s - could not clear EXT for slot %s",
|
||||||
__FUNCTION__, slot->hotplug_slot->name);
|
__FUNCTION__, slot->hotplug_slot->name);
|
||||||
retval = -ENODEV;
|
retval = -ENODEV;
|
||||||
|
goto disable_error;
|
||||||
}
|
}
|
||||||
cpci_led_on(slot);
|
cpci_led_on(slot);
|
||||||
|
|
||||||
if(controller->ops->set_power) {
|
if (controller->ops->set_power)
|
||||||
retval = controller->ops->set_power(slot, 0);
|
if ((retval = controller->ops->set_power(slot, 0)))
|
||||||
}
|
goto disable_error;
|
||||||
|
|
||||||
if(update_adapter_status(slot->hotplug_slot, 0)) {
|
if (update_adapter_status(slot->hotplug_slot, 0))
|
||||||
warn("failure to update adapter file");
|
warn("failure to update adapter file");
|
||||||
}
|
|
||||||
|
|
||||||
if (slot->extracting) {
|
if (slot->extracting) {
|
||||||
slot->extracting = 0;
|
slot->extracting = 0;
|
||||||
atomic_dec(&extracting);
|
atomic_dec(&extracting);
|
||||||
}
|
}
|
||||||
|
disable_error:
|
||||||
|
up_write(&list_rwsem);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,9 +167,8 @@ cpci_get_power_status(struct slot *slot)
|
||||||
{
|
{
|
||||||
u8 power = 1;
|
u8 power = 1;
|
||||||
|
|
||||||
if(controller->ops->get_power) {
|
if (controller->ops->get_power)
|
||||||
power = controller->ops->get_power(slot);
|
power = controller->ops->get_power(slot);
|
||||||
}
|
|
||||||
return power;
|
return power;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,9 +238,8 @@ cpci_hp_register_bus(struct pci_bus *bus, u8 first, u8 last)
|
||||||
int status = -ENOMEM;
|
int status = -ENOMEM;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if(!(controller && bus)) {
|
if (!(controller && bus))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a structure for each slot, and register that slot
|
* Create a structure for each slot, and register that slot
|
||||||
|
@ -316,32 +316,30 @@ int
|
||||||
cpci_hp_unregister_bus(struct pci_bus *bus)
|
cpci_hp_unregister_bus(struct pci_bus *bus)
|
||||||
{
|
{
|
||||||
struct slot *slot;
|
struct slot *slot;
|
||||||
struct list_head *tmp;
|
struct slot *tmp;
|
||||||
struct list_head *next;
|
int status = 0;
|
||||||
int status;
|
|
||||||
|
|
||||||
down_write(&list_rwsem);
|
down_write(&list_rwsem);
|
||||||
if (!slots) {
|
if (!slots) {
|
||||||
up_write(&list_rwsem);
|
up_write(&list_rwsem);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
list_for_each_safe(tmp, next, &slot_list) {
|
list_for_each_entry_safe(slot, tmp, &slot_list, slot_list) {
|
||||||
slot = list_entry(tmp, struct slot, slot_list);
|
|
||||||
if (slot->bus == bus) {
|
if (slot->bus == bus) {
|
||||||
|
list_del(&slot->slot_list);
|
||||||
|
slots--;
|
||||||
|
|
||||||
dbg("deregistering slot %s", slot->hotplug_slot->name);
|
dbg("deregistering slot %s", slot->hotplug_slot->name);
|
||||||
status = pci_hp_deregister(slot->hotplug_slot);
|
status = pci_hp_deregister(slot->hotplug_slot);
|
||||||
if (status) {
|
if (status) {
|
||||||
err("pci_hp_deregister failed with error %d",
|
err("pci_hp_deregister failed with error %d",
|
||||||
status);
|
status);
|
||||||
return status;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
list_del(&slot->slot_list);
|
|
||||||
slots--;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
up_write(&list_rwsem);
|
up_write(&list_rwsem);
|
||||||
return 0;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This is the interrupt mode interrupt handler */
|
/* This is the interrupt mode interrupt handler */
|
||||||
|
@ -373,10 +371,9 @@ cpci_hp_intr(int irq, void *data, struct pt_regs *regs)
|
||||||
* INS bits of the cold-inserted devices.
|
* INS bits of the cold-inserted devices.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
init_slots(void)
|
init_slots(int clear_ins)
|
||||||
{
|
{
|
||||||
struct slot *slot;
|
struct slot *slot;
|
||||||
struct list_head *tmp;
|
|
||||||
struct pci_dev* dev;
|
struct pci_dev* dev;
|
||||||
|
|
||||||
dbg("%s - enter", __FUNCTION__);
|
dbg("%s - enter", __FUNCTION__);
|
||||||
|
@ -385,26 +382,19 @@ init_slots(void)
|
||||||
up_read(&list_rwsem);
|
up_read(&list_rwsem);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
list_for_each(tmp, &slot_list) {
|
list_for_each_entry(slot, &slot_list, slot_list) {
|
||||||
slot = list_entry(tmp, struct slot, slot_list);
|
|
||||||
dbg("%s - looking at slot %s",
|
dbg("%s - looking at slot %s",
|
||||||
__FUNCTION__, slot->hotplug_slot->name);
|
__FUNCTION__, slot->hotplug_slot->name);
|
||||||
if(cpci_check_and_clear_ins(slot)) {
|
if (clear_ins && cpci_check_and_clear_ins(slot))
|
||||||
dbg("%s - cleared INS for slot %s",
|
dbg("%s - cleared INS for slot %s",
|
||||||
__FUNCTION__, slot->hotplug_slot->name);
|
__FUNCTION__, slot->hotplug_slot->name);
|
||||||
dev = pci_find_slot(slot->bus->number, PCI_DEVFN(slot->number, 0));
|
dev = pci_get_slot(slot->bus, PCI_DEVFN(slot->number, 0));
|
||||||
if (dev) {
|
if (dev) {
|
||||||
if(update_adapter_status(slot->hotplug_slot, 1)) {
|
if (update_adapter_status(slot->hotplug_slot, 1))
|
||||||
warn("failure to update adapter file");
|
warn("failure to update adapter file");
|
||||||
}
|
if (update_latch_status(slot->hotplug_slot, 1))
|
||||||
if(update_latch_status(slot->hotplug_slot, 1)) {
|
|
||||||
warn("failure to update latch file");
|
warn("failure to update latch file");
|
||||||
}
|
|
||||||
slot->dev = dev;
|
slot->dev = dev;
|
||||||
} else {
|
|
||||||
err("%s - no driver attached to device in slot %s",
|
|
||||||
__FUNCTION__, slot->hotplug_slot->name);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
up_read(&list_rwsem);
|
up_read(&list_rwsem);
|
||||||
|
@ -416,7 +406,6 @@ static int
|
||||||
check_slots(void)
|
check_slots(void)
|
||||||
{
|
{
|
||||||
struct slot *slot;
|
struct slot *slot;
|
||||||
struct list_head *tmp;
|
|
||||||
int extracted;
|
int extracted;
|
||||||
int inserted;
|
int inserted;
|
||||||
u16 hs_csr;
|
u16 hs_csr;
|
||||||
|
@ -428,14 +417,17 @@ check_slots(void)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
extracted = inserted = 0;
|
extracted = inserted = 0;
|
||||||
list_for_each(tmp, &slot_list) {
|
list_for_each_entry(slot, &slot_list, slot_list) {
|
||||||
slot = list_entry(tmp, struct slot, slot_list);
|
|
||||||
dbg("%s - looking at slot %s",
|
dbg("%s - looking at slot %s",
|
||||||
__FUNCTION__, slot->hotplug_slot->name);
|
__FUNCTION__, slot->hotplug_slot->name);
|
||||||
if (cpci_check_and_clear_ins(slot)) {
|
if (cpci_check_and_clear_ins(slot)) {
|
||||||
/* Some broken hardware (e.g. PLX 9054AB) asserts ENUM# twice... */
|
/*
|
||||||
|
* Some broken hardware (e.g. PLX 9054AB) asserts
|
||||||
|
* ENUM# twice...
|
||||||
|
*/
|
||||||
if (slot->dev) {
|
if (slot->dev) {
|
||||||
warn("slot %s already inserted", slot->hotplug_slot->name);
|
warn("slot %s already inserted",
|
||||||
|
slot->hotplug_slot->name);
|
||||||
inserted++;
|
inserted++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -465,13 +457,11 @@ check_slots(void)
|
||||||
dbg("%s - slot %s HS_CSR (2) = %04x",
|
dbg("%s - slot %s HS_CSR (2) = %04x",
|
||||||
__FUNCTION__, slot->hotplug_slot->name, hs_csr);
|
__FUNCTION__, slot->hotplug_slot->name, hs_csr);
|
||||||
|
|
||||||
if(update_latch_status(slot->hotplug_slot, 1)) {
|
if (update_latch_status(slot->hotplug_slot, 1))
|
||||||
warn("failure to update latch file");
|
warn("failure to update latch file");
|
||||||
}
|
|
||||||
|
|
||||||
if(update_adapter_status(slot->hotplug_slot, 1)) {
|
if (update_adapter_status(slot->hotplug_slot, 1))
|
||||||
warn("failure to update adapter file");
|
warn("failure to update adapter file");
|
||||||
}
|
|
||||||
|
|
||||||
cpci_led_off(slot);
|
cpci_led_off(slot);
|
||||||
|
|
||||||
|
@ -494,10 +484,9 @@ check_slots(void)
|
||||||
if (!slot->extracting) {
|
if (!slot->extracting) {
|
||||||
if (update_latch_status(slot->hotplug_slot, 0)) {
|
if (update_latch_status(slot->hotplug_slot, 0)) {
|
||||||
warn("failure to update latch file");
|
warn("failure to update latch file");
|
||||||
|
|
||||||
}
|
}
|
||||||
atomic_inc(&extracting);
|
|
||||||
slot->extracting = 1;
|
slot->extracting = 1;
|
||||||
|
atomic_inc(&extracting);
|
||||||
}
|
}
|
||||||
extracted++;
|
extracted++;
|
||||||
} else if (slot->extracting) {
|
} else if (slot->extracting) {
|
||||||
|
@ -509,9 +498,8 @@ check_slots(void)
|
||||||
*/
|
*/
|
||||||
err("card in slot %s was improperly removed",
|
err("card in slot %s was improperly removed",
|
||||||
slot->hotplug_slot->name);
|
slot->hotplug_slot->name);
|
||||||
if(update_adapter_status(slot->hotplug_slot, 0)) {
|
if (update_adapter_status(slot->hotplug_slot, 0))
|
||||||
warn("failure to update adapter file");
|
warn("failure to update adapter file");
|
||||||
}
|
|
||||||
slot->extracting = 0;
|
slot->extracting = 0;
|
||||||
atomic_dec(&extracting);
|
atomic_dec(&extracting);
|
||||||
}
|
}
|
||||||
|
@ -520,9 +508,8 @@ check_slots(void)
|
||||||
up_read(&list_rwsem);
|
up_read(&list_rwsem);
|
||||||
dbg("inserted=%d, extracted=%d, extracting=%d",
|
dbg("inserted=%d, extracted=%d, extracting=%d",
|
||||||
inserted, extracted, atomic_read(&extracting));
|
inserted, extracted, atomic_read(&extracting));
|
||||||
if(inserted || extracted) {
|
if (inserted || extracted)
|
||||||
return extracted;
|
return extracted;
|
||||||
}
|
|
||||||
else if (!atomic_read(&extracting)) {
|
else if (!atomic_read(&extracting)) {
|
||||||
err("cannot find ENUM# source, shutting down");
|
err("cannot find ENUM# source, shutting down");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -558,7 +545,9 @@ event_thread(void *data)
|
||||||
thread_finished = 1;
|
thread_finished = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while(atomic_read(&extracting) != 0);
|
} while (atomic_read(&extracting) && !thread_finished);
|
||||||
|
if (thread_finished)
|
||||||
|
break;
|
||||||
|
|
||||||
/* Re-enable ENUM# interrupt */
|
/* Re-enable ENUM# interrupt */
|
||||||
dbg("%s - re-enabling irq", __FUNCTION__);
|
dbg("%s - re-enabling irq", __FUNCTION__);
|
||||||
|
@ -593,7 +582,7 @@ poll_thread(void *data)
|
||||||
thread_finished = 1;
|
thread_finished = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} while(atomic_read(&extracting) != 0);
|
} while (atomic_read(&extracting) && !thread_finished);
|
||||||
}
|
}
|
||||||
msleep(100);
|
msleep(100);
|
||||||
}
|
}
|
||||||
|
@ -612,11 +601,10 @@ cpci_start_thread(void)
|
||||||
init_MUTEX_LOCKED(&thread_exit);
|
init_MUTEX_LOCKED(&thread_exit);
|
||||||
thread_finished = 0;
|
thread_finished = 0;
|
||||||
|
|
||||||
if(controller->irq) {
|
if (controller->irq)
|
||||||
pid = kernel_thread(event_thread, NULL, 0);
|
pid = kernel_thread(event_thread, NULL, 0);
|
||||||
} else {
|
else
|
||||||
pid = kernel_thread(poll_thread, NULL, 0);
|
pid = kernel_thread(poll_thread, NULL, 0);
|
||||||
}
|
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
err("Can't start up our thread");
|
err("Can't start up our thread");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -630,9 +618,8 @@ cpci_stop_thread(void)
|
||||||
{
|
{
|
||||||
thread_finished = 1;
|
thread_finished = 1;
|
||||||
dbg("thread finish command given");
|
dbg("thread finish command given");
|
||||||
if(controller->irq) {
|
if (controller->irq)
|
||||||
up(&event_semaphore);
|
up(&event_semaphore);
|
||||||
}
|
|
||||||
dbg("wait for thread to exit");
|
dbg("wait for thread to exit");
|
||||||
down(&thread_exit);
|
down(&thread_exit);
|
||||||
}
|
}
|
||||||
|
@ -642,45 +629,67 @@ cpci_hp_register_controller(struct cpci_hp_controller *new_controller)
|
||||||
{
|
{
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
if(!controller) {
|
if (controller)
|
||||||
controller = new_controller;
|
return -1;
|
||||||
if(controller->irq) {
|
if (!(new_controller && new_controller->ops))
|
||||||
if(request_irq(controller->irq,
|
return -EINVAL;
|
||||||
|
if (new_controller->irq) {
|
||||||
|
if (!(new_controller->ops->enable_irq &&
|
||||||
|
new_controller->ops->disable_irq))
|
||||||
|
status = -EINVAL;
|
||||||
|
if (request_irq(new_controller->irq,
|
||||||
cpci_hp_intr,
|
cpci_hp_intr,
|
||||||
controller->irq_flags,
|
new_controller->irq_flags,
|
||||||
MY_NAME, controller->dev_id)) {
|
MY_NAME,
|
||||||
err("Can't get irq %d for the hotplug cPCI controller", controller->irq);
|
new_controller->dev_id)) {
|
||||||
|
err("Can't get irq %d for the hotplug cPCI controller",
|
||||||
|
new_controller->irq);
|
||||||
status = -ENODEV;
|
status = -ENODEV;
|
||||||
}
|
}
|
||||||
dbg("%s - acquired controller irq %d", __FUNCTION__,
|
dbg("%s - acquired controller irq %d",
|
||||||
controller->irq);
|
__FUNCTION__, new_controller->irq);
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err("cPCI hotplug controller already registered");
|
|
||||||
status = -1;
|
|
||||||
}
|
}
|
||||||
|
if (!status)
|
||||||
|
controller = new_controller;
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
cleanup_slots(void)
|
||||||
|
{
|
||||||
|
struct slot *slot;
|
||||||
|
struct slot *tmp;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Unregister all of our slots with the pci_hotplug subsystem,
|
||||||
|
* and free up all memory that we had allocated.
|
||||||
|
*/
|
||||||
|
down_write(&list_rwsem);
|
||||||
|
if (!slots)
|
||||||
|
goto cleanup_null;
|
||||||
|
list_for_each_entry_safe(slot, tmp, &slot_list, slot_list) {
|
||||||
|
list_del(&slot->slot_list);
|
||||||
|
pci_hp_deregister(slot->hotplug_slot);
|
||||||
|
}
|
||||||
|
cleanup_null:
|
||||||
|
up_write(&list_rwsem);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
cpci_hp_unregister_controller(struct cpci_hp_controller *old_controller)
|
cpci_hp_unregister_controller(struct cpci_hp_controller *old_controller)
|
||||||
{
|
{
|
||||||
int status = 0;
|
int status = 0;
|
||||||
|
|
||||||
if (controller) {
|
if (controller) {
|
||||||
if(atomic_read(&extracting) != 0) {
|
if (!thread_finished)
|
||||||
return -EBUSY;
|
|
||||||
}
|
|
||||||
if(!thread_finished) {
|
|
||||||
cpci_stop_thread();
|
cpci_stop_thread();
|
||||||
}
|
if (controller->irq)
|
||||||
if(controller->irq) {
|
|
||||||
free_irq(controller->irq, controller->dev_id);
|
free_irq(controller->irq, controller->dev_id);
|
||||||
}
|
|
||||||
controller = NULL;
|
controller = NULL;
|
||||||
} else {
|
cleanup_slots();
|
||||||
|
} else
|
||||||
status = -ENODEV;
|
status = -ENODEV;
|
||||||
}
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -691,9 +700,8 @@ cpci_hp_start(void)
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
dbg("%s - enter", __FUNCTION__);
|
dbg("%s - enter", __FUNCTION__);
|
||||||
if(!controller) {
|
if (!controller)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
|
||||||
|
|
||||||
down_read(&list_rwsem);
|
down_read(&list_rwsem);
|
||||||
if (list_empty(&slot_list)) {
|
if (list_empty(&slot_list)) {
|
||||||
|
@ -702,18 +710,15 @@ cpci_hp_start(void)
|
||||||
}
|
}
|
||||||
up_read(&list_rwsem);
|
up_read(&list_rwsem);
|
||||||
|
|
||||||
if(first) {
|
status = init_slots(first);
|
||||||
status = init_slots();
|
if (first)
|
||||||
if(status) {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
first = 0;
|
first = 0;
|
||||||
}
|
if (status)
|
||||||
|
return status;
|
||||||
|
|
||||||
status = cpci_start_thread();
|
status = cpci_start_thread();
|
||||||
if(status) {
|
if (status)
|
||||||
return status;
|
return status;
|
||||||
}
|
|
||||||
dbg("%s - thread started", __FUNCTION__);
|
dbg("%s - thread started", __FUNCTION__);
|
||||||
|
|
||||||
if (controller->irq) {
|
if (controller->irq) {
|
||||||
|
@ -728,12 +733,8 @@ cpci_hp_start(void)
|
||||||
int
|
int
|
||||||
cpci_hp_stop(void)
|
cpci_hp_stop(void)
|
||||||
{
|
{
|
||||||
if(!controller) {
|
if (!controller)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
|
||||||
if(atomic_read(&extracting) != 0) {
|
|
||||||
return -EBUSY;
|
|
||||||
}
|
|
||||||
if (controller->irq) {
|
if (controller->irq) {
|
||||||
/* Stop enum interrupt processing */
|
/* Stop enum interrupt processing */
|
||||||
dbg("%s - disabling irq", __FUNCTION__);
|
dbg("%s - disabling irq", __FUNCTION__);
|
||||||
|
@ -743,34 +744,6 @@ cpci_hp_stop(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit
|
|
||||||
cleanup_slots(void)
|
|
||||||
{
|
|
||||||
struct list_head *tmp;
|
|
||||||
struct slot *slot;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Unregister all of our slots with the pci_hotplug subsystem,
|
|
||||||
* and free up all memory that we had allocated.
|
|
||||||
*/
|
|
||||||
down_write(&list_rwsem);
|
|
||||||
if(!slots) {
|
|
||||||
goto null_cleanup;
|
|
||||||
}
|
|
||||||
list_for_each(tmp, &slot_list) {
|
|
||||||
slot = list_entry(tmp, struct slot, slot_list);
|
|
||||||
list_del(&slot->slot_list);
|
|
||||||
pci_hp_deregister(slot->hotplug_slot);
|
|
||||||
kfree(slot->hotplug_slot->info);
|
|
||||||
kfree(slot->hotplug_slot->name);
|
|
||||||
kfree(slot->hotplug_slot);
|
|
||||||
kfree(slot);
|
|
||||||
}
|
|
||||||
null_cleanup:
|
|
||||||
up_write(&list_rwsem);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int __init
|
int __init
|
||||||
cpci_hotplug_init(int debug)
|
cpci_hotplug_init(int debug)
|
||||||
{
|
{
|
||||||
|
@ -784,7 +757,8 @@ cpci_hotplug_exit(void)
|
||||||
/*
|
/*
|
||||||
* Clean everything up.
|
* Clean everything up.
|
||||||
*/
|
*/
|
||||||
cleanup_slots();
|
cpci_hp_stop();
|
||||||
|
cpci_hp_unregister_controller(controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT_SYMBOL_GPL(cpci_hp_register_controller);
|
EXPORT_SYMBOL_GPL(cpci_hp_register_controller);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* CompactPCI Hot Plug Driver PCI functions
|
* CompactPCI Hot Plug Driver PCI functions
|
||||||
*
|
*
|
||||||
* Copyright (C) 2002 by SOMA Networks, Inc.
|
* Copyright (C) 2002,2005 by SOMA Networks, Inc.
|
||||||
*
|
*
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
|
@ -57,16 +57,15 @@ u8 cpci_get_attention_status(struct slot* slot)
|
||||||
hs_cap = pci_bus_find_capability(slot->bus,
|
hs_cap = pci_bus_find_capability(slot->bus,
|
||||||
slot->devfn,
|
slot->devfn,
|
||||||
PCI_CAP_ID_CHSWP);
|
PCI_CAP_ID_CHSWP);
|
||||||
if(!hs_cap) {
|
if (!hs_cap)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
if (pci_bus_read_config_word(slot->bus,
|
if (pci_bus_read_config_word(slot->bus,
|
||||||
slot->devfn,
|
slot->devfn,
|
||||||
hs_cap + 2,
|
hs_cap + 2,
|
||||||
&hs_csr)) {
|
&hs_csr))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
return hs_csr & 0x0008 ? 1 : 0;
|
return hs_csr & 0x0008 ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,27 +77,22 @@ int cpci_set_attention_status(struct slot* slot, int status)
|
||||||
hs_cap = pci_bus_find_capability(slot->bus,
|
hs_cap = pci_bus_find_capability(slot->bus,
|
||||||
slot->devfn,
|
slot->devfn,
|
||||||
PCI_CAP_ID_CHSWP);
|
PCI_CAP_ID_CHSWP);
|
||||||
if(!hs_cap) {
|
if (!hs_cap)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
if (pci_bus_read_config_word(slot->bus,
|
if (pci_bus_read_config_word(slot->bus,
|
||||||
slot->devfn,
|
slot->devfn,
|
||||||
hs_cap + 2,
|
hs_cap + 2,
|
||||||
&hs_csr)) {
|
&hs_csr))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
if (status)
|
||||||
if(status) {
|
|
||||||
hs_csr |= HS_CSR_LOO;
|
hs_csr |= HS_CSR_LOO;
|
||||||
} else {
|
else
|
||||||
hs_csr &= ~HS_CSR_LOO;
|
hs_csr &= ~HS_CSR_LOO;
|
||||||
}
|
|
||||||
if (pci_bus_write_config_word(slot->bus,
|
if (pci_bus_write_config_word(slot->bus,
|
||||||
slot->devfn,
|
slot->devfn,
|
||||||
hs_cap + 2,
|
hs_cap + 2,
|
||||||
hs_csr)) {
|
hs_csr))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,16 +104,13 @@ u16 cpci_get_hs_csr(struct slot* slot)
|
||||||
hs_cap = pci_bus_find_capability(slot->bus,
|
hs_cap = pci_bus_find_capability(slot->bus,
|
||||||
slot->devfn,
|
slot->devfn,
|
||||||
PCI_CAP_ID_CHSWP);
|
PCI_CAP_ID_CHSWP);
|
||||||
if(!hs_cap) {
|
if (!hs_cap)
|
||||||
return 0xFFFF;
|
return 0xFFFF;
|
||||||
}
|
|
||||||
|
|
||||||
if (pci_bus_read_config_word(slot->bus,
|
if (pci_bus_read_config_word(slot->bus,
|
||||||
slot->devfn,
|
slot->devfn,
|
||||||
hs_cap + 2,
|
hs_cap + 2,
|
||||||
&hs_csr)) {
|
&hs_csr))
|
||||||
return 0xFFFF;
|
return 0xFFFF;
|
||||||
}
|
|
||||||
return hs_csr;
|
return hs_csr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,23 +123,21 @@ int cpci_check_and_clear_ins(struct slot* slot)
|
||||||
hs_cap = pci_bus_find_capability(slot->bus,
|
hs_cap = pci_bus_find_capability(slot->bus,
|
||||||
slot->devfn,
|
slot->devfn,
|
||||||
PCI_CAP_ID_CHSWP);
|
PCI_CAP_ID_CHSWP);
|
||||||
if(!hs_cap) {
|
if (!hs_cap)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
if (pci_bus_read_config_word(slot->bus,
|
if (pci_bus_read_config_word(slot->bus,
|
||||||
slot->devfn,
|
slot->devfn,
|
||||||
hs_cap + 2,
|
hs_cap + 2,
|
||||||
&hs_csr)) {
|
&hs_csr))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
if (hs_csr & HS_CSR_INS) {
|
if (hs_csr & HS_CSR_INS) {
|
||||||
/* Clear INS (by setting it) */
|
/* Clear INS (by setting it) */
|
||||||
if (pci_bus_write_config_word(slot->bus,
|
if (pci_bus_write_config_word(slot->bus,
|
||||||
slot->devfn,
|
slot->devfn,
|
||||||
hs_cap + 2,
|
hs_cap + 2,
|
||||||
hs_csr)) {
|
hs_csr))
|
||||||
ins = 0;
|
ins = 0;
|
||||||
}
|
else
|
||||||
ins = 1;
|
ins = 1;
|
||||||
}
|
}
|
||||||
return ins;
|
return ins;
|
||||||
|
@ -163,18 +152,15 @@ int cpci_check_ext(struct slot* slot)
|
||||||
hs_cap = pci_bus_find_capability(slot->bus,
|
hs_cap = pci_bus_find_capability(slot->bus,
|
||||||
slot->devfn,
|
slot->devfn,
|
||||||
PCI_CAP_ID_CHSWP);
|
PCI_CAP_ID_CHSWP);
|
||||||
if(!hs_cap) {
|
if (!hs_cap)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
if (pci_bus_read_config_word(slot->bus,
|
if (pci_bus_read_config_word(slot->bus,
|
||||||
slot->devfn,
|
slot->devfn,
|
||||||
hs_cap + 2,
|
hs_cap + 2,
|
||||||
&hs_csr)) {
|
&hs_csr))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
if (hs_csr & HS_CSR_EXT)
|
||||||
if(hs_csr & HS_CSR_EXT) {
|
|
||||||
ext = 1;
|
ext = 1;
|
||||||
}
|
|
||||||
return ext;
|
return ext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,24 +172,21 @@ int cpci_clear_ext(struct slot* slot)
|
||||||
hs_cap = pci_bus_find_capability(slot->bus,
|
hs_cap = pci_bus_find_capability(slot->bus,
|
||||||
slot->devfn,
|
slot->devfn,
|
||||||
PCI_CAP_ID_CHSWP);
|
PCI_CAP_ID_CHSWP);
|
||||||
if(!hs_cap) {
|
if (!hs_cap)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
|
||||||
if (pci_bus_read_config_word(slot->bus,
|
if (pci_bus_read_config_word(slot->bus,
|
||||||
slot->devfn,
|
slot->devfn,
|
||||||
hs_cap + 2,
|
hs_cap + 2,
|
||||||
&hs_csr)) {
|
&hs_csr))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
|
||||||
if (hs_csr & HS_CSR_EXT) {
|
if (hs_csr & HS_CSR_EXT) {
|
||||||
/* Clear EXT (by setting it) */
|
/* Clear EXT (by setting it) */
|
||||||
if (pci_bus_write_config_word(slot->bus,
|
if (pci_bus_write_config_word(slot->bus,
|
||||||
slot->devfn,
|
slot->devfn,
|
||||||
hs_cap + 2,
|
hs_cap + 2,
|
||||||
hs_csr)) {
|
hs_csr))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,15 +198,13 @@ int cpci_led_on(struct slot* slot)
|
||||||
hs_cap = pci_bus_find_capability(slot->bus,
|
hs_cap = pci_bus_find_capability(slot->bus,
|
||||||
slot->devfn,
|
slot->devfn,
|
||||||
PCI_CAP_ID_CHSWP);
|
PCI_CAP_ID_CHSWP);
|
||||||
if(!hs_cap) {
|
if (!hs_cap)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
|
||||||
if (pci_bus_read_config_word(slot->bus,
|
if (pci_bus_read_config_word(slot->bus,
|
||||||
slot->devfn,
|
slot->devfn,
|
||||||
hs_cap + 2,
|
hs_cap + 2,
|
||||||
&hs_csr)) {
|
&hs_csr))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
|
||||||
if ((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) {
|
if ((hs_csr & HS_CSR_LOO) != HS_CSR_LOO) {
|
||||||
hs_csr |= HS_CSR_LOO;
|
hs_csr |= HS_CSR_LOO;
|
||||||
if (pci_bus_write_config_word(slot->bus,
|
if (pci_bus_write_config_word(slot->bus,
|
||||||
|
@ -246,15 +227,13 @@ int cpci_led_off(struct slot* slot)
|
||||||
hs_cap = pci_bus_find_capability(slot->bus,
|
hs_cap = pci_bus_find_capability(slot->bus,
|
||||||
slot->devfn,
|
slot->devfn,
|
||||||
PCI_CAP_ID_CHSWP);
|
PCI_CAP_ID_CHSWP);
|
||||||
if(!hs_cap) {
|
if (!hs_cap)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
|
||||||
if (pci_bus_read_config_word(slot->bus,
|
if (pci_bus_read_config_word(slot->bus,
|
||||||
slot->devfn,
|
slot->devfn,
|
||||||
hs_cap + 2,
|
hs_cap + 2,
|
||||||
&hs_csr)) {
|
&hs_csr))
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
|
||||||
if (hs_csr & HS_CSR_LOO) {
|
if (hs_csr & HS_CSR_LOO) {
|
||||||
hs_csr &= ~HS_CSR_LOO;
|
hs_csr &= ~HS_CSR_LOO;
|
||||||
if (pci_bus_write_config_word(slot->bus,
|
if (pci_bus_write_config_word(slot->bus,
|
||||||
|
@ -274,19 +253,6 @@ int cpci_led_off(struct slot* slot)
|
||||||
* Device configuration functions
|
* Device configuration functions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void cpci_enable_device(struct pci_dev *dev)
|
|
||||||
{
|
|
||||||
struct pci_bus *bus;
|
|
||||||
|
|
||||||
pci_enable_device(dev);
|
|
||||||
if(dev->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
|
|
||||||
bus = dev->subordinate;
|
|
||||||
list_for_each_entry(dev, &bus->devices, bus_list) {
|
|
||||||
cpci_enable_device(dev);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int cpci_configure_slot(struct slot* slot)
|
int cpci_configure_slot(struct slot* slot)
|
||||||
{
|
{
|
||||||
unsigned char busnr;
|
unsigned char busnr;
|
||||||
|
@ -297,7 +263,7 @@ int cpci_configure_slot(struct slot* slot)
|
||||||
if (slot->dev == NULL) {
|
if (slot->dev == NULL) {
|
||||||
dbg("pci_dev null, finding %02x:%02x:%x",
|
dbg("pci_dev null, finding %02x:%02x:%x",
|
||||||
slot->bus->number, PCI_SLOT(slot->devfn), PCI_FUNC(slot->devfn));
|
slot->bus->number, PCI_SLOT(slot->devfn), PCI_FUNC(slot->devfn));
|
||||||
slot->dev = pci_find_slot(slot->bus->number, slot->devfn);
|
slot->dev = pci_get_slot(slot->bus, slot->devfn);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Still NULL? Well then scan for it! */
|
/* Still NULL? Well then scan for it! */
|
||||||
|
@ -313,7 +279,7 @@ int cpci_configure_slot(struct slot* slot)
|
||||||
dbg("%s: pci_scan_slot returned %d", __FUNCTION__, n);
|
dbg("%s: pci_scan_slot returned %d", __FUNCTION__, n);
|
||||||
if (n > 0)
|
if (n > 0)
|
||||||
pci_bus_add_devices(slot->bus);
|
pci_bus_add_devices(slot->bus);
|
||||||
slot->dev = pci_find_slot(slot->bus->number, slot->devfn);
|
slot->dev = pci_get_slot(slot->bus, slot->devfn);
|
||||||
if (slot->dev == NULL) {
|
if (slot->dev == NULL) {
|
||||||
err("Could not find PCI device for slot %02x", slot->number);
|
err("Could not find PCI device for slot %02x", slot->number);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -329,8 +295,6 @@ int cpci_configure_slot(struct slot* slot)
|
||||||
|
|
||||||
pci_bus_assign_resources(slot->dev->bus);
|
pci_bus_assign_resources(slot->dev->bus);
|
||||||
|
|
||||||
cpci_enable_device(slot->dev);
|
|
||||||
|
|
||||||
dbg("%s - exit", __FUNCTION__);
|
dbg("%s - exit", __FUNCTION__);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -347,7 +311,7 @@ int cpci_unconfigure_slot(struct slot* slot)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
dev = pci_find_slot(slot->bus->number,
|
dev = pci_get_slot(slot->bus,
|
||||||
PCI_DEVFN(PCI_SLOT(slot->devfn), i));
|
PCI_DEVFN(PCI_SLOT(slot->devfn), i));
|
||||||
if (dev) {
|
if (dev) {
|
||||||
pci_remove_bus_device(dev);
|
pci_remove_bus_device(dev);
|
||||||
|
|
|
@ -1626,7 +1626,7 @@ int shpchprm_set_hpp(
|
||||||
pci_bus->number = func->bus;
|
pci_bus->number = func->bus;
|
||||||
devfn = PCI_DEVFN(func->device, func->function);
|
devfn = PCI_DEVFN(func->device, func->function);
|
||||||
|
|
||||||
ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus);
|
ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->slot_bus);
|
||||||
|
|
||||||
if (ab) {
|
if (ab) {
|
||||||
if (ab->_hpp) {
|
if (ab->_hpp) {
|
||||||
|
@ -1681,7 +1681,7 @@ void shpchprm_enable_card(
|
||||||
| PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
|
| PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
|
||||||
bcmd = bcommand = bcommand | PCI_BRIDGE_CTL_NO_ISA;
|
bcmd = bcommand = bcommand | PCI_BRIDGE_CTL_NO_ISA;
|
||||||
|
|
||||||
ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->bus);
|
ab = find_acpi_bridge_by_bus(acpi_bridges_head, ctrl->seg, ctrl->slot_bus);
|
||||||
if (ab) {
|
if (ab) {
|
||||||
if (ab->_hpp) {
|
if (ab->_hpp) {
|
||||||
if (ab->_hpp->enable_perr) {
|
if (ab->_hpp->enable_perr) {
|
||||||
|
|
|
@ -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);
|
return ata_pci_init_one(pdev, port_info, n_ports);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* piix_init -
|
|
||||||
*
|
|
||||||
* LOCKING:
|
|
||||||
*
|
|
||||||
* RETURNS:
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int __init piix_init(void)
|
static int __init piix_init(void)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
|
@ -689,13 +680,6 @@ static int __init piix_init(void)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* piix_exit -
|
|
||||||
*
|
|
||||||
* LOCKING:
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void __exit piix_exit(void)
|
static void __exit piix_exit(void)
|
||||||
{
|
{
|
||||||
pci_unregister_driver(&piix_pci_driver);
|
pci_unregister_driver(&piix_pci_driver);
|
||||||
|
|
|
@ -186,6 +186,28 @@ static void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
|
||||||
ata_wait_idle(ap);
|
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)
|
void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
|
||||||
{
|
{
|
||||||
if (ap->flags & ATA_FLAG_MMIO)
|
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
|
* @ap: port to which command is being issued
|
||||||
* @tf: ATA taskfile register set
|
* @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.
|
* synchronization with interrupt handler / other threads.
|
||||||
*
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
|
@ -235,6 +257,18 @@ static void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
|
||||||
ata_pause(ap);
|
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)
|
void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf)
|
||||||
{
|
{
|
||||||
if (ap->flags & ATA_FLAG_MMIO)
|
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
|
* @ap: Port from which input is read
|
||||||
* @tf: ATA taskfile register set for storing input
|
* @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)
|
void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
|
||||||
{
|
{
|
||||||
if (ap->flags & ATA_FLAG_MMIO)
|
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
|
* @ap: port where the device is
|
||||||
*
|
*
|
||||||
* Reads ATA taskfile status register for currently-selected device
|
* 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
|
* from this device
|
||||||
*
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
|
@ -397,7 +448,7 @@ static u8 ata_check_status_pio(struct ata_port *ap)
|
||||||
* @ap: port where the device is
|
* @ap: port where the device is
|
||||||
*
|
*
|
||||||
* Reads ATA taskfile status register for currently-selected device
|
* 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
|
* from this device
|
||||||
*
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
|
@ -408,6 +459,20 @@ static u8 ata_check_status_mmio(struct ata_port *ap)
|
||||||
return readb((void __iomem *) ap->ioaddr.status_addr);
|
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)
|
u8 ata_check_status(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
if (ap->flags & ATA_FLAG_MMIO)
|
if (ap->flags & ATA_FLAG_MMIO)
|
||||||
|
@ -415,6 +480,20 @@ u8 ata_check_status(struct ata_port *ap)
|
||||||
return ata_check_status_pio(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)
|
u8 ata_altstatus(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
if (ap->ops->check_altstatus)
|
if (ap->ops->check_altstatus)
|
||||||
|
@ -425,6 +504,20 @@ u8 ata_altstatus(struct ata_port *ap)
|
||||||
return inb(ap->ioaddr.altstatus_addr);
|
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)
|
u8 ata_chk_err(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
if (ap->ops->check_err)
|
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)
|
void ata_noop_dev_select (struct ata_port *ap, unsigned int device)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ata_std_dev_select - Select device 0/1 on ATA bus
|
* ata_std_dev_select - Select device 0/1 on ATA bus
|
||||||
* @ap: ATA channel to manipulate
|
* @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
|
* Use the method defined in the ATA specification to
|
||||||
* make either device 0, or device 1, active on the
|
* 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:
|
* LOCKING:
|
||||||
* caller.
|
* caller.
|
||||||
|
@ -1190,7 +1299,12 @@ err_out:
|
||||||
* ata_bus_probe - Reset and probe ATA bus
|
* ata_bus_probe - Reset and probe ATA bus
|
||||||
* @ap: Bus to probe
|
* @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:
|
* LOCKING:
|
||||||
|
* PCI/etc. bus probe sem.
|
||||||
*
|
*
|
||||||
* RETURNS:
|
* RETURNS:
|
||||||
* Zero on success, non-zero on error.
|
* Zero on success, non-zero on error.
|
||||||
|
@ -1229,10 +1343,14 @@ err_out:
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ata_port_probe -
|
* ata_port_probe - Mark port as enabled
|
||||||
* @ap:
|
* @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)
|
void ata_port_probe(struct ata_port *ap)
|
||||||
|
@ -1241,10 +1359,15 @@ void ata_port_probe(struct ata_port *ap)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __sata_phy_reset -
|
* __sata_phy_reset - Wake/reset a low-level SATA PHY
|
||||||
* @ap:
|
* @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:
|
* LOCKING:
|
||||||
|
* PCI/etc. bus probe sem.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void __sata_phy_reset(struct ata_port *ap)
|
void __sata_phy_reset(struct ata_port *ap)
|
||||||
|
@ -1289,10 +1412,14 @@ void __sata_phy_reset(struct ata_port *ap)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __sata_phy_reset -
|
* sata_phy_reset - Reset SATA bus.
|
||||||
* @ap:
|
* @ap: SATA port associated with target SATA PHY.
|
||||||
|
*
|
||||||
|
* This function resets the SATA bus, and then probes
|
||||||
|
* the bus for devices.
|
||||||
*
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
|
* PCI/etc. bus probe sem.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void sata_phy_reset(struct ata_port *ap)
|
void sata_phy_reset(struct ata_port *ap)
|
||||||
|
@ -1304,10 +1431,16 @@ void sata_phy_reset(struct ata_port *ap)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ata_port_disable -
|
* ata_port_disable - Disable port.
|
||||||
* @ap:
|
* @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)
|
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
|
* ata_set_mode - Program timings and issue SET FEATURES - XFER
|
||||||
* @ap: port on which timings will be programmed
|
* @ap: port on which timings will be programmed
|
||||||
*
|
*
|
||||||
|
* Set ATA device disk transfer mode (PIO3, UDMA6, etc.).
|
||||||
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
|
* PCI/etc. bus probe sem.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void ata_set_mode(struct ata_port *ap)
|
static void ata_set_mode(struct ata_port *ap)
|
||||||
|
@ -1467,7 +1603,10 @@ err_out:
|
||||||
* @tmout_pat: impatience timeout
|
* @tmout_pat: impatience timeout
|
||||||
* @tmout: overall 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 -
|
* ata_bus_edd - Issue EXECUTE DEVICE DIAGNOSTIC command.
|
||||||
* @ap:
|
* @ap: Port to reset and probe
|
||||||
|
*
|
||||||
|
* Use the EXECUTE DEVICE DIAGNOSTIC command to reset and
|
||||||
|
* probe the bus. Not often used these days.
|
||||||
*
|
*
|
||||||
* LOCKING:
|
* 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.
|
* the device is ATA or ATAPI.
|
||||||
*
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
* Inherited from caller. Some functions called by this function
|
* PCI/etc. bus probe sem.
|
||||||
* obtain the host_set lock.
|
* Obtains host_set lock.
|
||||||
*
|
*
|
||||||
* SIDE EFFECTS:
|
* SIDE EFFECTS:
|
||||||
* Sets ATA_FLAG_PORT_DISABLED if bus reset fails.
|
* 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_mode_out: (output) SET FEATURES - XFER MODE code
|
||||||
* @xfer_shift_out: (output) bit shift that selects this mode
|
* @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:
|
* LOCKING:
|
||||||
|
* PCI/etc. bus probe sem.
|
||||||
*
|
*
|
||||||
* RETURNS:
|
* RETURNS:
|
||||||
* Zero on success, negative on error.
|
* 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
|
* @ap: Port associated with device @dev
|
||||||
* @dev: Device to which command will be sent
|
* @dev: Device to which command will be sent
|
||||||
*
|
*
|
||||||
|
* Issue SET FEATURES - XFER MODE command to device @dev
|
||||||
|
* on port @ap.
|
||||||
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
|
* PCI/etc. bus probe sem.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
|
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 -
|
* ata_sg_clean - Unmap DMA memory associated with command
|
||||||
* @qc:
|
* @qc: Command containing DMA memory to be released
|
||||||
|
*
|
||||||
|
* Unmap all mapped DMA memory associated with this command.
|
||||||
*
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
|
* spin_lock_irqsave(host_set lock)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void ata_sg_clean(struct ata_queued_cmd *qc)
|
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
|
* ata_fill_sg - Fill PCI IDE PRD table
|
||||||
* @qc: Metadata associated with taskfile to be transferred
|
* @qc: Metadata associated with taskfile to be transferred
|
||||||
*
|
*
|
||||||
|
* Fill PCI IDE PRD (scatter-gather) table with segments
|
||||||
|
* associated with the current disk command.
|
||||||
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
|
* spin_lock_irqsave(host_set lock)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static void ata_fill_sg(struct ata_queued_cmd *qc)
|
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
|
* ata_check_atapi_dma - Check whether ATAPI DMA can be supported
|
||||||
* @qc: Metadata associated with taskfile to check
|
* @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:
|
* LOCKING:
|
||||||
|
* spin_lock_irqsave(host_set lock)
|
||||||
|
*
|
||||||
* RETURNS: 0 when ATAPI DMA can be used
|
* RETURNS: 0 when ATAPI DMA can be used
|
||||||
* nonzero otherwise
|
* nonzero otherwise
|
||||||
*/
|
*/
|
||||||
|
@ -2046,6 +2210,8 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc)
|
||||||
* ata_qc_prep - Prepare taskfile for submission
|
* ata_qc_prep - Prepare taskfile for submission
|
||||||
* @qc: Metadata associated with taskfile to be prepared
|
* @qc: Metadata associated with taskfile to be prepared
|
||||||
*
|
*
|
||||||
|
* Prepare ATA taskfile for submission.
|
||||||
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
* spin_lock_irqsave(host_set lock)
|
* spin_lock_irqsave(host_set lock)
|
||||||
*/
|
*/
|
||||||
|
@ -2057,6 +2223,32 @@ void ata_qc_prep(struct ata_queued_cmd *qc)
|
||||||
ata_fill_sg(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)
|
void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
|
||||||
{
|
{
|
||||||
struct scatterlist *sg;
|
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;
|
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,
|
void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
|
||||||
unsigned int n_elem)
|
unsigned int n_elem)
|
||||||
{
|
{
|
||||||
|
@ -2083,14 +2301,16 @@ void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ata_sg_setup_one -
|
* ata_sg_setup_one - DMA-map the memory buffer associated with a command.
|
||||||
* @qc:
|
* @qc: Command with memory buffer to be mapped.
|
||||||
|
*
|
||||||
|
* DMA-map the memory buffer associated with queued_cmd @qc.
|
||||||
*
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
* spin_lock_irqsave(host_set lock)
|
* spin_lock_irqsave(host_set lock)
|
||||||
*
|
*
|
||||||
* RETURNS:
|
* RETURNS:
|
||||||
*
|
* Zero on success, negative on error.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int ata_sg_setup_one(struct ata_queued_cmd *qc)
|
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 -
|
* ata_sg_setup - DMA-map the scatter-gather table associated with a command.
|
||||||
* @qc:
|
* @qc: Command with scatter-gather table to be mapped.
|
||||||
|
*
|
||||||
|
* DMA-map the scatter-gather table associated with queued_cmd @qc.
|
||||||
*
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
* spin_lock_irqsave(host_set lock)
|
* spin_lock_irqsave(host_set lock)
|
||||||
*
|
*
|
||||||
* RETURNS:
|
* RETURNS:
|
||||||
|
* Zero on success, negative on error.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -2151,6 +2374,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
|
||||||
* @ap:
|
* @ap:
|
||||||
*
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
|
* None. (executing in kernel thread context)
|
||||||
*
|
*
|
||||||
* RETURNS:
|
* RETURNS:
|
||||||
*
|
*
|
||||||
|
@ -2198,6 +2422,7 @@ static unsigned long ata_pio_poll(struct ata_port *ap)
|
||||||
* @ap:
|
* @ap:
|
||||||
*
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
|
* None. (executing in kernel thread context)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void ata_pio_complete (struct ata_port *ap)
|
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);
|
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)
|
void swap_buf_le16(u16 *buf, unsigned int buf_words)
|
||||||
{
|
{
|
||||||
#ifdef __BIG_ENDIAN
|
#ifdef __BIG_ENDIAN
|
||||||
|
@ -2415,6 +2652,7 @@ err_out:
|
||||||
* @ap:
|
* @ap:
|
||||||
*
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
|
* None. (executing in kernel thread context)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void ata_pio_block(struct ata_port *ap)
|
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.
|
* transaction completed successfully.
|
||||||
*
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
|
* Inherited from SCSI layer (none, can sleep)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void ata_qc_timeout(struct ata_queued_cmd *qc)
|
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
|
* @dev: Device from whom we request an available command structure
|
||||||
*
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
|
* None.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
|
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
|
* @dev: Device from whom we request an available command structure
|
||||||
*
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
|
* None.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
|
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.
|
* in case something prevents using it.
|
||||||
*
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
|
* spin_lock_irqsave(host_set lock)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void ata_qc_free(struct ata_queued_cmd *qc)
|
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
|
* ata_qc_complete - Complete an active ATA command
|
||||||
* @qc: Command to complete
|
* @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:
|
* LOCKING:
|
||||||
|
* spin_lock_irqsave(host_set lock)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -2892,6 +3138,7 @@ err_out:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ata_qc_issue_prot - issue taskfile to device in proto-dependent manner
|
* ata_qc_issue_prot - issue taskfile to device in proto-dependent manner
|
||||||
* @qc: command to issue to device
|
* @qc: command to issue to device
|
||||||
|
@ -2901,6 +3148,8 @@ err_out:
|
||||||
* classes called "protocols", and issuing each type of protocol
|
* classes called "protocols", and issuing each type of protocol
|
||||||
* is slightly different.
|
* is slightly different.
|
||||||
*
|
*
|
||||||
|
* May be used as the qc_issue() entry in ata_port_operations.
|
||||||
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
* spin_lock_irqsave(host_set lock)
|
* 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.
|
* @qc: Info associated with this ATA transaction.
|
||||||
*
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
|
@ -3065,6 +3314,18 @@ static void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
|
||||||
ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
|
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)
|
void ata_bmdma_start(struct ata_queued_cmd *qc)
|
||||||
{
|
{
|
||||||
if (qc->ap->flags & ATA_FLAG_MMIO)
|
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_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)
|
void ata_bmdma_setup(struct ata_queued_cmd *qc)
|
||||||
{
|
{
|
||||||
if (qc->ap->flags & ATA_FLAG_MMIO)
|
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_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)
|
void ata_bmdma_irq_clear(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
if (ap->flags & ATA_FLAG_MMIO) {
|
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 ata_bmdma_status(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
u8 host_stat;
|
u8 host_stat;
|
||||||
|
@ -3104,6 +3405,19 @@ u8 ata_bmdma_status(struct ata_port *ap)
|
||||||
return host_stat;
|
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)
|
void ata_bmdma_stop(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
if (ap->flags & ATA_FLAG_MMIO) {
|
if (ap->flags & ATA_FLAG_MMIO) {
|
||||||
|
@ -3203,13 +3517,18 @@ idle_irq:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ata_interrupt - Default ATA host interrupt handler
|
* ata_interrupt - Default ATA host interrupt handler
|
||||||
* @irq: irq line
|
* @irq: irq line (unused)
|
||||||
* @dev_instance: pointer to our host information structure
|
* @dev_instance: pointer to our ata_host_set information structure
|
||||||
* @regs: unused
|
* @regs: unused
|
||||||
*
|
*
|
||||||
|
* Default interrupt handler for PCI IDE devices. Calls
|
||||||
|
* ata_host_intr() for each port that is not disabled.
|
||||||
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
|
* Obtains host_set lock during operation.
|
||||||
*
|
*
|
||||||
* RETURNS:
|
* RETURNS:
|
||||||
|
* IRQ_NONE or IRQ_HANDLED.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -3302,6 +3621,19 @@ err_out:
|
||||||
ata_qc_complete(qc, ATA_ERR);
|
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)
|
int ata_port_start (struct ata_port *ap)
|
||||||
{
|
{
|
||||||
struct device *dev = ap->host_set->dev;
|
struct device *dev = ap->host_set->dev;
|
||||||
|
@ -3315,6 +3647,18 @@ int ata_port_start (struct ata_port *ap)
|
||||||
return 0;
|
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)
|
void ata_port_stop (struct ata_port *ap)
|
||||||
{
|
{
|
||||||
struct device *dev = ap->host_set->dev;
|
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
|
* @ent: Probe information provided by low-level driver
|
||||||
* @port_no: Port number associated with this ata_port
|
* @port_no: Port number associated with this ata_port
|
||||||
*
|
*
|
||||||
|
* Initialize a new ata_port structure, and its associated
|
||||||
|
* scsi_host.
|
||||||
|
*
|
||||||
* LOCKING:
|
* 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
|
* @host_set: Collections of ports to which we add
|
||||||
* @port_no: Port number associated with this host
|
* @port_no: Port number associated with this host
|
||||||
*
|
*
|
||||||
|
* Attach low-level ATA driver to system.
|
||||||
|
*
|
||||||
* LOCKING:
|
* LOCKING:
|
||||||
|
* PCI/etc. bus probe sem.
|
||||||
*
|
*
|
||||||
* RETURNS:
|
* RETURNS:
|
||||||
|
* New ata_port on success, for NULL on error.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -3447,12 +3799,22 @@ err_out:
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ata_device_add -
|
* ata_device_add - Register hardware device with ATA and SCSI layers
|
||||||
* @ent:
|
* @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:
|
* LOCKING:
|
||||||
|
* PCI/etc. bus probe sem.
|
||||||
*
|
*
|
||||||
* RETURNS:
|
* 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.
|
* ata_std_ports - initialize ioaddr with standard port offsets.
|
||||||
* @ioaddr: IO address structure to be initialized
|
* @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)
|
void ata_std_ports(struct ata_ioports *ioaddr)
|
||||||
{
|
{
|
||||||
ioaddr->data_addr = ioaddr->cmd_addr + ATA_REG_DATA;
|
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;
|
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
|
#ifdef CONFIG_PCI
|
||||||
struct ata_probe_ent *
|
struct ata_probe_ent *
|
||||||
ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port)
|
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
|
* @port_info: Information from low-level host driver
|
||||||
* @n_ports: Number of ports attached to host controller
|
* @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:
|
* LOCKING:
|
||||||
* Inherited from PCI layer (may sleep).
|
* Inherited from PCI layer (may sleep).
|
||||||
*
|
*
|
||||||
* RETURNS:
|
* 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 */
|
#endif /* CONFIG_PCI */
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ata_init -
|
|
||||||
*
|
|
||||||
* LOCKING:
|
|
||||||
*
|
|
||||||
* RETURNS:
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int __init ata_init(void)
|
static int __init ata_init(void)
|
||||||
{
|
{
|
||||||
ata_wq = create_workqueue("ata");
|
ata_wq = create_workqueue("ata");
|
||||||
|
|
|
@ -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.
|
* @args: device IDENTIFY data / SCSI command of interest.
|
||||||
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
|
* @rbuf: Response buffer, to which simulated SCSI cmd output is sent.
|
||||||
* @buflen: Response buffer length.
|
* @buflen: Response buffer length.
|
||||||
|
|
|
@ -507,6 +507,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
|
||||||
int ret, i;
|
int ret, i;
|
||||||
unsigned int id, lun;
|
unsigned int id, lun;
|
||||||
unsigned long serial;
|
unsigned long serial;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
if (!CMD_SP(cmd))
|
if (!CMD_SP(cmd))
|
||||||
return FAILED;
|
return FAILED;
|
||||||
|
@ -519,7 +520,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
|
||||||
|
|
||||||
/* Check active list for command command. */
|
/* Check active list for command command. */
|
||||||
spin_unlock_irq(ha->host->host_lock);
|
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++) {
|
for (i = 1; i < MAX_OUTSTANDING_COMMANDS; i++) {
|
||||||
sp = ha->outstanding_cmds[i];
|
sp = ha->outstanding_cmds[i];
|
||||||
|
|
||||||
|
@ -534,7 +535,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
|
||||||
sp->state));
|
sp->state));
|
||||||
DEBUG3(qla2x00_print_scsi_cmd(cmd);)
|
DEBUG3(qla2x00_print_scsi_cmd(cmd);)
|
||||||
|
|
||||||
spin_unlock(&ha->hardware_lock);
|
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||||
if (qla2x00_abort_command(ha, sp)) {
|
if (qla2x00_abort_command(ha, sp)) {
|
||||||
DEBUG2(printk("%s(%ld): abort_command "
|
DEBUG2(printk("%s(%ld): abort_command "
|
||||||
"mbx failed.\n", __func__, ha->host_no));
|
"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));
|
"mbx success.\n", __func__, ha->host_no));
|
||||||
ret = SUCCESS;
|
ret = SUCCESS;
|
||||||
}
|
}
|
||||||
spin_lock(&ha->hardware_lock);
|
spin_lock_irqsave(&ha->hardware_lock, flags);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||||
|
|
||||||
/* Wait for the command to be returned. */
|
/* Wait for the command to be returned. */
|
||||||
if (ret == SUCCESS) {
|
if (ret == SUCCESS) {
|
||||||
spin_unlock(&ha->hardware_lock);
|
|
||||||
if (qla2x00_eh_wait_on_command(ha, cmd) != QLA_SUCCESS) {
|
if (qla2x00_eh_wait_on_command(ha, cmd) != QLA_SUCCESS) {
|
||||||
qla_printk(KERN_ERR, ha,
|
qla_printk(KERN_ERR, ha,
|
||||||
"scsi(%ld:%d:%d): Abort handler timed out -- %lx "
|
"scsi(%ld:%d:%d): Abort handler timed out -- %lx "
|
||||||
"%x.\n", ha->host_no, id, lun, serial, ret);
|
"%x.\n", ha->host_no, id, lun, serial, ret);
|
||||||
}
|
}
|
||||||
spin_lock(&ha->hardware_lock);
|
|
||||||
}
|
}
|
||||||
spin_lock_irq(ha->host->host_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;
|
int status;
|
||||||
srb_t *sp;
|
srb_t *sp;
|
||||||
struct scsi_cmnd *cmd;
|
struct scsi_cmnd *cmd;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
status = 0;
|
status = 0;
|
||||||
|
|
||||||
|
@ -596,11 +597,11 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t)
|
||||||
* array
|
* array
|
||||||
*/
|
*/
|
||||||
for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
|
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];
|
sp = ha->outstanding_cmds[cnt];
|
||||||
if (sp) {
|
if (sp) {
|
||||||
cmd = sp->cmd;
|
cmd = sp->cmd;
|
||||||
spin_unlock(&ha->hardware_lock);
|
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||||
if (cmd->device->id == t) {
|
if (cmd->device->id == t) {
|
||||||
if (!qla2x00_eh_wait_on_command(ha, cmd)) {
|
if (!qla2x00_eh_wait_on_command(ha, cmd)) {
|
||||||
status = 1;
|
status = 1;
|
||||||
|
@ -608,7 +609,7 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
spin_unlock(&ha->hardware_lock);
|
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (status);
|
return (status);
|
||||||
|
@ -740,6 +741,7 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha)
|
||||||
int status;
|
int status;
|
||||||
srb_t *sp;
|
srb_t *sp;
|
||||||
struct scsi_cmnd *cmd;
|
struct scsi_cmnd *cmd;
|
||||||
|
unsigned long flags;
|
||||||
|
|
||||||
status = 1;
|
status = 1;
|
||||||
|
|
||||||
|
@ -748,17 +750,17 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha)
|
||||||
* array
|
* array
|
||||||
*/
|
*/
|
||||||
for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
|
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];
|
sp = ha->outstanding_cmds[cnt];
|
||||||
if (sp) {
|
if (sp) {
|
||||||
cmd = sp->cmd;
|
cmd = sp->cmd;
|
||||||
spin_unlock(&ha->hardware_lock);
|
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||||
status = qla2x00_eh_wait_on_command(ha, cmd);
|
status = qla2x00_eh_wait_on_command(ha, cmd);
|
||||||
if (status == 0)
|
if (status == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
spin_unlock(&ha->hardware_lock);
|
spin_unlock_irqrestore(&ha->hardware_lock, flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return (status);
|
return (status);
|
||||||
|
|
|
@ -1197,6 +1197,7 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel,
|
||||||
if (!starget)
|
if (!starget)
|
||||||
return ERR_PTR(-ENOMEM);
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
get_device(&starget->dev);
|
||||||
down(&shost->scan_mutex);
|
down(&shost->scan_mutex);
|
||||||
res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
|
res = scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata);
|
||||||
if (res != SCSI_SCAN_LUN_PRESENT)
|
if (res != SCSI_SCAN_LUN_PRESENT)
|
||||||
|
|
|
@ -234,7 +234,7 @@ static inline const char *siu_type_name(struct uart_port *port)
|
||||||
return "DSIU";
|
return "DSIU";
|
||||||
}
|
}
|
||||||
|
|
||||||
return "unknown";
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int siu_tx_empty(struct uart_port *port)
|
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;
|
struct uart_port *port;
|
||||||
uint8_t iir, lsr;
|
uint8_t iir, lsr;
|
||||||
|
|
||||||
if (dev_id == NULL)
|
|
||||||
return IRQ_NONE;
|
|
||||||
|
|
||||||
port = (struct uart_port *)dev_id;
|
port = (struct uart_port *)dev_id;
|
||||||
|
|
||||||
iir = siu_read(port, UART_IIR);
|
iir = siu_read(port, UART_IIR);
|
||||||
|
@ -507,6 +504,9 @@ static int siu_startup(struct uart_port *port)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
|
if (port->membase == NULL)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
siu_clear_fifo(port);
|
siu_clear_fifo(port);
|
||||||
|
|
||||||
(void)siu_read(port, UART_LSR);
|
(void)siu_read(port, UART_LSR);
|
||||||
|
@ -545,9 +545,6 @@ static void siu_shutdown(struct uart_port *port)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
uint8_t lcr;
|
uint8_t lcr;
|
||||||
|
|
||||||
if (port->membase == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
siu_write(port, UART_IER, 0);
|
siu_write(port, UART_IER, 0);
|
||||||
|
|
||||||
spin_lock_irqsave(&port->lock, flags);
|
spin_lock_irqsave(&port->lock, flags);
|
||||||
|
@ -802,53 +799,6 @@ static int siu_init_ports(void)
|
||||||
|
|
||||||
#ifdef CONFIG_SERIAL_VR41XX_CONSOLE
|
#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)
|
#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
|
||||||
|
|
||||||
static void wait_for_xmitr(struct uart_port *port)
|
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->membase == NULL) {
|
||||||
if (port->mapbase == 0)
|
if (port->mapbase == 0)
|
||||||
return -ENODEV;
|
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);
|
vr41xx_select_siu_interface(SIU_INTERFACE_RS232C);
|
||||||
|
@ -949,7 +899,7 @@ static int __devinit siu_console_init(void)
|
||||||
|
|
||||||
for (i = 0; i < num; i++) {
|
for (i = 0; i < num; i++) {
|
||||||
port = &siu_uart_ports[i];
|
port = &siu_uart_ports[i];
|
||||||
port->ops = &early_uart_ops;
|
port->ops = &siu_uart_ops;
|
||||||
}
|
}
|
||||||
|
|
||||||
register_console(&siu_console);
|
register_console(&siu_console);
|
||||||
|
@ -994,9 +944,11 @@ static int siu_probe(struct device *dev)
|
||||||
port->dev = dev;
|
port->dev = dev;
|
||||||
|
|
||||||
retval = uart_add_one_port(&siu_uart_driver, port);
|
retval = uart_add_one_port(&siu_uart_driver, port);
|
||||||
if (retval)
|
if (retval < 0) {
|
||||||
|
port->dev = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (i == 0 && retval < 0) {
|
if (i == 0 && retval < 0) {
|
||||||
uart_unregister_driver(&siu_uart_driver);
|
uart_unregister_driver(&siu_uart_driver);
|
||||||
|
|
|
@ -290,32 +290,30 @@ static ssize_t show_modalias(struct device *dev, char *buf)
|
||||||
{
|
{
|
||||||
struct usb_interface *intf;
|
struct usb_interface *intf;
|
||||||
struct usb_device *udev;
|
struct usb_device *udev;
|
||||||
|
int len;
|
||||||
|
|
||||||
intf = to_usb_interface(dev);
|
intf = to_usb_interface(dev);
|
||||||
udev = interface_to_usbdev(intf);
|
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,
|
|
||||||
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.idVendor),
|
||||||
le16_to_cpu(udev->descriptor.idProduct),
|
le16_to_cpu(udev->descriptor.idProduct),
|
||||||
le16_to_cpu(udev->descriptor.bcdDevice),
|
le16_to_cpu(udev->descriptor.bcdDevice),
|
||||||
udev->descriptor.bDeviceClass,
|
udev->descriptor.bDeviceClass,
|
||||||
udev->descriptor.bDeviceSubClass,
|
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 len + sprintf(buf, "*isc*ip*\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
|
static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL);
|
||||||
|
|
||||||
|
|
|
@ -124,3 +124,14 @@ config USB_SL811_HCD
|
||||||
To compile this driver as a module, choose M here: the
|
To compile this driver as a module, choose M here: the
|
||||||
module will be called sl811-hcd.
|
module will be called sl811-hcd.
|
||||||
|
|
||||||
|
config USB_SL811_CS
|
||||||
|
tristate "CF/PCMCIA support for SL811HS HCD"
|
||||||
|
depends on USB_SL811_HCD && PCMCIA
|
||||||
|
default N
|
||||||
|
help
|
||||||
|
Wraps a PCMCIA driver around the SL811HS HCD, supporting the RATOC
|
||||||
|
REX-CFU1U CF card (often used with PDAs). If unsure, say N.
|
||||||
|
|
||||||
|
To compile this driver as a module, choose M here: the
|
||||||
|
module will be called "sl811_cs".
|
||||||
|
|
||||||
|
|
|
@ -7,4 +7,5 @@ obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o
|
||||||
obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o
|
obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o
|
||||||
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o
|
obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o
|
||||||
obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o
|
obj-$(CONFIG_USB_SL811_HCD) += sl811-hcd.o
|
||||||
|
obj-$(CONFIG_USB_SL811_CS) += sl811_cs.o
|
||||||
obj-$(CONFIG_ETRAX_ARCH_V10) += hc_crisv10.o
|
obj-$(CONFIG_ETRAX_ARCH_V10) += hc_crisv10.o
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* SL811HS HCD (Host Controller Driver) for USB.
|
* SL811HS HCD (Host Controller Driver) for USB.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2004 Psion Teklogix (for NetBook PRO)
|
* Copyright (C) 2004 Psion Teklogix (for NetBook PRO)
|
||||||
* Copyright (C) 2004 David Brownell
|
* Copyright (C) 2004-2005 David Brownell
|
||||||
*
|
*
|
||||||
* Periodic scheduling is based on Roman's OHCI code
|
* Periodic scheduling is based on Roman's OHCI code
|
||||||
* Copyright (C) 1999 Roman Weissgaerber
|
* Copyright (C) 1999 Roman Weissgaerber
|
||||||
|
@ -67,7 +67,7 @@
|
||||||
MODULE_DESCRIPTION("SL811HS USB Host Controller Driver");
|
MODULE_DESCRIPTION("SL811HS USB Host Controller Driver");
|
||||||
MODULE_LICENSE("GPL");
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
#define DRIVER_VERSION "15 Dec 2004"
|
#define DRIVER_VERSION "19 May 2005"
|
||||||
|
|
||||||
|
|
||||||
#ifndef DEBUG
|
#ifndef DEBUG
|
||||||
|
@ -121,6 +121,10 @@ static void port_power(struct sl811 *sl811, int is_on)
|
||||||
/* reset as thoroughly as we can */
|
/* reset as thoroughly as we can */
|
||||||
if (sl811->board && sl811->board->reset)
|
if (sl811->board && sl811->board->reset)
|
||||||
sl811->board->reset(hcd->self.controller);
|
sl811->board->reset(hcd->self.controller);
|
||||||
|
else {
|
||||||
|
sl811_write(sl811, SL11H_CTLREG1, SL11H_CTL1MASK_SE0);
|
||||||
|
mdelay(20);
|
||||||
|
}
|
||||||
|
|
||||||
sl811_write(sl811, SL11H_IRQ_ENABLE, 0);
|
sl811_write(sl811, SL11H_IRQ_ENABLE, 0);
|
||||||
sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1);
|
sl811_write(sl811, SL11H_CTLREG1, sl811->ctrl1);
|
||||||
|
@ -443,6 +447,7 @@ static void finish_request(
|
||||||
spin_lock(&urb->lock);
|
spin_lock(&urb->lock);
|
||||||
if (urb->status == -EINPROGRESS)
|
if (urb->status == -EINPROGRESS)
|
||||||
urb->status = status;
|
urb->status = status;
|
||||||
|
urb->hcpriv = NULL;
|
||||||
spin_unlock(&urb->lock);
|
spin_unlock(&urb->lock);
|
||||||
|
|
||||||
spin_unlock(&sl811->lock);
|
spin_unlock(&sl811->lock);
|
||||||
|
@ -661,9 +666,9 @@ retry:
|
||||||
|
|
||||||
#ifdef QUIRK2
|
#ifdef QUIRK2
|
||||||
/* this may no longer be necessary ... */
|
/* this may no longer be necessary ... */
|
||||||
if (irqstat == 0 && ret == IRQ_NONE) {
|
if (irqstat == 0) {
|
||||||
irqstat = checkdone(sl811);
|
irqstat = checkdone(sl811);
|
||||||
if (irqstat /* && irq != ~0 */ )
|
if (irqstat)
|
||||||
sl811->stat_lost++;
|
sl811->stat_lost++;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -722,7 +727,8 @@ retry:
|
||||||
if (sl811->active_a) {
|
if (sl811->active_a) {
|
||||||
sl811_write(sl811, SL811_EP_A(SL11H_HOSTCTLREG), 0);
|
sl811_write(sl811, SL811_EP_A(SL11H_HOSTCTLREG), 0);
|
||||||
finish_request(sl811, sl811->active_a,
|
finish_request(sl811, sl811->active_a,
|
||||||
container_of(sl811->active_a->hep->urb_list.next,
|
container_of(sl811->active_a
|
||||||
|
->hep->urb_list.next,
|
||||||
struct urb, urb_list),
|
struct urb, urb_list),
|
||||||
NULL, -ESHUTDOWN);
|
NULL, -ESHUTDOWN);
|
||||||
sl811->active_a = NULL;
|
sl811->active_a = NULL;
|
||||||
|
@ -731,7 +737,8 @@ retry:
|
||||||
if (sl811->active_b) {
|
if (sl811->active_b) {
|
||||||
sl811_write(sl811, SL811_EP_B(SL11H_HOSTCTLREG), 0);
|
sl811_write(sl811, SL811_EP_B(SL11H_HOSTCTLREG), 0);
|
||||||
finish_request(sl811, sl811->active_b,
|
finish_request(sl811, sl811->active_b,
|
||||||
container_of(sl811->active_b->hep->urb_list.next,
|
container_of(sl811->active_b
|
||||||
|
->hep->urb_list.next,
|
||||||
struct urb, urb_list),
|
struct urb, urb_list),
|
||||||
NULL, -ESHUTDOWN);
|
NULL, -ESHUTDOWN);
|
||||||
sl811->active_b = NULL;
|
sl811->active_b = NULL;
|
||||||
|
@ -890,6 +897,7 @@ static int sl811h_urb_enqueue(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ep->hep = hep;
|
||||||
hep->hcpriv = ep;
|
hep->hcpriv = ep;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -961,15 +969,16 @@ fail:
|
||||||
static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
|
static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
|
||||||
{
|
{
|
||||||
struct sl811 *sl811 = hcd_to_sl811(hcd);
|
struct sl811 *sl811 = hcd_to_sl811(hcd);
|
||||||
struct usb_host_endpoint *hep = urb->hcpriv;
|
struct usb_host_endpoint *hep;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
struct sl811h_ep *ep;
|
struct sl811h_ep *ep;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
if (!hep)
|
|
||||||
return -EINVAL;
|
|
||||||
|
|
||||||
spin_lock_irqsave(&sl811->lock, flags);
|
spin_lock_irqsave(&sl811->lock, flags);
|
||||||
|
hep = urb->hcpriv;
|
||||||
|
if (!hep)
|
||||||
|
goto fail;
|
||||||
|
|
||||||
ep = hep->hcpriv;
|
ep = hep->hcpriv;
|
||||||
if (ep) {
|
if (ep) {
|
||||||
/* finish right away if this urb can't be active ...
|
/* finish right away if this urb can't be active ...
|
||||||
|
@ -1017,6 +1026,7 @@ static int sl811h_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
|
||||||
VDBG("dequeue, urb %p active %s; wait4irq\n", urb,
|
VDBG("dequeue, urb %p active %s; wait4irq\n", urb,
|
||||||
(sl811->active_a == ep) ? "A" : "B");
|
(sl811->active_a == ep) ? "A" : "B");
|
||||||
} else
|
} else
|
||||||
|
fail:
|
||||||
retval = -EINVAL;
|
retval = -EINVAL;
|
||||||
spin_unlock_irqrestore(&sl811->lock, flags);
|
spin_unlock_irqrestore(&sl811->lock, flags);
|
||||||
return retval;
|
return retval;
|
||||||
|
@ -1576,6 +1586,9 @@ sl811h_start(struct usb_hcd *hcd)
|
||||||
if (sl811->board && sl811->board->power)
|
if (sl811->board && sl811->board->power)
|
||||||
hub_set_power_budget(udev, sl811->board->power * 2);
|
hub_set_power_budget(udev, sl811->board->power * 2);
|
||||||
|
|
||||||
|
/* enable power and interupts */
|
||||||
|
port_power(sl811, 1);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1618,7 +1631,7 @@ static struct hc_driver sl811h_hc_driver = {
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static int __init_or_module
|
static int __devexit
|
||||||
sl811h_remove(struct device *dev)
|
sl811h_remove(struct device *dev)
|
||||||
{
|
{
|
||||||
struct usb_hcd *hcd = dev_get_drvdata(dev);
|
struct usb_hcd *hcd = dev_get_drvdata(dev);
|
||||||
|
@ -1631,21 +1644,20 @@ sl811h_remove(struct device *dev)
|
||||||
remove_debug_file(sl811);
|
remove_debug_file(sl811);
|
||||||
usb_remove_hcd(hcd);
|
usb_remove_hcd(hcd);
|
||||||
|
|
||||||
iounmap(sl811->data_reg);
|
/* some platforms may use IORESOURCE_IO */
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||||
release_mem_region(res->start, 1);
|
if (res)
|
||||||
|
iounmap(sl811->data_reg);
|
||||||
|
|
||||||
iounmap(sl811->addr_reg);
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
release_mem_region(res->start, 1);
|
if (res)
|
||||||
|
iounmap(sl811->addr_reg);
|
||||||
|
|
||||||
usb_put_hcd(hcd);
|
usb_put_hcd(hcd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define resource_len(r) (((r)->end - (r)->start) + 1)
|
static int __devinit
|
||||||
|
|
||||||
static int __init
|
|
||||||
sl811h_probe(struct device *dev)
|
sl811h_probe(struct device *dev)
|
||||||
{
|
{
|
||||||
struct usb_hcd *hcd;
|
struct usb_hcd *hcd;
|
||||||
|
@ -1656,7 +1668,7 @@ sl811h_probe(struct device *dev)
|
||||||
void __iomem *addr_reg;
|
void __iomem *addr_reg;
|
||||||
void __iomem *data_reg;
|
void __iomem *data_reg;
|
||||||
int retval;
|
int retval;
|
||||||
u8 tmp;
|
u8 tmp, ioaddr = 0;
|
||||||
|
|
||||||
/* basic sanity checks first. board-specific init logic should
|
/* basic sanity checks first. board-specific init logic should
|
||||||
* have initialized these three resources and probably board
|
* have initialized these three resources and probably board
|
||||||
|
@ -1664,13 +1676,8 @@ sl811h_probe(struct device *dev)
|
||||||
* minimal sanity checking.
|
* minimal sanity checking.
|
||||||
*/
|
*/
|
||||||
pdev = container_of(dev, struct platform_device, dev);
|
pdev = container_of(dev, struct platform_device, dev);
|
||||||
if (pdev->num_resources < 3)
|
|
||||||
return -ENODEV;
|
|
||||||
|
|
||||||
addr = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
||||||
data = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
|
||||||
irq = platform_get_irq(pdev, 0);
|
irq = platform_get_irq(pdev, 0);
|
||||||
if (!addr || !data || irq < 0)
|
if (pdev->num_resources < 3 || irq < 0)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
/* refuse to confuse usbcore */
|
/* refuse to confuse usbcore */
|
||||||
|
@ -1679,25 +1686,32 @@ sl811h_probe(struct device *dev)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!request_mem_region(addr->start, 1, hcd_name)) {
|
/* the chip may be wired for either kind of addressing */
|
||||||
|
addr = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
data = platform_get_resource(pdev, IORESOURCE_MEM, 1);
|
||||||
retval = -EBUSY;
|
retval = -EBUSY;
|
||||||
goto err1;
|
if (!addr || !data) {
|
||||||
}
|
addr = platform_get_resource(pdev, IORESOURCE_IO, 0);
|
||||||
addr_reg = ioremap(addr->start, resource_len(addr));
|
data = platform_get_resource(pdev, IORESOURCE_IO, 1);
|
||||||
|
if (!addr || !data)
|
||||||
|
return -ENODEV;
|
||||||
|
ioaddr = 1;
|
||||||
|
|
||||||
|
addr_reg = (void __iomem *) addr->start;
|
||||||
|
data_reg = (void __iomem *) data->start;
|
||||||
|
} else {
|
||||||
|
addr_reg = ioremap(addr->start, 1);
|
||||||
if (addr_reg == NULL) {
|
if (addr_reg == NULL) {
|
||||||
retval = -ENOMEM;
|
retval = -ENOMEM;
|
||||||
goto err2;
|
goto err2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!request_mem_region(data->start, 1, hcd_name)) {
|
data_reg = ioremap(data->start, 1);
|
||||||
retval = -EBUSY;
|
|
||||||
goto err3;
|
|
||||||
}
|
|
||||||
data_reg = ioremap(data->start, resource_len(addr));
|
|
||||||
if (data_reg == NULL) {
|
if (data_reg == NULL) {
|
||||||
retval = -ENOMEM;
|
retval = -ENOMEM;
|
||||||
goto err4;
|
goto err4;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* allocate and initialize hcd */
|
/* allocate and initialize hcd */
|
||||||
hcd = usb_create_hcd(&sl811h_hc_driver, dev, dev->bus_id);
|
hcd = usb_create_hcd(&sl811h_hc_driver, dev, dev->bus_id);
|
||||||
|
@ -1737,12 +1751,14 @@ sl811h_probe(struct device *dev)
|
||||||
goto err6;
|
goto err6;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sl811s would need a different handler for this irq */
|
/* The chip's IRQ is level triggered, active high. A requirement
|
||||||
#ifdef CONFIG_ARM
|
* for platform device setup is to cope with things like signal
|
||||||
/* Cypress docs say the IRQ is IRQT_HIGH ... */
|
* inverters (e.g. CF is active low) or working only with edge
|
||||||
set_irq_type(irq, IRQT_RISING);
|
* triggers (e.g. most ARM CPUs). Initial driver stress testing
|
||||||
#endif
|
* was on a system with single edge triggering, so most sorts of
|
||||||
retval = usb_add_hcd(hcd, irq, SA_INTERRUPT);
|
* triggering arrangement should work.
|
||||||
|
*/
|
||||||
|
retval = usb_add_hcd(hcd, irq, SA_INTERRUPT | SA_SHIRQ);
|
||||||
if (retval != 0)
|
if (retval != 0)
|
||||||
goto err6;
|
goto err6;
|
||||||
|
|
||||||
|
@ -1752,14 +1768,12 @@ sl811h_probe(struct device *dev)
|
||||||
err6:
|
err6:
|
||||||
usb_put_hcd(hcd);
|
usb_put_hcd(hcd);
|
||||||
err5:
|
err5:
|
||||||
|
if (!ioaddr)
|
||||||
iounmap(data_reg);
|
iounmap(data_reg);
|
||||||
err4:
|
err4:
|
||||||
release_mem_region(data->start, 1);
|
if (!ioaddr)
|
||||||
err3:
|
|
||||||
iounmap(addr_reg);
|
iounmap(addr_reg);
|
||||||
err2:
|
err2:
|
||||||
release_mem_region(addr->start, 1);
|
|
||||||
err1:
|
|
||||||
DBG("init error, %d\n", retval);
|
DBG("init error, %d\n", retval);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
@ -1821,16 +1835,18 @@ sl811h_resume(struct device *dev, u32 phase)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static struct device_driver sl811h_driver = {
|
/* this driver is exported so sl811_cs can depend on it */
|
||||||
|
struct device_driver sl811h_driver = {
|
||||||
.name = (char *) hcd_name,
|
.name = (char *) hcd_name,
|
||||||
.bus = &platform_bus_type,
|
.bus = &platform_bus_type,
|
||||||
|
|
||||||
.probe = sl811h_probe,
|
.probe = sl811h_probe,
|
||||||
.remove = sl811h_remove,
|
.remove = __devexit_p(sl811h_remove),
|
||||||
|
|
||||||
.suspend = sl811h_suspend,
|
.suspend = sl811h_suspend,
|
||||||
.resume = sl811h_resume,
|
.resume = sl811h_resume,
|
||||||
};
|
};
|
||||||
|
EXPORT_SYMBOL(sl811h_driver);
|
||||||
|
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,442 @@
|
||||||
|
/*
|
||||||
|
* PCMCIA driver for SL811HS (as found in REX-CFU1U)
|
||||||
|
* Filename: sl811_cs.c
|
||||||
|
* Author: Yukio Yamamoto
|
||||||
|
*
|
||||||
|
* Port to sl811-hcd and 2.6.x by
|
||||||
|
* Botond Botyanszki <boti@rocketmail.com>
|
||||||
|
* Simon Pickering
|
||||||
|
*
|
||||||
|
* Last update: 2005-05-12
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/ptrace.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
#include <linux/timer.h>
|
||||||
|
#include <linux/ioport.h>
|
||||||
|
|
||||||
|
#include <pcmcia/version.h>
|
||||||
|
#include <pcmcia/cs_types.h>
|
||||||
|
#include <pcmcia/cs.h>
|
||||||
|
#include <pcmcia/cistpl.h>
|
||||||
|
#include <pcmcia/cisreg.h>
|
||||||
|
#include <pcmcia/ds.h>
|
||||||
|
|
||||||
|
#include <linux/usb_sl811.h>
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Botond Botyanszki");
|
||||||
|
MODULE_DESCRIPTION("REX-CFU1U PCMCIA driver for 2.6");
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
|
|
||||||
|
/*====================================================================*/
|
||||||
|
/* MACROS */
|
||||||
|
/*====================================================================*/
|
||||||
|
|
||||||
|
#if defined(DEBUG) || defined(CONFIG_USB_DEBUG) || defined(PCMCIA_DEBUG)
|
||||||
|
|
||||||
|
static int pc_debug = 0;
|
||||||
|
module_param(pc_debug, int, 0644);
|
||||||
|
|
||||||
|
#define DBG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG "sl811_cs: " args)
|
||||||
|
|
||||||
|
#else
|
||||||
|
#define DBG(n, args...) do{}while(0)
|
||||||
|
#endif /* no debugging */
|
||||||
|
|
||||||
|
#define INFO(args...) printk(KERN_INFO "sl811_cs: " args)
|
||||||
|
|
||||||
|
#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444)
|
||||||
|
|
||||||
|
#define CS_CHECK(fn, ret) \
|
||||||
|
do { \
|
||||||
|
last_fn = (fn); \
|
||||||
|
if ((last_ret = (ret)) != 0) \
|
||||||
|
goto cs_failed; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/*====================================================================*/
|
||||||
|
/* VARIABLES */
|
||||||
|
/*====================================================================*/
|
||||||
|
|
||||||
|
static const char driver_name[DEV_NAME_LEN] = "sl811_cs";
|
||||||
|
|
||||||
|
static dev_link_t *dev_list = NULL;
|
||||||
|
|
||||||
|
static int irq_list[4] = { -1 };
|
||||||
|
static int irq_list_count;
|
||||||
|
|
||||||
|
module_param_array(irq_list, int, &irq_list_count, 0444);
|
||||||
|
|
||||||
|
INT_MODULE_PARM(irq_mask, 0xdeb8);
|
||||||
|
|
||||||
|
typedef struct local_info_t {
|
||||||
|
dev_link_t link;
|
||||||
|
dev_node_t node;
|
||||||
|
} local_info_t;
|
||||||
|
|
||||||
|
/*====================================================================*/
|
||||||
|
|
||||||
|
static void release_platform_dev(struct device * dev)
|
||||||
|
{
|
||||||
|
DBG(0, "sl811_cs platform_dev release\n");
|
||||||
|
dev->parent = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct sl811_platform_data platform_data = {
|
||||||
|
.potpg = 100,
|
||||||
|
.power = 50, /* == 100mA */
|
||||||
|
// .reset = ... FIXME: invoke CF reset on the card
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct resource resources[] = {
|
||||||
|
[0] = {
|
||||||
|
.flags = IORESOURCE_IRQ,
|
||||||
|
},
|
||||||
|
[1] = {
|
||||||
|
// .name = "address",
|
||||||
|
.flags = IORESOURCE_IO,
|
||||||
|
},
|
||||||
|
[2] = {
|
||||||
|
// .name = "data",
|
||||||
|
.flags = IORESOURCE_IO,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
extern struct device_driver sl811h_driver;
|
||||||
|
|
||||||
|
static struct platform_device platform_dev = {
|
||||||
|
.id = -1,
|
||||||
|
.dev = {
|
||||||
|
.platform_data = &platform_data,
|
||||||
|
.release = release_platform_dev,
|
||||||
|
},
|
||||||
|
.resource = resources,
|
||||||
|
.num_resources = ARRAY_SIZE(resources),
|
||||||
|
};
|
||||||
|
|
||||||
|
static int sl811_hc_init(struct device *parent, ioaddr_t base_addr, int irq)
|
||||||
|
{
|
||||||
|
if (platform_dev.dev.parent)
|
||||||
|
return -EBUSY;
|
||||||
|
platform_dev.dev.parent = parent;
|
||||||
|
|
||||||
|
/* finish seting up the platform device */
|
||||||
|
resources[0].start = irq;
|
||||||
|
|
||||||
|
resources[1].start = base_addr;
|
||||||
|
resources[1].end = base_addr;
|
||||||
|
|
||||||
|
resources[2].start = base_addr + 1;
|
||||||
|
resources[2].end = base_addr + 1;
|
||||||
|
|
||||||
|
/* The driver core will probe for us. We know sl811-hcd has been
|
||||||
|
* initialized already because of the link order dependency.
|
||||||
|
*/
|
||||||
|
platform_dev.name = sl811h_driver.name;
|
||||||
|
return platform_device_register(&platform_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*====================================================================*/
|
||||||
|
|
||||||
|
static void sl811_cs_detach(dev_link_t *link)
|
||||||
|
{
|
||||||
|
dev_link_t **linkp;
|
||||||
|
|
||||||
|
DBG(0, "sl811_cs_detach(0x%p)\n", link);
|
||||||
|
|
||||||
|
/* Locate device structure */
|
||||||
|
for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) {
|
||||||
|
if (*linkp == link)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (*linkp == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Break the link with Card Services */
|
||||||
|
if (link->handle)
|
||||||
|
pcmcia_deregister_client(link->handle);
|
||||||
|
|
||||||
|
/* Unlink device structure, and free it */
|
||||||
|
*linkp = link->next;
|
||||||
|
/* This points to the parent local_info_t struct */
|
||||||
|
kfree(link->priv);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sl811_cs_release(dev_link_t * link)
|
||||||
|
{
|
||||||
|
|
||||||
|
DBG(0, "sl811_cs_release(0x%p)\n", link);
|
||||||
|
|
||||||
|
if (link->open) {
|
||||||
|
DBG(1, "sl811_cs: release postponed, '%s' still open\n",
|
||||||
|
link->dev->dev_name);
|
||||||
|
link->state |= DEV_STALE_CONFIG;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unlink the device chain */
|
||||||
|
link->dev = NULL;
|
||||||
|
|
||||||
|
platform_device_unregister(&platform_dev);
|
||||||
|
pcmcia_release_configuration(link->handle);
|
||||||
|
if (link->io.NumPorts1)
|
||||||
|
pcmcia_release_io(link->handle, &link->io);
|
||||||
|
if (link->irq.AssignedIRQ)
|
||||||
|
pcmcia_release_irq(link->handle, &link->irq);
|
||||||
|
link->state &= ~DEV_CONFIG;
|
||||||
|
|
||||||
|
if (link->state & DEV_STALE_LINK)
|
||||||
|
sl811_cs_detach(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sl811_cs_config(dev_link_t *link)
|
||||||
|
{
|
||||||
|
client_handle_t handle = link->handle;
|
||||||
|
struct device *parent = &handle_to_dev(handle);
|
||||||
|
local_info_t *dev = link->priv;
|
||||||
|
tuple_t tuple;
|
||||||
|
cisparse_t parse;
|
||||||
|
int last_fn, last_ret;
|
||||||
|
u_char buf[64];
|
||||||
|
config_info_t conf;
|
||||||
|
cistpl_cftable_entry_t dflt = { 0 };
|
||||||
|
|
||||||
|
DBG(0, "sl811_cs_config(0x%p)\n", link);
|
||||||
|
|
||||||
|
tuple.DesiredTuple = CISTPL_CONFIG;
|
||||||
|
tuple.Attributes = 0;
|
||||||
|
tuple.TupleData = buf;
|
||||||
|
tuple.TupleDataMax = sizeof(buf);
|
||||||
|
tuple.TupleOffset = 0;
|
||||||
|
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
|
||||||
|
CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
|
||||||
|
CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
|
||||||
|
link->conf.ConfigBase = parse.config.base;
|
||||||
|
link->conf.Present = parse.config.rmask[0];
|
||||||
|
|
||||||
|
/* Configure card */
|
||||||
|
link->state |= DEV_CONFIG;
|
||||||
|
|
||||||
|
/* Look up the current Vcc */
|
||||||
|
CS_CHECK(GetConfigurationInfo,
|
||||||
|
pcmcia_get_configuration_info(handle, &conf));
|
||||||
|
link->conf.Vcc = conf.Vcc;
|
||||||
|
|
||||||
|
tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
|
||||||
|
CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
|
||||||
|
while (1) {
|
||||||
|
cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
|
||||||
|
|
||||||
|
if (pcmcia_get_tuple_data(handle, &tuple) != 0
|
||||||
|
|| pcmcia_parse_tuple(handle, &tuple, &parse)
|
||||||
|
!= 0)
|
||||||
|
goto next_entry;
|
||||||
|
|
||||||
|
if (cfg->flags & CISTPL_CFTABLE_DEFAULT) {
|
||||||
|
dflt = *cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cfg->index == 0)
|
||||||
|
goto next_entry;
|
||||||
|
|
||||||
|
link->conf.ConfigIndex = cfg->index;
|
||||||
|
|
||||||
|
/* Use power settings for Vcc and Vpp if present */
|
||||||
|
/* Note that the CIS values need to be rescaled */
|
||||||
|
if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM)) {
|
||||||
|
if (cfg->vcc.param[CISTPL_POWER_VNOM]/10000
|
||||||
|
!= conf.Vcc)
|
||||||
|
goto next_entry;
|
||||||
|
} else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM)) {
|
||||||
|
if (dflt.vcc.param[CISTPL_POWER_VNOM]/10000
|
||||||
|
!= conf.Vcc)
|
||||||
|
goto next_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
|
||||||
|
link->conf.Vpp1 = link->conf.Vpp2 =
|
||||||
|
cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
|
||||||
|
else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
|
||||||
|
link->conf.Vpp1 = link->conf.Vpp2 =
|
||||||
|
dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
|
||||||
|
|
||||||
|
/* we need an interrupt */
|
||||||
|
if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
|
||||||
|
link->conf.Attributes |= CONF_ENABLE_IRQ;
|
||||||
|
|
||||||
|
/* IO window settings */
|
||||||
|
link->io.NumPorts1 = link->io.NumPorts2 = 0;
|
||||||
|
if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
|
||||||
|
cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
|
||||||
|
|
||||||
|
link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
|
||||||
|
link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
|
||||||
|
link->io.BasePort1 = io->win[0].base;
|
||||||
|
link->io.NumPorts1 = io->win[0].len;
|
||||||
|
|
||||||
|
if (pcmcia_request_io(link->handle, &link->io) != 0)
|
||||||
|
goto next_entry;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
next_entry:
|
||||||
|
if (link->io.NumPorts1)
|
||||||
|
pcmcia_release_io(link->handle, &link->io);
|
||||||
|
last_ret = pcmcia_get_next_tuple(handle, &tuple);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* require an IRQ and two registers */
|
||||||
|
if (!link->io.NumPorts1 || link->io.NumPorts1 < 2)
|
||||||
|
goto cs_failed;
|
||||||
|
if (link->conf.Attributes & CONF_ENABLE_IRQ)
|
||||||
|
CS_CHECK(RequestIRQ,
|
||||||
|
pcmcia_request_irq(link->handle, &link->irq));
|
||||||
|
else
|
||||||
|
goto cs_failed;
|
||||||
|
|
||||||
|
CS_CHECK(RequestConfiguration,
|
||||||
|
pcmcia_request_configuration(link->handle, &link->conf));
|
||||||
|
|
||||||
|
sprintf(dev->node.dev_name, driver_name);
|
||||||
|
dev->node.major = dev->node.minor = 0;
|
||||||
|
link->dev = &dev->node;
|
||||||
|
|
||||||
|
printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
|
||||||
|
dev->node.dev_name, link->conf.ConfigIndex,
|
||||||
|
link->conf.Vcc/10, link->conf.Vcc%10);
|
||||||
|
if (link->conf.Vpp1)
|
||||||
|
printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
|
||||||
|
printk(", irq %d", link->irq.AssignedIRQ);
|
||||||
|
printk(", io 0x%04x-0x%04x", link->io.BasePort1,
|
||||||
|
link->io.BasePort1+link->io.NumPorts1-1);
|
||||||
|
printk("\n");
|
||||||
|
|
||||||
|
link->state &= ~DEV_CONFIG_PENDING;
|
||||||
|
|
||||||
|
if (sl811_hc_init(parent, link->io.BasePort1, link->irq.AssignedIRQ)
|
||||||
|
< 0) {
|
||||||
|
cs_failed:
|
||||||
|
printk("sl811_cs_config failed\n");
|
||||||
|
cs_error(link->handle, last_fn, last_ret);
|
||||||
|
sl811_cs_release(link);
|
||||||
|
link->state &= ~DEV_CONFIG_PENDING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
sl811_cs_event(event_t event, int priority, event_callback_args_t *args)
|
||||||
|
{
|
||||||
|
dev_link_t *link = args->client_data;
|
||||||
|
|
||||||
|
DBG(1, "sl811_cs_event(0x%06x)\n", event);
|
||||||
|
|
||||||
|
switch (event) {
|
||||||
|
case CS_EVENT_CARD_REMOVAL:
|
||||||
|
link->state &= ~DEV_PRESENT;
|
||||||
|
if (link->state & DEV_CONFIG)
|
||||||
|
sl811_cs_release(link);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CS_EVENT_CARD_INSERTION:
|
||||||
|
link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
|
||||||
|
sl811_cs_config(link);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CS_EVENT_PM_SUSPEND:
|
||||||
|
link->state |= DEV_SUSPEND;
|
||||||
|
/* Fall through... */
|
||||||
|
case CS_EVENT_RESET_PHYSICAL:
|
||||||
|
if (link->state & DEV_CONFIG)
|
||||||
|
pcmcia_release_configuration(link->handle);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CS_EVENT_PM_RESUME:
|
||||||
|
link->state &= ~DEV_SUSPEND;
|
||||||
|
/* Fall through... */
|
||||||
|
case CS_EVENT_CARD_RESET:
|
||||||
|
if (link->state & DEV_CONFIG)
|
||||||
|
pcmcia_request_configuration(link->handle, &link->conf);
|
||||||
|
DBG(0, "reset sl811-hcd here?\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static dev_link_t *sl811_cs_attach(void)
|
||||||
|
{
|
||||||
|
local_info_t *local;
|
||||||
|
dev_link_t *link;
|
||||||
|
client_reg_t client_reg;
|
||||||
|
int ret, i;
|
||||||
|
|
||||||
|
local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
|
||||||
|
if (!local)
|
||||||
|
return NULL;
|
||||||
|
memset(local, 0, sizeof(local_info_t));
|
||||||
|
link = &local->link;
|
||||||
|
link->priv = local;
|
||||||
|
|
||||||
|
/* Initialize */
|
||||||
|
link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
|
||||||
|
link->irq.IRQInfo1 = IRQ_INFO2_VALID|IRQ_LEVEL_ID;
|
||||||
|
if (irq_list[0] == -1)
|
||||||
|
link->irq.IRQInfo2 = irq_mask;
|
||||||
|
else
|
||||||
|
for (i = 0; i < irq_list_count; i++)
|
||||||
|
link->irq.IRQInfo2 |= 1 << irq_list[i];
|
||||||
|
link->irq.Handler = NULL;
|
||||||
|
|
||||||
|
link->conf.Attributes = 0;
|
||||||
|
link->conf.Vcc = 33;
|
||||||
|
link->conf.IntType = INT_MEMORY_AND_IO;
|
||||||
|
|
||||||
|
/* Register with Card Services */
|
||||||
|
link->next = dev_list;
|
||||||
|
dev_list = link;
|
||||||
|
client_reg.dev_info = (dev_info_t *) &driver_name;
|
||||||
|
client_reg.Attributes = INFO_IO_CLIENT | INFO_CARD_SHARE;
|
||||||
|
client_reg.EventMask =
|
||||||
|
CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
|
||||||
|
CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
|
||||||
|
CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
|
||||||
|
client_reg.event_handler = &sl811_cs_event;
|
||||||
|
client_reg.Version = 0x0210;
|
||||||
|
client_reg.event_callback_args.client_data = link;
|
||||||
|
ret = pcmcia_register_client(&link->handle, &client_reg);
|
||||||
|
if (ret != CS_SUCCESS) {
|
||||||
|
cs_error(link->handle, RegisterClient, ret);
|
||||||
|
sl811_cs_detach(link);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pcmcia_driver sl811_cs_driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.drv = {
|
||||||
|
.name = (char *)driver_name,
|
||||||
|
},
|
||||||
|
.attach = sl811_cs_attach,
|
||||||
|
.detach = sl811_cs_detach,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*====================================================================*/
|
||||||
|
|
||||||
|
static int __init init_sl811_cs(void)
|
||||||
|
{
|
||||||
|
return pcmcia_register_driver(&sl811_cs_driver);
|
||||||
|
}
|
||||||
|
module_init(init_sl811_cs);
|
||||||
|
|
||||||
|
static void __exit exit_sl811_cs(void)
|
||||||
|
{
|
||||||
|
pcmcia_unregister_driver(&sl811_cs_driver);
|
||||||
|
}
|
||||||
|
module_exit(exit_sl811_cs);
|
|
@ -1318,6 +1318,8 @@ void hid_init_reports(struct hid_device *hid)
|
||||||
#define USB_DEVICE_ID_WACOM_INTUOS2 0x0040
|
#define USB_DEVICE_ID_WACOM_INTUOS2 0x0040
|
||||||
#define USB_DEVICE_ID_WACOM_VOLITO 0x0060
|
#define USB_DEVICE_ID_WACOM_VOLITO 0x0060
|
||||||
#define USB_DEVICE_ID_WACOM_PTU 0x0003
|
#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_VENDOR_ID_KBGEAR 0x084e
|
||||||
#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001
|
#define USB_DEVICE_ID_KBGEAR_JAMSTUDIO 0x1001
|
||||||
|
@ -1404,6 +1406,7 @@ void hid_init_reports(struct hid_device *hid)
|
||||||
|
|
||||||
#define USB_VENDOR_ID_DELORME 0x1163
|
#define USB_VENDOR_ID_DELORME 0x1163
|
||||||
#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
|
#define USB_DEVICE_ID_DELORME_EARTHMATE 0x0100
|
||||||
|
#define USB_DEVICE_ID_DELORME_EM_LT20 0x0200
|
||||||
|
|
||||||
#define USB_VENDOR_ID_MCC 0x09db
|
#define USB_VENDOR_ID_MCC 0x09db
|
||||||
#define USB_DEVICE_ID_MCC_PMD1024LS 0x0076
|
#define USB_DEVICE_ID_MCC_PMD1024LS 0x0076
|
||||||
|
@ -1415,6 +1418,12 @@ void hid_init_reports(struct hid_device *hid)
|
||||||
#define USB_VENDOR_ID_BTC 0x046e
|
#define USB_VENDOR_ID_BTC 0x046e
|
||||||
#define USB_DEVICE_ID_BTC_KEYBOARD 0x5303
|
#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.
|
* Alphabetically sorted blacklist by quirk type.
|
||||||
|
@ -1440,6 +1449,7 @@ static struct hid_blacklist {
|
||||||
{ USB_VENDOR_ID_CODEMERCS, USB_DEVICE_ID_CODEMERCS_IOW28, HID_QUIRK_IGNORE },
|
{ 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_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_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_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_4_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
|
||||||
{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
|
{ USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30, HID_QUIRK_IGNORE },
|
||||||
|
@ -1459,6 +1469,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 + 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 + 400, HID_QUIRK_IGNORE },
|
||||||
{ USB_VENDOR_ID_ONTRAK, USB_DEVICE_ID_ONTRAK_ADU100 + 500, 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_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, HID_QUIRK_IGNORE },
|
||||||
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 1, HID_QUIRK_IGNORE },
|
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_GRAPHIRE + 1, HID_QUIRK_IGNORE },
|
||||||
|
@ -1484,6 +1498,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_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_VOLITO, HID_QUIRK_IGNORE },
|
||||||
{ USB_VENDOR_ID_WACOM, USB_DEVICE_ID_WACOM_PTU, 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_4_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
|
||||||
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
|
{ USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20, HID_QUIRK_IGNORE },
|
||||||
|
|
||||||
|
|
|
@ -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.
|
|
|
@ -2765,7 +2765,7 @@ static int blan_mdlm_bind (struct usbnet *dev, struct usb_interface *intf)
|
||||||
}
|
}
|
||||||
/* expect bcdVersion 1.0, ignore */
|
/* expect bcdVersion 1.0, ignore */
|
||||||
if (memcmp(&desc->bGUID, blan_guid, 16)
|
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! */
|
/* hey, this one might _really_ be MDLM! */
|
||||||
dev_dbg (&intf->dev, "MDLM guid\n");
|
dev_dbg (&intf->dev, "MDLM guid\n");
|
||||||
goto bad_desc;
|
goto bad_desc;
|
||||||
|
|
|
@ -455,6 +455,17 @@ config USB_SERIAL_XIRCOM
|
||||||
To compile this driver as a module, choose M here: the
|
To compile this driver as a module, choose M here: the
|
||||||
module will be called keyspan_pda.
|
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
|
config USB_SERIAL_OMNINET
|
||||||
tristate "USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)"
|
tristate "USB ZyXEL omni.net LCD Plus Driver (EXPERIMENTAL)"
|
||||||
depends on USB_SERIAL && EXPERIMENTAL
|
depends on USB_SERIAL && EXPERIMENTAL
|
||||||
|
|
|
@ -32,6 +32,7 @@ obj-$(CONFIG_USB_SERIAL_KLSI) += kl5kusb105.o
|
||||||
obj-$(CONFIG_USB_SERIAL_KOBIL_SCT) += kobil_sct.o
|
obj-$(CONFIG_USB_SERIAL_KOBIL_SCT) += kobil_sct.o
|
||||||
obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o
|
obj-$(CONFIG_USB_SERIAL_MCT_U232) += mct_u232.o
|
||||||
obj-$(CONFIG_USB_SERIAL_OMNINET) += omninet.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_PL2303) += pl2303.o
|
||||||
obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o
|
obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o
|
||||||
obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o
|
obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o
|
||||||
|
|
|
@ -7,6 +7,14 @@
|
||||||
* modify it under the terms of the GNU General Public License version
|
* modify it under the terms of the GNU General Public License version
|
||||||
* 2 as published by the Free Software Foundation.
|
* 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>
|
#include <linux/config.h>
|
||||||
|
@ -24,7 +32,7 @@
|
||||||
/*
|
/*
|
||||||
* Version Information
|
* Version Information
|
||||||
*/
|
*/
|
||||||
#define DRIVER_VERSION "v0.03"
|
#define DRIVER_VERSION "v0.04"
|
||||||
#define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver"
|
#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_close(struct usb_serial_port*, struct file*);
|
||||||
static void cp2101_get_termios(struct usb_serial_port*);
|
static void cp2101_get_termios(struct usb_serial_port*);
|
||||||
static void cp2101_set_termios(struct usb_serial_port*, struct termios*);
|
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 void cp2101_break_ctl(struct usb_serial_port*, int);
|
||||||
static int cp2101_startup (struct usb_serial *);
|
static int cp2101_startup (struct usb_serial *);
|
||||||
static void cp2101_shutdown(struct usb_serial*);
|
static void cp2101_shutdown(struct usb_serial*);
|
||||||
|
@ -43,8 +54,9 @@ static void cp2101_shutdown(struct usb_serial*);
|
||||||
static int debug;
|
static int debug;
|
||||||
|
|
||||||
static struct usb_device_id id_table [] = {
|
static struct usb_device_id id_table [] = {
|
||||||
{USB_DEVICE(0x10c4, 0xea60) }, /*Silicon labs factory default*/
|
{ USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */
|
||||||
{USB_DEVICE(0x10ab, 0x10c5) }, /*Siemens MC60 Cable*/
|
{ USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */
|
||||||
|
{ USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */
|
||||||
{ } /* Terminating Entry */
|
{ } /* Terminating Entry */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -70,6 +82,8 @@ static struct usb_serial_device_type cp2101_device = {
|
||||||
.close = cp2101_close,
|
.close = cp2101_close,
|
||||||
.break_ctl = cp2101_break_ctl,
|
.break_ctl = cp2101_break_ctl,
|
||||||
.set_termios = cp2101_set_termios,
|
.set_termios = cp2101_set_termios,
|
||||||
|
.tiocmget = cp2101_tiocmget,
|
||||||
|
.tiocmset = cp2101_tiocmset,
|
||||||
.attach = cp2101_startup,
|
.attach = cp2101_startup,
|
||||||
.shutdown = cp2101_shutdown,
|
.shutdown = cp2101_shutdown,
|
||||||
};
|
};
|
||||||
|
@ -83,8 +97,8 @@ static struct usb_serial_device_type cp2101_device = {
|
||||||
#define CP2101_BAUDRATE 0x01 /* (BAUD_RATE_GEN_FREQ / baudrate) */
|
#define CP2101_BAUDRATE 0x01 /* (BAUD_RATE_GEN_FREQ / baudrate) */
|
||||||
#define CP2101_BITS 0x03 /* 0x(0)(databits)(parity)(stopbits) */
|
#define CP2101_BITS 0x03 /* 0x(0)(databits)(parity)(stopbits) */
|
||||||
#define CP2101_BREAK 0x05 /* On / Off */
|
#define CP2101_BREAK 0x05 /* On / Off */
|
||||||
#define CP2101_DTRRTS 0x07 /*101 / 202 ???*/
|
#define CP2101_CONTROL 0x07 /* Flow control line states */
|
||||||
#define CP2101_CONFIG_16 0x13 /*16 bytes of config data ???*/
|
#define CP2101_MODEMCTL 0x13 /* Modem controls */
|
||||||
#define CP2101_CONFIG_6 0x19 /* 6 bytes of config data ??? */
|
#define CP2101_CONFIG_6 0x19 /* 6 bytes of config data ??? */
|
||||||
|
|
||||||
/* CP2101_UART */
|
/* CP2101_UART */
|
||||||
|
@ -96,6 +110,7 @@ static struct usb_serial_device_type cp2101_device = {
|
||||||
|
|
||||||
/* CP2101_BITS */
|
/* CP2101_BITS */
|
||||||
#define BITS_DATA_MASK 0X0f00
|
#define BITS_DATA_MASK 0X0f00
|
||||||
|
#define BITS_DATA_5 0X0500
|
||||||
#define BITS_DATA_6 0X0600
|
#define BITS_DATA_6 0X0600
|
||||||
#define BITS_DATA_7 0X0700
|
#define BITS_DATA_7 0X0700
|
||||||
#define BITS_DATA_8 0X0800
|
#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 0x0000
|
||||||
#define BITS_STOP_1_5 0x0001
|
#define BITS_STOP_1_5 0x0001
|
||||||
#define BITS_STOP_2 0x0002
|
#define BITS_STOP_2 0x0002
|
||||||
|
|
||||||
|
/* CP2101_BREAK */
|
||||||
#define BREAK_ON 0x0000
|
#define BREAK_ON 0x0000
|
||||||
#define BREAK_OFF 0x0001
|
#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;
|
struct usb_serial *serial = port->serial;
|
||||||
unsigned char buf[4];
|
u32 *buf;
|
||||||
unsigned int value;
|
int result, i, length;
|
||||||
int result, i;
|
|
||||||
|
/* 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++;
|
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),
|
result = usb_control_msg (serial->dev,usb_rcvctrlpipe (serial->dev, 0),
|
||||||
request, REQTYPE_DEVICE_TO_HOST, 0x0000,
|
request, REQTYPE_DEVICE_TO_HOST, 0x0000,
|
||||||
0, buf, 4, 300);
|
0, buf, size, 300);
|
||||||
|
|
||||||
if (result < 0) {
|
/* Convert data into an array of integers */
|
||||||
|
for (i=0; i<length; i++)
|
||||||
|
data[i] = le32_to_cpu(buf[i]);
|
||||||
|
|
||||||
|
kfree(buf);
|
||||||
|
|
||||||
|
if (result != size) {
|
||||||
dev_err(&port->dev, "%s - Unable to send config request, "
|
dev_err(&port->dev, "%s - Unable to send config request, "
|
||||||
"request=0x%x result=%d\n",
|
"request=0x%x size=%d result=%d\n",
|
||||||
__FUNCTION__, request, result);
|
__FUNCTION__, request, size, result);
|
||||||
return result;
|
return -EPROTO;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*Assemble each byte read into an integer value*/
|
|
||||||
value = 0;
|
|
||||||
for (i=0; i<4 && i<result; i++)
|
|
||||||
value |= (buf[i] << (i * 8));
|
|
||||||
|
|
||||||
dbg( " %s - request=0x%x result=%d value=0x%x",
|
|
||||||
__FUNCTION__, request, result, value);
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cp2101_set_config(struct usb_serial_port* port, u8 request, u16 value)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
dbg(" %s - request=0x%x value=0x%x result=%d",
|
|
||||||
__FUNCTION__, request, value, result);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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;
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
static int cp2101_open (struct usb_serial_port *port, struct file *filp)
|
||||||
{
|
{
|
||||||
struct usb_serial *serial = port->serial;
|
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);
|
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",
|
dev_err(&port->dev, "%s - Unable to enable UART\n",
|
||||||
__FUNCTION__);
|
__FUNCTION__);
|
||||||
return -EPROTO;
|
return -EPROTO;
|
||||||
|
@ -201,6 +289,9 @@ static int cp2101_open (struct usb_serial_port *port, struct file *filp)
|
||||||
/* Configure the termios structure */
|
/* Configure the termios structure */
|
||||||
cp2101_get_termios(port);
|
cp2101_get_termios(port);
|
||||||
|
|
||||||
|
/* Set the DTR and RTS pins low */
|
||||||
|
cp2101_tiocmset(port, NULL, TIOCM_DTR | TIOCM_RTS, 0);
|
||||||
|
|
||||||
return 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->write_urb);
|
||||||
usb_kill_urb(port->read_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*/
|
* cp2101_get_termios
|
||||||
/* Corrects any unsupported values*/
|
* Reads the baud rate, data bits, parity, stop bits and flow control mode
|
||||||
/* Configures the termios structure to reflect the state of the device*/
|
* 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)
|
static void cp2101_get_termios (struct usb_serial_port *port)
|
||||||
{
|
{
|
||||||
unsigned int cflag;
|
unsigned int cflag, modem_ctl[4];
|
||||||
int baud;
|
int baud;
|
||||||
int bits;
|
int bits;
|
||||||
|
|
||||||
|
@ -249,7 +342,7 @@ static void cp2101_get_termios (struct usb_serial_port *port)
|
||||||
}
|
}
|
||||||
cflag = port->tty->termios->c_cflag;
|
cflag = port->tty->termios->c_cflag;
|
||||||
|
|
||||||
baud = cp2101_get_config(port, CP2101_BAUDRATE);
|
cp2101_get_config(port, CP2101_BAUDRATE, &baud, 2);
|
||||||
/* Convert to baudrate */
|
/* Convert to baudrate */
|
||||||
if (baud)
|
if (baud)
|
||||||
baud = BAUD_RATE_GEN_FREQ / baud;
|
baud = BAUD_RATE_GEN_FREQ / baud;
|
||||||
|
@ -257,7 +350,8 @@ static void cp2101_get_termios (struct usb_serial_port *port)
|
||||||
dbg("%s - baud rate = %d", __FUNCTION__, baud);
|
dbg("%s - baud rate = %d", __FUNCTION__, baud);
|
||||||
cflag &= ~CBAUD;
|
cflag &= ~CBAUD;
|
||||||
switch (baud) {
|
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
|
* appear to be supported by the device
|
||||||
* but are non-standard
|
* 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, "
|
dbg("%s - Baud rate is not supported, "
|
||||||
"using 9600 baud", __FUNCTION__);
|
"using 9600 baud", __FUNCTION__);
|
||||||
cflag |= B9600;
|
cflag |= B9600;
|
||||||
cp2101_set_config(port, CP2101_BAUDRATE,
|
cp2101_set_config_single(port, CP2101_BAUDRATE,
|
||||||
(BAUD_RATE_GEN_FREQ/9600));
|
(BAUD_RATE_GEN_FREQ/9600));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bits = cp2101_get_config(port, CP2101_BITS);
|
cp2101_get_config(port, CP2101_BITS, &bits, 2);
|
||||||
cflag &= ~CSIZE;
|
cflag &= ~CSIZE;
|
||||||
switch(bits & BITS_DATA_MASK) {
|
switch(bits & BITS_DATA_MASK) {
|
||||||
|
case BITS_DATA_5:
|
||||||
|
dbg("%s - data bits = 5", __FUNCTION__);
|
||||||
|
cflag |= CS5;
|
||||||
|
break;
|
||||||
case BITS_DATA_6:
|
case BITS_DATA_6:
|
||||||
dbg("%s - data bits = 6", __FUNCTION__);
|
dbg("%s - data bits = 6", __FUNCTION__);
|
||||||
cflag |= CS6;
|
cflag |= CS6;
|
||||||
|
@ -310,7 +408,7 @@ static void cp2101_get_termios (struct usb_serial_port *port)
|
||||||
cflag |= CS8;
|
cflag |= CS8;
|
||||||
bits &= ~BITS_DATA_MASK;
|
bits &= ~BITS_DATA_MASK;
|
||||||
bits |= BITS_DATA_8;
|
bits |= BITS_DATA_8;
|
||||||
cp2101_set_config(port, CP2101_BITS, bits);
|
cp2101_set_config(port, CP2101_BITS, &bits, 2);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dbg("%s - Unknown number of data bits, "
|
dbg("%s - Unknown number of data bits, "
|
||||||
|
@ -318,7 +416,7 @@ static void cp2101_get_termios (struct usb_serial_port *port)
|
||||||
cflag |= CS8;
|
cflag |= CS8;
|
||||||
bits &= ~BITS_DATA_MASK;
|
bits &= ~BITS_DATA_MASK;
|
||||||
bits |= BITS_DATA_8;
|
bits |= BITS_DATA_8;
|
||||||
cp2101_set_config(port, CP2101_BITS, bits);
|
cp2101_set_config(port, CP2101_BITS, &bits, 2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -341,21 +439,21 @@ static void cp2101_get_termios (struct usb_serial_port *port)
|
||||||
"disabling parity)", __FUNCTION__);
|
"disabling parity)", __FUNCTION__);
|
||||||
cflag &= ~PARENB;
|
cflag &= ~PARENB;
|
||||||
bits &= ~BITS_PARITY_MASK;
|
bits &= ~BITS_PARITY_MASK;
|
||||||
cp2101_set_config(port, CP2101_BITS, bits);
|
cp2101_set_config(port, CP2101_BITS, &bits, 2);
|
||||||
break;
|
break;
|
||||||
case BITS_PARITY_SPACE:
|
case BITS_PARITY_SPACE:
|
||||||
dbg("%s - parity = SPACE (not supported, "
|
dbg("%s - parity = SPACE (not supported, "
|
||||||
"disabling parity)", __FUNCTION__);
|
"disabling parity)", __FUNCTION__);
|
||||||
cflag &= ~PARENB;
|
cflag &= ~PARENB;
|
||||||
bits &= ~BITS_PARITY_MASK;
|
bits &= ~BITS_PARITY_MASK;
|
||||||
cp2101_set_config(port, CP2101_BITS, bits);
|
cp2101_set_config(port, CP2101_BITS, &bits, 2);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dbg("%s - Unknown parity mode, "
|
dbg("%s - Unknown parity mode, "
|
||||||
"disabling parity", __FUNCTION__);
|
"disabling parity", __FUNCTION__);
|
||||||
cflag &= ~PARENB;
|
cflag &= ~PARENB;
|
||||||
bits &= ~BITS_PARITY_MASK;
|
bits &= ~BITS_PARITY_MASK;
|
||||||
cp2101_set_config(port, CP2101_BITS, bits);
|
cp2101_set_config(port, CP2101_BITS, &bits, 2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,9 +464,9 @@ static void cp2101_get_termios (struct usb_serial_port *port)
|
||||||
break;
|
break;
|
||||||
case BITS_STOP_1_5:
|
case BITS_STOP_1_5:
|
||||||
dbg("%s - stop bits = 1.5 (not supported, "
|
dbg("%s - stop bits = 1.5 (not supported, "
|
||||||
"using 1 stop bit", __FUNCTION__);
|
"using 1 stop bit)", __FUNCTION__);
|
||||||
bits &= ~BITS_STOP_MASK;
|
bits &= ~BITS_STOP_MASK;
|
||||||
cp2101_set_config(port, CP2101_BITS, bits);
|
cp2101_set_config(port, CP2101_BITS, &bits, 2);
|
||||||
break;
|
break;
|
||||||
case BITS_STOP_2:
|
case BITS_STOP_2:
|
||||||
dbg("%s - stop bits = 2", __FUNCTION__);
|
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, "
|
dbg("%s - Unknown number of stop bits, "
|
||||||
"using 1 stop bit", __FUNCTION__);
|
"using 1 stop bit", __FUNCTION__);
|
||||||
bits &= ~BITS_STOP_MASK;
|
bits &= ~BITS_STOP_MASK;
|
||||||
cp2101_set_config(port, CP2101_BITS, bits);
|
cp2101_set_config(port, CP2101_BITS, &bits, 2);
|
||||||
break;
|
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;
|
port->tty->termios->c_cflag = cflag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,8 +496,8 @@ static void cp2101_set_termios (struct usb_serial_port *port,
|
||||||
struct termios *old_termios)
|
struct termios *old_termios)
|
||||||
{
|
{
|
||||||
unsigned int cflag, old_cflag=0;
|
unsigned int cflag, old_cflag=0;
|
||||||
int baud=0;
|
int baud=0, bits;
|
||||||
int bits;
|
unsigned int modem_ctl[4];
|
||||||
|
|
||||||
dbg("%s - port %d", __FUNCTION__, port->number);
|
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;
|
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 (old_termios) {
|
||||||
if ((cflag == old_termios->c_cflag) &&
|
if ((cflag == old_termios->c_cflag) &&
|
||||||
(RELEVANT_IFLAG(port->tty->termios->c_iflag)
|
(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 the baud rate is to be updated*/
|
||||||
if ((cflag & CBAUD) != (old_cflag & CBAUD)) {
|
if ((cflag & CBAUD) != (old_cflag & CBAUD)) {
|
||||||
switch (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
|
* appear to be supported by the device
|
||||||
* but are non-standard
|
* but are non-standard
|
||||||
*/
|
*/
|
||||||
|
@ -448,7 +556,7 @@ static void cp2101_set_termios (struct usb_serial_port *port,
|
||||||
if (baud) {
|
if (baud) {
|
||||||
dbg("%s - Setting baud rate to %d baud", __FUNCTION__,
|
dbg("%s - Setting baud rate to %d baud", __FUNCTION__,
|
||||||
baud);
|
baud);
|
||||||
if (cp2101_set_config(port, CP2101_BAUDRATE,
|
if (cp2101_set_config_single(port, CP2101_BAUDRATE,
|
||||||
(BAUD_RATE_GEN_FREQ / baud)))
|
(BAUD_RATE_GEN_FREQ / baud)))
|
||||||
dev_err(&port->dev, "Baud rate requested not "
|
dev_err(&port->dev, "Baud rate requested not "
|
||||||
"supported by device\n");
|
"supported by device\n");
|
||||||
|
@ -457,9 +565,13 @@ static void cp2101_set_termios (struct usb_serial_port *port,
|
||||||
|
|
||||||
/* If the number of data bits is to be updated */
|
/* If the number of data bits is to be updated */
|
||||||
if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
|
if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
|
||||||
bits = cp2101_get_config(port, CP2101_BITS);
|
cp2101_get_config(port, CP2101_BITS, &bits, 2);
|
||||||
bits &= ~BITS_DATA_MASK;
|
bits &= ~BITS_DATA_MASK;
|
||||||
switch (cflag & CSIZE) {
|
switch (cflag & CSIZE) {
|
||||||
|
case CS5:
|
||||||
|
bits |= BITS_DATA_5;
|
||||||
|
dbg("%s - data bits = 5", __FUNCTION__);
|
||||||
|
break;
|
||||||
case CS6:
|
case CS6:
|
||||||
bits |= BITS_DATA_6;
|
bits |= BITS_DATA_6;
|
||||||
dbg("%s - data bits = 6", __FUNCTION__);
|
dbg("%s - data bits = 6", __FUNCTION__);
|
||||||
|
@ -483,13 +595,13 @@ static void cp2101_set_termios (struct usb_serial_port *port,
|
||||||
bits |= BITS_DATA_8;
|
bits |= BITS_DATA_8;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (cp2101_set_config(port, CP2101_BITS, bits))
|
if (cp2101_set_config(port, CP2101_BITS, &bits, 2))
|
||||||
dev_err(&port->dev, "Number of data bits requested "
|
dev_err(&port->dev, "Number of data bits requested "
|
||||||
"not supported by device\n");
|
"not supported by device\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))) {
|
if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))) {
|
||||||
bits = cp2101_get_config(port, CP2101_BITS);
|
cp2101_get_config(port, CP2101_BITS, &bits, 2);
|
||||||
bits &= ~BITS_PARITY_MASK;
|
bits &= ~BITS_PARITY_MASK;
|
||||||
if (cflag & PARENB) {
|
if (cflag & PARENB) {
|
||||||
if (cflag & PARODD) {
|
if (cflag & PARODD) {
|
||||||
|
@ -500,13 +612,13 @@ static void cp2101_set_termios (struct usb_serial_port *port,
|
||||||
dbg("%s - parity = EVEN", __FUNCTION__);
|
dbg("%s - parity = EVEN", __FUNCTION__);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (cp2101_set_config(port, CP2101_BITS, bits))
|
if (cp2101_set_config(port, CP2101_BITS, &bits, 2))
|
||||||
dev_err(&port->dev, "Parity mode not supported "
|
dev_err(&port->dev, "Parity mode not supported "
|
||||||
"by device\n");
|
"by device\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) {
|
if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) {
|
||||||
bits = cp2101_get_config(port, CP2101_BITS);
|
cp2101_get_config(port, CP2101_BITS, &bits, 2);
|
||||||
bits &= ~BITS_STOP_MASK;
|
bits &= ~BITS_STOP_MASK;
|
||||||
if (cflag & CSTOPB) {
|
if (cflag & CSTOPB) {
|
||||||
bits |= BITS_STOP_2;
|
bits |= BITS_STOP_2;
|
||||||
|
@ -515,15 +627,90 @@ static void cp2101_set_termios (struct usb_serial_port *port,
|
||||||
bits |= BITS_STOP_1;
|
bits |= BITS_STOP_1;
|
||||||
dbg("%s - stop bits = 1", __FUNCTION__);
|
dbg("%s - stop bits = 1", __FUNCTION__);
|
||||||
}
|
}
|
||||||
if (cp2101_set_config(port, CP2101_BITS, bits))
|
if (cp2101_set_config(port, CP2101_BITS, &bits, 2))
|
||||||
dev_err(&port->dev, "Number of stop bits requested "
|
dev_err(&port->dev, "Number of stop bits requested "
|
||||||
"not supported by device\n");
|
"not supported by device\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) {
|
||||||
|
cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16);
|
||||||
|
dbg("%s - read modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x",
|
||||||
|
__FUNCTION__, modem_ctl[0], modem_ctl[1],
|
||||||
|
modem_ctl[2], modem_ctl[3]);
|
||||||
|
|
||||||
|
if (cflag & CRTSCTS) {
|
||||||
|
modem_ctl[0] &= ~0x7B;
|
||||||
|
modem_ctl[0] |= 0x09;
|
||||||
|
modem_ctl[1] = 0x80;
|
||||||
|
dbg("%s - flow control = CRTSCTS", __FUNCTION__);
|
||||||
|
} else {
|
||||||
|
modem_ctl[0] &= ~0x7B;
|
||||||
|
modem_ctl[0] |= 0x01;
|
||||||
|
modem_ctl[1] |= 0x40;
|
||||||
|
dbg("%s - flow control = NONE", __FUNCTION__);
|
||||||
|
}
|
||||||
|
|
||||||
|
dbg("%s - write modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x",
|
||||||
|
__FUNCTION__, modem_ctl[0], modem_ctl[1],
|
||||||
|
modem_ctl[2], modem_ctl[3]);
|
||||||
|
cp2101_set_config(port, CP2101_MODEMCTL, modem_ctl, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cp2101_tiocmset (struct usb_serial_port *port, struct file *file,
|
||||||
|
unsigned int set, unsigned int clear)
|
||||||
|
{
|
||||||
|
int control = 0;
|
||||||
|
|
||||||
|
dbg("%s - port %d", __FUNCTION__, port->number);
|
||||||
|
|
||||||
|
if (set & TIOCM_RTS) {
|
||||||
|
control |= CONTROL_RTS;
|
||||||
|
control |= CONTROL_WRITE_RTS;
|
||||||
|
}
|
||||||
|
if (set & TIOCM_DTR) {
|
||||||
|
control |= CONTROL_DTR;
|
||||||
|
control |= CONTROL_WRITE_DTR;
|
||||||
|
}
|
||||||
|
if (clear & TIOCM_RTS) {
|
||||||
|
control &= ~CONTROL_RTS;
|
||||||
|
control |= CONTROL_WRITE_RTS;
|
||||||
|
}
|
||||||
|
if (clear & TIOCM_DTR) {
|
||||||
|
control &= ~CONTROL_DTR;
|
||||||
|
control |= CONTROL_WRITE_DTR;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbg("%s - control = 0x%.4x", __FUNCTION__, control);
|
||||||
|
|
||||||
|
return cp2101_set_config(port, CP2101_CONTROL, &control, 2);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cp2101_tiocmget (struct usb_serial_port *port, struct file *file)
|
||||||
|
{
|
||||||
|
int control, result;
|
||||||
|
|
||||||
|
dbg("%s - port %d", __FUNCTION__, port->number);
|
||||||
|
|
||||||
|
cp2101_get_config(port, CP2101_CONTROL, &control, 1);
|
||||||
|
|
||||||
|
result = ((control & CONTROL_DTR) ? TIOCM_DTR : 0)
|
||||||
|
|((control & CONTROL_RTS) ? TIOCM_RTS : 0)
|
||||||
|
|((control & CONTROL_CTS) ? TIOCM_CTS : 0)
|
||||||
|
|((control & CONTROL_DSR) ? TIOCM_DSR : 0)
|
||||||
|
|((control & CONTROL_RING)? TIOCM_RI : 0)
|
||||||
|
|((control & CONTROL_DCD) ? TIOCM_CD : 0);
|
||||||
|
|
||||||
|
dbg("%s - control = 0x%.2x", __FUNCTION__, control);
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void cp2101_break_ctl (struct usb_serial_port *port, int break_state)
|
static void cp2101_break_ctl (struct usb_serial_port *port, int break_state)
|
||||||
{
|
{
|
||||||
u16 state;
|
int state;
|
||||||
|
|
||||||
dbg("%s - port %d", __FUNCTION__, port->number);
|
dbg("%s - port %d", __FUNCTION__, port->number);
|
||||||
if (break_state == 0)
|
if (break_state == 0)
|
||||||
|
@ -532,7 +719,7 @@ static void cp2101_break_ctl (struct usb_serial_port *port, int break_state)
|
||||||
state = BREAK_ON;
|
state = BREAK_ON;
|
||||||
dbg("%s - turning break %s", __FUNCTION__,
|
dbg("%s - turning break %s", __FUNCTION__,
|
||||||
state==BREAK_OFF ? "off" : "on");
|
state==BREAK_OFF ? "off" : "on");
|
||||||
cp2101_set_config(port, CP2101_BREAK, state);
|
cp2101_set_config(port, CP2101_BREAK, &state, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cp2101_startup (struct usb_serial *serial)
|
static int cp2101_startup (struct usb_serial *serial)
|
||||||
|
@ -548,7 +735,7 @@ static void cp2101_shutdown (struct usb_serial *serial)
|
||||||
|
|
||||||
dbg("%s", __FUNCTION__);
|
dbg("%s", __FUNCTION__);
|
||||||
|
|
||||||
/* stop reads and writes on all ports */
|
/* Stop reads and writes on all ports */
|
||||||
for (i=0; i < serial->num_ports; ++i) {
|
for (i=0; i < serial->num_ports; ++i) {
|
||||||
cp2101_cleanup(serial->port[i]);
|
cp2101_cleanup(serial->port[i]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -364,6 +364,7 @@ static struct usb_device_id id_table_8U232AM [] = {
|
||||||
{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_3, 0, 0x3ff) },
|
{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_3, 0, 0x3ff) },
|
||||||
{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_4, 0, 0x3ff) },
|
{ USB_DEVICE_VER(FTDI_VID, PROTEGO_SPECIAL_4, 0, 0x3ff) },
|
||||||
{ USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0, 0x3ff) },
|
{ USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0, 0x3ff) },
|
||||||
|
{ USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UM100_PID, 0, 0x3ff) },
|
||||||
{ USB_DEVICE_VER(FTDI_VID, INSIDE_ACCESSO, 0, 0x3ff) },
|
{ USB_DEVICE_VER(FTDI_VID, INSIDE_ACCESSO, 0, 0x3ff) },
|
||||||
{ USB_DEVICE_VER(INTREPID_VID, INTREPID_VALUECAN_PID, 0, 0x3ff) },
|
{ USB_DEVICE_VER(INTREPID_VID, INTREPID_VALUECAN_PID, 0, 0x3ff) },
|
||||||
{ USB_DEVICE_VER(INTREPID_VID, INTREPID_NEOVI_PID, 0, 0x3ff) },
|
{ USB_DEVICE_VER(INTREPID_VID, INTREPID_NEOVI_PID, 0, 0x3ff) },
|
||||||
|
@ -475,6 +476,7 @@ static struct usb_device_id id_table_FT232BM [] = {
|
||||||
{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88E_PID, 0x400, 0xffff) },
|
{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88E_PID, 0x400, 0xffff) },
|
||||||
{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88F_PID, 0x400, 0xffff) },
|
{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88F_PID, 0x400, 0xffff) },
|
||||||
{ USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0x400, 0xffff) },
|
{ USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UO100_PID, 0x400, 0xffff) },
|
||||||
|
{ USB_DEVICE_VER(FTDI_VID, FTDI_ELV_UM100_PID, 0x400, 0xffff) },
|
||||||
{ USB_DEVICE_VER(FTDI_VID, LINX_SDMUSBQSS_PID, 0x400, 0xffff) },
|
{ USB_DEVICE_VER(FTDI_VID, LINX_SDMUSBQSS_PID, 0x400, 0xffff) },
|
||||||
{ USB_DEVICE_VER(FTDI_VID, LINX_MASTERDEVEL2_PID, 0x400, 0xffff) },
|
{ USB_DEVICE_VER(FTDI_VID, LINX_MASTERDEVEL2_PID, 0x400, 0xffff) },
|
||||||
{ USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_0_PID, 0x400, 0xffff) },
|
{ USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_0_PID, 0x400, 0xffff) },
|
||||||
|
@ -618,6 +620,7 @@ static struct usb_device_id id_table_combined [] = {
|
||||||
{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88E_PID, 0x400, 0xffff) },
|
{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88E_PID, 0x400, 0xffff) },
|
||||||
{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88F_PID, 0x400, 0xffff) },
|
{ USB_DEVICE_VER(FTDI_VID, FTDI_GUDEADS_E88F_PID, 0x400, 0xffff) },
|
||||||
{ USB_DEVICE(FTDI_VID, FTDI_ELV_UO100_PID) },
|
{ USB_DEVICE(FTDI_VID, FTDI_ELV_UO100_PID) },
|
||||||
|
{ USB_DEVICE(FTDI_VID, FTDI_ELV_UM100_PID) },
|
||||||
{ USB_DEVICE_VER(FTDI_VID, LINX_SDMUSBQSS_PID, 0x400, 0xffff) },
|
{ USB_DEVICE_VER(FTDI_VID, LINX_SDMUSBQSS_PID, 0x400, 0xffff) },
|
||||||
{ USB_DEVICE_VER(FTDI_VID, LINX_MASTERDEVEL2_PID, 0x400, 0xffff) },
|
{ USB_DEVICE_VER(FTDI_VID, LINX_MASTERDEVEL2_PID, 0x400, 0xffff) },
|
||||||
{ USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_0_PID, 0x400, 0xffff) },
|
{ USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_0_PID, 0x400, 0xffff) },
|
||||||
|
|
|
@ -144,6 +144,8 @@
|
||||||
|
|
||||||
/* ELV USB Module UO100 (PID sent by Stefan Frings) */
|
/* ELV USB Module UO100 (PID sent by Stefan Frings) */
|
||||||
#define FTDI_ELV_UO100_PID 0xFB58 /* Product Id */
|
#define FTDI_ELV_UO100_PID 0xFB58 /* Product Id */
|
||||||
|
/* ELV USB Module UM100 (PID sent by Arnim Laeuger) */
|
||||||
|
#define FTDI_ELV_UM100_PID 0xFB5A /* Product Id */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Definitions for ID TECH (www.idt-net.com) devices
|
* Definitions for ID TECH (www.idt-net.com) devices
|
||||||
|
|
|
@ -0,0 +1,729 @@
|
||||||
|
/*
|
||||||
|
Option Card (PCMCIA to) USB to Serial Driver
|
||||||
|
|
||||||
|
Copyright (C) 2005 Matthias Urlichs <smurf@smurf.noris.de>
|
||||||
|
|
||||||
|
This driver is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of Version 2 of the GNU General Public License as
|
||||||
|
published by the Free Software Foundation.
|
||||||
|
|
||||||
|
Portions copied from the Keyspan driver by Hugh Blemings <hugh@blemings.org>
|
||||||
|
|
||||||
|
History:
|
||||||
|
|
||||||
|
2005-05-19 v0.1 Initial version, based on incomplete docs
|
||||||
|
and analysis of misbehavior of the standard driver
|
||||||
|
2005-05-20 v0.2 Extended the input buffer to avoid losing
|
||||||
|
random 64-byte chunks of data
|
||||||
|
2005-05-21 v0.3 implemented chars_in_buffer()
|
||||||
|
turned on low_latency
|
||||||
|
simplified the code somewhat
|
||||||
|
*/
|
||||||
|
#define DRIVER_VERSION "v0.3"
|
||||||
|
#define DRIVER_AUTHOR "Matthias Urlichs <smurf@smurf.noris.de>"
|
||||||
|
#define DRIVER_DESC "Option Card (PC-Card to) USB to Serial Driver"
|
||||||
|
|
||||||
|
#include <linux/config.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/jiffies.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/tty.h>
|
||||||
|
#include <linux/tty_flip.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/usb.h>
|
||||||
|
#include "usb-serial.h"
|
||||||
|
|
||||||
|
/* Function prototypes */
|
||||||
|
static int option_open (struct usb_serial_port *port, struct file *filp);
|
||||||
|
static void option_close (struct usb_serial_port *port, struct file *filp);
|
||||||
|
static int option_startup (struct usb_serial *serial);
|
||||||
|
static void option_shutdown (struct usb_serial *serial);
|
||||||
|
static void option_rx_throttle (struct usb_serial_port *port);
|
||||||
|
static void option_rx_unthrottle (struct usb_serial_port *port);
|
||||||
|
static int option_write_room (struct usb_serial_port *port);
|
||||||
|
|
||||||
|
static void option_instat_callback(struct urb *urb, struct pt_regs *regs);
|
||||||
|
|
||||||
|
|
||||||
|
static int option_write (struct usb_serial_port *port,
|
||||||
|
const unsigned char *buf, int count);
|
||||||
|
|
||||||
|
static int option_chars_in_buffer (struct usb_serial_port *port);
|
||||||
|
static int option_ioctl (struct usb_serial_port *port, struct file *file,
|
||||||
|
unsigned int cmd, unsigned long arg);
|
||||||
|
static void option_set_termios (struct usb_serial_port *port,
|
||||||
|
struct termios *old);
|
||||||
|
static void option_break_ctl (struct usb_serial_port *port, int break_state);
|
||||||
|
static int option_tiocmget (struct usb_serial_port *port, struct file *file);
|
||||||
|
static int option_tiocmset (struct usb_serial_port *port, struct file *file,
|
||||||
|
unsigned int set, unsigned int clear);
|
||||||
|
static int option_send_setup (struct usb_serial_port *port);
|
||||||
|
|
||||||
|
/* Vendor and product IDs */
|
||||||
|
#define OPTION_VENDOR_ID 0x0AF0
|
||||||
|
|
||||||
|
#define OPTION_PRODUCT_OLD 0x5000
|
||||||
|
#define OPTION_PRODUCT_WLAN 0x6000
|
||||||
|
|
||||||
|
static struct usb_device_id option_ids[] = {
|
||||||
|
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_OLD) },
|
||||||
|
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_WLAN) },
|
||||||
|
{ } /* Terminating entry */
|
||||||
|
};
|
||||||
|
|
||||||
|
MODULE_DEVICE_TABLE(usb, option_ids);
|
||||||
|
|
||||||
|
static struct usb_driver option_driver = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = "option",
|
||||||
|
.probe = usb_serial_probe,
|
||||||
|
.disconnect = usb_serial_disconnect,
|
||||||
|
.id_table = option_ids,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The card has three separate interfaces, wich the serial driver
|
||||||
|
* recognizes separately, thus num_port=1.
|
||||||
|
*/
|
||||||
|
static struct usb_serial_device_type option_3port_device = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.name = "Option 3-port card",
|
||||||
|
.short_name = "option",
|
||||||
|
.id_table = option_ids,
|
||||||
|
.num_interrupt_in = NUM_DONT_CARE,
|
||||||
|
.num_bulk_in = NUM_DONT_CARE,
|
||||||
|
.num_bulk_out = NUM_DONT_CARE,
|
||||||
|
.num_ports = 1, /* 3 */
|
||||||
|
.open = option_open,
|
||||||
|
.close = option_close,
|
||||||
|
.write = option_write,
|
||||||
|
.write_room = option_write_room,
|
||||||
|
.chars_in_buffer = option_chars_in_buffer,
|
||||||
|
.throttle = option_rx_throttle,
|
||||||
|
.unthrottle = option_rx_unthrottle,
|
||||||
|
.ioctl = option_ioctl,
|
||||||
|
.set_termios = option_set_termios,
|
||||||
|
.break_ctl = option_break_ctl,
|
||||||
|
.tiocmget = option_tiocmget,
|
||||||
|
.tiocmset = option_tiocmset,
|
||||||
|
.attach = option_startup,
|
||||||
|
.shutdown = option_shutdown,
|
||||||
|
.read_int_callback = option_instat_callback,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int debug;
|
||||||
|
|
||||||
|
/* per port private data */
|
||||||
|
|
||||||
|
#define N_IN_URB 4
|
||||||
|
#define N_OUT_URB 1
|
||||||
|
#define IN_BUFLEN 1024
|
||||||
|
#define OUT_BUFLEN 1024
|
||||||
|
|
||||||
|
struct option_port_private {
|
||||||
|
/* Input endpoints and buffer for this port */
|
||||||
|
struct urb *in_urbs[N_IN_URB];
|
||||||
|
char in_buffer[N_IN_URB][IN_BUFLEN];
|
||||||
|
/* Output endpoints and buffer for this port */
|
||||||
|
struct urb *out_urbs[N_OUT_URB];
|
||||||
|
char out_buffer[N_OUT_URB][OUT_BUFLEN];
|
||||||
|
|
||||||
|
/* Settings for the port */
|
||||||
|
int rts_state; /* Handshaking pins (outputs) */
|
||||||
|
int dtr_state;
|
||||||
|
int cts_state; /* Handshaking pins (inputs) */
|
||||||
|
int dsr_state;
|
||||||
|
int dcd_state;
|
||||||
|
int ri_state;
|
||||||
|
// int break_on;
|
||||||
|
|
||||||
|
unsigned long tx_start_time[N_OUT_URB];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Functions used by new usb-serial code. */
|
||||||
|
static int __init
|
||||||
|
option_init (void)
|
||||||
|
{
|
||||||
|
int retval;
|
||||||
|
retval = usb_serial_register(&option_3port_device);
|
||||||
|
if (retval)
|
||||||
|
goto failed_3port_device_register;
|
||||||
|
retval = usb_register(&option_driver);
|
||||||
|
if (retval)
|
||||||
|
goto failed_driver_register;
|
||||||
|
|
||||||
|
info(DRIVER_DESC ": " DRIVER_VERSION);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
failed_driver_register:
|
||||||
|
usb_serial_deregister (&option_3port_device);
|
||||||
|
failed_3port_device_register:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit
|
||||||
|
option_exit (void)
|
||||||
|
{
|
||||||
|
usb_deregister (&option_driver);
|
||||||
|
usb_serial_deregister (&option_3port_device);
|
||||||
|
}
|
||||||
|
|
||||||
|
module_init(option_init);
|
||||||
|
module_exit(option_exit);
|
||||||
|
|
||||||
|
static void
|
||||||
|
option_rx_throttle (struct usb_serial_port *port)
|
||||||
|
{
|
||||||
|
dbg("%s", __FUNCTION__);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
option_rx_unthrottle (struct usb_serial_port *port)
|
||||||
|
{
|
||||||
|
dbg("%s", __FUNCTION__);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
option_break_ctl (struct usb_serial_port *port, int break_state)
|
||||||
|
{
|
||||||
|
/* Unfortunately, I don't know how to send a break */
|
||||||
|
dbg("%s", __FUNCTION__);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
option_set_termios (struct usb_serial_port *port,
|
||||||
|
struct termios *old_termios)
|
||||||
|
{
|
||||||
|
dbg("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
option_send_setup(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
option_tiocmget(struct usb_serial_port *port, struct file *file)
|
||||||
|
{
|
||||||
|
unsigned int value;
|
||||||
|
struct option_port_private *portdata;
|
||||||
|
|
||||||
|
portdata = usb_get_serial_port_data(port);
|
||||||
|
|
||||||
|
value = ((portdata->rts_state) ? TIOCM_RTS : 0) |
|
||||||
|
((portdata->dtr_state) ? TIOCM_DTR : 0) |
|
||||||
|
((portdata->cts_state) ? TIOCM_CTS : 0) |
|
||||||
|
((portdata->dsr_state) ? TIOCM_DSR : 0) |
|
||||||
|
((portdata->dcd_state) ? TIOCM_CAR : 0) |
|
||||||
|
((portdata->ri_state) ? TIOCM_RNG : 0);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
option_tiocmset (struct usb_serial_port *port, struct file *file,
|
||||||
|
unsigned int set, unsigned int clear)
|
||||||
|
{
|
||||||
|
struct option_port_private *portdata;
|
||||||
|
|
||||||
|
portdata = usb_get_serial_port_data(port);
|
||||||
|
|
||||||
|
if (set & TIOCM_RTS)
|
||||||
|
portdata->rts_state = 1;
|
||||||
|
if (set & TIOCM_DTR)
|
||||||
|
portdata->dtr_state = 1;
|
||||||
|
|
||||||
|
if (clear & TIOCM_RTS)
|
||||||
|
portdata->rts_state = 0;
|
||||||
|
if (clear & TIOCM_DTR)
|
||||||
|
portdata->dtr_state = 0;
|
||||||
|
return option_send_setup(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
option_ioctl (struct usb_serial_port *port, struct file *file,
|
||||||
|
unsigned int cmd, unsigned long arg)
|
||||||
|
{
|
||||||
|
return -ENOIOCTLCMD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write */
|
||||||
|
static int
|
||||||
|
option_write(struct usb_serial_port *port,
|
||||||
|
const unsigned char *buf, int count)
|
||||||
|
{
|
||||||
|
struct option_port_private *portdata;
|
||||||
|
int i;
|
||||||
|
int left, todo;
|
||||||
|
struct urb *this_urb = NULL; /* spurious */
|
||||||
|
int err;
|
||||||
|
|
||||||
|
portdata = usb_get_serial_port_data(port);
|
||||||
|
|
||||||
|
dbg("%s: write (%d chars)", __FUNCTION__, count);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
spin_lock(&port->lock);
|
||||||
|
if (port->write_urb_busy) {
|
||||||
|
spin_unlock(&port->lock);
|
||||||
|
dbg("%s: already writing", __FUNCTION__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
port->write_urb_busy = 1;
|
||||||
|
spin_unlock(&port->lock);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
left = count;
|
||||||
|
while (left>0) {
|
||||||
|
todo = left;
|
||||||
|
if (todo > OUT_BUFLEN)
|
||||||
|
todo = OUT_BUFLEN;
|
||||||
|
|
||||||
|
for (;i < N_OUT_URB; i++) {
|
||||||
|
/* Check we have a valid urb/endpoint before we use it... */
|
||||||
|
this_urb = portdata->out_urbs[i];
|
||||||
|
if (this_urb->status != -EINPROGRESS)
|
||||||
|
break;
|
||||||
|
if (this_urb->transfer_flags & URB_ASYNC_UNLINK)
|
||||||
|
continue;
|
||||||
|
if (time_before(jiffies, portdata->tx_start_time[i] + 10 * HZ))
|
||||||
|
continue;
|
||||||
|
this_urb->transfer_flags |= URB_ASYNC_UNLINK;
|
||||||
|
usb_unlink_urb(this_urb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == N_OUT_URB) {
|
||||||
|
/* no bulk out free! */
|
||||||
|
dbg("%s: no output urb -- left %d", __FUNCTION__,count-left);
|
||||||
|
#if 0
|
||||||
|
port->write_urb_busy = 0;
|
||||||
|
#endif
|
||||||
|
return count-left;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbg("%s: endpoint %d buf %d", __FUNCTION__, usb_pipeendpoint(this_urb->pipe), i);
|
||||||
|
|
||||||
|
memcpy (this_urb->transfer_buffer, buf, todo);
|
||||||
|
|
||||||
|
/* send the data out the bulk port */
|
||||||
|
this_urb->transfer_buffer_length = todo;
|
||||||
|
|
||||||
|
this_urb->transfer_flags &= ~URB_ASYNC_UNLINK;
|
||||||
|
this_urb->dev = port->serial->dev;
|
||||||
|
err = usb_submit_urb(this_urb, GFP_ATOMIC);
|
||||||
|
if (err) {
|
||||||
|
dbg("usb_submit_urb %p (write bulk) failed (%d,, has %d)", this_urb, err, this_urb->status);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
portdata->tx_start_time[i] = jiffies;
|
||||||
|
buf += todo;
|
||||||
|
left -= todo;
|
||||||
|
}
|
||||||
|
|
||||||
|
count -= left;
|
||||||
|
#if 0
|
||||||
|
port->write_urb_busy = 0;
|
||||||
|
#endif
|
||||||
|
dbg("%s: wrote (did %d)", __FUNCTION__, count);
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
option_indat_callback (struct urb *urb, struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
int i, err;
|
||||||
|
int endpoint;
|
||||||
|
struct usb_serial_port *port;
|
||||||
|
struct tty_struct *tty;
|
||||||
|
unsigned char *data = urb->transfer_buffer;
|
||||||
|
|
||||||
|
dbg("%s: %p", __FUNCTION__, urb);
|
||||||
|
|
||||||
|
endpoint = usb_pipeendpoint(urb->pipe);
|
||||||
|
port = (struct usb_serial_port *) urb->context;
|
||||||
|
|
||||||
|
if (urb->status) {
|
||||||
|
dbg("%s: nonzero status: %d on endpoint %02x.",
|
||||||
|
__FUNCTION__, urb->status, endpoint);
|
||||||
|
} else {
|
||||||
|
tty = port->tty;
|
||||||
|
if (urb->actual_length) {
|
||||||
|
for (i = 0; i < urb->actual_length ; ++i) {
|
||||||
|
if (tty->flip.count >= TTY_FLIPBUF_SIZE)
|
||||||
|
tty_flip_buffer_push(tty);
|
||||||
|
tty_insert_flip_char(tty, data[i], 0);
|
||||||
|
}
|
||||||
|
tty_flip_buffer_push(tty);
|
||||||
|
} else {
|
||||||
|
dbg("%s: empty read urb received", __FUNCTION__);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Resubmit urb so we continue receiving */
|
||||||
|
if (port->open_count && urb->status != -ESHUTDOWN) {
|
||||||
|
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||||
|
if (err)
|
||||||
|
printk(KERN_ERR "%s: resubmit read urb failed. (%d)", __FUNCTION__, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
option_outdat_callback (struct urb *urb, struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
struct usb_serial_port *port;
|
||||||
|
|
||||||
|
dbg("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
port = (struct usb_serial_port *) urb->context;
|
||||||
|
|
||||||
|
if (port->open_count)
|
||||||
|
schedule_work(&port->work);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
option_instat_callback (struct urb *urb, struct pt_regs *regs)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
|
||||||
|
struct option_port_private *portdata = usb_get_serial_port_data(port);
|
||||||
|
struct usb_serial *serial = port->serial;
|
||||||
|
|
||||||
|
dbg("%s", __FUNCTION__);
|
||||||
|
dbg("%s: urb %p port %p has data %p", __FUNCTION__,urb,port,portdata);
|
||||||
|
|
||||||
|
if (urb->status == 0) {
|
||||||
|
struct usb_ctrlrequest *req_pkt =
|
||||||
|
(struct usb_ctrlrequest *)urb->transfer_buffer;
|
||||||
|
|
||||||
|
if (!req_pkt) {
|
||||||
|
dbg("%s: NULL req_pkt\n", __FUNCTION__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ((req_pkt->bRequestType == 0xA1) && (req_pkt->bRequest == 0x20)) {
|
||||||
|
int old_dcd_state;
|
||||||
|
unsigned char signals = *((unsigned char *)
|
||||||
|
urb->transfer_buffer + sizeof(struct usb_ctrlrequest));
|
||||||
|
|
||||||
|
dbg("%s: signal x%x", __FUNCTION__, signals);
|
||||||
|
|
||||||
|
old_dcd_state = portdata->dcd_state;
|
||||||
|
portdata->cts_state = 1;
|
||||||
|
portdata->dcd_state = ((signals & 0x01) ? 1 : 0);
|
||||||
|
portdata->dsr_state = ((signals & 0x02) ? 1 : 0);
|
||||||
|
portdata->ri_state = ((signals & 0x08) ? 1 : 0);
|
||||||
|
|
||||||
|
if (port->tty && !C_CLOCAL(port->tty)
|
||||||
|
&& old_dcd_state && !portdata->dcd_state) {
|
||||||
|
tty_hangup(port->tty);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
dbg("%s: type %x req %x", __FUNCTION__, req_pkt->bRequestType,req_pkt->bRequest);
|
||||||
|
} else
|
||||||
|
dbg("%s: error %d", __FUNCTION__, urb->status);
|
||||||
|
|
||||||
|
/* Resubmit urb so we continue receiving IRQ data */
|
||||||
|
if (urb->status != -ESHUTDOWN) {
|
||||||
|
urb->dev = serial->dev;
|
||||||
|
err = usb_submit_urb(urb, GFP_ATOMIC);
|
||||||
|
if (err)
|
||||||
|
dbg("%s: resubmit intr urb failed. (%d)", __FUNCTION__, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
option_write_room (struct usb_serial_port *port)
|
||||||
|
{
|
||||||
|
struct option_port_private *portdata;
|
||||||
|
int i;
|
||||||
|
int data_len = 0;
|
||||||
|
struct urb *this_urb;
|
||||||
|
|
||||||
|
portdata = usb_get_serial_port_data(port);
|
||||||
|
|
||||||
|
for (i=0; i < N_OUT_URB; i++)
|
||||||
|
this_urb = portdata->out_urbs[i];
|
||||||
|
if (this_urb && this_urb->status != -EINPROGRESS)
|
||||||
|
data_len += OUT_BUFLEN;
|
||||||
|
|
||||||
|
dbg("%s: %d", __FUNCTION__, data_len);
|
||||||
|
return data_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
option_chars_in_buffer (struct usb_serial_port *port)
|
||||||
|
{
|
||||||
|
struct option_port_private *portdata;
|
||||||
|
int i;
|
||||||
|
int data_len = 0;
|
||||||
|
struct urb *this_urb;
|
||||||
|
|
||||||
|
portdata = usb_get_serial_port_data(port);
|
||||||
|
|
||||||
|
for (i=0; i < N_OUT_URB; i++)
|
||||||
|
this_urb = portdata->out_urbs[i];
|
||||||
|
if (this_urb && this_urb->status == -EINPROGRESS)
|
||||||
|
data_len += this_urb->transfer_buffer_length;
|
||||||
|
|
||||||
|
dbg("%s: %d", __FUNCTION__, data_len);
|
||||||
|
return data_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
option_open (struct usb_serial_port *port, struct file *filp)
|
||||||
|
{
|
||||||
|
struct option_port_private *portdata;
|
||||||
|
struct usb_serial *serial = port->serial;
|
||||||
|
int i, err;
|
||||||
|
struct urb *urb;
|
||||||
|
|
||||||
|
portdata = usb_get_serial_port_data(port);
|
||||||
|
|
||||||
|
dbg("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
/* Set some sane defaults */
|
||||||
|
portdata->rts_state = 1;
|
||||||
|
portdata->dtr_state = 1;
|
||||||
|
|
||||||
|
/* Reset low level data toggle and start reading from endpoints */
|
||||||
|
for (i = 0; i < N_IN_URB; i++) {
|
||||||
|
urb = portdata->in_urbs[i];
|
||||||
|
if (! urb)
|
||||||
|
continue;
|
||||||
|
if (urb->dev != serial->dev) {
|
||||||
|
dbg("%s: dev %p != %p", __FUNCTION__, urb->dev, serial->dev);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make sure endpoint data toggle is synchronized with the device */
|
||||||
|
|
||||||
|
usb_clear_halt(urb->dev, urb->pipe);
|
||||||
|
|
||||||
|
err = usb_submit_urb(urb, GFP_KERNEL);
|
||||||
|
if (err) {
|
||||||
|
dbg("%s: submit urb %d failed (%d) %d", __FUNCTION__, i, err,
|
||||||
|
urb->transfer_buffer_length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset low level data toggle on out endpoints */
|
||||||
|
for (i = 0; i < N_OUT_URB; i++) {
|
||||||
|
urb = portdata->out_urbs[i];
|
||||||
|
if (! urb)
|
||||||
|
continue;
|
||||||
|
urb->dev = serial->dev;
|
||||||
|
/* usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe), 0); */
|
||||||
|
}
|
||||||
|
|
||||||
|
port->tty->low_latency = 1;
|
||||||
|
|
||||||
|
option_send_setup(port);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
stop_urb(struct urb *urb)
|
||||||
|
{
|
||||||
|
if (urb && urb->status == -EINPROGRESS) {
|
||||||
|
urb->transfer_flags &= ~URB_ASYNC_UNLINK;
|
||||||
|
usb_kill_urb(urb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
option_close(struct usb_serial_port *port, struct file *filp)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct usb_serial *serial = port->serial;
|
||||||
|
struct option_port_private *portdata;
|
||||||
|
|
||||||
|
dbg("%s", __FUNCTION__);
|
||||||
|
portdata = usb_get_serial_port_data(port);
|
||||||
|
|
||||||
|
portdata->rts_state = 0;
|
||||||
|
portdata->dtr_state = 0;
|
||||||
|
|
||||||
|
if (serial->dev) {
|
||||||
|
option_send_setup(port);
|
||||||
|
|
||||||
|
/* Stop reading/writing urbs */
|
||||||
|
for (i = 0; i < N_IN_URB; i++)
|
||||||
|
stop_urb(portdata->in_urbs[i]);
|
||||||
|
for (i = 0; i < N_OUT_URB; i++)
|
||||||
|
stop_urb(portdata->out_urbs[i]);
|
||||||
|
}
|
||||||
|
port->tty = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Helper functions used by option_setup_urbs */
|
||||||
|
static struct urb *
|
||||||
|
option_setup_urb (struct usb_serial *serial, int endpoint,
|
||||||
|
int dir, void *ctx, char *buf, int len,
|
||||||
|
void (*callback)(struct urb *, struct pt_regs *regs))
|
||||||
|
{
|
||||||
|
struct urb *urb;
|
||||||
|
|
||||||
|
if (endpoint == -1)
|
||||||
|
return NULL; /* endpoint not needed */
|
||||||
|
|
||||||
|
urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */
|
||||||
|
if (urb == NULL) {
|
||||||
|
dbg("%s: alloc for endpoint %d failed.", __FUNCTION__, endpoint);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fill URB using supplied data. */
|
||||||
|
usb_fill_bulk_urb(urb, serial->dev,
|
||||||
|
usb_sndbulkpipe(serial->dev, endpoint) | dir,
|
||||||
|
buf, len, callback, ctx);
|
||||||
|
|
||||||
|
return urb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup urbs */
|
||||||
|
static void
|
||||||
|
option_setup_urbs(struct usb_serial *serial)
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
struct usb_serial_port *port;
|
||||||
|
struct option_port_private *portdata;
|
||||||
|
|
||||||
|
dbg("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
port = serial->port[0];
|
||||||
|
portdata = usb_get_serial_port_data(port);
|
||||||
|
|
||||||
|
/* Do indat endpoints first */
|
||||||
|
for (j = 0; j <= N_IN_URB; ++j) {
|
||||||
|
portdata->in_urbs[j] = option_setup_urb (serial,
|
||||||
|
port->bulk_in_endpointAddress, USB_DIR_IN, port,
|
||||||
|
portdata->in_buffer[j], IN_BUFLEN, option_indat_callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* outdat endpoints */
|
||||||
|
for (j = 0; j <= N_OUT_URB; ++j) {
|
||||||
|
portdata->out_urbs[j] = option_setup_urb (serial,
|
||||||
|
port->bulk_out_endpointAddress, USB_DIR_OUT, port,
|
||||||
|
portdata->out_buffer[j], OUT_BUFLEN, option_outdat_callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
option_send_setup(struct usb_serial_port *port)
|
||||||
|
{
|
||||||
|
struct usb_serial *serial = port->serial;
|
||||||
|
struct option_port_private *portdata;
|
||||||
|
|
||||||
|
dbg("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
portdata = usb_get_serial_port_data(port);
|
||||||
|
|
||||||
|
if (port->tty) {
|
||||||
|
int val = 0;
|
||||||
|
if (portdata->dtr_state)
|
||||||
|
val |= 0x01;
|
||||||
|
if (portdata->rts_state)
|
||||||
|
val |= 0x02;
|
||||||
|
|
||||||
|
return usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
|
||||||
|
0x22,0x21,val,0,NULL,0,USB_CTRL_SET_TIMEOUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
option_startup (struct usb_serial *serial)
|
||||||
|
{
|
||||||
|
int i, err;
|
||||||
|
struct usb_serial_port *port;
|
||||||
|
struct option_port_private *portdata;
|
||||||
|
|
||||||
|
dbg("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
/* Now setup per port private data */
|
||||||
|
for (i = 0; i < serial->num_ports; i++) {
|
||||||
|
port = serial->port[i];
|
||||||
|
portdata = kmalloc(sizeof(struct option_port_private), GFP_KERNEL);
|
||||||
|
if (!portdata) {
|
||||||
|
dbg("%s: kmalloc for option_port_private (%d) failed!.", __FUNCTION__, i);
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
memset(portdata, 0, sizeof(struct option_port_private));
|
||||||
|
|
||||||
|
usb_set_serial_port_data(port, portdata);
|
||||||
|
|
||||||
|
if (! port->interrupt_in_urb)
|
||||||
|
continue;
|
||||||
|
err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
|
||||||
|
if (err)
|
||||||
|
dbg("%s: submit irq_in urb failed %d", __FUNCTION__, err);
|
||||||
|
}
|
||||||
|
|
||||||
|
option_setup_urbs(serial);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
option_shutdown (struct usb_serial *serial)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
struct usb_serial_port *port;
|
||||||
|
struct option_port_private *portdata;
|
||||||
|
|
||||||
|
dbg("%s", __FUNCTION__);
|
||||||
|
|
||||||
|
/* Stop reading/writing urbs */
|
||||||
|
for (i = 0; i < serial->num_ports; ++i) {
|
||||||
|
port = serial->port[i];
|
||||||
|
portdata = usb_get_serial_port_data(port);
|
||||||
|
for (j = 0; j < N_IN_URB; j++)
|
||||||
|
stop_urb(portdata->in_urbs[j]);
|
||||||
|
for (j = 0; j < N_OUT_URB; j++)
|
||||||
|
stop_urb(portdata->out_urbs[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now free them */
|
||||||
|
for (i = 0; i < serial->num_ports; ++i) {
|
||||||
|
port = serial->port[i];
|
||||||
|
portdata = usb_get_serial_port_data(port);
|
||||||
|
|
||||||
|
for (j = 0; j < N_IN_URB; j++) {
|
||||||
|
if (portdata->in_urbs[j]) {
|
||||||
|
usb_free_urb(portdata->in_urbs[j]);
|
||||||
|
portdata->in_urbs[j] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (j = 0; j < N_OUT_URB; j++) {
|
||||||
|
if (portdata->out_urbs[j]) {
|
||||||
|
usb_free_urb(portdata->out_urbs[j]);
|
||||||
|
portdata->out_urbs[j] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Now free per port private data */
|
||||||
|
for (i = 0; i < serial->num_ports; i++) {
|
||||||
|
port = serial->port[i];
|
||||||
|
kfree(usb_get_serial_port_data(port));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MODULE_AUTHOR(DRIVER_AUTHOR);
|
||||||
|
MODULE_DESCRIPTION(DRIVER_DESC);
|
||||||
|
MODULE_VERSION(DRIVER_VERSION);
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
|
||||||
|
module_param(debug, bool, S_IRUGO | S_IWUSR);
|
||||||
|
MODULE_PARM_DESC(debug, "Debug messages");
|
||||||
|
|
|
@ -1297,13 +1297,6 @@ static int __init usb_serial_init(void)
|
||||||
goto exit_bus;
|
goto exit_bus;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* register the generic driver, if we should */
|
|
||||||
result = usb_serial_generic_register(debug);
|
|
||||||
if (result < 0) {
|
|
||||||
err("%s - registering generic driver failed", __FUNCTION__);
|
|
||||||
goto exit_generic;
|
|
||||||
}
|
|
||||||
|
|
||||||
usb_serial_tty_driver->owner = THIS_MODULE;
|
usb_serial_tty_driver->owner = THIS_MODULE;
|
||||||
usb_serial_tty_driver->driver_name = "usbserial";
|
usb_serial_tty_driver->driver_name = "usbserial";
|
||||||
usb_serial_tty_driver->devfs_name = "usb/tts/";
|
usb_serial_tty_driver->devfs_name = "usb/tts/";
|
||||||
|
@ -1329,17 +1322,24 @@ static int __init usb_serial_init(void)
|
||||||
goto exit_tty;
|
goto exit_tty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* register the generic driver, if we should */
|
||||||
|
result = usb_serial_generic_register(debug);
|
||||||
|
if (result < 0) {
|
||||||
|
err("%s - registering generic driver failed", __FUNCTION__);
|
||||||
|
goto exit_generic;
|
||||||
|
}
|
||||||
|
|
||||||
info(DRIVER_DESC " " DRIVER_VERSION);
|
info(DRIVER_DESC " " DRIVER_VERSION);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
|
exit_generic:
|
||||||
|
usb_deregister(&usb_serial_driver);
|
||||||
|
|
||||||
exit_tty:
|
exit_tty:
|
||||||
tty_unregister_driver(usb_serial_tty_driver);
|
tty_unregister_driver(usb_serial_tty_driver);
|
||||||
|
|
||||||
exit_reg_driver:
|
exit_reg_driver:
|
||||||
usb_serial_generic_deregister();
|
|
||||||
|
|
||||||
exit_generic:
|
|
||||||
bus_unregister(&usb_serial_bus_type);
|
bus_unregister(&usb_serial_bus_type);
|
||||||
|
|
||||||
exit_bus:
|
exit_bus:
|
||||||
|
|
|
@ -862,6 +862,15 @@ UNUSUAL_DEV( 0x090a, 0x1001, 0x0100, 0x0100,
|
||||||
US_SC_DEVICE, US_PR_BULK, NULL,
|
US_SC_DEVICE, US_PR_BULK, NULL,
|
||||||
US_FL_NEED_OVERRIDE ),
|
US_FL_NEED_OVERRIDE ),
|
||||||
|
|
||||||
|
/* Reported by Filippo Bardelli <filibard@libero.it>
|
||||||
|
* The device reports a subclass of RBC, which is wrong.
|
||||||
|
*/
|
||||||
|
UNUSUAL_DEV( 0x090a, 0x1050, 0x0100, 0x0100,
|
||||||
|
"Trumpion Microelectronics, Inc.",
|
||||||
|
"33520 USB Digital Voice Recorder",
|
||||||
|
US_SC_UFI, US_PR_DEVICE, NULL,
|
||||||
|
0),
|
||||||
|
|
||||||
/* Trumpion Microelectronics MP3 player (felipe_alfaro@linuxmail.org) */
|
/* Trumpion Microelectronics MP3 player (felipe_alfaro@linuxmail.org) */
|
||||||
UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999,
|
UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999,
|
||||||
"Trumpion",
|
"Trumpion",
|
||||||
|
|
|
@ -371,7 +371,7 @@ A partial list of the supported mount options follows:
|
||||||
on newly created files, directories, and devices (create,
|
on newly created files, directories, and devices (create,
|
||||||
mkdir, mknod) which will result in the server setting the
|
mkdir, mknod) which will result in the server setting the
|
||||||
uid and gid to the default (usually the server uid of the
|
uid and gid to the default (usually the server uid of the
|
||||||
usern who mounted the share). Letting the server (rather than
|
user who mounted the share). Letting the server (rather than
|
||||||
the client) set the uid and gid is the default. This
|
the client) set the uid and gid is the default. This
|
||||||
parameter has no effect if the CIFS Unix Extensions are not
|
parameter has no effect if the CIFS Unix Extensions are not
|
||||||
negotiated.
|
negotiated.
|
||||||
|
@ -384,7 +384,7 @@ A partial list of the supported mount options follows:
|
||||||
client (e.g. when the application is doing large sequential
|
client (e.g. when the application is doing large sequential
|
||||||
reads bigger than page size without rereading the same data)
|
reads bigger than page size without rereading the same data)
|
||||||
this can provide better performance than the default
|
this can provide better performance than the default
|
||||||
behavior which caches reads (reaadahead) and writes
|
behavior which caches reads (readahead) and writes
|
||||||
(writebehind) through the local Linux client pagecache
|
(writebehind) through the local Linux client pagecache
|
||||||
if oplock (caching token) is granted and held. Note that
|
if oplock (caching token) is granted and held. Note that
|
||||||
direct allows write operations larger than page size
|
direct allows write operations larger than page size
|
||||||
|
|
|
@ -228,7 +228,7 @@ extern int CIFSGetSrvInodeNumber(const int xid, struct cifsTconInfo *tcon,
|
||||||
const struct nls_table *nls_codepage,
|
const struct nls_table *nls_codepage,
|
||||||
int remap_special_chars);
|
int remap_special_chars);
|
||||||
#endif /* CONFIG_CIFS_EXPERIMENTAL */
|
#endif /* CONFIG_CIFS_EXPERIMENTAL */
|
||||||
extern int cifs_convertUCSpath(char *target, const __u16 *source, int maxlen,
|
extern int cifs_convertUCSpath(char *target, const __le16 *source, int maxlen,
|
||||||
const struct nls_table * codepage);
|
const struct nls_table * codepage);
|
||||||
extern int cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
|
extern int cifsConvertToUCS(__le16 * target, const char *source, int maxlen,
|
||||||
const struct nls_table * cp, int mapChars);
|
const struct nls_table * cp, int mapChars);
|
||||||
|
|
|
@ -567,7 +567,7 @@ DelFileRetry:
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len =
|
name_len =
|
||||||
cifsConvertToUCS((__u16 *) pSMB->fileName, fileName,
|
cifsConvertToUCS((__le16 *) pSMB->fileName, fileName,
|
||||||
PATH_MAX, nls_codepage, remap);
|
PATH_MAX, nls_codepage, remap);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
|
@ -665,7 +665,7 @@ MkDirRetry:
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len = cifsConvertToUCS((__u16 *) pSMB->DirName, name,
|
name_len = cifsConvertToUCS((__le16 *) pSMB->DirName, name,
|
||||||
PATH_MAX, nls_codepage, remap);
|
PATH_MAX, nls_codepage, remap);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
|
@ -719,7 +719,7 @@ openRetry:
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
count = 1; /* account for one byte pad to word boundary */
|
count = 1; /* account for one byte pad to word boundary */
|
||||||
name_len =
|
name_len =
|
||||||
cifsConvertToUCS((__u16 *) (pSMB->fileName + 1),
|
cifsConvertToUCS((__le16 *) (pSMB->fileName + 1),
|
||||||
fileName, PATH_MAX, nls_codepage, remap);
|
fileName, PATH_MAX, nls_codepage, remap);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
|
@ -1141,7 +1141,7 @@ renameRetry:
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len =
|
name_len =
|
||||||
cifsConvertToUCS((__u16 *) pSMB->OldFileName, fromName,
|
cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
|
||||||
PATH_MAX, nls_codepage, remap);
|
PATH_MAX, nls_codepage, remap);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
|
@ -1149,7 +1149,7 @@ renameRetry:
|
||||||
/* protocol requires ASCII signature byte on Unicode string */
|
/* protocol requires ASCII signature byte on Unicode string */
|
||||||
pSMB->OldFileName[name_len + 1] = 0x00;
|
pSMB->OldFileName[name_len + 1] = 0x00;
|
||||||
name_len2 =
|
name_len2 =
|
||||||
cifsConvertToUCS((__u16 *) &pSMB->OldFileName[name_len + 2],
|
cifsConvertToUCS((__le16 *) &pSMB->OldFileName[name_len + 2],
|
||||||
toName, PATH_MAX, nls_codepage, remap);
|
toName, PATH_MAX, nls_codepage, remap);
|
||||||
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
|
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
|
||||||
name_len2 *= 2; /* convert to bytes */
|
name_len2 *= 2; /* convert to bytes */
|
||||||
|
@ -1236,10 +1236,10 @@ int CIFSSMBRenameOpenFile(const int xid,struct cifsTconInfo *pTcon,
|
||||||
/* unicode only call */
|
/* unicode only call */
|
||||||
if(target_name == NULL) {
|
if(target_name == NULL) {
|
||||||
sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
|
sprintf(dummy_string,"cifs%x",pSMB->hdr.Mid);
|
||||||
len_of_str = cifsConvertToUCS((__u16 *)rename_info->target_name,
|
len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
|
||||||
dummy_string, 24, nls_codepage, remap);
|
dummy_string, 24, nls_codepage, remap);
|
||||||
} else {
|
} else {
|
||||||
len_of_str = cifsConvertToUCS((__u16 *)rename_info->target_name,
|
len_of_str = cifsConvertToUCS((__le16 *)rename_info->target_name,
|
||||||
target_name, PATH_MAX, nls_codepage, remap);
|
target_name, PATH_MAX, nls_codepage, remap);
|
||||||
}
|
}
|
||||||
rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
|
rename_info->target_name_len = cpu_to_le32(2 * len_of_str);
|
||||||
|
@ -1296,7 +1296,7 @@ copyRetry:
|
||||||
pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
|
pSMB->Flags = cpu_to_le16(flags & COPY_TREE);
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len = cifsConvertToUCS((__u16 *) pSMB->OldFileName,
|
name_len = cifsConvertToUCS((__le16 *) pSMB->OldFileName,
|
||||||
fromName, PATH_MAX, nls_codepage,
|
fromName, PATH_MAX, nls_codepage,
|
||||||
remap);
|
remap);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
|
@ -1304,7 +1304,7 @@ copyRetry:
|
||||||
pSMB->OldFileName[name_len] = 0x04; /* pad */
|
pSMB->OldFileName[name_len] = 0x04; /* pad */
|
||||||
/* protocol requires ASCII signature byte on Unicode string */
|
/* protocol requires ASCII signature byte on Unicode string */
|
||||||
pSMB->OldFileName[name_len + 1] = 0x00;
|
pSMB->OldFileName[name_len + 1] = 0x00;
|
||||||
name_len2 = cifsConvertToUCS((__u16 *)&pSMB->OldFileName[name_len + 2],
|
name_len2 = cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
|
||||||
toName, PATH_MAX, nls_codepage, remap);
|
toName, PATH_MAX, nls_codepage, remap);
|
||||||
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
|
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
|
||||||
name_len2 *= 2; /* convert to bytes */
|
name_len2 *= 2; /* convert to bytes */
|
||||||
|
@ -1453,7 +1453,7 @@ createHardLinkRetry:
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len = cifsConvertToUCS((__u16 *) pSMB->FileName, toName,
|
name_len = cifsConvertToUCS((__le16 *) pSMB->FileName, toName,
|
||||||
PATH_MAX, nls_codepage, remap);
|
PATH_MAX, nls_codepage, remap);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
|
@ -1476,7 +1476,7 @@ createHardLinkRetry:
|
||||||
data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
|
data_offset = (char *) (&pSMB->hdr.Protocol) + offset;
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len_target =
|
name_len_target =
|
||||||
cifsConvertToUCS((__u16 *) data_offset, fromName, PATH_MAX,
|
cifsConvertToUCS((__le16 *) data_offset, fromName, PATH_MAX,
|
||||||
nls_codepage, remap);
|
nls_codepage, remap);
|
||||||
name_len_target++; /* trailing null */
|
name_len_target++; /* trailing null */
|
||||||
name_len_target *= 2;
|
name_len_target *= 2;
|
||||||
|
@ -1546,14 +1546,14 @@ winCreateHardLinkRetry:
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len =
|
name_len =
|
||||||
cifsConvertToUCS((__u16 *) pSMB->OldFileName, fromName,
|
cifsConvertToUCS((__le16 *) pSMB->OldFileName, fromName,
|
||||||
PATH_MAX, nls_codepage, remap);
|
PATH_MAX, nls_codepage, remap);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
pSMB->OldFileName[name_len] = 0; /* pad */
|
pSMB->OldFileName[name_len] = 0; /* pad */
|
||||||
pSMB->OldFileName[name_len + 1] = 0x04;
|
pSMB->OldFileName[name_len + 1] = 0x04;
|
||||||
name_len2 =
|
name_len2 =
|
||||||
cifsConvertToUCS((__u16 *)&pSMB->OldFileName[name_len + 2],
|
cifsConvertToUCS((__le16 *)&pSMB->OldFileName[name_len + 2],
|
||||||
toName, PATH_MAX, nls_codepage, remap);
|
toName, PATH_MAX, nls_codepage, remap);
|
||||||
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
|
name_len2 += 1 /* trailing null */ + 1 /* Signature word */ ;
|
||||||
name_len2 *= 2; /* convert to bytes */
|
name_len2 *= 2; /* convert to bytes */
|
||||||
|
@ -1939,7 +1939,7 @@ queryAclRetry:
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len =
|
name_len =
|
||||||
cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
|
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
|
||||||
PATH_MAX, nls_codepage, remap);
|
PATH_MAX, nls_codepage, remap);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
|
@ -2024,7 +2024,7 @@ setAclRetry:
|
||||||
return rc;
|
return rc;
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len =
|
name_len =
|
||||||
cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
|
cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
|
||||||
PATH_MAX, nls_codepage, remap);
|
PATH_MAX, nls_codepage, remap);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
|
@ -2188,7 +2188,7 @@ QPathInfoRetry:
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len =
|
name_len =
|
||||||
cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
|
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
|
||||||
PATH_MAX, nls_codepage, remap);
|
PATH_MAX, nls_codepage, remap);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
|
@ -2269,7 +2269,7 @@ UnixQPathInfoRetry:
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len =
|
name_len =
|
||||||
cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
|
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
|
||||||
PATH_MAX, nls_codepage, remap);
|
PATH_MAX, nls_codepage, remap);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
|
@ -2350,7 +2350,7 @@ findUniqueRetry:
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len =
|
name_len =
|
||||||
cifsConvertToUCS((wchar_t *) pSMB->FileName, searchName, PATH_MAX
|
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName, PATH_MAX
|
||||||
/* find define for this maxpathcomponent */
|
/* find define for this maxpathcomponent */
|
||||||
, nls_codepage);
|
, nls_codepage);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
|
@ -2435,7 +2435,7 @@ findFirstRetry:
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len =
|
name_len =
|
||||||
cifsConvertToUCS((__u16 *) pSMB->FileName,searchName,
|
cifsConvertToUCS((__le16 *) pSMB->FileName,searchName,
|
||||||
PATH_MAX, nls_codepage, remap);
|
PATH_MAX, nls_codepage, remap);
|
||||||
/* We can not add the asterik earlier in case
|
/* We can not add the asterik earlier in case
|
||||||
it got remapped to 0xF03A as if it were part of the
|
it got remapped to 0xF03A as if it were part of the
|
||||||
|
@ -2726,7 +2726,7 @@ GetInodeNumberRetry:
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len =
|
name_len =
|
||||||
cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
|
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
|
||||||
PATH_MAX,nls_codepage, remap);
|
PATH_MAX,nls_codepage, remap);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
|
@ -2837,7 +2837,7 @@ getDFSRetry:
|
||||||
if (ses->capabilities & CAP_UNICODE) {
|
if (ses->capabilities & CAP_UNICODE) {
|
||||||
pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
|
pSMB->hdr.Flags2 |= SMBFLG2_UNICODE;
|
||||||
name_len =
|
name_len =
|
||||||
cifsConvertToUCS((__u16 *) pSMB->RequestFileName,
|
cifsConvertToUCS((__le16 *) pSMB->RequestFileName,
|
||||||
searchName, PATH_MAX, nls_codepage, remap);
|
searchName, PATH_MAX, nls_codepage, remap);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
|
@ -3369,7 +3369,7 @@ SetEOFRetry:
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len =
|
name_len =
|
||||||
cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
|
cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
|
||||||
PATH_MAX, nls_codepage, remap);
|
PATH_MAX, nls_codepage, remap);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
|
@ -3627,7 +3627,7 @@ SetTimesRetry:
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len =
|
name_len =
|
||||||
cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
|
cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
|
||||||
PATH_MAX, nls_codepage, remap);
|
PATH_MAX, nls_codepage, remap);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
|
@ -3708,7 +3708,7 @@ SetAttrLgcyRetry:
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len =
|
name_len =
|
||||||
ConvertToUCS((wchar_t *) pSMB->fileName, fileName,
|
ConvertToUCS((__le16 *) pSMB->fileName, fileName,
|
||||||
PATH_MAX, nls_codepage);
|
PATH_MAX, nls_codepage);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
|
@ -3759,7 +3759,7 @@ setPermsRetry:
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len =
|
name_len =
|
||||||
cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
|
cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
|
||||||
PATH_MAX, nls_codepage, remap);
|
PATH_MAX, nls_codepage, remap);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
|
@ -3904,7 +3904,7 @@ QAllEAsRetry:
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len =
|
name_len =
|
||||||
cifsConvertToUCS((wchar_t *) pSMB->FileName, searchName,
|
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
|
||||||
PATH_MAX, nls_codepage, remap);
|
PATH_MAX, nls_codepage, remap);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
|
@ -4047,7 +4047,7 @@ QEARetry:
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len =
|
name_len =
|
||||||
cifsConvertToUCS((__u16 *) pSMB->FileName, searchName,
|
cifsConvertToUCS((__le16 *) pSMB->FileName, searchName,
|
||||||
PATH_MAX, nls_codepage, remap);
|
PATH_MAX, nls_codepage, remap);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
|
@ -4194,7 +4194,7 @@ SetEARetry:
|
||||||
|
|
||||||
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
if (pSMB->hdr.Flags2 & SMBFLG2_UNICODE) {
|
||||||
name_len =
|
name_len =
|
||||||
cifsConvertToUCS((__u16 *) pSMB->FileName, fileName,
|
cifsConvertToUCS((__le16 *) pSMB->FileName, fileName,
|
||||||
PATH_MAX, nls_codepage, remap);
|
PATH_MAX, nls_codepage, remap);
|
||||||
name_len++; /* trailing null */
|
name_len++; /* trailing null */
|
||||||
name_len *= 2;
|
name_len *= 2;
|
||||||
|
|
|
@ -392,7 +392,8 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
|
||||||
rc = 0;
|
rc = 0;
|
||||||
d_add(direntry, NULL);
|
d_add(direntry, NULL);
|
||||||
} else {
|
} else {
|
||||||
cERROR(1,("Error 0x%x or on cifs_get_inode_info in lookup",rc));
|
cERROR(1,("Error 0x%x on cifs_get_inode_info in lookup of %s",
|
||||||
|
rc,full_path));
|
||||||
/* BB special case check for Access Denied - watch security
|
/* BB special case check for Access Denied - watch security
|
||||||
exposure of returning dir info implicitly via different rc
|
exposure of returning dir info implicitly via different rc
|
||||||
if file exists or not but no access BB */
|
if file exists or not but no access BB */
|
||||||
|
|
|
@ -422,6 +422,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
||||||
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
|
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
|
if(direntry->d_inode)
|
||||||
direntry->d_inode->i_nlink--;
|
direntry->d_inode->i_nlink--;
|
||||||
} else if (rc == -ENOENT) {
|
} else if (rc == -ENOENT) {
|
||||||
d_drop(direntry);
|
d_drop(direntry);
|
||||||
|
@ -440,6 +441,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
CIFSSMBClose(xid, pTcon, netfid);
|
CIFSSMBClose(xid, pTcon, netfid);
|
||||||
|
if(direntry->d_inode)
|
||||||
direntry->d_inode->i_nlink--;
|
direntry->d_inode->i_nlink--;
|
||||||
}
|
}
|
||||||
} else if (rc == -EACCES) {
|
} else if (rc == -EACCES) {
|
||||||
|
@ -494,6 +496,7 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
if (!rc) {
|
if (!rc) {
|
||||||
|
if(direntry->d_inode)
|
||||||
direntry->d_inode->i_nlink--;
|
direntry->d_inode->i_nlink--;
|
||||||
} else if (rc == -ETXTBSY) {
|
} else if (rc == -ETXTBSY) {
|
||||||
int oplock = FALSE;
|
int oplock = FALSE;
|
||||||
|
@ -514,17 +517,20 @@ int cifs_unlink(struct inode *inode, struct dentry *direntry)
|
||||||
cifs_sb->mnt_cifs_flags &
|
cifs_sb->mnt_cifs_flags &
|
||||||
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
CIFS_MOUNT_MAP_SPECIAL_CHR);
|
||||||
CIFSSMBClose(xid, pTcon, netfid);
|
CIFSSMBClose(xid, pTcon, netfid);
|
||||||
|
if(direntry->d_inode)
|
||||||
direntry->d_inode->i_nlink--;
|
direntry->d_inode->i_nlink--;
|
||||||
}
|
}
|
||||||
/* BB if rc = -ETXTBUSY goto the rename logic BB */
|
/* BB if rc = -ETXTBUSY goto the rename logic BB */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(direntry->d_inode) {
|
||||||
cifsInode = CIFS_I(direntry->d_inode);
|
cifsInode = CIFS_I(direntry->d_inode);
|
||||||
cifsInode->time = 0; /* will force revalidate to get info when
|
cifsInode->time = 0; /* will force revalidate to get info
|
||||||
needed */
|
when needed */
|
||||||
direntry->d_inode->i_ctime = inode->i_ctime = inode->i_mtime =
|
direntry->d_inode->i_ctime = current_fs_time(inode->i_sb);
|
||||||
current_fs_time(inode->i_sb);
|
}
|
||||||
|
inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
|
||||||
cifsInode = CIFS_I(inode);
|
cifsInode = CIFS_I(inode);
|
||||||
cifsInode->time = 0; /* force revalidate of dir as well */
|
cifsInode->time = 0; /* force revalidate of dir as well */
|
||||||
|
|
||||||
|
|
|
@ -571,6 +571,7 @@ cifs_convertUCSpath(char *target, const __le16 * source, int maxlen,
|
||||||
break;
|
break;
|
||||||
case UNI_LESSTHAN:
|
case UNI_LESSTHAN:
|
||||||
target[j] = '<';
|
target[j] = '<';
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
len = cp->uni2char(src_char, &target[j],
|
len = cp->uni2char(src_char, &target[j],
|
||||||
NLS_MAX_CHARSET_SIZE);
|
NLS_MAX_CHARSET_SIZE);
|
||||||
|
|
|
@ -188,7 +188,6 @@ static int __cleanup_transaction(journal_t *journal, transaction_t *transaction)
|
||||||
} else {
|
} else {
|
||||||
jbd_unlock_bh_state(bh);
|
jbd_unlock_bh_state(bh);
|
||||||
}
|
}
|
||||||
jh = next_jh;
|
|
||||||
} while (jh != last_jh);
|
} while (jh != last_jh);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -339,8 +338,10 @@ int log_do_checkpoint(journal_t *journal)
|
||||||
}
|
}
|
||||||
} while (jh != last_jh && !retry);
|
} while (jh != last_jh && !retry);
|
||||||
|
|
||||||
if (batch_count)
|
if (batch_count) {
|
||||||
__flush_batch(journal, bhs, &batch_count);
|
__flush_batch(journal, bhs, &batch_count);
|
||||||
|
retry = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If someone cleaned up this transaction while we slept, we're
|
* If someone cleaned up this transaction while we slept, we're
|
||||||
|
|
|
@ -79,8 +79,11 @@ static int mpage_end_io_write(struct bio *bio, unsigned int bytes_done, int err)
|
||||||
if (--bvec >= bio->bi_io_vec)
|
if (--bvec >= bio->bi_io_vec)
|
||||||
prefetchw(&bvec->bv_page->flags);
|
prefetchw(&bvec->bv_page->flags);
|
||||||
|
|
||||||
if (!uptodate)
|
if (!uptodate){
|
||||||
SetPageError(page);
|
SetPageError(page);
|
||||||
|
if (page->mapping)
|
||||||
|
set_bit(AS_EIO, &page->mapping->flags);
|
||||||
|
}
|
||||||
end_page_writeback(page);
|
end_page_writeback(page);
|
||||||
} while (bvec >= bio->bi_io_vec);
|
} while (bvec >= bio->bi_io_vec);
|
||||||
bio_put(bio);
|
bio_put(bio);
|
||||||
|
|
|
@ -12,15 +12,8 @@
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
|
|
||||||
#ifndef HAVE_ARCH_DEVTREE_FIXUPS
|
#ifndef HAVE_ARCH_DEVTREE_FIXUPS
|
||||||
static inline void set_node_proc_entry(struct device_node *np, struct proc_dir_entry *de)
|
static inline void set_node_proc_entry(struct device_node *np,
|
||||||
{
|
struct proc_dir_entry *de)
|
||||||
}
|
|
||||||
|
|
||||||
static void inline set_node_name_link(struct device_node *np, struct proc_dir_entry *de)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static void inline set_node_addr_link(struct device_node *np, struct proc_dir_entry *de)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -58,89 +51,67 @@ static int property_read_proc(char *page, char **start, off_t off,
|
||||||
/*
|
/*
|
||||||
* Process a node, adding entries for its children and its properties.
|
* Process a node, adding entries for its children and its properties.
|
||||||
*/
|
*/
|
||||||
void proc_device_tree_add_node(struct device_node *np, struct proc_dir_entry *de)
|
void proc_device_tree_add_node(struct device_node *np,
|
||||||
|
struct proc_dir_entry *de)
|
||||||
{
|
{
|
||||||
struct property *pp;
|
struct property *pp;
|
||||||
struct proc_dir_entry *ent;
|
struct proc_dir_entry *ent;
|
||||||
struct device_node *child, *sib;
|
struct device_node *child;
|
||||||
const char *p, *at;
|
struct proc_dir_entry *list = NULL, **lastp;
|
||||||
int l;
|
const char *p;
|
||||||
struct proc_dir_entry *list, **lastp, *al;
|
|
||||||
|
|
||||||
set_node_proc_entry(np, de);
|
set_node_proc_entry(np, de);
|
||||||
lastp = &list;
|
lastp = &list;
|
||||||
|
for (child = NULL; (child = of_get_next_child(np, child));) {
|
||||||
|
p = strrchr(child->full_name, '/');
|
||||||
|
if (!p)
|
||||||
|
p = child->full_name;
|
||||||
|
else
|
||||||
|
++p;
|
||||||
|
ent = proc_mkdir(p, de);
|
||||||
|
if (ent == 0)
|
||||||
|
break;
|
||||||
|
*lastp = ent;
|
||||||
|
ent->next = NULL;
|
||||||
|
lastp = &ent->next;
|
||||||
|
proc_device_tree_add_node(child, ent);
|
||||||
|
}
|
||||||
|
of_node_put(child);
|
||||||
for (pp = np->properties; pp != 0; pp = pp->next) {
|
for (pp = np->properties; pp != 0; pp = pp->next) {
|
||||||
|
/*
|
||||||
|
* Yet another Apple device-tree bogosity: on some machines,
|
||||||
|
* they have properties & nodes with the same name. Those
|
||||||
|
* properties are quite unimportant for us though, thus we
|
||||||
|
* simply "skip" them here, but we do have to check.
|
||||||
|
*/
|
||||||
|
for (ent = list; ent != NULL; ent = ent->next)
|
||||||
|
if (!strcmp(ent->name, pp->name))
|
||||||
|
break;
|
||||||
|
if (ent != NULL) {
|
||||||
|
printk(KERN_WARNING "device-tree: property \"%s\" name"
|
||||||
|
" conflicts with node in %s\n", pp->name,
|
||||||
|
np->full_name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unfortunately proc_register puts each new entry
|
* Unfortunately proc_register puts each new entry
|
||||||
* at the beginning of the list. So we rearrange them.
|
* at the beginning of the list. So we rearrange them.
|
||||||
*/
|
*/
|
||||||
ent = create_proc_read_entry(pp->name, strncmp(pp->name, "security-", 9) ?
|
ent = create_proc_read_entry(pp->name,
|
||||||
S_IRUGO : S_IRUSR, de, property_read_proc, pp);
|
strncmp(pp->name, "security-", 9)
|
||||||
|
? S_IRUGO : S_IRUSR, de,
|
||||||
|
property_read_proc, pp);
|
||||||
if (ent == 0)
|
if (ent == 0)
|
||||||
break;
|
break;
|
||||||
if (!strncmp(pp->name, "security-", 9))
|
if (!strncmp(pp->name, "security-", 9))
|
||||||
ent->size = 0; /* don't leak number of password chars */
|
ent->size = 0; /* don't leak number of password chars */
|
||||||
else
|
else
|
||||||
ent->size = pp->length;
|
ent->size = pp->length;
|
||||||
|
ent->next = NULL;
|
||||||
*lastp = ent;
|
*lastp = ent;
|
||||||
lastp = &ent->next;
|
lastp = &ent->next;
|
||||||
}
|
}
|
||||||
child = NULL;
|
|
||||||
while ((child = of_get_next_child(np, child))) {
|
|
||||||
p = strrchr(child->full_name, '/');
|
|
||||||
if (!p)
|
|
||||||
p = child->full_name;
|
|
||||||
else
|
|
||||||
++p;
|
|
||||||
/* chop off '@0' if the name ends with that */
|
|
||||||
l = strlen(p);
|
|
||||||
if (l > 2 && p[l-2] == '@' && p[l-1] == '0')
|
|
||||||
l -= 2;
|
|
||||||
ent = proc_mkdir(p, de);
|
|
||||||
if (ent == 0)
|
|
||||||
break;
|
|
||||||
*lastp = ent;
|
|
||||||
lastp = &ent->next;
|
|
||||||
proc_device_tree_add_node(child, ent);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If we left the address part on the name, consider
|
|
||||||
* adding symlinks from the name and address parts.
|
|
||||||
*/
|
|
||||||
if (p[l] != 0 || (at = strchr(p, '@')) == 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If this is the first node with a given name property,
|
|
||||||
* add a symlink with the name property as its name.
|
|
||||||
*/
|
|
||||||
sib = NULL;
|
|
||||||
while ((sib = of_get_next_child(np, sib)) && sib != child)
|
|
||||||
if (sib->name && strcmp(sib->name, child->name) == 0)
|
|
||||||
break;
|
|
||||||
if (sib == child && strncmp(p, child->name, l) != 0) {
|
|
||||||
al = proc_symlink(child->name, de, ent->name);
|
|
||||||
if (al == 0) {
|
|
||||||
of_node_put(sib);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
set_node_name_link(child, al);
|
|
||||||
*lastp = al;
|
|
||||||
lastp = &al->next;
|
|
||||||
}
|
|
||||||
of_node_put(sib);
|
|
||||||
/*
|
|
||||||
* Add another directory with the @address part as its name.
|
|
||||||
*/
|
|
||||||
al = proc_symlink(at, de, ent->name);
|
|
||||||
if (al == 0)
|
|
||||||
break;
|
|
||||||
set_node_addr_link(child, al);
|
|
||||||
*lastp = al;
|
|
||||||
lastp = &al->next;
|
|
||||||
}
|
|
||||||
of_node_put(child);
|
|
||||||
*lastp = NULL;
|
|
||||||
de->subdir = list;
|
de->subdir = list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -120,103 +120,18 @@
|
||||||
|
|
||||||
/* Special Purpose Registers (SPRNs)*/
|
/* Special Purpose Registers (SPRNs)*/
|
||||||
|
|
||||||
#define SPRN_CDBCR 0x3D7 /* Cache Debug Control Register */
|
|
||||||
#define SPRN_CTR 0x009 /* Count Register */
|
#define SPRN_CTR 0x009 /* Count Register */
|
||||||
#define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */
|
#define SPRN_DABR 0x3F5 /* Data Address Breakpoint Register */
|
||||||
#define SPRN_DAC1 0x3F6 /* Data Address Compare 1 */
|
#define DABR_TRANSLATION (1UL << 2)
|
||||||
#define SPRN_DAC2 0x3F7 /* Data Address Compare 2 */
|
|
||||||
#define SPRN_DAR 0x013 /* Data Address Register */
|
#define SPRN_DAR 0x013 /* Data Address Register */
|
||||||
#define SPRN_DBCR 0x3F2 /* Debug Control Regsiter */
|
|
||||||
#define DBCR_EDM 0x80000000
|
|
||||||
#define DBCR_IDM 0x40000000
|
|
||||||
#define DBCR_RST(x) (((x) & 0x3) << 28)
|
|
||||||
#define DBCR_RST_NONE 0
|
|
||||||
#define DBCR_RST_CORE 1
|
|
||||||
#define DBCR_RST_CHIP 2
|
|
||||||
#define DBCR_RST_SYSTEM 3
|
|
||||||
#define DBCR_IC 0x08000000 /* Instruction Completion Debug Evnt */
|
|
||||||
#define DBCR_BT 0x04000000 /* Branch Taken Debug Event */
|
|
||||||
#define DBCR_EDE 0x02000000 /* Exception Debug Event */
|
|
||||||
#define DBCR_TDE 0x01000000 /* TRAP Debug Event */
|
|
||||||
#define DBCR_FER 0x00F80000 /* First Events Remaining Mask */
|
|
||||||
#define DBCR_FT 0x00040000 /* Freeze Timers on Debug Event */
|
|
||||||
#define DBCR_IA1 0x00020000 /* Instr. Addr. Compare 1 Enable */
|
|
||||||
#define DBCR_IA2 0x00010000 /* Instr. Addr. Compare 2 Enable */
|
|
||||||
#define DBCR_D1R 0x00008000 /* Data Addr. Compare 1 Read Enable */
|
|
||||||
#define DBCR_D1W 0x00004000 /* Data Addr. Compare 1 Write Enable */
|
|
||||||
#define DBCR_D1S(x) (((x) & 0x3) << 12) /* Data Adrr. Compare 1 Size */
|
|
||||||
#define DAC_BYTE 0
|
|
||||||
#define DAC_HALF 1
|
|
||||||
#define DAC_WORD 2
|
|
||||||
#define DAC_QUAD 3
|
|
||||||
#define DBCR_D2R 0x00000800 /* Data Addr. Compare 2 Read Enable */
|
|
||||||
#define DBCR_D2W 0x00000400 /* Data Addr. Compare 2 Write Enable */
|
|
||||||
#define DBCR_D2S(x) (((x) & 0x3) << 8) /* Data Addr. Compare 2 Size */
|
|
||||||
#define DBCR_SBT 0x00000040 /* Second Branch Taken Debug Event */
|
|
||||||
#define DBCR_SED 0x00000020 /* Second Exception Debug Event */
|
|
||||||
#define DBCR_STD 0x00000010 /* Second Trap Debug Event */
|
|
||||||
#define DBCR_SIA 0x00000008 /* Second IAC Enable */
|
|
||||||
#define DBCR_SDA 0x00000004 /* Second DAC Enable */
|
|
||||||
#define DBCR_JOI 0x00000002 /* JTAG Serial Outbound Int. Enable */
|
|
||||||
#define DBCR_JII 0x00000001 /* JTAG Serial Inbound Int. Enable */
|
|
||||||
#define SPRN_DBCR0 0x3F2 /* Debug Control Register 0 */
|
|
||||||
#define SPRN_DBCR1 0x3BD /* Debug Control Register 1 */
|
|
||||||
#define SPRN_DBSR 0x3F0 /* Debug Status Register */
|
|
||||||
#define SPRN_DCCR 0x3FA /* Data Cache Cacheability Register */
|
|
||||||
#define DCCR_NOCACHE 0 /* Noncacheable */
|
|
||||||
#define DCCR_CACHE 1 /* Cacheable */
|
|
||||||
#define SPRN_DCMP 0x3D1 /* Data TLB Compare Register */
|
|
||||||
#define SPRN_DCWR 0x3BA /* Data Cache Write-thru Register */
|
|
||||||
#define DCWR_COPY 0 /* Copy-back */
|
|
||||||
#define DCWR_WRITE 1 /* Write-through */
|
|
||||||
#define SPRN_DEAR 0x3D5 /* Data Error Address Register */
|
|
||||||
#define SPRN_DEC 0x016 /* Decrement Register */
|
#define SPRN_DEC 0x016 /* Decrement Register */
|
||||||
#define SPRN_DMISS 0x3D0 /* Data TLB Miss Register */
|
|
||||||
#define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */
|
#define SPRN_DSISR 0x012 /* Data Storage Interrupt Status Register */
|
||||||
#define DSISR_NOHPTE 0x40000000 /* no translation found */
|
#define DSISR_NOHPTE 0x40000000 /* no translation found */
|
||||||
#define DSISR_PROTFAULT 0x08000000 /* protection fault */
|
#define DSISR_PROTFAULT 0x08000000 /* protection fault */
|
||||||
#define DSISR_ISSTORE 0x02000000 /* access was a store */
|
#define DSISR_ISSTORE 0x02000000 /* access was a store */
|
||||||
#define DSISR_DABRMATCH 0x00400000 /* hit data breakpoint */
|
#define DSISR_DABRMATCH 0x00400000 /* hit data breakpoint */
|
||||||
#define DSISR_NOSEGMENT 0x00200000 /* STAB/SLB miss */
|
#define DSISR_NOSEGMENT 0x00200000 /* STAB/SLB miss */
|
||||||
#define SPRN_EAR 0x11A /* External Address Register */
|
|
||||||
#define SPRN_ESR 0x3D4 /* Exception Syndrome Register */
|
|
||||||
#define ESR_IMCP 0x80000000 /* Instr. Machine Check - Protection */
|
|
||||||
#define ESR_IMCN 0x40000000 /* Instr. Machine Check - Non-config */
|
|
||||||
#define ESR_IMCB 0x20000000 /* Instr. Machine Check - Bus error */
|
|
||||||
#define ESR_IMCT 0x10000000 /* Instr. Machine Check - Timeout */
|
|
||||||
#define ESR_PIL 0x08000000 /* Program Exception - Illegal */
|
|
||||||
#define ESR_PPR 0x04000000 /* Program Exception - Priveleged */
|
|
||||||
#define ESR_PTR 0x02000000 /* Program Exception - Trap */
|
|
||||||
#define ESR_DST 0x00800000 /* Storage Exception - Data miss */
|
|
||||||
#define ESR_DIZ 0x00400000 /* Storage Exception - Zone fault */
|
|
||||||
#define SPRN_EVPR 0x3D6 /* Exception Vector Prefix Register */
|
|
||||||
#define SPRN_HASH1 0x3D2 /* Primary Hash Address Register */
|
|
||||||
#define SPRN_HASH2 0x3D3 /* Secondary Hash Address Resgister */
|
|
||||||
#define SPRN_HID0 0x3F0 /* Hardware Implementation Register 0 */
|
#define SPRN_HID0 0x3F0 /* Hardware Implementation Register 0 */
|
||||||
#define HID0_EMCP (1<<31) /* Enable Machine Check pin */
|
|
||||||
#define HID0_EBA (1<<29) /* Enable Bus Address Parity */
|
|
||||||
#define HID0_EBD (1<<28) /* Enable Bus Data Parity */
|
|
||||||
#define HID0_SBCLK (1<<27)
|
|
||||||
#define HID0_EICE (1<<26)
|
|
||||||
#define HID0_ECLK (1<<25)
|
|
||||||
#define HID0_PAR (1<<24)
|
|
||||||
#define HID0_DOZE (1<<23)
|
|
||||||
#define HID0_NAP (1<<22)
|
|
||||||
#define HID0_SLEEP (1<<21)
|
|
||||||
#define HID0_DPM (1<<20)
|
|
||||||
#define HID0_ICE (1<<15) /* Instruction Cache Enable */
|
|
||||||
#define HID0_DCE (1<<14) /* Data Cache Enable */
|
|
||||||
#define HID0_ILOCK (1<<13) /* Instruction Cache Lock */
|
|
||||||
#define HID0_DLOCK (1<<12) /* Data Cache Lock */
|
|
||||||
#define HID0_ICFI (1<<11) /* Instr. Cache Flash Invalidate */
|
|
||||||
#define HID0_DCI (1<<10) /* Data Cache Invalidate */
|
|
||||||
#define HID0_SPD (1<<9) /* Speculative disable */
|
|
||||||
#define HID0_SGE (1<<7) /* Store Gathering Enable */
|
|
||||||
#define HID0_SIED (1<<7) /* Serial Instr. Execution [Disable] */
|
|
||||||
#define HID0_BTIC (1<<5) /* Branch Target Instruction Cache Enable */
|
|
||||||
#define HID0_ABE (1<<3) /* Address Broadcast Enable */
|
|
||||||
#define HID0_BHTE (1<<2) /* Branch History Table Enable */
|
|
||||||
#define HID0_BTCD (1<<1) /* Branch target cache disable */
|
|
||||||
#define SPRN_MSRDORM 0x3F1 /* Hardware Implementation Register 1 */
|
#define SPRN_MSRDORM 0x3F1 /* Hardware Implementation Register 1 */
|
||||||
#define SPRN_HID1 0x3F1 /* Hardware Implementation Register 1 */
|
#define SPRN_HID1 0x3F1 /* Hardware Implementation Register 1 */
|
||||||
#define SPRN_IABR 0x3F2 /* Instruction Address Breakpoint Register */
|
#define SPRN_IABR 0x3F2 /* Instruction Address Breakpoint Register */
|
||||||
|
@ -225,23 +140,8 @@
|
||||||
#define SPRN_HID5 0x3F6 /* 970 HID5 */
|
#define SPRN_HID5 0x3F6 /* 970 HID5 */
|
||||||
#define SPRN_TSC 0x3FD /* Thread switch control */
|
#define SPRN_TSC 0x3FD /* Thread switch control */
|
||||||
#define SPRN_TST 0x3FC /* Thread switch timeout */
|
#define SPRN_TST 0x3FC /* Thread switch timeout */
|
||||||
#define SPRN_IAC1 0x3F4 /* Instruction Address Compare 1 */
|
|
||||||
#define SPRN_IAC2 0x3F5 /* Instruction Address Compare 2 */
|
|
||||||
#define SPRN_ICCR 0x3FB /* Instruction Cache Cacheability Register */
|
|
||||||
#define ICCR_NOCACHE 0 /* Noncacheable */
|
|
||||||
#define ICCR_CACHE 1 /* Cacheable */
|
|
||||||
#define SPRN_ICDBDR 0x3D3 /* Instruction Cache Debug Data Register */
|
|
||||||
#define SPRN_ICMP 0x3D5 /* Instruction TLB Compare Register */
|
|
||||||
#define SPRN_ICTC 0x3FB /* Instruction Cache Throttling Control Reg */
|
|
||||||
#define SPRN_IMISS 0x3D4 /* Instruction TLB Miss Register */
|
|
||||||
#define SPRN_IMMR 0x27E /* Internal Memory Map Register */
|
|
||||||
#define SPRN_L2CR 0x3F9 /* Level 2 Cache Control Regsiter */
|
#define SPRN_L2CR 0x3F9 /* Level 2 Cache Control Regsiter */
|
||||||
#define SPRN_LR 0x008 /* Link Register */
|
#define SPRN_LR 0x008 /* Link Register */
|
||||||
#define SPRN_PBL1 0x3FC /* Protection Bound Lower 1 */
|
|
||||||
#define SPRN_PBL2 0x3FE /* Protection Bound Lower 2 */
|
|
||||||
#define SPRN_PBU1 0x3FD /* Protection Bound Upper 1 */
|
|
||||||
#define SPRN_PBU2 0x3FF /* Protection Bound Upper 2 */
|
|
||||||
#define SPRN_PID 0x3B1 /* Process ID */
|
|
||||||
#define SPRN_PIR 0x3FF /* Processor Identification Register */
|
#define SPRN_PIR 0x3FF /* Processor Identification Register */
|
||||||
#define SPRN_PIT 0x3DB /* Programmable Interval Timer */
|
#define SPRN_PIT 0x3DB /* Programmable Interval Timer */
|
||||||
#define SPRN_PURR 0x135 /* Processor Utilization of Resources Register */
|
#define SPRN_PURR 0x135 /* Processor Utilization of Resources Register */
|
||||||
|
@ -249,9 +149,6 @@
|
||||||
#define SPRN_RPA 0x3D6 /* Required Physical Address Register */
|
#define SPRN_RPA 0x3D6 /* Required Physical Address Register */
|
||||||
#define SPRN_SDA 0x3BF /* Sampled Data Address Register */
|
#define SPRN_SDA 0x3BF /* Sampled Data Address Register */
|
||||||
#define SPRN_SDR1 0x019 /* MMU Hash Base Register */
|
#define SPRN_SDR1 0x019 /* MMU Hash Base Register */
|
||||||
#define SPRN_SGR 0x3B9 /* Storage Guarded Register */
|
|
||||||
#define SGR_NORMAL 0
|
|
||||||
#define SGR_GUARDED 1
|
|
||||||
#define SPRN_SIA 0x3BB /* Sampled Instruction Address Register */
|
#define SPRN_SIA 0x3BB /* Sampled Instruction Address Register */
|
||||||
#define SPRN_SPRG0 0x110 /* Special Purpose Register General 0 */
|
#define SPRN_SPRG0 0x110 /* Special Purpose Register General 0 */
|
||||||
#define SPRN_SPRG1 0x111 /* Special Purpose Register General 1 */
|
#define SPRN_SPRG1 0x111 /* Special Purpose Register General 1 */
|
||||||
|
@ -264,50 +161,12 @@
|
||||||
#define SPRN_TBWL 0x11C /* Time Base Lower Register (super, W/O) */
|
#define SPRN_TBWL 0x11C /* Time Base Lower Register (super, W/O) */
|
||||||
#define SPRN_TBWU 0x11D /* Time Base Write Upper Register (super, W/O) */
|
#define SPRN_TBWU 0x11D /* Time Base Write Upper Register (super, W/O) */
|
||||||
#define SPRN_HIOR 0x137 /* 970 Hypervisor interrupt offset */
|
#define SPRN_HIOR 0x137 /* 970 Hypervisor interrupt offset */
|
||||||
#define SPRN_TCR 0x3DA /* Timer Control Register */
|
|
||||||
#define TCR_WP(x) (((x)&0x3)<<30) /* WDT Period */
|
|
||||||
#define WP_2_17 0 /* 2^17 clocks */
|
|
||||||
#define WP_2_21 1 /* 2^21 clocks */
|
|
||||||
#define WP_2_25 2 /* 2^25 clocks */
|
|
||||||
#define WP_2_29 3 /* 2^29 clocks */
|
|
||||||
#define TCR_WRC(x) (((x)&0x3)<<28) /* WDT Reset Control */
|
|
||||||
#define WRC_NONE 0 /* No reset will occur */
|
|
||||||
#define WRC_CORE 1 /* Core reset will occur */
|
|
||||||
#define WRC_CHIP 2 /* Chip reset will occur */
|
|
||||||
#define WRC_SYSTEM 3 /* System reset will occur */
|
|
||||||
#define TCR_WIE 0x08000000 /* WDT Interrupt Enable */
|
|
||||||
#define TCR_PIE 0x04000000 /* PIT Interrupt Enable */
|
|
||||||
#define TCR_FP(x) (((x)&0x3)<<24) /* FIT Period */
|
|
||||||
#define FP_2_9 0 /* 2^9 clocks */
|
|
||||||
#define FP_2_13 1 /* 2^13 clocks */
|
|
||||||
#define FP_2_17 2 /* 2^17 clocks */
|
|
||||||
#define FP_2_21 3 /* 2^21 clocks */
|
|
||||||
#define TCR_FIE 0x00800000 /* FIT Interrupt Enable */
|
|
||||||
#define TCR_ARE 0x00400000 /* Auto Reload Enable */
|
|
||||||
#define SPRN_THRM1 0x3FC /* Thermal Management Register 1 */
|
|
||||||
#define THRM1_TIN (1<<0)
|
|
||||||
#define THRM1_TIV (1<<1)
|
|
||||||
#define THRM1_THRES (0x7f<<2)
|
|
||||||
#define THRM1_TID (1<<29)
|
|
||||||
#define THRM1_TIE (1<<30)
|
|
||||||
#define THRM1_V (1<<31)
|
|
||||||
#define SPRN_THRM2 0x3FD /* Thermal Management Register 2 */
|
|
||||||
#define SPRN_THRM3 0x3FE /* Thermal Management Register 3 */
|
|
||||||
#define THRM3_E (1<<31)
|
|
||||||
#define SPRN_TSR 0x3D8 /* Timer Status Register */
|
|
||||||
#define TSR_ENW 0x80000000 /* Enable Next Watchdog */
|
|
||||||
#define TSR_WIS 0x40000000 /* WDT Interrupt Status */
|
|
||||||
#define TSR_WRS(x) (((x)&0x3)<<28) /* WDT Reset Status */
|
|
||||||
#define WRS_NONE 0 /* No WDT reset occurred */
|
|
||||||
#define WRS_CORE 1 /* WDT forced core reset */
|
|
||||||
#define WRS_CHIP 2 /* WDT forced chip reset */
|
|
||||||
#define WRS_SYSTEM 3 /* WDT forced system reset */
|
|
||||||
#define TSR_PIS 0x08000000 /* PIT Interrupt Status */
|
|
||||||
#define TSR_FIS 0x04000000 /* FIT Interrupt Status */
|
|
||||||
#define SPRN_USIA 0x3AB /* User Sampled Instruction Address Register */
|
#define SPRN_USIA 0x3AB /* User Sampled Instruction Address Register */
|
||||||
#define SPRN_XER 0x001 /* Fixed Point Exception Register */
|
#define SPRN_XER 0x001 /* Fixed Point Exception Register */
|
||||||
#define SPRN_ZPR 0x3B0 /* Zone Protection Register */
|
|
||||||
#define SPRN_VRSAVE 0x100 /* Vector save */
|
#define SPRN_VRSAVE 0x100 /* Vector save */
|
||||||
|
#define SPRN_CTRLF 0x088
|
||||||
|
#define SPRN_CTRLT 0x098
|
||||||
|
#define CTRL_RUNLATCH 0x1
|
||||||
|
|
||||||
/* Performance monitor SPRs */
|
/* Performance monitor SPRs */
|
||||||
#define SPRN_SIAR 780
|
#define SPRN_SIAR 780
|
||||||
|
@ -352,28 +211,19 @@
|
||||||
#define CTR SPRN_CTR /* Counter Register */
|
#define CTR SPRN_CTR /* Counter Register */
|
||||||
#define DAR SPRN_DAR /* Data Address Register */
|
#define DAR SPRN_DAR /* Data Address Register */
|
||||||
#define DABR SPRN_DABR /* Data Address Breakpoint Register */
|
#define DABR SPRN_DABR /* Data Address Breakpoint Register */
|
||||||
#define DCMP SPRN_DCMP /* Data TLB Compare Register */
|
|
||||||
#define DEC SPRN_DEC /* Decrement Register */
|
#define DEC SPRN_DEC /* Decrement Register */
|
||||||
#define DMISS SPRN_DMISS /* Data TLB Miss Register */
|
|
||||||
#define DSISR SPRN_DSISR /* Data Storage Interrupt Status Register */
|
#define DSISR SPRN_DSISR /* Data Storage Interrupt Status Register */
|
||||||
#define EAR SPRN_EAR /* External Address Register */
|
|
||||||
#define HASH1 SPRN_HASH1 /* Primary Hash Address Register */
|
|
||||||
#define HASH2 SPRN_HASH2 /* Secondary Hash Address Register */
|
|
||||||
#define HID0 SPRN_HID0 /* Hardware Implementation Register 0 */
|
#define HID0 SPRN_HID0 /* Hardware Implementation Register 0 */
|
||||||
#define MSRDORM SPRN_MSRDORM /* MSR Dormant Register */
|
#define MSRDORM SPRN_MSRDORM /* MSR Dormant Register */
|
||||||
#define NIADORM SPRN_NIADORM /* NIA Dormant Register */
|
#define NIADORM SPRN_NIADORM /* NIA Dormant Register */
|
||||||
#define TSC SPRN_TSC /* Thread switch control */
|
#define TSC SPRN_TSC /* Thread switch control */
|
||||||
#define TST SPRN_TST /* Thread switch timeout */
|
#define TST SPRN_TST /* Thread switch timeout */
|
||||||
#define IABR SPRN_IABR /* Instruction Address Breakpoint Register */
|
#define IABR SPRN_IABR /* Instruction Address Breakpoint Register */
|
||||||
#define ICMP SPRN_ICMP /* Instruction TLB Compare Register */
|
|
||||||
#define IMISS SPRN_IMISS /* Instruction TLB Miss Register */
|
|
||||||
#define IMMR SPRN_IMMR /* PPC 860/821 Internal Memory Map Register */
|
|
||||||
#define L2CR SPRN_L2CR /* PPC 750 L2 control register */
|
#define L2CR SPRN_L2CR /* PPC 750 L2 control register */
|
||||||
#define __LR SPRN_LR
|
#define __LR SPRN_LR
|
||||||
#define PVR SPRN_PVR /* Processor Version */
|
#define PVR SPRN_PVR /* Processor Version */
|
||||||
#define PIR SPRN_PIR /* Processor ID */
|
#define PIR SPRN_PIR /* Processor ID */
|
||||||
#define PURR SPRN_PURR /* Processor Utilization of Resource Register */
|
#define PURR SPRN_PURR /* Processor Utilization of Resource Register */
|
||||||
//#define RPA SPRN_RPA /* Required Physical Address Register */
|
|
||||||
#define SDR1 SPRN_SDR1 /* MMU hash base register */
|
#define SDR1 SPRN_SDR1 /* MMU hash base register */
|
||||||
#define SPR0 SPRN_SPRG0 /* Supervisor Private Registers */
|
#define SPR0 SPRN_SPRG0 /* Supervisor Private Registers */
|
||||||
#define SPR1 SPRN_SPRG1
|
#define SPR1 SPRN_SPRG1
|
||||||
|
@ -389,10 +239,6 @@
|
||||||
#define TBRU SPRN_TBRU /* Time Base Read Upper Register */
|
#define TBRU SPRN_TBRU /* Time Base Read Upper Register */
|
||||||
#define TBWL SPRN_TBWL /* Time Base Write Lower Register */
|
#define TBWL SPRN_TBWL /* Time Base Write Lower Register */
|
||||||
#define TBWU SPRN_TBWU /* Time Base Write Upper Register */
|
#define TBWU SPRN_TBWU /* Time Base Write Upper Register */
|
||||||
#define ICTC 1019
|
|
||||||
#define THRM1 SPRN_THRM1 /* Thermal Management Register 1 */
|
|
||||||
#define THRM2 SPRN_THRM2 /* Thermal Management Register 2 */
|
|
||||||
#define THRM3 SPRN_THRM3 /* Thermal Management Register 3 */
|
|
||||||
#define XER SPRN_XER
|
#define XER SPRN_XER
|
||||||
|
|
||||||
/* Processor Version Register (PVR) field extraction */
|
/* Processor Version Register (PVR) field extraction */
|
||||||
|
@ -436,12 +282,6 @@
|
||||||
#define XGLUE(a,b) a##b
|
#define XGLUE(a,b) a##b
|
||||||
#define GLUE(a,b) XGLUE(a,b)
|
#define GLUE(a,b) XGLUE(a,b)
|
||||||
|
|
||||||
/* iSeries CTRL register (for runlatch) */
|
|
||||||
|
|
||||||
#define CTRLT 0x098
|
|
||||||
#define CTRLF 0x088
|
|
||||||
#define RUNLATCH 0x0001
|
|
||||||
|
|
||||||
#ifdef __ASSEMBLY__
|
#ifdef __ASSEMBLY__
|
||||||
|
|
||||||
#define _GLOBAL(name) \
|
#define _GLOBAL(name) \
|
||||||
|
@ -656,6 +496,24 @@ static inline void prefetchw(const void *x)
|
||||||
|
|
||||||
#define HAVE_ARCH_PICK_MMAP_LAYOUT
|
#define HAVE_ARCH_PICK_MMAP_LAYOUT
|
||||||
|
|
||||||
|
static inline void ppc64_runlatch_on(void)
|
||||||
|
{
|
||||||
|
unsigned long ctrl;
|
||||||
|
|
||||||
|
ctrl = mfspr(SPRN_CTRLF);
|
||||||
|
ctrl |= CTRL_RUNLATCH;
|
||||||
|
mtspr(SPRN_CTRLT, ctrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ppc64_runlatch_off(void)
|
||||||
|
{
|
||||||
|
unsigned long ctrl;
|
||||||
|
|
||||||
|
ctrl = mfspr(SPRN_CTRLF);
|
||||||
|
ctrl &= ~CTRL_RUNLATCH;
|
||||||
|
mtspr(SPRN_CTRLT, ctrl);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* __KERNEL__ */
|
#endif /* __KERNEL__ */
|
||||||
|
|
||||||
#endif /* __ASSEMBLY__ */
|
#endif /* __ASSEMBLY__ */
|
||||||
|
|
|
@ -148,8 +148,6 @@ struct device_node {
|
||||||
struct device_node *next; /* next device of same type */
|
struct device_node *next; /* next device of same type */
|
||||||
struct device_node *allnext; /* next in list of all nodes */
|
struct device_node *allnext; /* next in list of all nodes */
|
||||||
struct proc_dir_entry *pde; /* this node's proc directory */
|
struct proc_dir_entry *pde; /* this node's proc directory */
|
||||||
struct proc_dir_entry *name_link; /* name symlink */
|
|
||||||
struct proc_dir_entry *addr_link; /* addr symlink */
|
|
||||||
struct kref kref;
|
struct kref kref;
|
||||||
unsigned long _flags;
|
unsigned long _flags;
|
||||||
};
|
};
|
||||||
|
@ -174,15 +172,6 @@ static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_e
|
||||||
dn->pde = de;
|
dn->pde = de;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inline set_node_name_link(struct device_node *dn, struct proc_dir_entry *de)
|
|
||||||
{
|
|
||||||
dn->name_link = de;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void inline set_node_addr_link(struct device_node *dn, struct proc_dir_entry *de)
|
|
||||||
{
|
|
||||||
dn->addr_link = de;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* OBSOLETE: Old stlye node lookup */
|
/* OBSOLETE: Old stlye node lookup */
|
||||||
extern struct device_node *find_devices(const char *name);
|
extern struct device_node *find_devices(const char *name);
|
||||||
|
|
|
@ -96,7 +96,7 @@ static inline struct thread_info *current_thread_info(void)
|
||||||
#define TIF_POLLING_NRFLAG 4 /* true if poll_idle() is polling
|
#define TIF_POLLING_NRFLAG 4 /* true if poll_idle() is polling
|
||||||
TIF_NEED_RESCHED */
|
TIF_NEED_RESCHED */
|
||||||
#define TIF_32BIT 5 /* 32 bit binary */
|
#define TIF_32BIT 5 /* 32 bit binary */
|
||||||
#define TIF_RUN_LIGHT 6 /* iSeries run light */
|
/* #define SPARE 6 */
|
||||||
#define TIF_ABI_PENDING 7 /* 32/64 bit switch needed */
|
#define TIF_ABI_PENDING 7 /* 32/64 bit switch needed */
|
||||||
#define TIF_SYSCALL_AUDIT 8 /* syscall auditing active */
|
#define TIF_SYSCALL_AUDIT 8 /* syscall auditing active */
|
||||||
#define TIF_SINGLESTEP 9 /* singlestepping active */
|
#define TIF_SINGLESTEP 9 /* singlestepping active */
|
||||||
|
@ -110,7 +110,7 @@ static inline struct thread_info *current_thread_info(void)
|
||||||
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
|
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
|
||||||
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
|
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
|
||||||
#define _TIF_32BIT (1<<TIF_32BIT)
|
#define _TIF_32BIT (1<<TIF_32BIT)
|
||||||
#define _TIF_RUN_LIGHT (1<<TIF_RUN_LIGHT)
|
/* #define _SPARE (1<<SPARE) */
|
||||||
#define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING)
|
#define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING)
|
||||||
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
|
#define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT)
|
||||||
#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
|
#define _TIF_SINGLESTEP (1<<TIF_SINGLESTEP)
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#define _S390_USER_H
|
#define _S390_USER_H
|
||||||
|
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
#include <linux/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
/* Core file format: The core file is written in such a way that gdb
|
/* Core file format: The core file is written in such a way that gdb
|
||||||
can understand it and provide useful information to the user (under
|
can understand it and provide useful information to the user (under
|
||||||
linux we use the 'trad-core' bfd). There are quite a number of
|
linux we use the 'trad-core' bfd). There are quite a number of
|
||||||
|
|
|
@ -16,4 +16,6 @@
|
||||||
#define IOPTE_CACHE 0x0000000000000010UL /* Cached (in UPA E-cache) */
|
#define IOPTE_CACHE 0x0000000000000010UL /* Cached (in UPA E-cache) */
|
||||||
#define IOPTE_WRITE 0x0000000000000002UL /* Writeable */
|
#define IOPTE_WRITE 0x0000000000000002UL /* Writeable */
|
||||||
|
|
||||||
|
#define IOMMU_NUM_CTXS 4096
|
||||||
|
|
||||||
#endif /* !(_SPARC_IOMMU_H) */
|
#endif /* !(_SPARC_IOMMU_H) */
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
#include <asm/oplib.h>
|
#include <asm/oplib.h>
|
||||||
|
#include <asm/iommu.h>
|
||||||
|
|
||||||
/* The abstraction used here is that there are PCI controllers,
|
/* The abstraction used here is that there are PCI controllers,
|
||||||
* each with one (Sabre) or two (PSYCHO/SCHIZO) PCI bus modules
|
* each with one (Sabre) or two (PSYCHO/SCHIZO) PCI bus modules
|
||||||
|
@ -40,9 +41,6 @@ struct pci_iommu {
|
||||||
*/
|
*/
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
|
|
||||||
/* Context allocator. */
|
|
||||||
unsigned int iommu_cur_ctx;
|
|
||||||
|
|
||||||
/* IOMMU page table, a linear array of ioptes. */
|
/* IOMMU page table, a linear array of ioptes. */
|
||||||
iopte_t *page_table; /* The page table itself. */
|
iopte_t *page_table; /* The page table itself. */
|
||||||
int page_table_sz_bits; /* log2 of ow many pages does it map? */
|
int page_table_sz_bits; /* log2 of ow many pages does it map? */
|
||||||
|
@ -87,6 +85,10 @@ struct pci_iommu {
|
||||||
u16 flush;
|
u16 flush;
|
||||||
} alloc_info[PBM_NCLUSTERS];
|
} alloc_info[PBM_NCLUSTERS];
|
||||||
|
|
||||||
|
/* CTX allocation. */
|
||||||
|
unsigned long ctx_lowest_free;
|
||||||
|
unsigned long ctx_bitmap[IOMMU_NUM_CTXS / (sizeof(unsigned long) * 8)];
|
||||||
|
|
||||||
/* Here a PCI controller driver describes the areas of
|
/* Here a PCI controller driver describes the areas of
|
||||||
* PCI memory space where DMA to/from physical memory
|
* PCI memory space where DMA to/from physical memory
|
||||||
* are addressed. Drivers interrogate the PCI layer
|
* are addressed. Drivers interrogate the PCI layer
|
||||||
|
|
|
@ -23,7 +23,7 @@ struct shaper
|
||||||
__u32 shapeclock;
|
__u32 shapeclock;
|
||||||
unsigned long recovery; /* Time we can next clock a packet out on
|
unsigned long recovery; /* Time we can next clock a packet out on
|
||||||
an empty queue */
|
an empty queue */
|
||||||
unsigned long locked;
|
struct semaphore sem;
|
||||||
struct net_device_stats stats;
|
struct net_device_stats stats;
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
int (*hard_start_xmit) (struct sk_buff *skb,
|
int (*hard_start_xmit) (struct sk_buff *skb,
|
||||||
|
@ -38,7 +38,6 @@ struct shaper
|
||||||
int (*hard_header_cache)(struct neighbour *neigh, struct hh_cache *hh);
|
int (*hard_header_cache)(struct neighbour *neigh, struct hh_cache *hh);
|
||||||
void (*header_cache_update)(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr);
|
void (*header_cache_update)(struct hh_cache *hh, struct net_device *dev, unsigned char * haddr);
|
||||||
struct net_device_stats* (*get_stats)(struct net_device *dev);
|
struct net_device_stats* (*get_stats)(struct net_device *dev);
|
||||||
wait_queue_head_t wait_queue;
|
|
||||||
struct timer_list timer;
|
struct timer_list timer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -467,12 +467,34 @@ static inline u8 ata_chk_status(struct ata_port *ap)
|
||||||
return ap->ops->check_status(ap);
|
return ap->ops->check_status(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ata_pause - Flush writes and pause 400 nanoseconds.
|
||||||
|
* @ap: Port to wait for.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* Inherited from caller.
|
||||||
|
*/
|
||||||
|
|
||||||
static inline void ata_pause(struct ata_port *ap)
|
static inline void ata_pause(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
ata_altstatus(ap);
|
ata_altstatus(ap);
|
||||||
ndelay(400);
|
ndelay(400);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ata_busy_wait - Wait for a port status register
|
||||||
|
* @ap: Port to wait for.
|
||||||
|
*
|
||||||
|
* Waits up to max*10 microseconds for the selected bits in the port's
|
||||||
|
* status register to be cleared.
|
||||||
|
* Returns final value of status register.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* Inherited from caller.
|
||||||
|
*/
|
||||||
|
|
||||||
static inline u8 ata_busy_wait(struct ata_port *ap, unsigned int bits,
|
static inline u8 ata_busy_wait(struct ata_port *ap, unsigned int bits,
|
||||||
unsigned int max)
|
unsigned int max)
|
||||||
{
|
{
|
||||||
|
@ -487,6 +509,18 @@ static inline u8 ata_busy_wait(struct ata_port *ap, unsigned int bits,
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ata_wait_idle - Wait for a port to be idle.
|
||||||
|
* @ap: Port to wait for.
|
||||||
|
*
|
||||||
|
* Waits up to 10ms for port's BUSY and DRQ signals to clear.
|
||||||
|
* Returns final value of status register.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* Inherited from caller.
|
||||||
|
*/
|
||||||
|
|
||||||
static inline u8 ata_wait_idle(struct ata_port *ap)
|
static inline u8 ata_wait_idle(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
|
u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
|
||||||
|
@ -525,6 +559,18 @@ static inline void ata_tf_init(struct ata_port *ap, struct ata_taskfile *tf, uns
|
||||||
tf->device = ATA_DEVICE_OBS | ATA_DEV1;
|
tf->device = ATA_DEVICE_OBS | ATA_DEV1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ata_irq_on - Enable interrupts on a port.
|
||||||
|
* @ap: Port on which interrupts are enabled.
|
||||||
|
*
|
||||||
|
* Enable interrupts on a legacy IDE device using MMIO or PIO,
|
||||||
|
* wait for idle, clear any pending interrupts.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
* Inherited from caller.
|
||||||
|
*/
|
||||||
|
|
||||||
static inline u8 ata_irq_on(struct ata_port *ap)
|
static inline u8 ata_irq_on(struct ata_port *ap)
|
||||||
{
|
{
|
||||||
struct ata_ioports *ioaddr = &ap->ioaddr;
|
struct ata_ioports *ioaddr = &ap->ioaddr;
|
||||||
|
@ -544,6 +590,18 @@ static inline u8 ata_irq_on(struct ata_port *ap)
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ata_irq_ack - Acknowledge a device interrupt.
|
||||||
|
* @ap: Port on which interrupts are enabled.
|
||||||
|
*
|
||||||
|
* Wait up to 10 ms for legacy IDE device to become idle (BUSY
|
||||||
|
* or BUSY+DRQ clear). Obtain dma status and port status from
|
||||||
|
* device. Clear the interrupt. Return port status.
|
||||||
|
*
|
||||||
|
* LOCKING:
|
||||||
|
*/
|
||||||
|
|
||||||
static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
|
static inline u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
|
||||||
{
|
{
|
||||||
unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY;
|
unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY;
|
||||||
|
|
|
@ -204,7 +204,7 @@ struct hh_cache
|
||||||
/* cached hardware header; allow for machine alignment needs. */
|
/* cached hardware header; allow for machine alignment needs. */
|
||||||
#define HH_DATA_MOD 16
|
#define HH_DATA_MOD 16
|
||||||
#define HH_DATA_OFF(__len) \
|
#define HH_DATA_OFF(__len) \
|
||||||
(HH_DATA_MOD - ((__len) & (HH_DATA_MOD - 1)))
|
(HH_DATA_MOD - (((__len - 1) & (HH_DATA_MOD - 1)) + 1))
|
||||||
#define HH_DATA_ALIGN(__len) \
|
#define HH_DATA_ALIGN(__len) \
|
||||||
(((__len)+(HH_DATA_MOD-1))&~(HH_DATA_MOD - 1))
|
(((__len)+(HH_DATA_MOD-1))&~(HH_DATA_MOD - 1))
|
||||||
unsigned long hh_data[HH_DATA_ALIGN(LL_MAX_HEADER) / sizeof(long)];
|
unsigned long hh_data[HH_DATA_ALIGN(LL_MAX_HEADER) / sizeof(long)];
|
||||||
|
|
|
@ -1230,6 +1230,12 @@
|
||||||
#define PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL 0x0258
|
#define PCI_DEVICE_ID_NVIDIA_QUADRO4_900XGL 0x0258
|
||||||
#define PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL 0x0259
|
#define PCI_DEVICE_ID_NVIDIA_QUADRO4_750XGL 0x0259
|
||||||
#define PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL 0x025B
|
#define PCI_DEVICE_ID_NVIDIA_QUADRO4_700XGL 0x025B
|
||||||
|
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_IDE 0x0265
|
||||||
|
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA 0x0266
|
||||||
|
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP51_SATA2 0x0267
|
||||||
|
#define PCI_DEVICE_ID_NVIDIA_NVENET_12 0x0268
|
||||||
|
#define PCI_DEVICE_ID_NVIDIA_NVENET_13 0x0269
|
||||||
|
#define PCI_DEVICE_ID_NVIDIA_MCP51_AUDIO 0x026B
|
||||||
#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800 0x0280
|
#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800 0x0280
|
||||||
#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_8X 0x0281
|
#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800_8X 0x0281
|
||||||
#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800SE 0x0282
|
#define PCI_DEVICE_ID_NVIDIA_GEFORCE4_TI_4800SE 0x0282
|
||||||
|
|
|
@ -796,6 +796,10 @@ typedef void (*usb_complete_t)(struct urb *, struct pt_regs *);
|
||||||
* of the iso_frame_desc array, and the number of errors is reported in
|
* of the iso_frame_desc array, and the number of errors is reported in
|
||||||
* error_count. Completion callbacks for ISO transfers will normally
|
* error_count. Completion callbacks for ISO transfers will normally
|
||||||
* (re)submit URBs to ensure a constant transfer rate.
|
* (re)submit URBs to ensure a constant transfer rate.
|
||||||
|
*
|
||||||
|
* Note that even fields marked "public" should not be touched by the driver
|
||||||
|
* when the urb is owned by the hcd, that is, since the call to
|
||||||
|
* usb_submit_urb() till the entry into the completion routine.
|
||||||
*/
|
*/
|
||||||
struct urb
|
struct urb
|
||||||
{
|
{
|
||||||
|
@ -803,12 +807,12 @@ struct urb
|
||||||
struct kref kref; /* reference count of the URB */
|
struct kref kref; /* reference count of the URB */
|
||||||
spinlock_t lock; /* lock for the URB */
|
spinlock_t lock; /* lock for the URB */
|
||||||
void *hcpriv; /* private data for host controller */
|
void *hcpriv; /* private data for host controller */
|
||||||
struct list_head urb_list; /* list pointer to all active urbs */
|
|
||||||
int bandwidth; /* bandwidth for INT/ISO request */
|
int bandwidth; /* bandwidth for INT/ISO request */
|
||||||
atomic_t use_count; /* concurrent submissions counter */
|
atomic_t use_count; /* concurrent submissions counter */
|
||||||
u8 reject; /* submissions will fail */
|
u8 reject; /* submissions will fail */
|
||||||
|
|
||||||
/* public, documented fields in the urb that can be used by drivers */
|
/* public, documented fields in the urb that can be used by drivers */
|
||||||
|
struct list_head urb_list; /* list head for use by the urb owner */
|
||||||
struct usb_device *dev; /* (in) pointer to associated device */
|
struct usb_device *dev; /* (in) pointer to associated device */
|
||||||
unsigned int pipe; /* (in) pipe information */
|
unsigned int pipe; /* (in) pipe information */
|
||||||
int status; /* (return) non-ISO status */
|
int status; /* (return) non-ISO status */
|
||||||
|
|
|
@ -478,7 +478,7 @@ static int __init esp4_init(void)
|
||||||
{
|
{
|
||||||
struct xfrm_decap_state decap;
|
struct xfrm_decap_state decap;
|
||||||
|
|
||||||
if (sizeof(struct esp_decap_data) <
|
if (sizeof(struct esp_decap_data) >
|
||||||
sizeof(decap.decap_data)) {
|
sizeof(decap.decap_data)) {
|
||||||
extern void decap_data_too_small(void);
|
extern void decap_data_too_small(void);
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ ip_vs_proto-objs-$(CONFIG_IP_VS_PROTO_AH) += ip_vs_proto_ah.o
|
||||||
|
|
||||||
ip_vs-objs := ip_vs_conn.o ip_vs_core.o ip_vs_ctl.o ip_vs_sched.o \
|
ip_vs-objs := ip_vs_conn.o ip_vs_core.o ip_vs_ctl.o ip_vs_sched.o \
|
||||||
ip_vs_xmit.o ip_vs_app.o ip_vs_sync.o \
|
ip_vs_xmit.o ip_vs_app.o ip_vs_sync.o \
|
||||||
ip_vs_est.o ip_vs_proto.o ip_vs_proto_icmp.o \
|
ip_vs_est.o ip_vs_proto.o \
|
||||||
$(ip_vs_proto-objs-y)
|
$(ip_vs_proto-objs-y)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -216,9 +216,6 @@ int ip_vs_protocol_init(void)
|
||||||
#ifdef CONFIG_IP_VS_PROTO_UDP
|
#ifdef CONFIG_IP_VS_PROTO_UDP
|
||||||
REGISTER_PROTOCOL(&ip_vs_protocol_udp);
|
REGISTER_PROTOCOL(&ip_vs_protocol_udp);
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_IP_VS_PROTO_ICMP
|
|
||||||
REGISTER_PROTOCOL(&ip_vs_protocol_icmp);
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_IP_VS_PROTO_AH
|
#ifdef CONFIG_IP_VS_PROTO_AH
|
||||||
REGISTER_PROTOCOL(&ip_vs_protocol_ah);
|
REGISTER_PROTOCOL(&ip_vs_protocol_ah);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,182 +0,0 @@
|
||||||
/*
|
|
||||||
* ip_vs_proto_icmp.c: ICMP load balancing support for IP Virtual Server
|
|
||||||
*
|
|
||||||
* Authors: Julian Anastasov <ja@ssi.bg>, March 2002
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU General Public License
|
|
||||||
* version 2 as published by the Free Software Foundation;
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/kernel.h>
|
|
||||||
#include <linux/icmp.h>
|
|
||||||
#include <linux/netfilter.h>
|
|
||||||
#include <linux/netfilter_ipv4.h>
|
|
||||||
|
|
||||||
#include <net/ip_vs.h>
|
|
||||||
|
|
||||||
|
|
||||||
static int icmp_timeouts[1] = { 1*60*HZ };
|
|
||||||
|
|
||||||
static char * icmp_state_name_table[1] = { "ICMP" };
|
|
||||||
|
|
||||||
static struct ip_vs_conn *
|
|
||||||
icmp_conn_in_get(const struct sk_buff *skb,
|
|
||||||
struct ip_vs_protocol *pp,
|
|
||||||
const struct iphdr *iph,
|
|
||||||
unsigned int proto_off,
|
|
||||||
int inverse)
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
struct ip_vs_conn *cp;
|
|
||||||
|
|
||||||
if (likely(!inverse)) {
|
|
||||||
cp = ip_vs_conn_in_get(iph->protocol,
|
|
||||||
iph->saddr, 0,
|
|
||||||
iph->daddr, 0);
|
|
||||||
} else {
|
|
||||||
cp = ip_vs_conn_in_get(iph->protocol,
|
|
||||||
iph->daddr, 0,
|
|
||||||
iph->saddr, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cp;
|
|
||||||
|
|
||||||
#else
|
|
||||||
return NULL;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct ip_vs_conn *
|
|
||||||
icmp_conn_out_get(const struct sk_buff *skb,
|
|
||||||
struct ip_vs_protocol *pp,
|
|
||||||
const struct iphdr *iph,
|
|
||||||
unsigned int proto_off,
|
|
||||||
int inverse)
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
struct ip_vs_conn *cp;
|
|
||||||
|
|
||||||
if (likely(!inverse)) {
|
|
||||||
cp = ip_vs_conn_out_get(iph->protocol,
|
|
||||||
iph->saddr, 0,
|
|
||||||
iph->daddr, 0);
|
|
||||||
} else {
|
|
||||||
cp = ip_vs_conn_out_get(IPPROTO_UDP,
|
|
||||||
iph->daddr, 0,
|
|
||||||
iph->saddr, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return cp;
|
|
||||||
#else
|
|
||||||
return NULL;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
icmp_conn_schedule(struct sk_buff *skb, struct ip_vs_protocol *pp,
|
|
||||||
int *verdict, struct ip_vs_conn **cpp)
|
|
||||||
{
|
|
||||||
*verdict = NF_ACCEPT;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
icmp_csum_check(struct sk_buff *skb, struct ip_vs_protocol *pp)
|
|
||||||
{
|
|
||||||
if (!(skb->nh.iph->frag_off & __constant_htons(IP_OFFSET))) {
|
|
||||||
if (skb->ip_summed != CHECKSUM_UNNECESSARY) {
|
|
||||||
if (ip_vs_checksum_complete(skb, skb->nh.iph->ihl * 4)) {
|
|
||||||
IP_VS_DBG_RL_PKT(0, pp, skb, 0, "Failed checksum for");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
icmp_debug_packet(struct ip_vs_protocol *pp,
|
|
||||||
const struct sk_buff *skb,
|
|
||||||
int offset,
|
|
||||||
const char *msg)
|
|
||||||
{
|
|
||||||
char buf[256];
|
|
||||||
struct iphdr _iph, *ih;
|
|
||||||
|
|
||||||
ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
|
|
||||||
if (ih == NULL)
|
|
||||||
sprintf(buf, "%s TRUNCATED", pp->name);
|
|
||||||
else if (ih->frag_off & __constant_htons(IP_OFFSET))
|
|
||||||
sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u frag",
|
|
||||||
pp->name, NIPQUAD(ih->saddr),
|
|
||||||
NIPQUAD(ih->daddr));
|
|
||||||
else {
|
|
||||||
struct icmphdr _icmph, *ic;
|
|
||||||
|
|
||||||
ic = skb_header_pointer(skb, offset + ih->ihl*4,
|
|
||||||
sizeof(_icmph), &_icmph);
|
|
||||||
if (ic == NULL)
|
|
||||||
sprintf(buf, "%s TRUNCATED to %u bytes\n",
|
|
||||||
pp->name, skb->len - offset);
|
|
||||||
else
|
|
||||||
sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u T:%d C:%d",
|
|
||||||
pp->name, NIPQUAD(ih->saddr),
|
|
||||||
NIPQUAD(ih->daddr),
|
|
||||||
ic->type, ic->code);
|
|
||||||
}
|
|
||||||
printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
icmp_state_transition(struct ip_vs_conn *cp, int direction,
|
|
||||||
const struct sk_buff *skb,
|
|
||||||
struct ip_vs_protocol *pp)
|
|
||||||
{
|
|
||||||
cp->timeout = pp->timeout_table[IP_VS_ICMP_S_NORMAL];
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
icmp_set_state_timeout(struct ip_vs_protocol *pp, char *sname, int to)
|
|
||||||
{
|
|
||||||
int num;
|
|
||||||
char **names;
|
|
||||||
|
|
||||||
num = IP_VS_ICMP_S_LAST;
|
|
||||||
names = icmp_state_name_table;
|
|
||||||
return ip_vs_set_state_timeout(pp->timeout_table, num, names, sname, to);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void icmp_init(struct ip_vs_protocol *pp)
|
|
||||||
{
|
|
||||||
pp->timeout_table = icmp_timeouts;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void icmp_exit(struct ip_vs_protocol *pp)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ip_vs_protocol ip_vs_protocol_icmp = {
|
|
||||||
.name = "ICMP",
|
|
||||||
.protocol = IPPROTO_ICMP,
|
|
||||||
.dont_defrag = 0,
|
|
||||||
.init = icmp_init,
|
|
||||||
.exit = icmp_exit,
|
|
||||||
.conn_schedule = icmp_conn_schedule,
|
|
||||||
.conn_in_get = icmp_conn_in_get,
|
|
||||||
.conn_out_get = icmp_conn_out_get,
|
|
||||||
.snat_handler = NULL,
|
|
||||||
.dnat_handler = NULL,
|
|
||||||
.csum_check = icmp_csum_check,
|
|
||||||
.state_transition = icmp_state_transition,
|
|
||||||
.register_app = NULL,
|
|
||||||
.unregister_app = NULL,
|
|
||||||
.app_conn_bind = NULL,
|
|
||||||
.debug_packet = icmp_debug_packet,
|
|
||||||
.timeout_change = NULL,
|
|
||||||
.set_state_timeout = icmp_set_state_timeout,
|
|
||||||
};
|
|
|
@ -3,6 +3,7 @@
|
||||||
* communicating with userspace via netlink.
|
* communicating with userspace via netlink.
|
||||||
*
|
*
|
||||||
* (C) 2000-2002 James Morris <jmorris@intercode.com.au>
|
* (C) 2000-2002 James Morris <jmorris@intercode.com.au>
|
||||||
|
* (C) 2003-2005 Netfilter Core Team <coreteam@netfilter.org>
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License version 2 as
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
@ -17,6 +18,7 @@
|
||||||
* 2005-01-10: Added /proc counter for dropped packets; fixed so
|
* 2005-01-10: Added /proc counter for dropped packets; fixed so
|
||||||
* packets aren't delivered to user space if they're going
|
* packets aren't delivered to user space if they're going
|
||||||
* to be dropped.
|
* to be dropped.
|
||||||
|
* 2005-05-26: local_bh_{disable,enable} around nf_reinject (Harald Welte)
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
@ -71,7 +73,15 @@ static DECLARE_MUTEX(ipqnl_sem);
|
||||||
static void
|
static void
|
||||||
ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict)
|
ipq_issue_verdict(struct ipq_queue_entry *entry, int verdict)
|
||||||
{
|
{
|
||||||
|
/* TCP input path (and probably other bits) assume to be called
|
||||||
|
* from softirq context, not from syscall, like ipq_issue_verdict is
|
||||||
|
* called. TCP input path deadlocks with locks taken from timer
|
||||||
|
* softirq, e.g. We therefore emulate this by local_bh_disable() */
|
||||||
|
|
||||||
|
local_bh_disable();
|
||||||
nf_reinject(entry->skb, entry->info, verdict);
|
nf_reinject(entry->skb, entry->info, verdict);
|
||||||
|
local_bh_enable();
|
||||||
|
|
||||||
kfree(entry);
|
kfree(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -738,7 +738,7 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
|
||||||
unsigned long amount;
|
unsigned long amount;
|
||||||
|
|
||||||
amount = 0;
|
amount = 0;
|
||||||
spin_lock_irq(&sk->sk_receive_queue.lock);
|
spin_lock_bh(&sk->sk_receive_queue.lock);
|
||||||
skb = skb_peek(&sk->sk_receive_queue);
|
skb = skb_peek(&sk->sk_receive_queue);
|
||||||
if (skb != NULL) {
|
if (skb != NULL) {
|
||||||
/*
|
/*
|
||||||
|
@ -748,7 +748,7 @@ int udp_ioctl(struct sock *sk, int cmd, unsigned long arg)
|
||||||
*/
|
*/
|
||||||
amount = skb->len - sizeof(struct udphdr);
|
amount = skb->len - sizeof(struct udphdr);
|
||||||
}
|
}
|
||||||
spin_unlock_irq(&sk->sk_receive_queue.lock);
|
spin_unlock_bh(&sk->sk_receive_queue.lock);
|
||||||
return put_user(amount, (int __user *)arg);
|
return put_user(amount, (int __user *)arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -848,12 +848,12 @@ csum_copy_err:
|
||||||
/* Clear queue. */
|
/* Clear queue. */
|
||||||
if (flags&MSG_PEEK) {
|
if (flags&MSG_PEEK) {
|
||||||
int clear = 0;
|
int clear = 0;
|
||||||
spin_lock_irq(&sk->sk_receive_queue.lock);
|
spin_lock_bh(&sk->sk_receive_queue.lock);
|
||||||
if (skb == skb_peek(&sk->sk_receive_queue)) {
|
if (skb == skb_peek(&sk->sk_receive_queue)) {
|
||||||
__skb_unlink(skb, &sk->sk_receive_queue);
|
__skb_unlink(skb, &sk->sk_receive_queue);
|
||||||
clear = 1;
|
clear = 1;
|
||||||
}
|
}
|
||||||
spin_unlock_irq(&sk->sk_receive_queue.lock);
|
spin_unlock_bh(&sk->sk_receive_queue.lock);
|
||||||
if (clear)
|
if (clear)
|
||||||
kfree_skb(skb);
|
kfree_skb(skb);
|
||||||
}
|
}
|
||||||
|
@ -1334,7 +1334,7 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
|
||||||
struct sk_buff_head *rcvq = &sk->sk_receive_queue;
|
struct sk_buff_head *rcvq = &sk->sk_receive_queue;
|
||||||
struct sk_buff *skb;
|
struct sk_buff *skb;
|
||||||
|
|
||||||
spin_lock_irq(&rcvq->lock);
|
spin_lock_bh(&rcvq->lock);
|
||||||
while ((skb = skb_peek(rcvq)) != NULL) {
|
while ((skb = skb_peek(rcvq)) != NULL) {
|
||||||
if (udp_checksum_complete(skb)) {
|
if (udp_checksum_complete(skb)) {
|
||||||
UDP_INC_STATS_BH(UDP_MIB_INERRORS);
|
UDP_INC_STATS_BH(UDP_MIB_INERRORS);
|
||||||
|
@ -1345,7 +1345,7 @@ unsigned int udp_poll(struct file *file, struct socket *sock, poll_table *wait)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
spin_unlock_irq(&rcvq->lock);
|
spin_unlock_bh(&rcvq->lock);
|
||||||
|
|
||||||
/* nothing to see, move along */
|
/* nothing to see, move along */
|
||||||
if (skb == NULL)
|
if (skb == NULL)
|
||||||
|
|
|
@ -37,5 +37,4 @@ EXPORT_SYMBOL(in6_dev_finish_destroy);
|
||||||
EXPORT_SYMBOL(xfrm6_rcv);
|
EXPORT_SYMBOL(xfrm6_rcv);
|
||||||
#endif
|
#endif
|
||||||
EXPORT_SYMBOL(rt6_lookup);
|
EXPORT_SYMBOL(rt6_lookup);
|
||||||
EXPORT_SYMBOL(fl6_sock_lookup);
|
|
||||||
EXPORT_SYMBOL(ipv6_push_nfrag_opts);
|
EXPORT_SYMBOL(ipv6_push_nfrag_opts);
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#include <asm/byteorder.h>
|
#include <asm/byteorder.h>
|
||||||
|
|
||||||
|
|
||||||
#if 1 /* control */
|
#if 0 /* control */
|
||||||
#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
|
#define DPRINTK(format,args...) printk(KERN_DEBUG format,##args)
|
||||||
#else
|
#else
|
||||||
#define DPRINTK(format,args...)
|
#define DPRINTK(format,args...)
|
||||||
|
@ -73,8 +73,13 @@ static int dsmark_graft(struct Qdisc *sch,unsigned long arg,
|
||||||
|
|
||||||
DPRINTK("dsmark_graft(sch %p,[qdisc %p],new %p,old %p)\n",sch,p,new,
|
DPRINTK("dsmark_graft(sch %p,[qdisc %p],new %p,old %p)\n",sch,p,new,
|
||||||
old);
|
old);
|
||||||
if (!new)
|
|
||||||
|
if (new == NULL) {
|
||||||
|
new = qdisc_create_dflt(sch->dev, &pfifo_qdisc_ops);
|
||||||
|
if (new == NULL)
|
||||||
new = &noop_qdisc;
|
new = &noop_qdisc;
|
||||||
|
}
|
||||||
|
|
||||||
sch_tree_lock(sch);
|
sch_tree_lock(sch);
|
||||||
*old = xchg(&p->q,new);
|
*old = xchg(&p->q,new);
|
||||||
if (*old)
|
if (*old)
|
||||||
|
@ -163,13 +168,14 @@ static void dsmark_walk(struct Qdisc *sch,struct qdisc_walker *walker)
|
||||||
return;
|
return;
|
||||||
for (i = 0; i < p->indices; i++) {
|
for (i = 0; i < p->indices; i++) {
|
||||||
if (p->mask[i] == 0xff && !p->value[i])
|
if (p->mask[i] == 0xff && !p->value[i])
|
||||||
continue;
|
goto ignore;
|
||||||
if (walker->count >= walker->skip) {
|
if (walker->count >= walker->skip) {
|
||||||
if (walker->fn(sch, i+1, walker) < 0) {
|
if (walker->fn(sch, i+1, walker) < 0) {
|
||||||
walker->stop = 1;
|
walker->stop = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ignore:
|
||||||
walker->count++;
|
walker->count++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue