Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 206003
b: refs/heads/master
c: aa5873e
h: refs/heads/master
i:
  206001: 2d7d0de
  205999: d2fe9eb
v: v3
  • Loading branch information
Endre Kollar authored and Greg Kroah-Hartman committed Jul 27, 2010
1 parent 75520ec commit f96ab96
Show file tree
Hide file tree
Showing 4 changed files with 160 additions and 25 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 125ed824d3d03f5c470cf98aca757fd9423c49ab
refs/heads/master: aa5873e96271611ae55586f65e49ea1fab90cb88
17 changes: 16 additions & 1 deletion trunk/drivers/staging/usbip/stub.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
#include <linux/module.h>
#include <linux/net.h>

#define STUB_BUSID_OTHER 0
#define STUB_BUSID_REMOV 1
#define STUB_BUSID_ADDED 2
#define STUB_BUSID_ALLOC 3

struct stub_device {
struct usb_interface *interface;
struct list_head list;
Expand Down Expand Up @@ -72,6 +77,14 @@ struct stub_unlink {
__u32 status;
};

#define BUSID_SIZE 20
struct bus_id_priv {
char name[BUSID_SIZE];
char status;
int interf_count;
struct stub_device *sdev;
char shutdown_busid;
};

extern struct kmem_cache *stub_priv_cache;

Expand All @@ -91,5 +104,7 @@ void stub_rx_loop(struct usbip_task *);
void stub_enqueue_ret_unlink(struct stub_device *, __u32, __u32);

/* stub_main.c */
int match_busid(const char *busid);
struct bus_id_priv *get_busid_priv(const char *busid);
int del_match_busid(char *busid);

void stub_device_cleanup_urbs(struct stub_device *sdev);
101 changes: 91 additions & 10 deletions trunk/drivers/staging/usbip/stub_dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -393,11 +393,14 @@ static int stub_probe(struct usb_interface *interface,
struct stub_device *sdev = NULL;
const char *udev_busid = dev_name(interface->dev.parent);
int err = 0;
struct bus_id_priv *busid_priv;

dev_dbg(&interface->dev, "Enter\n");

/* check we should claim or not by busid_table */
if (match_busid(udev_busid)) {
busid_priv = get_busid_priv(udev_busid);
if (!busid_priv || (busid_priv->status == STUB_BUSID_REMOV) ||
(busid_priv->status == STUB_BUSID_OTHER)) {
dev_info(&interface->dev,
"this device %s is not in match_busid table. skip!\n",
udev_busid);
Expand All @@ -422,41 +425,102 @@ static int stub_probe(struct usb_interface *interface,
return -ENODEV;
}


if (busid_priv->status == STUB_BUSID_ALLOC) {
busid_priv->interf_count++;
sdev = busid_priv->sdev;
if (!sdev)
return -ENODEV;

dev_info(&interface->dev,
"USB/IP Stub: register a new interface "
"(bus %u dev %u ifn %u)\n", udev->bus->busnum, udev->devnum,
interface->cur_altsetting->desc.bInterfaceNumber);

/* set private data to usb_interface */
usb_set_intfdata(interface, sdev);

err = stub_add_files(&interface->dev);
if (err) {
dev_err(&interface->dev, "create sysfs files for %s\n",
udev_busid);
usb_set_intfdata(interface, NULL);
busid_priv->interf_count--;

return err;
}

return 0;
}

/* ok. this is my device. */
sdev = stub_device_alloc(interface);
if (!sdev)
return -ENOMEM;

dev_info(&interface->dev, "USB/IP Stub: register a new interface "
dev_info(&interface->dev, "USB/IP Stub: register a new device "
"(bus %u dev %u ifn %u)\n", udev->bus->busnum, udev->devnum,
interface->cur_altsetting->desc.bInterfaceNumber);

busid_priv->interf_count = 0;
busid_priv->shutdown_busid = 0;

/* set private data to usb_interface */
usb_set_intfdata(interface, sdev);
busid_priv->interf_count++;

busid_priv->sdev = sdev;

err = stub_add_files(&interface->dev);
if (err) {
dev_err(&interface->dev, "create sysfs files for %s\n",
udev_busid);
usb_set_intfdata(interface, 0);
usb_set_intfdata(interface, NULL);
busid_priv->interf_count = 0;

busid_priv->sdev = NULL;
stub_device_free(sdev);
return err;
}
busid_priv->status = STUB_BUSID_ALLOC;

return 0;
}

static void shutdown_busid(struct bus_id_priv *busid_priv)
{
if (busid_priv->sdev && !busid_priv->shutdown_busid) {
busid_priv->shutdown_busid = 1;
usbip_event_add(&busid_priv->sdev->ud, SDEV_EVENT_REMOVED);

/* 2. wait for the stop of the event handler */
usbip_stop_eh(&busid_priv->sdev->ud);
}

}


/*
* called in usb_disconnect() or usb_deregister()
* but only if actconfig(active configuration) exists
*/
static void stub_disconnect(struct usb_interface *interface)
{
struct stub_device *sdev = usb_get_intfdata(interface);
struct stub_device *sdev;
const char *udev_busid = dev_name(interface->dev.parent);
struct bus_id_priv *busid_priv;

busid_priv = get_busid_priv(udev_busid);

usbip_udbg("Enter\n");

if (!busid_priv) {
BUG();
return;
}

sdev = usb_get_intfdata(interface);

/* get stub_device */
if (!sdev) {
err(" could not get device from inteface data");
Expand All @@ -466,22 +530,39 @@ static void stub_disconnect(struct usb_interface *interface)

usb_set_intfdata(interface, NULL);


/*
* NOTE:
* rx/tx threads are invoked for each usb_device.
*/
stub_remove_files(&interface->dev);

/* 1. shutdown the current connection */
usbip_event_add(&sdev->ud, SDEV_EVENT_REMOVED);
/*If usb reset called from event handler*/
if (busid_priv->sdev->ud.eh.thread == current) {
busid_priv->interf_count--;
return;
}

if (busid_priv->interf_count > 1) {
busid_priv->interf_count--;
shutdown_busid(busid_priv);
return;
}

busid_priv->interf_count = 0;

/* 2. wait for the stop of the event handler */
usbip_stop_eh(&sdev->ud);

/* 1. shutdown the current connection */
shutdown_busid(busid_priv);

/* 3. free sdev */
busid_priv->sdev = NULL;
stub_device_free(sdev);


if (busid_priv->status == STUB_BUSID_ALLOC) {
busid_priv->status = STUB_BUSID_ADDED;
} else {
busid_priv->status = STUB_BUSID_OTHER;
del_match_busid((char *)udev_busid);
}
usbip_udbg("bye\n");
}
65 changes: 52 additions & 13 deletions trunk/drivers/staging/usbip/stub_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ struct kmem_cache *stub_priv_cache;
* remote host.
*/
#define MAX_BUSID 16
#define BUSID_SIZE 20
static char busid_table[MAX_BUSID][BUSID_SIZE];
static struct bus_id_priv busid_table[MAX_BUSID];
static spinlock_t busid_table_lock;


Expand All @@ -53,8 +52,8 @@ int match_busid(const char *busid)
spin_lock(&busid_table_lock);

for (i = 0; i < MAX_BUSID; i++)
if (busid_table[i][0])
if (!strncmp(busid_table[i], busid, BUSID_SIZE)) {
if (busid_table[i].name[0])
if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) {
/* already registerd */
spin_unlock(&busid_table_lock);
return 0;
Expand All @@ -65,6 +64,25 @@ int match_busid(const char *busid)
return 1;
}

struct bus_id_priv *get_busid_priv(const char *busid)
{
int i;

spin_lock(&busid_table_lock);

for (i = 0; i < MAX_BUSID; i++)
if (busid_table[i].name[0])
if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) {
/* already registerd */
spin_unlock(&busid_table_lock);
return &(busid_table[i]);
}

spin_unlock(&busid_table_lock);

return NULL;
}

static ssize_t show_match_busid(struct device_driver *drv, char *buf)
{
int i;
Expand All @@ -73,8 +91,8 @@ static ssize_t show_match_busid(struct device_driver *drv, char *buf)
spin_lock(&busid_table_lock);

for (i = 0; i < MAX_BUSID; i++)
if (busid_table[i][0])
out += sprintf(out, "%s ", busid_table[i]);
if (busid_table[i].name[0])
out += sprintf(out, "%s ", busid_table[i].name);

spin_unlock(&busid_table_lock);

Expand All @@ -93,8 +111,11 @@ static int add_match_busid(char *busid)
spin_lock(&busid_table_lock);

for (i = 0; i < MAX_BUSID; i++)
if (!busid_table[i][0]) {
strncpy(busid_table[i], busid, BUSID_SIZE);
if (!busid_table[i].name[0]) {
strncpy(busid_table[i].name, busid, BUSID_SIZE);
if ((busid_table[i].status != STUB_BUSID_ALLOC) &&
(busid_table[i].status != STUB_BUSID_REMOV))
busid_table[i].status = STUB_BUSID_ADDED;
spin_unlock(&busid_table_lock);
return 0;
}
Expand All @@ -104,16 +125,21 @@ static int add_match_busid(char *busid)
return -1;
}

static int del_match_busid(char *busid)
int del_match_busid(char *busid)
{
int i;

spin_lock(&busid_table_lock);

for (i = 0; i < MAX_BUSID; i++)
if (!strncmp(busid_table[i], busid, BUSID_SIZE)) {
if (!strncmp(busid_table[i].name, busid, BUSID_SIZE)) {
/* found */
memset(busid_table[i], 0, BUSID_SIZE);
if (busid_table[i].status == STUB_BUSID_OTHER)
memset(busid_table[i].name, 0, BUSID_SIZE);
if ((busid_table[i].status != STUB_BUSID_OTHER) &&
(busid_table[i].status != STUB_BUSID_ADDED)) {
busid_table[i].status = STUB_BUSID_REMOV;
}
spin_unlock(&busid_table_lock);
return 0;
}
Expand All @@ -122,6 +148,20 @@ static int del_match_busid(char *busid)

return -1;
}
static void init_busid_table(void)
{
int i;


for (i = 0; i < MAX_BUSID; i++) {
memset(busid_table[i].name, 0, BUSID_SIZE);
busid_table[i].status = STUB_BUSID_OTHER;
busid_table[i].interf_count = 0;
busid_table[i].sdev = NULL;
busid_table[i].shutdown_busid = 0;
}
spin_lock_init(&busid_table_lock);
}

static ssize_t store_match_busid(struct device_driver *dev, const char *buf,
size_t count)
Expand Down Expand Up @@ -261,8 +301,7 @@ static int __init usb_stub_init(void)
printk(KERN_INFO KBUILD_MODNAME ":"
DRIVER_DESC ":" DRIVER_VERSION "\n");

memset(busid_table, 0, sizeof(busid_table));
spin_lock_init(&busid_table_lock);
init_busid_table();

ret = driver_create_file(&stub_driver.drvwrap.driver,
&driver_attr_match_busid);
Expand Down

0 comments on commit f96ab96

Please sign in to comment.