Commit 9521288f authored by Linus Torvalds's avatar Linus Torvalds

Import 2.3.99pre9-5

parent dad12642
......@@ -12468,14 +12468,6 @@ CONFIG_APM_DISPLAY_BLANK
backlight at all, or it might print a lot of errors to the console,
especially if you are using gpm.
Ignore multiple suspend/standby events
CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
This option is necessary on the IBM Thinkpad 560, but should work on
all other laptops. When the APM BIOS returns multiple suspend or
standby events while one is already being processed they will be
ignored. Without this the Thinkpad 560 has troubles with the user
level daemon apmd, and with the PCMCIA package pcmcia-cs.
Ignore multiple suspend/resume cycles
CONFIG_APM_IGNORE_SUSPEND_BOUNCE
This option is necessary on the Dell Inspiron 3200 and others, but
......
This diff is collapsed.
......@@ -180,7 +180,6 @@ if [ "$CONFIG_APM" != "n" ]; then
bool ' Enable PM at boot time' CONFIG_APM_DO_ENABLE
bool ' Make CPU Idle calls when idle' CONFIG_APM_CPU_IDLE
bool ' Enable console blanking using APM' CONFIG_APM_DISPLAY_BLANK
bool ' Ignore multiple suspend' CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
bool ' Ignore multiple suspend/resume cycles' CONFIG_APM_IGNORE_SUSPEND_BOUNCE
bool ' RTC stores time in GMT' CONFIG_APM_RTC_IS_GMT
bool ' Allow interrupts during APM BIOS calls' CONFIG_APM_ALLOW_INTS
......
......@@ -132,6 +132,9 @@
* 1.13: Changes for new pm_ interfaces (Andy Henroid
* <andy_henroid@yahoo.com>).
* Modularize the code.
* Fix the Thinkpad (again) :-( (CONFIG_APM_IGNORE_MULTIPLE_SUSPENDS
* is now the way life works).
* Fix thinko in suspend() (wrong return).
*
* APM 1.1 Reference:
*
......@@ -308,9 +311,7 @@ static int clock_slowed = 0;
#endif
static int suspends_pending = 0;
static int standbys_pending = 0;
#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
static int waiting_for_resume = 0;
#endif
#ifdef CONFIG_APM_RTC_IS_GMT
# define clock_cmos_diff 0
......@@ -866,22 +867,22 @@ static void reinit_timer(void)
static int suspend(void)
{
int err;
int ret;
struct apm_user *as;
get_time_diff();
err = apm_set_power_state(APM_STATE_SUSPEND);
reinit_timer();
set_time();
ret = (err == APM_SUCCESS) || (err == APM_NO_ERROR);
if (!ret)
if (err == APM_NO_ERROR)
err = APM_SUCCESS;
if (err != APM_SUCCESS)
apm_error("suspend", err);
for (as = user_list; as != NULL; as = as->next) {
as->suspend_wait = 0;
as->suspend_result = (ret ? 0 : -EIO);
as->suspend_result = ((err == APM_SUCCESS) ? 0 : -EIO);
}
wake_up_interruptible(&apm_suspend_waitqueue);
return ret;
return err;
}
static void standby(void)
......@@ -962,14 +963,7 @@ static void check_events(void)
switch (event) {
case APM_SYS_STANDBY:
case APM_USER_STANDBY:
#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
if (waiting_for_resume)
break;
#endif
if (send_event(event, NULL)) {
#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
waiting_for_resume = 1;
#endif
if (standbys_pending <= 0)
standby();
}
......@@ -986,14 +980,18 @@ static void check_events(void)
if (ignore_bounce)
break;
#endif
#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
/*
* If we are already processing a SUSPEND,
* then further SUSPEND events from the BIOS
* will be ignored. We also return here to
* cope with the fact that the Thinkpads keep
* sending a SUSPEND event until something else
* happens!
*/
if (waiting_for_resume)
break;
#endif
return;
if (send_event(event, NULL)) {
#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
waiting_for_resume = 1;
#endif
if (suspends_pending <= 0)
(void) suspend();
}
......@@ -1002,9 +1000,7 @@ static void check_events(void)
case APM_NORMAL_RESUME:
case APM_CRITICAL_RESUME:
case APM_STANDBY_RESUME:
#ifdef CONFIG_APM_IGNORE_MULTIPLE_SUSPEND
waiting_for_resume = 0;
#endif
#ifdef CONFIG_APM_IGNORE_SUSPEND_BOUNCE
last_resume = jiffies;
ignore_bounce = 1;
......@@ -1036,8 +1032,10 @@ static void apm_event_handler(void)
int err;
if ((standbys_pending > 0) || (suspends_pending > 0)) {
if ((apm_bios_info.version > 0x100) && (pending_count-- < 0)) {
if ((apm_bios_info.version > 0x100) && (pending_count-- <= 0)) {
pending_count = 4;
if (debug)
printk(KERN_DEBUG "apm: setting state busy\n");
err = apm_set_power_state(APM_STATE_BUSY);
if (err)
apm_error("busy", err);
......@@ -1097,7 +1095,7 @@ static void apm_mainloop(void)
static int check_apm_user(struct apm_user *as, const char *func)
{
if ((as == NULL) || (as->magic != APM_BIOS_MAGIC)) {
printk(KERN_ERR "apm: %s passed bad filp", func);
printk(KERN_ERR "apm: %s passed bad filp\n", func);
return 1;
}
return 0;
......@@ -1200,7 +1198,7 @@ static int do_ioctl(struct inode * inode, struct file *filp,
} else if (!send_event(APM_USER_SUSPEND, as))
return -EAGAIN;
if (suspends_pending <= 0) {
if (!suspend())
if (suspend() != APM_SUCCESS)
return -EIO;
} else {
as->suspend_wait = 1;
......@@ -1251,7 +1249,7 @@ static int do_release(struct inode * inode, struct file * filp)
as1 = as1->next)
;
if (as1 == NULL)
printk(KERN_ERR "apm: filp not in user list");
printk(KERN_ERR "apm: filp not in user list\n");
else
as1->next = as->next;
}
......@@ -1268,7 +1266,7 @@ static int do_open(struct inode * inode, struct file * filp)
as = (struct apm_user *)kmalloc(sizeof(*as), GFP_KERNEL);
if (as == NULL) {
printk(KERN_ERR "apm: cannot allocate struct of size %d bytes",
printk(KERN_ERR "apm: cannot allocate struct of size %d bytes\n",
sizeof(*as));
MOD_DEC_USE_COUNT;
return -ENOMEM;
......
......@@ -12,7 +12,6 @@ extern int mkiss_init_ctrl_dev(void);
extern int slip_init_ctrl_dev(void);
extern int strip_init_ctrl_dev(void);
extern int x25_asy_init_ctrl_dev(void);
extern int slhc_install(void);
extern int dmascc_init(void);
extern int yam_init(void);
......@@ -78,22 +77,12 @@ struct net_probe pci_probes[] __initdata = {
#endif
#if defined(CONFIG_COMX)
{comx_init, 0},
#endif /*
* SLHC if present needs attaching so other people see it
* even if not opened.
*/
#endif
#if defined(CONFIG_LANMEDIA)
{lmc_setup, 0},
#endif
#ifdef CONFIG_INET
#if (defined(CONFIG_SLIP) && defined(CONFIG_SLIP_COMPRESSED)) \
|| defined(CONFIG_PPP) \
|| (defined(CONFIG_ISDN) && defined(CONFIG_ISDN_PPP))
{slhc_install, 0},
#endif
#endif
/*
*
* Wireless non-HAM
......
......@@ -77,7 +77,6 @@
#include <linux/timer.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/init.h>
#include <net/checksum.h>
#include <net/slhc_vj.h>
#include <asm/unaligned.h>
......@@ -751,12 +750,6 @@ void cleanup_module(void)
return;
}
#else /* MODULE */
int __init slhc_install(void)
{
return 0;
}
#endif /* MODULE */
#else /* CONFIG_INET */
......
2000-05-16 Tim Waugh <twaugh@redhat.com>
* share.c (parport_claim): Fix SMP race.
2000-05-15 Gunther Mayer <gunther.mayer@braunschweig.okersurf.de>
* parport_pc.c (parport_pc_compat_write_block_pio): Check for
......
......@@ -16,7 +16,7 @@
#include <linux/usb.h>
static const char *version = __FILE__ ": v0.3.9 2000/04/11 Written by Petko Manolov (petkan@spct.net)\n";
static const char *version = __FILE__ ": v0.3.12 2000/05/22 (C) 1999-2000 Petko Manolov (petkan@spct.net)\n";
#define PEGASUS_MTU 1500
......@@ -24,12 +24,15 @@ static const char *version = __FILE__ ": v0.3.9 2000/04/11 Written by Petko Mano
#define SROM_WRITE 0x01
#define SROM_READ 0x02
#define PEGASUS_TX_TIMEOUT (HZ*5)
#define PEGASUS_RESET 1
#define ALIGN(x) x __attribute__((aligned(L1_CACHE_BYTES)))
struct pegasus {
struct usb_device *usb;
struct net_device *net;
struct net_device_stats stats;
int flags;
spinlock_t pegasus_lock;
struct urb rx_urb, tx_urb, intr_urb;
unsigned char ALIGN(rx_buff[PEGASUS_MAX_MTU]);
......@@ -44,9 +47,11 @@ struct usb_eth_dev {
void *private;
};
static int loopback = 0;
static int multicast_filter_limit = 32;
MODULE_AUTHOR("Petko Manolov <petkan@spct.net>");
MODULE_DESCRIPTION("ADMtek AN986 Pegasus USB Ethernet driver");
MODULE_PARM(loopback, "i");
......@@ -98,6 +103,7 @@ static int pegasus_read_phy_word(struct usb_device *dev, __u8 index, __u16 *regd
return 1;
}
static int pegasus_write_phy_word(struct usb_device *dev, __u8 index, __u16 regdata)
{
int i;
......@@ -115,6 +121,7 @@ static int pegasus_write_phy_word(struct usb_device *dev, __u8 index, __u16 regd
return 1;
}
static int pegasus_rw_srom_word(struct usb_device *dev, __u8 index, __u16 *retdata, __u8 direction)
{
int i;
......@@ -134,6 +141,7 @@ static int pegasus_rw_srom_word(struct usb_device *dev, __u8 index, __u16 *retda
return 1;
}
static int pegasus_get_node_id(struct usb_device *dev, __u8 *id)
{
int i;
......@@ -143,6 +151,7 @@ static int pegasus_get_node_id(struct usb_device *dev, __u8 *id)
return 0;
}
static int pegasus_reset_mac(struct usb_device *dev)
{
__u8 data = 0x8;
......@@ -165,6 +174,7 @@ static int pegasus_reset_mac(struct usb_device *dev)
return 1;
}
static int pegasus_start_net(struct net_device *dev, struct usb_device *usb)
{
__u16 partmedia, temp;
......@@ -195,13 +205,14 @@ static int pegasus_start_net(struct net_device *dev, struct usb_device *usb)
data[0] = 0xc9;
data[1] = (partmedia & 0x100) ? 0x30 : ((partmedia & 0x80) ? 0x10 : 0);
data[2] = (loopback & 1) ? 0x08 : 0x00;
data[2] = (loopback & 1) ? 0x09 : 0x01;
pegasus_set_registers(usb, 0, 3, data);
return 0;
}
static void pegasus_read_bulk(struct urb *urb)
{
struct pegasus *pegasus = urb->context;
......@@ -253,15 +264,16 @@ static void pegasus_read_bulk(struct urb *urb)
warn("(prb)failed rx_urb %d", res);
}
static void pegasus_irq(urb_t *urb)
{
if(urb->status) {
__u8 *d = urb->transfer_buffer;
printk("txst0 %x, txst1 %x, rxst %x, rxlst0 %x, rxlst1 %x, wakest %x",
d[0], d[1], d[2], d[3], d[4], d[5]);
}
__u8 *d = urb->transfer_buffer;
if ( d[0] )
dbg("txst0=0x%2x", d[0]);
}
static void pegasus_write_bulk(struct urb *urb)
{
struct pegasus *pegasus = urb->context;
......@@ -280,12 +292,15 @@ static void pegasus_tx_timeout(struct net_device *net)
struct pegasus *pegasus = net->priv;
warn("%s: Tx timed out. Reseting...", net->name);
usb_unlink_urb(&pegasus->tx_urb);
pegasus->stats.tx_errors++;
net->trans_start = jiffies;
pegasus->flags |= PEGASUS_RESET;
netif_wake_queue(net);
}
static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net)
{
struct pegasus *pegasus = net->priv;
......@@ -317,11 +332,13 @@ static int pegasus_start_xmit(struct sk_buff *skb, struct net_device *net)
return 0;
}
static struct net_device_stats *pegasus_netdev_stats(struct net_device *dev)
{
return &((struct pegasus *)dev->priv)->stats;
}
static int pegasus_open(struct net_device *net)
{
struct pegasus *pegasus = (struct pegasus *)net->priv;
......@@ -334,8 +351,10 @@ static int pegasus_open(struct net_device *net)
if ((res = usb_submit_urb(&pegasus->rx_urb)))
warn("(open)failed rx_urb %d", res);
/* usb_submit_urb(&pegasus->intr_urb);*/
if ((res = usb_submit_urb(&pegasus->intr_urb)))
warn("(open)failed intr_urb %d", res);
netif_start_queue(net);
MOD_INC_USE_COUNT;
......@@ -343,6 +362,7 @@ static int pegasus_open(struct net_device *net)
return 0;
}
static int pegasus_close(struct net_device *net)
{
struct pegasus *pegasus = net->priv;
......@@ -351,13 +371,14 @@ static int pegasus_close(struct net_device *net)
usb_unlink_urb(&pegasus->rx_urb);
usb_unlink_urb(&pegasus->tx_urb);
/* usb_unlink_urb(&pegasus->intr_urb); */
usb_unlink_urb(&pegasus->intr_urb);
MOD_DEC_USE_COUNT;
return 0;
}
static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
{
__u16 *data = (__u16 *)&rq->ifr_data;
......@@ -379,6 +400,7 @@ static int pegasus_ioctl(struct net_device *net, struct ifreq *rq, int cmd)
}
}
static void pegasus_set_rx_mode(struct net_device *net)
{
struct pegasus *pegasus = net->priv;
......@@ -400,6 +422,7 @@ static void pegasus_set_rx_mode(struct net_device *net)
netif_wake_queue(net);
}
static int check_device_ids( __u16 vendor, __u16 product )
{
int i=0;
......@@ -413,6 +436,7 @@ static int check_device_ids( __u16 vendor, __u16 product )
return -1;
}
static void * pegasus_probe(struct usb_device *dev, unsigned int ifnum)
{
struct net_device *net;
......@@ -463,7 +487,7 @@ static void * pegasus_probe(struct usb_device *dev, unsigned int ifnum)
pegasus->tx_buff, PEGASUS_MAX_MTU, pegasus_write_bulk,
pegasus);
FILL_INT_URB(&pegasus->intr_urb, dev, usb_rcvintpipe(dev, 3),
pegasus->intr_buff, 8, pegasus_irq, pegasus, 250);
pegasus->intr_buff, 8, pegasus_irq, pegasus, 500);
printk(KERN_INFO "%s: %s\n", net->name, usb_dev_id[dev_indx].name);
......@@ -471,6 +495,7 @@ static void * pegasus_probe(struct usb_device *dev, unsigned int ifnum)
return pegasus;
}
static void pegasus_disconnect(struct usb_device *dev, void *ptr)
{
struct pegasus *pegasus = ptr;
......@@ -487,11 +512,12 @@ static void pegasus_disconnect(struct usb_device *dev, void *ptr)
usb_unlink_urb(&pegasus->rx_urb);
usb_unlink_urb(&pegasus->tx_urb);
/* usb_unlink_urb(&pegasus->intr_urb);*/
usb_unlink_urb(&pegasus->intr_urb);
kfree(pegasus);
}
static struct usb_driver pegasus_driver = {
name: "pegasus",
probe: pegasus_probe,
......
......@@ -4,8 +4,26 @@
O_TARGET := usb-serial.o
M_OBJS := usb-serial.o
O_OBJS := usbserial.o visor.o whiteheat.o ftdi_sio.o keyspan_pda.o omninet.o digi_acceleport.o
O_OBJS := usbserial.o
MOD_LIST_NAME := USB_SERIAL_MODULES
ifeq ($(CONFIG_USB_SERIAL_VISOR),y)
O_OBJS += visor.o
endif
ifeq ($(CONFIG_USB_SERIAL_WHITEHEAT),y)
O_OBJS += whiteheat.o
endif
ifeq ($(CONFIG_USB_SERIAL_FTDI_SIO),y)
O_OBJS += ftdi_sio.o
endif
ifeq ($(CONFIG_USB_SERIAL_KEYSPAN_PDA),y)
O_OBJS += keyspan_pda.o
endif
ifeq ($(CONFIG_USB_SERIAL_OMNINET),y)
O_OBJS += omninet.o
endif
ifeq ($(CONFIG_USB_SERIAL_DIGI_ACCELEPORT),y)
O_OBJS += digi_acceleport.o
endif
include $(TOPDIR)/Rules.make
......@@ -47,9 +47,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_USB_SERIAL_DIGI_ACCELEPORT
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/signal.h>
......@@ -1276,4 +1273,3 @@ dbg( "digi_read_oob: opcode=%d, line=%d, status=%d, ret=%d", oob_opcode, oob_lin
}
#endif /* CONFIG_USB_SERIAL_DIGI_ACCELEPORT */
......@@ -32,9 +32,6 @@
#include <linux/config.h>
#ifdef CONFIG_USB_SERIAL_FTDI_SIO
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/signal.h>
......@@ -723,6 +720,3 @@ static int ftdi_sio_ioctl (struct usb_serial_port *port, struct file * file, uns
return 0;
} /* ftdi_sio_ioctl */
#endif /* CONFIG_USB_SERIAL_FTDI_SIO */
......@@ -18,9 +18,6 @@
#include <linux/config.h>
#ifdef CONFIG_USB_SERIAL_KEYSPAN_PDA
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/signal.h>
......@@ -700,4 +697,3 @@ struct usb_serial_device_type keyspan_pda_device = {
shutdown: keyspan_pda_shutdown,
};
#endif /* CONFIG_USB_SERIAL_KEYSPAN_PDA */
......@@ -13,9 +13,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_USB_SERIAL_OMNINET
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/signal.h>
......@@ -336,6 +333,3 @@ static void omninet_write_bulk_callback (struct urb *urb)
return;
}
#endif /* CONFIG_USB_SERIAL_OMNINET */
......@@ -14,6 +14,10 @@
*
* See Documentation/usb/usb-serial.txt for more information on using this driver
*
* (05/22/2000) gkh
* Changed the makefile, enabling the big CONFIG_USB_SERIAL_SOMTHING to be
* removed from the individual device source files.
*
* (05/03/2000) gkh
* Added the Digi Acceleport driver from Al Borchers and Peter Berger.
*
......
......@@ -20,9 +20,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_USB_SERIAL_VISOR
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/signal.h>
......@@ -207,7 +204,3 @@ static int visor_startup (struct usb_serial *serial)
return (0);
}
#endif /* CONFIG_USB_SERIAL_VISOR*/
......@@ -21,9 +21,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_USB_SERIAL_WHITEHEAT
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/signal.h>
......@@ -407,6 +404,3 @@ static void whiteheat_shutdown (struct usb_serial *serial)
return;
}
#endif /* CONFIG_USB_SERIAL_WHITEHEAT */
......@@ -92,7 +92,6 @@ static void urb_rm_priv (urb_t * urb)
kfree (urb->hcpriv);
urb->hcpriv = NULL;
wake_up (&op_wakeup);
}
/*-------------------------------------------------------------------------*/
......@@ -493,6 +492,8 @@ static int sohci_submit_urb (urb_t * urb)
urb->start_frame = ((ed->state == ED_OPER)? (ed->last_iso + 1):
(le16_to_cpu (ohci->hcca.frame_no) + 10)) & 0xffff;
}
urb->status = USB_ST_URB_PENDING;
urb->actual_length = 0;
if (ed->state != ED_OPER) /* link the ed into a chain if is not already */
ep_link (ohci, ed);
......@@ -527,6 +528,8 @@ static int sohci_unlink_urb (urb_t * urb)
urb_print (urb, "UNLINK", 1);
#endif
usb_dec_dev_use (urb->dev);
if (usb_pipedevice (urb->pipe) == ohci->rh.devnum)
return rh_unlink_urb (urb); /* a request to the virtual root hub */
......@@ -544,19 +547,23 @@ static int sohci_unlink_urb (urb_t * urb)
ep_rm_ed (urb->dev, urb_priv->ed);
urb_priv->ed->state |= ED_URB_DEL;
spin_unlock_irqrestore (&usb_ed_lock, flags);
add_wait_queue (&op_wakeup, &wait);
current->state = TASK_UNINTERRUPTIBLE;
if (!schedule_timeout (HZ / 10)) /* wait until all TDs are deleted */
err("unlink URB timeout!");
remove_wait_queue (&op_wakeup, &wait);
} else
if (!(urb->transfer_flags & USB_ASYNC_UNLINK)) {
add_wait_queue (&op_wakeup, &wait);
current->state = TASK_UNINTERRUPTIBLE;
if (!schedule_timeout (HZ / 10)) /* wait until all TDs are deleted */
err("unlink URB timeout!");
remove_wait_queue (&op_wakeup, &wait);
urb->status = -ENOENT;
} else
urb->status = -EINPROGRESS;
} else {
urb_rm_priv (urb);
urb->status = -ENOENT; // mark urb as killed
if (urb->complete)
urb->complete ((struct urb *) urb);
usb_dec_dev_use (urb->dev);
if (urb->complete && (urb->transfer_flags & USB_ASYNC_UNLINK)) {
urb->complete (urb);
urb->status = 0;
} else
urb->status = -ENOENT;
}
}
return 0;
}
......@@ -965,7 +972,7 @@ static void ep_rm_ed (struct usb_device * usb_dev, ed_t * ed)
/* prepare a TD */
static void td_fill (unsigned int info, void * data, int len, urb_t * urb, int type, int index)
static void td_fill (unsigned int info, void * data, int len, urb_t * urb, int index)
{
volatile td_t * td, * td_pt;
urb_priv_t * urb_priv = urb->hcpriv;
......@@ -982,7 +989,6 @@ static void td_fill (unsigned int info, void * data, int len, urb_t * urb, int t
td->index = index;
td->urb = urb;
td->hwINFO = cpu_to_le32 (info);
td->type = type;
if ((td->ed->type & 3) == PIPE_ISOCHRONOUS) {
td->hwCBP = cpu_to_le32 (((!data || !len)?
0 : virt_to_bus (data)) & 0xFFFFF000);
......@@ -1029,12 +1035,12 @@ static void td_submit_urb (urb_t * urb)
info = usb_pipeout (urb->pipe)?
TD_CC | TD_DP_OUT : TD_CC | TD_DP_IN ;
while(data_len > 4096) {
td_fill (info | (cnt? TD_T_TOGGLE:toggle), data, 4096, urb, (cnt? 0: ST_ADDR) | ADD_LEN, cnt);
td_fill (info | (cnt? TD_T_TOGGLE:toggle), data, 4096, urb, cnt);
data += 4096; data_len -= 4096; cnt++;
}
info = usb_pipeout (urb->pipe)?
TD_CC | TD_DP_OUT : TD_CC | TD_R | TD_DP_IN ;
td_fill (info | (cnt? TD_T_TOGGLE:toggle), data, data_len, urb, (cnt? 0: ST_ADDR) | ADD_LEN, cnt);
td_fill (info | (cnt? TD_T_TOGGLE:toggle), data, data_len, urb, cnt);
cnt++;
writel (OHCI_BLF, &ohci->regs->cmdstatus); /* start bulk list */
break;
......@@ -1042,20 +1048,20 @@ static void td_submit_urb (urb_t * urb)
case PIPE_INTERRUPT:
info = usb_pipeout (urb->pipe)?
TD_CC | TD_DP_OUT | toggle: TD_CC | TD_R | TD_DP_IN | toggle;
td_fill (info, data, data_len, urb, ST_ADDR | ADD_LEN, cnt++);
td_fill (info, data, data_len, urb, cnt++);
break;
case PIPE_CONTROL:
info = TD_CC | TD_DP_SETUP | TD_T_DATA0;
td_fill (info, ctrl, 8, urb, ST_ADDR, cnt++);
td_fill (info, ctrl, 8, urb, cnt++);
if (data_len > 0) {
info = usb_pipeout (urb->pipe)?
TD_CC | TD_R | TD_DP_OUT | TD_T_DATA1 : TD_CC | TD_R | TD_DP_IN | TD_T_DATA1;
td_fill (info, data, data_len, urb, ADD_LEN, cnt++);
td_fill (info, data, data_len, urb, cnt++);
}
info = usb_pipeout (urb->pipe)?
TD_CC | TD_DP_IN | TD_T_DATA1: TD_CC | TD_DP_OUT | TD_T_DATA1;
td_fill (info, NULL, 0, urb, 0, cnt++);
td_fill (info, NULL, 0, urb, cnt++);
writel (OHCI_CLF, &ohci->regs->cmdstatus); /* start Control list */
break;
......@@ -1063,7 +1069,7 @@ static void td_submit_urb (urb_t * urb)
for (cnt = 0; cnt < urb->number_of_packets; cnt++) {
td_fill (TD_CC|TD_ISO | ((urb->start_frame + cnt) & 0xffff),
(__u8 *) data + urb->iso_frame_desc[cnt].offset,
urb->iso_frame_desc[cnt].length, urb, (cnt? 0: ST_ADDR) | ADD_LEN, cnt);
urb->iso_frame_desc[cnt].length, urb, cnt);
}
break;
}
......@@ -1074,7 +1080,55 @@ static void td_submit_urb (urb_t * urb)
/*-------------------------------------------------------------------------*
* Done List handling functions
*-------------------------------------------------------------------------*/
/* calculate the transfer length and update the urb */
static void dl_transfer_length(td_t * td)
{
__u32 tdINFO, tdBE, tdCBP;
__u16 tdPSW;
urb_t * urb = td->urb;
urb_priv_t * urb_priv = urb->hcpriv;
int dlen = 0;
int cc = 0;
tdINFO = le32_to_cpup (&td->hwINFO);
tdBE = le32_to_cpup (&td->hwBE);
tdCBP = le32_to_cpup (&td->hwCBP);
if (tdINFO & TD_ISO) {
tdPSW = le16_to_cpu (td->hwPSW[0]);
cc = (tdPSW >> 12) & 0xF;
if (cc < 0xE) {
if (usb_pipeout(urb->pipe)) {
dlen = urb->iso_frame_desc[td->index].length;
} else {
dlen = tdPSW & 0x3ff;
}
urb->actual_length += dlen;
urb->iso_frame_desc[td->index].actual_length = dlen;
if (!(urb->transfer_flags & USB_DISABLE_SPD) && (cc == TD_DATAUNDERRUN))
cc = TD_CC_NOERROR;
urb->iso_frame_desc[td->index].status = cc_to_error[cc];
}
} else { /* BULK, INT, CONTROL DATA */
if (!(usb_pipetype (urb->pipe) == PIPE_CONTROL &&
((td->index == 0) || (td->index == urb_priv->length - 1)))) {
if (tdBE != 0) {
if (td->hwCBP == 0)
urb->actual_length = bus_to_virt (tdBE) - urb->transfer_buffer + 1;
else
urb->actual_length = bus_to_virt (tdCBP) - urb->transfer_buffer;
}
}
}
}
/*-------------------------------------------------------------------------*/
/* replies to the request have to be on a FIFO basis so
* we reverse the reversed done-list */
......@@ -1128,6 +1182,7 @@ static void dl_del_list (ohci_t * ohci, unsigned int frame)
unsigned long flags;
ed_t * ed;
__u32 edINFO;
__u32 tdINFO;
td_t * td = NULL, * td_next = NULL, * tdHeadP = NULL, * tdTailP;
__u32 * td_p;
int ctrl = 0, bulk = 0;
......@@ -1139,16 +1194,25 @@ static void dl_del_list (ohci_t * ohci, unsigned int frame)
tdHeadP = bus_to_virt (le32_to_cpup (&ed->hwHeadP) & 0xfffffff0);
edINFO = le32_to_cpup (&ed->hwINFO);
td_p = &ed->hwHeadP;
for (td = tdHeadP; td != tdTailP; td = td_next) {
urb_t * urb = td->urb;
urb_priv_t * urb_priv = td->urb->hcpriv;
td_next = bus_to_virt (le32_to_cpup (&td->hwNextTD) & 0xfffffff0);
if ((urb_priv->state == URB_DEL) || (ed->state & ED_DEL)) {
tdINFO = le32_to_cpup (&td->hwINFO);
if (TD_CC_GET (tdINFO) < 0xE) dl_transfer_length (td);
*td_p = td->hwNextTD | (*td_p & cpu_to_le32 (0x3));
if(++ (urb_priv->td_cnt) == urb_priv->length)
urb_rm_priv (urb);
if (urb->transfer_flags & USB_ASYNC_UNLINK) {
usb_dec_dev_use (urb->dev);
urb->status = -ECONNRESET;
urb->complete (urb);
} else {
wake_up (&op_wakeup);
}
} else {
td_p = &td->hwNextTD;
}
......@@ -1165,7 +1229,7 @@ static void dl_del_list (ohci_t * ohci, unsigned int frame)
}
else {
ed->state &= ~ED_URB_DEL;
ed->hwINFO &= ~cpu_to_le32 (OHCI_ED_SKIP);
ed->hwINFO &= ~cpu_to_le32 (OHCI_ED_SKIP);
}
if ((ed->type & 3) == CTRL) ctrl |= 1;
......@@ -1183,6 +1247,8 @@ static void dl_del_list (ohci_t * ohci, unsigned int frame)
spin_unlock_irqrestore (&usb_ed_lock, flags);
}
/*-------------------------------------------------------------------------*/
/* td done list */
......@@ -1191,12 +1257,11 @@ static void dl_done_list (ohci_t * ohci, td_t * td_list)
{
td_t * td_list_next = NULL;
ed_t * ed;
int dlen = 0;
int cc = 0;
urb_t * urb;
urb_priv_t * urb_priv;
__u32 tdINFO, tdBE, tdCBP, edHeadP, edTailP;
__u16 tdPSW;
__u32 tdINFO, edHeadP, edTailP;
unsigned long flags;
while (td_list) {
......@@ -1205,40 +1270,11 @@ static void dl_done_list (ohci_t * ohci, td_t * td_list)
urb = td_list->urb;
urb_priv = urb->hcpriv;
tdINFO = le32_to_cpup (&td_list->hwINFO);
tdBE = le32_to_cpup (&td_list->hwBE);
tdCBP = le32_to_cpup (&td_list->hwCBP);
ed = td_list->ed;
if (td_list->type & ST_ADDR)
urb->actual_length = 0;
if (td_list->type & ADD_LEN) { /* accumulate length of multi td transfers */
if (tdINFO & TD_ISO) {
tdPSW = le16_to_cpu (td_list->hwPSW[0]);
cc = (tdPSW >> 12) & 0xF;
if (cc < 0xE) {
if (usb_pipeout(urb->pipe)) {
dlen = urb->iso_frame_desc[td_list->index].length;
} else {
dlen = tdPSW & 0x3ff;
}
urb->actual_length += dlen;
urb->iso_frame_desc[td_list->index].actual_length = dlen;
if (!(urb->transfer_flags & USB_DISABLE_SPD) && (cc == TD_DATAUNDERRUN))
cc = TD_CC_NOERROR;
urb->iso_frame_desc[td_list->index].status = cc_to_error[cc];
}
} else {
if (tdBE != 0) {
if (td_list->hwCBP == 0)
urb->actual_length = bus_to_virt (tdBE) - urb->transfer_buffer + 1;
else
urb->actual_length = bus_to_virt (tdCBP) - urb->transfer_buffer;
}
}
}
dl_transfer_length(td_list);
/* error code of transfer */
cc = TD_CC_GET (tdINFO);
if( cc == TD_CC_STALL) usb_endpoint_halt(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
......
......@@ -432,7 +432,7 @@ static int ep_unlink(ohci_t * ohci, ed_t * ed);
static ed_t * ep_add_ed(struct usb_device * usb_dev, unsigned int pipe, int interval, int load);
static void ep_rm_ed(struct usb_device * usb_dev, ed_t * ed);
/* td */
static void td_fill(unsigned int info, void * data, int len, urb_t * urb, int type, int index);
static void td_fill(unsigned int info, void * data, int len, urb_t * urb, int index);
static void td_submit_urb(urb_t * urb);
/* root hub */
static int rh_submit_urb(urb_t * urb);
......
......@@ -84,15 +84,17 @@ static struct inode *get_cramfs_inode(struct super_block *sb, struct cramfs_inod
#define NEXT_BUFFER(_ix) ((_ix) ^ 1)
/*
* BLKS_PER_BUF_SHIFT must be at least 1 to allow for "compressed"
* data that takes up more space than the original. 1 is guaranteed
* to suffice, though. Larger values provide more read-ahead and
* proportionally less wastage at the end of the buffer.
* BLKS_PER_BUF_SHIFT should be at least 2 to allow for "compressed"
* data that takes up more space than the original and with unlucky
* alignment.
*/
#define BLKS_PER_BUF_SHIFT (2)
#define BLKS_PER_BUF (1 << BLKS_PER_BUF_SHIFT)
static unsigned char read_buffers[READ_BUFFERS][BLKS_PER_BUF][PAGE_CACHE_SIZE];
#define BLKS_PER_BUF_SHIFT (2)
#define BLKS_PER_BUF (1 << BLKS_PER_BUF_SHIFT)
#define BUFFER_SIZE (BLKS_PER_BUF*PAGE_CACHE_SIZE)
static unsigned char read_buffers[READ_BUFFERS][BUFFER_SIZE];
static unsigned buffer_blocknr[READ_BUFFERS];
static struct super_block * buffer_dev[READ_BUFFERS];
static int next_buffer = 0;
/*
......@@ -102,19 +104,27 @@ static int next_buffer = 0;
static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned int len)
{
struct buffer_head * bh_array[BLKS_PER_BUF];
unsigned i, blocknr, last_blocknr, buffer;
unsigned i, blocknr, buffer;
char *data;
if (!len)
return NULL;
blocknr = offset >> PAGE_CACHE_SHIFT;
last_blocknr = (offset + len - 1) >> PAGE_CACHE_SHIFT;
if (last_blocknr - blocknr >= BLKS_PER_BUF)
goto eek; resume:
offset &= PAGE_CACHE_SIZE - 1;
/* Check if an existing buffer already has the data.. */
for (i = 0; i < READ_BUFFERS; i++) {
if ((blocknr >= buffer_blocknr[i]) &&
(last_blocknr - buffer_blocknr[i] < BLKS_PER_BUF))
return &read_buffers[i][blocknr - buffer_blocknr[i]][offset];
unsigned int blk_offset;
if (buffer_dev[i] != sb)
continue;
if (blocknr < buffer_blocknr[i])
continue;
blk_offset = (blocknr - buffer_blocknr[i]) << PAGE_CACHE_SHIFT;
blk_offset += offset;
if (blk_offset + len > BUFFER_SIZE)
continue;
return read_buffers[i] + blk_offset;
}
/* Ok, read in BLKS_PER_BUF pages completely first. */
......@@ -125,24 +135,18 @@ static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned i
buffer = next_buffer;
next_buffer = NEXT_BUFFER(buffer);
buffer_blocknr[buffer] = blocknr;
buffer_dev[buffer] = sb;
data = read_buffers[buffer];
for (i = 0; i < BLKS_PER_BUF; i++) {
struct buffer_head * bh = bh_array[i];
if (bh) {
memcpy(read_buffers[buffer][i], bh->b_data, PAGE_CACHE_SIZE);
memcpy(data, bh->b_data, PAGE_CACHE_SIZE);
bforget(bh);
} else
memset(read_buffers[buffer][i], 0, PAGE_CACHE_SIZE);
memset(data, 0, PAGE_CACHE_SIZE);
data += PAGE_CACHE_SIZE;
}
return read_buffers[buffer][0] + offset;
eek:
printk(KERN_ERR
"cramfs (device %s): requested chunk (%u:+%u) bigger than buffer\n",
bdevname(sb->s_dev), offset, len);
/* TODO: return EIO to process or kill the current process
instead of resuming. */
*((int *)0) = 0; /* XXX: doesn't work on all archs */
goto resume;
return read_buffers[buffer] + offset;
}
......
#ifndef __NET_SLHC_H
#define __NET_SLHC_H
extern void slhc_install(void);
#endif
......@@ -118,6 +118,7 @@ EXPORT_SYMBOL(kfree);
EXPORT_SYMBOL(kfree_s);
EXPORT_SYMBOL(vmalloc);
EXPORT_SYMBOL(vfree);
EXPORT_SYMBOL(__vmalloc);
EXPORT_SYMBOL(mem_map);
EXPORT_SYMBOL(remap_page_range);
EXPORT_SYMBOL(max_mapnr);
......
......@@ -79,7 +79,6 @@
#include <linux/brlock.h>
#include <net/sock.h>
#include <linux/rtnetlink.h>
#include <net/slhc.h>
#include <linux/proc_fs.h>
#include <linux/stat.h>
#include <linux/if_bridge.h>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment