Commit 8a51beef authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/davem/net-2.6

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents 88d0505c c8682fb0
......@@ -254,7 +254,7 @@ firmware_data_write(struct kobject *kobj,
return retval;
}
static struct bin_attribute firmware_attr_data_tmpl = {
.attr = {.name = "data", .mode = 0644},
.attr = {.name = "data", .mode = 0644, .owner = THIS_MODULE},
.size = 0,
.read = firmware_data_read,
.write = firmware_data_write,
......
......@@ -121,7 +121,7 @@ init_ti_parallel(int minor)
/* ----- global defines ----------------------------------------------- */
#define START(x) { x=jiffies+HZ/(timeout/10); }
#define START(x) { x = jiffies + (HZ * timeout) / 10; }
#define WAIT(x) { \
if (time_before((x), jiffies)) return -1; \
if (need_resched()) schedule(); }
......
......@@ -155,6 +155,7 @@ static struct bin_attribute eeprom_attr = {
.attr = {
.name = "eeprom",
.mode = S_IRUGO,
.owner = THIS_MODULE,
},
.size = EEPROM_SIZE,
.read = eeprom_read,
......
......@@ -402,6 +402,7 @@ static struct bin_attribute sysfs_fw_dump_attr = {
.attr = {
.name = "fw_dump",
.mode = S_IRUSR | S_IWUSR,
.owner = THIS_MODULE,
},
.size = 0,
.read = qla2x00_sysfs_read_fw_dump,
......@@ -415,6 +416,7 @@ static struct bin_attribute sysfs_nvram_attr = {
.attr = {
.name = "nvram",
.mode = S_IRUSR | S_IWUSR,
.owner = THIS_MODULE,
},
.size = sizeof(nvram_t),
.read = qla2x00_sysfs_read_nvram,
......
......@@ -573,9 +573,11 @@ static int acm_probe (struct usb_interface *intf,
struct usb_device *dev;
struct acm *acm;
struct usb_host_config *cfacm;
struct usb_interface *data;
struct usb_host_interface *ifcom, *ifdata;
struct usb_endpoint_descriptor *epctrl, *epread, *epwrite;
struct usb_interface *data = NULL;
struct usb_host_interface *ifcom, *ifdata = NULL;
struct usb_endpoint_descriptor *epctrl = NULL;
struct usb_endpoint_descriptor *epread = NULL;
struct usb_endpoint_descriptor *epwrite = NULL;
int readsize, ctrlsize, minor, j;
unsigned char *buf;
......@@ -583,44 +585,50 @@ static int acm_probe (struct usb_interface *intf,
cfacm = dev->actconfig;
for (j = 0; j < cfacm->desc.bNumInterfaces - 1; j++) {
if (usb_interface_claimed(cfacm->interface[j]) ||
usb_interface_claimed(cfacm->interface[j + 1]))
continue;
/* We know we're probe()d with the control interface. */
ifcom = intf->cur_altsetting;
/* We know we're probe()d with the control interface.
* FIXME ACM doesn't guarantee the data interface is
/* ACM doesn't guarantee the data interface is
* adjacent to the control interface, or that if one
* is there it's not for call management ... so use
* the cdc union descriptor whenever there is one.
* is there it's not for call management ... so find
* it
*/
ifcom = intf->cur_altsetting;
if (intf == cfacm->interface[j]) {
ifdata = cfacm->interface[j + 1]->cur_altsetting;
data = cfacm->interface[j + 1];
} else if (intf == cfacm->interface[j + 1]) {
for (j = 0; j < cfacm->desc.bNumInterfaces; j++) {
ifdata = cfacm->interface[j]->cur_altsetting;
data = cfacm->interface[j];
} else
continue;
if (ifdata->desc.bInterfaceClass != 10 || ifdata->desc.bNumEndpoints < 2)
continue;
if (ifdata->desc.bInterfaceClass == 10 &&
ifdata->desc.bNumEndpoints == 2) {
epctrl = &ifcom->endpoint[0].desc;
epread = &ifdata->endpoint[0].desc;
epwrite = &ifdata->endpoint[1].desc;
if ((epctrl->bEndpointAddress & 0x80) != 0x80 || (epctrl->bmAttributes & 3) != 3 ||
(epread->bmAttributes & 3) != 2 || (epwrite->bmAttributes & 3) != 2 ||
if ((epctrl->bEndpointAddress & 0x80) != 0x80 ||
(epctrl->bmAttributes & 3) != 3 ||
(epread->bmAttributes & 3) != 2 ||
(epwrite->bmAttributes & 3) != 2 ||
((epread->bEndpointAddress & 0x80) ^ (epwrite->bEndpointAddress & 0x80)) != 0x80)
continue;
goto next_interface;
if ((epread->bEndpointAddress & 0x80) != 0x80) {
epread = &ifdata->endpoint[1].desc;
epwrite = &ifdata->endpoint[0].desc;
}
dbg("found data interface at %d\n", j);
break;
} else {
next_interface:
ifdata = NULL;
data = NULL;
}
}
/* there's been a problem */
if (!ifdata) {
dbg("interface not found (%p)\n", ifdata);
return -ENODEV;
}
for (minor = 0; minor < ACM_TTY_MINORS && acm_table[minor]; minor++);
if (acm_table[minor]) {
......@@ -696,16 +704,21 @@ static int acm_probe (struct usb_interface *intf,
acm->line.databits = 8;
acm_set_line(acm, &acm->line);
usb_driver_claim_interface(&acm_driver, data, acm);
if ( (j = usb_driver_claim_interface(&acm_driver, data, acm)) != 0) {
err("claim failed");
usb_free_urb(acm->ctrlurb);
usb_free_urb(acm->readurb);
usb_free_urb(acm->writeurb);
kfree(acm);
kfree(buf);
return j;
}
tty_register_device(acm_tty_driver, minor, &intf->dev);
acm_table[minor] = acm;
usb_set_intfdata (intf, acm);
return 0;
}
return -EIO;
}
static void acm_disconnect(struct usb_interface *intf)
......
......@@ -284,6 +284,11 @@ int usb_hcd_pci_suspend (struct pci_dev *dev, u32 state)
dev_dbg (hcd->self.controller, "suspend D%d --> D%d\n",
dev->current_state, state);
if (pci_find_capability(dev, PCI_CAP_ID_PM)) {
dev_dbg(hcd->self.controller, "No PM capability\n");
return 0;
}
switch (hcd->state) {
case USB_STATE_HALT:
dev_dbg (hcd->self.controller, "halted; hcd not suspended\n");
......
......@@ -120,6 +120,7 @@ struct eth_dev {
unsigned long todo;
#define WORK_RX_MEMORY 0
int rndis_config;
u8 host_mac [ETH_ALEN];
};
/* This version autoconfigures as much as possible at run-time.
......@@ -159,9 +160,8 @@ static const char *EP_STATUS_NAME;
/* For hardware that can talk RNDIS and either of the above protocols,
* use this ID ... the windows INF files will know it. Unless it's
* used with CDC Ethernet, Linux hosts will need updates to choose the
* non-MSFT configuration, either in the kernel (2.4) or else from a
* hotplug script (2.6).
* used with CDC Ethernet, Linux 2.4 hosts will need updates to choose
* the non-RNDIS configuration.
*/
#define RNDIS_VENDOR_NUM 0x0525 /* NetChip */
#define RNDIS_PRODUCT_NUM 0xa4a2 /* Ethernet/RNDIS Gadget */
......@@ -1334,8 +1334,10 @@ static void rndis_command_complete (struct usb_ep *ep, struct usb_request *req)
struct eth_dev *dev = ep->driver_data;
/* received RNDIS command from CDC_SEND_ENCAPSULATED_COMMAND */
spin_lock(&dev->lock);
if (rndis_msg_parser (dev->rndis_config, (u8 *) req->buf))
ERROR(dev, "%s: rndis parse error\n", __FUNCTION__ );
spin_unlock(&dev->lock);
}
#endif /* RNDIS */
......@@ -1486,14 +1488,14 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
|| !dev->config
|| ctrl->wIndex > 1)
break;
if (!dev->cdc && ctrl->wIndex != 0)
if (!(dev->cdc || dev->rndis) && ctrl->wIndex != 0)
break;
/* if carrier is on, data interface is active. */
*(u8 *)req->buf =
((ctrl->wIndex == 1) && netif_carrier_ok (dev->net))
? 1
: 0,
/* for CDC, iff carrier is on, data interface is active. */
if (dev->rndis || ctrl->wIndex != 1)
*(u8 *)req->buf = 0;
else
*(u8 *)req->buf = netif_carrier_ok (dev->net) ? 1 : 0;
value = min (ctrl->wLength, (u16) 1);
break;
......@@ -1552,6 +1554,7 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
memcpy (req->buf, buf, value);
req->complete = rndis_response_complete;
}
/* else stalls ... spec says to avoid that */
}
break;
#endif /* RNDIS */
......@@ -1590,6 +1593,8 @@ eth_disconnect (struct usb_gadget *gadget)
eth_reset_config (dev);
spin_unlock_irqrestore (&dev->lock, flags);
/* FIXME RNDIS should enter RNDIS_UNINITIALIZED */
/* next we may get setup() calls to enumerate new connections;
* or an unbind() during shutdown (including removing module).
*/
......@@ -2376,19 +2381,19 @@ eth_bind (struct usb_gadget *gadget)
*/
random_ether_addr(net->dev_addr);
#ifdef DEV_CONFIG_CDC
/* ... another address for the host, on the other end of the
* link, gets exported through CDC (see CDC spec table 41)
* and RNDIS.
*/
if (cdc) {
u8 node_id [ETH_ALEN];
random_ether_addr(node_id);
if (cdc || rndis) {
random_ether_addr(dev->host_mac);
#ifdef DEV_CONFIG_CDC
snprintf (ethaddr, sizeof ethaddr, "%02X%02X%02X%02X%02X%02X",
node_id [0], node_id [1], node_id [2],
node_id [3], node_id [4], node_id [5]);
}
dev->host_mac [0], dev->host_mac [1],
dev->host_mac [2], dev->host_mac [3],
dev->host_mac [4], dev->host_mac [5]);
#endif
}
if (rndis) {
status = rndis_init();
......@@ -2448,10 +2453,11 @@ eth_bind (struct usb_gadget *gadget)
net->dev_addr [2], net->dev_addr [3],
net->dev_addr [4], net->dev_addr [5]);
#ifdef DEV_CONFIG_CDC
if (cdc)
INFO (dev, "CDC host enet %s\n", ethaddr);
#endif
if (cdc || rndis)
INFO (dev, "HOST MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
dev->host_mac [0], dev->host_mac [1],
dev->host_mac [2], dev->host_mac [3],
dev->host_mac [4], dev->host_mac [5]);
#ifdef CONFIG_USB_ETH_RNDIS
if (rndis) {
......@@ -2468,6 +2474,7 @@ eth_bind (struct usb_gadget *gadget)
}
/* these set up a lot of the OIDs that RNDIS needs */
rndis_set_host_mac (dev->rndis_config, dev->host_mac);
if (rndis_set_param_dev (dev->rndis_config, dev->net,
&dev->stats))
goto fail0;
......
......@@ -37,6 +37,16 @@
#include "rndis.h"
/* The driver for your USB chip needs to support ep0 OUT to work with
* RNDIS, plus the same three descriptors as CDC Ethernet.
*
* Windows hosts need an INF file like Documentation/usb/linux.inf
*/
#ifndef __LITTLE_ENDIAN
#warning this code is missing all cpu_to_leXX() calls ...
#endif
#if 0
#define DEBUG if (rndis_debug) printk
static int rndis_debug = 0;
......@@ -89,8 +99,12 @@ static u32 devFlags2currentFilter (struct net_device *dev)
static void currentFilter2devFlags (u32 currentFilter, struct net_device *dev)
{
/* FIXME the filter is supposed to control what gets
* forwarded from gadget to host; but dev->flags controls
* reporting from host to gadget ...
*/
#if 0
if (!dev) return;
if (currentFilter & NDIS_PACKET_TYPE_MULTICAST)
dev->flags |= IFF_MULTICAST;
if (currentFilter & NDIS_PACKET_TYPE_BROADCAST)
......@@ -99,8 +113,13 @@ static void currentFilter2devFlags (u32 currentFilter, struct net_device *dev)
dev->flags |= IFF_ALLMULTI;
if (currentFilter & NDIS_PACKET_TYPE_PROMISCUOUS)
dev->flags |= IFF_PROMISC;
#endif
}
/* FIXME OMITTED OIDs, that RNDIS-on-USB "must" support, include
* - power management (OID_PNP_CAPABILITIES, ...)
* - network wakeup (OID_PNP_ENABLE_WAKE_UP, ...)
*/
/* NDIS Functions */
static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
......@@ -114,8 +133,6 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
if (!resp) return -ENOMEM;
if (!resp) return -ENOMEM;
switch (OID) {
/* mandatory */
case OID_GEN_SUPPORTED_LIST:
......@@ -178,7 +195,8 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_GEN_LINK_SPEED:
DEBUG("%s: OID_GEN_LINK_SPEED\n", __FUNCTION__);
length = 4;
if (rndis_per_dev_params [configNr].media_state)
if (rndis_per_dev_params [configNr].media_state
== NDIS_MEDIA_STATE_DISCONNECTED)
*((u32 *) resp + 6) = 0;
else
*((u32 *) resp + 6) = rndis_per_dev_params [configNr].speed;
......@@ -611,15 +629,10 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_802_3_PERMANENT_ADDRESS:
DEBUG("%s: OID_802_3_PERMANENT_ADDRESS\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].dev) {
length = 6;
length = ETH_ALEN;
memcpy ((u8 *) resp + 24,
rndis_per_dev_params [configNr].dev->dev_addr,
rndis_per_dev_params [configNr].host_mac,
length);
/*
* we need a MAC address and hope that
* (our MAC + 1) is not in use
*/
*((u8 *) resp + 29) += 1;
retval = 0;
} else {
*((u32 *) resp + 6) = 0;
......@@ -631,15 +644,10 @@ static int gen_ndis_query_resp (int configNr, u32 OID, rndis_resp_t *r)
case OID_802_3_CURRENT_ADDRESS:
DEBUG("%s: OID_802_3_CURRENT_ADDRESS\n", __FUNCTION__);
if (rndis_per_dev_params [configNr].dev) {
length = 6;
length = ETH_ALEN;
memcpy ((u8 *) resp + 24,
rndis_per_dev_params [configNr].dev->dev_addr,
rndis_per_dev_params [configNr].host_mac,
length);
/*
* we need a MAC address and hope that
* (our MAC + 1) is not in use
*/
*((u8 *) resp + 29) += 1;
retval = 0;
}
break;
......@@ -746,22 +754,38 @@ static int gen_ndis_set_resp (u8 configNr, u32 OID, u8 *buf, u32 buf_len,
rndis_set_cmplt_type *resp;
int i, retval = -ENOTSUPP;
struct rndis_config_parameter *param;
struct rndis_params *params;
u8 *cp;
if (!r) return -ENOMEM;
if (!r)
return -ENOMEM;
resp = (rndis_set_cmplt_type *) r->buf;
if (!resp)
return -ENOMEM;
if (!resp) return -ENOMEM;
cp = (u8 *)resp;
switch (OID) {
case OID_GEN_CURRENT_PACKET_FILTER:
DEBUG("%s: OID_GEN_CURRENT_PACKET_FILTER\n", __FUNCTION__);
currentFilter2devFlags ((u32) ((u8 *) resp + 28),
rndis_per_dev_params [configNr].dev);
params = &rndis_per_dev_params [configNr];
currentFilter2devFlags(cp[28], params->dev);
retval = 0;
if ((u32) ((u8 *) resp + 28))
rndis_per_dev_params [configNr].state = RNDIS_INITIALIZED;
else
rndis_per_dev_params [configNr].state = RNDIS_UNINITIALIZED;
/* this call has a significant side effect: it's
* what makes the packet flow start and stop, like
* activating the CDC Ethernet altsetting.
*/
if (cp[28]) {
params->state = RNDIS_DATA_INITIALIZED;
netif_carrier_on(params->dev);
if (netif_running(params->dev))
netif_wake_queue (params->dev);
} else {
params->state = RNDIS_INITIALIZED;
netif_carrier_off (params->dev);
netif_stop_queue (params->dev);
}
break;
case OID_802_3_MULTICAST_LIST:
......@@ -938,9 +962,8 @@ static int rndis_keepalive_response (int configNr,
rndis_keepalive_cmplt_type *resp;
rndis_resp_t *r;
/* respond only in RNDIS_INITIALIZED state */
if (rndis_per_dev_params [configNr].state != RNDIS_INITIALIZED)
return 0;
/* host "should" check only in RNDIS_DATA_INITIALIZED state */
r = rndis_add_response (configNr, sizeof (rndis_keepalive_cmplt_type));
resp = (rndis_keepalive_cmplt_type *) r->buf;
if (!resp) return -ENOMEM;
......@@ -1004,35 +1027,48 @@ int rndis_signal_disconnect (int configNr)
RNDIS_STATUS_MEDIA_DISCONNECT);
}
void rndis_set_host_mac (int configNr, const u8 *addr)
{
rndis_per_dev_params [configNr].host_mac = addr;
}
/*
* Message Parser
*/
int rndis_msg_parser (u8 configNr, u8 *buf)
{
u32 MsgType, MsgLength, *tmp;
struct rndis_params *params;
if (!buf) return -ENOMEM;
if (!buf)
return -ENOMEM;
tmp = (u32 *) buf;
MsgType = *tmp;
MsgLength = *(tmp + 1);
if (configNr >= RNDIS_MAX_CONFIGS) return -ENOTSUPP;
if (configNr >= RNDIS_MAX_CONFIGS)
return -ENOTSUPP;
params = &rndis_per_dev_params [configNr];
/* For USB: responses may take up to 10 seconds */
switch (MsgType)
{
case REMOTE_NDIS_INIZIALIZE_MSG:
DEBUG(KERN_INFO "%s: REMOTE_NDIS_INIZIALIZE_MSG\n",
case REMOTE_NDIS_INITIALIZE_MSG:
DEBUG(KERN_INFO "%s: REMOTE_NDIS_INITIALIZE_MSG\n",
__FUNCTION__ );
rndis_per_dev_params [configNr].state = RNDIS_INITIALIZED;
params->state = RNDIS_INITIALIZED;
return rndis_init_response (configNr,
(rndis_init_msg_type *) buf);
break;
case REMOTE_NDIS_HALT_MSG:
DEBUG(KERN_INFO "%s: REMOTE_NDIS_HALT_MSG\n",
__FUNCTION__ );
rndis_per_dev_params [configNr].state = RNDIS_UNINITIALIZED;
params->state = RNDIS_UNINITIALIZED;
if (params->dev) {
netif_carrier_off (params->dev);
netif_stop_queue (params->dev);
}
return 0;
case REMOTE_NDIS_QUERY_MSG:
......@@ -1040,29 +1076,26 @@ int rndis_msg_parser (u8 configNr, u8 *buf)
__FUNCTION__ );
return rndis_query_response (configNr,
(rndis_query_msg_type *) buf);
break;
case REMOTE_NDIS_SET_MSG:
DEBUG(KERN_INFO "%s: REMOTE_NDIS_SET_MSG\n",
__FUNCTION__ );
return rndis_set_response (configNr,
(rndis_set_msg_type *) buf);
break;
case REMOTE_NDIS_RESET_MSG:
DEBUG(KERN_INFO "%s: REMOTE_NDIS_RESET_MSG\n",
__FUNCTION__ );
return rndis_reset_response (configNr,
(rndis_reset_msg_type *) buf);
break;
case REMOTE_NDIS_KEEPALIVE_MSG:
/* For USB: host does this every 5 seconds */
DEBUG(KERN_INFO "%s: REMOTE_NDIS_KEEPALIVE_MSG\n",
__FUNCTION__ );
return rndis_keepalive_response (configNr,
(rndis_keepalive_msg_type *)
buf);
break;
default:
printk (KERN_ERR "%s: unknown RNDIS Message Type 0x%08X\n",
......@@ -1240,9 +1273,15 @@ int rndis_proc_read (char *page, char **start, off_t off, int count, int *eof,
"vendor ID : 0x%08X\n"
"vendor : %s\n",
param->confignr, (param->used) ? "y" : "n",
(param->state)
? "RNDIS_INITIALIZED"
: "RNDIS_UNINITIALIZED",
({ char *s = "?";
switch (param->state) {
case RNDIS_UNINITIALIZED:
s = "RNDIS_UNINITIALIZED"; break;
case RNDIS_INITIALIZED:
s = "RNDIS_INITIALIZED"; break;
case RNDIS_DATA_INITIALIZED:
s = "RNDIS_DATA_INITIALIZED"; break;
}; s; }),
param->medium,
(param->media_state) ? 0 : param->speed*100,
(param->media_state) ? "disconnected" : "connected",
......@@ -1353,7 +1392,7 @@ int __init rndis_init (void)
return 0;
}
void __exit rndis_exit (void)
void rndis_exit (void)
{
u8 i;
char name [4];
......
......@@ -38,7 +38,7 @@
*/
/* Message Set for Connectionless (802.3) Devices */
#define REMOTE_NDIS_INIZIALIZE_MSG 0x00000002U /* Initialize device */
#define REMOTE_NDIS_INITIALIZE_MSG 0x00000002U /* Initialize device */
#define REMOTE_NDIS_HALT_MSG 0x00000003U
#define REMOTE_NDIS_QUERY_MSG 0x00000004U
#define REMOTE_NDIS_SET_MSG 0x00000005U
......@@ -280,6 +280,7 @@ typedef struct rndis_params
u32 medium;
u32 speed;
u32 media_state;
const u8 *host_mac;
struct net_device *dev;
struct net_device_stats *stats;
u32 vendorID;
......@@ -301,11 +302,13 @@ void rndis_add_hdr (struct sk_buff *skb);
int rndis_rm_hdr (u8 *buf, u32 *length);
u8 *rndis_get_next_response (int configNr, u32 *length);
void rndis_free_response (int configNr, u8 *buf);
int rndis_signal_connect (int configNr);
int rndis_signal_disconnect (int configNr);
int rndis_state (int configNr);
extern void rndis_set_host_mac (int configNr, const u8 *addr);
int __init rndis_init (void);
void __exit rndis_exit (void);
void rndis_exit (void);
#endif /* _LINUX_RNDIS_H */
......@@ -330,6 +330,7 @@ static int ehci_hc_reset (struct usb_hcd *hcd)
{
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
u32 temp;
unsigned count = 256/4;
spin_lock_init (&ehci->lock);
......@@ -345,16 +346,21 @@ static int ehci_hc_reset (struct usb_hcd *hcd)
temp = HCC_EXT_CAPS (readl (&ehci->caps->hcc_params));
else
temp = 0;
while (temp) {
while (temp && count--) {
u32 cap;
pci_read_config_dword (to_pci_dev(ehci->hcd.self.controller), temp, &cap);
pci_read_config_dword (to_pci_dev(ehci->hcd.self.controller),
temp, &cap);
ehci_dbg (ehci, "capability %04x at %02x\n", cap, temp);
switch (cap & 0xff) {
case 1: /* BIOS/SMM/... handoff */
if (bios_handoff (ehci, temp, cap) != 0)
return -EOPNOTSUPP;
break;
case 0x0a: /* appendix C */
ehci_dbg (ehci, "debug registers, BAR %d offset %d\n",
(cap >> 29) & 0x07, (cap >> 16) & 0x0fff);
break;
case 0: /* illegal reserved capability */
ehci_warn (ehci, "illegal capability!\n");
cap = 0;
......@@ -364,6 +370,10 @@ static int ehci_hc_reset (struct usb_hcd *hcd)
}
temp = (cap >> 8) & 0xff;
}
if (!count) {
ehci_err (ehci, "bogus capabilities ... PCI problems!\n");
return -EIO;
}
#endif
/* cache this readonly data; minimize PCI reads */
......@@ -577,6 +587,7 @@ static void ehci_stop (struct usb_hcd *hcd)
/* root hub is shut down separately (first, when possible) */
spin_lock_irq (&ehci->lock);
if (ehci->async)
ehci_work (ehci, NULL);
spin_unlock_irq (&ehci->lock);
ehci_mem_cleanup (ehci);
......
......@@ -252,14 +252,18 @@ static int ehci_hub_control (
/* force reset to complete */
writel (temp & ~PORT_RESET,
&ehci->regs->port_status [wIndex]);
do {
temp = readl (
&ehci->regs->port_status [wIndex]);
udelay (10);
} while (temp & PORT_RESET);
retval = handshake (
&ehci->regs->port_status [wIndex],
PORT_RESET, 0, 500);
if (retval != 0) {
ehci_err (ehci, "port %d reset error %d\n",
wIndex + 1, retval);
goto error;
}
/* see what we found out */
temp = check_reset_complete (ehci, wIndex, temp);
temp = check_reset_complete (ehci, wIndex,
readl (&ehci->regs->port_status [wIndex]));
}
// don't show wPortStatus if it's owned by a companion hc
......
......@@ -382,6 +382,7 @@ static void uhci_insert_qh(struct uhci_hcd *uhci, struct uhci_qh *skelqh, struct
static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
{
struct uhci_qh *pqh;
__u32 newlink;
if (!qh)
return;
......@@ -390,8 +391,24 @@ static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
* Only go through the hoops if it's actually linked in
*/
if (!list_empty(&qh->list)) {
pqh = list_entry(qh->list.prev, struct uhci_qh, list);
/* If our queue is nonempty, make the next URB the head */
if (!list_empty(&qh->urbp->queue_list)) {
struct urb_priv *nurbp;
nurbp = list_entry(qh->urbp->queue_list.next,
struct urb_priv, queue_list);
nurbp->queued = 0;
list_add(&nurbp->qh->list, &qh->list);
newlink = cpu_to_le32(nurbp->qh->dma_handle) | UHCI_PTR_QH;
} else
newlink = qh->link;
/* Fix up the previous QH's queue to link to either
* the new head of this queue or the start of the
* next endpoint's queue. */
pqh = list_entry(qh->list.prev, struct uhci_qh, list);
pqh->link = newlink;
if (pqh->urbp) {
struct list_head *head, *tmp;
......@@ -403,28 +420,19 @@ static void uhci_remove_qh(struct uhci_hcd *uhci, struct uhci_qh *qh)
tmp = tmp->next;
turbp->qh->link = qh->link;
turbp->qh->link = newlink;
}
}
pqh->link = qh->link;
mb();
/* Leave qh->link in case the HC is on the QH now, it will */
/* continue the rest of the schedule */
qh->element = UHCI_PTR_TERM;
/* If our queue is nonempty, make the next URB the head */
if (!list_empty(&qh->urbp->queue_list)) {
struct urb_priv *nurbp;
nurbp = list_entry(qh->urbp->queue_list.next,
struct urb_priv, queue_list);
nurbp->queued = 0;
list_add_tail(&nurbp->qh->list, &qh->list);
}
list_del_init(&qh->list);
}
list_del_init(&qh->urbp->queue_list);
qh->urbp = NULL;
/* Check to see if the remove list is empty. Set the IOC bit */
......@@ -579,7 +587,7 @@ static void uhci_delete_queued_urb(struct uhci_hcd *uhci, struct urb *urb)
pltd->link = UHCI_PTR_TERM;
}
list_del_init(&urbp->queue_list);
/* urbp->queue_list is handled in uhci_remove_qh() */
}
static struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
......
......@@ -3,7 +3,7 @@
* tiglusb -- Texas Instruments' USB GraphLink (aka SilverLink) driver.
* Target: Texas Instruments graphing calculators (http://lpg.ticalc.org).
*
* Copyright (C) 2001-2002:
* Copyright (C) 2001-2004:
* Romain Lievin <roms@lpg.ticalc.org>
* Julien BLACHE <jb@technologeek.org>
* under the terms of the GNU General Public License.
......@@ -20,6 +20,8 @@
* 1.04, Julien: clean-up & fixes; Romain: 2.4 backport.
* 1.05, Randy Dunlap: bug fix with the timeout parameter (divide-by-zero).
* 1.06, Romain: synched with 2.5, version/firmware changed (confusing).
* 1.07, Romain: fixed bad use of usb_clear_halt (invalid argument);
* timeout argument checked in ioctl + clean-up.
*/
#include <linux/module.h>
......@@ -38,8 +40,8 @@
/*
* Version Information
*/
#define DRIVER_VERSION "1.06"
#define DRIVER_AUTHOR "Romain Lievin <roms@lpg.ticalc.org> & Julien Blache <jb@jblache.org>"
#define DRIVER_VERSION "1.07"
#define DRIVER_AUTHOR "Romain Lievin <roms@tilp.info> & Julien Blache <jb@jblache.org>"
#define DRIVER_DESC "TI-GRAPH LINK USB (aka SilverLink) driver"
#define DRIVER_LICENSE "GPL"
......@@ -72,15 +74,15 @@ clear_pipes (struct usb_device *dev)
{
unsigned int pipe;
pipe = usb_sndbulkpipe (dev, 1);
if (usb_clear_halt (dev, usb_pipeendpoint (pipe))) {
err ("clear_pipe (r), request failed");
pipe = usb_sndbulkpipe (dev, 2);
if (usb_clear_halt (dev, pipe)) {
err ("clear_pipe (w), request failed");
return -1;
}
pipe = usb_sndbulkpipe (dev, 2);
if (usb_clear_halt (dev, usb_pipeendpoint (pipe))) {
err ("clear_pipe (w), request failed");
pipe = usb_rcvbulkpipe (dev, 1);
if (usb_clear_halt (dev, pipe)) {
err ("clear_pipe (r), request failed");
return -1;
}
......@@ -181,17 +183,16 @@ tiglusb_read (struct file *filp, char __user *buf, size_t count, loff_t * f_pos)
pipe = usb_rcvbulkpipe (s->dev, 1);
result = usb_bulk_msg (s->dev, pipe, buffer, bytes_to_read,
&bytes_read, HZ * 10 / timeout);
&bytes_read, (HZ * timeout) / 10);
if (result == -ETIMEDOUT) { /* NAK */
ret = result;
if (!bytes_read) {
if (!bytes_read)
dbg ("quirk !");
}
warn ("tiglusb_read, NAK received.");
ret = result;
goto out;
} else if (result == -EPIPE) { /* STALL -- shouldn't happen */
warn ("clear_halt request to remove STALL condition.");
if (usb_clear_halt (s->dev, usb_pipeendpoint (pipe)))
if (usb_clear_halt (s->dev, pipe))
err ("clear_halt, request failed");
clear_device (s->dev);
ret = result;
......@@ -243,7 +244,7 @@ tiglusb_write (struct file *filp, const char __user *buf, size_t count, loff_t *
pipe = usb_sndbulkpipe (s->dev, 2);
result = usb_bulk_msg (s->dev, pipe, buffer, bytes_to_write,
&bytes_written, HZ * 10 / timeout);
&bytes_written, (HZ * timeout) / 10);
if (result == -ETIMEDOUT) { /* NAK */
warn ("tiglusb_write, NAK received.");
......@@ -251,7 +252,7 @@ tiglusb_write (struct file *filp, const char __user *buf, size_t count, loff_t *
goto out;
} else if (result == -EPIPE) { /* STALL -- shouldn't happen */
warn ("clear_halt request to remove STALL condition.");
if (usb_clear_halt (s->dev, usb_pipeendpoint (pipe)))
if (usb_clear_halt (s->dev, pipe))
err ("clear_halt, request failed");
clear_device (s->dev);
ret = result;
......@@ -292,15 +293,16 @@ tiglusb_ioctl (struct inode *inode, struct file *filp,
switch (cmd) {
case IOCTL_TIUSB_TIMEOUT:
timeout = arg; // timeout value in tenth of seconds
if (arg > 0)
timeout = arg;
else
ret = -EINVAL;
break;
case IOCTL_TIUSB_RESET_DEVICE:
dbg ("IOCTL_TIGLUSB_RESET_DEVICE");
if (clear_device (s->dev))
ret = -EIO;
break;
case IOCTL_TIUSB_RESET_PIPES:
dbg ("IOCTL_TIGLUSB_RESET_PIPES");
if (clear_pipes (s->dev))
ret = -EIO;
break;
......@@ -447,7 +449,7 @@ static struct usb_driver tiglusb_driver = {
#ifndef MODULE
/*
* You can use 'tiusb=timeout'
* You can use 'tiusb=timeout' to set timeout.
*/
static int __init
tiglusb_setup (char *str)
......@@ -457,10 +459,11 @@ tiglusb_setup (char *str)
str = get_options (str, ARRAY_SIZE (ints), ints);
if (ints[0] > 0) {
if (ints[1] > 0)
timeout = ints[1];
else
info ("tiglusb: wrong timeout value (0), using default value.");
}
if (timeout <= 0)
timeout = TIMAXTIME;
return 1;
}
......@@ -502,9 +505,6 @@ tiglusb_init (void)
info (DRIVER_DESC ", version " DRIVER_VERSION);
if (timeout <= 0)
timeout = TIMAXTIME;
return 0;
}
......
......@@ -2107,8 +2107,12 @@ pl_set_QuickLink_features (struct usbnet *dev, int val)
static int pl_reset (struct usbnet *dev)
{
return pl_set_QuickLink_features (dev,
/* some units seem to need this reset, others reject it utterly.
* FIXME be more like "naplink" or windows drivers.
*/
(void) pl_set_QuickLink_features (dev,
PL_S_EN|PL_RESET_OUT|PL_RESET_IN|PL_PEER_E);
return 0;
}
static const struct driver_info prolific_info = {
......
......@@ -463,8 +463,6 @@ static struct usb_device_id id_table_FT232BM [] = {
{ USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_2_PID, 0x400, 0xffff) },
{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) },
{ } /* Terminating entry */
};
......@@ -566,6 +564,8 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_0_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_1_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, LINX_FUTURE_2_PID, 0x400, 0xffff) },
{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU20_0_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_CCSICDU40_1_PID) },
{ USB_DEVICE(FTDI_VID, INSIDE_ACCESSO) },
{ } /* Terminating entry */
};
......
......@@ -56,7 +56,8 @@ int dpcm_transport(Scsi_Cmnd *srb, struct us_data *us)
/*
* LUN 0 corresponds to the CompactFlash card reader.
*/
return usb_stor_CB_transport(srb, us);
ret = usb_stor_CB_transport(srb, us);
break;
#ifdef CONFIG_USB_STORAGE_SDDR09
case 1:
......@@ -71,12 +72,14 @@ int dpcm_transport(Scsi_Cmnd *srb, struct us_data *us)
srb->device->lun = 0; us->srb->device->lun = 0;
ret = sddr09_transport(srb, us);
srb->device->lun = 1; us->srb->device->lun = 1;
break;
return ret;
#endif
default:
US_DEBUGP("dpcm_transport: Invalid LUN %d\n", srb->device->lun);
return USB_STOR_TRANSPORT_ERROR;
ret = USB_STOR_TRANSPORT_ERROR;
break;
}
return ret;
}
......@@ -101,19 +101,27 @@ static int open(struct inode * inode, struct file * file)
if (!kobj || !attr)
goto Done;
/* Grab the module reference for this attribute if we have one */
error = -ENODEV;
if (!try_module_get(attr->attr.owner))
goto Done;
error = -EACCES;
if ((file->f_mode & FMODE_WRITE) && !attr->write)
goto Done;
goto Error;
if ((file->f_mode & FMODE_READ) && !attr->read)
goto Done;
goto Error;
error = -ENOMEM;
file->private_data = kmalloc(PAGE_SIZE, GFP_KERNEL);
if (!file->private_data)
goto Done;
goto Error;
error = 0;
goto Done;
Error:
module_put(attr->attr.owner);
Done:
if (error && kobj)
kobject_put(kobj);
......@@ -123,10 +131,12 @@ static int open(struct inode * inode, struct file * file)
static int release(struct inode * inode, struct file * file)
{
struct kobject * kobj = file->f_dentry->d_parent->d_fsdata;
struct bin_attribute * attr = file->f_dentry->d_fsdata;
u8 * buffer = file->private_data;
if (kobj)
kobject_put(kobj);
module_put(attr->attr.owner);
kfree(buffer);
return 0;
}
......
......@@ -42,7 +42,7 @@ static int object_path_length(struct kobject * kobj)
struct kobject * p = kobj;
int length = 1;
do {
length += strlen(p->name) + 1;
length += strlen(kobject_name(p)) + 1;
p = p->parent;
} while (p);
return length;
......@@ -54,11 +54,11 @@ static void fill_object_path(struct kobject * kobj, char * buffer, int length)
--length;
for (p = kobj; p; p = p->parent) {
int cur = strlen(p->name);
int cur = strlen(kobject_name(p));
/* back up enough to print this bus id with '/' */
length -= cur;
strncpy(buffer + length,p->name,cur);
strncpy(buffer + length,kobject_name(p),cur);
*(buffer + --length) = '/';
}
}
......
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