Commit e5679d07 authored by Kuninori Morimoto's avatar Kuninori Morimoto Committed by Felipe Balbi

usb: renesas_usbhs: add usbhs_pipe_attach() method

driver has to re-use the limited pipe for each device/endpoint
when it is USB host hub mode, since number of pipe has limitation.
This patch adds usbhsh_pipe_attach/detach() functions for it.
Signed-off-by: default avatarKuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent e4c57ded
...@@ -45,32 +45,31 @@ ...@@ -45,32 +45,31 @@
* *
* +--------+ pipes are reused for each uep. * +--------+ pipes are reused for each uep.
* | udev 1 |-+- [uep 0 (dcp) ] --+ pipe will be switched when * | udev 1 |-+- [uep 0 (dcp) ] --+ pipe will be switched when
* +--------+ | | target device was changed * +--------+ | | other device requested
* +- [uep 1 (bulk)] --|---+ +--------------+ * +- [uep 1 (bulk)] --|---+ +--------------+
* | +--------------> | pipe0 (dcp) | * | +--------------> | pipe0 (dcp) |
* +- [uep 2 (bulk)] --|---|---+ +--------------+ * +- [uep 2 (bulk)] -@ | +--------------+
* | | | | pipe1 (isoc) | * | | pipe1 (isoc) |
* +--------+ | | | +--------------+ * +--------+ | +--------------+
* | udev 2 |-+- [uep 0 (dcp) ] --+ +-- |------> | pipe2 (bulk) | * | udev 2 |-+- [uep 0 (dcp) ] -@ +----------> | pipe2 (bulk) |
* +--------+ | | | | +--------------+ * +--------+ | +--------------+
* +- [uep 1 (int) ] --|-+ | +------> | pipe3 (bulk) | * +- [uep 1 (int) ] ----+ +------> | pipe3 (bulk) |
* | | | | +--------------+ * | | +--------------+
* +--------+ | +-|---|------> | pipe4 (int) | * +--------+ +-----|------> | pipe4 (int) |
* | udev 3 |-+- [uep 0 (dcp) ] --+ | | +--------------+ * | udev 3 |-+- [uep 0 (dcp) ] -@ | +--------------+
* +--------+ | | | | .... | * +--------+ | | | .... |
* +- [uep 1 (bulk)] ------+ | | .... | * +- [uep 1 (bulk)] -@ | | .... |
* | | * | |
* +- [uep 2 (bulk)]-----------+ * +- [uep 2 (bulk)]-----------+
*
* @ : uep requested free pipe, but all have been used.
* now it is waiting for free pipe
*/ */
/* /*
* struct * struct
*/ */
struct usbhsh_pipe_info {
unsigned int usr_cnt; /* see usbhsh_endpoint_alloc() */
};
struct usbhsh_request { struct usbhsh_request {
struct urb *urb; struct urb *urb;
struct usbhs_pkt pkt; struct usbhs_pkt pkt;
...@@ -82,12 +81,10 @@ struct usbhsh_device { ...@@ -82,12 +81,10 @@ struct usbhsh_device {
}; };
struct usbhsh_ep { struct usbhsh_ep {
struct usbhs_pipe *pipe; struct usbhs_pipe *pipe; /* attached pipe */
struct usbhsh_device *udev; /* attached udev */ struct usbhsh_device *udev; /* attached udev */
struct usb_host_endpoint *ep; struct usb_host_endpoint *ep;
struct list_head ep_list; /* list to usbhsh_device */ struct list_head ep_list; /* list to usbhsh_device */
int maxp;
}; };
#define USBHSH_DEVICE_MAX 10 /* see DEVADDn / DCPMAXP / PIPEMAXP */ #define USBHSH_DEVICE_MAX 10 /* see DEVADDn / DCPMAXP / PIPEMAXP */
...@@ -98,9 +95,6 @@ struct usbhsh_hpriv { ...@@ -98,9 +95,6 @@ struct usbhsh_hpriv {
struct usbhsh_device udev[USBHSH_DEVICE_MAX]; struct usbhsh_device udev[USBHSH_DEVICE_MAX];
struct usbhsh_pipe_info *pipe_info;
int pipe_size;
u32 port_stat; /* USB_PORT_STAT_xxx */ u32 port_stat; /* USB_PORT_STAT_xxx */
struct completion setup_ack_done; struct completion setup_ack_done;
...@@ -115,17 +109,6 @@ static const char usbhsh_hcd_name[] = "renesas_usbhs host"; ...@@ -115,17 +109,6 @@ static const char usbhsh_hcd_name[] = "renesas_usbhs host";
#define usbhsh_priv_to_hpriv(priv) \ #define usbhsh_priv_to_hpriv(priv) \
container_of(usbhs_mod_get(priv, USBHS_HOST), struct usbhsh_hpriv, mod) container_of(usbhs_mod_get(priv, USBHS_HOST), struct usbhsh_hpriv, mod)
#define __usbhsh_for_each_hpipe(start, pos, h, i) \
for (i = start, pos = (h)->hpipe + i; \
i < (h)->hpipe_size; \
i++, pos = (h)->hpipe + i)
#define usbhsh_for_each_hpipe(pos, hpriv, i) \
__usbhsh_for_each_hpipe(1, pos, hpriv, i)
#define usbhsh_for_each_hpipe_with_dcp(pos, hpriv, i) \
__usbhsh_for_each_hpipe(0, pos, hpriv, i)
#define __usbhsh_for_each_udev(start, pos, h, i) \ #define __usbhsh_for_each_udev(start, pos, h, i) \
for (i = start, pos = (h)->udev + i; \ for (i = start, pos = (h)->udev + i; \
i < USBHSH_DEVICE_MAX; \ i < USBHSH_DEVICE_MAX; \
...@@ -158,7 +141,7 @@ static const char usbhsh_hcd_name[] = "renesas_usbhs host"; ...@@ -158,7 +141,7 @@ static const char usbhsh_hcd_name[] = "renesas_usbhs host";
#define usbhsh_udev_to_usbv(h) ((h)->usbv) #define usbhsh_udev_to_usbv(h) ((h)->usbv)
#define usbhsh_udev_is_used(h) usbhsh_udev_to_usbv(h) #define usbhsh_udev_is_used(h) usbhsh_udev_to_usbv(h)
#define usbhsh_pipe_info(p) ((p)->mod_private) #define usbhsh_pipe_to_uep(p) ((p)->mod_private)
#define usbhsh_device_parent(d) (usbhsh_usbv_to_udev((d)->usbv->parent)) #define usbhsh_device_parent(d) (usbhsh_usbv_to_udev((d)->usbv->parent))
#define usbhsh_device_hubport(d) ((d)->usbv->portnum) #define usbhsh_device_hubport(d) ((d)->usbv->portnum)
...@@ -208,106 +191,166 @@ static void usbhsh_ureq_free(struct usbhsh_hpriv *hpriv, ...@@ -208,106 +191,166 @@ static void usbhsh_ureq_free(struct usbhsh_hpriv *hpriv,
} }
/* /*
* end-point control * pipe control
*/ */
static struct usbhsh_device *usbhsh_device_get(struct usbhsh_hpriv *hpriv, static struct usbhsh_device *usbhsh_device_get(struct usbhsh_hpriv *hpriv,
struct urb *urb); struct urb *urb);
static int usbhsh_endpoint_attach(struct usbhsh_hpriv *hpriv,
struct urb *urb, static int usbhsh_pipe_attach(struct usbhsh_hpriv *hpriv,
gfp_t mem_flags) struct urb *urb)
{ {
struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv);
struct usbhsh_ep *uep = usbhsh_ep_to_uep(urb->ep);
struct usbhsh_device *udev = usbhsh_device_get(hpriv, urb); struct usbhsh_device *udev = usbhsh_device_get(hpriv, urb);
struct usb_host_endpoint *ep = urb->ep; struct usbhs_pipe *pipe;
struct usbhsh_ep *uep; struct usb_endpoint_descriptor *desc = &urb->ep->desc;
struct usbhsh_pipe_info *info;
struct usbhs_pipe *best_pipe = NULL;
struct device *dev = usbhs_priv_to_dev(priv); struct device *dev = usbhs_priv_to_dev(priv);
struct usb_endpoint_descriptor *desc = &ep->desc;
unsigned long flags; unsigned long flags;
int dir_in_req = !!usb_pipein(urb->pipe);
uep = kzalloc(sizeof(struct usbhsh_ep), mem_flags); int is_dcp = usb_endpoint_xfer_control(desc);
if (!uep) { int i, dir_in;
dev_err(dev, "usbhsh_ep alloc fail\n"); int ret = -EBUSY;
return -ENOMEM;
}
/******************** spin lock ********************/ /******************** spin lock ********************/
usbhs_lock(priv, flags); usbhs_lock(priv, flags);
/* if (unlikely(usbhsh_uep_to_pipe(uep))) {
* find best pipe for endpoint dev_err(dev, "uep already has pipe\n");
* see goto usbhsh_pipe_attach_done;
* HARDWARE LIMITATION }
*/
if (usb_endpoint_xfer_control(desc)) {
/* best pipe is DCP */
best_pipe = usbhsh_hpriv_to_dcp(hpriv);
} else {
struct usbhs_pipe *pipe;
unsigned int min_usr = ~0;
int dir_in_req = !!usb_pipein(urb->pipe);
int i, dir_in;
usbhs_for_each_pipe(pipe, priv, i) { usbhs_for_each_pipe_with_dcp(pipe, priv, i) {
if (!usbhs_pipe_type_is(pipe, usb_endpoint_type(desc)))
continue; /* check pipe type */
if (!usbhs_pipe_type_is(pipe, usb_endpoint_type(desc)))
continue;
/* check pipe direction if normal pipe */
if (!is_dcp) {
dir_in = !!usbhs_pipe_is_dir_in(pipe); dir_in = !!usbhs_pipe_is_dir_in(pipe);
if (0 != (dir_in - dir_in_req)) if (0 != (dir_in - dir_in_req))
continue; continue;
}
info = usbhsh_pipe_info(pipe); /* check pipe is free */
if (min_usr > info->usr_cnt) { if (usbhsh_pipe_to_uep(pipe))
min_usr = info->usr_cnt; continue;
best_pipe = pipe;
} /*
* attach pipe to uep
*
* usbhs_pipe_config_update() should be called after
* usbhs_set_device_config()
* see
* DCPMAXP/PIPEMAXP
*/
usbhsh_uep_to_pipe(uep) = pipe;
usbhsh_pipe_to_uep(pipe) = uep;
if (!usb_gettoggle(urb->dev,
usb_pipeendpoint(urb->pipe),
usb_pipeout(urb->pipe))) {
usbhs_pipe_sequence_data0(pipe);
usb_settoggle(urb->dev,
usb_pipeendpoint(urb->pipe),
usb_pipeout(urb->pipe), 1);
} }
usbhs_pipe_config_update(pipe,
usbhsh_device_number(hpriv, udev),
usb_endpoint_num(desc),
usb_endpoint_maxp(desc));
dev_dbg(dev, "%s [%d-%d(%s:%s)]\n", __func__,
usbhsh_device_number(hpriv, udev),
usb_endpoint_num(desc),
usbhs_pipe_name(pipe),
dir_in_req ? "in" : "out");
ret = 0;
break;
} }
if (best_pipe) { usbhsh_pipe_attach_done:
/* update pipe user count */ usbhs_unlock(priv, flags);
info = usbhsh_pipe_info(best_pipe); /******************** spin unlock ******************/
info->usr_cnt++;
/* init this endpoint, and attach it to udev */ return ret;
INIT_LIST_HEAD(&uep->ep_list); }
list_add_tail(&uep->ep_list, &udev->ep_list_head);
static void usbhsh_pipe_detach(struct usbhsh_hpriv *hpriv,
struct usbhsh_ep *uep)
{
struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv);
struct usbhs_pipe *pipe;
struct device *dev = usbhs_priv_to_dev(priv);
unsigned long flags;
/******************** spin lock ********************/
usbhs_lock(priv, flags);
pipe = usbhsh_uep_to_pipe(uep);
if (unlikely(!pipe)) {
dev_err(dev, "uep doens't have pipe\n");
} else {
struct usb_host_endpoint *ep = usbhsh_uep_to_ep(uep);
struct usbhsh_device *udev = usbhsh_uep_to_udev(uep);
/* detach pipe from uep */
usbhsh_uep_to_pipe(uep) = NULL;
usbhsh_pipe_to_uep(pipe) = NULL;
dev_dbg(dev, "%s [%d-%d(%s)]\n", __func__,
usbhsh_device_number(hpriv, udev),
usb_endpoint_num(&ep->desc),
usbhs_pipe_name(pipe));
} }
usbhs_unlock(priv, flags); usbhs_unlock(priv, flags);
/******************** spin unlock ******************/ /******************** spin unlock ******************/
}
if (unlikely(!best_pipe)) { /*
dev_err(dev, "couldn't find best pipe\n"); * endpoint control
kfree(uep); */
return -EIO; static int usbhsh_endpoint_attach(struct usbhsh_hpriv *hpriv,
struct urb *urb,
gfp_t mem_flags)
{
struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv);
struct usbhsh_device *udev = usbhsh_device_get(hpriv, urb);
struct usb_host_endpoint *ep = urb->ep;
struct usbhsh_ep *uep;
struct device *dev = usbhs_priv_to_dev(priv);
struct usb_endpoint_descriptor *desc = &ep->desc;
unsigned long flags;
uep = kzalloc(sizeof(struct usbhsh_ep), mem_flags);
if (!uep) {
dev_err(dev, "usbhsh_ep alloc fail\n");
return -ENOMEM;
} }
/******************** spin lock ********************/
usbhs_lock(priv, flags);
/* /*
* init uep * init endpoint
*/ */
uep->pipe = best_pipe; INIT_LIST_HEAD(&uep->ep_list);
uep->maxp = usb_endpoint_maxp(desc); list_add_tail(&uep->ep_list, &udev->ep_list_head);
usbhsh_uep_to_udev(uep) = udev; usbhsh_uep_to_udev(uep) = udev;
usbhsh_uep_to_ep(uep) = ep; usbhsh_uep_to_ep(uep) = ep;
usbhsh_ep_to_uep(ep) = uep; usbhsh_ep_to_uep(ep) = uep;
/* usbhs_unlock(priv, flags);
* usbhs_pipe_config_update() should be called after /******************** spin unlock ******************/
* usbhs_set_device_config()
* see
* DCPMAXP/PIPEMAXP
*/
usbhs_pipe_sequence_data0(uep->pipe);
usbhs_pipe_config_update(uep->pipe,
usbhsh_device_number(hpriv, udev),
usb_endpoint_num(desc),
uep->maxp);
dev_dbg(dev, "%s [%d-%s](%p)\n", __func__, dev_dbg(dev, "%s [%d-%d]\n", __func__,
usbhsh_device_number(hpriv, udev), usbhsh_device_number(hpriv, udev),
usbhs_pipe_name(uep->pipe), uep); usb_endpoint_num(desc));
return 0; return 0;
} }
...@@ -318,27 +361,24 @@ static void usbhsh_endpoint_detach(struct usbhsh_hpriv *hpriv, ...@@ -318,27 +361,24 @@ static void usbhsh_endpoint_detach(struct usbhsh_hpriv *hpriv,
struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv); struct usbhs_priv *priv = usbhsh_hpriv_to_priv(hpriv);
struct device *dev = usbhs_priv_to_dev(priv); struct device *dev = usbhs_priv_to_dev(priv);
struct usbhsh_ep *uep = usbhsh_ep_to_uep(ep); struct usbhsh_ep *uep = usbhsh_ep_to_uep(ep);
struct usbhsh_pipe_info *info;
unsigned long flags; unsigned long flags;
if (!uep) if (!uep)
return; return;
dev_dbg(dev, "%s [%d-%s](%p)\n", __func__, dev_dbg(dev, "%s [%d-%d]\n", __func__,
usbhsh_device_number(hpriv, usbhsh_uep_to_udev(uep)), usbhsh_device_number(hpriv, usbhsh_uep_to_udev(uep)),
usbhs_pipe_name(uep->pipe), uep); usb_endpoint_num(&ep->desc));
if (usbhsh_uep_to_pipe(uep))
usbhsh_pipe_detach(hpriv, uep);
/******************** spin lock ********************/ /******************** spin lock ********************/
usbhs_lock(priv, flags); usbhs_lock(priv, flags);
info = usbhsh_pipe_info(uep->pipe);
info->usr_cnt--;
/* remove this endpoint from udev */ /* remove this endpoint from udev */
list_del_init(&uep->ep_list); list_del_init(&uep->ep_list);
uep->pipe = NULL;
uep->maxp = 0;
usbhsh_uep_to_udev(uep) = NULL; usbhsh_uep_to_udev(uep) = NULL;
usbhsh_uep_to_ep(uep) = NULL; usbhsh_uep_to_ep(uep) = NULL;
usbhsh_ep_to_uep(ep) = NULL; usbhsh_ep_to_uep(ep) = NULL;
...@@ -545,6 +585,7 @@ static void usbhsh_queue_done(struct usbhs_priv *priv, struct usbhs_pkt *pkt) ...@@ -545,6 +585,7 @@ static void usbhsh_queue_done(struct usbhs_priv *priv, struct usbhs_pkt *pkt)
struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv);
struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv); struct usb_hcd *hcd = usbhsh_hpriv_to_hcd(hpriv);
struct urb *urb = ureq->urb; struct urb *urb = ureq->urb;
struct usbhsh_ep *uep = usbhsh_ep_to_uep(urb->ep);
struct device *dev = usbhs_priv_to_dev(priv); struct device *dev = usbhs_priv_to_dev(priv);
dev_dbg(dev, "%s\n", __func__); dev_dbg(dev, "%s\n", __func__);
...@@ -559,6 +600,8 @@ static void usbhsh_queue_done(struct usbhs_priv *priv, struct usbhs_pkt *pkt) ...@@ -559,6 +600,8 @@ static void usbhsh_queue_done(struct usbhs_priv *priv, struct usbhs_pkt *pkt)
usb_hcd_unlink_urb_from_ep(hcd, urb); usb_hcd_unlink_urb_from_ep(hcd, urb);
usb_hcd_giveback_urb(hcd, urb, 0); usb_hcd_giveback_urb(hcd, urb, 0);
usbhsh_pipe_detach(hpriv, uep);
} }
static int usbhsh_queue_push(struct usb_hcd *hcd, static int usbhsh_queue_push(struct usb_hcd *hcd,
...@@ -811,7 +854,7 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd, ...@@ -811,7 +854,7 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd,
struct usb_host_endpoint *ep = urb->ep; struct usb_host_endpoint *ep = urb->ep;
struct usbhsh_device *new_udev = NULL; struct usbhsh_device *new_udev = NULL;
int is_dir_in = usb_pipein(urb->pipe); int is_dir_in = usb_pipein(urb->pipe);
int i;
int ret; int ret;
dev_dbg(dev, "%s (%s)\n", __func__, is_dir_in ? "in" : "out"); dev_dbg(dev, "%s (%s)\n", __func__, is_dir_in ? "in" : "out");
...@@ -822,6 +865,7 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd, ...@@ -822,6 +865,7 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd,
/* /*
* attach udev if needed * attach udev if needed
* see [image of mod_host]
*/ */
if (!usbhsh_device_get(hpriv, urb)) { if (!usbhsh_device_get(hpriv, urb)) {
new_udev = usbhsh_device_attach(hpriv, urb); new_udev = usbhsh_device_attach(hpriv, urb);
...@@ -833,6 +877,7 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd, ...@@ -833,6 +877,7 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd,
/* /*
* attach endpoint if needed * attach endpoint if needed
* see [image of mod_host]
*/ */
if (!usbhsh_ep_to_uep(ep)) { if (!usbhsh_ep_to_uep(ep)) {
ret = usbhsh_endpoint_attach(hpriv, urb, mem_flags); ret = usbhsh_endpoint_attach(hpriv, urb, mem_flags);
...@@ -840,6 +885,20 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd, ...@@ -840,6 +885,20 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd,
goto usbhsh_urb_enqueue_error_free_device; goto usbhsh_urb_enqueue_error_free_device;
} }
/*
* attach pipe to endpoint
* see [image of mod_host]
*/
for (i = 0; i < 1024; i++) {
ret = usbhsh_pipe_attach(hpriv, urb);
if (ret < 0)
msleep(100);
else
break;
}
if (ret < 0)
goto usbhsh_urb_enqueue_error_free_endpoint;
/* /*
* push packet * push packet
*/ */
...@@ -850,6 +909,8 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd, ...@@ -850,6 +909,8 @@ static int usbhsh_urb_enqueue(struct usb_hcd *hcd,
return ret; return ret;
usbhsh_urb_enqueue_error_free_endpoint:
usbhsh_endpoint_detach(hpriv, ep);
usbhsh_urb_enqueue_error_free_device: usbhsh_urb_enqueue_error_free_device:
if (new_udev) if (new_udev)
usbhsh_device_detach(hpriv, new_udev); usbhsh_device_detach(hpriv, new_udev);
...@@ -1192,7 +1253,6 @@ static int usbhsh_irq_setup_err(struct usbhs_priv *priv, ...@@ -1192,7 +1253,6 @@ static int usbhsh_irq_setup_err(struct usbhs_priv *priv,
static void usbhsh_pipe_init_for_host(struct usbhs_priv *priv) static void usbhsh_pipe_init_for_host(struct usbhs_priv *priv)
{ {
struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv); struct usbhsh_hpriv *hpriv = usbhsh_priv_to_hpriv(priv);
struct usbhsh_pipe_info *pipe_info = hpriv->pipe_info;
struct usbhs_pipe *pipe; struct usbhs_pipe *pipe;
u32 *pipe_type = usbhs_get_dparam(priv, pipe_type); u32 *pipe_type = usbhs_get_dparam(priv, pipe_type);
int pipe_size = usbhs_get_dparam(priv, pipe_size); int pipe_size = usbhs_get_dparam(priv, pipe_size);
...@@ -1201,7 +1261,6 @@ static void usbhsh_pipe_init_for_host(struct usbhs_priv *priv) ...@@ -1201,7 +1261,6 @@ static void usbhsh_pipe_init_for_host(struct usbhs_priv *priv)
/* init all pipe */ /* init all pipe */
old_type = USB_ENDPOINT_XFER_CONTROL; old_type = USB_ENDPOINT_XFER_CONTROL;
for (i = 0; i < pipe_size; i++) { for (i = 0; i < pipe_size; i++) {
pipe_info[i].usr_cnt = 0;
/* /*
* data "output" will be finished as soon as possible, * data "output" will be finished as soon as possible,
...@@ -1235,7 +1294,7 @@ static void usbhsh_pipe_init_for_host(struct usbhs_priv *priv) ...@@ -1235,7 +1294,7 @@ static void usbhsh_pipe_init_for_host(struct usbhs_priv *priv)
dir_in); dir_in);
} }
pipe->mod_private = pipe_info + i; pipe->mod_private = NULL;
} }
} }
...@@ -1312,10 +1371,8 @@ int usbhs_mod_host_probe(struct usbhs_priv *priv) ...@@ -1312,10 +1371,8 @@ int usbhs_mod_host_probe(struct usbhs_priv *priv)
{ {
struct usbhsh_hpriv *hpriv; struct usbhsh_hpriv *hpriv;
struct usb_hcd *hcd; struct usb_hcd *hcd;
struct usbhsh_pipe_info *pipe_info;
struct usbhsh_device *udev; struct usbhsh_device *udev;
struct device *dev = usbhs_priv_to_dev(priv); struct device *dev = usbhs_priv_to_dev(priv);
int pipe_size = usbhs_get_dparam(priv, pipe_size);
int i; int i;
/* initialize hcd */ /* initialize hcd */
...@@ -1325,12 +1382,6 @@ int usbhs_mod_host_probe(struct usbhs_priv *priv) ...@@ -1325,12 +1382,6 @@ int usbhs_mod_host_probe(struct usbhs_priv *priv)
return -ENOMEM; return -ENOMEM;
} }
pipe_info = kzalloc(sizeof(*pipe_info) * pipe_size, GFP_KERNEL);
if (!pipe_info) {
dev_err(dev, "Could not allocate pipe_info\n");
goto usbhs_mod_host_probe_err;
}
/* /*
* CAUTION * CAUTION
* *
...@@ -1350,8 +1401,6 @@ int usbhs_mod_host_probe(struct usbhs_priv *priv) ...@@ -1350,8 +1401,6 @@ int usbhs_mod_host_probe(struct usbhs_priv *priv)
hpriv->mod.name = "host"; hpriv->mod.name = "host";
hpriv->mod.start = usbhsh_start; hpriv->mod.start = usbhsh_start;
hpriv->mod.stop = usbhsh_stop; hpriv->mod.stop = usbhsh_stop;
hpriv->pipe_info = pipe_info;
hpriv->pipe_size = pipe_size;
usbhsh_port_stat_init(hpriv); usbhsh_port_stat_init(hpriv);
/* init all device */ /* init all device */
...@@ -1363,11 +1412,6 @@ int usbhs_mod_host_probe(struct usbhs_priv *priv) ...@@ -1363,11 +1412,6 @@ int usbhs_mod_host_probe(struct usbhs_priv *priv)
dev_info(dev, "host probed\n"); dev_info(dev, "host probed\n");
return 0; return 0;
usbhs_mod_host_probe_err:
usb_put_hcd(hcd);
return -ENOMEM;
} }
int usbhs_mod_host_remove(struct usbhs_priv *priv) int usbhs_mod_host_remove(struct usbhs_priv *priv)
......
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