From 4b345c9a3c7452340fb477868d8db475f05978b1 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 16 Jul 2012 14:08:16 +0300 Subject: usb: dwc3: gadget: set Ignore Sequence Number bit from ConnectDone Event Databook says we should set Ignore Sequence Number bit from ConnectDone Event, so let's do so. Signed-off-by: Felipe Balbi diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 58fdfad..283c0cb 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -431,7 +431,8 @@ static int dwc3_gadget_start_config(struct dwc3 *dwc, struct dwc3_ep *dep) static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep, const struct usb_endpoint_descriptor *desc, - const struct usb_ss_ep_comp_descriptor *comp_desc) + const struct usb_ss_ep_comp_descriptor *comp_desc, + bool ignore) { struct dwc3_gadget_ep_cmd_params params; @@ -441,6 +442,9 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep, | DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc)) | DWC3_DEPCFG_BURST_SIZE(dep->endpoint.maxburst - 1); + if (ignore) + params.param0 |= DWC3_DEPCFG_IGN_SEQ_NUM; + params.param1 = DWC3_DEPCFG_XFER_COMPLETE_EN | DWC3_DEPCFG_XFER_NOT_READY_EN; @@ -498,7 +502,8 @@ static int dwc3_gadget_set_xfer_resource(struct dwc3 *dwc, struct dwc3_ep *dep) */ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, const struct usb_endpoint_descriptor *desc, - const struct usb_ss_ep_comp_descriptor *comp_desc) + const struct usb_ss_ep_comp_descriptor *comp_desc, + bool ignore) { struct dwc3 *dwc = dep->dwc; u32 reg; @@ -510,7 +515,7 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, return ret; } - ret = dwc3_gadget_set_ep_config(dwc, dep, desc, comp_desc); + ret = dwc3_gadget_set_ep_config(dwc, dep, desc, comp_desc, ignore); if (ret) return ret; @@ -683,7 +688,7 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep, dev_vdbg(dwc->dev, "Enabling %s\n", dep->name); spin_lock_irqsave(&dwc->lock, flags); - ret = __dwc3_gadget_ep_enable(dep, desc, ep->comp_desc); + ret = __dwc3_gadget_ep_enable(dep, desc, ep->comp_desc, false); spin_unlock_irqrestore(&dwc->lock, flags); return ret; @@ -1518,14 +1523,14 @@ static int dwc3_gadget_start(struct usb_gadget *g, dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); dep = dwc->eps[0]; - ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL); + ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false); if (ret) { dev_err(dwc->dev, "failed to enable %s\n", dep->name); goto err0; } dep = dwc->eps[1]; - ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL); + ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, false); if (ret) { dev_err(dwc->dev, "failed to enable %s\n", dep->name); goto err1; @@ -2141,14 +2146,14 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) } dep = dwc->eps[0]; - ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL); + ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, true); if (ret) { dev_err(dwc->dev, "failed to enable %s\n", dep->name); return; } dep = dwc->eps[1]; - ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL); + ret = __dwc3_gadget_ep_enable(dep, &dwc3_gadget_ep0_desc, NULL, true); if (ret) { dev_err(dwc->dev, "failed to enable %s\n", dep->name); return; -- cgit v0.10.2 From 35f75696649d43aee8031d81783322b0708805b5 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 19 Jul 2012 08:49:01 +0300 Subject: usb: dwc3: ep0: drop unnecessary variable When returning from ep0_queue, we have an unnecessary ret variable which is always zero. Remove it. Signed-off-by: Felipe Balbi diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 9b94886..962fb9b 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -125,7 +125,6 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, struct dwc3_request *req) { struct dwc3 *dwc = dep->dwc; - int ret = 0; req->request.actual = 0; req->request.status = -EINPROGRESS; @@ -165,7 +164,7 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, dev_dbg(dwc->dev, "too early for delayed status\n"); } - return ret; + return 0; } int dwc3_gadget_ep0_queue(struct usb_ep *ep, struct usb_request *request, -- cgit v0.10.2 From d9b33c605c398df1d42c694bda28fe8708754c64 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 19 Jul 2012 08:51:13 +0300 Subject: usb: dwc3: ep0: split the special cases on ep0_queue We can return early from each if () branch and split the special cases for clarity. While at that also add a comment to the delayed_status case. Signed-off-by: Felipe Balbi diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 962fb9b..28bce9b 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -155,13 +155,23 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, dep->flags &= ~(DWC3_EP_PENDING_REQUEST | DWC3_EP0_DIR_IN); - } else if (dwc->delayed_status) { + + return 0; + } + + /* + * In case gadget driver asked us to delay the STATUS phase, + * handle it here. + */ + if (dwc->delayed_status) { dwc->delayed_status = false; if (dwc->ep0state == EP0_STATUS_PHASE) __dwc3_ep0_do_control_status(dwc, dwc->eps[1]); else dev_dbg(dwc->dev, "too early for delayed status\n"); + + return 0; } return 0; -- cgit v0.10.2 From 4635d3f29864d723a74983339ffc85db212e304b Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 19 Jul 2012 08:53:41 +0300 Subject: usb: dwc3: ep0: drop dead code There's no such thing as XferNotReady(SETUP), we can safely drop all that code with no problems whatsoever. Signed-off-by: Felipe Balbi diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 151eca8..c611d80 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -457,7 +457,6 @@ enum dwc3_phy { enum dwc3_ep0_next { DWC3_EP0_UNKNOWN = 0, DWC3_EP0_COMPLETE, - DWC3_EP0_NRDY_SETUP, DWC3_EP0_NRDY_DATA, DWC3_EP0_NRDY_STATUS, }; @@ -779,7 +778,6 @@ struct dwc3_event_depevt { #define DEPEVT_STREAMEVT_NOTFOUND 2 /* Control-only Status */ -#define DEPEVT_STATUS_CONTROL_SETUP 0 #define DEPEVT_STATUS_CONTROL_DATA 1 #define DEPEVT_STATUS_CONTROL_STATUS 2 diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 28bce9b..d4b38c7 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -809,12 +809,6 @@ static void dwc3_ep0_xfer_complete(struct dwc3 *dwc, } } -static void dwc3_ep0_do_control_setup(struct dwc3 *dwc, - const struct dwc3_event_depevt *event) -{ - dwc3_ep0_out_start(dwc); -} - static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, struct dwc3_ep *dep, struct dwc3_request *req) { @@ -926,50 +920,7 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc, { dwc->setup_packet_pending = true; - /* - * This part is very tricky: If we have just handled - * XferNotReady(Setup) and we're now expecting a - * XferComplete but, instead, we receive another - * XferNotReady(Setup), we should STALL and restart - * the state machine. - * - * In all other cases, we just continue waiting - * for the XferComplete event. - * - * We are a little bit unsafe here because we're - * not trying to ensure that last event was, indeed, - * XferNotReady(Setup). - * - * Still, we don't expect any condition where that - * should happen and, even if it does, it would be - * another error condition. - */ - if (dwc->ep0_next_event == DWC3_EP0_COMPLETE) { - switch (event->status) { - case DEPEVT_STATUS_CONTROL_SETUP: - dev_vdbg(dwc->dev, "Unexpected XferNotReady(Setup)\n"); - dwc3_ep0_stall_and_restart(dwc); - break; - case DEPEVT_STATUS_CONTROL_DATA: - /* FALLTHROUGH */ - case DEPEVT_STATUS_CONTROL_STATUS: - /* FALLTHROUGH */ - default: - dev_vdbg(dwc->dev, "waiting for XferComplete\n"); - } - - return; - } - switch (event->status) { - case DEPEVT_STATUS_CONTROL_SETUP: - dev_vdbg(dwc->dev, "Control Setup\n"); - - dwc->ep0state = EP0_SETUP_PHASE; - - dwc3_ep0_do_control_setup(dwc, event); - break; - case DEPEVT_STATUS_CONTROL_DATA: dev_vdbg(dwc->dev, "Control Data\n"); -- cgit v0.10.2 From 77fa6df82f154535293beb9bc68851f75c2c22cb Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 23 Jul 2012 09:09:32 +0300 Subject: usb: dwc3: ep0: ignore XferNotReady(STATUS) when we're not expecting it Databook doesn't say we should stall if we get XferNotReady(STATUS) while we're expecting something else. Instead of stalling and restarting, tests have proven that ignoring the event is far more effective. This problem has been caught while rewriting ep0 handling in order we pass Link Layer TD7.6. Signed-off-by: Felipe Balbi diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index d4b38c7..39abc58 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -953,19 +953,13 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc, break; case DEPEVT_STATUS_CONTROL_STATUS: + if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS) + return; + dev_vdbg(dwc->dev, "Control Status\n"); dwc->ep0state = EP0_STATUS_PHASE; - if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS) { - dev_vdbg(dwc->dev, "Expected %d got %d\n", - dwc->ep0_next_event, - DWC3_EP0_NRDY_STATUS); - - dwc3_ep0_stall_and_restart(dwc); - return; - } - if (dwc->delayed_status) { WARN_ON_ONCE(event->endpoint_number != 1); dev_vdbg(dwc->dev, "Mass Storage delayed status\n"); -- cgit v0.10.2 From fca8892ae552668e726ec9dad6ba7a26743e9a09 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 19 Jul 2012 09:05:35 +0300 Subject: usb: dwc3: ep0: move DATA phase away from on-demand We uncovered a limitation of this core WRT to the Link Layer Compliance Suite's TD7.06. On that test, host will start a GetDescriptor(DEVICE) standard request, but it will do so only on the SETUP phase, meaning there will *NOT* be any DATA or STATUS phases. The idea of the test is to verify robustness of the IP WRT framing errors, so the test will send a sequence of different SETUP_DPs each with a different framing error and the Suite expects us to be able to receive all SETUP_DPs with no timeouts. This core, has the ability to tell us which phase the host is expecting before we start it. Whenever we receive a TP or DP when no transfers are cached on the internal IP's caches, the IP will generate a XferNotReady event with status informing us (in case of physical ep0/ep1) if it's related to DATA or STATUS phases - SETUP phase is expected to be prestarted. Because we're always waiting for XferNotReady events for DATA and STATUS phases, we will never be able to know that the Host wants to start another SETUP phase instead, which will render us "not compliant" with TD7.06. In order to "fix" the problem we must not rely on XferNotReady events for the DATA phase and try to always pre-start DATA transfers on physical endpoints 0 and 1. If host goes back to SETUP phase from DATA phase we will receive a XferComplete for that phase with TRB's status set to SETUP_PENDING, which is only useful for printing a debugging log as the core expects us to still go through to the STATUS phase, initiate a CONTROL_STATUS TRB just so it completes right away and, only then, we go back to the pending SETUP phase. SNPS has decided to modify the programming model of the core so that on-demand DATA phases will not be supported anymore. Note that this limitation does not affect 2-stage transfers, meaning that if TD7.06 would start a 2-stage transfer instead of a 3-stage transfer, we would receive a "fake" XferNotReady(STATUS) which would complete right after being initiated with SETUP_PENDING status. Other endpoints are also not affected, so we can still use on-demand transfers on Bulk/Isoc/Interrupt endpoints. Signed-off-by: Felipe Balbi diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 39abc58..69d5741 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -174,6 +174,49 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, return 0; } + /* + * Unfortunately we have uncovered a limitation wrt the Data Phase. + * + * Section 9.4 says we can wait for the XferNotReady(DATA) event to + * come before issueing Start Transfer command, but if we do, we will + * miss situations where the host starts another SETUP phase instead of + * the DATA phase. Such cases happen at least on TD.7.6 of the Link + * Layer Compliance Suite. + * + * The problem surfaces due to the fact that in case of back-to-back + * SETUP packets there will be no XferNotReady(DATA) generated and we + * will be stuck waiting for XferNotReady(DATA) forever. + * + * By looking at tables 9-13 and 9-14 of the Databook, we can see that + * it tells us to start Data Phase right away. It also mentions that if + * we receive a SETUP phase instead of the DATA phase, core will issue + * XferComplete for the DATA phase, before actually initiating it in + * the wire, with the TRB's status set to "SETUP_PENDING". Such status + * can only be used to print some debugging logs, as the core expects + * us to go through to the STATUS phase and start a CONTROL_STATUS TRB, + * just so it completes right away, without transferring anything and, + * only then, we can go back to the SETUP phase. + * + * Because of this scenario, SNPS decided to change the programming + * model of control transfers and support on-demand transfers only for + * the STATUS phase. To fix the issue we have now, we will always wait + * for gadget driver to queue the DATA phase's struct usb_request, then + * start it right away. + * + * If we're actually in a 2-stage transfer, we will wait for + * XferNotReady(STATUS). + */ + if (dwc->three_stage_setup) { + unsigned direction; + + direction = dwc->ep0_expect_in; + dwc->ep0state = EP0_DATA_PHASE; + + __dwc3_ep0_do_control_data(dwc, dwc->eps[direction], req); + + dep->flags &= ~DWC3_EP0_DIR_IN; + } + return 0; } @@ -707,6 +750,7 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, struct dwc3_trb *trb; struct dwc3_ep *ep0; u32 transferred; + u32 status; u32 length; u8 epnum; @@ -719,6 +763,17 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc, ur = &r->request; trb = dwc->ep0_trb; + + status = DWC3_TRB_SIZE_TRBSTS(trb->size); + if (status == DWC3_TRBSTS_SETUP_PENDING) { + dev_dbg(dwc->dev, "Setup Pending received\n"); + + if (r) + dwc3_gadget_giveback(ep0, r, -ECONNRESET); + + return; + } + length = trb->size & DWC3_TRB_SIZE_MASK; if (dwc->ep0_bounced) { @@ -755,8 +810,11 @@ static void dwc3_ep0_complete_status(struct dwc3 *dwc, { struct dwc3_request *r; struct dwc3_ep *dep; + struct dwc3_trb *trb; + u32 status; dep = dwc->eps[0]; + trb = dwc->ep0_trb; if (!list_empty(&dep->request_list)) { r = next_request(&dep->request_list); @@ -776,6 +834,10 @@ static void dwc3_ep0_complete_status(struct dwc3 *dwc, } } + status = DWC3_TRB_SIZE_TRBSTS(trb->size); + if (status == DWC3_TRBSTS_SETUP_PENDING) + dev_dbg(dwc->dev, "Setup Pending received\n"); + dwc->ep0state = EP0_SETUP_PHASE; dwc3_ep0_out_start(dwc); } -- cgit v0.10.2 From 2e3db064855a637c45f7e011214f15bc536e61ad Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 19 Jul 2012 09:26:59 +0300 Subject: usb: dwc3: ep0: drop XferNotReady(DATA) support Due to the late Silicon limitation found, we are now pre-starting DATA phase's TRBs. If, still, we get XferNotReady(DATA) we will ignore it unless we're getting it for the wrong direction. In that case we must keep the error case handling plus add a ENDTRANSFER command to forcefully end the Data TRB we started previously, then continue to SetStall and so on. Signed-off-by: Felipe Balbi diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 69d5741..3936c64 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -923,29 +923,6 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, WARN_ON(ret < 0); } -static void dwc3_ep0_do_control_data(struct dwc3 *dwc, - const struct dwc3_event_depevt *event) -{ - struct dwc3_ep *dep; - struct dwc3_request *req; - - dep = dwc->eps[0]; - - if (list_empty(&dep->request_list)) { - dev_vdbg(dwc->dev, "pending request for EP0 Data phase\n"); - dep->flags |= DWC3_EP_PENDING_REQUEST; - - if (event->endpoint_number) - dep->flags |= DWC3_EP0_DIR_IN; - return; - } - - req = next_request(&dep->request_list); - dep = dwc->eps[event->endpoint_number]; - - __dwc3_ep0_do_control_data(dwc, dep, req); -} - static int dwc3_ep0_start_control_status(struct dwc3_ep *dep) { struct dwc3 *dwc = dep->dwc; @@ -977,6 +954,24 @@ static void dwc3_ep0_do_control_status(struct dwc3 *dwc, __dwc3_ep0_do_control_status(dwc, dep); } +static void dwc3_ep0_end_control_data(struct dwc3 *dwc, struct dwc3_ep *dep) +{ + struct dwc3_gadget_ep_cmd_params params; + u32 cmd; + int ret; + + if (!dep->resource_index) + return; + + cmd = DWC3_DEPCMD_ENDTRANSFER; + cmd |= DWC3_DEPCMD_CMDIOC; + cmd |= DWC3_DEPCMD_PARAM(dep->resource_index); + memset(¶ms, 0, sizeof(params)); + ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, ¶ms); + WARN_ON_ONCE(ret); + dep->resource_index = 0; +} + static void dwc3_ep0_xfernotready(struct dwc3 *dwc, const struct dwc3_event_depevt *event) { @@ -986,32 +981,24 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc, case DEPEVT_STATUS_CONTROL_DATA: dev_vdbg(dwc->dev, "Control Data\n"); - dwc->ep0state = EP0_DATA_PHASE; - - if (dwc->ep0_next_event != DWC3_EP0_NRDY_DATA) { - dev_vdbg(dwc->dev, "Expected %d got %d\n", - dwc->ep0_next_event, - DWC3_EP0_NRDY_DATA); - - dwc3_ep0_stall_and_restart(dwc); - return; - } - /* - * One of the possible error cases is when Host _does_ - * request for Data Phase, but it does so on the wrong - * direction. + * We already have a DATA transfer in the controller's cache, + * if we receive a XferNotReady(DATA) we will ignore it, unless + * it's for the wrong direction. * - * Here, we already know ep0_next_event is DATA (see above), - * so we only need to check for direction. + * In that case, we must issue END_TRANSFER command to the Data + * Phase we already have started and issue SetStall on the + * control endpoint. */ if (dwc->ep0_expect_in != event->endpoint_number) { + struct dwc3_ep *dep = dwc->eps[dwc->ep0_expect_in]; + dev_vdbg(dwc->dev, "Wrong direction for Data phase\n"); + dwc3_ep0_end_control_data(dwc, dep); dwc3_ep0_stall_and_restart(dwc); return; } - dwc3_ep0_do_control_data(dwc, event); break; case DEPEVT_STATUS_CONTROL_STATUS: -- cgit v0.10.2 From 7125d584d20ba7624488ddefa84b17ea6ce558f1 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 19 Jul 2012 21:05:08 +0300 Subject: usb: dwc3: ep0: fix status phase delayed status direction commit 68d3e66 (usb: dwc3: ep0: fix for possible early delayed_status) added handling for early delayed status, but the current code only works because so far delayed status will always be on the IN direction. This patch makes the code more robust by making sure that we can handle all directions properly. Signed-off-by: Felipe Balbi diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 3936c64..3f2c698 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -164,10 +164,13 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep, * handle it here. */ if (dwc->delayed_status) { + unsigned direction; + + direction = !dwc->ep0_expect_in; dwc->delayed_status = false; if (dwc->ep0state == EP0_STATUS_PHASE) - __dwc3_ep0_do_control_status(dwc, dwc->eps[1]); + __dwc3_ep0_do_control_status(dwc, dwc->eps[direction]); else dev_dbg(dwc->dev, "too early for delayed status\n"); -- cgit v0.10.2 From 2dfe37d4a5f9a7586a7ff79249492fb8280afb6f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Mon, 23 Jul 2012 09:07:41 +0300 Subject: usb: dwc3: ep0: make sure to reinitilize ep1 on STALL When issuing SetStall on ep0, we must make sure to reinitialize all flags on physical ep1 too. Signed-off-by: Felipe Balbi diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index 3f2c698..1bba97b 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c @@ -262,9 +262,14 @@ out: static void dwc3_ep0_stall_and_restart(struct dwc3 *dwc) { - struct dwc3_ep *dep = dwc->eps[0]; + struct dwc3_ep *dep; + + /* reinitialize physical ep1 */ + dep = dwc->eps[1]; + dep->flags = DWC3_EP_ENABLED; /* stall is always issued on EP0 */ + dep = dwc->eps[0]; __dwc3_gadget_ep_set_halt(dep, 1); dep->flags = DWC3_EP_ENABLED; dwc->delayed_status = false; -- cgit v0.10.2 From f0443afd1d82b07305df1511a6055311047fdfc6 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Mon, 16 Jul 2012 23:25:04 +0400 Subject: usb: musb: gadget: use variables according to their names in rxstate() In rxstate(), improper types are given to 'fifo_count' and 'len' variables, and these variables are not used in accordance to their names (up to the certain point), i.e. 'len' to hold the size of a packet in the RX FIFO, and 'fifo_count' to hold a difference between 'request->length' and 'request->actual'... Interchange the variables up to the point where their use starts to make sense again. Signed-off-by: Sergei Shtylyov Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index f7194cf..49d7bee 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -644,8 +644,8 @@ static void rxstate(struct musb *musb, struct musb_request *req) struct usb_request *request = &req->request; struct musb_ep *musb_ep; void __iomem *epio = musb->endpoints[epnum].regs; - unsigned fifo_count = 0; - u16 len; + unsigned len = 0; + u16 fifo_count; u16 csr = musb_readw(epio, MUSB_RXCSR); struct musb_hw_ep *hw_ep = &musb->endpoints[epnum]; u8 use_mode_1; @@ -655,7 +655,7 @@ static void rxstate(struct musb *musb, struct musb_request *req) else musb_ep = &hw_ep->ep_out; - len = musb_ep->packet_sz; + fifo_count = musb_ep->packet_sz; /* Check if EP is disabled */ if (!musb_ep->desc) { @@ -704,7 +704,7 @@ static void rxstate(struct musb *musb, struct musb_request *req) } if (csr & MUSB_RXCSR_RXPKTRDY) { - len = musb_readw(epio, MUSB_RXCOUNT); + fifo_count = musb_readw(epio, MUSB_RXCOUNT); /* * Enable Mode 1 on RX transfers only when short_not_ok flag @@ -712,7 +712,7 @@ static void rxstate(struct musb *musb, struct musb_request *req) * file_storage and f_mass_storage drivers */ - if (request->short_not_ok && len == musb_ep->packet_sz) + if (request->short_not_ok && fifo_count == musb_ep->packet_sz) use_mode_1 = 1; else use_mode_1 = 0; @@ -780,7 +780,7 @@ static void rxstate(struct musb *musb, struct musb_request *req) musb_ep->dma->desired_mode = 1; } else { transfer_size = min(request->length - request->actual, - (unsigned)len); + (unsigned)fifo_count); musb_ep->dma->desired_mode = 0; } @@ -808,8 +808,8 @@ static void rxstate(struct musb *musb, struct musb_request *req) channel = musb_ep->dma; /* In case first packet is short */ - if (len < musb_ep->packet_sz) - transfer_size = len; + if (fifo_count < musb_ep->packet_sz) + transfer_size = fifo_count; else if (request->short_not_ok) transfer_size = min(request->length - request->actual, @@ -817,7 +817,7 @@ static void rxstate(struct musb *musb, struct musb_request *req) else transfer_size = min(request->length - request->actual, - (unsigned)len); + (unsigned)fifo_count); csr &= ~MUSB_RXCSR_DMAMODE; csr |= (MUSB_RXCSR_DMAENAB | @@ -845,10 +845,10 @@ static void rxstate(struct musb *musb, struct musb_request *req) } #endif /* Mentor's DMA */ - fifo_count = request->length - request->actual; + len = request->length - request->actual; dev_dbg(musb->controller, "%s OUT/RX pio fifo %d/%d, maxpacket %d\n", musb_ep->end_point.name, - len, fifo_count, + fifo_count, len, musb_ep->packet_sz); fifo_count = min_t(unsigned, len, fifo_count); @@ -901,7 +901,8 @@ static void rxstate(struct musb *musb, struct musb_request *req) } /* reach the end or short packet detected */ - if (request->actual == request->length || len < musb_ep->packet_sz) + if (request->actual == request->length || + fifo_count < musb_ep->packet_sz) musb_g_giveback(musb_ep, request, 0); } -- cgit v0.10.2 From 3132122c664dd9361e2179e8a388d87ca89ace6c Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Fri, 20 Jul 2012 11:07:22 +0530 Subject: usb: musb: host: don't program dma for zero byte tx This is to reduce the overhead of dma programming for zero byte transmit as same can be done using pio mode. Signed-off-by: Ajay Kumar Gupta Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 4bb717d..29b5149 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -693,6 +693,8 @@ static void musb_ep_program(struct musb *musb, u8 epnum, void __iomem *epio = hw_ep->regs; struct musb_qh *qh = musb_ep_get_qh(hw_ep, !is_out); u16 packet_sz = qh->maxpacket; + u8 use_dma = 1; + u16 csr; dev_dbg(musb->controller, "%s hw%d urb %p spd%d dev%d ep%d%s " "h_addr%02x h_port%02x bytes %d\n", @@ -704,9 +706,17 @@ static void musb_ep_program(struct musb *musb, u8 epnum, musb_ep_select(mbase, epnum); + if (is_out && !len) { + use_dma = 0; + csr = musb_readw(epio, MUSB_TXCSR); + csr &= ~MUSB_TXCSR_DMAENAB; + musb_writew(epio, MUSB_TXCSR, csr); + hw_ep->tx_channel = NULL; + } + /* candidate for DMA? */ dma_controller = musb->dma_controller; - if (is_dma_capable() && epnum && dma_controller) { + if (use_dma && is_dma_capable() && epnum && dma_controller) { dma_channel = is_out ? hw_ep->tx_channel : hw_ep->rx_channel; if (!dma_channel) { dma_channel = dma_controller->channel_alloc( -- cgit v0.10.2 From d17d535fec07dbd298b3f65838ec8d63c26ab360 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Fri, 20 Jul 2012 11:07:23 +0530 Subject: usb: musb: gadget: don't program dma for zero byte tx This is to reduce the overhead of dma programming for zero byte transmit as same can be done using pio mode. Signed-off-by: Ajay Kumar Gupta Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 49d7bee..8d2cce1 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -373,7 +373,7 @@ static void txstate(struct musb *musb, struct musb_request *req) request_size = min_t(size_t, request->length - request->actual, musb_ep->dma->max_len); - use_dma = (request->dma != DMA_ADDR_INVALID); + use_dma = (request->dma != DMA_ADDR_INVALID && request_size); /* MUSB_TXCSR_P_ISO is still set correctly */ -- cgit v0.10.2 From 603fe2b21d9fcde2022f9b52d95027bea29fe9e3 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Fri, 20 Jul 2012 11:07:24 +0530 Subject: usb: musb: check for zero byte in musb_read/write_fifo Added a check in musb_{read | write}_fifo for zero byte length. Signed-off-by: Ajay Kumar Gupta Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 26f1bef..69711e4 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -234,6 +234,9 @@ void musb_write_fifo(struct musb_hw_ep *hw_ep, u16 len, const u8 *src) struct musb *musb = hw_ep->musb; void __iomem *fifo = hw_ep->fifo; + if (unlikely(len == 0)) + return; + prefetch((u8 *)src); dev_dbg(musb->controller, "%cX ep%d fifo %p count %d buf %p\n", @@ -276,6 +279,9 @@ void musb_read_fifo(struct musb_hw_ep *hw_ep, u16 len, u8 *dst) struct musb *musb = hw_ep->musb; void __iomem *fifo = hw_ep->fifo; + if (unlikely(len == 0)) + return; + dev_dbg(musb->controller, "%cX ep%d fifo %p count %d buf %p\n", 'R', hw_ep->epnum, fifo, len, dst); -- cgit v0.10.2 From f283862f3b5cb1f3dde37b9d21007b299c083e66 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Thu, 19 Jul 2012 13:41:59 +0530 Subject: usb: musb: NAK timeout scheme on bulk TX endpoint Fixes endpoint starvation issue when more than one bulk QH is multiplexed on the reserved bulk TX endpoint. This patch sets the NAK timeout interval for such QHs, and when a timeout triggers the next QH will be scheduled. This scheme doesn't work for devices which are connected to a high to full speed tree (transaction translator) as there is no NAK timeout interrupt from the musb controller from such devices. Signed-off-by: Ajay Kumar Gupta Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 29b5149..2f6f9a8 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -892,6 +892,73 @@ static void musb_ep_program(struct musb *musb, u8 epnum, } } +/* Schedule next QH from musb->in_bulk/out_bulk and move the current qh to + * the end; avoids starvation for other endpoints. + */ +static void musb_bulk_nak_timeout(struct musb *musb, struct musb_hw_ep *ep, + int is_in) +{ + struct dma_channel *dma; + struct urb *urb; + void __iomem *mbase = musb->mregs; + void __iomem *epio = ep->regs; + struct musb_qh *cur_qh, *next_qh; + u16 rx_csr, tx_csr; + + musb_ep_select(mbase, ep->epnum); + if (is_in) { + dma = is_dma_capable() ? ep->rx_channel : NULL; + + /* clear nak timeout bit */ + rx_csr = musb_readw(epio, MUSB_RXCSR); + rx_csr |= MUSB_RXCSR_H_WZC_BITS; + rx_csr &= ~MUSB_RXCSR_DATAERROR; + musb_writew(epio, MUSB_RXCSR, rx_csr); + + cur_qh = first_qh(&musb->in_bulk); + } else { + dma = is_dma_capable() ? ep->tx_channel : NULL; + + /* clear nak timeout bit */ + tx_csr = musb_readw(epio, MUSB_TXCSR); + tx_csr |= MUSB_TXCSR_H_WZC_BITS; + tx_csr &= ~MUSB_TXCSR_H_NAKTIMEOUT; + musb_writew(epio, MUSB_TXCSR, tx_csr); + + cur_qh = first_qh(&musb->out_bulk); + } + if (cur_qh) { + urb = next_urb(cur_qh); + if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { + dma->status = MUSB_DMA_STATUS_CORE_ABORT; + musb->dma_controller->channel_abort(dma); + urb->actual_length += dma->actual_len; + dma->actual_len = 0L; + } + musb_save_toggle(cur_qh, is_in, urb); + + if (is_in) { + /* move cur_qh to end of queue */ + list_move_tail(&cur_qh->ring, &musb->in_bulk); + + /* get the next qh from musb->in_bulk */ + next_qh = first_qh(&musb->in_bulk); + + /* set rx_reinit and schedule the next qh */ + ep->rx_reinit = 1; + } else { + /* move cur_qh to end of queue */ + list_move_tail(&cur_qh->ring, &musb->out_bulk); + + /* get the next qh from musb->out_bulk */ + next_qh = first_qh(&musb->out_bulk); + + /* set tx_reinit and schedule the next qh */ + ep->tx_reinit = 1; + } + musb_start_urb(musb, is_in, next_qh); + } +} /* * Service the default endpoint (ep0) as host. @@ -1156,21 +1223,28 @@ void musb_host_tx(struct musb *musb, u8 epnum) status = -ETIMEDOUT; } else if (tx_csr & MUSB_TXCSR_H_NAKTIMEOUT) { - dev_dbg(musb->controller, "TX end=%d device not responding\n", epnum); - - /* NOTE: this code path would be a good place to PAUSE a - * transfer, if there's some other (nonperiodic) tx urb - * that could use this fifo. (dma complicates it...) - * That's already done for bulk RX transfers. - * - * if (bulk && qh->ring.next != &musb->out_bulk), then - * we have a candidate... NAKing is *NOT* an error - */ - musb_ep_select(mbase, epnum); - musb_writew(epio, MUSB_TXCSR, - MUSB_TXCSR_H_WZC_BITS - | MUSB_TXCSR_TXPKTRDY); - return; + if (USB_ENDPOINT_XFER_BULK == qh->type && qh->mux == 1 + && !list_is_singular(&musb->out_bulk)) { + dev_dbg(musb->controller, + "NAK timeout on TX%d ep\n", epnum); + musb_bulk_nak_timeout(musb, hw_ep, 0); + } else { + dev_dbg(musb->controller, + "TX end=%d device not responding\n", epnum); + /* NOTE: this code path would be a good place to PAUSE a + * transfer, if there's some other (nonperiodic) tx urb + * that could use this fifo. (dma complicates it...) + * That's already done for bulk RX transfers. + * + * if (bulk && qh->ring.next != &musb->out_bulk), then + * we have a candidate... NAKing is *NOT* an error + */ + musb_ep_select(mbase, epnum); + musb_writew(epio, MUSB_TXCSR, + MUSB_TXCSR_H_WZC_BITS + | MUSB_TXCSR_TXPKTRDY); + } + return; } if (status) { @@ -1390,50 +1464,6 @@ void musb_host_tx(struct musb *musb, u8 epnum) #endif -/* Schedule next QH from musb->in_bulk and move the current qh to - * the end; avoids starvation for other endpoints. - */ -static void musb_bulk_rx_nak_timeout(struct musb *musb, struct musb_hw_ep *ep) -{ - struct dma_channel *dma; - struct urb *urb; - void __iomem *mbase = musb->mregs; - void __iomem *epio = ep->regs; - struct musb_qh *cur_qh, *next_qh; - u16 rx_csr; - - musb_ep_select(mbase, ep->epnum); - dma = is_dma_capable() ? ep->rx_channel : NULL; - - /* clear nak timeout bit */ - rx_csr = musb_readw(epio, MUSB_RXCSR); - rx_csr |= MUSB_RXCSR_H_WZC_BITS; - rx_csr &= ~MUSB_RXCSR_DATAERROR; - musb_writew(epio, MUSB_RXCSR, rx_csr); - - cur_qh = first_qh(&musb->in_bulk); - if (cur_qh) { - urb = next_urb(cur_qh); - if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { - dma->status = MUSB_DMA_STATUS_CORE_ABORT; - musb->dma_controller->channel_abort(dma); - urb->actual_length += dma->actual_len; - dma->actual_len = 0L; - } - musb_save_toggle(cur_qh, 1, urb); - - /* move cur_qh to end of queue */ - list_move_tail(&cur_qh->ring, &musb->in_bulk); - - /* get the next qh from musb->in_bulk */ - next_qh = first_qh(&musb->in_bulk); - - /* set rx_reinit and schedule the next qh */ - ep->rx_reinit = 1; - musb_start_urb(musb, 1, next_qh); - } -} - /* * Service an RX interrupt for the given IN endpoint; docs cover bulk, iso, * and high-bandwidth IN transfer cases. @@ -1510,7 +1540,7 @@ void musb_host_rx(struct musb *musb, u8 epnum) if (usb_pipebulk(urb->pipe) && qh->mux == 1 && !list_is_singular(&musb->in_bulk)) { - musb_bulk_rx_nak_timeout(musb, hw_ep); + musb_bulk_nak_timeout(musb, hw_ep, 1); return; } musb_ep_select(mbase, epnum); @@ -1873,14 +1903,14 @@ static int musb_schedule( else head = &musb->out_bulk; - /* Enable bulk RX NAK timeout scheme when bulk requests are + /* Enable bulk RX/TX NAK timeout scheme when bulk requests are * multiplexed. This scheme doen't work in high speed to full * speed scenario as NAK interrupts are not coming from a * full speed device connected to a high speed device. * NAK timeout interval is 8 (128 uframe or 16ms) for HS and * 4 (8 frame or 8ms) for FS device. */ - if (is_in && qh->dev) + if (qh->dev) qh->intv_reg = (USB_SPEED_HIGH == qh->dev->speed) ? 8 : 4; goto success; -- cgit v0.10.2 From 78c289f8769aaefcc52d26ca53c8b2ee545fb332 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 19 Jul 2012 13:32:15 +0300 Subject: usb: xceiv: create nop-usb-xceiv.h and avoid pollution on otg.h nop-usb-xceiv was polluting otg.h with its own function prototypes. Move those prototypes to a nop-usb-xceiv.h header. Signed-off-by: Felipe Balbi diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c index ef230a0..9894e3d 100644 --- a/arch/arm/mach-omap2/board-omap3evm.c +++ b/arch/arm/mach-omap2/board-omap3evm.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c index 7a95ab8..5d64c5b 100644 --- a/drivers/usb/musb/am35x.c +++ b/drivers/usb/musb/am35x.c @@ -33,6 +33,7 @@ #include #include #include +#include #include diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index 428e6aa..b562623 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -19,6 +19,7 @@ #include #include #include +#include #include diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c index 0f9fcec..16798c9 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 472c8b4..863a9b6 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 217808d..4e899bb 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 1a1bd9c..00f21df 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "musb_core.h" diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c index 803f958..3c3ad6b 100644 --- a/drivers/usb/otg/nop-usb-xceiv.c +++ b/drivers/usb/otg/nop-usb-xceiv.c @@ -30,6 +30,7 @@ #include #include #include +#include #include struct nop_usb_xceiv { diff --git a/include/linux/usb/nop-usb-xceiv.h b/include/linux/usb/nop-usb-xceiv.h new file mode 100644 index 0000000..ecc7562 --- /dev/null +++ b/include/linux/usb/nop-usb-xceiv.h @@ -0,0 +1,18 @@ +#ifndef __LINUX_USB_NOP_XCEIV_H +#define __LINUX_USB_NOP_XCEIV_H + +#if defined(CONFIG_NOP_USB_XCEIV) || (defined(CONFIG_NOP_USB_XCEIV_MODULE) && defined(MODULE)) +/* sometimes transceivers are accessed only through e.g. ULPI */ +extern void usb_nop_xceiv_register(void); +extern void usb_nop_xceiv_unregister(void); +#else +static inline void usb_nop_xceiv_register(void) +{ +} + +static inline void usb_nop_xceiv_unregister(void) +{ +} +#endif + +#endif /* __LINUX_USB_NOP_XCEIV_H */ diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h index 45824be..16dc520d 100644 --- a/include/linux/usb/otg.h +++ b/include/linux/usb/otg.h @@ -138,20 +138,6 @@ struct usb_phy { extern int usb_add_phy(struct usb_phy *, enum usb_phy_type type); extern void usb_remove_phy(struct usb_phy *); -#if defined(CONFIG_NOP_USB_XCEIV) || (defined(CONFIG_NOP_USB_XCEIV_MODULE) && defined(MODULE)) -/* sometimes transceivers are accessed only through e.g. ULPI */ -extern void usb_nop_xceiv_register(void); -extern void usb_nop_xceiv_unregister(void); -#else -static inline void usb_nop_xceiv_register(void) -{ -} - -static inline void usb_nop_xceiv_unregister(void) -{ -} -#endif - /* helpers for direct access thru low-level io interface */ static inline int usb_phy_io_read(struct usb_phy *x, u32 reg) { -- cgit v0.10.2 From c84d364f8178d2bc12827836bf58eb45598262a4 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 19 Jul 2012 13:38:06 +0300 Subject: usb: xceiv: nop: let it work as USB2 and USB3 phy We add a platform_data to pass the desired mode for the nop-xceiv so it can work on USB2 and USB3 modes. Signed-off-by: Felipe Balbi diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c index 3c3ad6b..e52e35e 100644 --- a/drivers/usb/otg/nop-usb-xceiv.c +++ b/drivers/usb/otg/nop-usb-xceiv.c @@ -95,7 +95,9 @@ static int nop_set_host(struct usb_otg *otg, struct usb_bus *host) static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev) { + struct nop_usb_xceiv_platform_data *pdata = pdev->dev.platform_data; struct nop_usb_xceiv *nop; + enum usb_phy_type type = USB_PHY_TYPE_USB2; int err; nop = kzalloc(sizeof *nop, GFP_KERNEL); @@ -108,6 +110,9 @@ static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev) return -ENOMEM; } + if (pdata) + type = pdata->type; + nop->dev = &pdev->dev; nop->phy.dev = nop->dev; nop->phy.label = "nop-xceiv"; @@ -118,7 +123,7 @@ static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev) nop->phy.otg->set_host = nop_set_host; nop->phy.otg->set_peripheral = nop_set_peripheral; - err = usb_add_phy(&nop->phy, USB_PHY_TYPE_USB2); + err = usb_add_phy(&nop->phy, type); if (err) { dev_err(&pdev->dev, "can't register transceiver, err: %d\n", err); diff --git a/include/linux/usb/nop-usb-xceiv.h b/include/linux/usb/nop-usb-xceiv.h index ecc7562..28884c7 100644 --- a/include/linux/usb/nop-usb-xceiv.h +++ b/include/linux/usb/nop-usb-xceiv.h @@ -1,6 +1,12 @@ #ifndef __LINUX_USB_NOP_XCEIV_H #define __LINUX_USB_NOP_XCEIV_H +#include + +struct nop_usb_xceiv_platform_data { + enum usb_phy_type type; +}; + #if defined(CONFIG_NOP_USB_XCEIV) || (defined(CONFIG_NOP_USB_XCEIV_MODULE) && defined(MODULE)) /* sometimes transceivers are accessed only through e.g. ULPI */ extern void usb_nop_xceiv_register(void); -- cgit v0.10.2 From f039df580a518df49abff35fec970268bc3c51e3 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Thu, 2 Aug 2012 15:30:07 +0530 Subject: usb: musb: cleanup while removing musb omap glue driver No functional change. Just replaced the call to platform_device_del and platform_device_put with platform_device_unregister. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 5fdb9da..392fc7a 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -509,8 +509,7 @@ static int __devexit omap2430_remove(struct platform_device *pdev) struct omap2430_glue *glue = platform_get_drvdata(pdev); cancel_work_sync(&glue->omap_musb_mailbox_work); - platform_device_del(glue->musb); - platform_device_put(glue->musb); + platform_device_unregister(glue->musb); return 0; } -- cgit v0.10.2 From 348e026fafe2501281db5fb7fed599b337cad358 Mon Sep 17 00:00:00 2001 From: Moiz Sonasath Date: Wed, 1 Aug 2012 14:08:30 -0500 Subject: usb: dwc3: gadget: Fix sparse warnings This patch fixes the following sparse warnings: drivers/usb/dwc3/gadget.c:1096:7: warning: symbol 'ret' shadows an earlier one drivers/usb/dwc3/gadget.c:1058:8: originally declared here drivers/usb/dwc3/gadget.c:1100:16: warning: symbol 'dwc' shadows an earlier one drivers/usb/dwc3/gadget.c:1057:15: originally declared here drivers/usb/dwc3/gadget.c:1118:16: warning: symbol 'dwc' shadows an earlier one drivers/usb/dwc3/gadget.c:1057:15: originally declared here drivers/usb/dwc3/gadget.c:1800:19: warning: symbol 'dep' shadows an earlier one drivers/usb/dwc3/gadget.c:1778:18: originally declared here Also, fix the potential checkpatch errors around the if() loops that this fix patch can create. Signed-off-by: Moiz Sonasath Signed-off-by: Felipe Balbi diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 283c0cb..920d997 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1092,15 +1092,10 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) * */ if (dep->flags & DWC3_EP_PENDING_REQUEST) { - int ret; - ret = __dwc3_gadget_kick_transfer(dep, 0, true); - if (ret && ret != -EBUSY) { - struct dwc3 *dwc = dep->dwc; - + if (ret && ret != -EBUSY) dev_dbg(dwc->dev, "%s: failed to kick transfers\n", dep->name); - } } /* @@ -1113,12 +1108,9 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) WARN_ON_ONCE(!dep->resource_index); ret = __dwc3_gadget_kick_transfer(dep, dep->resource_index, false); - if (ret && ret != -EBUSY) { - struct dwc3 *dwc = dep->dwc; - + if (ret && ret != -EBUSY) dev_dbg(dwc->dev, "%s: failed to kick transfers\n", dep->name); - } } /* @@ -1755,7 +1747,7 @@ static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc, int i; for (i = 0; i < DWC3_ENDPOINTS_NUM; i++) { - struct dwc3_ep *dep = dwc->eps[i]; + dep = dwc->eps[i]; if (!(dep->flags & DWC3_EP_ENABLED)) continue; -- cgit v0.10.2 From a156544bc90e82d61bd7c25e6258e4da32256bea Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 7 Aug 2012 14:00:50 +0300 Subject: usb: musb: fix sparse warnings The following warnings are fixed: drivers/usb/musb/musb_core.c:357:6: warning: symbol 'musb_otg_timer_func' was not declared. Should it be static? drivers/usb/musb/musb_core.c:1339:27: warning: incorrect type in initializer (different address spaces) drivers/usb/musb/musb_core.c:1339:27: expected void *mbase drivers/usb/musb/musb_core.c:1339:27: got void [noderef] *mregs drivers/usb/musb/musb_core.c:1347:17: warning: incorrect type in argument 1 (different address spaces) drivers/usb/musb/musb_core.c:1347:17: expected void [noderef] *addr drivers/usb/musb/musb_core.c:1347:17: got void *mbase drivers/usb/musb/musb_core.h:487:27: warning: incorrect type in initializer (different address spaces) drivers/usb/musb/musb_core.h:487:27: expected void *mbase drivers/usb/musb/musb_core.h:487:27: got void [noderef] *mregs drivers/usb/musb/musb_core.h:491:26: warning: incorrect type in argument 1 (different address spaces) drivers/usb/musb/musb_core.h:491:26: expected void const [noderef] *addr drivers/usb/musb/musb_core.h:491:26: got void *mbase drivers/usb/musb/tusb6010.c:270:48: warning: incorrect type in argument 2 (different address spaces) drivers/usb/musb/tusb6010.c:270:48: expected void [noderef] *buf drivers/usb/musb/tusb6010.c:270:48: got unsigned char [usertype] *[assigned] buf drivers/usb/musb/tusb6010.c:164:32: warning: incorrect type in argument 1 (different address spaces) drivers/usb/musb/tusb6010.c:164:32: expected void *to drivers/usb/musb/tusb6010.c:164:32: got void [noderef] *buf drivers/usb/musb/tusb6010.c:172:24: warning: incorrect type in argument 1 (different address spaces) drivers/usb/musb/tusb6010.c:172:24: expected void *to drivers/usb/musb/tusb6010.c:172:24: got void [noderef] *[assigned] buf Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 69711e4..9bc4feab 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -354,7 +354,7 @@ void musb_load_testpacket(struct musb *musb) /* * Handles OTG hnp timeouts, such as b_ase0_brst */ -void musb_otg_timer_func(unsigned long data) +static void musb_otg_timer_func(unsigned long data) { struct musb *musb = (struct musb *)data; unsigned long flags; @@ -1336,7 +1336,7 @@ static int __devinit ep_config_from_hw(struct musb *musb) { u8 epnum = 0; struct musb_hw_ep *hw_ep; - void *mbase = musb->mregs; + void __iomem *mbase = musb->mregs; int ret = 0; dev_dbg(musb->controller, "<== static silicon ep config\n"); diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 586105b..8bb324d 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -484,7 +484,7 @@ static inline void musb_configure_ep0(struct musb *musb) static inline int musb_read_fifosize(struct musb *musb, struct musb_hw_ep *hw_ep, u8 epnum) { - void *mbase = musb->mregs; + void __iomem *mbase = musb->mregs; u8 reg = 0; /* read from core using indexed model */ diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 1a1bd9c..4073a6f 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -153,7 +153,7 @@ tusb_fifo_write_unaligned(void __iomem *fifo, const u8 *buf, u16 len) } static inline void tusb_fifo_read_unaligned(void __iomem *fifo, - void __iomem *buf, u16 len) + void *buf, u16 len) { u32 val; int i; -- cgit v0.10.2 From decadacbd7259b1dce0aeb9cb4468432edf88fb4 Mon Sep 17 00:00:00 2001 From: Brian Downing Date: Sat, 4 Aug 2012 18:32:19 -0500 Subject: usb: musb: Fix bad call to kfree() in musb_free Commit 622859634a663c5e55d0e2a2cdbb55ac058d97b3 (usb: musb: drop a gigantic amount of ifdeferry) included this change: @@ -1901,11 +1844,7 @@ static void musb_free(struct musb *musb) dma_controller_destroy(c); } -#ifdef CONFIG_USB_MUSB_HDRC_HCD - usb_put_hcd(musb_to_hcd(musb)); -#else kfree(musb); -#endif } /* Since musb comes from struct usb_hcd's hcd_priv, which is allocated on the end of that struct, kfree'ing it is not going to work. Replace kfree(musb) with usb_put_hcd(musb_to_hcd(musb)), which appears to be the right thing to do here. Signed-off-by: Brian Downing Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 9bc4feab..65b3f53 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1868,7 +1868,7 @@ static void musb_free(struct musb *musb) dma_controller_destroy(c); } - kfree(musb); + usb_put_hcd(musb_to_hcd(musb)); } /* -- cgit v0.10.2 From 8e8a55165469c99af0c24a276d997f9473dc89ab Mon Sep 17 00:00:00 2001 From: Virupax Sadashivpetimath Date: Tue, 7 Aug 2012 14:46:20 +0530 Subject: usb: musb: host: Handle highmem in PIO mode In case of USB bulk transfer, when himem page is received, the usb_sg_init function sets the urb transfer buffer to NULL. When such URB transfer is handled, kernel crashes in PIO mode. Handle this by mapping the highmem buffer in PIO mode. Signed-off-by: Virupax Sadashivpetimath Signed-off-by: Praveena NADAHALLY Acked-by: Linus Walleij Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 2f6f9a8..d385e8a 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -823,9 +823,28 @@ static void musb_ep_program(struct musb *musb, u8 epnum, if (load_count) { /* PIO to load FIFO */ qh->segsize = load_count; - musb_write_fifo(hw_ep, load_count, buf); + if (!buf) { + sg_miter_start(&qh->sg_miter, urb->sg, 1, + SG_MITER_ATOMIC + | SG_MITER_FROM_SG); + if (!sg_miter_next(&qh->sg_miter)) { + dev_err(musb->controller, + "error: sg" + "list empty\n"); + sg_miter_stop(&qh->sg_miter); + goto finish; + } + buf = qh->sg_miter.addr + urb->sg->offset + + urb->actual_length; + load_count = min_t(u32, load_count, + qh->sg_miter.length); + musb_write_fifo(hw_ep, load_count, buf); + qh->sg_miter.consumed = load_count; + sg_miter_stop(&qh->sg_miter); + } else + musb_write_fifo(hw_ep, load_count, buf); } - +finish: /* re-enable interrupt */ musb_writew(mbase, MUSB_INTRTXE, int_txe); @@ -1193,6 +1212,7 @@ void musb_host_tx(struct musb *musb, u8 epnum) void __iomem *mbase = musb->mregs; struct dma_channel *dma; bool transfer_pending = false; + static bool use_sg; musb_ep_select(mbase, epnum); tx_csr = musb_readw(epio, MUSB_TXCSR); @@ -1247,6 +1267,7 @@ void musb_host_tx(struct musb *musb, u8 epnum) return; } +done: if (status) { if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { dma->status = MUSB_DMA_STATUS_CORE_ABORT; @@ -1416,9 +1437,38 @@ void musb_host_tx(struct musb *musb, u8 epnum) length = qh->maxpacket; /* Unmap the buffer so that CPU can use it */ usb_hcd_unmap_urb_for_dma(musb_to_hcd(musb), urb); - musb_write_fifo(hw_ep, length, urb->transfer_buffer + offset); + + /* + * We need to map sg if the transfer_buffer is + * NULL. + */ + if (!urb->transfer_buffer) + use_sg = true; + + if (use_sg) { + /* sg_miter_start is already done in musb_ep_program */ + if (!sg_miter_next(&qh->sg_miter)) { + dev_err(musb->controller, "error: sg list empty\n"); + sg_miter_stop(&qh->sg_miter); + status = -EINVAL; + goto done; + } + urb->transfer_buffer = qh->sg_miter.addr; + length = min_t(u32, length, qh->sg_miter.length); + musb_write_fifo(hw_ep, length, urb->transfer_buffer); + qh->sg_miter.consumed = length; + sg_miter_stop(&qh->sg_miter); + } else { + musb_write_fifo(hw_ep, length, urb->transfer_buffer + offset); + } + qh->segsize = length; + if (use_sg) { + if (offset + length >= urb->transfer_buffer_length) + use_sg = false; + } + musb_ep_select(mbase, epnum); musb_writew(epio, MUSB_TXCSR, MUSB_TXCSR_H_WZC_BITS | MUSB_TXCSR_TXPKTRDY); @@ -1482,6 +1532,8 @@ void musb_host_rx(struct musb *musb, u8 epnum) bool done = false; u32 status; struct dma_channel *dma; + static bool use_sg; + unsigned int sg_flags = SG_MITER_ATOMIC | SG_MITER_TO_SG; musb_ep_select(mbase, epnum); @@ -1796,10 +1848,43 @@ void musb_host_rx(struct musb *musb, u8 epnum) #endif /* Mentor DMA */ if (!dma) { + unsigned int received_len; + /* Unmap the buffer so that CPU can use it */ usb_hcd_unmap_urb_for_dma(musb_to_hcd(musb), urb); - done = musb_host_packet_rx(musb, urb, - epnum, iso_err); + + /* + * We need to map sg if the transfer_buffer is + * NULL. + */ + if (!urb->transfer_buffer) { + use_sg = true; + sg_miter_start(&qh->sg_miter, urb->sg, 1, + sg_flags); + } + + if (use_sg) { + if (!sg_miter_next(&qh->sg_miter)) { + dev_err(musb->controller, "error: sg list empty\n"); + sg_miter_stop(&qh->sg_miter); + status = -EINVAL; + done = true; + goto finish; + } + urb->transfer_buffer = qh->sg_miter.addr; + received_len = urb->actual_length; + qh->offset = 0x0; + done = musb_host_packet_rx(musb, urb, epnum, + iso_err); + /* Calculate the number of bytes received */ + received_len = urb->actual_length - + received_len; + qh->sg_miter.consumed = received_len; + sg_miter_stop(&qh->sg_miter); + } else { + done = musb_host_packet_rx(musb, urb, + epnum, iso_err); + } dev_dbg(musb->controller, "read %spacket\n", done ? "last " : ""); } } @@ -1808,6 +1893,9 @@ finish: urb->actual_length += xfer_len; qh->offset += xfer_len; if (done) { + if (use_sg) + use_sg = false; + if (urb->status == -EINPROGRESS) urb->status = status; musb_advance_schedule(musb, urb, hw_ep, USB_DIR_IN); diff --git a/drivers/usb/musb/musb_host.h b/drivers/usb/musb/musb_host.h index 622d09f..5a9c8fe 100644 --- a/drivers/usb/musb/musb_host.h +++ b/drivers/usb/musb/musb_host.h @@ -35,6 +35,8 @@ #ifndef _MUSB_HOST_H #define _MUSB_HOST_H +#include + static inline struct usb_hcd *musb_to_hcd(struct musb *musb) { return container_of((void *) musb, struct usb_hcd, hcd_priv); @@ -71,6 +73,7 @@ struct musb_qh { u16 maxpacket; u16 frame; /* for periodic schedule */ unsigned iso_idx; /* in urb->iso_frame_desc[] */ + struct sg_mapping_iter sg_miter; /* for highmem in PIO mode */ }; /* map from control or bulk queue head to the first qh on that ring */ -- cgit v0.10.2 From 79c9046ec52b5aaa9f055e3d928d676dd37a6f9d Mon Sep 17 00:00:00 2001 From: Pratyush Anand Date: Tue, 7 Aug 2012 16:54:18 +0530 Subject: usb: dwc3: gadget: correct missed isoc when endpoint is busy When MISSED_ISOC is set, BUSY is also set. Since, we are handling MISSED_ISOC as a separate case in third scenario, therefore handle only BUSY but not MISSED_ISOC in second scenario. Signed-off-by: Pratyush Anand Signed-off-by: Felipe Balbi diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 920d997..fc05910 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1104,7 +1104,8 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req) * core may not see the modified TRB(s). */ if (usb_endpoint_xfer_isoc(dep->endpoint.desc) && - (dep->flags & DWC3_EP_BUSY)) { + (dep->flags & DWC3_EP_BUSY) && + !(dep->flags & DWC3_EP_MISSED_ISOC)) { WARN_ON_ONCE(!dep->resource_index); ret = __dwc3_gadget_kick_transfer(dep, dep->resource_index, false); -- cgit v0.10.2 From 4f3e8d263d34e52e75b5adfa14811467d3033d8e Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 7 Aug 2012 16:09:56 +0300 Subject: usb: musb: use DMA mode 1 whenever possible Do not rely on any hints from gadget drivers and use DMA mode 1 whenever we expect data of at least the endpoint's packet size and have not yet received a short packet. The last packet if short is always transferred using DMA mode 0. This patch fixes USB throughput issues in mass storage mode for host to device transfers. Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 8d2cce1..5c4392b 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -707,12 +707,11 @@ static void rxstate(struct musb *musb, struct musb_request *req) fifo_count = musb_readw(epio, MUSB_RXCOUNT); /* - * Enable Mode 1 on RX transfers only when short_not_ok flag - * is set. Currently short_not_ok flag is set only from - * file_storage and f_mass_storage drivers + * use mode 1 only if we expect data of at least ep packet_sz + * and have not yet received a short packet */ - - if (request->short_not_ok && fifo_count == musb_ep->packet_sz) + if ((request->length - request->actual >= musb_ep->packet_sz) && + (fifo_count >= musb_ep->packet_sz)) use_mode_1 = 1; else use_mode_1 = 0; @@ -727,27 +726,6 @@ static void rxstate(struct musb *musb, struct musb_request *req) c = musb->dma_controller; channel = musb_ep->dma; - /* We use DMA Req mode 0 in rx_csr, and DMA controller operates in - * mode 0 only. So we do not get endpoint interrupts due to DMA - * completion. We only get interrupts from DMA controller. - * - * We could operate in DMA mode 1 if we knew the size of the tranfer - * in advance. For mass storage class, request->length = what the host - * sends, so that'd work. But for pretty much everything else, - * request->length is routinely more than what the host sends. For - * most these gadgets, end of is signified either by a short packet, - * or filling the last byte of the buffer. (Sending extra data in - * that last pckate should trigger an overflow fault.) But in mode 1, - * we don't get DMA completion interrupt for short packets. - * - * Theoretically, we could enable DMAReq irq (MUSB_RXCSR_DMAMODE = 1), - * to get endpoint interrupt on every DMA req, but that didn't seem - * to work reliably. - * - * REVISIT an updated g_file_storage can set req->short_not_ok, which - * then becomes usable as a runtime "use mode 1" hint... - */ - /* Experimental: Mode1 works with mass storage use cases */ if (use_mode_1) { csr |= MUSB_RXCSR_AUTOCLEAR; -- cgit v0.10.2 From 032ec49f5351e9cb242b1a1c367d14415043ab95 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Nov 2011 15:46:26 +0200 Subject: usb: musb: drop useless board_mode usage we are compiling the driver always with full OTG capabilities, so that board_mode trick becomes useless. Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c index 7a95ab8..9fbe736 100644 --- a/drivers/usb/musb/am35x.c +++ b/drivers/usb/musb/am35x.c @@ -107,9 +107,8 @@ static void am35x_musb_enable(struct musb *musb) musb_writel(reg_base, CORE_INTR_MASK_SET_REG, AM35X_INTR_USB_MASK); /* Force the DRVVBUS IRQ so we can start polling for ID change. */ - if (is_otg_enabled(musb)) - musb_writel(reg_base, CORE_INTR_SRC_SET_REG, - AM35X_INTR_DRVVBUS << AM35X_INTR_USB_SHIFT); + musb_writel(reg_base, CORE_INTR_SRC_SET_REG, + AM35X_INTR_DRVVBUS << AM35X_INTR_USB_SHIFT); } /* @@ -173,9 +172,6 @@ static void otg_timer(unsigned long _musb) MUSB_INTR_VBUSERROR << AM35X_INTR_USB_SHIFT); break; case OTG_STATE_B_IDLE: - if (!is_peripheral_enabled(musb)) - break; - devctl = musb_readb(mregs, MUSB_DEVCTL); if (devctl & MUSB_DEVCTL_BDEVICE) mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); @@ -192,9 +188,6 @@ static void am35x_musb_try_idle(struct musb *musb, unsigned long timeout) { static unsigned long last_timer; - if (!is_otg_enabled(musb)) - return; - if (timeout == 0) timeout = jiffies + msecs_to_jiffies(3); @@ -271,8 +264,7 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci) u8 devctl = musb_readb(mregs, MUSB_DEVCTL); int err; - err = is_host_enabled(musb) && (musb->int_usb & - MUSB_INTR_VBUSERROR); + err = musb->int_usb & MUSB_INTR_VBUSERROR; if (err) { /* * The Mentor core doesn't debounce VBUS as needed @@ -289,7 +281,7 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci) musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); WARNING("VBUS error workaround (delay coming)\n"); - } else if (is_host_enabled(musb) && drvvbus) { + } else if (drvvbus) { MUSB_HST_MODE(musb); otg->default_a = 1; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; @@ -326,7 +318,7 @@ eoi: } /* Poll for ID change */ - if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE) + if (musb->xceiv->state == OTG_STATE_B_IDLE) mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); spin_unlock_irqrestore(&musb->lock, flags); @@ -369,8 +361,7 @@ static int am35x_musb_init(struct musb *musb) if (IS_ERR_OR_NULL(musb->xceiv)) return -ENODEV; - if (is_host_enabled(musb)) - setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); + setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); /* Reset the musb */ if (data->reset) @@ -400,8 +391,7 @@ static int am35x_musb_exit(struct musb *musb) struct musb_hdrc_platform_data *plat = dev->platform_data; struct omap_musb_board_data *data = plat->board_data; - if (is_host_enabled(musb)) - del_timer_sync(&otg_workaround); + del_timer_sync(&otg_workaround); /* Shutdown the on-chip PHY and its PLL. */ if (data->set_phy_power) diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index 428e6aa..54f1b98 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -184,8 +184,8 @@ static irqreturn_t blackfin_interrupt(int irq, void *__hci) } /* Start sampling ID pin, when plug is removed from MUSB */ - if ((is_otg_enabled(musb) && (musb->xceiv->state == OTG_STATE_B_IDLE - || musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) || + if ((musb->xceiv->state == OTG_STATE_B_IDLE + || musb->xceiv->state == OTG_STATE_A_WAIT_BCON) || (musb->int_usb & MUSB_INTR_DISCONNECT && is_host_active(musb))) { mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); musb->a_wait_bcon = TIMER_DELAY; @@ -228,18 +228,13 @@ static void musb_conn_timer_handler(unsigned long _musb) val = MUSB_INTR_SUSPEND | MUSB_INTR_VBUSERROR; musb_writeb(musb->mregs, MUSB_INTRUSB, val); - if (is_otg_enabled(musb)) - musb->xceiv->state = OTG_STATE_B_IDLE; - else - musb_writeb(musb->mregs, MUSB_POWER, MUSB_POWER_HSENAB); + musb->xceiv->state = OTG_STATE_B_IDLE; } mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); break; case OTG_STATE_B_IDLE: - - if (!is_peripheral_enabled(musb)) - break; - /* Start a new session. It seems that MUSB needs taking + /* + * Start a new session. It seems that MUSB needs taking * some time to recognize the type of the plug inserted? */ val = musb_readw(musb->mregs, MUSB_DEVCTL); @@ -295,10 +290,7 @@ static void musb_conn_timer_handler(unsigned long _musb) static void bfin_musb_enable(struct musb *musb) { - if (!is_otg_enabled(musb) && is_host_enabled(musb)) { - mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); - musb->a_wait_bcon = TIMER_DELAY; - } + /* REVISIT is this really correct ? */ } static void bfin_musb_disable(struct musb *musb) @@ -323,12 +315,6 @@ static int bfin_musb_set_power(struct usb_phy *x, unsigned mA) return 0; } -static void bfin_musb_try_idle(struct musb *musb, unsigned long timeout) -{ - if (!is_otg_enabled(musb) && is_host_enabled(musb)) - mod_timer(&musb_conn_timer, jiffies + TIMER_DELAY); -} - static int bfin_musb_vbus_status(struct musb *musb) { return 0; @@ -424,12 +410,10 @@ static int bfin_musb_init(struct musb *musb) bfin_musb_reg_init(musb); - if (is_host_enabled(musb)) { - setup_timer(&musb_conn_timer, - musb_conn_timer_handler, (unsigned long) musb); - } - if (is_peripheral_enabled(musb)) - musb->xceiv->set_power = bfin_musb_set_power; + setup_timer(&musb_conn_timer, musb_conn_timer_handler, + (unsigned long) musb); + + musb->xceiv->set_power = bfin_musb_set_power; musb->isr = blackfin_interrupt; musb->double_buffer_not_ok = true; @@ -454,7 +438,6 @@ static const struct musb_platform_ops bfin_ops = { .disable = bfin_musb_disable, .set_mode = bfin_musb_set_mode, - .try_idle = bfin_musb_try_idle, .vbus_status = bfin_musb_vbus_status, .set_vbus = bfin_musb_set_vbus, diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c index 0f9fcec..4e4df9d 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c @@ -155,9 +155,8 @@ static void da8xx_musb_enable(struct musb *musb) musb_writel(reg_base, DA8XX_USB_INTR_MASK_SET_REG, mask); /* Force the DRVVBUS IRQ so we can start polling for ID change. */ - if (is_otg_enabled(musb)) - musb_writel(reg_base, DA8XX_USB_INTR_SRC_SET_REG, - DA8XX_INTR_DRVVBUS << DA8XX_INTR_USB_SHIFT); + musb_writel(reg_base, DA8XX_USB_INTR_SRC_SET_REG, + DA8XX_INTR_DRVVBUS << DA8XX_INTR_USB_SHIFT); } /** @@ -231,9 +230,6 @@ static void otg_timer(unsigned long _musb) MUSB_INTR_VBUSERROR << DA8XX_INTR_USB_SHIFT); break; case OTG_STATE_B_IDLE: - if (!is_peripheral_enabled(musb)) - break; - /* * There's no ID-changed IRQ, so we have no good way to tell * when to switch to the A-Default state machine (by setting @@ -263,9 +259,6 @@ static void da8xx_musb_try_idle(struct musb *musb, unsigned long timeout) { static unsigned long last_timer; - if (!is_otg_enabled(musb)) - return; - if (timeout == 0) timeout = jiffies + msecs_to_jiffies(3); @@ -333,8 +326,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) u8 devctl = musb_readb(mregs, MUSB_DEVCTL); int err; - err = is_host_enabled(musb) && (musb->int_usb & - MUSB_INTR_VBUSERROR); + err = musb->int_usb & USB_INTR_VBUSERROR; if (err) { /* * The Mentor core doesn't debounce VBUS as needed @@ -351,7 +343,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); WARNING("VBUS error workaround (delay coming)\n"); - } else if (is_host_enabled(musb) && drvvbus) { + } else if (drvvbus) { MUSB_HST_MODE(musb); otg->default_a = 1; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; @@ -382,7 +374,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) musb_writel(reg_base, DA8XX_USB_END_OF_INTR_REG, 0); /* Poll for ID change */ - if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE) + if (musb->xceiv->state == OTG_STATE_B_IDLE) mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); spin_unlock_irqrestore(&musb->lock, flags); @@ -430,8 +422,7 @@ static int da8xx_musb_init(struct musb *musb) if (IS_ERR_OR_NULL(musb->xceiv)) goto fail; - if (is_host_enabled(musb)) - setup_timer(&otg_workaround, otg_timer, (unsigned long)musb); + setup_timer(&otg_workaround, otg_timer, (unsigned long)musb); /* Reset the controller */ musb_writel(reg_base, DA8XX_USB_CTRL_REG, DA8XX_SOFT_RESET_MASK); @@ -454,8 +445,7 @@ fail: static int da8xx_musb_exit(struct musb *musb) { - if (is_host_enabled(musb)) - del_timer_sync(&otg_workaround); + del_timer_sync(&otg_workaround); phy_off(); diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 472c8b4..8805f80 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -115,8 +115,7 @@ static void davinci_musb_enable(struct musb *musb) dma_off = 0; /* force a DRVVBUS irq so we can start polling for ID change */ - if (is_otg_enabled(musb)) - musb_writel(musb->ctrl_base, DAVINCI_USB_INT_SET_REG, + musb_writel(musb->ctrl_base, DAVINCI_USB_INT_SET_REG, DAVINCI_INTR_DRVVBUS << DAVINCI_USB_USBINT_SHIFT); } @@ -234,10 +233,8 @@ static void otg_timer(unsigned long _musb) MUSB_INTR_VBUSERROR << DAVINCI_USB_USBINT_SHIFT); break; case OTG_STATE_B_IDLE: - if (!is_peripheral_enabled(musb)) - break; - - /* There's no ID-changed IRQ, so we have no good way to tell + /* + * There's no ID-changed IRQ, so we have no good way to tell * when to switch to the A-Default state machine (by setting * the DEVCTL.SESSION flag). * @@ -315,8 +312,7 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci) u8 devctl = musb_readb(mregs, MUSB_DEVCTL); int err = musb->int_usb & MUSB_INTR_VBUSERROR; - err = is_host_enabled(musb) - && (musb->int_usb & MUSB_INTR_VBUSERROR); + err = musb->int_usb & MUSB_INTR_VBUSERROR; if (err) { /* The Mentor core doesn't debounce VBUS as needed * to cope with device connect current spikes. This @@ -332,7 +328,7 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci) musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); WARNING("VBUS error workaround (delay coming)\n"); - } else if (is_host_enabled(musb) && drvvbus) { + } else if (drvvbus) { MUSB_HST_MODE(musb); otg->default_a = 1; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; @@ -365,8 +361,7 @@ static irqreturn_t davinci_musb_interrupt(int irq, void *__hci) musb_writel(tibase, DAVINCI_USB_EOI_REG, 0); /* poll for ID change */ - if (is_otg_enabled(musb) - && musb->xceiv->state == OTG_STATE_B_IDLE) + if (musb->xceiv->state == OTG_STATE_B_IDLE) mod_timer(&otg_workaround, jiffies + POLL_SECONDS * HZ); spin_unlock_irqrestore(&musb->lock, flags); @@ -397,8 +392,7 @@ static int davinci_musb_init(struct musb *musb) if (revision == 0) goto fail; - if (is_host_enabled(musb)) - setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); + setup_timer(&otg_workaround, otg_timer, (unsigned long) musb); davinci_musb_source_power(musb, 0, 1); @@ -419,12 +413,7 @@ static int davinci_musb_init(struct musb *musb) if (cpu_is_davinci_dm355()) { u32 deepsleep = __raw_readl(DM355_DEEPSLEEP); - if (is_host_enabled(musb)) { - deepsleep &= ~DRVVBUS_OVERRIDE; - } else { - deepsleep &= ~DRVVBUS_FORCE; - deepsleep |= DRVVBUS_OVERRIDE; - } + deepsleep &= ~DRVVBUS_FORCE; __raw_writel(deepsleep, DM355_DEEPSLEEP); } @@ -453,8 +442,7 @@ unregister: static int davinci_musb_exit(struct musb *musb) { - if (is_host_enabled(musb)) - del_timer_sync(&otg_workaround); + del_timer_sync(&otg_workaround); /* force VBUS off */ if (cpu_is_davinci_dm355()) { @@ -468,7 +456,7 @@ static int davinci_musb_exit(struct musb *musb) davinci_musb_source_power(musb, 0 /*off*/, 1); /* delay, to avoid problems with module reload */ - if (is_host_enabled(musb) && musb->xceiv->otg->default_a) { + if (musb->xceiv->otg->default_a) { int maxdelay = 30; u8 devctl, warn = 0; diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 65b3f53..3d9b647 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -649,8 +649,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, break; case OTG_STATE_B_PERIPHERAL: musb_g_suspend(musb); - musb->is_active = is_otg_enabled(musb) - && otg->gadget->b_hnp_enable; + musb->is_active = otg->gadget->b_hnp_enable; if (musb->is_active) { musb->xceiv->state = OTG_STATE_B_WAIT_ACON; dev_dbg(musb->controller, "HNP: Setting timer for b_ase0_brst\n"); @@ -666,8 +665,7 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb, break; case OTG_STATE_A_HOST: musb->xceiv->state = OTG_STATE_A_SUSPEND; - musb->is_active = is_otg_enabled(musb) - && otg->host->b_hnp_enable; + musb->is_active = otg->host->b_hnp_enable; break; case OTG_STATE_B_HOST: /* Transition to B_PERIPHERAL, see 6.8.2.6 p 44 */ @@ -755,7 +753,7 @@ b_host: case OTG_STATE_A_SUSPEND: usb_hcd_resume_root_hub(musb_to_hcd(musb)); musb_root_disconnect(musb); - if (musb->a_wait_bcon != 0 && is_otg_enabled(musb)) + if (musb->a_wait_bcon != 0) musb_platform_try_idle(musb, jiffies + msecs_to_jiffies(musb->a_wait_bcon)); break; @@ -931,25 +929,16 @@ void musb_start(struct musb *musb) devctl = musb_readb(regs, MUSB_DEVCTL); devctl &= ~MUSB_DEVCTL_SESSION; - if (is_otg_enabled(musb)) { - /* session started after: - * (a) ID-grounded irq, host mode; - * (b) vbus present/connect IRQ, peripheral mode; - * (c) peripheral initiates, using SRP - */ - if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) - musb->is_active = 1; - else - devctl |= MUSB_DEVCTL_SESSION; - - } else if (is_host_enabled(musb)) { - /* assume ID pin is hard-wired to ground */ + /* session started after: + * (a) ID-grounded irq, host mode; + * (b) vbus present/connect IRQ, peripheral mode; + * (c) peripheral initiates, using SRP + */ + if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) + musb->is_active = 1; + else devctl |= MUSB_DEVCTL_SESSION; - } else /* peripheral is enabled */ { - if ((devctl & MUSB_DEVCTL_VBUS) == MUSB_DEVCTL_VBUS) - musb->is_active = 1; - } musb_platform_enable(musb); musb_writeb(regs, MUSB_DEVCTL, devctl); } @@ -1013,8 +1002,6 @@ static void musb_shutdown(struct platform_device *pdev) musb_generic_disable(musb); spin_unlock_irqrestore(&musb->lock, flags); - if (!is_otg_enabled(musb) && is_host_enabled(musb)) - usb_remove_hcd(musb_to_hcd(musb)); musb_writeb(musb->mregs, MUSB_DEVCTL, 0); musb_platform_exit(musb); @@ -1885,6 +1872,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) int status; struct musb *musb; struct musb_hdrc_platform_data *plat = dev->platform_data; + struct usb_hcd *hcd; /* The driver might handle more features than the board; OK. * Fail when the board needs a feature that's not enabled. @@ -1907,7 +1895,6 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) pm_runtime_enable(musb->controller); spin_lock_init(&musb->lock); - musb->board_mode = plat->mode; musb->board_set_power = plat->set_power; musb->min_power = plat->min_power; musb->ops = plat->platform_ops; @@ -1978,7 +1965,7 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) goto fail3; } musb->nIrq = nIrq; -/* FIXME this handles wakeup irqs wrong */ + /* FIXME this handles wakeup irqs wrong */ if (enable_irq_wake(nIrq) == 0) { musb->irq_wake = 1; device_init_wakeup(dev, 1); @@ -1987,58 +1974,25 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) } /* host side needs more setup */ - if (is_host_enabled(musb)) { - struct usb_hcd *hcd = musb_to_hcd(musb); - - otg_set_host(musb->xceiv->otg, &hcd->self); - - if (is_otg_enabled(musb)) - hcd->self.otg_port = 1; - musb->xceiv->otg->host = &hcd->self; - hcd->power_budget = 2 * (plat->power ? : 250); - - /* program PHY to use external vBus if required */ - if (plat->extvbus) { - u8 busctl = musb_read_ulpi_buscontrol(musb->mregs); - busctl |= MUSB_ULPI_USE_EXTVBUS; - musb_write_ulpi_buscontrol(musb->mregs, busctl); - } + hcd = musb_to_hcd(musb); + otg_set_host(musb->xceiv->otg, &hcd->self); + hcd->self.otg_port = 1; + musb->xceiv->otg->host = &hcd->self; + hcd->power_budget = 2 * (plat->power ? : 250); + + /* program PHY to use external vBus if required */ + if (plat->extvbus) { + u8 busctl = musb_read_ulpi_buscontrol(musb->mregs); + busctl |= MUSB_ULPI_USE_EXTVBUS; + musb_write_ulpi_buscontrol(musb->mregs, busctl); } - /* For the host-only role, we can activate right away. - * (We expect the ID pin to be forcibly grounded!!) - * Otherwise, wait till the gadget driver hooks up. - */ - if (!is_otg_enabled(musb) && is_host_enabled(musb)) { - struct usb_hcd *hcd = musb_to_hcd(musb); - - MUSB_HST_MODE(musb); - musb->xceiv->otg->default_a = 1; - musb->xceiv->state = OTG_STATE_A_IDLE; - - status = usb_add_hcd(musb_to_hcd(musb), 0, 0); - - hcd->self.uses_pio_for_control = 1; - dev_dbg(musb->controller, "%s mode, status %d, devctl %02x %c\n", - "HOST", status, - musb_readb(musb->mregs, MUSB_DEVCTL), - (musb_readb(musb->mregs, MUSB_DEVCTL) - & MUSB_DEVCTL_BDEVICE - ? 'B' : 'A')); - - } else /* peripheral is enabled */ { - MUSB_DEV_MODE(musb); - musb->xceiv->otg->default_a = 0; - musb->xceiv->state = OTG_STATE_B_IDLE; - - status = musb_gadget_setup(musb); + MUSB_DEV_MODE(musb); + musb->xceiv->otg->default_a = 0; + musb->xceiv->state = OTG_STATE_B_IDLE; - dev_dbg(musb->controller, "%s mode, status %d, dev%02x\n", - is_otg_enabled(musb) ? "OTG" : "PERIPHERAL", - status, - musb_readb(musb->mregs, MUSB_DEVCTL)); + status = musb_gadget_setup(musb); - } if (status < 0) goto fail3; @@ -2054,28 +2008,13 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) pm_runtime_put(musb->controller); - dev_info(dev, "USB %s mode controller at %p using %s, IRQ %d\n", - ({char *s; - switch (musb->board_mode) { - case MUSB_HOST: s = "Host"; break; - case MUSB_PERIPHERAL: s = "Peripheral"; break; - default: s = "OTG"; break; - }; s; }), - ctrl, - (is_dma_capable() && musb->dma_controller) - ? "DMA" : "PIO", - musb->nIrq); - return 0; fail5: musb_exit_debugfs(musb); fail4: - if (!is_otg_enabled(musb) && is_host_enabled(musb)) - usb_remove_hcd(musb_to_hcd(musb)); - else - musb_gadget_cleanup(musb); + musb_gadget_cleanup(musb); fail3: pm_runtime_put_sync(musb->controller); @@ -2166,11 +2105,9 @@ static void musb_save_context(struct musb *musb) void __iomem *musb_base = musb->mregs; void __iomem *epio; - if (is_host_enabled(musb)) { - musb->context.frame = musb_readw(musb_base, MUSB_FRAME); - musb->context.testmode = musb_readb(musb_base, MUSB_TESTMODE); - musb->context.busctl = musb_read_ulpi_buscontrol(musb->mregs); - } + musb->context.frame = musb_readw(musb_base, MUSB_FRAME); + musb->context.testmode = musb_readb(musb_base, MUSB_TESTMODE); + musb->context.busctl = musb_read_ulpi_buscontrol(musb->mregs); musb->context.power = musb_readb(musb_base, MUSB_POWER); musb->context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE); musb->context.intrrxe = musb_readw(musb_base, MUSB_INTRRXE); @@ -2209,30 +2146,29 @@ static void musb_save_context(struct musb *musb) musb->context.index_regs[i].rxfifosz = musb_read_rxfifosz(musb_base); } - if (is_host_enabled(musb)) { - musb->context.index_regs[i].txtype = - musb_readb(epio, MUSB_TXTYPE); - musb->context.index_regs[i].txinterval = - musb_readb(epio, MUSB_TXINTERVAL); - musb->context.index_regs[i].rxtype = - musb_readb(epio, MUSB_RXTYPE); - musb->context.index_regs[i].rxinterval = - musb_readb(epio, MUSB_RXINTERVAL); - - musb->context.index_regs[i].txfunaddr = - musb_read_txfunaddr(musb_base, i); - musb->context.index_regs[i].txhubaddr = - musb_read_txhubaddr(musb_base, i); - musb->context.index_regs[i].txhubport = - musb_read_txhubport(musb_base, i); - - musb->context.index_regs[i].rxfunaddr = - musb_read_rxfunaddr(musb_base, i); - musb->context.index_regs[i].rxhubaddr = - musb_read_rxhubaddr(musb_base, i); - musb->context.index_regs[i].rxhubport = - musb_read_rxhubport(musb_base, i); - } + + musb->context.index_regs[i].txtype = + musb_readb(epio, MUSB_TXTYPE); + musb->context.index_regs[i].txinterval = + musb_readb(epio, MUSB_TXINTERVAL); + musb->context.index_regs[i].rxtype = + musb_readb(epio, MUSB_RXTYPE); + musb->context.index_regs[i].rxinterval = + musb_readb(epio, MUSB_RXINTERVAL); + + musb->context.index_regs[i].txfunaddr = + musb_read_txfunaddr(musb_base, i); + musb->context.index_regs[i].txhubaddr = + musb_read_txhubaddr(musb_base, i); + musb->context.index_regs[i].txhubport = + musb_read_txhubport(musb_base, i); + + musb->context.index_regs[i].rxfunaddr = + musb_read_rxfunaddr(musb_base, i); + musb->context.index_regs[i].rxhubaddr = + musb_read_rxhubaddr(musb_base, i); + musb->context.index_regs[i].rxhubport = + musb_read_rxhubport(musb_base, i); } } @@ -2243,11 +2179,9 @@ static void musb_restore_context(struct musb *musb) void __iomem *ep_target_regs; void __iomem *epio; - if (is_host_enabled(musb)) { - musb_writew(musb_base, MUSB_FRAME, musb->context.frame); - musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode); - musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl); - } + musb_writew(musb_base, MUSB_FRAME, musb->context.frame); + musb_writeb(musb_base, MUSB_TESTMODE, musb->context.testmode); + musb_write_ulpi_buscontrol(musb->mregs, musb->context.busctl); musb_writeb(musb_base, MUSB_POWER, musb->context.power); musb_writew(musb_base, MUSB_INTRTXE, musb->context.intrtxe); musb_writew(musb_base, MUSB_INTRRXE, musb->context.intrrxe); @@ -2286,33 +2220,31 @@ static void musb_restore_context(struct musb *musb) musb->context.index_regs[i].rxfifoadd); } - if (is_host_enabled(musb)) { - musb_writeb(epio, MUSB_TXTYPE, + musb_writeb(epio, MUSB_TXTYPE, musb->context.index_regs[i].txtype); - musb_writeb(epio, MUSB_TXINTERVAL, + musb_writeb(epio, MUSB_TXINTERVAL, musb->context.index_regs[i].txinterval); - musb_writeb(epio, MUSB_RXTYPE, + musb_writeb(epio, MUSB_RXTYPE, musb->context.index_regs[i].rxtype); - musb_writeb(epio, MUSB_RXINTERVAL, + musb_writeb(epio, MUSB_RXINTERVAL, - musb->context.index_regs[i].rxinterval); - musb_write_txfunaddr(musb_base, i, + musb->context.index_regs[i].rxinterval); + musb_write_txfunaddr(musb_base, i, musb->context.index_regs[i].txfunaddr); - musb_write_txhubaddr(musb_base, i, + musb_write_txhubaddr(musb_base, i, musb->context.index_regs[i].txhubaddr); - musb_write_txhubport(musb_base, i, + musb_write_txhubport(musb_base, i, musb->context.index_regs[i].txhubport); - ep_target_regs = - musb_read_target_reg_base(i, musb_base); + ep_target_regs = + musb_read_target_reg_base(i, musb_base); - musb_write_rxfunaddr(ep_target_regs, + musb_write_rxfunaddr(ep_target_regs, musb->context.index_regs[i].rxfunaddr); - musb_write_rxhubaddr(ep_target_regs, + musb_write_rxhubaddr(ep_target_regs, musb->context.index_regs[i].rxhubaddr); - musb_write_rxhubport(ep_target_regs, + musb_write_rxhubport(ep_target_regs, musb->context.index_regs[i].rxhubport); - } } musb_writeb(musb_base, MUSB_INDEX, musb->context.index); } diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 8bb324d..5dab2da 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -71,10 +71,6 @@ struct musb_ep; #include #include "musb_host.h" -#define is_peripheral_enabled(musb) ((musb)->board_mode != MUSB_HOST) -#define is_host_enabled(musb) ((musb)->board_mode != MUSB_PERIPHERAL) -#define is_otg_enabled(musb) ((musb)->board_mode == MUSB_OTG) - /* NOTE: otg and peripheral-only state machines start at B_IDLE. * OTG or host-only go to A_IDLE when ID is sensed. */ @@ -376,7 +372,6 @@ struct musb { u16 epmask; u8 nr_endpoints; - u8 board_mode; /* enum musb_mode */ int (*board_set_power)(int state); u8 min_power; /* vbus for periph, in mA/2 */ diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 217808d..51ff1bb 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -137,9 +137,8 @@ static void dsps_musb_enable(struct musb *musb) dsps_writel(reg_base, wrp->epintr_set, epmask); dsps_writel(reg_base, wrp->coreintr_set, coremask); /* Force the DRVVBUS IRQ so we can start polling for ID change. */ - if (is_otg_enabled(musb)) - dsps_writel(reg_base, wrp->coreintr_set, - (1 << wrp->drvvbus) << wrp->usb_shift); + dsps_writel(reg_base, wrp->coreintr_set, + (1 << wrp->drvvbus) << wrp->usb_shift); } /** @@ -200,9 +199,6 @@ static void otg_timer(unsigned long _musb) MUSB_INTR_VBUSERROR << wrp->usb_shift); break; case OTG_STATE_B_IDLE: - if (!is_peripheral_enabled(musb)) - break; - devctl = dsps_readb(mregs, MUSB_DEVCTL); if (devctl & MUSB_DEVCTL_BDEVICE) mod_timer(&glue->timer, @@ -223,9 +219,6 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout) struct dsps_glue *glue = platform_get_drvdata(pdev); static unsigned long last_timer; - if (!is_otg_enabled(musb)) - return; - if (timeout == 0) timeout = jiffies + msecs_to_jiffies(3); @@ -293,7 +286,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) * value but DEVCTL.BDEVICE is invalid without DEVCTL.SESSION set. * Also, DRVVBUS pulses for SRP (but not at 5V) ... */ - if ((usbintr & MUSB_INTR_BABBLE) && is_host_enabled(musb)) + if (usbintr & MUSB_INTR_BABBLE) pr_info("CAUTION: musb: Babble Interrupt Occured\n"); if (usbintr & ((1 << wrp->drvvbus) << wrp->usb_shift)) { @@ -302,8 +295,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) u8 devctl = dsps_readb(mregs, MUSB_DEVCTL); int err; - err = is_host_enabled(musb) && (musb->int_usb & - MUSB_INTR_VBUSERROR); + err = musb->int_usb & MUSB_INTR_VBUSERROR; if (err) { /* * The Mentor core doesn't debounce VBUS as needed @@ -321,7 +313,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ); WARNING("VBUS error workaround (delay coming)\n"); - } else if (is_host_enabled(musb) && drvvbus) { + } else if (drvvbus) { musb->is_active = 1; MUSB_HST_MODE(musb); musb->xceiv->otg->default_a = 1; @@ -352,7 +344,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) dsps_writel(reg_base, wrp->eoi, 1); /* Poll for ID change */ - if (is_otg_enabled(musb) && musb->xceiv->state == OTG_STATE_B_IDLE) + if (musb->xceiv->state == OTG_STATE_B_IDLE) mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ); spin_unlock_irqrestore(&musb->lock, flags); @@ -388,8 +380,7 @@ static int dsps_musb_init(struct musb *musb) goto err0; } - if (is_host_enabled(musb)) - setup_timer(&glue->timer, otg_timer, (unsigned long) musb); + setup_timer(&glue->timer, otg_timer, (unsigned long) musb); /* Reset the musb */ dsps_writel(reg_base, wrp->control, (1 << wrp->reset)); @@ -423,8 +414,7 @@ static int dsps_musb_exit(struct musb *musb) struct platform_device *pdev = to_platform_device(dev->parent); struct dsps_glue *glue = platform_get_drvdata(pdev); - if (is_host_enabled(musb)) - del_timer_sync(&glue->timer); + del_timer_sync(&glue->timer); /* Shutdown the on-chip PHY and its PLL. */ if (data->set_phy_power) diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 5c4392b..7fb060d 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -1864,8 +1864,7 @@ int __devinit musb_gadget_setup(struct musb *musb) musb->g.dev.release = musb_gadget_release; musb->g.name = musb_driver_name; - if (is_otg_enabled(musb)) - musb->g.is_otg = 1; + musb->g.is_otg = 1; musb_g_init_endpoints(musb); @@ -1911,11 +1910,14 @@ static int musb_gadget_start(struct usb_gadget *g, { struct musb *musb = gadget_to_musb(g); struct usb_otg *otg = musb->xceiv->otg; + struct usb_hcd *hcd = musb_to_hcd(musb); unsigned long flags; - int retval = -EINVAL; + int retval = 0; - if (driver->max_speed < USB_SPEED_HIGH) - goto err0; + if (driver->max_speed < USB_SPEED_HIGH) { + retval = -EINVAL; + goto err; + } pm_runtime_get_sync(musb->controller); @@ -1929,49 +1931,30 @@ static int musb_gadget_start(struct usb_gadget *g, otg_set_peripheral(otg, &musb->g); musb->xceiv->state = OTG_STATE_B_IDLE; - - /* - * FIXME this ignores the softconnect flag. Drivers are - * allowed hold the peripheral inactive until for example - * userspace hooks up printer hardware or DSP codecs, so - * hosts only see fully functional devices. - */ - - if (!is_otg_enabled(musb)) - musb_start(musb); - spin_unlock_irqrestore(&musb->lock, flags); - if (is_otg_enabled(musb)) { - struct usb_hcd *hcd = musb_to_hcd(musb); - - dev_dbg(musb->controller, "OTG startup...\n"); + /* REVISIT: funcall to other code, which also + * handles power budgeting ... this way also + * ensures HdrcStart is indirectly called. + */ + retval = usb_add_hcd(hcd, 0, 0); + if (retval < 0) { + dev_dbg(musb->controller, "add_hcd failed, %d\n", retval); + goto err; + } - /* REVISIT: funcall to other code, which also - * handles power budgeting ... this way also - * ensures HdrcStart is indirectly called. - */ - retval = usb_add_hcd(musb_to_hcd(musb), 0, 0); - if (retval < 0) { - dev_dbg(musb->controller, "add_hcd failed, %d\n", retval); - goto err2; - } + if ((musb->xceiv->last_event == USB_EVENT_ID) + && otg->set_vbus) + otg_set_vbus(otg, 1); - if ((musb->xceiv->last_event == USB_EVENT_ID) - && otg->set_vbus) - otg_set_vbus(otg, 1); + hcd->self.uses_pio_for_control = 1; - hcd->self.uses_pio_for_control = 1; - } if (musb->xceiv->last_event == USB_EVENT_NONE) pm_runtime_put(musb->controller); return 0; -err2: - if (!is_otg_enabled(musb)) - musb_stop(musb); -err0: +err: return retval; } @@ -2049,16 +2032,12 @@ static int musb_gadget_stop(struct usb_gadget *g, musb_platform_try_idle(musb, 0); spin_unlock_irqrestore(&musb->lock, flags); - if (is_otg_enabled(musb)) { - usb_remove_hcd(musb_to_hcd(musb)); - /* FIXME we need to be able to register another - * gadget driver here and have everything work; - * that currently misbehaves. - */ - } - - if (!is_otg_enabled(musb)) - musb_stop(musb); + usb_remove_hcd(musb_to_hcd(musb)); + /* + * FIXME we need to be able to register another + * gadget driver here and have everything work; + * that currently misbehaves. + */ pm_runtime_put(musb->controller); @@ -2220,13 +2199,11 @@ __acquires(musb->lock) if (devctl & MUSB_DEVCTL_BDEVICE) { musb->xceiv->state = OTG_STATE_B_PERIPHERAL; musb->g.is_a_peripheral = 0; - } else if (is_otg_enabled(musb)) { + } else { musb->xceiv->state = OTG_STATE_A_PERIPHERAL; musb->g.is_a_peripheral = 1; - } else - WARN_ON(1); + } /* start with default limits on VBUS power draw */ - (void) musb_gadget_vbus_draw(&musb->g, - is_otg_enabled(musb) ? 8 : 100); + (void) musb_gadget_vbus_draw(&musb->g, 8); } diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index 22ec3e3..f705791 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -81,8 +81,7 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend) switch (musb->xceiv->state) { case OTG_STATE_A_HOST: musb->xceiv->state = OTG_STATE_A_SUSPEND; - musb->is_active = is_otg_enabled(musb) - && otg->host->b_hnp_enable; + musb->is_active = otg->host->b_hnp_enable; if (musb->is_active) mod_timer(&musb->otg_timer, jiffies + msecs_to_jiffies( @@ -91,8 +90,7 @@ static void musb_port_suspend(struct musb *musb, bool do_suspend) break; case OTG_STATE_B_HOST: musb->xceiv->state = OTG_STATE_B_WAIT_ACON; - musb->is_active = is_otg_enabled(musb) - && otg->host->b_hnp_enable; + musb->is_active = otg->host->b_hnp_enable; musb_platform_try_idle(musb, 0); break; default: @@ -190,8 +188,7 @@ void musb_root_disconnect(struct musb *musb) switch (musb->xceiv->state) { case OTG_STATE_A_SUSPEND: - if (is_otg_enabled(musb) - && otg->host->b_hnp_enable) { + if (otg->host->b_hnp_enable) { musb->xceiv->state = OTG_STATE_A_PERIPHERAL; musb->g.is_a_peripheral = 1; break; @@ -273,7 +270,7 @@ int musb_hub_control( musb_port_suspend(musb, false); break; case USB_PORT_FEAT_POWER: - if (!(is_otg_enabled(musb) && hcd->self.is_b_host)) + if (!hcd->self.is_b_host) musb_platform_set_vbus(musb, 0); break; case USB_PORT_FEAT_C_CONNECTION: @@ -369,7 +366,7 @@ int musb_hub_control( * initialization logic, e.g. for OTG, or change any * logic relating to VBUS power-up. */ - if (!(is_otg_enabled(musb) && hcd->self.is_b_host)) + if (!hcd->self.is_b_host) musb_start(musb); break; case USB_PORT_FEAT_RESET: diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 392fc7a..e32aff9 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -258,7 +258,7 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) otg->default_a = true; musb->xceiv->state = OTG_STATE_A_IDLE; musb->xceiv->last_event = USB_EVENT_ID; - if (!is_otg_enabled(musb) || musb->gadget_driver) { + if (musb->gadget_driver) { pm_runtime_get_sync(dev); usb_phy_init(musb->xceiv); omap2430_musb_set_vbus(musb, 1); @@ -281,11 +281,10 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) dev_dbg(dev, "VBUS Disconnect\n"); musb->xceiv->last_event = USB_EVENT_NONE; - if (is_otg_enabled(musb) || is_peripheral_enabled(musb)) - if (musb->gadget_driver) { - pm_runtime_mark_last_busy(dev); - pm_runtime_put_autosuspend(dev); - } + if (musb->gadget_driver) { + pm_runtime_mark_last_busy(dev); + pm_runtime_put_autosuspend(dev); + } if (data->interface_type == MUSB_INTERFACE_UTMI) { if (musb->xceiv->otg->set_vbus) diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 4073a6f..1d0c090 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -437,14 +437,13 @@ static void musb_do_idle(unsigned long _musb) if (is_host_active(musb) && (musb->port1_status >> 16)) goto done; - if (is_peripheral_enabled(musb) && !musb->gadget_driver) { + if (!musb->gadget_driver) { wakeups = 0; } else { wakeups = TUSB_PRCM_WHOSTDISCON | TUSB_PRCM_WBUS | TUSB_PRCM_WVBUS; - if (is_otg_enabled(musb)) - wakeups |= TUSB_PRCM_WID; + wakeups |= TUSB_PRCM_WID; } tusb_allow_idle(musb, wakeups); } @@ -582,21 +581,12 @@ static void tusb_musb_set_vbus(struct musb *musb, int is_on) * * Note that if a mini-A cable is plugged in the ID line will stay down as * the weak ID pull-up is not able to pull the ID up. - * - * REVISIT: It would be possible to add support for changing between host - * and peripheral modes in non-OTG configurations by reconfiguring hardware - * and then setting musb->board_mode. For now, only support OTG mode. */ static int tusb_musb_set_mode(struct musb *musb, u8 musb_mode) { void __iomem *tbase = musb->ctrl_base; u32 otg_stat, phy_otg_ctrl, phy_otg_ena, dev_conf; - if (musb->board_mode != MUSB_OTG) { - ERR("Changing mode currently only supported in OTG mode\n"); - return -EINVAL; - } - otg_stat = musb_readl(tbase, TUSB_DEV_OTG_STAT); phy_otg_ctrl = musb_readl(tbase, TUSB_PHY_OTG_CTRL); phy_otg_ena = musb_readl(tbase, TUSB_PHY_OTG_CTRL_ENABLE); @@ -652,10 +642,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) if ((int_src & TUSB_INT_SRC_ID_STATUS_CHNG)) { int default_a; - if (is_otg_enabled(musb)) - default_a = !(otg_stat & TUSB_DEV_OTG_STAT_ID_STATUS); - else - default_a = is_host_enabled(musb); + default_a = !(otg_stat & TUSB_DEV_OTG_STAT_ID_STATUS); dev_dbg(musb->controller, "Default-%c\n", default_a ? 'A' : 'B'); otg->default_a = default_a; tusb_musb_set_vbus(musb, default_a); @@ -669,8 +656,7 @@ tusb_otg_ints(struct musb *musb, u32 int_src, void __iomem *tbase) if (int_src & TUSB_INT_SRC_VBUS_SENSE_CHNG) { /* B-dev state machine: no vbus ~= disconnect */ - if ((is_otg_enabled(musb) && !otg->default_a) - || !is_host_enabled(musb)) { + if (!otg->default_a) { /* ? musb_root_disconnect(musb); */ musb->port1_status &= ~(USB_PORT_STAT_CONNECTION @@ -1119,10 +1105,8 @@ static int tusb_musb_init(struct musb *musb) } musb->isr = tusb_musb_interrupt; - if (is_peripheral_enabled(musb)) { - musb->xceiv->set_power = tusb_draw_power; - the_musb = musb; - } + musb->xceiv->set_power = tusb_draw_power; + the_musb = musb; setup_timer(&musb_idle_timer, musb_do_idle, (unsigned long) musb); -- cgit v0.10.2 From a04d46d02e0c511dabb3c0a29286811a00d12b10 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 24 Nov 2011 15:46:27 +0200 Subject: usb: musb: drop is_host_capable() and is_peripheral_capable() those two were defined to 1 anyway, quite useless. Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 3d9b647..4bc2ad8 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -791,7 +791,7 @@ b_host: */ if (int_usb & MUSB_INTR_RESET) { handled = IRQ_HANDLED; - if (is_host_capable() && (devctl & MUSB_DEVCTL_HM) != 0) { + if ((devctl & MUSB_DEVCTL_HM) != 0) { /* * Looks like non-HS BABBLE can be ignored, but * HS BABBLE is an error condition. For HS the solution @@ -805,7 +805,7 @@ b_host: ERR("Stopping host session -- babble\n"); musb_writeb(musb->mregs, MUSB_DEVCTL, 0); } - } else if (is_peripheral_capable()) { + } else { dev_dbg(musb->controller, "BUS RESET as %s\n", otg_state_string(musb->xceiv->state)); switch (musb->xceiv->state) { @@ -1564,13 +1564,10 @@ irqreturn_t musb_interrupt(struct musb *musb) /* musb_ep_select(musb->mregs, ep_num); */ /* REVISIT just retval = ep->rx_irq(...) */ retval = IRQ_HANDLED; - if (devctl & MUSB_DEVCTL_HM) { - if (is_host_capable()) - musb_host_rx(musb, ep_num); - } else { - if (is_peripheral_capable()) - musb_g_rx(musb, ep_num); - } + if (devctl & MUSB_DEVCTL_HM) + musb_host_rx(musb, ep_num); + else + musb_g_rx(musb, ep_num); } reg >>= 1; @@ -1585,13 +1582,10 @@ irqreturn_t musb_interrupt(struct musb *musb) /* musb_ep_select(musb->mregs, ep_num); */ /* REVISIT just retval |= ep->tx_irq(...) */ retval = IRQ_HANDLED; - if (devctl & MUSB_DEVCTL_HM) { - if (is_host_capable()) - musb_host_tx(musb, ep_num); - } else { - if (is_peripheral_capable()) - musb_g_tx(musb, ep_num); - } + if (devctl & MUSB_DEVCTL_HM) + musb_host_tx(musb, ep_num); + else + musb_g_tx(musb, ep_num); } reg >>= 1; ep_num++; @@ -1627,22 +1621,16 @@ void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit) } else { /* endpoints 1..15 */ if (transmit) { - if (devctl & MUSB_DEVCTL_HM) { - if (is_host_capable()) - musb_host_tx(musb, epnum); - } else { - if (is_peripheral_capable()) - musb_g_tx(musb, epnum); - } + if (devctl & MUSB_DEVCTL_HM) + musb_host_tx(musb, epnum); + else + musb_g_tx(musb, epnum); } else { /* receive */ - if (devctl & MUSB_DEVCTL_HM) { - if (is_host_capable()) - musb_host_rx(musb, epnum); - } else { - if (is_peripheral_capable()) - musb_g_rx(musb, epnum); - } + if (devctl & MUSB_DEVCTL_HM) + musb_host_rx(musb, epnum); + else + musb_g_rx(musb, epnum); } } } diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 5dab2da..a1a32c6 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -84,8 +84,6 @@ struct musb_ep; /****************************** PERIPHERAL ROLE *****************************/ -#define is_peripheral_capable() (1) - extern irqreturn_t musb_g_ep0_irq(struct musb *); extern void musb_g_tx(struct musb *, u8); extern void musb_g_rx(struct musb *, u8); @@ -97,8 +95,6 @@ extern void musb_g_disconnect(struct musb *); /****************************** HOST ROLE ***********************************/ -#define is_host_capable() (1) - extern irqreturn_t musb_h_ep0_irq(struct musb *); extern void musb_host_tx(struct musb *, u8); extern void musb_host_rx(struct musb *, u8); -- cgit v0.10.2 From 660fa8863d2623b733d7977a56e2990437abcbdb Mon Sep 17 00:00:00 2001 From: Roger Quadros Date: Tue, 7 Aug 2012 16:26:32 +0300 Subject: usb: musb: Remove redundant if statement Remove unnecessary if condition. No change in logic. Signed-off-by: Roger Quadros Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index 7fb060d..d0b87e7 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c @@ -722,6 +722,7 @@ static void rxstate(struct musb *musb, struct musb_request *req) struct dma_controller *c; struct dma_channel *channel; int use_dma = 0; + int transfer_size; c = musb->dma_controller; channel = musb_ep->dma; @@ -742,35 +743,30 @@ static void rxstate(struct musb *musb, struct musb_request *req) csr | MUSB_RXCSR_DMAMODE); musb_writew(epio, MUSB_RXCSR, csr); + transfer_size = min(request->length - request->actual, + channel->max_len); + musb_ep->dma->desired_mode = 1; + } else { if (!musb_ep->hb_mult && musb_ep->hw_ep->rx_double_buffered) csr |= MUSB_RXCSR_AUTOCLEAR; csr |= MUSB_RXCSR_DMAENAB; musb_writew(epio, MUSB_RXCSR, csr); - } - if (request->actual < request->length) { - int transfer_size = 0; - if (use_mode_1) { - transfer_size = min(request->length - request->actual, - channel->max_len); - musb_ep->dma->desired_mode = 1; - } else { - transfer_size = min(request->length - request->actual, + transfer_size = min(request->length - request->actual, (unsigned)fifo_count); - musb_ep->dma->desired_mode = 0; - } - - use_dma = c->channel_program( - channel, - musb_ep->packet_sz, - channel->desired_mode, - request->dma - + request->actual, - transfer_size); + musb_ep->dma->desired_mode = 0; } + use_dma = c->channel_program( + channel, + musb_ep->packet_sz, + channel->desired_mode, + request->dma + + request->actual, + transfer_size); + if (use_dma) return; } -- cgit v0.10.2 From 57911504a93909034ba5b90c20f3e6df8409ebd8 Mon Sep 17 00:00:00 2001 From: Pratyush Anand Date: Fri, 6 Jul 2012 15:19:10 +0530 Subject: usb: dwc3: gadget: Fix dwc3_stop_active_transfer for synchronization delay dwc3_stop_active_transfer has been called from two places. After each calling of this function , we should allow 100 us delay to synchronize with interconnect. It would be better if we put this delay in that function only, rather than into calling routine of this function. Signed-off-by: Pratyush Anand Reported-by: Michel Sanches Signed-off-by: Felipe Balbi diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index fc05910..dd5945c 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -563,27 +563,7 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep) if (!list_empty(&dep->req_queued)) { dwc3_stop_active_transfer(dwc, dep->number); - /* - * NOTICE: We are violating what the Databook says about the - * EndTransfer command. Ideally we would _always_ wait for the - * EndTransfer Command Completion IRQ, but that's causing too - * much trouble synchronizing between us and gadget driver. - * - * We have discussed this with the IP Provider and it was - * suggested to giveback all requests here, but give HW some - * extra time to synchronize with the interconnect. We're using - * an arbitraty 100us delay for that. - * - * Note also that a similar handling was tested by Synopsys - * (thanks a lot Paul) and nothing bad has come out of it. - * In short, what we're doing is: - * - * - Issue EndTransfer WITH CMDIOC bit set - * - Wait 100us - * - giveback all requests to gadget driver - */ - udelay(100); - + /* - giveback all requests to gadget driver */ while (!list_empty(&dep->req_queued)) { req = next_request(&dep->req_queued); @@ -1875,6 +1855,25 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum) if (!dep->resource_index) return; + /* + * NOTICE: We are violating what the Databook says about the + * EndTransfer command. Ideally we would _always_ wait for the + * EndTransfer Command Completion IRQ, but that's causing too + * much trouble synchronizing between us and gadget driver. + * + * We have discussed this with the IP Provider and it was + * suggested to giveback all requests here, but give HW some + * extra time to synchronize with the interconnect. We're using + * an arbitraty 100us delay for that. + * + * Note also that a similar handling was tested by Synopsys + * (thanks a lot Paul) and nothing bad has come out of it. + * In short, what we're doing is: + * + * - Issue EndTransfer WITH CMDIOC bit set + * - Wait 100us + */ + cmd = DWC3_DEPCMD_ENDTRANSFER; cmd |= DWC3_DEPCMD_HIPRI_FORCERM | DWC3_DEPCMD_CMDIOC; cmd |= DWC3_DEPCMD_PARAM(dep->resource_index); @@ -1882,6 +1881,8 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum) ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, ¶ms); WARN_ON_ONCE(ret); dep->resource_index = 0; + + udelay(100); } static void dwc3_stop_active_transfers(struct dwc3 *dwc) -- cgit v0.10.2 From df6791d7042d839b68c58cd7dc3699f9ae5a8f22 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti D Date: Tue, 7 Aug 2012 19:56:30 +0530 Subject: usb: otg: Remove the unneeded NULL check The function usb_add_phy trusts the sanity of the caller. Also it accesses x after the NULL check. Remove the unneeded check. Signed-off-by: Shubhrajyoti D Signed-off-by: Felipe Balbi diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c index 1bf60a2..a30c041 100644 --- a/drivers/usb/otg/otg.c +++ b/drivers/usb/otg/otg.c @@ -159,7 +159,7 @@ int usb_add_phy(struct usb_phy *x, enum usb_phy_type type) unsigned long flags; struct usb_phy *phy; - if (x && x->type != USB_PHY_TYPE_UNDEFINED) { + if (x->type != USB_PHY_TYPE_UNDEFINED) { dev_err(x->dev, "not accepting initialized PHY %s\n", x->label); return -EINVAL; } -- cgit v0.10.2 From f69dfa1f01e20387ada601f2bf772061d79e6a8f Mon Sep 17 00:00:00 2001 From: Shubhrajyoti D Date: Tue, 7 Aug 2012 19:56:31 +0530 Subject: usb: musb: Prevent the masking of the return value Currently the errors returned by fifo_setup get masked by EINVAL, propagate the same to the caller. Signed-off-by: Shubhrajyoti D Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 4bc2ad8..dd24f96 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1295,7 +1295,7 @@ done: if (offset < 0) { pr_debug("%s: mem overrun, ep %d\n", musb_driver_name, epn); - return -EINVAL; + return offset; } epn++; musb->nr_endpoints = max(epn, musb->nr_endpoints); -- cgit v0.10.2 From a67e76ac904cb48946262bf353f1df0d1b349368 Mon Sep 17 00:00:00 2001 From: Yu Xu Date: Thu, 9 Aug 2012 22:29:31 +0800 Subject: usb: phy: mv_u3d: Add usb phy driver for mv_u3d The driver supports phy_init and phy_shutdown functions to enable and disable phy for Marvell USB 3.0 controller. Signed-off-by: Yu Xu Signed-off-by: Felipe Balbi diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index e7cf84f..2838adb 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -15,3 +15,11 @@ config USB_ISP1301 To compile this driver as a module, choose M here: the module will be called isp1301. + +config MV_U3D_PHY + bool "Marvell USB 3.0 PHY controller Driver" + depends on USB_MV_U3D + select USB_OTG_UTILS + help + Enable this to support Marvell USB 3.0 phy controller for Marvell + SoC. diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index eca095b..cf38f08 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -5,3 +5,4 @@ ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG obj-$(CONFIG_USB_ISP1301) += isp1301.o +obj-$(CONFIG_MV_U3D_PHY) += mv_u3d_phy.o diff --git a/drivers/usb/phy/mv_u3d_phy.c b/drivers/usb/phy/mv_u3d_phy.c new file mode 100644 index 0000000..9f1c5d3 --- /dev/null +++ b/drivers/usb/phy/mv_u3d_phy.c @@ -0,0 +1,345 @@ +/* + * Copyright (C) 2011 Marvell International Ltd. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mv_u3d_phy.h" + +/* + * struct mv_u3d_phy - transceiver driver state + * @phy: transceiver structure + * @dev: The parent device supplied to the probe function + * @clk: usb phy clock + * @base: usb phy register memory base + */ +struct mv_u3d_phy { + struct usb_phy phy; + struct mv_usb_platform_data *plat; + struct device *dev; + struct clk *clk; + void __iomem *base; +}; + +static u32 mv_u3d_phy_read(void __iomem *base, u32 reg) +{ + void __iomem *addr, *data; + + addr = base; + data = base + 0x4; + + writel_relaxed(reg, addr); + return readl_relaxed(data); +} + +static void mv_u3d_phy_set(void __iomem *base, u32 reg, u32 value) +{ + void __iomem *addr, *data; + u32 tmp; + + addr = base; + data = base + 0x4; + + writel_relaxed(reg, addr); + tmp = readl_relaxed(data); + tmp |= value; + writel_relaxed(tmp, data); +} + +static void mv_u3d_phy_clear(void __iomem *base, u32 reg, u32 value) +{ + void __iomem *addr, *data; + u32 tmp; + + addr = base; + data = base + 0x4; + + writel_relaxed(reg, addr); + tmp = readl_relaxed(data); + tmp &= ~value; + writel_relaxed(tmp, data); +} + +static void mv_u3d_phy_write(void __iomem *base, u32 reg, u32 value) +{ + void __iomem *addr, *data; + + addr = base; + data = base + 0x4; + + writel_relaxed(reg, addr); + writel_relaxed(value, data); +} + +void mv_u3d_phy_shutdown(struct usb_phy *phy) +{ + struct mv_u3d_phy *mv_u3d_phy; + void __iomem *base; + u32 val; + + mv_u3d_phy = container_of(phy, struct mv_u3d_phy, phy); + base = mv_u3d_phy->base; + + /* Power down Reference Analog current, bit 15 + * Power down PLL, bit 14 + * Power down Receiver, bit 13 + * Power down Transmitter, bit 12 + * of USB3_POWER_PLL_CONTROL register + */ + val = mv_u3d_phy_read(base, USB3_POWER_PLL_CONTROL); + val &= ~(USB3_POWER_PLL_CONTROL_PU); + mv_u3d_phy_write(base, USB3_POWER_PLL_CONTROL, val); + + if (mv_u3d_phy->clk) + clk_disable(mv_u3d_phy->clk); +} + +static int mv_u3d_phy_init(struct usb_phy *phy) +{ + struct mv_u3d_phy *mv_u3d_phy; + void __iomem *base; + u32 val, count; + + /* enable usb3 phy */ + mv_u3d_phy = container_of(phy, struct mv_u3d_phy, phy); + + if (mv_u3d_phy->clk) + clk_enable(mv_u3d_phy->clk); + + base = mv_u3d_phy->base; + + val = mv_u3d_phy_read(base, USB3_POWER_PLL_CONTROL); + val &= ~(USB3_POWER_PLL_CONTROL_PU_MASK); + val |= 0xF << USB3_POWER_PLL_CONTROL_PU_SHIFT; + mv_u3d_phy_write(base, USB3_POWER_PLL_CONTROL, val); + udelay(100); + + mv_u3d_phy_write(base, USB3_RESET_CONTROL, + USB3_RESET_CONTROL_RESET_PIPE); + udelay(100); + + mv_u3d_phy_write(base, USB3_RESET_CONTROL, + USB3_RESET_CONTROL_RESET_PIPE + | USB3_RESET_CONTROL_RESET_PHY); + udelay(100); + + val = mv_u3d_phy_read(base, USB3_POWER_PLL_CONTROL); + val &= ~(USB3_POWER_PLL_CONTROL_REF_FREF_SEL_MASK + | USB3_POWER_PLL_CONTROL_PHY_MODE_MASK); + val |= (USB3_PLL_25MHZ << USB3_POWER_PLL_CONTROL_REF_FREF_SEL_SHIFT) + | (0x5 << USB3_POWER_PLL_CONTROL_PHY_MODE_SHIFT); + mv_u3d_phy_write(base, USB3_POWER_PLL_CONTROL, val); + udelay(100); + + mv_u3d_phy_clear(base, USB3_KVCO_CALI_CONTROL, + USB3_KVCO_CALI_CONTROL_USE_MAX_PLL_RATE_MASK); + udelay(100); + + val = mv_u3d_phy_read(base, USB3_SQUELCH_FFE); + val &= ~(USB3_SQUELCH_FFE_FFE_CAP_SEL_MASK + | USB3_SQUELCH_FFE_FFE_RES_SEL_MASK + | USB3_SQUELCH_FFE_SQ_THRESH_IN_MASK); + val |= ((0xD << USB3_SQUELCH_FFE_FFE_CAP_SEL_SHIFT) + | (0x7 << USB3_SQUELCH_FFE_FFE_RES_SEL_SHIFT) + | (0x8 << USB3_SQUELCH_FFE_SQ_THRESH_IN_SHIFT)); + mv_u3d_phy_write(base, USB3_SQUELCH_FFE, val); + udelay(100); + + val = mv_u3d_phy_read(base, USB3_GEN1_SET0); + val &= ~USB3_GEN1_SET0_G1_TX_SLEW_CTRL_EN_MASK; + val |= 1 << USB3_GEN1_SET0_G1_TX_EMPH_EN_SHIFT; + mv_u3d_phy_write(base, USB3_GEN1_SET0, val); + udelay(100); + + val = mv_u3d_phy_read(base, USB3_GEN2_SET0); + val &= ~(USB3_GEN2_SET0_G2_TX_AMP_MASK + | USB3_GEN2_SET0_G2_TX_EMPH_AMP_MASK + | USB3_GEN2_SET0_G2_TX_SLEW_CTRL_EN_MASK); + val |= ((0x14 << USB3_GEN2_SET0_G2_TX_AMP_SHIFT) + | (1 << USB3_GEN2_SET0_G2_TX_AMP_ADJ_SHIFT) + | (0xA << USB3_GEN2_SET0_G2_TX_EMPH_AMP_SHIFT) + | (1 << USB3_GEN2_SET0_G2_TX_EMPH_EN_SHIFT)); + mv_u3d_phy_write(base, USB3_GEN2_SET0, val); + udelay(100); + + mv_u3d_phy_read(base, USB3_TX_EMPPH); + val &= ~(USB3_TX_EMPPH_AMP_MASK + | USB3_TX_EMPPH_EN_MASK + | USB3_TX_EMPPH_AMP_FORCE_MASK + | USB3_TX_EMPPH_PAR1_MASK + | USB3_TX_EMPPH_PAR2_MASK); + val |= ((0xB << USB3_TX_EMPPH_AMP_SHIFT) + | (1 << USB3_TX_EMPPH_EN_SHIFT) + | (1 << USB3_TX_EMPPH_AMP_FORCE_SHIFT) + | (0x1C << USB3_TX_EMPPH_PAR1_SHIFT) + | (1 << USB3_TX_EMPPH_PAR2_SHIFT)); + + mv_u3d_phy_write(base, USB3_TX_EMPPH, val); + udelay(100); + + val = mv_u3d_phy_read(base, USB3_GEN2_SET1); + val &= ~(USB3_GEN2_SET1_G2_RX_SELMUPI_MASK + | USB3_GEN2_SET1_G2_RX_SELMUPF_MASK + | USB3_GEN2_SET1_G2_RX_SELMUFI_MASK + | USB3_GEN2_SET1_G2_RX_SELMUFF_MASK); + val |= ((1 << USB3_GEN2_SET1_G2_RX_SELMUPI_SHIFT) + | (1 << USB3_GEN2_SET1_G2_RX_SELMUPF_SHIFT) + | (1 << USB3_GEN2_SET1_G2_RX_SELMUFI_SHIFT) + | (1 << USB3_GEN2_SET1_G2_RX_SELMUFF_SHIFT)); + mv_u3d_phy_write(base, USB3_GEN2_SET1, val); + udelay(100); + + val = mv_u3d_phy_read(base, USB3_DIGITAL_LOOPBACK_EN); + val &= ~USB3_DIGITAL_LOOPBACK_EN_SEL_BITS_MASK; + val |= 1 << USB3_DIGITAL_LOOPBACK_EN_SEL_BITS_SHIFT; + mv_u3d_phy_write(base, USB3_DIGITAL_LOOPBACK_EN, val); + udelay(100); + + val = mv_u3d_phy_read(base, USB3_IMPEDANCE_TX_SSC); + val &= ~USB3_IMPEDANCE_TX_SSC_SSC_AMP_MASK; + val |= 0xC << USB3_IMPEDANCE_TX_SSC_SSC_AMP_SHIFT; + mv_u3d_phy_write(base, USB3_IMPEDANCE_TX_SSC, val); + udelay(100); + + val = mv_u3d_phy_read(base, USB3_IMPEDANCE_CALI_CTRL); + val &= ~USB3_IMPEDANCE_CALI_CTRL_IMP_CAL_THR_MASK; + val |= 0x4 << USB3_IMPEDANCE_CALI_CTRL_IMP_CAL_THR_SHIFT; + mv_u3d_phy_write(base, USB3_IMPEDANCE_CALI_CTRL, val); + udelay(100); + + val = mv_u3d_phy_read(base, USB3_PHY_ISOLATION_MODE); + val &= ~(USB3_PHY_ISOLATION_MODE_PHY_GEN_RX_MASK + | USB3_PHY_ISOLATION_MODE_PHY_GEN_TX_MASK + | USB3_PHY_ISOLATION_MODE_TX_DRV_IDLE_MASK); + val |= ((1 << USB3_PHY_ISOLATION_MODE_PHY_GEN_RX_SHIFT) + | (1 << USB3_PHY_ISOLATION_MODE_PHY_GEN_TX_SHIFT)); + mv_u3d_phy_write(base, USB3_PHY_ISOLATION_MODE, val); + udelay(100); + + val = mv_u3d_phy_read(base, USB3_TXDETRX); + val &= ~(USB3_TXDETRX_VTHSEL_MASK); + val |= 0x1 << USB3_TXDETRX_VTHSEL_SHIFT; + mv_u3d_phy_write(base, USB3_TXDETRX, val); + udelay(100); + + dev_dbg(mv_u3d_phy->dev, "start calibration\n"); + +calstart: + /* Perform Manual Calibration */ + mv_u3d_phy_set(base, USB3_KVCO_CALI_CONTROL, + 1 << USB3_KVCO_CALI_CONTROL_CAL_START_SHIFT); + + mdelay(1); + + count = 0; + while (1) { + val = mv_u3d_phy_read(base, USB3_KVCO_CALI_CONTROL); + if (val & (1 << USB3_KVCO_CALI_CONTROL_CAL_DONE_SHIFT)) + break; + else if (count > 50) { + dev_dbg(mv_u3d_phy->dev, "calibration failure, retry...\n"); + goto calstart; + } + count++; + mdelay(1); + } + + /* active PIPE interface */ + mv_u3d_phy_write(base, USB3_PIPE_SM_CTRL, + 1 << USB3_PIPE_SM_CTRL_PHY_INIT_DONE); + + return 0; +} + +static int __devinit mv_u3d_phy_probe(struct platform_device *pdev) +{ + struct mv_u3d_phy *mv_u3d_phy; + struct mv_usb_platform_data *pdata; + struct device *dev = &pdev->dev; + struct resource *res; + void __iomem *phy_base; + int ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "%s: no platform data defined\n", __func__); + return -EINVAL; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "missing mem resource\n"); + return -ENODEV; + } + + phy_base = devm_request_and_ioremap(dev, res); + if (!phy_base) { + dev_err(dev, "%s: register mapping failed\n", __func__); + return -ENXIO; + } + + mv_u3d_phy = devm_kzalloc(dev, sizeof(*mv_u3d_phy), GFP_KERNEL); + if (!mv_u3d_phy) + return -ENOMEM; + + mv_u3d_phy->dev = &pdev->dev; + mv_u3d_phy->plat = pdata; + mv_u3d_phy->base = phy_base; + mv_u3d_phy->phy.dev = mv_u3d_phy->dev; + mv_u3d_phy->phy.label = "mv-u3d-phy"; + mv_u3d_phy->phy.init = mv_u3d_phy_init; + mv_u3d_phy->phy.shutdown = mv_u3d_phy_shutdown; + + ret = usb_add_phy(&mv_u3d_phy->phy, USB_PHY_TYPE_USB3); + if (ret) + goto err; + + if (!mv_u3d_phy->clk) + mv_u3d_phy->clk = clk_get(mv_u3d_phy->dev, "u3dphy"); + + platform_set_drvdata(pdev, mv_u3d_phy); + + dev_info(&pdev->dev, "Initialized Marvell USB 3.0 PHY\n"); +err: + return ret; +} + +static int __exit mv_u3d_phy_remove(struct platform_device *pdev) +{ + struct mv_u3d_phy *mv_u3d_phy = platform_get_drvdata(pdev); + + usb_remove_phy(&mv_u3d_phy->phy); + + if (mv_u3d_phy->clk) { + clk_put(mv_u3d_phy->clk); + mv_u3d_phy->clk = NULL; + } + + return 0; +} + +static struct platform_driver mv_u3d_phy_driver = { + .probe = mv_u3d_phy_probe, + .remove = __devexit_p(mv_u3d_phy_remove), + .driver = { + .name = "mv-u3d-phy", + .owner = THIS_MODULE, + }, +}; + +module_platform_driver(mv_u3d_phy_driver); +MODULE_DESCRIPTION("Marvell USB 3.0 PHY controller"); +MODULE_AUTHOR("Yu Xu "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:mv-u3d-phy"); diff --git a/drivers/usb/phy/mv_u3d_phy.h b/drivers/usb/phy/mv_u3d_phy.h new file mode 100644 index 0000000..2a658cb --- /dev/null +++ b/drivers/usb/phy/mv_u3d_phy.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2011 Marvell International Ltd. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + */ + +#ifndef __MV_U3D_PHY_H +#define __MV_U3D_PHY_H + +#define USB3_POWER_PLL_CONTROL 0x1 +#define USB3_KVCO_CALI_CONTROL 0x2 +#define USB3_IMPEDANCE_CALI_CTRL 0x3 +#define USB3_IMPEDANCE_TX_SSC 0x4 +#define USB3_SQUELCH_FFE 0x6 +#define USB3_GEN1_SET0 0xD +#define USB3_GEN2_SET0 0xF +#define USB3_GEN2_SET1 0x10 +#define USB3_DIGITAL_LOOPBACK_EN 0x23 +#define USB3_PHY_ISOLATION_MODE 0x26 +#define USB3_TXDETRX 0x48 +#define USB3_TX_EMPPH 0x5E +#define USB3_RESET_CONTROL 0x90 +#define USB3_PIPE_SM_CTRL 0x91 + +#define USB3_RESET_CONTROL_RESET_PIPE 0x1 +#define USB3_RESET_CONTROL_RESET_PHY 0x2 + +#define USB3_POWER_PLL_CONTROL_REF_FREF_SEL_MASK (0x1F << 0) +#define USB3_POWER_PLL_CONTROL_REF_FREF_SEL_SHIFT 0 +#define USB3_PLL_25MHZ 0x2 +#define USB3_PLL_26MHZ 0x5 +#define USB3_POWER_PLL_CONTROL_PHY_MODE_MASK (0x7 << 5) +#define USB3_POWER_PLL_CONTROL_PHY_MODE_SHIFT 5 +#define USB3_POWER_PLL_CONTROL_PU_MASK (0xF << 12) +#define USB3_POWER_PLL_CONTROL_PU_SHIFT 12 +#define USB3_POWER_PLL_CONTROL_PU (0xF << 12) + +#define USB3_KVCO_CALI_CONTROL_USE_MAX_PLL_RATE_MASK (0x1 << 12) +#define USB3_KVCO_CALI_CONTROL_USE_MAX_PLL_RATE_SHIFT 12 +#define USB3_KVCO_CALI_CONTROL_CAL_DONE_SHIFT 14 +#define USB3_KVCO_CALI_CONTROL_CAL_START_SHIFT 15 + +#define USB3_SQUELCH_FFE_FFE_CAP_SEL_MASK 0xF +#define USB3_SQUELCH_FFE_FFE_CAP_SEL_SHIFT 0 +#define USB3_SQUELCH_FFE_FFE_RES_SEL_MASK (0x7 << 4) +#define USB3_SQUELCH_FFE_FFE_RES_SEL_SHIFT 4 +#define USB3_SQUELCH_FFE_SQ_THRESH_IN_MASK (0x1F << 8) +#define USB3_SQUELCH_FFE_SQ_THRESH_IN_SHIFT 8 + +#define USB3_GEN1_SET0_G1_TX_SLEW_CTRL_EN_MASK (0x1 << 15) +#define USB3_GEN1_SET0_G1_TX_EMPH_EN_SHIFT 11 + +#define USB3_GEN2_SET0_G2_TX_AMP_MASK (0x1F << 1) +#define USB3_GEN2_SET0_G2_TX_AMP_SHIFT 1 +#define USB3_GEN2_SET0_G2_TX_AMP_ADJ_SHIFT 6 +#define USB3_GEN2_SET0_G2_TX_EMPH_AMP_MASK (0xF << 7) +#define USB3_GEN2_SET0_G2_TX_EMPH_AMP_SHIFT 7 +#define USB3_GEN2_SET0_G2_TX_EMPH_EN_MASK (0x1 << 11) +#define USB3_GEN2_SET0_G2_TX_EMPH_EN_SHIFT 11 +#define USB3_GEN2_SET0_G2_TX_SLEW_CTRL_EN_MASK (0x1 << 15) +#define USB3_GEN2_SET0_G2_TX_SLEW_CTRL_EN_SHIFT 15 + +#define USB3_GEN2_SET1_G2_RX_SELMUPI_MASK (0x7 << 0) +#define USB3_GEN2_SET1_G2_RX_SELMUPI_SHIFT 0 +#define USB3_GEN2_SET1_G2_RX_SELMUPF_MASK (0x7 << 3) +#define USB3_GEN2_SET1_G2_RX_SELMUPF_SHIFT 3 +#define USB3_GEN2_SET1_G2_RX_SELMUFI_MASK (0x3 << 6) +#define USB3_GEN2_SET1_G2_RX_SELMUFI_SHIFT 6 +#define USB3_GEN2_SET1_G2_RX_SELMUFF_MASK (0x3 << 8) +#define USB3_GEN2_SET1_G2_RX_SELMUFF_SHIFT 8 + +#define USB3_DIGITAL_LOOPBACK_EN_SEL_BITS_MASK (0x3 << 10) +#define USB3_DIGITAL_LOOPBACK_EN_SEL_BITS_SHIFT 10 + +#define USB3_IMPEDANCE_CALI_CTRL_IMP_CAL_THR_MASK (0x7 << 12) +#define USB3_IMPEDANCE_CALI_CTRL_IMP_CAL_THR_SHIFT 12 + +#define USB3_IMPEDANCE_TX_SSC_SSC_AMP_MASK (0x3F << 0) +#define USB3_IMPEDANCE_TX_SSC_SSC_AMP_SHIFT 0 + +#define USB3_PHY_ISOLATION_MODE_PHY_GEN_RX_MASK 0xF +#define USB3_PHY_ISOLATION_MODE_PHY_GEN_RX_SHIFT 0 +#define USB3_PHY_ISOLATION_MODE_PHY_GEN_TX_MASK (0xF << 4) +#define USB3_PHY_ISOLATION_MODE_PHY_GEN_TX_SHIFT 4 +#define USB3_PHY_ISOLATION_MODE_TX_DRV_IDLE_MASK (0x1 << 8) + +#define USB3_TXDETRX_VTHSEL_MASK (0x3 << 4) +#define USB3_TXDETRX_VTHSEL_SHIFT 4 + +#define USB3_TX_EMPPH_AMP_MASK (0xF << 0) +#define USB3_TX_EMPPH_AMP_SHIFT 0 +#define USB3_TX_EMPPH_EN_MASK (0x1 << 6) +#define USB3_TX_EMPPH_EN_SHIFT 6 +#define USB3_TX_EMPPH_AMP_FORCE_MASK (0x1 << 7) +#define USB3_TX_EMPPH_AMP_FORCE_SHIFT 7 +#define USB3_TX_EMPPH_PAR1_MASK (0x1F << 8) +#define USB3_TX_EMPPH_PAR1_SHIFT 8 +#define USB3_TX_EMPPH_PAR2_MASK (0x1 << 13) +#define USB3_TX_EMPPH_PAR2_SHIFT 13 + +#define USB3_PIPE_SM_CTRL_PHY_INIT_DONE 15 + +#endif /* __MV_U3D_PHY_H */ -- cgit v0.10.2 From 07a67bbb95ea7977846bd851dab5f4f2be8e488c Mon Sep 17 00:00:00 2001 From: Shubhrajyoti D Date: Thu, 9 Aug 2012 20:08:32 +0530 Subject: usb: musb: Make dma_controller_create __devinit dma_controller_create is called only from musb_init_controller which is __devint so annotate dma_controller_create also with __devint. fixes the warn WARNING: vmlinux.o(.devinit.text+0x6fa8): Section mismatch in reference from the function musb_init_controller() to the function .init.text:dma_controller_create() The function __devinit musb_init_controller() references a function __init dma_controller_create(). If dma_controller_create is only used by musb_init_controller then annotate dma_controller_create with a matching annotation. Signed-off-by: Shubhrajyoti D Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index 8637c1f..e19da82 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c @@ -1316,7 +1316,7 @@ irqreturn_t cppi_interrupt(int irq, void *dev_id) } /* Instantiate a software object representing a DMA controller. */ -struct dma_controller *__init +struct dma_controller *__devinit dma_controller_create(struct musb *musb, void __iomem *mregs) { struct cppi *controller; diff --git a/drivers/usb/musb/musb_dma.h b/drivers/usb/musb/musb_dma.h index 3a97c4e..24d3921 100644 --- a/drivers/usb/musb/musb_dma.h +++ b/drivers/usb/musb/musb_dma.h @@ -178,7 +178,7 @@ struct dma_controller { extern void musb_dma_completion(struct musb *musb, u8 epnum, u8 transmit); -extern struct dma_controller *__init +extern struct dma_controller *__devinit dma_controller_create(struct musb *, void __iomem *); extern void dma_controller_destroy(struct dma_controller *); diff --git a/drivers/usb/musb/musbhsdma.c b/drivers/usb/musb/musbhsdma.c index 57a6085..444b9ee 100644 --- a/drivers/usb/musb/musbhsdma.c +++ b/drivers/usb/musb/musbhsdma.c @@ -380,7 +380,7 @@ void dma_controller_destroy(struct dma_controller *c) kfree(controller); } -struct dma_controller *__init +struct dma_controller *__devinit dma_controller_create(struct musb *musb, void __iomem *base) { struct musb_dma_controller *controller; diff --git a/drivers/usb/musb/tusb6010_omap.c b/drivers/usb/musb/tusb6010_omap.c index b67b4bc..53e2596 100644 --- a/drivers/usb/musb/tusb6010_omap.c +++ b/drivers/usb/musb/tusb6010_omap.c @@ -662,7 +662,7 @@ void dma_controller_destroy(struct dma_controller *c) kfree(tusb_dma); } -struct dma_controller *__init +struct dma_controller *__devinit dma_controller_create(struct musb *musb, void __iomem *base) { void __iomem *tbase = musb->ctrl_base; diff --git a/drivers/usb/musb/ux500_dma.c b/drivers/usb/musb/ux500_dma.c index d05c7fb..639d58e 100644 --- a/drivers/usb/musb/ux500_dma.c +++ b/drivers/usb/musb/ux500_dma.c @@ -364,7 +364,7 @@ void dma_controller_destroy(struct dma_controller *c) kfree(controller); } -struct dma_controller *__init +struct dma_controller *__devinit dma_controller_create(struct musb *musb, void __iomem *base) { struct ux500_dma_controller *controller; -- cgit v0.10.2 From b7e38aa67d73cbb9d5d2e1e5de379f473fa7d7bf Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Fri, 10 Aug 2012 09:16:43 +0300 Subject: usb: dwc3: core: use devm_iremap_nocache() version This just guarantees that this piece of memory will be marked uncachable. Signed-off-by: Felipe Balbi diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c34452a..4f2ef53 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -459,7 +459,7 @@ static int __devinit dwc3_probe(struct platform_device *pdev) return -ENOMEM; } - regs = devm_ioremap(dev, res->start, resource_size(res)); + regs = devm_ioremap_nocache(dev, res->start, resource_size(res)); if (!regs) { dev_err(dev, "ioremap failed\n"); return -ENOMEM; -- cgit v0.10.2 From 1139b4516f3927ae835ed3b0a9c69a0dfaf4cdd4 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Mon, 30 Jul 2012 09:29:12 +0200 Subject: USB: ohci-pxa27x: add DT bindings Add DT bindings to the ohci-pxa27x driver and some documentation. Successfully tested on a PXA3xx board. Signed-off-by: Daniel Mack Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/devicetree/bindings/usb/pxa-usb.txt b/Documentation/devicetree/bindings/usb/pxa-usb.txt new file mode 100644 index 0000000..79729a9 --- /dev/null +++ b/Documentation/devicetree/bindings/usb/pxa-usb.txt @@ -0,0 +1,31 @@ +PXA USB controllers + +OHCI + +Required properties: + - compatible: Should be "marvell,pxa-ohci" for USB controllers + used in host mode. + +Optional properties: + - "marvell,enable-port1", "marvell,enable-port2", "marvell,enable-port3" + If present, enables the appropriate USB port of the controller. + - "marvell,port-mode" selects the mode of the ports: + 1 = PMM_NPS_MODE + 2 = PMM_GLOBAL_MODE + 3 = PMM_PERPORT_MODE + - "marvell,power-sense-low" - power sense pin is low-active. + - "marvell,power-control-low" - power control pin is low-active. + - "marvell,no-oc-protection" - disable over-current protection. + - "marvell,oc-mode-perport" - enable per-port over-current protection. + - "marvell,power_on_delay" Power On to Power Good time - in ms. + +Example: + + usb0: ohci@4c000000 { + compatible = "marvell,pxa-ohci", "usb-ohci"; + reg = <0x4c000000 0x100000>; + interrupts = <18>; + marvell,enable-port1; + marvell,port-mode = <2>; /* PMM_GLOBAL_MODE */ + }; + diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index e1a3cc6..77f4402 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include #include @@ -272,6 +274,67 @@ static void pxa27x_stop_hc(struct pxa27x_ohci *ohci, struct device *dev) clk_disable_unprepare(ohci->clk); } +#ifdef CONFIG_OF +static const struct of_device_id pxa_ohci_dt_ids[] = { + { .compatible = "marvell,pxa-ohci" }, + { } +}; + +MODULE_DEVICE_TABLE(of, pxa_ohci_dt_ids); + +static u64 pxa_ohci_dma_mask = DMA_BIT_MASK(32); + +static int __devinit ohci_pxa_of_init(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct pxaohci_platform_data *pdata; + u32 tmp; + + if (!np) + return 0; + + /* Right now device-tree probed devices don't get dma_mask set. + * Since shared usb code relies on it, set it here for now. + * Once we have dma capability bindings this can go away. + */ + if (!pdev->dev.dma_mask) + pdev->dev.dma_mask = &pxa_ohci_dma_mask; + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + if (of_get_property(np, "marvell,enable-port1", NULL)) + pdata->flags |= ENABLE_PORT1; + if (of_get_property(np, "marvell,enable-port2", NULL)) + pdata->flags |= ENABLE_PORT2; + if (of_get_property(np, "marvell,enable-port3", NULL)) + pdata->flags |= ENABLE_PORT3; + if (of_get_property(np, "marvell,port-sense-low", NULL)) + pdata->flags |= POWER_SENSE_LOW; + if (of_get_property(np, "marvell,power-control-low", NULL)) + pdata->flags |= POWER_CONTROL_LOW; + if (of_get_property(np, "marvell,no-oc-protection", NULL)) + pdata->flags |= NO_OC_PROTECTION; + if (of_get_property(np, "marvell,oc-mode-perport", NULL)) + pdata->flags |= OC_MODE_PERPORT; + if (!of_property_read_u32(np, "marvell,power-on-delay", &tmp)) + pdata->power_on_delay = tmp; + if (!of_property_read_u32(np, "marvell,port-mode", &tmp)) + pdata->port_mode = tmp; + if (!of_property_read_u32(np, "marvell,power-budget", &tmp)) + pdata->power_budget = tmp; + + pdev->dev.platform_data = pdata; + + return 0; +} +#else +static int __devinit ohci_pxa_of_init(struct platform_device *pdev) +{ + return 0; +} +#endif /*-------------------------------------------------------------------------*/ @@ -297,6 +360,10 @@ int usb_hcd_pxa27x_probe (const struct hc_driver *driver, struct platform_device struct resource *r; struct clk *usb_clk; + retval = ohci_pxa_of_init(pdev); + if (retval) + return retval; + inf = pdev->dev.platform_data; if (!inf) @@ -544,6 +611,7 @@ static struct platform_driver ohci_hcd_pxa27x_driver = { .driver = { .name = "pxa27x-ohci", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(pxa_ohci_dt_ids), #ifdef CONFIG_PM .pm = &ohci_hcd_pxa27x_pm_ops, #endif -- cgit v0.10.2 From a816e3113b63753c330ca4751ea1d208e93e3015 Mon Sep 17 00:00:00 2001 From: Ying Xue Date: Mon, 6 Aug 2012 17:46:37 +0800 Subject: USB: ftdi_sio: Quiet sparse noise about using plain integer was NULL pointer Pointers should not be compared to plain integers. Quiets the sparse warning: warning: Using plain integer as NULL pointer Signed-off-by: Ying Xue Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index bc912e5..70688cb 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -2106,7 +2106,7 @@ static void ftdi_set_termios(struct tty_struct *tty, cflag = termios->c_cflag; - if (old_termios == 0) + if (!old_termios) goto no_skip; if (old_termios->c_cflag == termios->c_cflag -- cgit v0.10.2 From 979834313271203d1e6e84241cc3aca4503a3dbb Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 29 Jul 2012 21:46:05 +0200 Subject: drivers/usb/host/ehci-atmel.c: use devm_ functions The various devm_ functions allocate memory that is released when a driver detaches. This patch uses these functions for data that is allocated in the probe function of a platform device and is only freed in the remove function. Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c index a47e2cf..411bb74 100644 --- a/drivers/usb/host/ehci-atmel.c +++ b/drivers/usb/host/ehci-atmel.c @@ -150,31 +150,24 @@ static int __devinit ehci_atmel_drv_probe(struct platform_device *pdev) hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, - driver->description)) { - dev_dbg(&pdev->dev, "controller already in use\n"); - retval = -EBUSY; - goto fail_request_resource; - } - - hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = devm_request_and_ioremap(&pdev->dev, res); if (hcd->regs == NULL) { dev_dbg(&pdev->dev, "error mapping memory\n"); retval = -EFAULT; - goto fail_ioremap; + goto fail_request_resource; } - iclk = clk_get(&pdev->dev, "ehci_clk"); + iclk = devm_clk_get(&pdev->dev, "ehci_clk"); if (IS_ERR(iclk)) { dev_err(&pdev->dev, "Error getting interface clock\n"); retval = -ENOENT; - goto fail_get_iclk; + goto fail_request_resource; } - fclk = clk_get(&pdev->dev, "uhpck"); + fclk = devm_clk_get(&pdev->dev, "uhpck"); if (IS_ERR(fclk)) { dev_err(&pdev->dev, "Error getting function clock\n"); retval = -ENOENT; - goto fail_get_fclk; + goto fail_request_resource; } atmel_start_ehci(pdev); @@ -187,13 +180,6 @@ static int __devinit ehci_atmel_drv_probe(struct platform_device *pdev) fail_add_hcd: atmel_stop_ehci(pdev); - clk_put(fclk); -fail_get_fclk: - clk_put(iclk); -fail_get_iclk: - iounmap(hcd->regs); -fail_ioremap: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); fail_request_resource: usb_put_hcd(hcd); fail_create_hcd: @@ -209,13 +195,9 @@ static int __devexit ehci_atmel_drv_remove(struct platform_device *pdev) ehci_shutdown(hcd); usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); atmel_stop_ehci(pdev); - clk_put(fclk); - clk_put(iclk); fclk = iclk = NULL; return 0; -- cgit v0.10.2 From 8ca41ae35f5567280eac787a9cc9bcd5988b9f82 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 29 Jul 2012 21:46:06 +0200 Subject: drivers/usb/host/ehci-au1xxx.c: use devm_ functions The various devm_ functions allocate memory that is released when a driver detaches. This patch uses these functions for data that is allocated in the probe function of a platform device and is only freed in the remove function. Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c index cba10d6..65c945e 100644 --- a/drivers/usb/host/ehci-au1xxx.c +++ b/drivers/usb/host/ehci-au1xxx.c @@ -98,23 +98,17 @@ static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev) hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - pr_debug("request_mem_region failed"); - ret = -EBUSY; - goto err1; - } - - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = devm_request_and_ioremap(&pdev->dev, res); if (!hcd->regs) { - pr_debug("ioremap failed"); + pr_debug("devm_request_and_ioremap failed"); ret = -ENOMEM; - goto err2; + goto err1; } if (alchemy_usb_control(ALCHEMY_USB_EHCI0, 1)) { printk(KERN_INFO "%s: controller init failed!\n", pdev->name); ret = -ENODEV; - goto err3; + goto err1; } ret = usb_add_hcd(hcd, pdev->resource[1].start, @@ -125,10 +119,6 @@ static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev) } alchemy_usb_control(ALCHEMY_USB_EHCI0, 0); -err3: - iounmap(hcd->regs); -err2: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); err1: usb_put_hcd(hcd); return ret; @@ -140,8 +130,6 @@ static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev) usb_remove_hcd(hcd); alchemy_usb_control(ALCHEMY_USB_EHCI0, 0); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); platform_set_drvdata(pdev, NULL); -- cgit v0.10.2 From f0675e2a99dd305114986d22e2572c72bd69804b Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 29 Jul 2012 21:46:07 +0200 Subject: drivers/usb/host/ehci-cns3xxx.c: use devm_ functions The various devm_ functions allocate memory that is released when a driver detaches. This patch uses these functions for data that is allocated in the probe function of a platform device and is only freed in the remove function. Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-cns3xxx.c b/drivers/usb/host/ehci-cns3xxx.c index caaa3e5..d91708d 100644 --- a/drivers/usb/host/ehci-cns3xxx.c +++ b/drivers/usb/host/ehci-cns3xxx.c @@ -105,27 +105,17 @@ static int cns3xxx_ehci_probe(struct platform_device *pdev) hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, - driver->description)) { - dev_dbg(dev, "controller already in use\n"); - retval = -EBUSY; - goto err1; - } - - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = devm_request_and_ioremap(&pdev->dev, res); if (hcd->regs == NULL) { dev_dbg(dev, "error mapping memory\n"); retval = -EFAULT; - goto err2; + goto err1; } retval = usb_add_hcd(hcd, irq, IRQF_SHARED); if (retval == 0) return retval; - iounmap(hcd->regs); -err2: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); err1: usb_put_hcd(hcd); @@ -137,8 +127,6 @@ static int cns3xxx_ehci_remove(struct platform_device *pdev) struct usb_hcd *hcd = platform_get_drvdata(pdev); usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); /* * EHCI and OHCI share the same clock and power, -- cgit v0.10.2 From 436f271996a1925e506d5004dcbf62bce24e5777 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 29 Jul 2012 21:46:08 +0200 Subject: drivers/usb/host/ehci-grlib.c: use devm_ functions The various devm_ functions allocate memory that is released when a driver detaches. This patch uses these functions for data that is allocated in the probe function of a platform device and is only freed in the remove function. Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c index 22ca45c..3180cb3 100644 --- a/drivers/usb/host/ehci-grlib.c +++ b/drivers/usb/host/ehci-grlib.c @@ -127,12 +127,6 @@ static int __devinit ehci_hcd_grlib_probe(struct platform_device *op) hcd->rsrc_start = res.start; hcd->rsrc_len = resource_size(&res); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - printk(KERN_ERR "%s: request_mem_region failed\n", __FILE__); - rv = -EBUSY; - goto err_rmr; - } - irq = irq_of_parse_and_map(dn, 0); if (irq == NO_IRQ) { printk(KERN_ERR "%s: irq_of_parse_and_map failed\n", __FILE__); @@ -140,9 +134,9 @@ static int __devinit ehci_hcd_grlib_probe(struct platform_device *op) goto err_irq; } - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = devm_request_and_ioremap(&op->dev, &res); if (!hcd->regs) { - printk(KERN_ERR "%s: ioremap failed\n", __FILE__); + pr_err("%s: devm_request_and_ioremap failed\n", __FILE__); rv = -ENOMEM; goto err_ioremap; } @@ -161,17 +155,13 @@ static int __devinit ehci_hcd_grlib_probe(struct platform_device *op) rv = usb_add_hcd(hcd, irq, 0); if (rv) - goto err_ehci; + goto err_ioremap; return 0; -err_ehci: - iounmap(hcd->regs); err_ioremap: irq_dispose_mapping(irq); err_irq: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err_rmr: usb_put_hcd(hcd); return rv; @@ -188,9 +178,7 @@ static int ehci_hcd_grlib_remove(struct platform_device *op) usb_remove_hcd(hcd); - iounmap(hcd->regs); irq_dispose_mapping(hcd->irq); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); -- cgit v0.10.2 From 1feda3ed2e5b5968c8393c0e7fe2c27a06a0f4f7 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 29 Jul 2012 21:46:09 +0200 Subject: drivers/usb/host/ehci-ixp4xx.c: use devm_ functions The various devm_ functions allocate memory that is released when a driver detaches. This patch uses these functions for data that is allocated in the probe function of a platform device and is only freed in the remove function. Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-ixp4xx.c b/drivers/usb/host/ehci-ixp4xx.c index 488d401..f224c0a 100644 --- a/drivers/usb/host/ehci-ixp4xx.c +++ b/drivers/usb/host/ehci-ixp4xx.c @@ -98,30 +98,19 @@ static int ixp4xx_ehci_probe(struct platform_device *pdev) hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, - driver->description)) { - dev_dbg(&pdev->dev, "controller already in use\n"); - retval = -EBUSY; - goto fail_request_resource; - } - - hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = devm_request_and_ioremap(&pdev->dev, res); if (hcd->regs == NULL) { dev_dbg(&pdev->dev, "error mapping memory\n"); retval = -EFAULT; - goto fail_ioremap; + goto fail_request_resource; } retval = usb_add_hcd(hcd, irq, IRQF_SHARED); if (retval) - goto fail_add_hcd; + goto fail_request_resource; return retval; -fail_add_hcd: - iounmap(hcd->regs); -fail_ioremap: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); fail_request_resource: usb_put_hcd(hcd); fail_create_hcd: @@ -134,8 +123,6 @@ static int ixp4xx_ehci_remove(struct platform_device *pdev) struct usb_hcd *hcd = platform_get_drvdata(pdev); usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); return 0; -- cgit v0.10.2 From 84b79838b9bcf7a9c2c09f4de930b8d476f1e70b Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 29 Jul 2012 21:46:10 +0200 Subject: drivers/usb/host/ehci-ls1x.c: use devm_ functions The various devm_ functions allocate memory that is released when a driver detaches. This patch uses these functions for data that is allocated in the probe function of a platform device and is only freed in the remove function. Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-ls1x.c b/drivers/usb/host/ehci-ls1x.c index a283e59..aa0f328 100644 --- a/drivers/usb/host/ehci-ls1x.c +++ b/drivers/usb/host/ehci-ls1x.c @@ -106,29 +106,19 @@ static int ehci_hcd_ls1x_probe(struct platform_device *pdev) hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - dev_dbg(&pdev->dev, "controller already in use\n"); - ret = -EBUSY; - goto err_put_hcd; - } - - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = devm_request_and_ioremap(&pdev->dev, res); if (hcd->regs == NULL) { dev_dbg(&pdev->dev, "error mapping memory\n"); ret = -EFAULT; - goto err_release_region; + goto err_put_hcd; } ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); if (ret) - goto err_iounmap; + goto err_put_hcd; return ret; -err_iounmap: - iounmap(hcd->regs); -err_release_region: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); err_put_hcd: usb_put_hcd(hcd); return ret; @@ -139,8 +129,6 @@ static int ehci_hcd_ls1x_remove(struct platform_device *pdev) struct usb_hcd *hcd = platform_get_drvdata(pdev); usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); return 0; -- cgit v0.10.2 From df5eb3ffa8bfd23be8189cb0c58ed0c4902b6bfd Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 29 Jul 2012 21:46:11 +0200 Subject: drivers/usb/host/ehci-msm.c: use devm_ functions The various devm_ functions allocate memory that is released when a driver detaches. This patch uses these functions for data that is allocated in the probe function of a platform device and is only freed in the remove function. The original code was also missing a call to iounmap(hcd->regs); in the remove function, so this patch also implicitly fixes a bug. Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index 17dd9e9..4af4dc5 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -133,7 +133,7 @@ static int ehci_msm_probe(struct platform_device *pdev) hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = devm_ioremap(&pdev->dev, hcd->rsrc_start, hcd->rsrc_len); if (!hcd->regs) { dev_err(&pdev->dev, "ioremap failed\n"); ret = -ENOMEM; @@ -145,17 +145,17 @@ static int ehci_msm_probe(struct platform_device *pdev) * powering up VBUS, mapping of registers address space and power * management. */ - phy = usb_get_phy(USB_PHY_TYPE_USB2); + phy = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); if (IS_ERR_OR_NULL(phy)) { dev_err(&pdev->dev, "unable to find transceiver\n"); ret = -ENODEV; - goto unmap; + goto put_hcd; } ret = otg_set_host(phy->otg, &hcd->self); if (ret < 0) { dev_err(&pdev->dev, "unable to register with transceiver\n"); - goto put_transceiver; + goto put_hcd; } device_init_wakeup(&pdev->dev, 1); @@ -168,10 +168,6 @@ static int ehci_msm_probe(struct platform_device *pdev) return 0; -put_transceiver: - usb_put_phy(phy); -unmap: - iounmap(hcd->regs); put_hcd: usb_put_hcd(hcd); @@ -187,7 +183,6 @@ static int __devexit ehci_msm_remove(struct platform_device *pdev) pm_runtime_set_suspended(&pdev->dev); otg_set_host(phy->otg, NULL); - usb_put_phy(phy); usb_put_hcd(hcd); -- cgit v0.10.2 From 35b55563dffd4a68988077e402ddd330e8cfa580 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 29 Jul 2012 21:46:12 +0200 Subject: drivers/usb/host/ehci-mv.c: use devm_ functions The various devm_ functions allocate memory that is released when a driver detaches. This patch uses these functions for data that is allocated in the probe function of a platform device and is only freed in the remove function. A new label name is created in one case to better reflect the contents of the error-handling code. Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c index f6df1cc..f7bfc0b 100644 --- a/drivers/usb/host/ehci-mv.c +++ b/drivers/usb/host/ehci-mv.c @@ -161,7 +161,7 @@ static int mv_ehci_probe(struct platform_device *pdev) return -ENOMEM; size = sizeof(*ehci_mv) + sizeof(struct clk *) * pdata->clknum; - ehci_mv = kzalloc(size, GFP_KERNEL); + ehci_mv = devm_kzalloc(&pdev->dev, size, GFP_KERNEL); if (ehci_mv == NULL) { dev_err(&pdev->dev, "cannot allocate ehci_hcd_mv\n"); retval = -ENOMEM; @@ -175,12 +175,12 @@ static int mv_ehci_probe(struct platform_device *pdev) ehci_mv->clknum = pdata->clknum; for (clk_i = 0; clk_i < ehci_mv->clknum; clk_i++) { ehci_mv->clk[clk_i] = - clk_get(&pdev->dev, pdata->clkname[clk_i]); + devm_clk_get(&pdev->dev, pdata->clkname[clk_i]); if (IS_ERR(ehci_mv->clk[clk_i])) { dev_err(&pdev->dev, "error get clck \"%s\"\n", pdata->clkname[clk_i]); retval = PTR_ERR(ehci_mv->clk[clk_i]); - goto err_put_clk; + goto err_clear_drvdata; } } @@ -188,34 +188,36 @@ static int mv_ehci_probe(struct platform_device *pdev) if (r == NULL) { dev_err(&pdev->dev, "no phy I/O memory resource defined\n"); retval = -ENODEV; - goto err_put_clk; + goto err_clear_drvdata; } - ehci_mv->phy_regs = ioremap(r->start, resource_size(r)); + ehci_mv->phy_regs = devm_ioremap(&pdev->dev, r->start, + resource_size(r)); if (ehci_mv->phy_regs == 0) { dev_err(&pdev->dev, "failed to map phy I/O memory\n"); retval = -EFAULT; - goto err_put_clk; + goto err_clear_drvdata; } r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "capregs"); if (!r) { dev_err(&pdev->dev, "no I/O memory resource defined\n"); retval = -ENODEV; - goto err_iounmap_phyreg; + goto err_clear_drvdata; } - ehci_mv->cap_regs = ioremap(r->start, resource_size(r)); + ehci_mv->cap_regs = devm_ioremap(&pdev->dev, r->start, + resource_size(r)); if (ehci_mv->cap_regs == NULL) { dev_err(&pdev->dev, "failed to map I/O memory\n"); retval = -EFAULT; - goto err_iounmap_phyreg; + goto err_clear_drvdata; } retval = mv_ehci_enable(ehci_mv); if (retval) { dev_err(&pdev->dev, "init phy error %d\n", retval); - goto err_iounmap_capreg; + goto err_clear_drvdata; } offset = readl(ehci_mv->cap_regs) & CAPLENGTH_MASK; @@ -239,7 +241,7 @@ static int mv_ehci_probe(struct platform_device *pdev) ehci_mv->mode = pdata->mode; if (ehci_mv->mode == MV_USB_MODE_OTG) { #ifdef CONFIG_USB_OTG_UTILS - ehci_mv->otg = usb_get_phy(USB_PHY_TYPE_USB2); + ehci_mv->otg = devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); if (IS_ERR_OR_NULL(ehci_mv->otg)) { dev_err(&pdev->dev, "unable to find transceiver\n"); @@ -252,7 +254,7 @@ static int mv_ehci_probe(struct platform_device *pdev) dev_err(&pdev->dev, "unable to register with transceiver\n"); retval = -ENODEV; - goto err_put_transceiver; + goto err_disable_clk; } /* otg will enable clock before use as host */ mv_ehci_disable(ehci_mv); @@ -286,22 +288,10 @@ static int mv_ehci_probe(struct platform_device *pdev) err_set_vbus: if (pdata->set_vbus) pdata->set_vbus(0); -#ifdef CONFIG_USB_OTG_UTILS -err_put_transceiver: - if (!IS_ERR_OR_NULL(ehci_mv->otg)) - usb_put_phy(ehci_mv->otg); -#endif err_disable_clk: mv_ehci_disable(ehci_mv); -err_iounmap_capreg: - iounmap(ehci_mv->cap_regs); -err_iounmap_phyreg: - iounmap(ehci_mv->phy_regs); -err_put_clk: - for (clk_i--; clk_i >= 0; clk_i--) - clk_put(ehci_mv->clk[clk_i]); +err_clear_drvdata: platform_set_drvdata(pdev, NULL); - kfree(ehci_mv); err_put_hcd: usb_put_hcd(hcd); @@ -317,10 +307,8 @@ static int mv_ehci_remove(struct platform_device *pdev) if (hcd->rh_registered) usb_remove_hcd(hcd); - if (!IS_ERR_OR_NULL(ehci_mv->otg)) { + if (!IS_ERR_OR_NULL(ehci_mv->otg)) otg_set_host(ehci_mv->otg->otg, NULL); - usb_put_phy(ehci_mv->otg); - } if (ehci_mv->mode == MV_USB_MODE_HOST) { if (ehci_mv->pdata->set_vbus) @@ -329,15 +317,8 @@ static int mv_ehci_remove(struct platform_device *pdev) mv_ehci_disable(ehci_mv); } - iounmap(ehci_mv->cap_regs); - iounmap(ehci_mv->phy_regs); - - for (clk_i = 0; clk_i < ehci_mv->clknum; clk_i++) - clk_put(ehci_mv->clk[clk_i]); - platform_set_drvdata(pdev, NULL); - kfree(ehci_mv); usb_put_hcd(hcd); return 0; -- cgit v0.10.2 From af09c060895b9c9137c02943c71302ac0fc9555a Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 29 Jul 2012 21:46:13 +0200 Subject: drivers/usb/host/ehci-mxc.c: use devm_ functions The various devm_ functions allocate memory that is released when a driver detaches. This patch uses these functions for data that is allocated in the probe function of a platform device and is only freed in the remove function. Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index 3420137..959e1a4 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c @@ -121,7 +121,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) if (!hcd) return -ENOMEM; - priv = kzalloc(sizeof(*priv), GFP_KERNEL); + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) { ret = -ENOMEM; goto err_alloc; @@ -131,34 +131,28 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) if (!res) { dev_err(dev, "Found HC with no register addr. Check setup!\n"); ret = -ENODEV; - goto err_get_resource; + goto err_alloc; } hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - dev_dbg(dev, "controller already in use\n"); - ret = -EBUSY; - goto err_request_mem; - } - - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = devm_request_and_ioremap(&pdev->dev, res); if (!hcd->regs) { dev_err(dev, "error mapping memory\n"); ret = -EFAULT; - goto err_ioremap; + goto err_alloc; } /* enable clocks */ - priv->usbclk = clk_get(dev, "ipg"); + priv->usbclk = devm_clk_get(&pdev->dev, "ipg"); if (IS_ERR(priv->usbclk)) { ret = PTR_ERR(priv->usbclk); - goto err_clk; + goto err_alloc; } clk_prepare_enable(priv->usbclk); - priv->ahbclk = clk_get(dev, "ahb"); + priv->ahbclk = devm_clk_get(&pdev->dev, "ahb"); if (IS_ERR(priv->ahbclk)) { ret = PTR_ERR(priv->ahbclk); goto err_clk_ahb; @@ -166,7 +160,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) clk_prepare_enable(priv->ahbclk); /* "dr" device has its own clock on i.MX51 */ - priv->phyclk = clk_get(dev, "phy"); + priv->phyclk = devm_clk_get(&pdev->dev, "phy"); if (IS_ERR(priv->phyclk)) priv->phyclk = NULL; if (priv->phyclk) @@ -245,23 +239,12 @@ err_add: if (pdata && pdata->exit) pdata->exit(pdev); err_init: - if (priv->phyclk) { + if (priv->phyclk) clk_disable_unprepare(priv->phyclk); - clk_put(priv->phyclk); - } clk_disable_unprepare(priv->ahbclk); - clk_put(priv->ahbclk); err_clk_ahb: clk_disable_unprepare(priv->usbclk); - clk_put(priv->usbclk); -err_clk: - iounmap(hcd->regs); -err_ioremap: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err_request_mem: -err_get_resource: - kfree(priv); err_alloc: usb_put_hcd(hcd); return ret; @@ -280,22 +263,14 @@ static int __exit ehci_mxc_drv_remove(struct platform_device *pdev) usb_phy_shutdown(pdata->otg); usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); platform_set_drvdata(pdev, NULL); clk_disable_unprepare(priv->usbclk); - clk_put(priv->usbclk); clk_disable_unprepare(priv->ahbclk); - clk_put(priv->ahbclk); - if (priv->phyclk) { + if (priv->phyclk) clk_disable_unprepare(priv->phyclk); - clk_put(priv->phyclk); - } - - kfree(priv); return 0; } -- cgit v0.10.2 From 1c5404f7abd250ce71849c2687d266073b54e1d4 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 30 Jul 2012 16:43:45 +0200 Subject: drivers/usb/host/ehci-ppc-of.c: use devm_ functions The various devm_ functions allocate memory that is released when a driver detaches. This patch uses these functions for data that is allocated in the probe function of a platform device and is only freed in the remove function. Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c index bbbe89d..fa937d0 100644 --- a/drivers/usb/host/ehci-ppc-of.c +++ b/drivers/usb/host/ehci-ppc-of.c @@ -114,12 +114,6 @@ static int __devinit ehci_hcd_ppc_of_probe(struct platform_device *op) hcd->rsrc_start = res.start; hcd->rsrc_len = resource_size(&res); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - printk(KERN_ERR "%s: request_mem_region failed\n", __FILE__); - rv = -EBUSY; - goto err_rmr; - } - irq = irq_of_parse_and_map(dn, 0); if (irq == NO_IRQ) { printk(KERN_ERR "%s: irq_of_parse_and_map failed\n", __FILE__); @@ -127,9 +121,9 @@ static int __devinit ehci_hcd_ppc_of_probe(struct platform_device *op) goto err_irq; } - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = devm_request_and_ioremap(&op->dev, &res); if (!hcd->regs) { - printk(KERN_ERR "%s: ioremap failed\n", __FILE__); + pr_err("%s: devm_request_and_ioremap failed\n", __FILE__); rv = -ENOMEM; goto err_ioremap; } @@ -139,8 +133,10 @@ static int __devinit ehci_hcd_ppc_of_probe(struct platform_device *op) if (np != NULL) { /* claim we really affected by usb23 erratum */ if (!of_address_to_resource(np, 0, &res)) - ehci->ohci_hcctrl_reg = ioremap(res.start + - OHCI_HCCTRL_OFFSET, OHCI_HCCTRL_LEN); + ehci->ohci_hcctrl_reg = + devm_ioremap(&op->dev, + res.start + OHCI_HCCTRL_OFFSET, + OHCI_HCCTRL_LEN); else pr_debug("%s: no ohci offset in fdt\n", __FILE__); if (!ehci->ohci_hcctrl_reg) { @@ -169,19 +165,13 @@ static int __devinit ehci_hcd_ppc_of_probe(struct platform_device *op) rv = usb_add_hcd(hcd, irq, 0); if (rv) - goto err_ehci; + goto err_ioremap; return 0; -err_ehci: - if (ehci->has_amcc_usb23) - iounmap(ehci->ohci_hcctrl_reg); - iounmap(hcd->regs); err_ioremap: irq_dispose_mapping(irq); err_irq: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err_rmr: usb_put_hcd(hcd); return rv; @@ -202,9 +192,7 @@ static int ehci_hcd_ppc_of_remove(struct platform_device *op) usb_remove_hcd(hcd); - iounmap(hcd->regs); irq_dispose_mapping(hcd->irq); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); /* use request_mem_region to test if the ohci driver is loaded. if so * ensure the ohci core is operational. @@ -222,8 +210,6 @@ static int ehci_hcd_ppc_of_remove(struct platform_device *op) pr_debug("%s: no ohci offset in fdt\n", __FILE__); of_node_put(np); } - - iounmap(ehci->ohci_hcctrl_reg); } usb_put_hcd(hcd); -- cgit v0.10.2 From 63fd0ae4b7ca60f7322341b0fbd9cda2f3d2e22d Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 30 Jul 2012 16:43:44 +0200 Subject: drivers/usb/host/ehci-s5p.c: use devm_ functions The various devm_ functions allocate memory that is released when a driver detaches. This patch uses these functions for data that is allocated in the probe function of a platform device and is only freed in the remove function. Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c index 9d8f1dd..d055503 100644 --- a/drivers/usb/host/ehci-s5p.c +++ b/drivers/usb/host/ehci-s5p.c @@ -128,7 +128,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) } s5p_ehci->hcd = hcd; - s5p_ehci->clk = clk_get(&pdev->dev, "usbhost"); + s5p_ehci->clk = devm_clk_get(&pdev->dev, "usbhost"); if (IS_ERR(s5p_ehci->clk)) { dev_err(&pdev->dev, "Failed to get usbhost clock\n"); @@ -138,7 +138,7 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) err = clk_enable(s5p_ehci->clk); if (err) - goto fail_clken; + goto fail_clk; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!res) { @@ -184,8 +184,6 @@ static int __devinit s5p_ehci_probe(struct platform_device *pdev) fail_io: clk_disable(s5p_ehci->clk); -fail_clken: - clk_put(s5p_ehci->clk); fail_clk: usb_put_hcd(hcd); return err; @@ -203,7 +201,6 @@ static int __devexit s5p_ehci_remove(struct platform_device *pdev) pdata->phy_exit(pdev, S5P_USB_PHY_HOST); clk_disable(s5p_ehci->clk); - clk_put(s5p_ehci->clk); usb_put_hcd(hcd); -- cgit v0.10.2 From 6c40f5ee0f6213705eb6d3b706fc103b9dba72fb Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 30 Jul 2012 16:43:43 +0200 Subject: drivers/usb/host/ehci-sead3.c: use devm_ functions The various devm_ functions allocate memory that is released when a driver detaches. This patch uses these functions for data that is allocated in the probe function of a platform device and is only freed in the remove function. Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-sead3.c b/drivers/usb/host/ehci-sead3.c index 58c96bd..802dad8 100644 --- a/drivers/usb/host/ehci-sead3.c +++ b/drivers/usb/host/ehci-sead3.c @@ -112,17 +112,11 @@ static int ehci_hcd_sead3_drv_probe(struct platform_device *pdev) hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - pr_debug("request_mem_region failed"); - ret = -EBUSY; - goto err1; - } - - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = devm_request_and_ioremap(&pdev->dev, res); if (!hcd->regs) { pr_debug("ioremap failed"); ret = -ENOMEM; - goto err2; + goto err1; } /* Root hub has integrated TT. */ @@ -135,9 +129,6 @@ static int ehci_hcd_sead3_drv_probe(struct platform_device *pdev) return ret; } - iounmap(hcd->regs); -err2: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); err1: usb_put_hcd(hcd); return ret; @@ -148,8 +139,6 @@ static int ehci_hcd_sead3_drv_remove(struct platform_device *pdev) struct usb_hcd *hcd = platform_get_drvdata(pdev); usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); platform_set_drvdata(pdev, NULL); -- cgit v0.10.2 From a926e298b66a7a2d70a95810efdb0e64f3f24ae0 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 30 Jul 2012 16:43:42 +0200 Subject: drivers/usb/host/ehci-sh.c: use devm_ functions The various devm_ functions allocate memory that is released when a driver detaches. This patch uses these functions for data that is allocated in the probe function of a platform device and is only freed in the remove function. Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c index b3f1e36..6081e1e 100644 --- a/drivers/usb/host/ehci-sh.c +++ b/drivers/usb/host/ehci-sh.c @@ -125,33 +125,27 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev) hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, - driver->description)) { - dev_dbg(&pdev->dev, "controller already in use\n"); - ret = -EBUSY; - goto fail_request_resource; - } - - hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = devm_request_and_ioremap(&pdev->dev, res); if (hcd->regs == NULL) { dev_dbg(&pdev->dev, "error mapping memory\n"); ret = -ENXIO; - goto fail_ioremap; + goto fail_request_resource; } - priv = kmalloc(sizeof(struct ehci_sh_priv), GFP_KERNEL); + priv = devm_kzalloc(&pdev->dev, sizeof(struct ehci_sh_priv), + GFP_KERNEL); if (!priv) { dev_dbg(&pdev->dev, "error allocating priv data\n"); ret = -ENOMEM; - goto fail_alloc; + goto fail_request_resource; } /* These are optional, we don't care if they fail */ - priv->fclk = clk_get(&pdev->dev, "usb_fck"); + priv->fclk = devm_clk_get(&pdev->dev, "usb_fck"); if (IS_ERR(priv->fclk)) priv->fclk = NULL; - priv->iclk = clk_get(&pdev->dev, "usb_ick"); + priv->iclk = devm_clk_get(&pdev->dev, "usb_ick"); if (IS_ERR(priv->iclk)) priv->iclk = NULL; @@ -176,14 +170,6 @@ fail_add_hcd: clk_disable(priv->iclk); clk_disable(priv->fclk); - clk_put(priv->iclk); - clk_put(priv->fclk); - - kfree(priv); -fail_alloc: - iounmap(hcd->regs); -fail_ioremap: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); fail_request_resource: usb_put_hcd(hcd); fail_create_hcd: @@ -198,19 +184,12 @@ static int __exit ehci_hcd_sh_remove(struct platform_device *pdev) struct usb_hcd *hcd = priv->hcd; usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); platform_set_drvdata(pdev, NULL); clk_disable(priv->fclk); clk_disable(priv->iclk); - clk_put(priv->fclk); - clk_put(priv->iclk); - - kfree(priv); - return 0; } -- cgit v0.10.2 From bc2ff98ffa52d36b5df925a1f783ff2e035ed55e Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 30 Jul 2012 16:43:41 +0200 Subject: drivers/usb/host/ehci-tegra.c: use devm_ functions The various devm_ functions allocate memory that is released when a driver detaches. This patch uses these functions for data that is allocated in the probe function of a platform device and is only freed in the remove function. Signed-off-by: Julia Lawall Tested-by: Stephen Warren Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 950e95e..ba5039f 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -634,7 +634,8 @@ static int tegra_ehci_probe(struct platform_device *pdev) setup_vbus_gpio(pdev, pdata); - tegra = kzalloc(sizeof(struct tegra_ehci_hcd), GFP_KERNEL); + tegra = devm_kzalloc(&pdev->dev, sizeof(struct tegra_ehci_hcd), + GFP_KERNEL); if (!tegra) return -ENOMEM; @@ -642,13 +643,12 @@ static int tegra_ehci_probe(struct platform_device *pdev) dev_name(&pdev->dev)); if (!hcd) { dev_err(&pdev->dev, "Unable to create HCD\n"); - err = -ENOMEM; - goto fail_hcd; + return -ENOMEM; } platform_set_drvdata(pdev, tegra); - tegra->clk = clk_get(&pdev->dev, NULL); + tegra->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(tegra->clk)) { dev_err(&pdev->dev, "Can't get ehci clock\n"); err = PTR_ERR(tegra->clk); @@ -657,9 +657,9 @@ static int tegra_ehci_probe(struct platform_device *pdev) err = clk_prepare_enable(tegra->clk); if (err) - goto fail_clken; + goto fail_clk; - tegra->emc_clk = clk_get(&pdev->dev, "emc"); + tegra->emc_clk = devm_clk_get(&pdev->dev, "emc"); if (IS_ERR(tegra->emc_clk)) { dev_err(&pdev->dev, "Can't get emc clock\n"); err = PTR_ERR(tegra->emc_clk); @@ -677,7 +677,7 @@ static int tegra_ehci_probe(struct platform_device *pdev) } hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); - hcd->regs = ioremap(res->start, resource_size(res)); + hcd->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res)); if (!hcd->regs) { dev_err(&pdev->dev, "Failed to remap I/O memory\n"); err = -ENOMEM; @@ -702,7 +702,7 @@ static int tegra_ehci_probe(struct platform_device *pdev) default: err = -ENODEV; dev_err(&pdev->dev, "unknown usb instance\n"); - goto fail_phy; + goto fail_io; } } @@ -712,7 +712,7 @@ static int tegra_ehci_probe(struct platform_device *pdev) if (IS_ERR(tegra->phy)) { dev_err(&pdev->dev, "Failed to open USB phy\n"); err = -ENXIO; - goto fail_phy; + goto fail_io; } err = tegra_usb_phy_power_on(tegra->phy); @@ -733,7 +733,8 @@ static int tegra_ehci_probe(struct platform_device *pdev) #ifdef CONFIG_USB_OTG_UTILS if (pdata->operating_mode == TEGRA_USB_OTG) { - tegra->transceiver = usb_get_phy(USB_PHY_TYPE_USB2); + tegra->transceiver = + devm_usb_get_phy(&pdev->dev, USB_PHY_TYPE_USB2); if (!IS_ERR_OR_NULL(tegra->transceiver)) otg_set_host(tegra->transceiver->otg, &hcd->self); } @@ -757,25 +758,16 @@ static int tegra_ehci_probe(struct platform_device *pdev) fail: #ifdef CONFIG_USB_OTG_UTILS - if (!IS_ERR_OR_NULL(tegra->transceiver)) { + if (!IS_ERR_OR_NULL(tegra->transceiver)) otg_set_host(tegra->transceiver->otg, NULL); - usb_put_phy(tegra->transceiver); - } #endif tegra_usb_phy_close(tegra->phy); -fail_phy: - iounmap(hcd->regs); fail_io: clk_disable_unprepare(tegra->emc_clk); - clk_put(tegra->emc_clk); fail_emc_clk: clk_disable_unprepare(tegra->clk); -fail_clken: - clk_put(tegra->clk); fail_clk: usb_put_hcd(hcd); -fail_hcd: - kfree(tegra); return err; } @@ -792,25 +784,19 @@ static int tegra_ehci_remove(struct platform_device *pdev) pm_runtime_put_noidle(&pdev->dev); #ifdef CONFIG_USB_OTG_UTILS - if (!IS_ERR_OR_NULL(tegra->transceiver)) { + if (!IS_ERR_OR_NULL(tegra->transceiver)) otg_set_host(tegra->transceiver->otg, NULL); - usb_put_phy(tegra->transceiver); - } #endif usb_remove_hcd(hcd); usb_put_hcd(hcd); tegra_usb_phy_close(tegra->phy); - iounmap(hcd->regs); clk_disable_unprepare(tegra->clk); - clk_put(tegra->clk); clk_disable_unprepare(tegra->emc_clk); - clk_put(tegra->emc_clk); - kfree(tegra); return 0; } -- cgit v0.10.2 From f1d4eb788a007e3816132e6d1d28c25a64e86d24 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 30 Jul 2012 16:43:40 +0200 Subject: drivers/usb/host/ehci-vt8500.c: use devm_ functions The various devm_ functions allocate memory that is released when a driver detaches. This patch uses these functions for data that is allocated in the probe function of a platform device and is only freed in the remove function. Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c index 4d147c4..a891617 100644 --- a/drivers/usb/host/ehci-vt8500.c +++ b/drivers/usb/host/ehci-vt8500.c @@ -106,17 +106,11 @@ static int vt8500_ehci_drv_probe(struct platform_device *pdev) hcd->rsrc_start = res->start; hcd->rsrc_len = resource_size(res); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - pr_debug("request_mem_region failed"); - ret = -EBUSY; - goto err1; - } - - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = devm_request_and_ioremap(&pdev->dev, res); if (!hcd->regs) { pr_debug("ioremap failed"); ret = -ENOMEM; - goto err2; + goto err1; } ehci = hcd_to_ehci(hcd); @@ -129,9 +123,6 @@ static int vt8500_ehci_drv_probe(struct platform_device *pdev) return ret; } - iounmap(hcd->regs); -err2: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); err1: usb_put_hcd(hcd); return ret; @@ -142,8 +133,6 @@ static int vt8500_ehci_drv_remove(struct platform_device *pdev) struct usb_hcd *hcd = platform_get_drvdata(pdev); usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); usb_put_hcd(hcd); platform_set_drvdata(pdev, NULL); -- cgit v0.10.2 From 6df471ea04bd65603b67d821f2df359cc2cfac68 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 30 Jul 2012 16:43:39 +0200 Subject: drivers/usb/host/ehci-xilinx-of.c: use devm_ functions The various devm_ functions allocate memory that is released when a driver detaches. This patch uses these functions for data that is allocated in the probe function of a platform device and is only freed in the remove function. Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c index 39f24fa..6a3f921 100644 --- a/drivers/usb/host/ehci-xilinx-of.c +++ b/drivers/usb/host/ehci-xilinx-of.c @@ -152,12 +152,6 @@ static int __devinit ehci_hcd_xilinx_of_probe(struct platform_device *op) hcd->rsrc_start = res.start; hcd->rsrc_len = resource_size(&res); - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - printk(KERN_ERR "%s: request_mem_region failed\n", __FILE__); - rv = -EBUSY; - goto err_rmr; - } - irq = irq_of_parse_and_map(dn, 0); if (!irq) { printk(KERN_ERR "%s: irq_of_parse_and_map failed\n", __FILE__); @@ -165,11 +159,11 @@ static int __devinit ehci_hcd_xilinx_of_probe(struct platform_device *op) goto err_irq; } - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + hcd->regs = devm_request_and_ioremap(&op->dev, &res); if (!hcd->regs) { - printk(KERN_ERR "%s: ioremap failed\n", __FILE__); + pr_err("%s: devm_request_and_ioremap failed\n", __FILE__); rv = -ENOMEM; - goto err_ioremap; + goto err_irq; } ehci = hcd_to_ehci(hcd); @@ -200,12 +194,7 @@ static int __devinit ehci_hcd_xilinx_of_probe(struct platform_device *op) if (rv == 0) return 0; - iounmap(hcd->regs); - -err_ioremap: err_irq: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err_rmr: usb_put_hcd(hcd); return rv; @@ -227,9 +216,6 @@ static int ehci_hcd_xilinx_of_remove(struct platform_device *op) usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - usb_put_hcd(hcd); return 0; -- cgit v0.10.2 From 86e4cb35f2260374df4139c2352afe7fe247cb60 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 6 Aug 2012 18:06:53 -0700 Subject: usb: host: ehci-platform: BUG_ON() to WARN_ON() on probe usb_ehci_pdata is certainly required in ehci-platform driver. This patch avoids using BUG_ON() from driver, and return from probe with WARN_ON() if pdata was NULL. Signed-off-by: Kuninori Morimoto Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index 4b1d896..a2aaef6 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -82,10 +82,14 @@ static int __devinit ehci_platform_probe(struct platform_device *dev) { struct usb_hcd *hcd; struct resource *res_mem; + struct usb_ehci_pdata *pdata = dev->dev.platform_data; int irq; int err = -ENOMEM; - BUG_ON(!dev->dev.platform_data); + if (!pdata) { + WARN_ON(1); + return -ENODEV; + } if (usb_disabled()) return -ENODEV; -- cgit v0.10.2 From b6dd245c4594482d46507a0bfd100439be367952 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 6 Aug 2012 18:07:30 -0700 Subject: usb: host: ohci-platform: BUG_ON() to WARN_ON() on probe usb_ohci_pdata is certainly required in ohci-platform driver. This patch avoids using BUG_ON() from driver, and return from probe with WARN_ON() if pdata was NULL. Signed-off-by: Kuninori Morimoto Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c index 670c705..4c886f9 100644 --- a/drivers/usb/host/ohci-platform.c +++ b/drivers/usb/host/ohci-platform.c @@ -83,10 +83,14 @@ static int __devinit ohci_platform_probe(struct platform_device *dev) { struct usb_hcd *hcd; struct resource *res_mem; + struct usb_ohci_pdata *pdata = dev->dev.platform_data; int irq; int err = -ENOMEM; - BUG_ON(!dev->dev.platform_data); + if (!pdata) { + WARN_ON(1); + return -ENODEV; + } if (usb_disabled()) return -ENODEV; -- cgit v0.10.2 From 04216bedafb1b3992a6c2b7f1518281d2ba5fc7b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 6 Aug 2012 18:08:39 -0700 Subject: usb: host: ehci-platform: add platform specific power callback This patch enables to call platform specific power callback function. Signed-off-by: Kuninori Morimoto Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index a2aaef6..91acdde 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -105,10 +105,18 @@ static int __devinit ehci_platform_probe(struct platform_device *dev) return -ENXIO; } + if (pdata->power_on) { + err = pdata->power_on(dev); + if (err < 0) + return err; + } + hcd = usb_create_hcd(&ehci_platform_hc_driver, &dev->dev, dev_name(&dev->dev)); - if (!hcd) - return -ENOMEM; + if (!hcd) { + err = -ENOMEM; + goto err_power; + } hcd->rsrc_start = res_mem->start; hcd->rsrc_len = resource_size(res_mem); @@ -136,12 +144,17 @@ err_release_region: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); err_put_hcd: usb_put_hcd(hcd); +err_power: + if (pdata->power_off) + pdata->power_off(dev); + return err; } static int __devexit ehci_platform_remove(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); + struct usb_ehci_pdata *pdata = dev->dev.platform_data; usb_remove_hcd(hcd); iounmap(hcd->regs); @@ -149,6 +162,9 @@ static int __devexit ehci_platform_remove(struct platform_device *dev) usb_put_hcd(hcd); platform_set_drvdata(dev, NULL); + if (pdata->power_off) + pdata->power_off(dev); + return 0; } @@ -157,14 +173,32 @@ static int __devexit ehci_platform_remove(struct platform_device *dev) static int ehci_platform_suspend(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); + struct usb_ehci_pdata *pdata = dev->platform_data; + struct platform_device *pdev = + container_of(dev, struct platform_device, dev); bool do_wakeup = device_may_wakeup(dev); + int ret; + + ret = ehci_suspend(hcd, do_wakeup); - return ehci_suspend(hcd, do_wakeup); + if (pdata->power_suspend) + pdata->power_suspend(pdev); + + return ret; } static int ehci_platform_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); + struct usb_ehci_pdata *pdata = dev->platform_data; + struct platform_device *pdev = + container_of(dev, struct platform_device, dev); + + if (pdata->power_on) { + int err = pdata->power_on(pdev); + if (err < 0) + return err; + } ehci_resume(hcd, false); return 0; diff --git a/include/linux/usb/ehci_pdriver.h b/include/linux/usb/ehci_pdriver.h index 1894f42..c9d09f8 100644 --- a/include/linux/usb/ehci_pdriver.h +++ b/include/linux/usb/ehci_pdriver.h @@ -41,6 +41,14 @@ struct usb_ehci_pdata { unsigned big_endian_mmio:1; unsigned port_power_on:1; unsigned port_power_off:1; + + /* Turn on all power and clocks */ + int (*power_on)(struct platform_device *pdev); + /* Turn off all power and clocks */ + void (*power_off)(struct platform_device *pdev); + /* Turn on only VBUS suspend power and hotplug detection, + * turn off everything else */ + void (*power_suspend)(struct platform_device *pdev); }; #endif /* __USB_CORE_EHCI_PDRIVER_H */ -- cgit v0.10.2 From e4d37aeb373a5edceecc1dadc76fabbe8bc18e44 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 6 Aug 2012 18:09:10 -0700 Subject: usb: host: ohci-platform: add platform specific power callback This patch enables to call platform specific power callback function. Signed-off-by: Kuninori Morimoto Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c index 4c886f9..10d85b9 100644 --- a/drivers/usb/host/ohci-platform.c +++ b/drivers/usb/host/ohci-platform.c @@ -107,10 +107,18 @@ static int __devinit ohci_platform_probe(struct platform_device *dev) return -ENXIO; } + if (pdata->power_on) { + err = pdata->power_on(dev); + if (err < 0) + return err; + } + hcd = usb_create_hcd(&ohci_platform_hc_driver, &dev->dev, dev_name(&dev->dev)); - if (!hcd) - return -ENOMEM; + if (!hcd) { + err = -ENOMEM; + goto err_power; + } hcd->rsrc_start = res_mem->start; hcd->rsrc_len = resource_size(res_mem); @@ -138,12 +146,17 @@ err_release_region: release_mem_region(hcd->rsrc_start, hcd->rsrc_len); err_put_hcd: usb_put_hcd(hcd); +err_power: + if (pdata->power_off) + pdata->power_off(dev); + return err; } static int __devexit ohci_platform_remove(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); + struct usb_ohci_pdata *pdata = dev->dev.platform_data; usb_remove_hcd(hcd); iounmap(hcd->regs); @@ -151,6 +164,9 @@ static int __devexit ohci_platform_remove(struct platform_device *dev) usb_put_hcd(hcd); platform_set_drvdata(dev, NULL); + if (pdata->power_off) + pdata->power_off(dev); + return 0; } @@ -158,12 +174,28 @@ static int __devexit ohci_platform_remove(struct platform_device *dev) static int ohci_platform_suspend(struct device *dev) { + struct usb_ohci_pdata *pdata = dev->platform_data; + struct platform_device *pdev = + container_of(dev, struct platform_device, dev); + + if (pdata->power_suspend) + pdata->power_suspend(pdev); + return 0; } static int ohci_platform_resume(struct device *dev) { struct usb_hcd *hcd = dev_get_drvdata(dev); + struct usb_ohci_pdata *pdata = dev->platform_data; + struct platform_device *pdev = + container_of(dev, struct platform_device, dev); + + if (pdata->power_on) { + int err = pdata->power_on(pdev); + if (err < 0) + return err; + } ohci_finish_controller_resume(hcd); return 0; diff --git a/include/linux/usb/ohci_pdriver.h b/include/linux/usb/ohci_pdriver.h index 2808f2a..74e7755 100644 --- a/include/linux/usb/ohci_pdriver.h +++ b/include/linux/usb/ohci_pdriver.h @@ -33,6 +33,14 @@ struct usb_ohci_pdata { unsigned big_endian_desc:1; unsigned big_endian_mmio:1; unsigned no_big_frame_no:1; + + /* Turn on all power and clocks */ + int (*power_on)(struct platform_device *pdev); + /* Turn off all power and clocks */ + void (*power_off)(struct platform_device *pdev); + /* Turn on only VBUS suspend power and hotplug detection, + * turn off everything else */ + void (*power_suspend)(struct platform_device *pdev); }; #endif /* __USB_CORE_OHCI_PDRIVER_H */ -- cgit v0.10.2 From e58ba01e2cfe7b7d54d28f78c7af3cff4d5419a3 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Wed, 8 Aug 2012 16:49:48 +0400 Subject: wusb: Fix potential memory leak in wusb_dev_sec_add() Do not leak memory by updating pointer with potentially NULL realloc return value. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/wusbcore/security.c b/drivers/usb/wusbcore/security.c index fa810a8..dd88441 100644 --- a/drivers/usb/wusbcore/security.c +++ b/drivers/usb/wusbcore/security.c @@ -202,7 +202,7 @@ int wusb_dev_sec_add(struct wusbhc *wusbhc, { int result, bytes, secd_size; struct device *dev = &usb_dev->dev; - struct usb_security_descriptor *secd; + struct usb_security_descriptor *secd, *new_secd; const struct usb_encryption_descriptor *etd, *ccm1_etd = NULL; const void *itr, *top; char buf[64]; @@ -221,11 +221,12 @@ int wusb_dev_sec_add(struct wusbhc *wusbhc, goto out; } secd_size = le16_to_cpu(secd->wTotalLength); - secd = krealloc(secd, secd_size, GFP_KERNEL); - if (secd == NULL) { + new_secd = krealloc(secd, secd_size, GFP_KERNEL); + if (new_secd == NULL) { dev_err(dev, "Can't allocate space for security descriptors\n"); goto out; } + secd = new_secd; result = usb_get_descriptor(usb_dev, USB_DT_SECURITY, 0, secd, secd_size); if (result < secd_size) { -- cgit v0.10.2 From 05f2b3912323b4130dbf6d5091601d9ca3aaf119 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Wed, 8 Aug 2012 12:53:07 +0400 Subject: USB: whci-hcd: Fix potential memory leak in qset_add_urb_sg() Do not leak memory by updating pointer with potentially NULL realloc return value. By the way remove unused local variable: struct whc_page_list_entry *entry; More precisely, it was used to increment uninitialized value within one of cycles. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/whci/qset.c b/drivers/usb/host/whci/qset.c index 76083ae..dc31c42 100644 --- a/drivers/usb/host/whci/qset.c +++ b/drivers/usb/host/whci/qset.c @@ -436,7 +436,7 @@ static int qset_add_urb_sg(struct whc *whc, struct whc_qset *qset, struct urb *u int i; int ntds = 0; struct whc_std *std = NULL; - struct whc_page_list_entry *entry; + struct whc_page_list_entry *new_pl_virt; dma_addr_t prev_end = 0; size_t pl_len; int p = 0; @@ -508,12 +508,15 @@ static int qset_add_urb_sg(struct whc *whc, struct whc_qset *qset, struct urb *u pl_len = std->num_pointers * sizeof(struct whc_page_list_entry); - std->pl_virt = krealloc(std->pl_virt, pl_len, mem_flags); - if (std->pl_virt == NULL) { + new_pl_virt = krealloc(std->pl_virt, pl_len, mem_flags); + if (new_pl_virt == NULL) { + kfree(std->pl_virt); + std->pl_virt = NULL; return -ENOMEM; } + std->pl_virt = new_pl_virt; - for (;p < std->num_pointers; p++, entry++) { + for (;p < std->num_pointers; p++) { std->pl_virt[p].buf_ptr = cpu_to_le64(dma_addr); dma_addr = (dma_addr + WHCI_PAGE_SIZE) & ~(WHCI_PAGE_SIZE-1); } -- cgit v0.10.2 From 7fc2cc320cd3e53954187d9cff8145f38ae4a015 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Fri, 3 Aug 2012 16:30:35 +0800 Subject: usb: Rename temp variable "config" to "val" in the set_avoid_reset_quirk() In USB, the word "config" already has aseparate meaning. So it will cause confusion if use "config" as variable's name for other purposes. This patch is to convert the "config" to "val" Acked-by: Alan Stern Signed-off-by: Lan Tianyu Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 682e825..d6c49d9 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -204,12 +204,12 @@ set_avoid_reset_quirk(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct usb_device *udev = to_usb_device(dev); - int config; + int val; - if (sscanf(buf, "%d", &config) != 1 || config < 0 || config > 1) + if (sscanf(buf, "%d", &val) != 1 || val < 0 || val > 1) return -EINVAL; usb_lock_device(udev); - if (config) + if (val) udev->quirks |= USB_QUIRK_RESET_MORPHS; else udev->quirks &= ~USB_QUIRK_RESET_MORPHS; -- cgit v0.10.2 From 4d9e4088e074e674bc7a9fef4381e0910323c649 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Fri, 3 Aug 2012 16:30:36 +0800 Subject: usb: add decriptor of persist fail for some morph usb devices Some morph devices will morph after being reset and cause persist to fail. This patch is to add descriptor about this in the Document/usb/persist.txt Signed-off-by: Lan Tianyu Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/usb/persist.txt b/Documentation/usb/persist.txt index 074b159..35d70ed 100644 --- a/Documentation/usb/persist.txt +++ b/Documentation/usb/persist.txt @@ -155,6 +155,9 @@ If the kernel gets fooled in this way, it's almost certain to cause data corruption and to crash your system. You'll have no one to blame but yourself. +For those devices with avoid_reset_quirk attribute being set, persist +maybe fail because they may morph after reset. + YOU HAVE BEEN WARNED! USE AT YOUR OWN RISK! That having been said, most of the time there shouldn't be any trouble -- cgit v0.10.2 From 12a19b5f836c1a1b838e668f9aa804d017d8c58b Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 13 Aug 2012 12:32:58 +1000 Subject: usb: musb: omap2430: don't loop indefinitely in interrupt. When called during resume_irqs, omap2430_musb_set_vbus() is run with interrupts disabled, In that case 'jiffies' never changes so the loop can loop forever. So impose a maximum loop count and add an 'mdelay' to ensure we wait a reasonable amount of time for bit to be cleared. This fixes a hang on resume. Signed-of-by: NeilBrown Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index e32aff9..af5f421 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include "musb_core.h" @@ -150,6 +151,7 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on) if (is_on) { if (musb->xceiv->state == OTG_STATE_A_IDLE) { + int loops = 100; /* start the session */ devctl |= MUSB_DEVCTL_SESSION; musb_writeb(musb->mregs, MUSB_DEVCTL, devctl); @@ -159,9 +161,11 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on) */ while (musb_readb(musb->mregs, MUSB_DEVCTL) & 0x80) { + mdelay(5); cpu_relax(); - if (time_after(jiffies, timeout)) { + if (time_after(jiffies, timeout) + || loops-- <= 0) { dev_err(musb->controller, "configured as A device timeout"); ret = -EINVAL; -- cgit v0.10.2 From c6f83f386c2f7987a344368e33e55840c12bd38f Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Wed, 15 Aug 2012 12:28:29 +0300 Subject: usb: dwc3: gadget: warn about endpoint already enabled before changing ep name In case some gadget driver tries to enable an endpoint which is already enabled, we print a nice WARN so we can track broken gadget drivers. The only problem is that we're printing the WARN when we already changed endpoint's name, which would result in endpoints named as: ep1in-bulk-bulk-bulk-bulk-bulk-bulk-bulk To prevent that, we will continue to print the WARN, but do so before changing endpoint's name and return early. Signed-off-by: Felipe Balbi diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index dd5945c..029cf06 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -642,6 +642,12 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep, dep = to_dwc3_ep(ep); dwc = dep->dwc; + if (dep->flags & DWC3_EP_ENABLED) { + dev_WARN_ONCE(dwc->dev, true, "%s is already enabled\n", + dep->name); + return 0; + } + switch (usb_endpoint_type(desc)) { case USB_ENDPOINT_XFER_CONTROL: strlcat(dep->name, "-control", sizeof(dep->name)); @@ -659,12 +665,6 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep, dev_err(dwc->dev, "invalid endpoint transfer type\n"); } - if (dep->flags & DWC3_EP_ENABLED) { - dev_WARN_ONCE(dwc->dev, true, "%s is already enabled\n", - dep->name); - return 0; - } - dev_vdbg(dwc->dev, "Enabling %s\n", dep->name); spin_lock_irqsave(&dwc->lock, flags); -- cgit v0.10.2 From 644034c21209feaddd6d584669ffb40561525d18 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 20 Jul 2012 10:10:19 +0300 Subject: USB: legousbtower.c: remove a bogus NULL check "udev" can't be NULL here. The debugging printk() makes static checkers complain when we dereference it later in the function inside the call to usb_rcvctrlpipe(). Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/misc/legousbtower.c b/drivers/usb/misc/legousbtower.c index a2702cb..8089479 100644 --- a/drivers/usb/misc/legousbtower.c +++ b/drivers/usb/misc/legousbtower.c @@ -868,9 +868,6 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device dbg(2, "%s: enter", __func__); - if (udev == NULL) - dev_info(&interface->dev, "udev is NULL.\n"); - /* allocate memory for our device state and initialize it */ dev = kmalloc (sizeof(struct lego_usb_tower), GFP_KERNEL); -- cgit v0.10.2 From 3821bf4abb7f78c90af7fa2975df6618906b11ec Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Fri, 20 Jul 2012 09:58:16 +0300 Subject: USB: whci-hcd: fix NULL dereference on allocation failure If usb_create_hcd() fails here then we dereference "whc" inside the call to whc_clean_up() before it has been set. The compiler would have warned about this if we hadn't initialized all the pointers to NULL at the start of the function. I've cleaned that up as well. Signed-off-by: Dan Carpenter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/whci/hcd.c b/drivers/usb/host/whci/hcd.c index 1e141f7..c3a6478 100644 --- a/drivers/usb/host/whci/hcd.c +++ b/drivers/usb/host/whci/hcd.c @@ -238,16 +238,16 @@ static struct hc_driver whc_hc_driver = { static int whc_probe(struct umc_dev *umc) { - int ret = -ENOMEM; + int ret; struct usb_hcd *usb_hcd; - struct wusbhc *wusbhc = NULL; - struct whc *whc = NULL; + struct wusbhc *wusbhc; + struct whc *whc; struct device *dev = &umc->dev; usb_hcd = usb_create_hcd(&whc_hc_driver, dev, "whci"); if (usb_hcd == NULL) { dev_err(dev, "unable to create hcd\n"); - goto error; + return -ENOMEM; } usb_hcd->wireless = 1; -- cgit v0.10.2 From c54103d00957a6725be3b2f4abdf230680db06f4 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 23 Jul 2012 14:26:07 -0500 Subject: USB: qcserial: fix port handling on Gobi 1K and 2K+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bjorn's latest patchset does break Gobi 1K and 2K because on both devices as it claims usb interface 0. That's because usbif 0 is not handled in the switch statement, and thus the if0 gets claimed when it should not. So let's just make things even simpler yet, and handle both the 1K and 2K+ cases separately. This patch should not affect the new Sierra device support, because those devices are matched via interface-specific matching and thus should never hit the composite code. Signed-off-by: Dan Williams Tested-by: Bjørn Mork Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 8d10301..1c94618 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -199,43 +199,49 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) /* default to enabling interface */ altsetting = 0; - switch (ifnum) { - /* Composite mode; don't bind to the QMI/net interface as that - * gets handled by other drivers. - */ + /* Composite mode; don't bind to the QMI/net interface as that + * gets handled by other drivers. + */ + + if (is_gobi1k) { /* Gobi 1K USB layout: * 0: serial port (doesn't respond) * 1: serial port (doesn't respond) * 2: AT-capable modem port * 3: QMI/net - * - * Gobi 2K+ USB layout: + */ + if (ifnum == 2) + dev_dbg(dev, "Modem port found\n"); + else + altsetting = -1; + } else { + /* Gobi 2K+ USB layout: * 0: QMI/net * 1: DM/DIAG (use libqcdm from ModemManager for communication) * 2: AT-capable modem port * 3: NMEA */ - - case 1: - if (is_gobi1k) + switch (ifnum) { + case 0: + /* Don't claim the QMI/net interface */ altsetting = -1; - else + break; + case 1: dev_dbg(dev, "Gobi 2K+ DM/DIAG interface found\n"); - break; - case 2: - dev_dbg(dev, "Modem port found\n"); - break; - case 3: - if (is_gobi1k) - altsetting = -1; - else + break; + case 2: + dev_dbg(dev, "Modem port found\n"); + break; + case 3: /* * NMEA (serial line 9600 8N1) * # echo "\$GPS_START" > /dev/ttyUSBx * # echo "\$GPS_STOP" > /dev/ttyUSBx */ dev_dbg(dev, "Gobi 2K+ NMEA GPS interface found\n"); + break; + } } done: -- cgit v0.10.2 From 595c8970064275d1eb59b8df5c871ccda2f2bc88 Mon Sep 17 00:00:00 2001 From: Tim Gardner Date: Fri, 27 Jul 2012 10:53:21 -0600 Subject: USB: storage: ene_ub6250: Use macros for firmware names Advertise firmware files using MODULE_FIRMWARE macros. Fix a debug string: SD_RDWR_PATTERN --> SD_RW_PATTERN Signed-off-by: Tim Gardner Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c index b28f2ad..95edee5 100644 --- a/drivers/usb/storage/ene_ub6250.c +++ b/drivers/usb/storage/ene_ub6250.c @@ -29,9 +29,21 @@ #include "protocol.h" #include "debug.h" +#define SD_INIT1_FIRMWARE "ene-ub6250/sd_init1.bin" +#define SD_INIT2_FIRMWARE "ene-ub6250/sd_init2.bin" +#define SD_RW_FIRMWARE "ene-ub6250/sd_rdwr.bin" +#define MS_INIT_FIRMWARE "ene-ub6250/ms_init.bin" +#define MSP_RW_FIRMWARE "ene-ub6250/msp_rdwr.bin" +#define MS_RW_FIRMWARE "ene-ub6250/ms_rdwr.bin" + MODULE_DESCRIPTION("Driver for ENE UB6250 reader"); MODULE_LICENSE("GPL"); - +MODULE_FIRMWARE(SD_INIT1_FIRMWARE); +MODULE_FIRMWARE(SD_INIT2_FIRMWARE); +MODULE_FIRMWARE(SD_RW_FIRMWARE); +MODULE_FIRMWARE(MS_INIT_FIRMWARE); +MODULE_FIRMWARE(MSP_RW_FIRMWARE); +MODULE_FIRMWARE(MS_RW_FIRMWARE); /* * The table of devices @@ -1883,28 +1895,28 @@ static int ene_load_bincode(struct us_data *us, unsigned char flag) /* For SD */ case SD_INIT1_PATTERN: US_DEBUGP("SD_INIT1_PATTERN\n"); - fw_name = "ene-ub6250/sd_init1.bin"; + fw_name = SD_INIT1_FIRMWARE; break; case SD_INIT2_PATTERN: US_DEBUGP("SD_INIT2_PATTERN\n"); - fw_name = "ene-ub6250/sd_init2.bin"; + fw_name = SD_INIT2_FIRMWARE; break; case SD_RW_PATTERN: - US_DEBUGP("SD_RDWR_PATTERN\n"); - fw_name = "ene-ub6250/sd_rdwr.bin"; + US_DEBUGP("SD_RW_PATTERN\n"); + fw_name = SD_RW_FIRMWARE; break; /* For MS */ case MS_INIT_PATTERN: US_DEBUGP("MS_INIT_PATTERN\n"); - fw_name = "ene-ub6250/ms_init.bin"; + fw_name = MS_INIT_FIRMWARE; break; case MSP_RW_PATTERN: US_DEBUGP("MSP_RW_PATTERN\n"); - fw_name = "ene-ub6250/msp_rdwr.bin"; + fw_name = MSP_RW_FIRMWARE; break; case MS_RW_PATTERN: US_DEBUGP("MS_RW_PATTERN\n"); - fw_name = "ene-ub6250/ms_rdwr.bin"; + fw_name = MS_RW_FIRMWARE; break; default: US_DEBUGP("----------- Unknown PATTERN ----------\n"); -- cgit v0.10.2 From 47282502933e94a2e443fab36c412191fc3ed6ce Mon Sep 17 00:00:00 2001 From: Tim Gardner Date: Wed, 25 Jul 2012 14:32:50 -0600 Subject: USB: atm: ueagle-atm: Declare MODULE_FIRMWARE usage Signed-off-by: Tim Gardner Cc: Stanislaw Gruszka Acked-by: Matthieu Castet Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index d7e422d..e1f8b2c 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -307,6 +307,34 @@ enum { #define FW_GET_BYTE(p) (*((__u8 *) (p))) #define FW_DIR "ueagle-atm/" +#define EAGLE_FIRMWARE FW_DIR "eagle.fw" +#define ADI930_FIRMWARE FW_DIR "adi930.fw" +#define EAGLE_I_FIRMWARE FW_DIR "eagleI.fw" +#define EAGLE_II_FIRMWARE FW_DIR "eagleII.fw" +#define EAGLE_III_FIRMWARE FW_DIR "eagleIII.fw" +#define EAGLE_IV_FIRMWARE FW_DIR "eagleIV.fw" + +#define DSP4I_FIRMWARE FW_DIR "DSP4i.bin" +#define DSP4P_FIRMWARE FW_DIR "DSP4p.bin" +#define DSP9I_FIRMWARE FW_DIR "DSP9i.bin" +#define DSP9P_FIRMWARE FW_DIR "DSP9p.bin" +#define DSPEI_FIRMWARE FW_DIR "DSPei.bin" +#define DSPEP_FIRMWARE FW_DIR "DSPep.bin" +#define FPGA930_FIRMWARE FW_DIR "930-fpga.bin" + +#define CMV4P_FIRMWARE FW_DIR "CMV4p.bin" +#define CMV4PV2_FIRMWARE FW_DIR "CMV4p.bin.v2" +#define CMV4I_FIRMWARE FW_DIR "CMV4i.bin" +#define CMV4IV2_FIRMWARE FW_DIR "CMV4i.bin.v2" +#define CMV9P_FIRMWARE FW_DIR "CMV9p.bin" +#define CMV9PV2_FIRMWARE FW_DIR "CMV9p.bin.v2" +#define CMV9I_FIRMWARE FW_DIR "CMV9i.bin" +#define CMV9IV2_FIRMWARE FW_DIR "CMV9i.bin.v2" +#define CMVEP_FIRMWARE FW_DIR "CMVep.bin" +#define CMVEPV2_FIRMWARE FW_DIR "CMVep.bin.v2" +#define CMVEI_FIRMWARE FW_DIR "CMVei.bin" +#define CMVEIV2_FIRMWARE FW_DIR "CMVei.bin.v2" + #define UEA_FW_NAME_MAX 30 #define NB_MODEM 4 @@ -694,26 +722,26 @@ err: static int uea_load_firmware(struct usb_device *usb, unsigned int ver) { int ret; - char *fw_name = FW_DIR "eagle.fw"; + char *fw_name = EAGLE_FIRMWARE; uea_enters(usb); uea_info(usb, "pre-firmware device, uploading firmware\n"); switch (ver) { case ADI930: - fw_name = FW_DIR "adi930.fw"; + fw_name = ADI930_FIRMWARE; break; case EAGLE_I: - fw_name = FW_DIR "eagleI.fw"; + fw_name = EAGLE_I_FIRMWARE; break; case EAGLE_II: - fw_name = FW_DIR "eagleII.fw"; + fw_name = EAGLE_II_FIRMWARE; break; case EAGLE_III: - fw_name = FW_DIR "eagleIII.fw"; + fw_name = EAGLE_III_FIRMWARE; break; case EAGLE_IV: - fw_name = FW_DIR "eagleIV.fw"; + fw_name = EAGLE_IV_FIRMWARE; break; } @@ -869,19 +897,19 @@ static int request_dsp(struct uea_softc *sc) if (UEA_CHIP_VERSION(sc) == EAGLE_IV) { if (IS_ISDN(sc)) - dsp_name = FW_DIR "DSP4i.bin"; + dsp_name = DSP4I_FIRMWARE; else - dsp_name = FW_DIR "DSP4p.bin"; + dsp_name = DSP4P_FIRMWARE; } else if (UEA_CHIP_VERSION(sc) == ADI930) { if (IS_ISDN(sc)) - dsp_name = FW_DIR "DSP9i.bin"; + dsp_name = DSP9I_FIRMWARE; else - dsp_name = FW_DIR "DSP9p.bin"; + dsp_name = DSP9P_FIRMWARE; } else { if (IS_ISDN(sc)) - dsp_name = FW_DIR "DSPei.bin"; + dsp_name = DSPEI_FIRMWARE; else - dsp_name = FW_DIR "DSPep.bin"; + dsp_name = DSPEP_FIRMWARE; } ret = request_firmware(&sc->dsp_firm, dsp_name, &sc->usb_dev->dev); @@ -1925,7 +1953,7 @@ static int load_XILINX_firmware(struct uea_softc *sc) int ret, size, u, ln; const u8 *pfw; u8 value; - char *fw_name = FW_DIR "930-fpga.bin"; + char *fw_name = FPGA930_FIRMWARE; uea_enters(INS_TO_USBDEV(sc)); @@ -2753,3 +2781,28 @@ module_usb_driver(uea_driver); MODULE_AUTHOR("Damien Bergamini/Matthieu Castet/Stanislaw W. Gruszka"); MODULE_DESCRIPTION("ADI 930/Eagle USB ADSL Modem driver"); MODULE_LICENSE("Dual BSD/GPL"); +MODULE_FIRMWARE(EAGLE_FIRMWARE); +MODULE_FIRMWARE(ADI930_FIRMWARE); +MODULE_FIRMWARE(EAGLE_I_FIRMWARE); +MODULE_FIRMWARE(EAGLE_II_FIRMWARE); +MODULE_FIRMWARE(EAGLE_III_FIRMWARE); +MODULE_FIRMWARE(EAGLE_IV_FIRMWARE); +MODULE_FIRMWARE(DSP4I_FIRMWARE); +MODULE_FIRMWARE(DSP4P_FIRMWARE); +MODULE_FIRMWARE(DSP9I_FIRMWARE); +MODULE_FIRMWARE(DSP9P_FIRMWARE); +MODULE_FIRMWARE(DSPEI_FIRMWARE); +MODULE_FIRMWARE(DSPEP_FIRMWARE); +MODULE_FIRMWARE(FPGA930_FIRMWARE); +MODULE_FIRMWARE(CMV4P_FIRMWARE); +MODULE_FIRMWARE(CMV4PV2_FIRMWARE); +MODULE_FIRMWARE(CMV4I_FIRMWARE); +MODULE_FIRMWARE(CMV4IV2_FIRMWARE); +MODULE_FIRMWARE(CMV9P_FIRMWARE); +MODULE_FIRMWARE(CMV9PV2_FIRMWARE); +MODULE_FIRMWARE(CMV9I_FIRMWARE); +MODULE_FIRMWARE(CMV9IV2_FIRMWARE); +MODULE_FIRMWARE(CMVEP_FIRMWARE); +MODULE_FIRMWARE(CMVEPV2_FIRMWARE); +MODULE_FIRMWARE(CMVEI_FIRMWARE); +MODULE_FIRMWARE(CMVEIV2_FIRMWARE); -- cgit v0.10.2 From ec03ad85486e94f133a721a5d6fd3aaef1176c46 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 14 Aug 2012 08:47:38 +0200 Subject: drivers/usb/host/ehci-platform.c: fix error return code Convert a possibly 0 error return code to a negative one, as returned elsewhere in the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ identifier ret; expression e,e1,e2,e3,e4,x; @@ ( if (\(ret != 0\|ret < 0\) || ...) { ... return ...; } | ret = 0 ) ... when != ret = e1 *x = \(kmalloc\|kzalloc\|kcalloc\|devm_kzalloc\|ioremap\|ioremap_nocache\|devm_ioremap\|devm_ioremap_nocache\)(...); ... when != x = e2 when != ret = e3 *if (x == NULL || ...) { ... when != ret = e4 * return ret; } // Signed-off-by: Julia Lawall Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index 91acdde..764e010 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -128,8 +128,10 @@ static int __devinit ehci_platform_probe(struct platform_device *dev) } hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) + if (!hcd->regs) { + err = -ENOMEM; goto err_release_region; + } err = usb_add_hcd(hcd, irq, IRQF_SHARED); if (err) goto err_iounmap; -- cgit v0.10.2 From aece389ea58ff507801ce260a84905bbe2ab7948 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 14 Aug 2012 08:47:37 +0200 Subject: drivers/usb/host/ohci-platform.c: fix error return code Convert a possibly 0 error return code to a negative one, as returned elsewhere in the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ identifier ret; expression e,e1,e2,e3,e4,x; @@ ( if (\(ret != 0\|ret < 0\) || ...) { ... return ...; } | ret = 0 ) ... when != ret = e1 *x = \(kmalloc\|kzalloc\|kcalloc\|devm_kzalloc\|ioremap\|ioremap_nocache\|devm_ioremap\|devm_ioremap_nocache\)(...); ... when != x = e2 when != ret = e3 *if (x == NULL || ...) { ... when != ret = e4 * return ret; } // Signed-off-by: Julia Lawall Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c index 10d85b9..e24ec9f 100644 --- a/drivers/usb/host/ohci-platform.c +++ b/drivers/usb/host/ohci-platform.c @@ -130,8 +130,10 @@ static int __devinit ohci_platform_probe(struct platform_device *dev) } hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); - if (!hcd->regs) + if (!hcd->regs) { + err = -ENOMEM; goto err_release_region; + } err = usb_add_hcd(hcd, irq, IRQF_SHARED); if (err) goto err_iounmap; -- cgit v0.10.2 From fd4d72cb0d31e13f0eb4c90c26580a5784c76527 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 14 Aug 2012 08:47:36 +0200 Subject: drivers/usb/wusbcore/wa-hc.c: fix error return code Convert a 0 error return code to a negative one, as returned elsewhere in the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ identifier ret; expression e,e1,e2,e3,e4,x; @@ ( if (\(ret != 0\|ret < 0\) || ...) { ... return ...; } | ret = 0 ) ... when != ret = e1 *x = \(kmalloc\|kzalloc\|kcalloc\|devm_kzalloc\|ioremap\|ioremap_nocache\|devm_ioremap\|devm_ioremap_nocache\)(...); ... when != x = e2 when != ret = e3 *if (x == NULL || ...) { ... when != ret = e4 * return ret; } // Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/wusbcore/wa-hc.c b/drivers/usb/wusbcore/wa-hc.c index 9e4a924..a09b65e 100644 --- a/drivers/usb/wusbcore/wa-hc.c +++ b/drivers/usb/wusbcore/wa-hc.c @@ -46,8 +46,10 @@ int wa_create(struct wahc *wa, struct usb_interface *iface) wa->dto_epd = &iface->cur_altsetting->endpoint[2].desc; wa->xfer_result_size = usb_endpoint_maxp(wa->dti_epd); wa->xfer_result = kmalloc(wa->xfer_result_size, GFP_KERNEL); - if (wa->xfer_result == NULL) + if (wa->xfer_result == NULL) { + result = -ENOMEM; goto error_xfer_result_alloc; + } result = wa_nep_create(wa, iface); if (result < 0) { dev_err(dev, "WA-CDS: can't initialize notif endpoint: %d\n", -- cgit v0.10.2 From dfdda5a0fa3f458e9807da1d1a1d2c56076d43e5 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Tue, 14 Aug 2012 08:47:34 +0200 Subject: drivers/usb/gadget/s3c-hsotg.c: fix error return code Convert a 0 error return code to a negative one, as returned elsewhere in the function. A simplified version of the semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ identifier ret; expression e,e1,e2,e3,e4,x; @@ ( if (\(ret != 0\|ret < 0\) || ...) { ... return ...; } | ret = 0 ) ... when != ret = e1 *x = \(kmalloc\|kzalloc\|kcalloc\|devm_kzalloc\|ioremap\|ioremap_nocache\|devm_ioremap\|devm_ioremap_nocache\)(...); ... when != x = e2 when != ret = e3 *if (x == NULL || ...) { ... when != ret = e4 * return ret; } // Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index b13e0bb..0bb617e 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -3599,6 +3599,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) if (hsotg->num_of_eps == 0) { dev_err(dev, "wrong number of EPs (zero)\n"); + ret = -EINVAL; goto err_supplies; } @@ -3606,6 +3607,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) GFP_KERNEL); if (!eps) { dev_err(dev, "cannot get memory\n"); + ret = -ENOMEM; goto err_supplies; } @@ -3622,6 +3624,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) GFP_KERNEL); if (!hsotg->ctrl_req) { dev_err(dev, "failed to allocate ctrl req\n"); + ret = -ENOMEM; goto err_ep_mem; } -- cgit v0.10.2 From 8ad551d150e3bb0902696496a9d2aa094335705a Mon Sep 17 00:00:00 2001 From: Tony Prisk Date: Sat, 21 Jul 2012 22:58:52 +1200 Subject: ARM: vt8500: Update vt8500-ehci driver to support device tree. Signed-off-by: Tony Prisk Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/devicetree/bindings/usb/vt8500-ehci.txt b/Documentation/devicetree/bindings/usb/vt8500-ehci.txt new file mode 100644 index 0000000..5fb8fd6 --- /dev/null +++ b/Documentation/devicetree/bindings/usb/vt8500-ehci.txt @@ -0,0 +1,12 @@ +VIA VT8500 and Wondermedia WM8xxx SoC USB controllers. + +Required properties: + - compatible: Should be "via,vt8500-ehci" or "wm,prizm-ehci". + - reg: Address range of the ehci registers. size should be 0x200 + - interrupts: Should contain the ehci interrupt. + +usb: ehci@D8007100 { + compatible = "wm,prizm-ehci", "usb-ehci"; + reg = <0xD8007100 0x200>; + interrupts = <1>; +}; diff --git a/drivers/usb/host/ehci-vt8500.c b/drivers/usb/host/ehci-vt8500.c index a891617..96722bf 100644 --- a/drivers/usb/host/ehci-vt8500.c +++ b/drivers/usb/host/ehci-vt8500.c @@ -16,6 +16,7 @@ * */ +#include #include static int ehci_update_device(struct usb_hcd *hcd, struct usb_device *udev) @@ -139,6 +140,12 @@ static int vt8500_ehci_drv_remove(struct platform_device *pdev) return 0; } +static const struct of_device_id vt8500_ehci_ids[] = { + { .compatible = "via,vt8500-ehci", }, + { .compatible = "wm,prizm-ehci", }, + {} +}; + static struct platform_driver vt8500_ehci_driver = { .probe = vt8500_ehci_drv_probe, .remove = vt8500_ehci_drv_remove, @@ -146,7 +153,9 @@ static struct platform_driver vt8500_ehci_driver = { .driver = { .name = "vt8500-ehci", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(vt8500_ehci_ids), } }; MODULE_ALIAS("platform:vt8500-ehci"); +MODULE_DEVICE_TABLE(of, vt8500_ehci_ids); -- cgit v0.10.2 From 100d45970327f78584ff4846deeca14bba511e28 Mon Sep 17 00:00:00 2001 From: Tony Prisk Date: Sat, 21 Jul 2012 22:58:53 +1200 Subject: ARM: vt8500: Add support for UHCI companion controller Add support for a generic non-pci UHCI companion controller. Existing board files for arch-vt8500 updated to include UHCI support. Signed-off-by: Tony Prisk Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/devicetree/bindings/usb/platform-uhci.txt b/Documentation/devicetree/bindings/usb/platform-uhci.txt new file mode 100644 index 0000000..91477d6 --- /dev/null +++ b/Documentation/devicetree/bindings/usb/platform-uhci.txt @@ -0,0 +1,12 @@ +Generic Platform UHCI controllers. + +Required properties: + - compatible: Should be "platform-uhci". + - reg: Address range of the uhci registers + - interrupts: Should contain the uhci interrupt. + +usb: uhci@D8007301 { + compatible = "platform-uhci", "usb-uhci"; + reg = <0xD8007301 0x200>; + interrupts = <0>; +}; diff --git a/arch/arm/mach-vt8500/bv07.c b/arch/arm/mach-vt8500/bv07.c index f9fbeb2..6fd9d60 100644 --- a/arch/arm/mach-vt8500/bv07.c +++ b/arch/arm/mach-vt8500/bv07.c @@ -33,6 +33,7 @@ static struct platform_device *devices[] __initdata = { &vt8500_device_uart0, &vt8500_device_lcdc, &vt8500_device_ehci, + &vt8500_device_uhci, &vt8500_device_ge_rops, &vt8500_device_pwm, &vt8500_device_pwmbl, diff --git a/arch/arm/mach-vt8500/devices-vt8500.c b/arch/arm/mach-vt8500/devices-vt8500.c index 19519ae..def7fe3 100644 --- a/arch/arm/mach-vt8500/devices-vt8500.c +++ b/arch/arm/mach-vt8500/devices-vt8500.c @@ -48,6 +48,11 @@ void __init vt8500_set_resources(void) tmp[1] = wmt_irq_res(IRQ_EHCI); wmt_res_add(&vt8500_device_ehci, tmp, 2); + /* vt8500 uses a single IRQ for both EHCI and UHCI controllers */ + tmp[0] = wmt_mmio_res(VT8500_UHCI_BASE, SZ_512); + tmp[1] = wmt_irq_res(IRQ_EHCI); + wmt_res_add(&vt8500_device_uhci, tmp, 2); + tmp[0] = wmt_mmio_res(VT8500_GEGEA_BASE, SZ_256); wmt_res_add(&vt8500_device_ge_rops, tmp, 1); diff --git a/arch/arm/mach-vt8500/devices-wm8505.c b/arch/arm/mach-vt8500/devices-wm8505.c index db4594e..c810454 100644 --- a/arch/arm/mach-vt8500/devices-wm8505.c +++ b/arch/arm/mach-vt8500/devices-wm8505.c @@ -55,6 +55,10 @@ void __init wm8505_set_resources(void) tmp[1] = wmt_irq_res(IRQ_EHCI); wmt_res_add(&vt8500_device_ehci, tmp, 2); + tmp[0] = wmt_mmio_res(WM8505_UHCI_BASE, SZ_512); + tmp[1] = wmt_irq_res(IRQ_UHCI); + wmt_res_add(&vt8500_device_uhci, tmp, 2); + tmp[0] = wmt_mmio_res(WM8505_GEGEA_BASE, SZ_256); wmt_res_add(&vt8500_device_ge_rops, tmp, 1); diff --git a/arch/arm/mach-vt8500/devices.c b/arch/arm/mach-vt8500/devices.c index 1fcdc36..46ff82d 100644 --- a/arch/arm/mach-vt8500/devices.c +++ b/arch/arm/mach-vt8500/devices.c @@ -204,6 +204,17 @@ struct platform_device vt8500_device_ehci = { }, }; +static u64 uhci_dma_mask = DMA_BIT_MASK(32); + +struct platform_device vt8500_device_uhci = { + .name = "platform-uhci", + .id = 0, + .dev = { + .dma_mask = &uhci_dma_mask, + .coherent_dma_mask = DMA_BIT_MASK(32), + }, +}; + struct platform_device vt8500_device_ge_rops = { .name = "wmt_ge_rops", .id = -1, diff --git a/arch/arm/mach-vt8500/devices.h b/arch/arm/mach-vt8500/devices.h index 188d4e1..0e6d9f9 100644 --- a/arch/arm/mach-vt8500/devices.h +++ b/arch/arm/mach-vt8500/devices.h @@ -81,6 +81,7 @@ extern struct platform_device vt8500_device_uart5; extern struct platform_device vt8500_device_lcdc; extern struct platform_device vt8500_device_wm8505_fb; extern struct platform_device vt8500_device_ehci; +extern struct platform_device vt8500_device_uhci; extern struct platform_device vt8500_device_ge_rops; extern struct platform_device vt8500_device_pwm; extern struct platform_device vt8500_device_pwmbl; diff --git a/arch/arm/mach-vt8500/wm8505_7in.c b/arch/arm/mach-vt8500/wm8505_7in.c index db19886..4804e2a 100644 --- a/arch/arm/mach-vt8500/wm8505_7in.c +++ b/arch/arm/mach-vt8500/wm8505_7in.c @@ -32,6 +32,7 @@ static void __iomem *pmc_hiber; static struct platform_device *devices[] __initdata = { &vt8500_device_uart0, &vt8500_device_ehci, + &vt8500_device_uhci, &vt8500_device_wm8505_fb, &vt8500_device_ge_rops, &vt8500_device_pwm, diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 075d2ec..c3f619b 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -450,7 +450,7 @@ config USB_OHCI_LITTLE_ENDIAN config USB_UHCI_HCD tristate "UHCI HCD (most Intel and VIA) support" - depends on USB && (PCI || SPARC_LEON) + depends on USB && (PCI || SPARC_LEON || ARCH_VT8500) ---help--- The Universal Host Controller Interface is a standard by Intel for accessing the USB hardware in the PC (which is also called the USB @@ -468,7 +468,15 @@ config USB_UHCI_HCD config USB_UHCI_SUPPORT_NON_PCI_HC bool depends on USB_UHCI_HCD - default y if SPARC_LEON + default y if (SPARC_LEON || ARCH_VT8500) + +config USB_UHCI_PLATFORM + bool "Generic UHCI Platform Driver support" + depends on USB_UHCI_SUPPORT_NON_PCI_HC + default y if ARCH_VT8500 + ---help--- + Enable support for generic UHCI platform devices that require no + additional configuration. config USB_UHCI_BIG_ENDIAN_MMIO bool diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index e4db350..4b9e9ab 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c @@ -846,6 +846,11 @@ static const char hcd_name[] = "uhci_hcd"; #define PLATFORM_DRIVER uhci_grlib_driver #endif +#ifdef CONFIG_USB_UHCI_PLATFORM +#include "uhci-platform.c" +#define PLATFORM_DRIVER uhci_platform_driver +#endif + #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) #error "missing bus glue for uhci-hcd" #endif diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c new file mode 100644 index 0000000..e478049 --- /dev/null +++ b/drivers/usb/host/uhci-platform.c @@ -0,0 +1,157 @@ +/* + * Generic UHCI HCD (Host Controller Driver) for Platform Devices + * + * Copyright (c) 2011 Tony Prisk + * + * This file is based on uhci-grlib.c + * (C) Copyright 2004-2007 Alan Stern, stern@rowland.harvard.edu + */ + +#include +#include + +static int uhci_platform_init(struct usb_hcd *hcd) +{ + struct uhci_hcd *uhci = hcd_to_uhci(hcd); + + uhci->rh_numports = uhci_count_ports(hcd); + + /* Set up pointers to to generic functions */ + uhci->reset_hc = uhci_generic_reset_hc; + uhci->check_and_reset_hc = uhci_generic_check_and_reset_hc; + + /* No special actions need to be taken for the functions below */ + uhci->configure_hc = NULL; + uhci->resume_detect_interrupts_are_broken = NULL; + uhci->global_suspend_mode_is_broken = NULL; + + /* Reset if the controller isn't already safely quiescent. */ + check_and_reset_hc(uhci); + return 0; +} + +static const struct hc_driver uhci_platform_hc_driver = { + .description = hcd_name, + .product_desc = "Generic UHCI Host Controller", + .hcd_priv_size = sizeof(struct uhci_hcd), + + /* Generic hardware linkage */ + .irq = uhci_irq, + .flags = HCD_MEMORY | HCD_USB11, + + /* Basic lifecycle operations */ + .reset = uhci_platform_init, + .start = uhci_start, +#ifdef CONFIG_PM + .pci_suspend = NULL, + .pci_resume = NULL, + .bus_suspend = uhci_rh_suspend, + .bus_resume = uhci_rh_resume, +#endif + .stop = uhci_stop, + + .urb_enqueue = uhci_urb_enqueue, + .urb_dequeue = uhci_urb_dequeue, + + .endpoint_disable = uhci_hcd_endpoint_disable, + .get_frame_number = uhci_hcd_get_frame_number, + + .hub_status_data = uhci_hub_status_data, + .hub_control = uhci_hub_control, +}; + + +static int __devinit uhci_hcd_platform_probe(struct platform_device *pdev) +{ + struct usb_hcd *hcd; + struct uhci_hcd *uhci; + struct resource *res; + int ret; + + if (usb_disabled()) + return -ENODEV; + + hcd = usb_create_hcd(&uhci_platform_hc_driver, &pdev->dev, + pdev->name); + if (!hcd) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + hcd->rsrc_start = res->start; + hcd->rsrc_len = resource_size(res); + + if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { + pr_err("%s: request_mem_region failed\n", __func__); + ret = -EBUSY; + goto err_rmr; + } + + hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); + if (!hcd->regs) { + pr_err("%s: ioremap failed\n", __func__); + ret = -ENOMEM; + goto err_irq; + } + uhci = hcd_to_uhci(hcd); + + uhci->regs = hcd->regs; + + ret = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_DISABLED | + IRQF_SHARED); + if (ret) + goto err_uhci; + + return 0; + +err_uhci: + iounmap(hcd->regs); +err_irq: + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); +err_rmr: + usb_put_hcd(hcd); + + return ret; +} + +static int uhci_hcd_platform_remove(struct platform_device *pdev) +{ + struct usb_hcd *hcd = platform_get_drvdata(pdev); + + usb_remove_hcd(hcd); + iounmap(hcd->regs); + release_mem_region(hcd->rsrc_start, hcd->rsrc_len); + usb_put_hcd(hcd); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +/* Make sure the controller is quiescent and that we're not using it + * any more. This is mainly for the benefit of programs which, like kexec, + * expect the hardware to be idle: not doing DMA or generating IRQs. + * + * This routine may be called in a damaged or failing kernel. Hence we + * do not acquire the spinlock before shutting down the controller. + */ +static void uhci_hcd_platform_shutdown(struct platform_device *op) +{ + struct usb_hcd *hcd = dev_get_drvdata(&op->dev); + + uhci_hc_died(hcd_to_uhci(hcd)); +} + +static const struct of_device_id platform_uhci_ids[] = { + { .compatible = "platform-uhci", }, + {} +}; + +static struct platform_driver uhci_platform_driver = { + .probe = uhci_hcd_platform_probe, + .remove = uhci_hcd_platform_remove, + .shutdown = uhci_hcd_platform_shutdown, + .driver = { + .name = "platform-uhci", + .owner = THIS_MODULE, + .of_match_table = of_match_ptr(platform_uhci_ids), + }, +}; -- cgit v0.10.2 From 26f944b2716717aa243f16cd2181f80441153f0d Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Thu, 16 Aug 2012 18:24:19 +0530 Subject: usb: hcd: use *resource_size_t* for specifying resource data Changed the type of rsrc_start and rsrc_len from u64 to resource_size_t so that it behaves well with resource API's like *resource_size()* on both 32bit and 64bit devices. Signed-off-by: Kishon Vijay Abraham I Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index c5fdb14..608050b 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -135,8 +135,8 @@ struct usb_hcd { unsigned int irq; /* irq allocated */ void __iomem *regs; /* device memory/io */ - u64 rsrc_start; /* memory/io resource start */ - u64 rsrc_len; /* memory/io resource length */ + resource_size_t rsrc_start; /* memory/io resource start */ + resource_size_t rsrc_len; /* memory/io resource length */ unsigned power_budget; /* in mA, 0 = no limit */ /* bandwidth_mutex should be taken before adding or removing -- cgit v0.10.2 From e7aafd72f3bbf5032db5e96dd3b130e0077513ee Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Sun, 19 Aug 2012 13:04:29 +0200 Subject: usb: phy: isp1301: Remove unused static array and define This patch removes an unused statically defined array and an associated #define. Signed-off-by: Roland Stigge Signed-off-by: Felipe Balbi diff --git a/drivers/usb/phy/isp1301.c b/drivers/usb/phy/isp1301.c index b19f493..18dbf7e 100644 --- a/drivers/usb/phy/isp1301.c +++ b/drivers/usb/phy/isp1301.c @@ -15,12 +15,6 @@ #define DRV_NAME "isp1301" -#define ISP1301_I2C_ADDR 0x2C - -static const unsigned short normal_i2c[] = { - ISP1301_I2C_ADDR, ISP1301_I2C_ADDR + 1, I2C_CLIENT_END -}; - static const struct i2c_device_id isp1301_id[] = { { "isp1301", 0 }, { } -- cgit v0.10.2 From 10770c5aa0fe686014e9c15906a3ff702a4b0baf Mon Sep 17 00:00:00 2001 From: Matthias Brugger Date: Thu, 16 Aug 2012 13:00:25 +0200 Subject: usb: musb: omap2430.c delete unused variable. Variable ret is always evaluated as true, so we don't need to check it. Signed-off-by: Matthias Brugger Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index af5f421..02c39a7 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -141,7 +141,6 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on) struct usb_otg *otg = musb->xceiv->otg; u8 devctl; unsigned long timeout = jiffies + msecs_to_jiffies(1000); - int ret = 1; /* HDRC controls CPEN, but beware current surges during device * connect. They can trigger transient overcurrent conditions * that must be ignored. @@ -168,12 +167,11 @@ static void omap2430_musb_set_vbus(struct musb *musb, int is_on) || loops-- <= 0) { dev_err(musb->controller, "configured as A device timeout"); - ret = -EINVAL; break; } } - if (ret && otg->set_vbus) + if (otg->set_vbus) otg_set_vbus(otg, 1); } else { musb->is_active = 1; -- cgit v0.10.2 From 57bfc0a7ae21ee3c5a7f38b0577450b29a3333ac Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Sat, 18 Aug 2012 17:34:09 +0200 Subject: usb: musb: fix spelling of families in Kconfig Trivial patch fixin spelling of families in Kconfig [ balbi@ti.com : added the obvious commit log ] Signed-off-by: Peter Meerwald Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index ef0c3f9..2c74188 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -20,7 +20,7 @@ config USB_MUSB_HDRC it's being used with, including the USB peripheral role, or the USB host role, or both. - Texas Instruments familiies using this IP include DaVinci + Texas Instruments families using this IP include DaVinci (35x, 644x ...), OMAP 243x, OMAP 3, and TUSB 6010. Analog Devices parts using this IP include Blackfin BF54x, -- cgit v0.10.2 From 2d366846598d5f562866bba61a836d9325878066 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Fri, 17 Aug 2012 16:44:55 +0800 Subject: usb/endpoint: Set release callback in the struct device_type instead of in the device itself directly For following the way the rest of the usb core does, this patch is to change the place of setting release callback. Signed-off-by: Lan Tianyu Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index db7fe50..68cc653 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c @@ -24,10 +24,6 @@ struct ep_device { #define to_ep_device(_dev) \ container_of(_dev, struct ep_device, dev) -struct device_type usb_ep_device_type = { - .name = "usb_endpoint", -}; - struct ep_attribute { struct attribute attr; ssize_t (*show)(struct usb_device *, @@ -172,6 +168,11 @@ static void ep_device_release(struct device *dev) kfree(ep_dev); } +struct device_type usb_ep_device_type = { + .name = "usb_endpoint", + .release = ep_device_release, +}; + int usb_create_ep_devs(struct device *parent, struct usb_host_endpoint *endpoint, struct usb_device *udev) @@ -190,7 +191,6 @@ int usb_create_ep_devs(struct device *parent, ep_dev->dev.groups = ep_dev_groups; ep_dev->dev.type = &usb_ep_device_type; ep_dev->dev.parent = parent; - ep_dev->dev.release = ep_device_release; dev_set_name(&ep_dev->dev, "ep_%02x", endpoint->desc.bEndpointAddress); retval = device_register(&ep_dev->dev); -- cgit v0.10.2 From 7fda953ffed1b94aa68f80c6c3ab312328aedcb3 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Fri, 17 Aug 2012 16:44:56 +0800 Subject: usb: convert USB_QUIRK_RESET_MORPHS to USB_QUIRK_RESET Since the attribute avoid_reset_quirk is work for all devices including those devices that can't morph, convert USB_QUIRK_RESET_MORPHS to USB_QUIRK_RESET. Signed-off-by: Lan Tianyu Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index f15501f4c..2dbb515 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -205,7 +205,7 @@ void usb_detect_quirks(struct usb_device *udev) * for all devices. It will affect things like hub resets * and EMF-related port disables. */ - if (!(udev->quirks & USB_QUIRK_RESET_MORPHS)) + if (!(udev->quirks & USB_QUIRK_RESET)) udev->persist_enabled = 1; #endif /* CONFIG_PM */ } diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index d6c49d9..818e4a0 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -196,7 +196,7 @@ show_avoid_reset_quirk(struct device *dev, struct device_attribute *attr, char * struct usb_device *udev; udev = to_usb_device(dev); - return sprintf(buf, "%d\n", !!(udev->quirks & USB_QUIRK_RESET_MORPHS)); + return sprintf(buf, "%d\n", !!(udev->quirks & USB_QUIRK_RESET)); } static ssize_t @@ -210,9 +210,9 @@ set_avoid_reset_quirk(struct device *dev, struct device_attribute *attr, return -EINVAL; usb_lock_device(udev); if (val) - udev->quirks |= USB_QUIRK_RESET_MORPHS; + udev->quirks |= USB_QUIRK_RESET; else - udev->quirks &= ~USB_QUIRK_RESET_MORPHS; + udev->quirks &= ~USB_QUIRK_RESET; usb_unlock_device(udev); return count; } diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index c70109e..c0543c8 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -1331,7 +1331,7 @@ int usb_stor_port_reset(struct us_data *us) int result; /*for these devices we must use the class specific method */ - if (us->pusb_dev->quirks & USB_QUIRK_RESET_MORPHS) + if (us->pusb_dev->quirks & USB_QUIRK_RESET) return -EPERM; result = usb_lock_device_for_reset(us->pusb_dev, us->pusb_intf); diff --git a/include/linux/usb/quirks.h b/include/linux/usb/quirks.h index 3e93de7..52f944d 100644 --- a/include/linux/usb/quirks.h +++ b/include/linux/usb/quirks.h @@ -19,8 +19,8 @@ /* device can't handle its Configuration or Interface strings */ #define USB_QUIRK_CONFIG_INTF_STRINGS 0x00000008 -/*device will morph if reset, don't use reset for handling errors */ -#define USB_QUIRK_RESET_MORPHS 0x00000010 +/* device can't be reset(e.g morph devices), don't use reset */ +#define USB_QUIRK_RESET 0x00000010 /* device has more interface descriptions than the bNumInterfaces count, and can't handle talking to these interfaces */ -- cgit v0.10.2 From 9b2035a0b9ee9745c236cc2ec1ec0b0eae692a1a Mon Sep 17 00:00:00 2001 From: Neil Zhang Date: Tue, 10 Jul 2012 10:07:01 +0800 Subject: usb: gadget: mv_udc: reduce the delay interval There are several places use udelay(LOOPS_USEC) to wait the status to be changed, but the delay interval is a bit too long, so reduce it to enhance the performance. Signed-off-by: Neil Zhang Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index 75db2c3..9e40f89 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -53,7 +53,7 @@ #define READSAFE_TIMEOUT 1000 #define DTD_TIMEOUT 1000 -#define LOOPS_USEC_SHIFT 4 +#define LOOPS_USEC_SHIFT 1 #define LOOPS_USEC (1 << LOOPS_USEC_SHIFT) #define LOOPS(timeout) ((timeout) >> LOOPS_USEC_SHIFT) -- cgit v0.10.2 From a07bc24e2773e11cb4a6c03d72cd3cdb50c41914 Mon Sep 17 00:00:00 2001 From: Neil Zhang Date: Tue, 10 Jul 2012 10:07:02 +0800 Subject: usb: gadget: mv_udc: remove unused code Clean unused code for mv_udc driver. Signed-off-by: Neil Zhang Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index 9e40f89..c05d340 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -51,7 +51,6 @@ #define EPSTATUS_TIMEOUT 10000 #define PRIME_TIMEOUT 10000 #define READSAFE_TIMEOUT 1000 -#define DTD_TIMEOUT 1000 #define LOOPS_USEC_SHIFT 1 #define LOOPS_USEC (1 << LOOPS_USEC_SHIFT) @@ -64,7 +63,6 @@ static const char driver_desc[] = DRIVER_DESC; /* controller device global variable */ static struct mv_udc *the_controller; -int mv_usb_otgsc; static void nuke(struct mv_ep *ep, int status); static void stop_activity(struct mv_udc *udc, struct usb_gadget_driver *driver); -- cgit v0.10.2 From 0344606bec0f3325ba9c1d4de74a5dd98911916d Mon Sep 17 00:00:00 2001 From: Neil Zhang Date: Tue, 10 Jul 2012 10:07:03 +0800 Subject: usb: gadget: mv_udc: avoid sleeping on spinlock build_dtd() can be called when hold a spinlock, but GFP_KERNEL may cause dma_pool_alloc() sleep, So we need use GFP_ATOMIC instead of GFP_KERNEL. But using GFP_ATOMIC may cause failure when allocating memory, add error handler to handle it. Signed-off-by: Alexey Khoroshilov Signed-off-by: Neil Zhang Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index c05d340..425a204 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -373,7 +373,7 @@ static struct mv_dtd *build_dtd(struct mv_req *req, unsigned *length, * Be careful that no _GFP_HIGHMEM is set, * or we can not use dma_to_virt */ - dtd = dma_pool_alloc(udc->dtd_pool, GFP_KERNEL, dma); + dtd = dma_pool_alloc(udc->dtd_pool, GFP_ATOMIC, dma); if (dtd == NULL) return dtd; @@ -706,6 +706,7 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) struct mv_req *req = container_of(_req, struct mv_req, req); struct mv_udc *udc = ep->udc; unsigned long flags; + int retval; /* catch various bogus parameters */ if (!_req || !req->req.complete || !req->req.buf @@ -753,15 +754,17 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) /* build dtds and push them to device queue */ if (!req_to_dtd(req)) { - int retval; retval = queue_dtd(ep, req); if (retval) { spin_unlock_irqrestore(&udc->lock, flags); - return retval; + dev_err(&udc->dev->dev, "Failed to queue dtd\n"); + goto err_unmap_dma; } } else { spin_unlock_irqrestore(&udc->lock, flags); - return -ENOMEM; + dev_err(&udc->dev->dev, "Failed to dma_pool_alloc\n"); + retval = -ENOMEM; + goto err_unmap_dma; } /* Update ep0 state */ @@ -773,6 +776,22 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) spin_unlock_irqrestore(&udc->lock, flags); return 0; + +err_unmap_dma: + if (req->mapped) { + dma_unmap_single(ep->udc->gadget.dev.parent, + req->req.dma, req->req.length, + ((ep_dir(ep) == EP_DIR_IN) ? + DMA_TO_DEVICE : DMA_FROM_DEVICE)); + req->req.dma = DMA_ADDR_INVALID; + req->mapped = 0; + } else + dma_sync_single_for_cpu(ep->udc->gadget.dev.parent, + req->req.dma, req->req.length, + ((ep_dir(ep) == EP_DIR_IN) ? + DMA_TO_DEVICE : DMA_FROM_DEVICE)); + + return retval; } static void mv_prime_ep(struct mv_ep *ep, struct mv_req *req) @@ -1497,15 +1516,17 @@ udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty) } /* prime the data phase */ - if (!req_to_dtd(req)) + if (!req_to_dtd(req)) { retval = queue_dtd(ep, req); - else{ /* no mem */ + if (retval) { + dev_err(&udc->dev->dev, + "Failed to queue dtd when prime status\n"); + goto out; + } + } else{ /* no mem */ retval = -ENOMEM; - goto out; - } - - if (retval) { - dev_err(&udc->dev->dev, "response error on GET_STATUS request\n"); + dev_err(&udc->dev->dev, + "Failed to dma_pool_alloc when prime status\n"); goto out; } @@ -1513,6 +1534,15 @@ udc_prime_status(struct mv_udc *udc, u8 direction, u16 status, bool empty) return 0; out: + if (req->mapped) { + dma_unmap_single(ep->udc->gadget.dev.parent, + req->req.dma, req->req.length, + ((ep_dir(ep) == EP_DIR_IN) ? + DMA_TO_DEVICE : DMA_FROM_DEVICE)); + req->req.dma = DMA_ADDR_INVALID; + req->mapped = 0; + } + return retval; } -- cgit v0.10.2 From 583a7263c7ed05c9a625d50950551ba5749c9379 Mon Sep 17 00:00:00 2001 From: Neil Zhang Date: Tue, 10 Jul 2012 10:07:04 +0800 Subject: usb: gadget: mv_udc: enable stream mode According to ChipIdea's reference manual in section 8.5.2 "Non-streaming operational mode in device mode", we'd better enable stream mode, especially that ISO endpoints are not supported when the SDIS bit is set. Signed-off-by: Neil Zhang Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index 425a204..4d3a413 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -1082,7 +1082,7 @@ static int udc_reset(struct mv_udc *udc) tmp |= USBMODE_CTRL_MODE_DEVICE; /* turn setup lockout off, require setup tripwire in usbcmd */ - tmp |= USBMODE_SETUP_LOCK_OFF | USBMODE_STREAM_DISABLE; + tmp |= USBMODE_SETUP_LOCK_OFF; writel(tmp, &udc->op_regs->usbmode); -- cgit v0.10.2 From 60326ce377090541db9ba1a05a041316ab5b46ec Mon Sep 17 00:00:00 2001 From: Chao Xie Date: Tue, 10 Jul 2012 10:07:05 +0800 Subject: usb: gadget: mv_udc: add iso support In order to support iso, we need do the following things: 1. fix length for one dtd 2. allow req contains multiple packets for a ISO transfer Signed-off-by: Chao Xie Signed-off-by: Yu Xu Signed-off-by: Neil Zhang Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index 4d3a413..ff6154d 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -355,17 +355,24 @@ done: return retval; } - static struct mv_dtd *build_dtd(struct mv_req *req, unsigned *length, dma_addr_t *dma, int *is_last) { - u32 temp; struct mv_dtd *dtd; struct mv_udc *udc; + struct mv_dqh *dqh; + u32 temp, mult = 0; /* how big will this transfer be? */ - *length = min(req->req.length - req->req.actual, - (unsigned)EP_MAX_LENGTH_TRANSFER); + if (usb_endpoint_xfer_isoc(req->ep->ep.desc)) { + dqh = req->ep->dqh; + mult = (dqh->max_packet_length >> EP_QUEUE_HEAD_MULT_POS) + & 0x3; + *length = min(req->req.length - req->req.actual, + (unsigned)(mult * req->ep->ep.maxpacket)); + } else + *length = min(req->req.length - req->req.actual, + (unsigned)EP_MAX_LENGTH_TRANSFER); udc = req->ep->udc; @@ -407,6 +414,8 @@ static struct mv_dtd *build_dtd(struct mv_req *req, unsigned *length, if (*is_last && !req->req.no_interrupt) temp |= DTD_IOC; + temp |= mult << 10; + dtd->size_ioc_sts = temp; mb(); @@ -718,10 +727,6 @@ mv_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) dev_err(&udc->dev->dev, "%s, bad ep", __func__); return -EINVAL; } - if (ep->ep.desc->bmAttributes == USB_ENDPOINT_XFER_ISOC) { - if (req->req.length > ep->ep.maxpacket) - return -EMSGSIZE; - } udc = ep->udc; if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) -- cgit v0.10.2 From 1dcaa252fdf01e4ba49ece156812043baf01c7cc Mon Sep 17 00:00:00 2001 From: Yunfan Zhang Date: Tue, 10 Jul 2012 10:07:06 +0800 Subject: usb: gadget: mv_udc: fix hang when shutdown Fix system hang in udc shutdown routine which caused by accessing usb register when clock is disabled. So enable usb clock before access register. Signed-off-by: Yunfan Zhang Signed-off-by: Neil Zhang Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index ff6154d..58edff9 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -2501,9 +2501,11 @@ static void mv_udc_shutdown(struct platform_device *dev) u32 mode; /* reset controller mode to IDLE */ + mv_udc_enable(udc); mode = readl(&udc->op_regs->usbmode); mode &= ~3; writel(mode, &udc->op_regs->usbmode); + mv_udc_disable(udc); } static struct platform_driver udc_driver = { -- cgit v0.10.2 From 11c37c8b64b9d9d4ab19d387e6028eee3ec188d3 Mon Sep 17 00:00:00 2001 From: Neil Zhang Date: Tue, 10 Jul 2012 10:07:07 +0800 Subject: usb: gadget: mv_udc: fix boot up hang Fix boot up hang when enable udc without otg enabled. The root cause is that the clock will be shut down when probe routine is finished because of clock gating. When a gadget driver is registered at this time, it will call mv_udc_start which in turn will call mv_udc_vbus_session. If there is no cable attached at the boot up time, the vbus is low, so it will call stop_activity path without clock enabled which will cause system hang then. Actually, we need't go this path when clock is disabled, what we need to do is just jump out. Signed-off-by: Neil Zhang Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index 58edff9..ad91de4 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -1221,12 +1221,16 @@ static int mv_udc_vbus_session(struct usb_gadget *gadget, int is_active) udc_start(udc); } } else if (udc->driver && udc->softconnect) { + if (!udc->active) + goto out; + /* stop all the transfer in queue*/ stop_activity(udc, udc->driver); udc_stop(udc); mv_udc_disable(udc); } +out: spin_unlock_irqrestore(&udc->lock, flags); return retval; } -- cgit v0.10.2 From 4fefe9f6de3d6e0b5e58b17cbab9c47c74f88cb6 Mon Sep 17 00:00:00 2001 From: Michael Grzeschik Date: Thu, 19 Jul 2012 00:20:11 +0200 Subject: usb composite: fix locking in usb_function_activate The lockdep hunter mentions a non consistent usage of spin_lock and spin_lock_irqsafe in the composite_disconnect and usb_function_activate function: [ 15.700897] ================================= [ 15.705255] [ INFO: inconsistent lock state ] [ 15.709617] 3.5.0-rc5+ #413 Not tainted [ 15.713453] --------------------------------- [ 15.717812] inconsistent {HARDIRQ-ON-W} -> {IN-HARDIRQ-W} usage. [ 15.723822] uvc-gadget/116 [HC1[1]:SC0[0]:HE0:SE1] takes: [ 15.729222] (&(&cdev->lock)->rlock){?.+...}, at: [<7f0049e8>] composite_disconnect+0x2c/0x74 [g_webcam] [ 15.738797] {HARDIRQ-ON-W} state was registered at: [ 15.743677] [<8006de3c>] mark_lock+0x148/0x688 [ 15.748325] [<8006ecb0>] __lock_acquire+0x934/0x1b74 [ 15.753481] [<8007047c>] lock_acquire+0x98/0x138 [ 15.758288] [<804c776c>] _raw_spin_lock+0x4c/0x84 [ 15.763188] [<7f006ae4>] usb_function_activate+0x28/0x94 [g_webcam] [ 15.769652] [<7f00820c>] usb_ep_autoconfig_reset+0x78/0x98 [g_webcam] [ 15.776287] [<7f0082a4>] uvc_v4l2_open+0x78/0x94 [g_webcam] [ 15.782054] [<80366a38>] v4l2_open+0x104/0x130 [ 15.786697] [<800efd30>] chrdev_open+0xa0/0x170 [ 15.791423] [<800e9718>] do_dentry_open.isra.13+0x1e8/0x264 [ 15.797186] [<800ea5d4>] nameidata_to_filp+0x58/0x94 [ 15.802340] [<800fa29c>] do_last.isra.31+0x2a0/0x808 [ 15.807497] [<800faa40>] path_openat+0xc8/0x3e8 [ 15.812216] [<800fae90>] do_filp_open+0x3c/0x90 [ 15.816936] [<800ea6fc>] do_sys_open+0xec/0x184 [ 15.821655] [<800ea7c4>] sys_open+0x30/0x34 [ 15.826027] [<8000e5c0>] ret_fast_syscall+0x0/0x48 [ 15.831015] irq event stamp: 6048 [ 15.834330] hardirqs last enabled at (6047): [<804c81b8>] _raw_spin_unlock_irqrestore+0x40/0x54 [ 15.843132] hardirqs last disabled at (6048): [<8000e174>] __irq_svc+0x34/0x60 [ 15.850370] softirqs last enabled at (5940): [<80028380>] __do_softirq+0x188/0x270 [ 15.858043] softirqs last disabled at (5935): [<80028944>] irq_exit+0xa0/0xa8 [ 15.865195] [ 15.865195] other info that might help us debug this: [ 15.871724] Possible unsafe locking scenario: [ 15.871724] [ 15.877645] CPU0 [ 15.880091] ---- [ 15.882537] lock(&(&cdev->lock)->rlock); [ 15.886659] [ 15.889278] lock(&(&cdev->lock)->rlock); [ 15.893573] [ 15.893573] *** DEADLOCK *** [ 15.893573] [ 15.899496] no locks held by uvc-gadget/116. [ 15.903765] [ 15.903765] stack backtrace: [ 15.908125] Backtrace: [ 15.910604] [<80012038>] (dump_backtrace+0x0/0x114) from [<804bf8a4>] (dump_stack+0x20/0x24) [ 15.919043] r6:dfb8e6f0 r5:dfb8e400 r4:809717ec r3:60000193 [ 15.924766] [<804bf884>] (dump_stack+0x0/0x24) from [<804c0c0c>] (print_usage_bug+0x258/0x2c0) [ 15.933388] [<804c09b4>] (print_usage_bug+0x0/0x2c0) from [<8006e240>] (mark_lock+0x54c/0x688) [ 15.942006] [<8006dcf4>] (mark_lock+0x0/0x688) from [<8006edb8>] (__lock_acquire+0xa3c/0x1b74) [ 15.950625] [<8006e37c>] (__lock_acquire+0x0/0x1b74) from [<8007047c>] (lock_acquire+0x98/0x138) [ 15.959418] [<800703e4>] (lock_acquire+0x0/0x138) from [<804c78fc>] (_raw_spin_lock_irqsave+0x58/0x94) [ 15.968736] [<804c78a4>] (_raw_spin_lock_irqsave+0x0/0x94) from [<7f0049e8>] (composite_disconnect+0x2c/0x74 [g_webcam]) [ 15.979605] r7:00000012 r6:df82b0c4 r5:ded755bc r4:ded75580 [ 15.985331] [<7f0049bc>] (composite_disconnect+0x0/0x74 [g_webcam]) from [<8033c170>] (_gadget_stop_activity+0xc4/0x120) [ 15.996200] r6:df82b0c4 r5:df82b0c8 r4:df82b0d0 r3:7f0049bc [ 16.001919] [<8033c0ac>] (_gadget_stop_activity+0x0/0x120) from [<8033e390>] (udc_irq+0x724/0xcb8) [ 16.010877] r6:df82b010 r5:00000000 r4:df82b010 r3:00000000 [ 16.016595] [<8033dc6c>] (udc_irq+0x0/0xcb8) from [<8033baec>] (ci_irq+0x64/0xdc) [ 16.024086] [<8033ba88>] (ci_irq+0x0/0xdc) from [<80086538>] (handle_irq_event_percpu+0x74/0x298) [ 16.032958] r5:807fd414 r4:df38fdc0 [ 16.036566] [<800864c4>] (handle_irq_event_percpu+0x0/0x298) from [<800867a8>] (handle_irq_event+0x4c/0x6c) [ 16.046315] [<8008675c>] (handle_irq_event+0x0/0x6c) from [<80089318>] (handle_level_irq+0xbc/0x11c) [ 16.055447] r6:def04000 r5:807fd414 r4:807fd3c0 r3:00020000 [ 16.061166] [<8008925c>] (handle_level_irq+0x0/0x11c) from [<80085cc8>] (generic_handle_irq+0x38/0x4c) [ 16.070472] r5:807f7f64 r4:8081e9f8 [ 16.074082] [<80085c90>] (generic_handle_irq+0x0/0x4c) from [<8000ef98>] (handle_IRQ+0x5c/0xbc) [ 16.082788] [<8000ef3c>] (handle_IRQ+0x0/0xbc) from [<800085cc>] (tzic_handle_irq+0x6c/0x9c) [ 16.091225] r8:00000000 r7:def059b0 r6:00000001 r5:00000000 r4:00000000 r3:00000012 [ 16.099141] [<80008560>] (tzic_handle_irq+0x0/0x9c) from [<8000e184>] (__irq_svc+0x44/0x60) [ 16.107494] Exception stack(0xdef059b0 to 0xdef059f8) [ 16.112550] 59a0: 00000001 00000001 00000000 dfb8e400 [ 16.120732] 59c0: 40000013 81a2e500 00000000 81a2e500 00000000 00000000 80862418 def05a0c [ 16.128912] 59e0: def059c8 def059f8 80070e24 804c81bc 20000013 ffffffff [ 16.135542] [<804c8178>] (_raw_spin_unlock_irqrestore+0x0/0x54) from [<8003d0ec>] (__queue_work+0x108/0x470) [ 16.145369] r5:dfb1a30c r4:81b93c00 [ 16.148978] [<8003cfe4>] (__queue_work+0x0/0x470) from [<8003d4e0>] (queue_work_on+0x4c/0x54) [ 16.157511] [<8003d494>] (queue_work_on+0x0/0x54) from [<8003d544>] (queue_work+0x30/0x34) [ 16.165774] r6:df2e6900 r5:80e0c2f8 r4:dfb1a2c8 r3:def04000 [ 16.171495] [<8003d514>] (queue_work+0x0/0x34) from [<80493284>] (rpc_make_runnable+0x9c/0xac) [ 16.180113] [<804931e8>] (rpc_make_runnable+0x0/0xac) from [<80493c88>] (rpc_execute+0x40/0xa8) [ 16.188811] r5:def05ad4 r4:dfb1a2c8 [ 16.192426] [<80493c48>] (rpc_execute+0x0/0xa8) from [<8048c734>] (rpc_run_task+0xa8/0xb4) [ 16.200690] r8:00000001 r7:df74f520 r6:ded75700 r5:def05ad4 r4:dfb1a2c8 r3:00000002 [ 16.208618] [<8048c68c>] (rpc_run_task+0x0/0xb4) from [<801f1608>] (nfs_initiate_read+0xb4/0xd4) [ 16.217403] r5:df3e86c0 r4:00000000 [ 16.221015] [<801f1554>] (nfs_initiate_read+0x0/0xd4) from [<801f1c64>] (nfs_generic_pg_readpages+0x9c/0x114) [ 16.230937] [<801f1bc8>] (nfs_generic_pg_readpages+0x0/0x114) from [<801f0744>] (__nfs_pageio_add_request+0xe8/0x214) [ 16.241545] r8:000bf000 r7:00000000 r6:00000000 r5:deef4640 r4:def05c1c r3:801f1bc8 [ 16.249463] [<801f065c>] (__nfs_pageio_add_request+0x0/0x214) from [<801f0e3c>] (nfs_pageio_add_request+0x28/0x54) [ 16.259818] [<801f0e14>] (nfs_pageio_add_request+0x0/0x54) from [<801f1394>] (readpage_async_filler+0x114/0x170) [ 16.269992] r5:def05c58 r4:80fd7300 [ 16.273607] [<801f1280>] (readpage_async_filler+0x0/0x170) from [<800bb418>] (read_cache_pages+0xa0/0x108) [ 16.283259] r8:00200200 r7:00100100 r6:df74f654 r5:def05cd0 r4:80fd7300 [ 16.290034] [<800bb378>] (read_cache_pages+0x0/0x108) from [<801f218c>] (nfs_readpages+0xc4/0x168) [ 16.298999] [<801f20c8>] (nfs_readpages+0x0/0x168) from [<800bb1d0>] (__do_page_cache_readahead+0x254/0x354) [ 16.308833] [<800baf7c>] (__do_page_cache_readahead+0x0/0x354) from [<800bb5d0>] (ra_submit+0x38/0x40) [ 16.318145] [<800bb598>] (ra_submit+0x0/0x40) from [<800bb6b0>] (ondemand_readahead+0xd8/0x3b0) [ 16.326851] [<800bb5d8>] (ondemand_readahead+0x0/0x3b0) from [<800bba20>] (page_cache_async_readahead+0x98/0xa8) [ 16.337043] [<800bb988>] (page_cache_async_readahead+0x0/0xa8) from [<800b2118>] (generic_file_aio_read+0x5b4/0x7c4) [ 16.347565] r6:00000000 r5:df74f654 r4:80fd70a0 [ 16.352231] [<800b1b64>] (generic_file_aio_read+0x0/0x7c4) from [<801e82c0>] (nfs_file_read+0x7c/0xcc) [ 16.361544] [<801e8244>] (nfs_file_read+0x0/0xcc) from [<800eab80>] (do_sync_read+0xb4/0xf4) [ 16.369981] r9:00000000 r8:def05f70 r7:00000000 r6:00000000 r5:dec34900 r4:fffffdee [ 16.377896] [<800eaacc>] (do_sync_read+0x0/0xf4) from [<800eb548>] (vfs_read+0xb4/0x144) [ 16.385987] r8:00000000 r7:def05f70 r6:76a95008 r5:003e3dd6 r4:dec34900 [ 16.392761] [<800eb494>] (vfs_read+0x0/0x144) from [<800eb624>] (sys_read+0x4c/0x78) [ 16.400504] r8:00000000 r7:00000003 r6:003e3dd6 r5:76a95008 r4:dec34900 [ 16.407279] [<800eb5d8>] (sys_read+0x0/0x78) from [<8000e5c0>] (ret_fast_syscall+0x0/0x48) [ 16.415543] r9:def04000 r8:8000e864 r6:000086b4 r5:00000000 r4:00000000 [ 20.872729] gadget: high-speed config #1: Video [ 20.877368] gadget: uvc_function_set_alt(0, 0) [ 20.881908] gadget: uvc_function_set_alt(1, 0) [ 20.891464] gadget: uvc_function_set_alt(1, 0) Signed-off-by: Michael Grzeschik Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 3f72110..2cb1030 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -300,9 +300,10 @@ int usb_function_deactivate(struct usb_function *function) int usb_function_activate(struct usb_function *function) { struct usb_composite_dev *cdev = function->config->cdev; + unsigned long flags; int status = 0; - spin_lock(&cdev->lock); + spin_lock_irqsave(&cdev->lock, flags); if (WARN_ON(cdev->deactivations == 0)) status = -EINVAL; @@ -312,7 +313,7 @@ int usb_function_activate(struct usb_function *function) status = usb_gadget_connect(cdev->gadget); } - spin_unlock(&cdev->lock); + spin_unlock_irqrestore(&cdev->lock, flags); return status; } -- cgit v0.10.2 From 2868fea2d615d9f445a0ccaf988e1418a9787ebe Mon Sep 17 00:00:00 2001 From: "Du, Changbin" Date: Tue, 24 Jul 2012 08:19:25 +0800 Subject: usb: gadget: s3c-hsotg: fix core reset timeout failure The timeout values were 1000 and timeout issue occured many times on my s3c6410 Soc based board (mostly when booting whith USB cable not connected). This patch increase the values to 10000 to guarantee the success of reset. Having set timeout to 10000, I printed the remained timeout values which could cause timeout issue before this change (tested several times). the first timeout value remained: timeout = 8079 timeout = 8079 timeout = 8078 timeout = 8081 the second timeout value remained: timeout = 7940 timeout = 7945 timeout = 7940 timeout = 7938 Seeing from above values, I think the value 10000 is big enough. Signed-off-by: Du, Changbin Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index b13e0bb..a826cb9 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -2197,7 +2197,7 @@ static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg) /* issue soft reset */ writel(GRSTCTL_CSftRst, hsotg->regs + GRSTCTL); - timeout = 1000; + timeout = 10000; do { grstctl = readl(hsotg->regs + GRSTCTL); } while ((grstctl & GRSTCTL_CSftRst) && timeout-- > 0); @@ -2207,7 +2207,7 @@ static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg) return -EINVAL; } - timeout = 1000; + timeout = 10000; while (1) { u32 grstctl = readl(hsotg->regs + GRSTCTL); -- cgit v0.10.2 From d3091cfff73ce44c6b0cb61b25074f0ac648604f Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Tue, 7 Aug 2012 19:07:58 +0300 Subject: usb: gadget: use native print_hex_dump_bytes() Acked-by: Michal Nazarewicz Signed-off-by: Andy Shevchenko Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c index b35babe..e4192b8 100644 --- a/drivers/usb/gadget/rndis.c +++ b/drivers/usb/gadget/rndis.c @@ -863,26 +863,8 @@ int rndis_msg_parser(u8 configNr, u8 *buf) */ pr_warning("%s: unknown RNDIS message 0x%08X len %d\n", __func__, MsgType, MsgLength); - { - unsigned i; - for (i = 0; i < MsgLength; i += 16) { - pr_debug("%03d: " - " %02x %02x %02x %02x" - " %02x %02x %02x %02x" - " %02x %02x %02x %02x" - " %02x %02x %02x %02x" - "\n", - i, - buf[i], buf [i+1], - buf[i+2], buf[i+3], - buf[i+4], buf [i+5], - buf[i+6], buf[i+7], - buf[i+8], buf [i+9], - buf[i+10], buf[i+11], - buf[i+12], buf [i+13], - buf[i+14], buf[i+15]); - } - } + print_hex_dump_bytes(__func__, DUMP_PREFIX_OFFSET, + buf, MsgLength); break; } -- cgit v0.10.2 From 974e9323deefbab923d7aa8f0e4bcf9066c2ec97 Mon Sep 17 00:00:00 2001 From: Kevin Cernekee Date: Thu, 9 Aug 2012 11:23:52 +0300 Subject: usb: gadget: udc-core: Race between disconnect/unbind and setup usb_gadget_remove_driver() runs through a four-step sequence to shut down the gadget driver. For the case of a composite gadget + at91 UDC, this would look like: udc->driver->disconnect(udc->gadget); // composite_disconnect() usb_gadget_disconnect(udc->gadget); // at91_pullup(gadget, 0) udc->driver->unbind(udc->gadget); // composite_unbind() usb_gadget_udc_stop(udc->gadget, udc->driver); // at91_stop() The UDC driver can receive SETUP packets from the host up until the point when usb_gadget_disconnect() returns. On rare occasions, the gadget driver may see this sequence: udc->driver->disconnect(udc->gadget); // composite_disconnect() udc->driver->setup(udc->gadget, &ctrl); // composite_setup() udc->driver->unbind(udc->gadget); // composite_unbind() Some gadget drivers, such as composite, assume this will never happen and crash as a result. The fix is to quiesce the UDC hardware (via usb_gadget_disconnect) before running the gadget driver through the disconnect/unbind sequence. Reviewed-by: Peter Chen Signed-off-by: Kevin Cernekee Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index e5e44f8..bae243c 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -262,8 +262,8 @@ static void usb_gadget_remove_driver(struct usb_udc *udc) kobject_uevent(&udc->dev.kobj, KOBJ_CHANGE); if (udc_is_newstyle(udc)) { - udc->driver->disconnect(udc->gadget); usb_gadget_disconnect(udc->gadget); + udc->driver->disconnect(udc->gadget); udc->driver->unbind(udc->gadget); usb_gadget_udc_stop(udc->gadget, udc->driver); } else { -- cgit v0.10.2 From 8c7ca99250de69dfe97c5f4f6e2eb11dc6145779 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Fri, 6 Jul 2012 18:30:21 +0300 Subject: usb: gadget: use %pm to print mac addresses %pm already provides pretty print for mac addresses, let's use that and drop homebrew mac address printing. Signed-off-by: Andy Shevchenko Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c index 30b908f..95bc94f 100644 --- a/drivers/usb/gadget/f_ecm.c +++ b/drivers/usb/gadget/f_ecm.c @@ -897,10 +897,7 @@ ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) return -ENOMEM; /* export host's Ethernet address in CDC format */ - snprintf(ecm->ethaddr, sizeof ecm->ethaddr, - "%02X%02X%02X%02X%02X%02X", - ethaddr[0], ethaddr[1], ethaddr[2], - ethaddr[3], ethaddr[4], ethaddr[5]); + snprintf(ecm->ethaddr, sizeof ecm->ethaddr, "%pm", ethaddr); ecm_string_defs[1].s = ecm->ethaddr; ecm->port.cdc_filter = DEFAULT_FILTER; diff --git a/drivers/usb/gadget/f_ncm.c b/drivers/usb/gadget/f_ncm.c index aab8ede..b651b52 100644 --- a/drivers/usb/gadget/f_ncm.c +++ b/drivers/usb/gadget/f_ncm.c @@ -1346,10 +1346,7 @@ int __init ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) return -ENOMEM; /* export host's Ethernet address in CDC format */ - snprintf(ncm->ethaddr, sizeof ncm->ethaddr, - "%02X%02X%02X%02X%02X%02X", - ethaddr[0], ethaddr[1], ethaddr[2], - ethaddr[3], ethaddr[4], ethaddr[5]); + snprintf(ncm->ethaddr, sizeof ncm->ethaddr, "%pm", ethaddr); ncm_string_defs[1].s = ncm->ethaddr; spin_lock_init(&ncm->lock); diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c index 21ab474..4060c0b 100644 --- a/drivers/usb/gadget/f_subset.c +++ b/drivers/usb/gadget/f_subset.c @@ -436,10 +436,7 @@ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]) return -ENOMEM; /* export host's Ethernet address in CDC format */ - snprintf(geth->ethaddr, sizeof geth->ethaddr, - "%02X%02X%02X%02X%02X%02X", - ethaddr[0], ethaddr[1], ethaddr[2], - ethaddr[3], ethaddr[4], ethaddr[5]); + snprintf(geth->ethaddr, sizeof geth->ethaddr, "%pm", ethaddr); geth_string_defs[1].s = geth->ethaddr; geth->port.cdc_filter = DEFAULT_FILTER; -- cgit v0.10.2 From 4e177260e547e438c78c60b6db6f755bb89e0596 Mon Sep 17 00:00:00 2001 From: "Shimoda, Yoshihiro" Date: Mon, 20 Aug 2012 18:39:23 +0900 Subject: usb: renesas_usbhs: modify the irq handler for sharing irq When IORESOURCE_IRQ_SHAREABLE is set, the irq handler may be called even if the interupt of the USB module doesn't happen. So, it may clear the interrupt flags by mistake. This patch fixes it. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Felipe Balbi diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c index 82a628f..35c5208 100644 --- a/drivers/usb/renesas_usbhs/mod.c +++ b/drivers/usb/renesas_usbhs/mod.c @@ -209,14 +209,18 @@ int usbhs_status_get_ctrl_stage(struct usbhs_irq_state *irq_state) return (int)irq_state->intsts0 & CTSQ_MASK; } -static void usbhs_status_get_each_irq(struct usbhs_priv *priv, - struct usbhs_irq_state *state) +static int usbhs_status_get_each_irq(struct usbhs_priv *priv, + struct usbhs_irq_state *state) { struct usbhs_mod *mod = usbhs_mod_get_current(priv); + u16 intenb0, intenb1; state->intsts0 = usbhs_read(priv, INTSTS0); state->intsts1 = usbhs_read(priv, INTSTS1); + intenb0 = usbhs_read(priv, INTENB0); + intenb1 = usbhs_read(priv, INTENB1); + /* mask */ if (mod) { state->brdysts = usbhs_read(priv, BRDYSTS); @@ -226,6 +230,20 @@ static void usbhs_status_get_each_irq(struct usbhs_priv *priv, state->bempsts &= mod->irq_bempsts; state->brdysts &= mod->irq_brdysts; } + + /* + * Check whether the irq enable registers and the irq status are set + * when IRQF_SHARED is set. + */ + if (priv->irqflags & IRQF_SHARED) { + if (!(intenb0 & state->intsts0) && + !(intenb1 & state->intsts1) && + !(state->bempsts) && + !(state->brdysts)) + return -EIO; + } + + return 0; } /* @@ -238,7 +256,8 @@ static irqreturn_t usbhs_interrupt(int irq, void *data) struct usbhs_priv *priv = data; struct usbhs_irq_state irq_state; - usbhs_status_get_each_irq(priv, &irq_state); + if (usbhs_status_get_each_irq(priv, &irq_state) < 0) + return IRQ_NONE; /* * clear interrupt -- cgit v0.10.2 From 2a540edf7bb02f3e968d1ce7cb355e740ba7de13 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Sun, 26 Aug 2012 21:34:19 +0200 Subject: usb: dwc3: core: memory ordering fix in close As a bitmap is used for free/used. As a device freed all memory operations must be scheduled before the bitmap is manipulated. Signed-off-by: Oliver Neukum Signed-off-by: Felipe Balbi diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 4f2ef53..08a5738 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -99,6 +99,7 @@ void dwc3_put_device_id(int id) ret = test_bit(id, dwc3_devs); WARN(!ret, "dwc3: ID %d not in use\n", id); + smp_mb__before_clear_bit(); clear_bit(id, dwc3_devs); } EXPORT_SYMBOL_GPL(dwc3_put_device_id); -- cgit v0.10.2 From d2e9a13a388304bc2a7b25a6c34c6e2ab1540a5d Mon Sep 17 00:00:00 2001 From: Chanho Park Date: Fri, 31 Aug 2012 16:54:07 +0900 Subject: usb: dwc3: set up burst size only superspeed mode When connection is established non-ss mode, endpoint.maxburst is correctly set to 0, this means that current code will set maxburst bitfield on DEPCFG's parameter 0 to the highest possible value (0x0f) which is wrong. Even though this hasn't caused any issues so far (HW seems to ignore that when not running in SS mode) we want to make sure maxburst bitfield is only set to anything other than zero if we're running on SuperSpeed mode. In order to achieve that, let's check for gadget's operating speed before setting maxburst bitfield when issuing DEPCFG command. [ balbi@ti.com : improved commit log a bit in order to clarify the situation ] Signed-off-by: Chanho Park Signed-off-by: Kyungmin Park Signed-off-by: Felipe Balbi diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 029cf06..ba444e7 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -439,8 +439,14 @@ static int dwc3_gadget_set_ep_config(struct dwc3 *dwc, struct dwc3_ep *dep, memset(¶ms, 0x00, sizeof(params)); params.param0 = DWC3_DEPCFG_EP_TYPE(usb_endpoint_type(desc)) - | DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc)) - | DWC3_DEPCFG_BURST_SIZE(dep->endpoint.maxburst - 1); + | DWC3_DEPCFG_MAX_PACKET_SIZE(usb_endpoint_maxp(desc)); + + /* Burst size is only needed in SuperSpeed mode */ + if (dwc->gadget.speed == USB_SPEED_SUPER) { + u32 burst = dep->endpoint.maxburst - 1; + + params.param0 |= DWC3_DEPCFG_BURST_SIZE(burst); + } if (ignore) params.param0 |= DWC3_DEPCFG_IGN_SEQ_NUM; -- cgit v0.10.2 From 252d8cec49a79d26fafb845337dd16e5e1012c1b Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Mon, 20 Aug 2012 10:30:12 +0200 Subject: usb: gadget: lpc32xx_udc: Port to new start/stop interface This patch adjusts the LPC32xx USB gadget driver to the new udc_start / udc_stop interface. Signed-off-by: Roland Stigge Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c index f1ec99e..7e31ac2 100644 --- a/drivers/usb/gadget/lpc32xx_udc.c +++ b/drivers/usb/gadget/lpc32xx_udc.c @@ -2599,9 +2599,8 @@ static int lpc32xx_pullup(struct usb_gadget *gadget, int is_on) return 0; } -static int lpc32xx_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)); -static int lpc32xx_stop(struct usb_gadget_driver *driver); +static int lpc32xx_start(struct usb_gadget *, struct usb_gadget_driver *); +static int lpc32xx_stop(struct usb_gadget *, struct usb_gadget_driver *); static const struct usb_gadget_ops lpc32xx_udc_ops = { .get_frame = lpc32xx_get_frame, @@ -2609,8 +2608,8 @@ static const struct usb_gadget_ops lpc32xx_udc_ops = { .set_selfpowered = lpc32xx_set_selfpowered, .vbus_session = lpc32xx_vbus_session, .pullup = lpc32xx_pullup, - .start = lpc32xx_start, - .stop = lpc32xx_stop, + .udc_start = lpc32xx_start, + .udc_stop = lpc32xx_stop, }; static void nop_release(struct device *dev) @@ -2987,14 +2986,13 @@ static irqreturn_t lpc32xx_usb_vbus_irq(int irq, void *_udc) return IRQ_HANDLED; } -static int lpc32xx_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) +static int lpc32xx_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { - struct lpc32xx_udc *udc = &controller; - int retval, i; + struct lpc32xx_udc *udc = to_udc(gadget); + int i; - if (!driver || driver->max_speed < USB_SPEED_FULL || - !bind || !driver->setup) { + if (!driver || driver->max_speed < USB_SPEED_FULL || !driver->setup) { dev_err(udc->dev, "bad parameter.\n"); return -EINVAL; } @@ -3011,18 +3009,6 @@ static int lpc32xx_start(struct usb_gadget_driver *driver, udc->selfpowered = 1; udc->vbus = 0; - retval = bind(&udc->gadget); - if (retval) { - dev_err(udc->dev, "bind() returned %d\n", retval); - udc->enabled = 0; - udc->selfpowered = 0; - udc->driver = NULL; - udc->gadget.dev.driver = NULL; - return retval; - } - - dev_dbg(udc->dev, "bound to %s\n", driver->driver.name); - /* Force VBUS process once to check for cable insertion */ udc->last_vbus = udc->vbus = 0; schedule_work(&udc->vbus_job); @@ -3034,22 +3020,19 @@ static int lpc32xx_start(struct usb_gadget_driver *driver, return 0; } -static int lpc32xx_stop(struct usb_gadget_driver *driver) +static int lpc32xx_stop(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { int i; - struct lpc32xx_udc *udc = &controller; + struct lpc32xx_udc *udc = to_udc(gadget); - if (!driver || driver != udc->driver || !driver->unbind) + if (!driver || driver != udc->driver) return -EINVAL; - /* Disable USB pullup */ - isp1301_pullup_enable(udc, 0, 1); - for (i = IRQ_USB_LP; i <= IRQ_USB_ATX; i++) disable_irq(udc->udp_irq[i]); if (udc->clocked) { - spin_lock(&udc->lock); stop_activity(udc); spin_unlock(&udc->lock); @@ -3069,20 +3052,16 @@ static int lpc32xx_stop(struct usb_gadget_driver *driver) } udc->enabled = 0; - pullup(udc, 0); - - driver->unbind(&udc->gadget); udc->gadget.dev.driver = NULL; udc->driver = NULL; - dev_dbg(udc->dev, "unbound from %s\n", driver->driver.name); return 0; } static void lpc32xx_udc_shutdown(struct platform_device *dev) { /* Force disconnect on reboot */ - struct lpc32xx_udc *udc = &controller; + struct lpc32xx_udc *udc = platform_get_drvdata(dev); pullup(udc, 0); } -- cgit v0.10.2 From 78ca9139736f059b70bd797b01227271e0efa681 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Mon, 20 Aug 2012 10:30:13 +0200 Subject: usb: gadget: lpc32xx_udc: Remove usb_endpoint_descriptor This patch removes the utilization of struct usb_endpoint_descriptor, as done by other drivers also. This was done on request by the USB gadget maintainers, since this API is obsoleted. Signed-off-by: Roland Stigge Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c index 7e31ac2..6dd8f69 100644 --- a/drivers/usb/gadget/lpc32xx_udc.c +++ b/drivers/usb/gadget/lpc32xx_udc.c @@ -141,8 +141,6 @@ struct lpc32xx_ep { u32 totalints; bool wedge; - - const struct usb_endpoint_descriptor *desc; }; /* @@ -556,10 +554,8 @@ static int proc_udc_show(struct seq_file *s, void *unused) if (udc->enabled && udc->vbus) { proc_ep_show(s, &udc->ep[0]); - list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) { - if (ep->desc) - proc_ep_show(s, ep); - } + list_for_each_entry(ep, &udc->gadget.ep_list, ep.ep_list) + proc_ep_show(s, ep); } spin_unlock_irqrestore(&udc->lock, flags); @@ -1453,7 +1449,6 @@ static void udc_reinit(struct lpc32xx_udc *udc) if (i != 0) list_add_tail(&ep->ep.ep_list, &udc->gadget.ep_list); - ep->desc = NULL; ep->ep.maxpacket = ep->maxpacket; INIT_LIST_HEAD(&ep->queue); ep->req_pending = 0; @@ -1515,7 +1510,7 @@ static void nuke(struct lpc32xx_ep *ep, int status) done(ep, req, status); } - if (ep->desc && status == -ESHUTDOWN) { + if (status == -ESHUTDOWN) { uda_disable_hwepint(ep->udc, ep->hwep_num); udc_disable_hwep(ep->udc, ep->hwep_num); } @@ -1658,9 +1653,6 @@ static int lpc32xx_ep_disable(struct usb_ep *_ep) nuke(ep, -ESHUTDOWN); - /* restore the endpoint's pristine config */ - ep->desc = NULL; - /* Clear all DMA statuses for this EP */ udc_ep_dma_disable(udc, ep->hwep_num); writel(1 << ep->hwep_num, USBD_EOTINTCLR(udc->udp_baseaddr)); @@ -1696,7 +1688,7 @@ static int lpc32xx_ep_enable(struct usb_ep *_ep, unsigned long flags; /* Verify EP data */ - if ((!_ep) || (!ep) || (!desc) || (ep->desc) || + if ((!_ep) || (!ep) || (!desc) || (desc->bDescriptorType != USB_DT_ENDPOINT)) { dev_dbg(udc->dev, "bad ep or descriptor\n"); return -EINVAL; @@ -1754,7 +1746,6 @@ static int lpc32xx_ep_enable(struct usb_ep *_ep, /* Initialize endpoint to match the selected descriptor */ ep->is_in = (desc->bEndpointAddress & USB_DIR_IN) != 0; - ep->desc = desc; ep->ep.maxpacket = maxpacket; /* Map hardware endpoint from base and direction */ @@ -1837,7 +1828,7 @@ static int lpc32xx_ep_queue(struct usb_ep *_ep, udc = ep->udc; - if (!_ep || (!ep->desc && ep->hwep_num_base != 0)) { + if (!_ep) { dev_dbg(udc->dev, "invalid ep\n"); return -EINVAL; } @@ -1976,7 +1967,7 @@ static int lpc32xx_ep_set_halt(struct usb_ep *_ep, int value) struct lpc32xx_udc *udc = ep->udc; unsigned long flags; - if ((!ep) || (ep->desc == NULL) || (ep->hwep_num <= 1)) + if ((!ep) || (ep->hwep_num <= 1)) return -EINVAL; /* Don't halt an IN EP */ @@ -2262,7 +2253,7 @@ static int udc_get_status(struct lpc32xx_udc *udc, u16 reqtype, u16 wIndex) case USB_RECIP_ENDPOINT: tmp = wIndex & USB_ENDPOINT_NUMBER_MASK; ep = &udc->ep[tmp]; - if ((tmp == 0) || (tmp >= NUM_ENDPOINTS) || (tmp && !ep->desc)) + if ((tmp == 0) || (tmp >= NUM_ENDPOINTS)) return -EOPNOTSUPP; if (wIndex & USB_DIR_IN) { -- cgit v0.10.2 From c4846a1807fc6138e2f010d65757feb4b7b0c2cf Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Mon, 20 Aug 2012 10:30:14 +0200 Subject: usb: gadget: lpc32xx_udc: Support multiple controllers The lpc32xx_udc driver supported only one controller by defining a global static struct for it. This patch enables multiple instances of the controller by dynamic allocation of the struct at probe(). A static struct is kept as a template on initialization since it does some complex preset, reflecting fixed hardware endpoint structure. Signed-off-by: Roland Stigge Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c index 6dd8f69..a0195f2 100644 --- a/drivers/usb/gadget/lpc32xx_udc.c +++ b/drivers/usb/gadget/lpc32xx_udc.c @@ -2608,10 +2608,9 @@ static void nop_release(struct device *dev) /* nothing to free */ } -static struct lpc32xx_udc controller = { +static const struct lpc32xx_udc controller_template = { .gadget = { .ops = &lpc32xx_udc_ops, - .ep0 = &controller.ep[0].ep, .name = driver_name, .dev = { .init_name = "gadget", @@ -2623,7 +2622,6 @@ static struct lpc32xx_udc controller = { .name = "ep0", .ops = &lpc32xx_ep_ops, }, - .udc = &controller, .maxpacket = 64, .hwep_num_base = 0, .hwep_num = 0, /* Can be 0 or 1, has special handling */ @@ -2635,7 +2633,6 @@ static struct lpc32xx_udc controller = { .name = "ep1-int", .ops = &lpc32xx_ep_ops, }, - .udc = &controller, .maxpacket = 64, .hwep_num_base = 2, .hwep_num = 0, /* 2 or 3, will be set later */ @@ -2647,7 +2644,6 @@ static struct lpc32xx_udc controller = { .name = "ep2-bulk", .ops = &lpc32xx_ep_ops, }, - .udc = &controller, .maxpacket = 64, .hwep_num_base = 4, .hwep_num = 0, /* 4 or 5, will be set later */ @@ -2659,7 +2655,6 @@ static struct lpc32xx_udc controller = { .name = "ep3-iso", .ops = &lpc32xx_ep_ops, }, - .udc = &controller, .maxpacket = 1023, .hwep_num_base = 6, .hwep_num = 0, /* 6 or 7, will be set later */ @@ -2671,7 +2666,6 @@ static struct lpc32xx_udc controller = { .name = "ep4-int", .ops = &lpc32xx_ep_ops, }, - .udc = &controller, .maxpacket = 64, .hwep_num_base = 8, .hwep_num = 0, /* 8 or 9, will be set later */ @@ -2683,7 +2677,6 @@ static struct lpc32xx_udc controller = { .name = "ep5-bulk", .ops = &lpc32xx_ep_ops, }, - .udc = &controller, .maxpacket = 64, .hwep_num_base = 10, .hwep_num = 0, /* 10 or 11, will be set later */ @@ -2695,7 +2688,6 @@ static struct lpc32xx_udc controller = { .name = "ep6-iso", .ops = &lpc32xx_ep_ops, }, - .udc = &controller, .maxpacket = 1023, .hwep_num_base = 12, .hwep_num = 0, /* 12 or 13, will be set later */ @@ -2707,7 +2699,6 @@ static struct lpc32xx_udc controller = { .name = "ep7-int", .ops = &lpc32xx_ep_ops, }, - .udc = &controller, .maxpacket = 64, .hwep_num_base = 14, .hwep_num = 0, @@ -2719,7 +2710,6 @@ static struct lpc32xx_udc controller = { .name = "ep8-bulk", .ops = &lpc32xx_ep_ops, }, - .udc = &controller, .maxpacket = 64, .hwep_num_base = 16, .hwep_num = 0, @@ -2731,7 +2721,6 @@ static struct lpc32xx_udc controller = { .name = "ep9-iso", .ops = &lpc32xx_ep_ops, }, - .udc = &controller, .maxpacket = 1023, .hwep_num_base = 18, .hwep_num = 0, @@ -2743,7 +2732,6 @@ static struct lpc32xx_udc controller = { .name = "ep10-int", .ops = &lpc32xx_ep_ops, }, - .udc = &controller, .maxpacket = 64, .hwep_num_base = 20, .hwep_num = 0, @@ -2755,7 +2743,6 @@ static struct lpc32xx_udc controller = { .name = "ep11-bulk", .ops = &lpc32xx_ep_ops, }, - .udc = &controller, .maxpacket = 64, .hwep_num_base = 22, .hwep_num = 0, @@ -2767,7 +2754,6 @@ static struct lpc32xx_udc controller = { .name = "ep12-iso", .ops = &lpc32xx_ep_ops, }, - .udc = &controller, .maxpacket = 1023, .hwep_num_base = 24, .hwep_num = 0, @@ -2779,7 +2765,6 @@ static struct lpc32xx_udc controller = { .name = "ep13-int", .ops = &lpc32xx_ep_ops, }, - .udc = &controller, .maxpacket = 64, .hwep_num_base = 26, .hwep_num = 0, @@ -2791,7 +2776,6 @@ static struct lpc32xx_udc controller = { .name = "ep14-bulk", .ops = &lpc32xx_ep_ops, }, - .udc = &controller, .maxpacket = 64, .hwep_num_base = 28, .hwep_num = 0, @@ -2803,7 +2787,6 @@ static struct lpc32xx_udc controller = { .name = "ep15-bulk", .ops = &lpc32xx_ep_ops, }, - .udc = &controller, .maxpacket = 1023, .hwep_num_base = 30, .hwep_num = 0, @@ -3090,12 +3073,21 @@ static u64 lpc32xx_usbd_dmamask = ~(u32) 0x7F; static int __init lpc32xx_udc_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; - struct lpc32xx_udc *udc = &controller; + struct lpc32xx_udc *udc; int retval, i; struct resource *res; dma_addr_t dma_handle; struct device_node *isp1301_node; + udc = kzalloc(sizeof(*udc), GFP_KERNEL); + if (!udc) + return -ENOMEM; + + memcpy(udc, &controller_template, sizeof(*udc)); + for (i = 0; i <= 15; i++) + udc->ep[i].udc = udc; + udc->gadget.ep0 = &udc->ep[0].ep; + /* init software state */ udc->gadget.dev.parent = dev; udc->pdev = pdev; @@ -3110,8 +3102,10 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev) } udc->isp1301_i2c_client = isp1301_get_client(isp1301_node); - if (!udc->isp1301_i2c_client) - return -EPROBE_DEFER; + if (!udc->isp1301_i2c_client) { + retval = -EPROBE_DEFER; + goto phy_fail; + } dev_info(udc->dev, "ISP1301 I2C device at address 0x%x\n", udc->isp1301_i2c_client->addr); @@ -3130,8 +3124,10 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev) * IORESOURCE_IRQ, USB transceiver interrupt number */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENXIO; + if (!res) { + retval = -ENXIO; + goto resource_fail; + } spin_lock_init(&udc->lock); @@ -3141,7 +3137,8 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev) if (udc->udp_irq[i] < 0) { dev_err(udc->dev, "irq resource %d not available!\n", i); - return udc->udp_irq[i]; + retval = udc->udp_irq[i]; + goto irq_fail; } } @@ -3149,7 +3146,8 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev) udc->io_p_size = resource_size(res); if (!request_mem_region(udc->io_p_start, udc->io_p_size, driver_name)) { dev_err(udc->dev, "someone's using UDC memory\n"); - return -EBUSY; + retval = -EBUSY; + goto request_mem_region_fail; } udc->udp_baseaddr = ioremap(udc->io_p_start, udc->io_p_size); @@ -3346,7 +3344,11 @@ pll_get_fail: io_map_fail: release_mem_region(udc->io_p_start, udc->io_p_size); dev_err(udc->dev, "%s probe failed, %d\n", driver_name, retval); - +request_mem_region_fail: +irq_fail: +resource_fail: +phy_fail: + kfree(udc); return retval; } @@ -3384,6 +3386,7 @@ static int __devexit lpc32xx_udc_remove(struct platform_device *pdev) clk_put(udc->usb_pll_clk); iounmap(udc->udp_baseaddr); release_mem_region(udc->io_p_start, udc->io_p_size); + kfree(udc); return 0; } -- cgit v0.10.2 From d0d860758bd350206242962a223858bd01cd8a93 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 20 Aug 2012 16:12:47 -0400 Subject: usb: gadget: dummy-hcd: remember to update driver pointer This patch (as1599) fixes dummy-hcd to make it update the appropriate driver pointer when a new gadget driver is bound or unbound. Without this change, the gadget driver's name doesn't appear in dev_printk output. Signed-off-by: Alan Stern Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index b799106..91916f6 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -909,6 +909,7 @@ static int dummy_udc_start(struct usb_gadget *g, dum->devstatus = 0; dum->driver = driver; + dum->gadget.dev.driver = &driver->driver; dev_dbg(udc_dev(dum), "binding gadget driver '%s'\n", driver->driver.name); return 0; @@ -923,6 +924,7 @@ static int dummy_udc_stop(struct usb_gadget *g, dev_dbg(udc_dev(dum), "unregister gadget driver '%s'\n", driver->driver.name); + dum->gadget.dev.driver = NULL; dum->driver = NULL; return 0; -- cgit v0.10.2 From 2e8e25b882f8077c5fb38c111c0cb0fb079fb62d Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 22 Aug 2012 15:48:58 +0530 Subject: usb: gadget: s3c2410_udc: Replace with Fixes the following warning: WARNING: Use #include instead of Signed-off-by: Sachin Kamat Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index f2e51f5..7acecc0 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -35,7 +36,6 @@ #include #include -#include #include #include #include -- cgit v0.10.2 From c2892cd4d9251d62419b731816633b9041fa7e3c Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 22 Aug 2012 15:48:59 +0530 Subject: usb: gadget: s3c2410_udc: Use pr_* and dev_err functions Replace printk with corresponding pr_* and dev_err functions. Signed-off-by: Sachin Kamat Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index 7acecc0..55a571e 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -12,6 +12,8 @@ * (at your option) any later version. */ +#define pr_fmt(fmt) "s3c2410_udc: " fmt + #include #include #include @@ -115,7 +117,7 @@ static int dprintk(int level, const char *fmt, ...) sizeof(printk_buf)-len, fmt, args); va_end(args); - return printk(KERN_DEBUG "%s", printk_buf); + return pr_debug("%s", printk_buf); } #else static int dprintk(int level, const char *fmt, ...) @@ -1683,13 +1685,13 @@ static int s3c2410_udc_start(struct usb_gadget_driver *driver, return -EBUSY; if (!bind || !driver->setup || driver->max_speed < USB_SPEED_FULL) { - printk(KERN_ERR "Invalid driver: bind %p setup %p speed %d\n", + dev_err(&udc->gadget.dev, "Invalid driver: bind %p setup %p speed %d\n", bind, driver->setup, driver->max_speed); return -EINVAL; } #if defined(MODULE) if (!driver->unbind) { - printk(KERN_ERR "Invalid driver: no unbind method\n"); + dev_err(&udc->gadget.dev, "Invalid driver: no unbind method\n"); return -EINVAL; } #endif @@ -1700,7 +1702,7 @@ static int s3c2410_udc_start(struct usb_gadget_driver *driver, /* Bind the driver */ if ((retval = device_add(&udc->gadget.dev)) != 0) { - printk(KERN_ERR "Error in device_add() : %d\n",retval); + dev_err(&udc->gadget.dev, "Error in device_add() : %d\n", retval); goto register_error; } @@ -2073,7 +2075,7 @@ static int __init udc_init(void) s3c2410_udc_debugfs_root = debugfs_create_dir(gadget_name, NULL); if (IS_ERR(s3c2410_udc_debugfs_root)) { - printk(KERN_ERR "%s: debugfs dir creation failed %ld\n", + pr_err("%s: debugfs dir creation failed %ld\n", gadget_name, PTR_ERR(s3c2410_udc_debugfs_root)); s3c2410_udc_debugfs_root = NULL; } -- cgit v0.10.2 From ff24166c3996a343f3901a47bd5fef6181ac21f9 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 22 Aug 2012 15:49:00 +0530 Subject: usb: gadget: s3c2410_udc: Silence checkpatch errors and warnings Silences about 75 errors and warnings related to - Spacing - Alignment of braces - Line over 80 characters Signed-off-by: Sachin Kamat Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index 55a571e..d9e3a21 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -127,10 +127,10 @@ static int dprintk(int level, const char *fmt, ...) #endif static int s3c2410_udc_debugfs_seq_show(struct seq_file *m, void *p) { - u32 addr_reg,pwr_reg,ep_int_reg,usb_int_reg; + u32 addr_reg, pwr_reg, ep_int_reg, usb_int_reg; u32 ep_int_en_reg, usb_int_en_reg, ep0_csr; - u32 ep1_i_csr1,ep1_i_csr2,ep1_o_csr1,ep1_o_csr2; - u32 ep2_i_csr1,ep2_i_csr2,ep2_o_csr1,ep2_o_csr2; + u32 ep1_i_csr1, ep1_i_csr2, ep1_o_csr1, ep1_o_csr2; + u32 ep2_i_csr1, ep2_i_csr2, ep2_o_csr1, ep2_o_csr2; addr_reg = udc_read(S3C2410_UDC_FUNC_ADDR_REG); pwr_reg = udc_read(S3C2410_UDC_PWR_REG); @@ -166,10 +166,10 @@ static int s3c2410_udc_debugfs_seq_show(struct seq_file *m, void *p) "EP2_I_CSR2 : 0x%04X\n" "EP2_O_CSR1 : 0x%04X\n" "EP2_O_CSR2 : 0x%04X\n", - addr_reg,pwr_reg,ep_int_reg,usb_int_reg, + addr_reg, pwr_reg, ep_int_reg, usb_int_reg, ep_int_en_reg, usb_int_en_reg, ep0_csr, - ep1_i_csr1,ep1_i_csr2,ep1_o_csr1,ep1_o_csr2, - ep2_i_csr1,ep2_i_csr2,ep2_o_csr1,ep2_o_csr2 + ep1_i_csr1, ep1_i_csr2, ep1_o_csr1, ep1_o_csr2, + ep2_i_csr1, ep2_i_csr2, ep2_o_csr1, ep2_o_csr2 ); return 0; @@ -232,7 +232,7 @@ static inline void s3c2410_udc_set_ep0_de_out(void __iomem *base) { udc_writeb(base, S3C2410_UDC_INDEX_EP0, S3C2410_UDC_INDEX_REG); - udc_writeb(base,(S3C2410_UDC_EP0_CSR_SOPKTRDY + udc_writeb(base, (S3C2410_UDC_EP0_CSR_SOPKTRDY | S3C2410_UDC_EP0_CSR_DE), S3C2410_UDC_EP0_CSR_REG); } @@ -265,7 +265,7 @@ static void s3c2410_udc_done(struct s3c2410_ep *ep, list_del_init(&req->queue); - if (likely (req->req.status == -EINPROGRESS)) + if (likely(req->req.status == -EINPROGRESS)) req->req.status = status; else status = req->req.status; @@ -282,9 +282,9 @@ static void s3c2410_udc_nuke(struct s3c2410_udc *udc, if (&ep->queue == NULL) return; - while (!list_empty (&ep->queue)) { + while (!list_empty(&ep->queue)) { struct s3c2410_request *req; - req = list_entry (ep->queue.next, struct s3c2410_request, + req = list_entry(ep->queue.next, struct s3c2410_request, queue); s3c2410_udc_done(ep, req, status); } @@ -391,10 +391,10 @@ static int s3c2410_udc_write_fifo(struct s3c2410_ep *ep, if (idx == 0) { /* Reset signal => no need to say 'data sent' */ - if (! (udc_read(S3C2410_UDC_USB_INT_REG) + if (!(udc_read(S3C2410_UDC_USB_INT_REG) & S3C2410_UDC_USBINT_RESET)) s3c2410_udc_set_ep0_de_in(base_addr); - ep->dev->ep0state=EP0_IDLE; + ep->dev->ep0state = EP0_IDLE; } else { udc_write(idx, S3C2410_UDC_INDEX_REG); ep_csr = udc_read(S3C2410_UDC_IN_CSR1_REG); @@ -408,7 +408,7 @@ static int s3c2410_udc_write_fifo(struct s3c2410_ep *ep, } else { if (idx == 0) { /* Reset signal => no need to say 'data sent' */ - if (! (udc_read(S3C2410_UDC_USB_INT_REG) + if (!(udc_read(S3C2410_UDC_USB_INT_REG) & S3C2410_UDC_USBINT_RESET)) s3c2410_udc_set_ep0_ipr(base_addr); } else { @@ -444,7 +444,7 @@ static int s3c2410_udc_read_fifo(struct s3c2410_ep *ep, u8 *buf; u32 ep_csr; unsigned bufferspace; - int is_last=1; + int is_last = 1; unsigned avail; int fifo_count = 0; u32 idx; @@ -512,7 +512,7 @@ static int s3c2410_udc_read_fifo(struct s3c2410_ep *ep, /* Only ep0 debug messages are interesting */ if (idx == 0) dprintk(DEBUG_VERBOSE, "%s fifo count : %d [last %d]\n", - __func__, fifo_count,is_last); + __func__, fifo_count, is_last); if (is_last) { if (idx == 0) { @@ -544,7 +544,7 @@ static int s3c2410_udc_read_fifo(struct s3c2410_ep *ep, static int s3c2410_udc_read_fifo_crq(struct usb_ctrlrequest *crq) { - unsigned char *outbuf = (unsigned char*)crq; + unsigned char *outbuf = (unsigned char *)crq; int bytes_read = 0; udc_write(0, S3C2410_UDC_INDEX_REG); @@ -650,7 +650,7 @@ static void s3c2410_udc_handle_ep0_idle(struct s3c2410_udc *dev, switch (crq->bRequest) { case USB_REQ_SET_CONFIGURATION: - dprintk(DEBUG_NORMAL, "USB_REQ_SET_CONFIGURATION ... \n"); + dprintk(DEBUG_NORMAL, "USB_REQ_SET_CONFIGURATION ...\n"); if (crq->bRequestType == USB_RECIP_DEVICE) { dev->req_config = 1; @@ -659,7 +659,7 @@ static void s3c2410_udc_handle_ep0_idle(struct s3c2410_udc *dev, break; case USB_REQ_SET_INTERFACE: - dprintk(DEBUG_NORMAL, "USB_REQ_SET_INTERFACE ... \n"); + dprintk(DEBUG_NORMAL, "USB_REQ_SET_INTERFACE ...\n"); if (crq->bRequestType == USB_RECIP_INTERFACE) { dev->req_config = 1; @@ -668,7 +668,7 @@ static void s3c2410_udc_handle_ep0_idle(struct s3c2410_udc *dev, break; case USB_REQ_SET_ADDRESS: - dprintk(DEBUG_NORMAL, "USB_REQ_SET_ADDRESS ... \n"); + dprintk(DEBUG_NORMAL, "USB_REQ_SET_ADDRESS ...\n"); if (crq->bRequestType == USB_RECIP_DEVICE) { tmp = crq->wValue & 0x7F; @@ -681,13 +681,12 @@ static void s3c2410_udc_handle_ep0_idle(struct s3c2410_udc *dev, break; case USB_REQ_GET_STATUS: - dprintk(DEBUG_NORMAL, "USB_REQ_GET_STATUS ... \n"); + dprintk(DEBUG_NORMAL, "USB_REQ_GET_STATUS ...\n"); s3c2410_udc_clear_ep0_opr(base_addr); if (dev->req_std) { - if (!s3c2410_udc_get_status(dev, crq)) { + if (!s3c2410_udc_get_status(dev, crq)) return; - } } break; @@ -752,7 +751,7 @@ static void s3c2410_udc_handle_ep0_idle(struct s3c2410_udc *dev, /* deferred i/o == no response yet */ } else if (dev->req_pending) { dprintk(DEBUG_VERBOSE, "dev->req_pending... what now?\n"); - dev->req_pending=0; + dev->req_pending = 0; } dprintk(DEBUG_VERBOSE, "ep0state %s\n", ep0states[dev->ep0state]); @@ -803,16 +802,14 @@ static void s3c2410_udc_handle_ep0(struct s3c2410_udc *dev) case EP0_IN_DATA_PHASE: /* GET_DESCRIPTOR etc */ dprintk(DEBUG_NORMAL, "EP0_IN_DATA_PHASE ... what now?\n"); - if (!(ep0csr & S3C2410_UDC_EP0_CSR_IPKRDY) && req) { + if (!(ep0csr & S3C2410_UDC_EP0_CSR_IPKRDY) && req) s3c2410_udc_write_fifo(ep, req); - } break; case EP0_OUT_DATA_PHASE: /* SET_DESCRIPTOR etc */ dprintk(DEBUG_NORMAL, "EP0_OUT_DATA_PHASE ... what now?\n"); - if ((ep0csr & S3C2410_UDC_EP0_CSR_OPKRDY) && req ) { - s3c2410_udc_read_fifo(ep,req); - } + if ((ep0csr & S3C2410_UDC_EP0_CSR_OPKRDY) && req) + s3c2410_udc_read_fifo(ep, req); break; case EP0_END_XFER: @@ -838,7 +835,7 @@ static void s3c2410_udc_handle_ep(struct s3c2410_ep *ep) u32 ep_csr1; u32 idx; - if (likely (!list_empty(&ep->queue))) + if (likely(!list_empty(&ep->queue))) req = list_entry(ep->queue.next, struct s3c2410_request, queue); else @@ -860,9 +857,8 @@ static void s3c2410_udc_handle_ep(struct s3c2410_ep *ep) return; } - if (!(ep_csr1 & S3C2410_UDC_ICSR1_PKTRDY) && req) { - s3c2410_udc_write_fifo(ep,req); - } + if (!(ep_csr1 & S3C2410_UDC_ICSR1_PKTRDY) && req) + s3c2410_udc_write_fifo(ep, req); } else { udc_write(idx, S3C2410_UDC_INDEX_REG); ep_csr1 = udc_read(S3C2410_UDC_OUT_CSR1_REG); @@ -875,9 +871,8 @@ static void s3c2410_udc_handle_ep(struct s3c2410_ep *ep) return; } - if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && req) { - s3c2410_udc_read_fifo(ep,req); - } + if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && req) + s3c2410_udc_read_fifo(ep, req); } } @@ -1059,7 +1054,7 @@ static int s3c2410_udc_ep_enable(struct usb_ep *_ep, struct s3c2410_ep *ep; u32 max, tmp; unsigned long flags; - u32 csr1,csr2; + u32 csr1, csr2; u32 int_en_reg; ep = to_s3c2410_ep(_ep); @@ -1075,7 +1070,7 @@ static int s3c2410_udc_ep_enable(struct usb_ep *_ep, max = usb_endpoint_maxp(desc) & 0x1fff; - local_irq_save (flags); + local_irq_save(flags); _ep->maxpacket = max & 0x7ff; ep->ep.desc = desc; ep->halted = 0; @@ -1119,11 +1114,11 @@ static int s3c2410_udc_ep_enable(struct usb_ep *_ep, /* print some debug message */ tmp = desc->bEndpointAddress; - dprintk (DEBUG_NORMAL, "enable %s(%d) ep%x%s-blk max %02x\n", - _ep->name,ep->num, tmp, + dprintk(DEBUG_NORMAL, "enable %s(%d) ep%x%s-blk max %02x\n", + _ep->name, ep->num, tmp, desc->bEndpointAddress & USB_DIR_IN ? "in" : "out", max); - local_irq_restore (flags); + local_irq_restore(flags); s3c2410_udc_set_halt(_ep, 0); return 0; @@ -1151,7 +1146,7 @@ static int s3c2410_udc_ep_disable(struct usb_ep *_ep) ep->ep.desc = NULL; ep->halted = 1; - s3c2410_udc_nuke (ep->dev, ep, -ESHUTDOWN); + s3c2410_udc_nuke(ep->dev, ep, -ESHUTDOWN); /* disable irqs */ int_en_reg = udc_read(S3C2410_UDC_EP_INT_EN_REG); @@ -1172,16 +1167,16 @@ s3c2410_udc_alloc_request(struct usb_ep *_ep, gfp_t mem_flags) { struct s3c2410_request *req; - dprintk(DEBUG_VERBOSE,"%s(%p,%d)\n", __func__, _ep, mem_flags); + dprintk(DEBUG_VERBOSE, "%s(%p,%d)\n", __func__, _ep, mem_flags); if (!_ep) return NULL; - req = kzalloc (sizeof(struct s3c2410_request), mem_flags); + req = kzalloc(sizeof(struct s3c2410_request), mem_flags); if (!req) return NULL; - INIT_LIST_HEAD (&req->queue); + INIT_LIST_HEAD(&req->queue); return &req->req; } @@ -1199,7 +1194,7 @@ s3c2410_udc_free_request(struct usb_ep *_ep, struct usb_request *_req) if (!ep || !_req || (!ep->ep.desc && _ep->name != ep0name)) return; - WARN_ON (!list_empty (&req->queue)); + WARN_ON(!list_empty(&req->queue)); kfree(req); } @@ -1222,12 +1217,12 @@ static int s3c2410_udc_queue(struct usb_ep *_ep, struct usb_request *_req, } dev = ep->dev; - if (unlikely (!dev->driver + if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) { return -ESHUTDOWN; } - local_irq_save (flags); + local_irq_save(flags); if (unlikely(!_req || !_req->complete || !_req->buf || !list_empty(&req->queue))) { @@ -1235,7 +1230,7 @@ static int s3c2410_udc_queue(struct usb_ep *_ep, struct usb_request *_req, dprintk(DEBUG_NORMAL, "%s: 1 X X X\n", __func__); else { dprintk(DEBUG_NORMAL, "%s: 0 %01d %01d %01d\n", - __func__, !_req->complete,!_req->buf, + __func__, !_req->complete, !_req->buf, !list_empty(&req->queue)); } @@ -1301,7 +1296,7 @@ static int s3c2410_udc_queue(struct usb_ep *_ep, struct usb_request *_req, } /* pio or dma irq handler advances the queue. */ - if (likely (req != 0)) + if (likely(req != 0)) list_add_tail(&req->queue, &ep->queue); local_irq_restore(flags); @@ -1331,11 +1326,11 @@ static int s3c2410_udc_dequeue(struct usb_ep *_ep, struct usb_request *_req) udc = to_s3c2410_udc(ep->gadget); - local_irq_save (flags); + local_irq_save(flags); - list_for_each_entry (req, &ep->queue, queue) { + list_for_each_entry(req, &ep->queue, queue) { if (&req->req == _req) { - list_del_init (&req->queue); + list_del_init(&req->queue); _req->status = -ECONNRESET; retval = 0; break; @@ -1350,7 +1345,7 @@ static int s3c2410_udc_dequeue(struct usb_ep *_ep, struct usb_request *_req) s3c2410_udc_done(ep, req, -ECONNRESET); } - local_irq_restore (flags); + local_irq_restore(flags); return retval; } @@ -1369,7 +1364,7 @@ static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value) return -EINVAL; } - local_irq_save (flags); + local_irq_save(flags); idx = ep->bEndpointAddress & 0x7F; @@ -1378,7 +1373,7 @@ static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value) s3c2410_udc_set_ep0_de_out(base_addr); } else { udc_write(idx, S3C2410_UDC_INDEX_REG); - ep_csr = udc_read((ep->bEndpointAddress &USB_DIR_IN) + ep_csr = udc_read((ep->bEndpointAddress & USB_DIR_IN) ? S3C2410_UDC_IN_CSR1_REG : S3C2410_UDC_OUT_CSR1_REG); @@ -1406,7 +1401,7 @@ static int s3c2410_udc_set_halt(struct usb_ep *_ep, int value) } ep->halted = value ? 1 : 0; - local_irq_restore (flags); + local_irq_restore(flags); return 0; } @@ -1486,9 +1481,9 @@ static int s3c2410_udc_set_pullup(struct s3c2410_udc *udc, int is_on) } s3c2410_udc_disable(udc); } - } - else + } else { return -EOPNOTSUPP; + } return 0; } @@ -1619,20 +1614,20 @@ static void s3c2410_udc_reinit(struct s3c2410_udc *dev) u32 i; /* device/ep0 records init */ - INIT_LIST_HEAD (&dev->gadget.ep_list); - INIT_LIST_HEAD (&dev->gadget.ep0->ep_list); + INIT_LIST_HEAD(&dev->gadget.ep_list); + INIT_LIST_HEAD(&dev->gadget.ep0->ep_list); dev->ep0state = EP0_IDLE; for (i = 0; i < S3C2410_ENDPOINTS; i++) { struct s3c2410_ep *ep = &dev->ep[i]; if (i != 0) - list_add_tail (&ep->ep.ep_list, &dev->gadget.ep_list); + list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list); ep->dev = dev; ep->ep.desc = NULL; ep->halted = 0; - INIT_LIST_HEAD (&ep->queue); + INIT_LIST_HEAD(&ep->queue); } } @@ -1867,7 +1862,7 @@ static int s3c2410_udc_probe(struct platform_device *pdev) memory.ep[4].fifo_size = S3C2440_EP_FIFO_SIZE; } - spin_lock_init (&udc->lock); + spin_lock_init(&udc->lock); udc_info = pdev->dev.platform_data; rsrc_start = S3C2410_PA_USBDEV; @@ -2030,7 +2025,8 @@ static int s3c2410_udc_remove(struct platform_device *pdev) } #ifdef CONFIG_PM -static int s3c2410_udc_suspend(struct platform_device *pdev, pm_message_t message) +static int +s3c2410_udc_suspend(struct platform_device *pdev, pm_message_t message) { s3c2410_udc_command(S3C2410_UDC_P_DISABLE); -- cgit v0.10.2 From 1660c8944652aac142e622d276c3750f735a568f Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 22 Aug 2012 15:49:01 +0530 Subject: usb: gadget: s3c2410_udc: Move assignment outside if condition Fixes the following checkpatch errors: ERROR: do not use assignment in if condition Signed-off-by: Sachin Kamat Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index d9e3a21..e895ea1 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -1696,7 +1696,8 @@ static int s3c2410_udc_start(struct usb_gadget_driver *driver, udc->gadget.dev.driver = &driver->driver; /* Bind the driver */ - if ((retval = device_add(&udc->gadget.dev)) != 0) { + retval = device_add(&udc->gadget.dev); + if (retval) { dev_err(&udc->gadget.dev, "Error in device_add() : %d\n", retval); goto register_error; } @@ -1704,7 +1705,8 @@ static int s3c2410_udc_start(struct usb_gadget_driver *driver, dprintk(DEBUG_NORMAL, "binding gadget driver '%s'\n", driver->driver.name); - if ((retval = bind(&udc->gadget)) != 0) { + retval = bind(&udc->gadget); + if (retval) { device_del(&udc->gadget.dev); goto register_error; } -- cgit v0.10.2 From 86bab36662d47388102ca437a3cbfd79e0ea75cd Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Wed, 22 Aug 2012 15:49:02 +0530 Subject: usb: gadget: s3c2410_udc: Do not use integer for NULL 'req' being a pointer shouldn't be equated with 0. Fixes the following compilation warning: drivers/usb/gadget/s3c2410_udc.c:1299:13: warning: Using plain integer as NULL pointer Signed-off-by: Sachin Kamat Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index e895ea1..b627c9b 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -1296,7 +1296,7 @@ static int s3c2410_udc_queue(struct usb_ep *_ep, struct usb_request *_req, } /* pio or dma irq handler advances the queue. */ - if (likely(req != 0)) + if (likely(req)) list_add_tail(&req->queue, &ep->queue); local_irq_restore(flags); -- cgit v0.10.2 From 85b8614d722389202af298e1bf8a599c431fef19 Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Fri, 24 Aug 2012 20:46:18 +0200 Subject: usb: gadget: get rid of USB_GADGET_{DUAL,SUPER}SPEED This commit removes USB_GADGET_DUALSPEED and USB_GADGET_SUPERSPEED Kconfig options. Since now kernel allows many UDC drivers to be compiled, those options may turn to no longer be valid. For instance, if someone decides to build UDC that supports super speed and UDC that supports high speed only, the latter will be "assumed" to support super speed since USB_GADGET_SUPERSPEED will be selected by the former. The test of whether CONFIG_USB_GADGET_*SPEED was defined was just an optimisation which removed otherwise dead code (ie. if UDC is not dual speed, there is no need to handle cases that can happen if speed is high). This commit removes those checks. Signed-off-by: Michal Nazarewicz Signed-off-by: Felipe Balbi diff --git a/drivers/usb/chipidea/Kconfig b/drivers/usb/chipidea/Kconfig index 8337fb5..272109f 100644 --- a/drivers/usb/chipidea/Kconfig +++ b/drivers/usb/chipidea/Kconfig @@ -13,7 +13,6 @@ if USB_CHIPIDEA config USB_CHIPIDEA_UDC bool "ChipIdea device controller" depends on USB_GADGET - select USB_GADGET_DUALSPEED help Say Y here to enable device controller functionality of the ChipIdea driver. diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig index d13c60f4..f6a6e07 100644 --- a/drivers/usb/dwc3/Kconfig +++ b/drivers/usb/dwc3/Kconfig @@ -2,8 +2,6 @@ config USB_DWC3 tristate "DesignWare USB3 DRD Core Support" depends on (USB && USB_GADGET) select USB_OTG_UTILS - select USB_GADGET_DUALSPEED - select USB_GADGET_SUPERSPEED select USB_XHCI_PLATFORM if USB_SUPPORT && USB_XHCI_HCD help Say Y or M here if your system has a Dual Role SuperSpeed diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 51ab5fd..2ba0d0e 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -154,7 +154,6 @@ config USB_LPC32XX config USB_ATMEL_USBA tristate "Atmel USBA" - select USB_GADGET_DUALSPEED depends on AVR32 || ARCH_AT91SAM9RL || ARCH_AT91SAM9G45 help USBA is the integrated high-speed USB Device controller on @@ -163,7 +162,6 @@ config USB_ATMEL_USBA config USB_FSL_USB2 tristate "Freescale Highspeed USB DR Peripheral Controller" depends on FSL_SOC || ARCH_MXC - select USB_GADGET_DUALSPEED select USB_FSL_MPH_DR_OF if OF help Some of Freescale PowerPC and i.MX processors have a High Speed @@ -179,7 +177,6 @@ config USB_FSL_USB2 config USB_FUSB300 tristate "Faraday FUSB300 USB Peripheral Controller" depends on !PHYS_ADDR_T_64BIT - select USB_GADGET_DUALSPEED help Faraday usb device controller FUSB300 driver @@ -227,7 +224,6 @@ config USB_PXA25X_SMALL config USB_R8A66597 tristate "Renesas R8A66597 USB Peripheral Controller" - select USB_GADGET_DUALSPEED help R8A66597 is a discrete USB host and peripheral controller chip that supports both full and high speed USB 2.0 data transfers. @@ -240,7 +236,6 @@ config USB_R8A66597 config USB_RENESAS_USBHS_UDC tristate 'Renesas USBHS controller' depends on USB_RENESAS_USBHS - select USB_GADGET_DUALSPEED help Renesas USBHS is a discrete USB host and peripheral controller chip that supports both full and high speed USB 2.0 data transfers. @@ -268,7 +263,6 @@ config USB_PXA27X config USB_S3C_HSOTG tristate "S3C HS/OtG USB Device controller" depends on S3C_DEV_USB_HSOTG - select USB_GADGET_DUALSPEED help The Samsung S3C64XX USB2.0 high-speed gadget controller integrated into the S3C64XX series SoC. @@ -305,7 +299,6 @@ config USB_S3C2410_DEBUG config USB_S3C_HSUDC tristate "S3C2416, S3C2443 and S3C2450 USB Device Controller" depends on ARCH_S3C24XX - select USB_GADGET_DUALSPEED help Samsung's S3C2416, S3C2443 and S3C2450 is an ARM9 based SoC integrated with dual speed USB 2.0 device controller. It has @@ -315,7 +308,6 @@ config USB_S3C_HSUDC config USB_MV_UDC tristate "Marvell USB2.0 Device Controller" - select USB_GADGET_DUALSPEED help Marvell Socs (including PXA and MMP series) include a high speed USB2.0 OTG controller, which can be configured as high speed or @@ -338,14 +330,12 @@ config USB_MV_U3D config USB_GADGET_MUSB_HDRC tristate "Inventra HDRC USB Peripheral (TI, ADI, ...)" depends on USB_MUSB_HDRC - select USB_GADGET_DUALSPEED help This OTG-capable silicon IP is used in dual designs including the TI DaVinci, OMAP 243x, OMAP 343x, TUSB 6010, and ADI Blackfin config USB_M66592 tristate "Renesas M66592 USB Peripheral Controller" - select USB_GADGET_DUALSPEED help M66592 is a discrete USB peripheral controller chip that supports both full and high speed USB 2.0 data transfers. @@ -362,7 +352,6 @@ config USB_M66592 config USB_AMD5536UDC tristate "AMD5536 UDC" depends on PCI - select USB_GADGET_DUALSPEED help The AMD5536 UDC is part of the AMD Geode CS5536, an x86 southbridge. It is a USB Highspeed DMA capable USB device controller. Beside ep0 @@ -389,7 +378,6 @@ config USB_FSL_QE config USB_NET2272 tristate "PLX NET2272" - select USB_GADGET_DUALSPEED help PLX NET2272 is a USB peripheral controller which supports both full and high speed USB 2.0 data transfers. @@ -413,7 +401,6 @@ config USB_NET2272_DMA config USB_NET2280 tristate "NetChip 228x" depends on PCI - select USB_GADGET_DUALSPEED help NetChip 2280 / 2282 is a PCI based USB peripheral controller which supports both full and high speed USB 2.0 data transfers. @@ -443,7 +430,6 @@ config USB_GOKU config USB_EG20T tristate "Intel EG20T PCH/LAPIS Semiconductor IOH(ML7213/ML7831) UDC" depends on PCI - select USB_GADGET_DUALSPEED help This is a USB device driver for EG20T PCH. EG20T PCH is the platform controller hub that is used in Intel's @@ -470,8 +456,6 @@ config USB_EG20T config USB_DUMMY_HCD tristate "Dummy HCD (DEVELOPMENT)" depends on USB=y || (USB=m && USB_GADGET=m) - select USB_GADGET_DUALSPEED - select USB_GADGET_SUPERSPEED help This host controller driver emulates USB, looping all data transfer requests back to a USB "gadget driver" in the same host. The host @@ -496,15 +480,6 @@ config USB_DUMMY_HCD endmenu -# Selected by UDC drivers that support high-speed operation. -config USB_GADGET_DUALSPEED - bool - -# Selected by UDC drivers that support super-speed opperation -config USB_GADGET_SUPERSPEED - bool - depends on USB_GADGET_DUALSPEED - # # USB Gadget Drivers # diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 2cb1030..91411a6 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1586,12 +1586,6 @@ composite_resume(struct usb_gadget *gadget) /*-------------------------------------------------------------------------*/ static struct usb_gadget_driver composite_driver = { -#ifdef CONFIG_USB_GADGET_SUPERSPEED - .max_speed = USB_SPEED_SUPER, -#else - .max_speed = USB_SPEED_HIGH, -#endif - .unbind = composite_unbind, .setup = composite_setup, @@ -1636,8 +1630,7 @@ int usb_composite_probe(struct usb_composite_driver *driver, driver->iProduct = driver->name; composite_driver.function = (char *) driver->name; composite_driver.driver.name = driver->name; - composite_driver.max_speed = - min_t(u8, composite_driver.max_speed, driver->max_speed); + composite_driver.max_speed = driver->max_speed; composite = driver; composite_gadget_bind = bind; diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index e58b164..ae13a10 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -828,7 +828,6 @@ ep_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) if (value == 0) data->state = STATE_EP_ENABLED; break; -#ifdef CONFIG_USB_GADGET_DUALSPEED case USB_SPEED_HIGH: /* fails if caller didn't provide that descriptor... */ ep->desc = &data->hs_desc; @@ -836,7 +835,6 @@ ep_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) if (value == 0) data->state = STATE_EP_ENABLED; break; -#endif default: DBG(data->dev, "unconnected, %s init abandoned\n", data->name); @@ -1324,7 +1322,6 @@ static const struct file_operations ep0_io_operations = { * Unrecognized ep0 requests may be handled in user space. */ -#ifdef CONFIG_USB_GADGET_DUALSPEED static void make_qualifier (struct dev_data *dev) { struct usb_qualifier_descriptor qual; @@ -1347,7 +1344,6 @@ static void make_qualifier (struct dev_data *dev) memcpy (dev->rbuf, &qual, sizeof qual); } -#endif static int config_buf (struct dev_data *dev, u8 type, unsigned index) @@ -1427,7 +1423,6 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) dev->dev->bMaxPacketSize0 = dev->gadget->ep0->maxpacket; req->buf = dev->dev; break; -#ifdef CONFIG_USB_GADGET_DUALSPEED case USB_DT_DEVICE_QUALIFIER: if (!dev->hs_config) break; @@ -1437,7 +1432,6 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) break; case USB_DT_OTHER_SPEED_CONFIG: // FALLTHROUGH -#endif case USB_DT_CONFIG: value = config_buf (dev, w_value >> 8, @@ -1763,11 +1757,6 @@ gadgetfs_suspend (struct usb_gadget *gadget) } static struct usb_gadget_driver gadgetfs_driver = { -#ifdef CONFIG_USB_GADGET_DUALSPEED - .max_speed = USB_SPEED_HIGH, -#else - .max_speed = USB_SPEED_FULL, -#endif .function = (char *) driver_desc, .unbind = gadgetfs_unbind, .setup = gadgetfs_setup, @@ -1900,6 +1889,10 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) /* triggers gadgetfs_bind(); then we can enumerate. */ spin_unlock_irq (&dev->lock); + if (dev->hs_config) + gadgetfs_driver.max_speed = USB_SPEED_HIGH; + else + gadgetfs_driver.max_speed = USB_SPEED_FULL; value = usb_gadget_probe_driver(&gadgetfs_driver, gadgetfs_bind); if (value != 0) { kfree (dev->buf); diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index 90e82e2..1154a99 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -83,17 +83,10 @@ struct eth_dev { #define DEFAULT_QLEN 2 /* double buffering by default */ - -#ifdef CONFIG_USB_GADGET_DUALSPEED - static unsigned qmult = 5; module_param(qmult, uint, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(qmult, "queue length multiplier at high/super speed"); -#else /* full speed (low speed doesn't do bulk) */ -#define qmult 1 -#endif - /* for dual-speed hardware, use deeper queues at high/super speed */ static inline int qlen(struct usb_gadget *gadget) { diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index ef0c3f9..1b9f005 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -12,7 +12,6 @@ config USB_MUSB_HDRC select TWL4030_USB if MACH_OMAP_3430SDP select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA select USB_OTG_UTILS - select USB_GADGET_DUALSPEED help Say Y here if your system has a dual role high speed USB controller based on the Mentor Graphics silicon IP. Then diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 9517466..d05b220 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -558,14 +558,7 @@ static inline struct usb_gadget *dev_to_usb_gadget(struct device *dev) */ static inline int gadget_is_dualspeed(struct usb_gadget *g) { -#ifdef CONFIG_USB_GADGET_DUALSPEED - /* runtime test would check "g->max_speed" ... that might be - * useful to work around hardware bugs, but is mostly pointless - */ - return 1; -#else - return 0; -#endif + return g->max_speed >= USB_SPEED_HIGH; } /** @@ -575,15 +568,7 @@ static inline int gadget_is_dualspeed(struct usb_gadget *g) */ static inline int gadget_is_superspeed(struct usb_gadget *g) { -#ifdef CONFIG_USB_GADGET_SUPERSPEED - /* - * runtime test would check "g->max_speed" ... that might be - * useful to work around hardware bugs, but is mostly pointless - */ - return 1; -#else - return 0; -#endif + return g->max_speed >= USB_SPEED_SUPER; } /** -- cgit v0.10.2 From 44fd6c0266d3ec752be1bf003015544ea45f473f Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 25 Aug 2012 21:57:06 +0200 Subject: usb: gadget: lpc32xx_udc.c: adjust inconsistent IS_ERR and PTR_ERR Change the call to PTR_ERR to access the value just tested by IS_ERR. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression e,e1; @@ ( if (IS_ERR(e)) { ... PTR_ERR(e) ... } | if (IS_ERR(e=e1)) { ... PTR_ERR(e) ... } | *if (IS_ERR(e)) { ... * PTR_ERR(e1) ... } ) // Signed-off-by: Julia Lawall Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c index a0195f2..f696fb9 100644 --- a/drivers/usb/gadget/lpc32xx_udc.c +++ b/drivers/usb/gadget/lpc32xx_udc.c @@ -3176,7 +3176,7 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev) udc->usb_otg_clk = clk_get(&pdev->dev, "ck_usb_otg"); if (IS_ERR(udc->usb_otg_clk)) { dev_err(udc->dev, "failed to acquire USB otg clock\n"); - retval = PTR_ERR(udc->usb_slv_clk); + retval = PTR_ERR(udc->usb_otg_clk); goto usb_otg_clk_get_fail; } -- cgit v0.10.2 From 9d2333d0d9bc03da3d8c11f92c602dac97ffea1e Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 26 Aug 2012 09:43:00 +0800 Subject: usb: gadget: remove duplicated include from pxa25x_udc.c From: Wei Yongjun Remove duplicated include. Signed-off-by: Wei Yongjun Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index 907ad3e..c246c08 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include -- cgit v0.10.2 From 28dd924a7b023d49401f9fcbd9efcdaa161370c6 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Tue, 21 Aug 2012 21:22:45 +0400 Subject: usb: musb: core: fix kernel-doc of musb_init_controller() Some parameter names in this function's kernel-doc don't match the real parameters. While at it, give the 'nIrq' parameter slightly more verbose description. Signed-off-by: Sergei Shtylyov Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index dd24f96..5cacccb 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -1849,9 +1849,9 @@ static void musb_free(struct musb *musb) /* * Perform generic per-controller initialization. * - * @pDevice: the controller (already clocked, etc) - * @nIrq: irq - * @mregs: virtual address of controller registers, + * @dev: the controller (already clocked, etc) + * @nIrq: IRQ number + * @ctrl: virtual address of controller registers, * not yet corrected for platform-specific offsets */ static int __devinit -- cgit v0.10.2 From 78f0c53ef8563009bf089ef90c7204f526d4a589 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 3 Sep 2012 15:48:18 +0530 Subject: usb: gadget: s3c-hsudc: Use devm_* functions devm_* functions are used to replace kzalloc, request_mem_region, ioremap clk_get and request_irq functions in probe call. With the usage of devm_* functions explicit freeing and unmapping is not required. Signed-off-by: Sachin Kamat Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index e26a4e7..fe4a461 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -135,7 +135,6 @@ struct s3c_hsudc_req { * @dev: The device reference used by probe function. * @lock: Lock to synchronize the usage of Endpoints (EP's are indexed). * @regs: Remapped base address of controller's register space. - * @mem_rsrc: Device memory resource used for remapping device register space. * irq: IRQ number used by the controller. * uclk: Reference to the controller clock. * ep0state: Current state of EP0. @@ -150,7 +149,6 @@ struct s3c_hsudc { struct regulator_bulk_data supplies[ARRAY_SIZE(s3c_hsudc_supply_names)]; spinlock_t lock; void __iomem *regs; - struct resource *mem_rsrc; int irq; struct clk *uclk; int ep0state; @@ -1271,7 +1269,7 @@ static int __devinit s3c_hsudc_probe(struct platform_device *pdev) struct s3c24xx_hsudc_platdata *pd = pdev->dev.platform_data; int ret, i; - hsudc = kzalloc(sizeof(struct s3c_hsudc) + + hsudc = devm_kzalloc(&pdev->dev, sizeof(struct s3c_hsudc) + sizeof(struct s3c_hsudc_ep) * pd->epnum, GFP_KERNEL); if (!hsudc) { @@ -1296,25 +1294,12 @@ static int __devinit s3c_hsudc_probe(struct platform_device *pdev) } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(dev, "unable to obtain driver resource data\n"); - ret = -ENODEV; - goto err_res; - } - - hsudc->mem_rsrc = request_mem_region(res->start, resource_size(res), - dev_name(&pdev->dev)); - if (!hsudc->mem_rsrc) { - dev_err(dev, "failed to reserve register area\n"); - ret = -ENODEV; - goto err_res; - } - hsudc->regs = ioremap(res->start, resource_size(res)); + hsudc->regs = devm_request_and_ioremap(&pdev->dev, res); if (!hsudc->regs) { dev_err(dev, "error mapping device register area\n"); ret = -EBUSY; - goto err_remap; + goto err_res; } spin_lock_init(&hsudc->lock); @@ -1337,21 +1322,22 @@ static int __devinit s3c_hsudc_probe(struct platform_device *pdev) ret = platform_get_irq(pdev, 0); if (ret < 0) { dev_err(dev, "unable to obtain IRQ number\n"); - goto err_irq; + goto err_res; } hsudc->irq = ret; - ret = request_irq(hsudc->irq, s3c_hsudc_irq, 0, driver_name, hsudc); + ret = devm_request_irq(&pdev->dev, hsudc->irq, s3c_hsudc_irq, 0, + driver_name, hsudc); if (ret < 0) { dev_err(dev, "irq request failed\n"); - goto err_irq; + goto err_res; } - hsudc->uclk = clk_get(&pdev->dev, "usb-device"); + hsudc->uclk = devm_clk_get(&pdev->dev, "usb-device"); if (IS_ERR(hsudc->uclk)) { dev_err(dev, "failed to find usb-device clock source\n"); ret = PTR_ERR(hsudc->uclk); - goto err_clk; + goto err_res; } clk_enable(hsudc->uclk); @@ -1377,21 +1363,12 @@ err_add_udc: device_unregister(&hsudc->gadget.dev); err_add_device: clk_disable(hsudc->uclk); - clk_put(hsudc->uclk); -err_clk: - free_irq(hsudc->irq, hsudc); -err_irq: - iounmap(hsudc->regs); - -err_remap: - release_mem_region(res->start, resource_size(res)); err_res: if (!IS_ERR_OR_NULL(hsudc->transceiver)) usb_put_phy(hsudc->transceiver); regulator_bulk_free(ARRAY_SIZE(hsudc->supplies), hsudc->supplies); err_supplies: - kfree(hsudc); return ret; } -- cgit v0.10.2 From affaab4c58d8e5f7c30ca2be351277cf72d2336f Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 3 Sep 2012 15:48:19 +0530 Subject: usb: gadget: s3c-hsudc: Add missing braces around sizeof Silences the following checkpatch warning: WARNING: sizeof *hsreq should be sizeof(*hsreq) Signed-off-by: Sachin Kamat Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index fe4a461..35cdc6a 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -833,7 +833,7 @@ static struct usb_request *s3c_hsudc_alloc_request(struct usb_ep *_ep, { struct s3c_hsudc_req *hsreq; - hsreq = kzalloc(sizeof *hsreq, gfp_flags); + hsreq = kzalloc(sizeof(*hsreq), gfp_flags); if (!hsreq) return 0; -- cgit v0.10.2 From dc2cdcaf4caafeb069d01704fdfda24f9c1f443a Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 3 Sep 2012 15:48:20 +0530 Subject: usb: gadget: s3c-hsudc: Replace 0 with NULL for pointers Silences the following type of sparse warnings: warning: Using plain integer as NULL pointer Signed-off-by: Sachin Kamat Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/s3c-hsudc.c b/drivers/usb/gadget/s3c-hsudc.c index 35cdc6a..d8e785d 100644 --- a/drivers/usb/gadget/s3c-hsudc.c +++ b/drivers/usb/gadget/s3c-hsudc.c @@ -835,7 +835,7 @@ static struct usb_request *s3c_hsudc_alloc_request(struct usb_ep *_ep, hsreq = kzalloc(sizeof(*hsreq), gfp_flags); if (!hsreq) - return 0; + return NULL; INIT_LIST_HEAD(&hsreq->queue); return &hsreq->req; @@ -904,16 +904,16 @@ static int s3c_hsudc_queue(struct usb_ep *_ep, struct usb_request *_req, csr = readl((u32)hsudc->regs + offset); if (!(csr & S3C_ESR_TX_SUCCESS) && (s3c_hsudc_write_fifo(hsep, hsreq) == 1)) - hsreq = 0; + hsreq = NULL; } else { csr = readl((u32)hsudc->regs + offset); if ((csr & S3C_ESR_RX_SUCCESS) && (s3c_hsudc_read_fifo(hsep, hsreq) == 1)) - hsreq = 0; + hsreq = NULL; } } - if (hsreq != 0) + if (hsreq) list_add_tail(&hsreq->queue, &hsep->queue); spin_unlock_irqrestore(&hsudc->lock, flags); -- cgit v0.10.2 From 84749c6dcb694a7aa793221ea8cc3d70bd46d466 Mon Sep 17 00:00:00 2001 From: Sachin Kamat Date: Mon, 3 Sep 2012 16:15:18 +0530 Subject: usb: gadget: s3c-hsotg: Use devm_clk_get function devm_* functions are already used in this file. Hence convert clk_get to devm_clk_get for completeness. Signed-off-by: Sachin Kamat Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index a826cb9..5b90a3c 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c @@ -3516,7 +3516,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev) hsotg->dev = dev; hsotg->plat = plat; - hsotg->clk = clk_get(&pdev->dev, "otg"); + hsotg->clk = devm_clk_get(&pdev->dev, "otg"); if (IS_ERR(hsotg->clk)) { dev_err(dev, "cannot get otg clock\n"); return PTR_ERR(hsotg->clk); @@ -3664,7 +3664,6 @@ err_supplies: err_clk: clk_disable_unprepare(hsotg->clk); - clk_put(hsotg->clk); return ret; } @@ -3690,7 +3689,6 @@ static int __devexit s3c_hsotg_remove(struct platform_device *pdev) regulator_bulk_free(ARRAY_SIZE(hsotg->supplies), hsotg->supplies); clk_disable_unprepare(hsotg->clk); - clk_put(hsotg->clk); device_unregister(&hsotg->gadget.dev); return 0; -- cgit v0.10.2 From de4217d90fed1b1714a270ceb5d092f7314e8bda Mon Sep 17 00:00:00 2001 From: Venu Byravarasu Date: Tue, 4 Sep 2012 14:25:58 +0530 Subject: usb: otg: Move phy interface to separate file. As otg.h is containing lots of phy interface related stuff, moving all phy interface related stuff to new file named phy.h Signed-off-by: Venu Byravarasu Signed-off-by: Felipe Balbi diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h index 16dc520d..65a2b6a 100644 --- a/include/linux/usb/otg.h +++ b/include/linux/usb/otg.h @@ -9,7 +9,7 @@ #ifndef __LINUX_USB_OTG_H #define __LINUX_USB_OTG_H -#include +#include /* OTG defines lots of enumeration states before device reset */ enum usb_otg_state { @@ -35,31 +35,6 @@ enum usb_otg_state { OTG_STATE_A_VBUS_ERR, }; -enum usb_phy_events { - USB_EVENT_NONE, /* no events or cable disconnected */ - USB_EVENT_VBUS, /* vbus valid event */ - USB_EVENT_ID, /* id was grounded */ - USB_EVENT_CHARGER, /* usb dedicated charger */ - USB_EVENT_ENUMERATED, /* gadget driver enumerated */ -}; - -/* associate a type with PHY */ -enum usb_phy_type { - USB_PHY_TYPE_UNDEFINED, - USB_PHY_TYPE_USB2, - USB_PHY_TYPE_USB3, -}; - -struct usb_phy; - -/* for transceivers connected thru an ULPI interface, the user must - * provide access ops - */ -struct usb_phy_io_ops { - int (*read)(struct usb_phy *x, u32 reg); - int (*write)(struct usb_phy *x, u32 val, u32 reg); -}; - struct usb_otg { u8 default_a; @@ -85,120 +60,9 @@ struct usb_otg { }; -/* - * the otg driver needs to interact with both device side and host side - * usb controllers. it decides which controller is active at a given - * moment, using the transceiver, ID signal, HNP and sometimes static - * configuration information (including "board isn't wired for otg"). - */ -struct usb_phy { - struct device *dev; - const char *label; - unsigned int flags; - - enum usb_phy_type type; - enum usb_otg_state state; - enum usb_phy_events last_event; - - struct usb_otg *otg; - - struct device *io_dev; - struct usb_phy_io_ops *io_ops; - void __iomem *io_priv; - - /* for notification of usb_phy_events */ - struct atomic_notifier_head notifier; - - /* to pass extra port status to the root hub */ - u16 port_status; - u16 port_change; - - /* to support controllers that have multiple transceivers */ - struct list_head head; - - /* initialize/shutdown the OTG controller */ - int (*init)(struct usb_phy *x); - void (*shutdown)(struct usb_phy *x); - - /* effective for B devices, ignored for A-peripheral */ - int (*set_power)(struct usb_phy *x, - unsigned mA); - - /* for non-OTG B devices: set transceiver into suspend mode */ - int (*set_suspend)(struct usb_phy *x, - int suspend); - - /* notify phy connect status change */ - int (*notify_connect)(struct usb_phy *x, int port); - int (*notify_disconnect)(struct usb_phy *x, int port); -}; - - -/* for board-specific init logic */ -extern int usb_add_phy(struct usb_phy *, enum usb_phy_type type); -extern void usb_remove_phy(struct usb_phy *); - -/* helpers for direct access thru low-level io interface */ -static inline int usb_phy_io_read(struct usb_phy *x, u32 reg) -{ - if (x->io_ops && x->io_ops->read) - return x->io_ops->read(x, reg); - - return -EINVAL; -} - -static inline int usb_phy_io_write(struct usb_phy *x, u32 val, u32 reg) -{ - if (x->io_ops && x->io_ops->write) - return x->io_ops->write(x, val, reg); - - return -EINVAL; -} - -static inline int -usb_phy_init(struct usb_phy *x) -{ - if (x->init) - return x->init(x); - - return 0; -} - -static inline void -usb_phy_shutdown(struct usb_phy *x) -{ - if (x->shutdown) - x->shutdown(x); -} - -/* for usb host and peripheral controller drivers */ #ifdef CONFIG_USB_OTG_UTILS -extern struct usb_phy *usb_get_phy(enum usb_phy_type type); -extern struct usb_phy *devm_usb_get_phy(struct device *dev, - enum usb_phy_type type); -extern void usb_put_phy(struct usb_phy *); -extern void devm_usb_put_phy(struct device *dev, struct usb_phy *x); extern const char *otg_state_string(enum usb_otg_state state); #else -static inline struct usb_phy *usb_get_phy(enum usb_phy_type type) -{ - return NULL; -} - -static inline struct usb_phy *devm_usb_get_phy(struct device *dev, - enum usb_phy_type type) -{ - return NULL; -} - -static inline void usb_put_phy(struct usb_phy *x) -{ -} - -static inline void devm_usb_put_phy(struct device *dev, struct usb_phy *x) -{ -} - static inline const char *otg_state_string(enum usb_otg_state state) { return NULL; @@ -248,42 +112,6 @@ otg_set_peripheral(struct usb_otg *otg, struct usb_gadget *periph) } static inline int -usb_phy_set_power(struct usb_phy *x, unsigned mA) -{ - if (x && x->set_power) - return x->set_power(x, mA); - return 0; -} - -/* Context: can sleep */ -static inline int -usb_phy_set_suspend(struct usb_phy *x, int suspend) -{ - if (x->set_suspend != NULL) - return x->set_suspend(x, suspend); - else - return 0; -} - -static inline int -usb_phy_notify_connect(struct usb_phy *x, int port) -{ - if (x->notify_connect) - return x->notify_connect(x, port); - else - return 0; -} - -static inline int -usb_phy_notify_disconnect(struct usb_phy *x, int port) -{ - if (x->notify_disconnect) - return x->notify_disconnect(x, port); - else - return 0; -} - -static inline int otg_start_srp(struct usb_otg *otg) { if (otg && otg->start_srp) @@ -292,31 +120,7 @@ otg_start_srp(struct usb_otg *otg) return -ENOTSUPP; } -/* notifiers */ -static inline int -usb_register_notifier(struct usb_phy *x, struct notifier_block *nb) -{ - return atomic_notifier_chain_register(&x->notifier, nb); -} - -static inline void -usb_unregister_notifier(struct usb_phy *x, struct notifier_block *nb) -{ - atomic_notifier_chain_unregister(&x->notifier, nb); -} - /* for OTG controller drivers (and maybe other stuff) */ extern int usb_bus_start_enum(struct usb_bus *bus, unsigned port_num); -static inline const char *usb_phy_type_string(enum usb_phy_type type) -{ - switch (type) { - case USB_PHY_TYPE_USB2: - return "USB2 PHY"; - case USB_PHY_TYPE_USB3: - return "USB3 PHY"; - default: - return "UNKNOWN PHY TYPE"; - } -} #endif /* __LINUX_USB_OTG_H */ diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h new file mode 100644 index 0000000..88fc160 --- /dev/null +++ b/include/linux/usb/phy.h @@ -0,0 +1,208 @@ +/* USB OTG (On The Go) defines */ +/* + * + * These APIs may be used between USB controllers. USB device drivers + * (for either host or peripheral roles) don't use these calls; they + * continue to use just usb_device and usb_gadget. + */ + +#ifndef __LINUX_USB_PHY_H +#define __LINUX_USB_PHY_H + +#include + +enum usb_phy_events { + USB_EVENT_NONE, /* no events or cable disconnected */ + USB_EVENT_VBUS, /* vbus valid event */ + USB_EVENT_ID, /* id was grounded */ + USB_EVENT_CHARGER, /* usb dedicated charger */ + USB_EVENT_ENUMERATED, /* gadget driver enumerated */ +}; + +/* associate a type with PHY */ +enum usb_phy_type { + USB_PHY_TYPE_UNDEFINED, + USB_PHY_TYPE_USB2, + USB_PHY_TYPE_USB3, +}; + +struct usb_phy; +struct usb_otg; + +/* for transceivers connected thru an ULPI interface, the user must + * provide access ops + */ +struct usb_phy_io_ops { + int (*read)(struct usb_phy *x, u32 reg); + int (*write)(struct usb_phy *x, u32 val, u32 reg); +}; + +struct usb_phy { + struct device *dev; + const char *label; + unsigned int flags; + + enum usb_phy_type type; + enum usb_phy_events last_event; + + struct usb_otg *otg; + + struct device *io_dev; + struct usb_phy_io_ops *io_ops; + void __iomem *io_priv; + + /* for notification of usb_phy_events */ + struct atomic_notifier_head notifier; + + /* to pass extra port status to the root hub */ + u16 port_status; + u16 port_change; + + /* to support controllers that have multiple transceivers */ + struct list_head head; + + /* initialize/shutdown the OTG controller */ + int (*init)(struct usb_phy *x); + void (*shutdown)(struct usb_phy *x); + + /* effective for B devices, ignored for A-peripheral */ + int (*set_power)(struct usb_phy *x, + unsigned mA); + + /* for non-OTG B devices: set transceiver into suspend mode */ + int (*set_suspend)(struct usb_phy *x, + int suspend); + + /* notify phy connect status change */ + int (*notify_connect)(struct usb_phy *x, int port); + int (*notify_disconnect)(struct usb_phy *x, int port); +}; + + +/* for board-specific init logic */ +extern int usb_add_phy(struct usb_phy *, enum usb_phy_type type); +extern void usb_remove_phy(struct usb_phy *); + +/* helpers for direct access thru low-level io interface */ +static inline int usb_phy_io_read(struct usb_phy *x, u32 reg) +{ + if (x->io_ops && x->io_ops->read) + return x->io_ops->read(x, reg); + + return -EINVAL; +} + +static inline int usb_phy_io_write(struct usb_phy *x, u32 val, u32 reg) +{ + if (x->io_ops && x->io_ops->write) + return x->io_ops->write(x, val, reg); + + return -EINVAL; +} + +static inline int +usb_phy_init(struct usb_phy *x) +{ + if (x->init) + return x->init(x); + + return 0; +} + +static inline void +usb_phy_shutdown(struct usb_phy *x) +{ + if (x->shutdown) + x->shutdown(x); +} + +/* for usb host and peripheral controller drivers */ +#ifdef CONFIG_USB_OTG_UTILS +extern struct usb_phy *usb_get_phy(enum usb_phy_type type); +extern struct usb_phy *devm_usb_get_phy(struct device *dev, + enum usb_phy_type type); +extern void usb_put_phy(struct usb_phy *); +extern void devm_usb_put_phy(struct device *dev, struct usb_phy *x); +#else +static inline struct usb_phy *usb_get_phy(enum usb_phy_type type) +{ + return NULL; +} + +static inline struct usb_phy *devm_usb_get_phy(struct device *dev, + enum usb_phy_type type) +{ + return NULL; +} + +static inline void usb_put_phy(struct usb_phy *x) +{ +} + +static inline void devm_usb_put_phy(struct device *dev, struct usb_phy *x) +{ +} + +#endif + +static inline int +usb_phy_set_power(struct usb_phy *x, unsigned mA) +{ + if (x && x->set_power) + return x->set_power(x, mA); + return 0; +} + +/* Context: can sleep */ +static inline int +usb_phy_set_suspend(struct usb_phy *x, int suspend) +{ + if (x->set_suspend != NULL) + return x->set_suspend(x, suspend); + else + return 0; +} + +static inline int +usb_phy_notify_connect(struct usb_phy *x, int port) +{ + if (x->notify_connect) + return x->notify_connect(x, port); + else + return 0; +} + +static inline int +usb_phy_notify_disconnect(struct usb_phy *x, int port) +{ + if (x->notify_disconnect) + return x->notify_disconnect(x, port); + else + return 0; +} + +/* notifiers */ +static inline int +usb_register_notifier(struct usb_phy *x, struct notifier_block *nb) +{ + return atomic_notifier_chain_register(&x->notifier, nb); +} + +static inline void +usb_unregister_notifier(struct usb_phy *x, struct notifier_block *nb) +{ + atomic_notifier_chain_unregister(&x->notifier, nb); +} + +static inline const char *usb_phy_type_string(enum usb_phy_type type) +{ + switch (type) { + case USB_PHY_TYPE_USB2: + return "USB2 PHY"; + case USB_PHY_TYPE_USB3: + return "USB3 PHY"; + default: + return "UNKNOWN PHY TYPE"; + } +} +#endif /* __LINUX_USB_PHY_H */ -- cgit v0.10.2 From 613065e53cb191d00d9d4fc377398b656ed05a45 Mon Sep 17 00:00:00 2001 From: Kevin Cernekee Date: Sat, 25 Aug 2012 12:38:52 -0700 Subject: usb: gadget: bcm63xx UDC driver Driver for the "USB20D" / "USBD" block on BCM6328, BCM6368, BCM6816, BCM6362, BCM3383, and others. The hardware block was designed to support networking applications (direct connection of a home router to a PC), and the endpoint configuration is fixed. [ balbi@ti.com : dropped USB_GADGET_DUALSPEED from Kconfig ] Signed-off-by: Kevin Cernekee Acked-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 2ba0d0e..75b76d5 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -159,6 +159,17 @@ config USB_ATMEL_USBA USBA is the integrated high-speed USB Device controller on the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel. +config USB_BCM63XX_UDC + tristate "Broadcom BCM63xx Peripheral Controller" + depends on BCM63XX + help + Many Broadcom BCM63xx chipsets (such as the BCM6328) have a + high speed USB Device Port with support for four fixed endpoints + (plus endpoint zero). + + Say "y" to link the driver statically, or "m" to build a + dynamically linked module called "bcm63xx_udc". + config USB_FSL_USB2 tristate "Freescale Highspeed USB DR Peripheral Controller" depends on FSL_SOC || ARCH_MXC diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 3fd8cd0..d84f923 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_USB_OMAP) += omap_udc.o obj-$(CONFIG_USB_S3C2410) += s3c2410_udc.o obj-$(CONFIG_USB_AT91) += at91_udc.o obj-$(CONFIG_USB_ATMEL_USBA) += atmel_usba_udc.o +obj-$(CONFIG_USB_BCM63XX_UDC) += bcm63xx_udc.o obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o fsl_usb2_udc-y := fsl_udc_core.o fsl_usb2_udc-$(CONFIG_ARCH_MXC) += fsl_mxc_udc.o diff --git a/drivers/usb/gadget/bcm63xx_udc.c b/drivers/usb/gadget/bcm63xx_udc.c new file mode 100644 index 0000000..9ca7922 --- /dev/null +++ b/drivers/usb/gadget/bcm63xx_udc.c @@ -0,0 +1,2464 @@ +/* + * bcm63xx_udc.c -- BCM63xx UDC high/full speed USB device controller + * + * Copyright (C) 2012 Kevin Cernekee + * Copyright (C) 2012 Broadcom Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define DRV_MODULE_NAME "bcm63xx_udc" + +static const char bcm63xx_ep0name[] = "ep0"; +static const char *const bcm63xx_ep_name[] = { + bcm63xx_ep0name, + "ep1in-bulk", "ep2out-bulk", "ep3in-int", "ep4out-int", +}; + +static bool use_fullspeed; +module_param(use_fullspeed, bool, S_IRUGO); +MODULE_PARM_DESC(use_fullspeed, "true for fullspeed only"); + +/* + * RX IRQ coalescing options: + * + * false (default) - one IRQ per DATAx packet. Slow but reliable. The + * driver is able to pass the "testusb" suite and recover from conditions like: + * + * 1) Device queues up a 2048-byte RX IUDMA transaction on an OUT bulk ep + * 2) Host sends 512 bytes of data + * 3) Host decides to reconfigure the device and sends SET_INTERFACE + * 4) Device shuts down the endpoint and cancels the RX transaction + * + * true - one IRQ per transfer, for transfers <= 2048B. Generates + * considerably fewer IRQs, but error recovery is less robust. Does not + * reliably pass "testusb". + * + * TX always uses coalescing, because we can cancel partially complete TX + * transfers by repeatedly flushing the FIFO. The hardware doesn't allow + * this on RX. + */ +static bool irq_coalesce; +module_param(irq_coalesce, bool, S_IRUGO); +MODULE_PARM_DESC(irq_coalesce, "take one IRQ per RX transfer"); + +#define BCM63XX_NUM_EP 5 +#define BCM63XX_NUM_IUDMA 6 +#define BCM63XX_NUM_FIFO_PAIRS 3 + +#define IUDMA_RESET_TIMEOUT_US 10000 + +#define IUDMA_EP0_RXCHAN 0 +#define IUDMA_EP0_TXCHAN 1 + +#define IUDMA_MAX_FRAGMENT 2048 +#define BCM63XX_MAX_CTRL_PKT 64 + +#define BCMEP_CTRL 0x00 +#define BCMEP_ISOC 0x01 +#define BCMEP_BULK 0x02 +#define BCMEP_INTR 0x03 + +#define BCMEP_OUT 0x00 +#define BCMEP_IN 0x01 + +#define BCM63XX_SPD_FULL 1 +#define BCM63XX_SPD_HIGH 0 + +#define IUDMA_DMAC_OFFSET 0x200 +#define IUDMA_DMAS_OFFSET 0x400 + +enum bcm63xx_ep0_state { + EP0_REQUEUE, + EP0_IDLE, + EP0_IN_DATA_PHASE_SETUP, + EP0_IN_DATA_PHASE_COMPLETE, + EP0_OUT_DATA_PHASE_SETUP, + EP0_OUT_DATA_PHASE_COMPLETE, + EP0_OUT_STATUS_PHASE, + EP0_IN_FAKE_STATUS_PHASE, + EP0_SHUTDOWN, +}; + +static const char __maybe_unused bcm63xx_ep0_state_names[][32] = { + "REQUEUE", + "IDLE", + "IN_DATA_PHASE_SETUP", + "IN_DATA_PHASE_COMPLETE", + "OUT_DATA_PHASE_SETUP", + "OUT_DATA_PHASE_COMPLETE", + "OUT_STATUS_PHASE", + "IN_FAKE_STATUS_PHASE", + "SHUTDOWN", +}; + +/** + * struct iudma_ch_cfg - Static configuration for an IUDMA channel. + * @ep_num: USB endpoint number. + * @n_bds: Number of buffer descriptors in the ring. + * @ep_type: Endpoint type (control, bulk, interrupt). + * @dir: Direction (in, out). + * @n_fifo_slots: Number of FIFO entries to allocate for this channel. + * @max_pkt_hs: Maximum packet size in high speed mode. + * @max_pkt_fs: Maximum packet size in full speed mode. + */ +struct iudma_ch_cfg { + int ep_num; + int n_bds; + int ep_type; + int dir; + int n_fifo_slots; + int max_pkt_hs; + int max_pkt_fs; +}; + +static const struct iudma_ch_cfg iudma_defaults[] = { + + /* This controller was designed to support a CDC/RNDIS application. + It may be possible to reconfigure some of the endpoints, but + the hardware limitations (FIFO sizing and number of DMA channels) + may significantly impact flexibility and/or stability. Change + these values at your own risk. + + ep_num ep_type n_fifo_slots max_pkt_fs + idx | n_bds | dir | max_pkt_hs | + | | | | | | | | */ + [0] = { -1, 4, BCMEP_CTRL, BCMEP_OUT, 32, 64, 64 }, + [1] = { 0, 4, BCMEP_CTRL, BCMEP_OUT, 32, 64, 64 }, + [2] = { 2, 16, BCMEP_BULK, BCMEP_OUT, 128, 512, 64 }, + [3] = { 1, 16, BCMEP_BULK, BCMEP_IN, 128, 512, 64 }, + [4] = { 4, 4, BCMEP_INTR, BCMEP_OUT, 32, 64, 64 }, + [5] = { 3, 4, BCMEP_INTR, BCMEP_IN, 32, 64, 64 }, +}; + +struct bcm63xx_udc; + +/** + * struct iudma_ch - Represents the current state of a single IUDMA channel. + * @ch_idx: IUDMA channel index (0 to BCM63XX_NUM_IUDMA-1). + * @ep_num: USB endpoint number. -1 for ep0 RX. + * @enabled: Whether bcm63xx_ep_enable() has been called. + * @max_pkt: "Chunk size" on the USB interface. Based on interface speed. + * @is_tx: true for TX, false for RX. + * @bep: Pointer to the associated endpoint. NULL for ep0 RX. + * @udc: Reference to the device controller. + * @read_bd: Next buffer descriptor to reap from the hardware. + * @write_bd: Next BD available for a new packet. + * @end_bd: Points to the final BD in the ring. + * @n_bds_used: Number of BD entries currently occupied. + * @bd_ring: Base pointer to the BD ring. + * @bd_ring_dma: Physical (DMA) address of bd_ring. + * @n_bds: Total number of BDs in the ring. + * + * ep0 has two IUDMA channels (IUDMA_EP0_RXCHAN and IUDMA_EP0_TXCHAN), as it is + * bidirectional. The "struct usb_ep" associated with ep0 is for TX (IN) + * only. + * + * Each bulk/intr endpoint has a single IUDMA channel and a single + * struct usb_ep. + */ +struct iudma_ch { + unsigned int ch_idx; + int ep_num; + bool enabled; + int max_pkt; + bool is_tx; + struct bcm63xx_ep *bep; + struct bcm63xx_udc *udc; + + struct bcm_enet_desc *read_bd; + struct bcm_enet_desc *write_bd; + struct bcm_enet_desc *end_bd; + int n_bds_used; + + struct bcm_enet_desc *bd_ring; + dma_addr_t bd_ring_dma; + unsigned int n_bds; +}; + +/** + * struct bcm63xx_ep - Internal (driver) state of a single endpoint. + * @ep_num: USB endpoint number. + * @iudma: Pointer to IUDMA channel state. + * @ep: USB gadget layer representation of the EP. + * @udc: Reference to the device controller. + * @queue: Linked list of outstanding requests for this EP. + * @halted: 1 if the EP is stalled; 0 otherwise. + */ +struct bcm63xx_ep { + unsigned int ep_num; + struct iudma_ch *iudma; + struct usb_ep ep; + struct bcm63xx_udc *udc; + struct list_head queue; + unsigned halted:1; +}; + +/** + * struct bcm63xx_req - Internal (driver) state of a single request. + * @queue: Links back to the EP's request list. + * @req: USB gadget layer representation of the request. + * @offset: Current byte offset into the data buffer (next byte to queue). + * @bd_bytes: Number of data bytes in outstanding BD entries. + * @iudma: IUDMA channel used for the request. + */ +struct bcm63xx_req { + struct list_head queue; /* ep's requests */ + struct usb_request req; + unsigned int offset; + unsigned int bd_bytes; + struct iudma_ch *iudma; +}; + +/** + * struct bcm63xx_udc - Driver/hardware private context. + * @lock: Spinlock to mediate access to this struct, and (most) HW regs. + * @dev: Generic Linux device structure. + * @pd: Platform data (board/port info). + * @usbd_clk: Clock descriptor for the USB device block. + * @usbh_clk: Clock descriptor for the USB host block. + * @gadget: USB slave device. + * @driver: Driver for USB slave devices. + * @usbd_regs: Base address of the USBD/USB20D block. + * @iudma_regs: Base address of the USBD's associated IUDMA block. + * @bep: Array of endpoints, including ep0. + * @iudma: Array of all IUDMA channels used by this controller. + * @cfg: USB configuration number, from SET_CONFIGURATION wValue. + * @iface: USB interface number, from SET_INTERFACE wIndex. + * @alt_iface: USB alt interface number, from SET_INTERFACE wValue. + * @ep0_ctrl_req: Request object for bcm63xx_udc-initiated ep0 transactions. + * @ep0_ctrl_buf: Data buffer for ep0_ctrl_req. + * @ep0state: Current state of the ep0 state machine. + * @ep0_wq: Workqueue struct used to wake up the ep0 state machine. + * @wedgemap: Bitmap of wedged endpoints. + * @ep0_req_reset: USB reset is pending. + * @ep0_req_set_cfg: Need to spoof a SET_CONFIGURATION packet. + * @ep0_req_set_iface: Need to spoof a SET_INTERFACE packet. + * @ep0_req_shutdown: Driver is shutting down; requesting ep0 to halt activity. + * @ep0_req_completed: ep0 request has completed; worker has not seen it yet. + * @ep0_reply: Pending reply from gadget driver. + * @ep0_request: Outstanding ep0 request. + * @debugfs_root: debugfs directory: /sys/kernel/debug/. + * @debugfs_usbd: debugfs file "usbd" for controller state. + * @debugfs_iudma: debugfs file "usbd" for IUDMA state. + */ +struct bcm63xx_udc { + spinlock_t lock; + + struct device *dev; + struct bcm63xx_usbd_platform_data *pd; + struct clk *usbd_clk; + struct clk *usbh_clk; + + struct usb_gadget gadget; + struct usb_gadget_driver *driver; + + void __iomem *usbd_regs; + void __iomem *iudma_regs; + + struct bcm63xx_ep bep[BCM63XX_NUM_EP]; + struct iudma_ch iudma[BCM63XX_NUM_IUDMA]; + + int cfg; + int iface; + int alt_iface; + + struct bcm63xx_req ep0_ctrl_req; + u8 *ep0_ctrl_buf; + + int ep0state; + struct work_struct ep0_wq; + + unsigned long wedgemap; + + unsigned ep0_req_reset:1; + unsigned ep0_req_set_cfg:1; + unsigned ep0_req_set_iface:1; + unsigned ep0_req_shutdown:1; + + unsigned ep0_req_completed:1; + struct usb_request *ep0_reply; + struct usb_request *ep0_request; + + struct dentry *debugfs_root; + struct dentry *debugfs_usbd; + struct dentry *debugfs_iudma; +}; + +static const struct usb_ep_ops bcm63xx_udc_ep_ops; + +/*********************************************************************** + * Convenience functions + ***********************************************************************/ + +static inline struct bcm63xx_udc *gadget_to_udc(struct usb_gadget *g) +{ + return container_of(g, struct bcm63xx_udc, gadget); +} + +static inline struct bcm63xx_ep *our_ep(struct usb_ep *ep) +{ + return container_of(ep, struct bcm63xx_ep, ep); +} + +static inline struct bcm63xx_req *our_req(struct usb_request *req) +{ + return container_of(req, struct bcm63xx_req, req); +} + +static inline u32 usbd_readl(struct bcm63xx_udc *udc, u32 off) +{ + return bcm_readl(udc->usbd_regs + off); +} + +static inline void usbd_writel(struct bcm63xx_udc *udc, u32 val, u32 off) +{ + bcm_writel(val, udc->usbd_regs + off); +} + +static inline u32 usb_dma_readl(struct bcm63xx_udc *udc, u32 off) +{ + return bcm_readl(udc->iudma_regs + off); +} + +static inline void usb_dma_writel(struct bcm63xx_udc *udc, u32 val, u32 off) +{ + bcm_writel(val, udc->iudma_regs + off); +} + +static inline u32 usb_dmac_readl(struct bcm63xx_udc *udc, u32 off) +{ + return bcm_readl(udc->iudma_regs + IUDMA_DMAC_OFFSET + off); +} + +static inline void usb_dmac_writel(struct bcm63xx_udc *udc, u32 val, u32 off) +{ + bcm_writel(val, udc->iudma_regs + IUDMA_DMAC_OFFSET + off); +} + +static inline u32 usb_dmas_readl(struct bcm63xx_udc *udc, u32 off) +{ + return bcm_readl(udc->iudma_regs + IUDMA_DMAS_OFFSET + off); +} + +static inline void usb_dmas_writel(struct bcm63xx_udc *udc, u32 val, u32 off) +{ + bcm_writel(val, udc->iudma_regs + IUDMA_DMAS_OFFSET + off); +} + +static inline void set_clocks(struct bcm63xx_udc *udc, bool is_enabled) +{ + if (is_enabled) { + clk_enable(udc->usbh_clk); + clk_enable(udc->usbd_clk); + udelay(10); + } else { + clk_disable(udc->usbd_clk); + clk_disable(udc->usbh_clk); + } +} + +/*********************************************************************** + * Low-level IUDMA / FIFO operations + ***********************************************************************/ + +/** + * bcm63xx_ep_dma_select - Helper function to set up the init_sel signal. + * @udc: Reference to the device controller. + * @idx: Desired init_sel value. + * + * The "init_sel" signal is used as a selection index for both endpoints + * and IUDMA channels. Since these do not map 1:1, the use of this signal + * depends on the context. + */ +static void bcm63xx_ep_dma_select(struct bcm63xx_udc *udc, int idx) +{ + u32 val = usbd_readl(udc, USBD_CONTROL_REG); + + val &= ~USBD_CONTROL_INIT_SEL_MASK; + val |= idx << USBD_CONTROL_INIT_SEL_SHIFT; + usbd_writel(udc, val, USBD_CONTROL_REG); +} + +/** + * bcm63xx_set_stall - Enable/disable stall on one endpoint. + * @udc: Reference to the device controller. + * @bep: Endpoint on which to operate. + * @is_stalled: true to enable stall, false to disable. + * + * See notes in bcm63xx_update_wedge() regarding automatic clearing of + * halt/stall conditions. + */ +static void bcm63xx_set_stall(struct bcm63xx_udc *udc, struct bcm63xx_ep *bep, + bool is_stalled) +{ + u32 val; + + val = USBD_STALL_UPDATE_MASK | + (is_stalled ? USBD_STALL_ENABLE_MASK : 0) | + (bep->ep_num << USBD_STALL_EPNUM_SHIFT); + usbd_writel(udc, val, USBD_STALL_REG); +} + +/** + * bcm63xx_fifo_setup - (Re)initialize FIFO boundaries and settings. + * @udc: Reference to the device controller. + * + * These parameters depend on the USB link speed. Settings are + * per-IUDMA-channel-pair. + */ +static void bcm63xx_fifo_setup(struct bcm63xx_udc *udc) +{ + int is_hs = udc->gadget.speed == USB_SPEED_HIGH; + u32 i, val, rx_fifo_slot, tx_fifo_slot; + + /* set up FIFO boundaries and packet sizes; this is done in pairs */ + rx_fifo_slot = tx_fifo_slot = 0; + for (i = 0; i < BCM63XX_NUM_IUDMA; i += 2) { + const struct iudma_ch_cfg *rx_cfg = &iudma_defaults[i]; + const struct iudma_ch_cfg *tx_cfg = &iudma_defaults[i + 1]; + + bcm63xx_ep_dma_select(udc, i >> 1); + + val = (rx_fifo_slot << USBD_RXFIFO_CONFIG_START_SHIFT) | + ((rx_fifo_slot + rx_cfg->n_fifo_slots - 1) << + USBD_RXFIFO_CONFIG_END_SHIFT); + rx_fifo_slot += rx_cfg->n_fifo_slots; + usbd_writel(udc, val, USBD_RXFIFO_CONFIG_REG); + usbd_writel(udc, + is_hs ? rx_cfg->max_pkt_hs : rx_cfg->max_pkt_fs, + USBD_RXFIFO_EPSIZE_REG); + + val = (tx_fifo_slot << USBD_TXFIFO_CONFIG_START_SHIFT) | + ((tx_fifo_slot + tx_cfg->n_fifo_slots - 1) << + USBD_TXFIFO_CONFIG_END_SHIFT); + tx_fifo_slot += tx_cfg->n_fifo_slots; + usbd_writel(udc, val, USBD_TXFIFO_CONFIG_REG); + usbd_writel(udc, + is_hs ? tx_cfg->max_pkt_hs : tx_cfg->max_pkt_fs, + USBD_TXFIFO_EPSIZE_REG); + + usbd_readl(udc, USBD_TXFIFO_EPSIZE_REG); + } +} + +/** + * bcm63xx_fifo_reset_ep - Flush a single endpoint's FIFO. + * @udc: Reference to the device controller. + * @ep_num: Endpoint number. + */ +static void bcm63xx_fifo_reset_ep(struct bcm63xx_udc *udc, int ep_num) +{ + u32 val; + + bcm63xx_ep_dma_select(udc, ep_num); + + val = usbd_readl(udc, USBD_CONTROL_REG); + val |= USBD_CONTROL_FIFO_RESET_MASK; + usbd_writel(udc, val, USBD_CONTROL_REG); + usbd_readl(udc, USBD_CONTROL_REG); +} + +/** + * bcm63xx_fifo_reset - Flush all hardware FIFOs. + * @udc: Reference to the device controller. + */ +static void bcm63xx_fifo_reset(struct bcm63xx_udc *udc) +{ + int i; + + for (i = 0; i < BCM63XX_NUM_FIFO_PAIRS; i++) + bcm63xx_fifo_reset_ep(udc, i); +} + +/** + * bcm63xx_ep_init - Initial (one-time) endpoint initialization. + * @udc: Reference to the device controller. + */ +static void bcm63xx_ep_init(struct bcm63xx_udc *udc) +{ + u32 i, val; + + for (i = 0; i < BCM63XX_NUM_IUDMA; i++) { + const struct iudma_ch_cfg *cfg = &iudma_defaults[i]; + + if (cfg->ep_num < 0) + continue; + + bcm63xx_ep_dma_select(udc, cfg->ep_num); + val = (cfg->ep_type << USBD_EPNUM_TYPEMAP_TYPE_SHIFT) | + ((i >> 1) << USBD_EPNUM_TYPEMAP_DMA_CH_SHIFT); + usbd_writel(udc, val, USBD_EPNUM_TYPEMAP_REG); + } +} + +/** + * bcm63xx_ep_setup - Configure per-endpoint settings. + * @udc: Reference to the device controller. + * + * This needs to be rerun if the speed/cfg/intf/altintf changes. + */ +static void bcm63xx_ep_setup(struct bcm63xx_udc *udc) +{ + u32 val, i; + + usbd_writel(udc, USBD_CSR_SETUPADDR_DEF, USBD_CSR_SETUPADDR_REG); + + for (i = 0; i < BCM63XX_NUM_IUDMA; i++) { + const struct iudma_ch_cfg *cfg = &iudma_defaults[i]; + int max_pkt = udc->gadget.speed == USB_SPEED_HIGH ? + cfg->max_pkt_hs : cfg->max_pkt_fs; + int idx = cfg->ep_num; + + udc->iudma[i].max_pkt = max_pkt; + + if (idx < 0) + continue; + udc->bep[idx].ep.maxpacket = max_pkt; + + val = (idx << USBD_CSR_EP_LOG_SHIFT) | + (cfg->dir << USBD_CSR_EP_DIR_SHIFT) | + (cfg->ep_type << USBD_CSR_EP_TYPE_SHIFT) | + (udc->cfg << USBD_CSR_EP_CFG_SHIFT) | + (udc->iface << USBD_CSR_EP_IFACE_SHIFT) | + (udc->alt_iface << USBD_CSR_EP_ALTIFACE_SHIFT) | + (max_pkt << USBD_CSR_EP_MAXPKT_SHIFT); + usbd_writel(udc, val, USBD_CSR_EP_REG(idx)); + } +} + +/** + * iudma_write - Queue a single IUDMA transaction. + * @udc: Reference to the device controller. + * @iudma: IUDMA channel to use. + * @breq: Request containing the transaction data. + * + * For RX IUDMA, this will queue a single buffer descriptor, as RX IUDMA + * does not honor SOP/EOP so the handling of multiple buffers is ambiguous. + * So iudma_write() may be called several times to fulfill a single + * usb_request. + * + * For TX IUDMA, this can queue multiple buffer descriptors if needed. + */ +static void iudma_write(struct bcm63xx_udc *udc, struct iudma_ch *iudma, + struct bcm63xx_req *breq) +{ + int first_bd = 1, last_bd = 0, extra_zero_pkt = 0; + unsigned int bytes_left = breq->req.length - breq->offset; + const int max_bd_bytes = !irq_coalesce && !iudma->is_tx ? + iudma->max_pkt : IUDMA_MAX_FRAGMENT; + + iudma->n_bds_used = 0; + breq->bd_bytes = 0; + breq->iudma = iudma; + + if ((bytes_left % iudma->max_pkt == 0) && bytes_left && breq->req.zero) + extra_zero_pkt = 1; + + do { + struct bcm_enet_desc *d = iudma->write_bd; + u32 dmaflags = 0; + unsigned int n_bytes; + + if (d == iudma->end_bd) { + dmaflags |= DMADESC_WRAP_MASK; + iudma->write_bd = iudma->bd_ring; + } else { + iudma->write_bd++; + } + iudma->n_bds_used++; + + n_bytes = min_t(int, bytes_left, max_bd_bytes); + if (n_bytes) + dmaflags |= n_bytes << DMADESC_LENGTH_SHIFT; + else + dmaflags |= (1 << DMADESC_LENGTH_SHIFT) | + DMADESC_USB_ZERO_MASK; + + dmaflags |= DMADESC_OWNER_MASK; + if (first_bd) { + dmaflags |= DMADESC_SOP_MASK; + first_bd = 0; + } + + /* + * extra_zero_pkt forces one more iteration through the loop + * after all data is queued up, to send the zero packet + */ + if (extra_zero_pkt && !bytes_left) + extra_zero_pkt = 0; + + if (!iudma->is_tx || iudma->n_bds_used == iudma->n_bds || + (n_bytes == bytes_left && !extra_zero_pkt)) { + last_bd = 1; + dmaflags |= DMADESC_EOP_MASK; + } + + d->address = breq->req.dma + breq->offset; + mb(); + d->len_stat = dmaflags; + + breq->offset += n_bytes; + breq->bd_bytes += n_bytes; + bytes_left -= n_bytes; + } while (!last_bd); + + usb_dmac_writel(udc, ENETDMAC_CHANCFG_EN_MASK, + ENETDMAC_CHANCFG_REG(iudma->ch_idx)); +} + +/** + * iudma_read - Check for IUDMA buffer completion. + * @udc: Reference to the device controller. + * @iudma: IUDMA channel to use. + * + * This checks to see if ALL of the outstanding BDs on the DMA channel + * have been filled. If so, it returns the actual transfer length; + * otherwise it returns -EBUSY. + */ +static int iudma_read(struct bcm63xx_udc *udc, struct iudma_ch *iudma) +{ + int i, actual_len = 0; + struct bcm_enet_desc *d = iudma->read_bd; + + if (!iudma->n_bds_used) + return -EINVAL; + + for (i = 0; i < iudma->n_bds_used; i++) { + u32 dmaflags; + + dmaflags = d->len_stat; + + if (dmaflags & DMADESC_OWNER_MASK) + return -EBUSY; + + actual_len += (dmaflags & DMADESC_LENGTH_MASK) >> + DMADESC_LENGTH_SHIFT; + if (d == iudma->end_bd) + d = iudma->bd_ring; + else + d++; + } + + iudma->read_bd = d; + iudma->n_bds_used = 0; + return actual_len; +} + +/** + * iudma_reset_channel - Stop DMA on a single channel. + * @udc: Reference to the device controller. + * @iudma: IUDMA channel to reset. + */ +static void iudma_reset_channel(struct bcm63xx_udc *udc, struct iudma_ch *iudma) +{ + int timeout = IUDMA_RESET_TIMEOUT_US; + struct bcm_enet_desc *d; + int ch_idx = iudma->ch_idx; + + if (!iudma->is_tx) + bcm63xx_fifo_reset_ep(udc, max(0, iudma->ep_num)); + + /* stop DMA, then wait for the hardware to wrap up */ + usb_dmac_writel(udc, 0, ENETDMAC_CHANCFG_REG(ch_idx)); + + while (usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG(ch_idx)) & + ENETDMAC_CHANCFG_EN_MASK) { + udelay(1); + + /* repeatedly flush the FIFO data until the BD completes */ + if (iudma->is_tx && iudma->ep_num >= 0) + bcm63xx_fifo_reset_ep(udc, iudma->ep_num); + + if (!timeout--) { + dev_err(udc->dev, "can't reset IUDMA channel %d\n", + ch_idx); + break; + } + if (timeout == IUDMA_RESET_TIMEOUT_US / 2) { + dev_warn(udc->dev, "forcibly halting IUDMA channel %d\n", + ch_idx); + usb_dmac_writel(udc, ENETDMAC_CHANCFG_BUFHALT_MASK, + ENETDMAC_CHANCFG_REG(ch_idx)); + } + } + usb_dmac_writel(udc, ~0, ENETDMAC_IR_REG(ch_idx)); + + /* don't leave "live" HW-owned entries for the next guy to step on */ + for (d = iudma->bd_ring; d <= iudma->end_bd; d++) + d->len_stat = 0; + mb(); + + iudma->read_bd = iudma->write_bd = iudma->bd_ring; + iudma->n_bds_used = 0; + + /* set up IRQs, UBUS burst size, and BD base for this channel */ + usb_dmac_writel(udc, ENETDMAC_IR_BUFDONE_MASK, + ENETDMAC_IRMASK_REG(ch_idx)); + usb_dmac_writel(udc, 8, ENETDMAC_MAXBURST_REG(ch_idx)); + + usb_dmas_writel(udc, iudma->bd_ring_dma, ENETDMAS_RSTART_REG(ch_idx)); + usb_dmas_writel(udc, 0, ENETDMAS_SRAM2_REG(ch_idx)); +} + +/** + * iudma_init_channel - One-time IUDMA channel initialization. + * @udc: Reference to the device controller. + * @ch_idx: Channel to initialize. + */ +static int iudma_init_channel(struct bcm63xx_udc *udc, unsigned int ch_idx) +{ + struct iudma_ch *iudma = &udc->iudma[ch_idx]; + const struct iudma_ch_cfg *cfg = &iudma_defaults[ch_idx]; + unsigned int n_bds = cfg->n_bds; + struct bcm63xx_ep *bep = NULL; + + iudma->ep_num = cfg->ep_num; + iudma->ch_idx = ch_idx; + iudma->is_tx = !!(ch_idx & 0x01); + if (iudma->ep_num >= 0) { + bep = &udc->bep[iudma->ep_num]; + bep->iudma = iudma; + INIT_LIST_HEAD(&bep->queue); + } + + iudma->bep = bep; + iudma->udc = udc; + + /* ep0 is always active; others are controlled by the gadget driver */ + if (iudma->ep_num <= 0) + iudma->enabled = true; + + iudma->n_bds = n_bds; + iudma->bd_ring = dmam_alloc_coherent(udc->dev, + n_bds * sizeof(struct bcm_enet_desc), + &iudma->bd_ring_dma, GFP_KERNEL); + if (!iudma->bd_ring) + return -ENOMEM; + iudma->end_bd = &iudma->bd_ring[n_bds - 1]; + + return 0; +} + +/** + * iudma_init - One-time initialization of all IUDMA channels. + * @udc: Reference to the device controller. + * + * Enable DMA, flush channels, and enable global IUDMA IRQs. + */ +static int iudma_init(struct bcm63xx_udc *udc) +{ + int i, rc; + + usb_dma_writel(udc, ENETDMA_CFG_EN_MASK, ENETDMA_CFG_REG); + + for (i = 0; i < BCM63XX_NUM_IUDMA; i++) { + rc = iudma_init_channel(udc, i); + if (rc) + return rc; + iudma_reset_channel(udc, &udc->iudma[i]); + } + + usb_dma_writel(udc, BIT(BCM63XX_NUM_IUDMA)-1, ENETDMA_GLB_IRQMASK_REG); + return 0; +} + +/** + * iudma_uninit - Uninitialize IUDMA channels. + * @udc: Reference to the device controller. + * + * Kill global IUDMA IRQs, flush channels, and kill DMA. + */ +static void iudma_uninit(struct bcm63xx_udc *udc) +{ + int i; + + usb_dma_writel(udc, 0, ENETDMA_GLB_IRQMASK_REG); + + for (i = 0; i < BCM63XX_NUM_IUDMA; i++) + iudma_reset_channel(udc, &udc->iudma[i]); + + usb_dma_writel(udc, 0, ENETDMA_CFG_REG); +} + +/*********************************************************************** + * Other low-level USBD operations + ***********************************************************************/ + +/** + * bcm63xx_set_ctrl_irqs - Mask/unmask control path interrupts. + * @udc: Reference to the device controller. + * @enable_irqs: true to enable, false to disable. + */ +static void bcm63xx_set_ctrl_irqs(struct bcm63xx_udc *udc, bool enable_irqs) +{ + u32 val; + + usbd_writel(udc, 0, USBD_STATUS_REG); + + val = BIT(USBD_EVENT_IRQ_USB_RESET) | + BIT(USBD_EVENT_IRQ_SETUP) | + BIT(USBD_EVENT_IRQ_SETCFG) | + BIT(USBD_EVENT_IRQ_SETINTF) | + BIT(USBD_EVENT_IRQ_USB_LINK); + usbd_writel(udc, enable_irqs ? val : 0, USBD_EVENT_IRQ_MASK_REG); + usbd_writel(udc, val, USBD_EVENT_IRQ_STATUS_REG); +} + +/** + * bcm63xx_select_phy_mode - Select between USB device and host mode. + * @udc: Reference to the device controller. + * @is_device: true for device, false for host. + * + * This should probably be reworked to use the drivers/usb/otg + * infrastructure. + * + * By default, the AFE/pullups are disabled in device mode, until + * bcm63xx_select_pullup() is called. + */ +static void bcm63xx_select_phy_mode(struct bcm63xx_udc *udc, bool is_device) +{ + u32 val, portmask = BIT(udc->pd->port_no); + + if (BCMCPU_IS_6328()) { + /* configure pinmux to sense VBUS signal */ + val = bcm_gpio_readl(GPIO_PINMUX_OTHR_REG); + val &= ~GPIO_PINMUX_OTHR_6328_USB_MASK; + val |= is_device ? GPIO_PINMUX_OTHR_6328_USB_DEV : + GPIO_PINMUX_OTHR_6328_USB_HOST; + bcm_gpio_writel(val, GPIO_PINMUX_OTHR_REG); + } + + val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG); + if (is_device) { + val |= (portmask << USBH_PRIV_UTMI_CTL_HOSTB_SHIFT); + val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT); + } else { + val &= ~(portmask << USBH_PRIV_UTMI_CTL_HOSTB_SHIFT); + val &= ~(portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT); + } + bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG); + + val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_SWAP_6368_REG); + if (is_device) + val |= USBH_PRIV_SWAP_USBD_MASK; + else + val &= ~USBH_PRIV_SWAP_USBD_MASK; + bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_SWAP_6368_REG); +} + +/** + * bcm63xx_select_pullup - Enable/disable the pullup on D+ + * @udc: Reference to the device controller. + * @is_on: true to enable the pullup, false to disable. + * + * If the pullup is active, the host will sense a FS/HS device connected to + * the port. If the pullup is inactive, the host will think the USB + * device has been disconnected. + */ +static void bcm63xx_select_pullup(struct bcm63xx_udc *udc, bool is_on) +{ + u32 val, portmask = BIT(udc->pd->port_no); + + val = bcm_rset_readl(RSET_USBH_PRIV, USBH_PRIV_UTMI_CTL_6368_REG); + if (is_on) + val &= ~(portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT); + else + val |= (portmask << USBH_PRIV_UTMI_CTL_NODRIV_SHIFT); + bcm_rset_writel(RSET_USBH_PRIV, val, USBH_PRIV_UTMI_CTL_6368_REG); +} + +/** + * bcm63xx_uninit_udc_hw - Shut down the hardware prior to driver removal. + * @udc: Reference to the device controller. + * + * This just masks the IUDMA IRQs and releases the clocks. It is assumed + * that bcm63xx_udc_stop() has already run, and the clocks are stopped. + */ +static void bcm63xx_uninit_udc_hw(struct bcm63xx_udc *udc) +{ + set_clocks(udc, true); + iudma_uninit(udc); + set_clocks(udc, false); + + clk_put(udc->usbd_clk); + clk_put(udc->usbh_clk); +} + +/** + * bcm63xx_init_udc_hw - Initialize the controller hardware and data structures. + * @udc: Reference to the device controller. + */ +static int bcm63xx_init_udc_hw(struct bcm63xx_udc *udc) +{ + int i, rc = 0; + u32 val; + + udc->ep0_ctrl_buf = devm_kzalloc(udc->dev, BCM63XX_MAX_CTRL_PKT, + GFP_KERNEL); + if (!udc->ep0_ctrl_buf) + return -ENOMEM; + + INIT_LIST_HEAD(&udc->gadget.ep_list); + for (i = 0; i < BCM63XX_NUM_EP; i++) { + struct bcm63xx_ep *bep = &udc->bep[i]; + + bep->ep.name = bcm63xx_ep_name[i]; + bep->ep_num = i; + bep->ep.ops = &bcm63xx_udc_ep_ops; + list_add_tail(&bep->ep.ep_list, &udc->gadget.ep_list); + bep->halted = 0; + bep->ep.maxpacket = BCM63XX_MAX_CTRL_PKT; + bep->udc = udc; + bep->ep.desc = NULL; + INIT_LIST_HEAD(&bep->queue); + } + + udc->gadget.ep0 = &udc->bep[0].ep; + list_del(&udc->bep[0].ep.ep_list); + + udc->gadget.speed = USB_SPEED_UNKNOWN; + udc->ep0state = EP0_SHUTDOWN; + + udc->usbh_clk = clk_get(udc->dev, "usbh"); + if (IS_ERR(udc->usbh_clk)) + return -EIO; + + udc->usbd_clk = clk_get(udc->dev, "usbd"); + if (IS_ERR(udc->usbd_clk)) { + clk_put(udc->usbh_clk); + return -EIO; + } + + set_clocks(udc, true); + + val = USBD_CONTROL_AUTO_CSRS_MASK | + USBD_CONTROL_DONE_CSRS_MASK | + (irq_coalesce ? USBD_CONTROL_RXZSCFG_MASK : 0); + usbd_writel(udc, val, USBD_CONTROL_REG); + + val = USBD_STRAPS_APP_SELF_PWR_MASK | + USBD_STRAPS_APP_RAM_IF_MASK | + USBD_STRAPS_APP_CSRPRGSUP_MASK | + USBD_STRAPS_APP_8BITPHY_MASK | + USBD_STRAPS_APP_RMTWKUP_MASK; + + if (udc->gadget.max_speed == USB_SPEED_HIGH) + val |= (BCM63XX_SPD_HIGH << USBD_STRAPS_SPEED_SHIFT); + else + val |= (BCM63XX_SPD_FULL << USBD_STRAPS_SPEED_SHIFT); + usbd_writel(udc, val, USBD_STRAPS_REG); + + bcm63xx_set_ctrl_irqs(udc, false); + + usbd_writel(udc, 0, USBD_EVENT_IRQ_CFG_LO_REG); + + val = USBD_EVENT_IRQ_CFG_FALLING(USBD_EVENT_IRQ_ENUM_ON) | + USBD_EVENT_IRQ_CFG_FALLING(USBD_EVENT_IRQ_SET_CSRS); + usbd_writel(udc, val, USBD_EVENT_IRQ_CFG_HI_REG); + + rc = iudma_init(udc); + set_clocks(udc, false); + if (rc) + bcm63xx_uninit_udc_hw(udc); + + return 0; +} + +/*********************************************************************** + * Standard EP gadget operations + ***********************************************************************/ + +/** + * bcm63xx_ep_enable - Enable one endpoint. + * @ep: Endpoint to enable. + * @desc: Contains max packet, direction, etc. + * + * Most of the endpoint parameters are fixed in this controller, so there + * isn't much for this function to do. + */ +static int bcm63xx_ep_enable(struct usb_ep *ep, + const struct usb_endpoint_descriptor *desc) +{ + struct bcm63xx_ep *bep = our_ep(ep); + struct bcm63xx_udc *udc = bep->udc; + struct iudma_ch *iudma = bep->iudma; + unsigned long flags; + + if (!ep || !desc || ep->name == bcm63xx_ep0name) + return -EINVAL; + + if (!udc->driver) + return -ESHUTDOWN; + + spin_lock_irqsave(&udc->lock, flags); + if (iudma->enabled) { + spin_unlock_irqrestore(&udc->lock, flags); + return -EINVAL; + } + + iudma->enabled = true; + BUG_ON(!list_empty(&bep->queue)); + + iudma_reset_channel(udc, iudma); + + bep->halted = 0; + bcm63xx_set_stall(udc, bep, false); + clear_bit(bep->ep_num, &udc->wedgemap); + + ep->desc = desc; + ep->maxpacket = usb_endpoint_maxp(desc); + + spin_unlock_irqrestore(&udc->lock, flags); + return 0; +} + +/** + * bcm63xx_ep_disable - Disable one endpoint. + * @ep: Endpoint to disable. + */ +static int bcm63xx_ep_disable(struct usb_ep *ep) +{ + struct bcm63xx_ep *bep = our_ep(ep); + struct bcm63xx_udc *udc = bep->udc; + struct iudma_ch *iudma = bep->iudma; + struct list_head *pos, *n; + unsigned long flags; + + if (!ep || !ep->desc) + return -EINVAL; + + spin_lock_irqsave(&udc->lock, flags); + if (!iudma->enabled) { + spin_unlock_irqrestore(&udc->lock, flags); + return -EINVAL; + } + iudma->enabled = false; + + iudma_reset_channel(udc, iudma); + + if (!list_empty(&bep->queue)) { + list_for_each_safe(pos, n, &bep->queue) { + struct bcm63xx_req *breq = + list_entry(pos, struct bcm63xx_req, queue); + + usb_gadget_unmap_request(&udc->gadget, &breq->req, + iudma->is_tx); + list_del(&breq->queue); + breq->req.status = -ESHUTDOWN; + + spin_unlock_irqrestore(&udc->lock, flags); + breq->req.complete(&iudma->bep->ep, &breq->req); + spin_lock_irqsave(&udc->lock, flags); + } + } + ep->desc = NULL; + + spin_unlock_irqrestore(&udc->lock, flags); + return 0; +} + +/** + * bcm63xx_udc_alloc_request - Allocate a new request. + * @ep: Endpoint associated with the request. + * @mem_flags: Flags to pass to kzalloc(). + */ +static struct usb_request *bcm63xx_udc_alloc_request(struct usb_ep *ep, + gfp_t mem_flags) +{ + struct bcm63xx_req *breq; + + breq = kzalloc(sizeof(*breq), mem_flags); + if (!breq) + return NULL; + return &breq->req; +} + +/** + * bcm63xx_udc_free_request - Free a request. + * @ep: Endpoint associated with the request. + * @req: Request to free. + */ +static void bcm63xx_udc_free_request(struct usb_ep *ep, + struct usb_request *req) +{ + struct bcm63xx_req *breq = our_req(req); + kfree(breq); +} + +/** + * bcm63xx_udc_queue - Queue up a new request. + * @ep: Endpoint associated with the request. + * @req: Request to add. + * @mem_flags: Unused. + * + * If the queue is empty, start this request immediately. Otherwise, add + * it to the list. + * + * ep0 replies are sent through this function from the gadget driver, but + * they are treated differently because they need to be handled by the ep0 + * state machine. (Sometimes they are replies to control requests that + * were spoofed by this driver, and so they shouldn't be transmitted at all.) + */ +static int bcm63xx_udc_queue(struct usb_ep *ep, struct usb_request *req, + gfp_t mem_flags) +{ + struct bcm63xx_ep *bep = our_ep(ep); + struct bcm63xx_udc *udc = bep->udc; + struct bcm63xx_req *breq = our_req(req); + unsigned long flags; + int rc = 0; + + if (unlikely(!req || !req->complete || !req->buf || !ep)) + return -EINVAL; + + req->actual = 0; + req->status = 0; + breq->offset = 0; + + if (bep == &udc->bep[0]) { + /* only one reply per request, please */ + if (udc->ep0_reply) + return -EINVAL; + + udc->ep0_reply = req; + schedule_work(&udc->ep0_wq); + return 0; + } + + spin_lock_irqsave(&udc->lock, flags); + if (!bep->iudma->enabled) { + rc = -ESHUTDOWN; + goto out; + } + + rc = usb_gadget_map_request(&udc->gadget, req, bep->iudma->is_tx); + if (rc == 0) { + list_add_tail(&breq->queue, &bep->queue); + if (list_is_singular(&bep->queue)) + iudma_write(udc, bep->iudma, breq); + } + +out: + spin_unlock_irqrestore(&udc->lock, flags); + return rc; +} + +/** + * bcm63xx_udc_dequeue - Remove a pending request from the queue. + * @ep: Endpoint associated with the request. + * @req: Request to remove. + * + * If the request is not at the head of the queue, this is easy - just nuke + * it. If the request is at the head of the queue, we'll need to stop the + * DMA transaction and then queue up the successor. + */ +static int bcm63xx_udc_dequeue(struct usb_ep *ep, struct usb_request *req) +{ + struct bcm63xx_ep *bep = our_ep(ep); + struct bcm63xx_udc *udc = bep->udc; + struct bcm63xx_req *breq = our_req(req), *cur; + unsigned long flags; + int rc = 0; + + spin_lock_irqsave(&udc->lock, flags); + if (list_empty(&bep->queue)) { + rc = -EINVAL; + goto out; + } + + cur = list_first_entry(&bep->queue, struct bcm63xx_req, queue); + usb_gadget_unmap_request(&udc->gadget, &breq->req, bep->iudma->is_tx); + + if (breq == cur) { + iudma_reset_channel(udc, bep->iudma); + list_del(&breq->queue); + + if (!list_empty(&bep->queue)) { + struct bcm63xx_req *next; + + next = list_first_entry(&bep->queue, + struct bcm63xx_req, queue); + iudma_write(udc, bep->iudma, next); + } + } else { + list_del(&breq->queue); + } + +out: + spin_unlock_irqrestore(&udc->lock, flags); + + req->status = -ESHUTDOWN; + req->complete(ep, req); + + return rc; +} + +/** + * bcm63xx_udc_set_halt - Enable/disable STALL flag in the hardware. + * @ep: Endpoint to halt. + * @value: Zero to clear halt; nonzero to set halt. + * + * See comments in bcm63xx_update_wedge(). + */ +static int bcm63xx_udc_set_halt(struct usb_ep *ep, int value) +{ + struct bcm63xx_ep *bep = our_ep(ep); + struct bcm63xx_udc *udc = bep->udc; + unsigned long flags; + + spin_lock_irqsave(&udc->lock, flags); + bcm63xx_set_stall(udc, bep, !!value); + bep->halted = value; + spin_unlock_irqrestore(&udc->lock, flags); + + return 0; +} + +/** + * bcm63xx_udc_set_wedge - Stall the endpoint until the next reset. + * @ep: Endpoint to wedge. + * + * See comments in bcm63xx_update_wedge(). + */ +static int bcm63xx_udc_set_wedge(struct usb_ep *ep) +{ + struct bcm63xx_ep *bep = our_ep(ep); + struct bcm63xx_udc *udc = bep->udc; + unsigned long flags; + + spin_lock_irqsave(&udc->lock, flags); + set_bit(bep->ep_num, &udc->wedgemap); + bcm63xx_set_stall(udc, bep, true); + spin_unlock_irqrestore(&udc->lock, flags); + + return 0; +} + +static const struct usb_ep_ops bcm63xx_udc_ep_ops = { + .enable = bcm63xx_ep_enable, + .disable = bcm63xx_ep_disable, + + .alloc_request = bcm63xx_udc_alloc_request, + .free_request = bcm63xx_udc_free_request, + + .queue = bcm63xx_udc_queue, + .dequeue = bcm63xx_udc_dequeue, + + .set_halt = bcm63xx_udc_set_halt, + .set_wedge = bcm63xx_udc_set_wedge, +}; + +/*********************************************************************** + * EP0 handling + ***********************************************************************/ + +/** + * bcm63xx_ep0_setup_callback - Drop spinlock to invoke ->setup callback. + * @udc: Reference to the device controller. + * @ctrl: 8-byte SETUP request. + */ +static int bcm63xx_ep0_setup_callback(struct bcm63xx_udc *udc, + struct usb_ctrlrequest *ctrl) +{ + int rc; + + spin_unlock_irq(&udc->lock); + rc = udc->driver->setup(&udc->gadget, ctrl); + spin_lock_irq(&udc->lock); + return rc; +} + +/** + * bcm63xx_ep0_spoof_set_cfg - Synthesize a SET_CONFIGURATION request. + * @udc: Reference to the device controller. + * + * Many standard requests are handled automatically in the hardware, but + * we still need to pass them to the gadget driver so that it can + * reconfigure the interfaces/endpoints if necessary. + * + * Unfortunately we are not able to send a STALL response if the host + * requests an invalid configuration. If this happens, we'll have to be + * content with printing a warning. + */ +static int bcm63xx_ep0_spoof_set_cfg(struct bcm63xx_udc *udc) +{ + struct usb_ctrlrequest ctrl; + int rc; + + ctrl.bRequestType = USB_DIR_OUT | USB_RECIP_DEVICE; + ctrl.bRequest = USB_REQ_SET_CONFIGURATION; + ctrl.wValue = cpu_to_le16(udc->cfg); + ctrl.wIndex = 0; + ctrl.wLength = 0; + + rc = bcm63xx_ep0_setup_callback(udc, &ctrl); + if (rc < 0) { + dev_warn_ratelimited(udc->dev, + "hardware auto-acked bad SET_CONFIGURATION(%d) request\n", + udc->cfg); + } + return rc; +} + +/** + * bcm63xx_ep0_spoof_set_iface - Synthesize a SET_INTERFACE request. + * @udc: Reference to the device controller. + */ +static int bcm63xx_ep0_spoof_set_iface(struct bcm63xx_udc *udc) +{ + struct usb_ctrlrequest ctrl; + int rc; + + ctrl.bRequestType = USB_DIR_OUT | USB_RECIP_INTERFACE; + ctrl.bRequest = USB_REQ_SET_INTERFACE; + ctrl.wValue = cpu_to_le16(udc->alt_iface); + ctrl.wIndex = cpu_to_le16(udc->iface); + ctrl.wLength = 0; + + rc = bcm63xx_ep0_setup_callback(udc, &ctrl); + if (rc < 0) { + dev_warn_ratelimited(udc->dev, + "hardware auto-acked bad SET_INTERFACE(%d,%d) request\n", + udc->iface, udc->alt_iface); + } + return rc; +} + +/** + * bcm63xx_ep0_map_write - dma_map and iudma_write a single request. + * @udc: Reference to the device controller. + * @ch_idx: IUDMA channel number. + * @req: USB gadget layer representation of the request. + */ +static void bcm63xx_ep0_map_write(struct bcm63xx_udc *udc, int ch_idx, + struct usb_request *req) +{ + struct bcm63xx_req *breq = our_req(req); + struct iudma_ch *iudma = &udc->iudma[ch_idx]; + + BUG_ON(udc->ep0_request); + udc->ep0_request = req; + + req->actual = 0; + breq->offset = 0; + usb_gadget_map_request(&udc->gadget, req, iudma->is_tx); + iudma_write(udc, iudma, breq); +} + +/** + * bcm63xx_ep0_complete - Set completion status and "stage" the callback. + * @udc: Reference to the device controller. + * @req: USB gadget layer representation of the request. + * @status: Status to return to the gadget driver. + */ +static void bcm63xx_ep0_complete(struct bcm63xx_udc *udc, + struct usb_request *req, int status) +{ + req->status = status; + if (status) + req->actual = 0; + if (req->complete) { + spin_unlock_irq(&udc->lock); + req->complete(&udc->bep[0].ep, req); + spin_lock_irq(&udc->lock); + } +} + +/** + * bcm63xx_ep0_nuke_reply - Abort request from the gadget driver due to + * reset/shutdown. + * @udc: Reference to the device controller. + * @is_tx: Nonzero for TX (IN), zero for RX (OUT). + */ +static void bcm63xx_ep0_nuke_reply(struct bcm63xx_udc *udc, int is_tx) +{ + struct usb_request *req = udc->ep0_reply; + + udc->ep0_reply = NULL; + usb_gadget_unmap_request(&udc->gadget, req, is_tx); + if (udc->ep0_request == req) { + udc->ep0_req_completed = 0; + udc->ep0_request = NULL; + } + bcm63xx_ep0_complete(udc, req, -ESHUTDOWN); +} + +/** + * bcm63xx_ep0_read_complete - Close out the pending ep0 request; return + * transfer len. + * @udc: Reference to the device controller. + */ +static int bcm63xx_ep0_read_complete(struct bcm63xx_udc *udc) +{ + struct usb_request *req = udc->ep0_request; + + udc->ep0_req_completed = 0; + udc->ep0_request = NULL; + + return req->actual; +} + +/** + * bcm63xx_ep0_internal_request - Helper function to submit an ep0 request. + * @udc: Reference to the device controller. + * @ch_idx: IUDMA channel number. + * @length: Number of bytes to TX/RX. + * + * Used for simple transfers performed by the ep0 worker. This will always + * use ep0_ctrl_req / ep0_ctrl_buf. + */ +static void bcm63xx_ep0_internal_request(struct bcm63xx_udc *udc, int ch_idx, + int length) +{ + struct usb_request *req = &udc->ep0_ctrl_req.req; + + req->buf = udc->ep0_ctrl_buf; + req->length = length; + req->complete = NULL; + + bcm63xx_ep0_map_write(udc, ch_idx, req); +} + +/** + * bcm63xx_ep0_do_setup - Parse new SETUP packet and decide how to handle it. + * @udc: Reference to the device controller. + * + * EP0_IDLE probably shouldn't ever happen. EP0_REQUEUE means we're ready + * for the next packet. Anything else means the transaction requires multiple + * stages of handling. + */ +static enum bcm63xx_ep0_state bcm63xx_ep0_do_setup(struct bcm63xx_udc *udc) +{ + int rc; + struct usb_ctrlrequest *ctrl = (void *)udc->ep0_ctrl_buf; + + rc = bcm63xx_ep0_read_complete(udc); + + if (rc < 0) { + dev_err(udc->dev, "missing SETUP packet\n"); + return EP0_IDLE; + } + + /* + * Handle 0-byte IN STATUS acknowledgement. The hardware doesn't + * ALWAYS deliver these 100% of the time, so if we happen to see one, + * just throw it away. + */ + if (rc == 0) + return EP0_REQUEUE; + + /* Drop malformed SETUP packets */ + if (rc != sizeof(*ctrl)) { + dev_warn_ratelimited(udc->dev, + "malformed SETUP packet (%d bytes)\n", rc); + return EP0_REQUEUE; + } + + /* Process new SETUP packet arriving on ep0 */ + rc = bcm63xx_ep0_setup_callback(udc, ctrl); + if (rc < 0) { + bcm63xx_set_stall(udc, &udc->bep[0], true); + return EP0_REQUEUE; + } + + if (!ctrl->wLength) + return EP0_REQUEUE; + else if (ctrl->bRequestType & USB_DIR_IN) + return EP0_IN_DATA_PHASE_SETUP; + else + return EP0_OUT_DATA_PHASE_SETUP; +} + +/** + * bcm63xx_ep0_do_idle - Check for outstanding requests if ep0 is idle. + * @udc: Reference to the device controller. + * + * In state EP0_IDLE, the RX descriptor is either pending, or has been + * filled with a SETUP packet from the host. This function handles new + * SETUP packets, control IRQ events (which can generate fake SETUP packets), + * and reset/shutdown events. + * + * Returns 0 if work was done; -EAGAIN if nothing to do. + */ +static int bcm63xx_ep0_do_idle(struct bcm63xx_udc *udc) +{ + if (udc->ep0_req_reset) { + udc->ep0_req_reset = 0; + } else if (udc->ep0_req_set_cfg) { + udc->ep0_req_set_cfg = 0; + if (bcm63xx_ep0_spoof_set_cfg(udc) >= 0) + udc->ep0state = EP0_IN_FAKE_STATUS_PHASE; + } else if (udc->ep0_req_set_iface) { + udc->ep0_req_set_iface = 0; + if (bcm63xx_ep0_spoof_set_iface(udc) >= 0) + udc->ep0state = EP0_IN_FAKE_STATUS_PHASE; + } else if (udc->ep0_req_completed) { + udc->ep0state = bcm63xx_ep0_do_setup(udc); + return udc->ep0state == EP0_IDLE ? -EAGAIN : 0; + } else if (udc->ep0_req_shutdown) { + udc->ep0_req_shutdown = 0; + udc->ep0_req_completed = 0; + udc->ep0_request = NULL; + iudma_reset_channel(udc, &udc->iudma[IUDMA_EP0_RXCHAN]); + usb_gadget_unmap_request(&udc->gadget, + &udc->ep0_ctrl_req.req, 0); + + /* bcm63xx_udc_pullup() is waiting for this */ + mb(); + udc->ep0state = EP0_SHUTDOWN; + } else if (udc->ep0_reply) { + /* + * This could happen if a USB RESET shows up during an ep0 + * transaction (especially if a laggy driver like gadgetfs + * is in use). + */ + dev_warn(udc->dev, "nuking unexpected reply\n"); + bcm63xx_ep0_nuke_reply(udc, 0); + } else { + return -EAGAIN; + } + + return 0; +} + +/** + * bcm63xx_ep0_one_round - Handle the current ep0 state. + * @udc: Reference to the device controller. + * + * Returns 0 if work was done; -EAGAIN if nothing to do. + */ +static int bcm63xx_ep0_one_round(struct bcm63xx_udc *udc) +{ + enum bcm63xx_ep0_state ep0state = udc->ep0state; + bool shutdown = udc->ep0_req_reset || udc->ep0_req_shutdown; + + switch (udc->ep0state) { + case EP0_REQUEUE: + /* set up descriptor to receive SETUP packet */ + bcm63xx_ep0_internal_request(udc, IUDMA_EP0_RXCHAN, + BCM63XX_MAX_CTRL_PKT); + ep0state = EP0_IDLE; + break; + case EP0_IDLE: + return bcm63xx_ep0_do_idle(udc); + case EP0_IN_DATA_PHASE_SETUP: + /* + * Normal case: TX request is in ep0_reply (queued by the + * callback), or will be queued shortly. When it's here, + * send it to the HW and go to EP0_IN_DATA_PHASE_COMPLETE. + * + * Shutdown case: Stop waiting for the reply. Just + * REQUEUE->IDLE. The gadget driver is NOT expected to + * queue anything else now. + */ + if (udc->ep0_reply) { + bcm63xx_ep0_map_write(udc, IUDMA_EP0_TXCHAN, + udc->ep0_reply); + ep0state = EP0_IN_DATA_PHASE_COMPLETE; + } else if (shutdown) { + ep0state = EP0_REQUEUE; + } + break; + case EP0_IN_DATA_PHASE_COMPLETE: { + /* + * Normal case: TX packet (ep0_reply) is in flight; wait for + * it to finish, then go back to REQUEUE->IDLE. + * + * Shutdown case: Reset the TX channel, send -ESHUTDOWN + * completion to the gadget driver, then REQUEUE->IDLE. + */ + if (udc->ep0_req_completed) { + udc->ep0_reply = NULL; + bcm63xx_ep0_read_complete(udc); + /* + * the "ack" sometimes gets eaten (see + * bcm63xx_ep0_do_idle) + */ + ep0state = EP0_REQUEUE; + } else if (shutdown) { + iudma_reset_channel(udc, &udc->iudma[IUDMA_EP0_TXCHAN]); + bcm63xx_ep0_nuke_reply(udc, 1); + ep0state = EP0_REQUEUE; + } + break; + } + case EP0_OUT_DATA_PHASE_SETUP: + /* Similar behavior to EP0_IN_DATA_PHASE_SETUP */ + if (udc->ep0_reply) { + bcm63xx_ep0_map_write(udc, IUDMA_EP0_RXCHAN, + udc->ep0_reply); + ep0state = EP0_OUT_DATA_PHASE_COMPLETE; + } else if (shutdown) { + ep0state = EP0_REQUEUE; + } + break; + case EP0_OUT_DATA_PHASE_COMPLETE: { + /* Similar behavior to EP0_IN_DATA_PHASE_COMPLETE */ + if (udc->ep0_req_completed) { + udc->ep0_reply = NULL; + bcm63xx_ep0_read_complete(udc); + + /* send 0-byte ack to host */ + bcm63xx_ep0_internal_request(udc, IUDMA_EP0_TXCHAN, 0); + ep0state = EP0_OUT_STATUS_PHASE; + } else if (shutdown) { + iudma_reset_channel(udc, &udc->iudma[IUDMA_EP0_RXCHAN]); + bcm63xx_ep0_nuke_reply(udc, 0); + ep0state = EP0_REQUEUE; + } + break; + } + case EP0_OUT_STATUS_PHASE: + /* + * Normal case: 0-byte OUT ack packet is in flight; wait + * for it to finish, then go back to REQUEUE->IDLE. + * + * Shutdown case: just cancel the transmission. Don't bother + * calling the completion, because it originated from this + * function anyway. Then go back to REQUEUE->IDLE. + */ + if (udc->ep0_req_completed) { + bcm63xx_ep0_read_complete(udc); + ep0state = EP0_REQUEUE; + } else if (shutdown) { + iudma_reset_channel(udc, &udc->iudma[IUDMA_EP0_TXCHAN]); + udc->ep0_request = NULL; + ep0state = EP0_REQUEUE; + } + break; + case EP0_IN_FAKE_STATUS_PHASE: { + /* + * Normal case: we spoofed a SETUP packet and are now + * waiting for the gadget driver to send a 0-byte reply. + * This doesn't actually get sent to the HW because the + * HW has already sent its own reply. Once we get the + * response, return to IDLE. + * + * Shutdown case: return to IDLE immediately. + * + * Note that the ep0 RX descriptor has remained queued + * (and possibly unfilled) during this entire transaction. + * The HW datapath (IUDMA) never even sees SET_CONFIGURATION + * or SET_INTERFACE transactions. + */ + struct usb_request *r = udc->ep0_reply; + + if (!r) { + if (shutdown) + ep0state = EP0_IDLE; + break; + } + + bcm63xx_ep0_complete(udc, r, 0); + udc->ep0_reply = NULL; + ep0state = EP0_IDLE; + break; + } + case EP0_SHUTDOWN: + break; + } + + if (udc->ep0state == ep0state) + return -EAGAIN; + + udc->ep0state = ep0state; + return 0; +} + +/** + * bcm63xx_ep0_process - ep0 worker thread / state machine. + * @w: Workqueue struct. + * + * bcm63xx_ep0_process is triggered any time an event occurs on ep0. It + * is used to synchronize ep0 events and ensure that both HW and SW events + * occur in a well-defined order. When the ep0 IUDMA queues are idle, it may + * synthesize SET_CONFIGURATION / SET_INTERFACE requests that were consumed + * by the USBD hardware. + * + * The worker function will continue iterating around the state machine + * until there is nothing left to do. Usually "nothing left to do" means + * that we're waiting for a new event from the hardware. + */ +static void bcm63xx_ep0_process(struct work_struct *w) +{ + struct bcm63xx_udc *udc = container_of(w, struct bcm63xx_udc, ep0_wq); + spin_lock_irq(&udc->lock); + while (bcm63xx_ep0_one_round(udc) == 0) + ; + spin_unlock_irq(&udc->lock); +} + +/*********************************************************************** + * Standard UDC gadget operations + ***********************************************************************/ + +/** + * bcm63xx_udc_get_frame - Read current SOF frame number from the HW. + * @gadget: USB slave device. + */ +static int bcm63xx_udc_get_frame(struct usb_gadget *gadget) +{ + struct bcm63xx_udc *udc = gadget_to_udc(gadget); + + return (usbd_readl(udc, USBD_STATUS_REG) & + USBD_STATUS_SOF_MASK) >> USBD_STATUS_SOF_SHIFT; +} + +/** + * bcm63xx_udc_pullup - Enable/disable pullup on D+ line. + * @gadget: USB slave device. + * @is_on: 0 to disable pullup, 1 to enable. + * + * See notes in bcm63xx_select_pullup(). + */ +static int bcm63xx_udc_pullup(struct usb_gadget *gadget, int is_on) +{ + struct bcm63xx_udc *udc = gadget_to_udc(gadget); + unsigned long flags; + int i, rc = -EINVAL; + + spin_lock_irqsave(&udc->lock, flags); + if (is_on && udc->ep0state == EP0_SHUTDOWN) { + udc->gadget.speed = USB_SPEED_UNKNOWN; + udc->ep0state = EP0_REQUEUE; + bcm63xx_fifo_setup(udc); + bcm63xx_fifo_reset(udc); + bcm63xx_ep_setup(udc); + + bitmap_zero(&udc->wedgemap, BCM63XX_NUM_EP); + for (i = 0; i < BCM63XX_NUM_EP; i++) + bcm63xx_set_stall(udc, &udc->bep[i], false); + + bcm63xx_set_ctrl_irqs(udc, true); + bcm63xx_select_pullup(gadget_to_udc(gadget), true); + rc = 0; + } else if (!is_on && udc->ep0state != EP0_SHUTDOWN) { + bcm63xx_select_pullup(gadget_to_udc(gadget), false); + + udc->ep0_req_shutdown = 1; + spin_unlock_irqrestore(&udc->lock, flags); + + while (1) { + schedule_work(&udc->ep0_wq); + if (udc->ep0state == EP0_SHUTDOWN) + break; + msleep(50); + } + bcm63xx_set_ctrl_irqs(udc, false); + cancel_work_sync(&udc->ep0_wq); + return 0; + } + + spin_unlock_irqrestore(&udc->lock, flags); + return rc; +} + +/** + * bcm63xx_udc_start - Start the controller. + * @gadget: USB slave device. + * @driver: Driver for USB slave devices. + */ +static int bcm63xx_udc_start(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) +{ + struct bcm63xx_udc *udc = gadget_to_udc(gadget); + unsigned long flags; + + if (!driver || driver->max_speed < USB_SPEED_HIGH || + !driver->setup) + return -EINVAL; + if (!udc) + return -ENODEV; + if (udc->driver) + return -EBUSY; + + spin_lock_irqsave(&udc->lock, flags); + + set_clocks(udc, true); + bcm63xx_fifo_setup(udc); + bcm63xx_ep_init(udc); + bcm63xx_ep_setup(udc); + bcm63xx_fifo_reset(udc); + bcm63xx_select_phy_mode(udc, true); + + udc->driver = driver; + driver->driver.bus = NULL; + udc->gadget.dev.driver = &driver->driver; + udc->gadget.dev.of_node = udc->dev->of_node; + + spin_unlock_irqrestore(&udc->lock, flags); + + return 0; +} + +/** + * bcm63xx_udc_stop - Shut down the controller. + * @gadget: USB slave device. + * @driver: Driver for USB slave devices. + */ +static int bcm63xx_udc_stop(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) +{ + struct bcm63xx_udc *udc = gadget_to_udc(gadget); + unsigned long flags; + + spin_lock_irqsave(&udc->lock, flags); + + udc->driver = NULL; + udc->gadget.dev.driver = NULL; + + /* + * If we switch the PHY too abruptly after dropping D+, the host + * will often complain: + * + * hub 1-0:1.0: port 1 disabled by hub (EMI?), re-enabling... + */ + msleep(100); + + bcm63xx_select_phy_mode(udc, false); + set_clocks(udc, false); + + spin_unlock_irqrestore(&udc->lock, flags); + + return 0; +} + +static const struct usb_gadget_ops bcm63xx_udc_ops = { + .get_frame = bcm63xx_udc_get_frame, + .pullup = bcm63xx_udc_pullup, + .udc_start = bcm63xx_udc_start, + .udc_stop = bcm63xx_udc_stop, +}; + +/*********************************************************************** + * IRQ handling + ***********************************************************************/ + +/** + * bcm63xx_update_cfg_iface - Read current configuration/interface settings. + * @udc: Reference to the device controller. + * + * This controller intercepts SET_CONFIGURATION and SET_INTERFACE messages. + * The driver never sees the raw control packets coming in on the ep0 + * IUDMA channel, but at least we get an interrupt event to tell us that + * new values are waiting in the USBD_STATUS register. + */ +static void bcm63xx_update_cfg_iface(struct bcm63xx_udc *udc) +{ + u32 reg = usbd_readl(udc, USBD_STATUS_REG); + + udc->cfg = (reg & USBD_STATUS_CFG_MASK) >> USBD_STATUS_CFG_SHIFT; + udc->iface = (reg & USBD_STATUS_INTF_MASK) >> USBD_STATUS_INTF_SHIFT; + udc->alt_iface = (reg & USBD_STATUS_ALTINTF_MASK) >> + USBD_STATUS_ALTINTF_SHIFT; + bcm63xx_ep_setup(udc); +} + +/** + * bcm63xx_update_link_speed - Check to see if the link speed has changed. + * @udc: Reference to the device controller. + * + * The link speed update coincides with a SETUP IRQ. Returns 1 if the + * speed has changed, so that the caller can update the endpoint settings. + */ +static int bcm63xx_update_link_speed(struct bcm63xx_udc *udc) +{ + u32 reg = usbd_readl(udc, USBD_STATUS_REG); + enum usb_device_speed oldspeed = udc->gadget.speed; + + switch ((reg & USBD_STATUS_SPD_MASK) >> USBD_STATUS_SPD_SHIFT) { + case BCM63XX_SPD_HIGH: + udc->gadget.speed = USB_SPEED_HIGH; + break; + case BCM63XX_SPD_FULL: + udc->gadget.speed = USB_SPEED_FULL; + break; + default: + /* this should never happen */ + udc->gadget.speed = USB_SPEED_UNKNOWN; + dev_err(udc->dev, + "received SETUP packet with invalid link speed\n"); + return 0; + } + + if (udc->gadget.speed != oldspeed) { + dev_info(udc->dev, "link up, %s-speed mode\n", + udc->gadget.speed == USB_SPEED_HIGH ? "high" : "full"); + return 1; + } else { + return 0; + } +} + +/** + * bcm63xx_update_wedge - Iterate through wedged endpoints. + * @udc: Reference to the device controller. + * @new_status: true to "refresh" wedge status; false to clear it. + * + * On a SETUP interrupt, we need to manually "refresh" the wedge status + * because the controller hardware is designed to automatically clear + * stalls in response to a CLEAR_FEATURE request from the host. + * + * On a RESET interrupt, we do want to restore all wedged endpoints. + */ +static void bcm63xx_update_wedge(struct bcm63xx_udc *udc, bool new_status) +{ + int i; + + for_each_set_bit(i, &udc->wedgemap, BCM63XX_NUM_EP) { + bcm63xx_set_stall(udc, &udc->bep[i], new_status); + if (!new_status) + clear_bit(i, &udc->wedgemap); + } +} + +/** + * bcm63xx_udc_ctrl_isr - ISR for control path events (USBD). + * @irq: IRQ number (unused). + * @dev_id: Reference to the device controller. + * + * This is where we handle link (VBUS) down, USB reset, speed changes, + * SET_CONFIGURATION, and SET_INTERFACE events. + */ +static irqreturn_t bcm63xx_udc_ctrl_isr(int irq, void *dev_id) +{ + struct bcm63xx_udc *udc = dev_id; + u32 stat; + bool disconnected = false; + + stat = usbd_readl(udc, USBD_EVENT_IRQ_STATUS_REG) & + usbd_readl(udc, USBD_EVENT_IRQ_MASK_REG); + + usbd_writel(udc, stat, USBD_EVENT_IRQ_STATUS_REG); + + spin_lock(&udc->lock); + if (stat & BIT(USBD_EVENT_IRQ_USB_LINK)) { + /* VBUS toggled */ + + if (!(usbd_readl(udc, USBD_EVENTS_REG) & + USBD_EVENTS_USB_LINK_MASK) && + udc->gadget.speed != USB_SPEED_UNKNOWN) + dev_info(udc->dev, "link down\n"); + + udc->gadget.speed = USB_SPEED_UNKNOWN; + disconnected = true; + } + if (stat & BIT(USBD_EVENT_IRQ_USB_RESET)) { + bcm63xx_fifo_setup(udc); + bcm63xx_fifo_reset(udc); + bcm63xx_ep_setup(udc); + + bcm63xx_update_wedge(udc, false); + + udc->ep0_req_reset = 1; + schedule_work(&udc->ep0_wq); + disconnected = true; + } + if (stat & BIT(USBD_EVENT_IRQ_SETUP)) { + if (bcm63xx_update_link_speed(udc)) { + bcm63xx_fifo_setup(udc); + bcm63xx_ep_setup(udc); + } + bcm63xx_update_wedge(udc, true); + } + if (stat & BIT(USBD_EVENT_IRQ_SETCFG)) { + bcm63xx_update_cfg_iface(udc); + udc->ep0_req_set_cfg = 1; + schedule_work(&udc->ep0_wq); + } + if (stat & BIT(USBD_EVENT_IRQ_SETINTF)) { + bcm63xx_update_cfg_iface(udc); + udc->ep0_req_set_iface = 1; + schedule_work(&udc->ep0_wq); + } + spin_unlock(&udc->lock); + + if (disconnected && udc->driver) + udc->driver->disconnect(&udc->gadget); + + return IRQ_HANDLED; +} + +/** + * bcm63xx_udc_data_isr - ISR for data path events (IUDMA). + * @irq: IRQ number (unused). + * @dev_id: Reference to the IUDMA channel that generated the interrupt. + * + * For the two ep0 channels, we have special handling that triggers the + * ep0 worker thread. For normal bulk/intr channels, either queue up + * the next buffer descriptor for the transaction (incomplete transaction), + * or invoke the completion callback (complete transactions). + */ +static irqreturn_t bcm63xx_udc_data_isr(int irq, void *dev_id) +{ + struct iudma_ch *iudma = dev_id; + struct bcm63xx_udc *udc = iudma->udc; + struct bcm63xx_ep *bep; + struct usb_request *req = NULL; + struct bcm63xx_req *breq = NULL; + int rc; + bool is_done = false; + + spin_lock(&udc->lock); + + usb_dmac_writel(udc, ENETDMAC_IR_BUFDONE_MASK, + ENETDMAC_IR_REG(iudma->ch_idx)); + bep = iudma->bep; + rc = iudma_read(udc, iudma); + + /* special handling for EP0 RX (0) and TX (1) */ + if (iudma->ch_idx == IUDMA_EP0_RXCHAN || + iudma->ch_idx == IUDMA_EP0_TXCHAN) { + req = udc->ep0_request; + breq = our_req(req); + + /* a single request could require multiple submissions */ + if (rc >= 0) { + req->actual += rc; + + if (req->actual >= req->length || breq->bd_bytes > rc) { + udc->ep0_req_completed = 1; + is_done = true; + schedule_work(&udc->ep0_wq); + + /* "actual" on a ZLP is 1 byte */ + req->actual = min(req->actual, req->length); + } else { + /* queue up the next BD (same request) */ + iudma_write(udc, iudma, breq); + } + } + } else if (!list_empty(&bep->queue)) { + breq = list_first_entry(&bep->queue, struct bcm63xx_req, queue); + req = &breq->req; + + if (rc >= 0) { + req->actual += rc; + + if (req->actual >= req->length || breq->bd_bytes > rc) { + is_done = true; + list_del(&breq->queue); + + req->actual = min(req->actual, req->length); + + if (!list_empty(&bep->queue)) { + struct bcm63xx_req *next; + + next = list_first_entry(&bep->queue, + struct bcm63xx_req, queue); + iudma_write(udc, iudma, next); + } + } else { + iudma_write(udc, iudma, breq); + } + } + } + spin_unlock(&udc->lock); + + if (is_done) { + usb_gadget_unmap_request(&udc->gadget, req, iudma->is_tx); + if (req->complete) + req->complete(&bep->ep, req); + } + + return IRQ_HANDLED; +} + +/*********************************************************************** + * Debug filesystem + ***********************************************************************/ + +/* + * bcm63xx_usbd_dbg_show - Show USBD controller state. + * @s: seq_file to which the information will be written. + * @p: Unused. + * + * This file nominally shows up as /sys/kernel/debug/bcm63xx_udc/usbd + */ +static int bcm63xx_usbd_dbg_show(struct seq_file *s, void *p) +{ + struct bcm63xx_udc *udc = s->private; + + if (!udc->driver) + return -ENODEV; + + seq_printf(s, "ep0 state: %s\n", + bcm63xx_ep0_state_names[udc->ep0state]); + seq_printf(s, " pending requests: %s%s%s%s%s%s%s\n", + udc->ep0_req_reset ? "reset " : "", + udc->ep0_req_set_cfg ? "set_cfg " : "", + udc->ep0_req_set_iface ? "set_iface " : "", + udc->ep0_req_shutdown ? "shutdown " : "", + udc->ep0_request ? "pending " : "", + udc->ep0_req_completed ? "completed " : "", + udc->ep0_reply ? "reply " : ""); + seq_printf(s, "cfg: %d; iface: %d; alt_iface: %d\n", + udc->cfg, udc->iface, udc->alt_iface); + seq_printf(s, "regs:\n"); + seq_printf(s, " control: %08x; straps: %08x; status: %08x\n", + usbd_readl(udc, USBD_CONTROL_REG), + usbd_readl(udc, USBD_STRAPS_REG), + usbd_readl(udc, USBD_STATUS_REG)); + seq_printf(s, " events: %08x; stall: %08x\n", + usbd_readl(udc, USBD_EVENTS_REG), + usbd_readl(udc, USBD_STALL_REG)); + + return 0; +} + +/* + * bcm63xx_iudma_dbg_show - Show IUDMA status and descriptors. + * @s: seq_file to which the information will be written. + * @p: Unused. + * + * This file nominally shows up as /sys/kernel/debug/bcm63xx_udc/iudma + */ +static int bcm63xx_iudma_dbg_show(struct seq_file *s, void *p) +{ + struct bcm63xx_udc *udc = s->private; + int ch_idx, i; + u32 sram2, sram3; + + if (!udc->driver) + return -ENODEV; + + for (ch_idx = 0; ch_idx < BCM63XX_NUM_IUDMA; ch_idx++) { + struct iudma_ch *iudma = &udc->iudma[ch_idx]; + struct list_head *pos; + + seq_printf(s, "IUDMA channel %d -- ", ch_idx); + switch (iudma_defaults[ch_idx].ep_type) { + case BCMEP_CTRL: + seq_printf(s, "control"); + break; + case BCMEP_BULK: + seq_printf(s, "bulk"); + break; + case BCMEP_INTR: + seq_printf(s, "interrupt"); + break; + } + seq_printf(s, ch_idx & 0x01 ? " tx" : " rx"); + seq_printf(s, " [ep%d]:\n", + max_t(int, iudma_defaults[ch_idx].ep_num, 0)); + seq_printf(s, " cfg: %08x; irqstat: %08x; irqmask: %08x; maxburst: %08x\n", + usb_dmac_readl(udc, ENETDMAC_CHANCFG_REG(ch_idx)), + usb_dmac_readl(udc, ENETDMAC_IR_REG(ch_idx)), + usb_dmac_readl(udc, ENETDMAC_IRMASK_REG(ch_idx)), + usb_dmac_readl(udc, ENETDMAC_MAXBURST_REG(ch_idx))); + + sram2 = usb_dmas_readl(udc, ENETDMAS_SRAM2_REG(ch_idx)); + sram3 = usb_dmas_readl(udc, ENETDMAS_SRAM3_REG(ch_idx)); + seq_printf(s, " base: %08x; index: %04x_%04x; desc: %04x_%04x %08x\n", + usb_dmas_readl(udc, ENETDMAS_RSTART_REG(ch_idx)), + sram2 >> 16, sram2 & 0xffff, + sram3 >> 16, sram3 & 0xffff, + usb_dmas_readl(udc, ENETDMAS_SRAM4_REG(ch_idx))); + seq_printf(s, " desc: %d/%d used", iudma->n_bds_used, + iudma->n_bds); + + if (iudma->bep) { + i = 0; + list_for_each(pos, &iudma->bep->queue) + i++; + seq_printf(s, "; %d queued\n", i); + } else { + seq_printf(s, "\n"); + } + + for (i = 0; i < iudma->n_bds; i++) { + struct bcm_enet_desc *d = &iudma->bd_ring[i]; + + seq_printf(s, " %03x (%02x): len_stat: %04x_%04x; pa %08x", + i * sizeof(*d), i, + d->len_stat >> 16, d->len_stat & 0xffff, + d->address); + if (d == iudma->read_bd) + seq_printf(s, " <write_bd) + seq_printf(s, " <i_private); +} + +static int bcm63xx_iudma_dbg_open(struct inode *inode, struct file *file) +{ + return single_open(file, bcm63xx_iudma_dbg_show, inode->i_private); +} + +static const struct file_operations usbd_dbg_fops = { + .owner = THIS_MODULE, + .open = bcm63xx_usbd_dbg_open, + .llseek = seq_lseek, + .read = seq_read, + .release = single_release, +}; + +static const struct file_operations iudma_dbg_fops = { + .owner = THIS_MODULE, + .open = bcm63xx_iudma_dbg_open, + .llseek = seq_lseek, + .read = seq_read, + .release = single_release, +}; + + +/** + * bcm63xx_udc_init_debugfs - Create debugfs entries. + * @udc: Reference to the device controller. + */ +static void bcm63xx_udc_init_debugfs(struct bcm63xx_udc *udc) +{ + struct dentry *root, *usbd, *iudma; + + if (!IS_ENABLED(CONFIG_USB_GADGET_DEBUG_FS)) + return; + + root = debugfs_create_dir(udc->gadget.name, NULL); + if (IS_ERR(root) || !root) + goto err_root; + + usbd = debugfs_create_file("usbd", 0400, root, udc, + &usbd_dbg_fops); + if (!usbd) + goto err_usbd; + iudma = debugfs_create_file("iudma", 0400, root, udc, + &iudma_dbg_fops); + if (!iudma) + goto err_iudma; + + udc->debugfs_root = root; + udc->debugfs_usbd = usbd; + udc->debugfs_iudma = iudma; + return; +err_iudma: + debugfs_remove(usbd); +err_usbd: + debugfs_remove(root); +err_root: + dev_err(udc->dev, "debugfs is not available\n"); +} + +/** + * bcm63xx_udc_cleanup_debugfs - Remove debugfs entries. + * @udc: Reference to the device controller. + * + * debugfs_remove() is safe to call with a NULL argument. + */ +static void bcm63xx_udc_cleanup_debugfs(struct bcm63xx_udc *udc) +{ + debugfs_remove(udc->debugfs_iudma); + debugfs_remove(udc->debugfs_usbd); + debugfs_remove(udc->debugfs_root); + udc->debugfs_iudma = NULL; + udc->debugfs_usbd = NULL; + udc->debugfs_root = NULL; +} + +/*********************************************************************** + * Driver init/exit + ***********************************************************************/ + +/** + * bcm63xx_udc_gadget_release - Called from device_release(). + * @dev: Unused. + * + * We get a warning if this function doesn't exist, but it's empty because + * we don't have to free any of the memory allocated with the devm_* APIs. + */ +static void bcm63xx_udc_gadget_release(struct device *dev) +{ +} + +/** + * bcm63xx_udc_probe - Initialize a new instance of the UDC. + * @pdev: Platform device struct from the bcm63xx BSP code. + * + * Note that platform data is required, because pd.port_no varies from chip + * to chip and is used to switch the correct USB port to device mode. + */ +static int __devinit bcm63xx_udc_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct bcm63xx_usbd_platform_data *pd = dev->platform_data; + struct bcm63xx_udc *udc; + struct resource *res; + int rc = -ENOMEM, i, irq; + + udc = devm_kzalloc(dev, sizeof(*udc), GFP_KERNEL); + if (!udc) { + dev_err(dev, "cannot allocate memory\n"); + return -ENOMEM; + } + + platform_set_drvdata(pdev, udc); + udc->dev = dev; + udc->pd = pd; + + if (!pd) { + dev_err(dev, "missing platform data\n"); + return -EINVAL; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(dev, "error finding USBD resource\n"); + return -ENXIO; + } + udc->usbd_regs = devm_request_and_ioremap(dev, res); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + if (!res) { + dev_err(dev, "error finding IUDMA resource\n"); + return -ENXIO; + } + udc->iudma_regs = devm_request_and_ioremap(dev, res); + + if (!udc->usbd_regs || !udc->iudma_regs) { + dev_err(dev, "error requesting resources\n"); + return -ENXIO; + } + + spin_lock_init(&udc->lock); + INIT_WORK(&udc->ep0_wq, bcm63xx_ep0_process); + dev_set_name(&udc->gadget.dev, "gadget"); + + udc->gadget.ops = &bcm63xx_udc_ops; + udc->gadget.name = dev_name(dev); + udc->gadget.dev.parent = dev; + udc->gadget.dev.release = bcm63xx_udc_gadget_release; + udc->gadget.dev.dma_mask = dev->dma_mask; + + if (!pd->use_fullspeed && !use_fullspeed) + udc->gadget.max_speed = USB_SPEED_HIGH; + else + udc->gadget.max_speed = USB_SPEED_FULL; + + /* request clocks, allocate buffers, and clear any pending IRQs */ + rc = bcm63xx_init_udc_hw(udc); + if (rc) + return rc; + + rc = -ENXIO; + + /* IRQ resource #0: control interrupt (VBUS, speed, etc.) */ + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(dev, "missing IRQ resource #0\n"); + goto out_uninit; + } + if (devm_request_irq(dev, irq, &bcm63xx_udc_ctrl_isr, 0, + dev_name(dev), udc) < 0) { + dev_err(dev, "error requesting IRQ #%d\n", irq); + goto out_uninit; + } + + /* IRQ resources #1-6: data interrupts for IUDMA channels 0-5 */ + for (i = 0; i < BCM63XX_NUM_IUDMA; i++) { + irq = platform_get_irq(pdev, i + 1); + if (irq < 0) { + dev_err(dev, "missing IRQ resource #%d\n", i + 1); + goto out_uninit; + } + if (devm_request_irq(dev, irq, &bcm63xx_udc_data_isr, 0, + dev_name(dev), &udc->iudma[i]) < 0) { + dev_err(dev, "error requesting IRQ #%d\n", irq); + goto out_uninit; + } + } + + rc = device_register(&udc->gadget.dev); + if (rc) + goto out_uninit; + + bcm63xx_udc_init_debugfs(udc); + rc = usb_add_gadget_udc(dev, &udc->gadget); + if (!rc) + return 0; + + bcm63xx_udc_cleanup_debugfs(udc); + device_unregister(&udc->gadget.dev); +out_uninit: + bcm63xx_uninit_udc_hw(udc); + return rc; +} + +/** + * bcm63xx_udc_remove - Remove the device from the system. + * @pdev: Platform device struct from the bcm63xx BSP code. + */ +static int __devexit bcm63xx_udc_remove(struct platform_device *pdev) +{ + struct bcm63xx_udc *udc = platform_get_drvdata(pdev); + + bcm63xx_udc_cleanup_debugfs(udc); + usb_del_gadget_udc(&udc->gadget); + device_unregister(&udc->gadget.dev); + BUG_ON(udc->driver); + + platform_set_drvdata(pdev, NULL); + bcm63xx_uninit_udc_hw(udc); + + return 0; +} + +static struct platform_driver bcm63xx_udc_driver = { + .probe = bcm63xx_udc_probe, + .remove = __devexit_p(bcm63xx_udc_remove), + .driver = { + .name = DRV_MODULE_NAME, + .owner = THIS_MODULE, + }, +}; +module_platform_driver(bcm63xx_udc_driver); + +MODULE_DESCRIPTION("BCM63xx USB Peripheral Controller"); +MODULE_AUTHOR("Kevin Cernekee "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRV_MODULE_NAME); diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index b8b3a34..0ccca58 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h @@ -28,6 +28,7 @@ #define gadget_is_amd5536udc(g) (!strcmp("amd5536udc", (g)->name)) #define gadget_is_at91(g) (!strcmp("at91_udc", (g)->name)) #define gadget_is_atmel_usba(g) (!strcmp("atmel_usba_udc", (g)->name)) +#define gadget_is_bcm63xx(g) (!strcmp("bcm63xx_udc", (g)->name)) #define gadget_is_ci13xxx_msm(g) (!strcmp("ci13xxx_msm", (g)->name)) #define gadget_is_ci13xxx_pci(g) (!strcmp("ci13xxx_pci", (g)->name)) #define gadget_is_dummy(g) (!strcmp("dummy_udc", (g)->name)) @@ -121,6 +122,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget) return 0x32; else if (gadget_is_lpc32xx(gadget)) return 0x33; + else if (gadget_is_bcm63xx(gadget)) + return 0x34; return -ENOENT; } -- cgit v0.10.2 From 1ba8216f0bc02af6ba70d1108d60eb1b064395e4 Mon Sep 17 00:00:00 2001 From: Venu Byravarasu Date: Wed, 5 Sep 2012 18:50:23 +0530 Subject: usb: move phy driver from mach-tegra to drivers/usb As part of this patch: 1. Moved existing tegra phy driver to drivers/USB directory. 2. Added standard USB phy driver APIs to tegra phy driver. Signed-off-by: Venu Byravarasu Tested-by: Stephen Warren Signed-off-by: Felipe Balbi diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile index c3d7303..0e82b7f 100644 --- a/arch/arm/mach-tegra/Makefile +++ b/arch/arm/mach-tegra/Makefile @@ -21,7 +21,6 @@ obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o obj-$(CONFIG_TEGRA_SYSTEM_DMA) += dma.o obj-$(CONFIG_CPU_FREQ) += cpu-tegra.o obj-$(CONFIG_TEGRA_PCI) += pcie.o -obj-$(CONFIG_USB_SUPPORT) += usb_phy.o obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += board-dt-tegra20.o obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += board-dt-tegra30.o diff --git a/arch/arm/mach-tegra/devices.c b/arch/arm/mach-tegra/devices.c index c70e65f..d8ab762 100644 --- a/arch/arm/mach-tegra/devices.c +++ b/arch/arm/mach-tegra/devices.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include "gpio-names.h" #include "devices.h" diff --git a/arch/arm/mach-tegra/devices.h b/arch/arm/mach-tegra/devices.h index 4f50527..906a61f 100644 --- a/arch/arm/mach-tegra/devices.h +++ b/arch/arm/mach-tegra/devices.h @@ -22,7 +22,7 @@ #include #include -#include +#include extern struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config; diff --git a/arch/arm/mach-tegra/include/mach/usb_phy.h b/arch/arm/mach-tegra/include/mach/usb_phy.h deleted file mode 100644 index 935ce9f..0000000 --- a/arch/arm/mach-tegra/include/mach/usb_phy.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * arch/arm/mach-tegra/include/mach/usb_phy.h - * - * Copyright (C) 2010 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef __MACH_USB_PHY_H -#define __MACH_USB_PHY_H - -#include -#include - -struct tegra_utmip_config { - u8 hssync_start_delay; - u8 elastic_limit; - u8 idle_wait_delay; - u8 term_range_adj; - u8 xcvr_setup; - u8 xcvr_lsfslew; - u8 xcvr_lsrslew; -}; - -struct tegra_ulpi_config { - int reset_gpio; - const char *clk; -}; - -enum tegra_usb_phy_port_speed { - TEGRA_USB_PHY_PORT_SPEED_FULL = 0, - TEGRA_USB_PHY_PORT_SPEED_LOW, - TEGRA_USB_PHY_PORT_SPEED_HIGH, -}; - -enum tegra_usb_phy_mode { - TEGRA_USB_PHY_MODE_DEVICE, - TEGRA_USB_PHY_MODE_HOST, -}; - -struct tegra_xtal_freq; - -struct tegra_usb_phy { - int instance; - const struct tegra_xtal_freq *freq; - void __iomem *regs; - void __iomem *pad_regs; - struct clk *clk; - struct clk *pll_u; - struct clk *pad_clk; - enum tegra_usb_phy_mode mode; - void *config; - struct usb_phy *ulpi; -}; - -struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, - void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode); - -int tegra_usb_phy_power_on(struct tegra_usb_phy *phy); - -void tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy); - -void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy); - -void tegra_usb_phy_power_off(struct tegra_usb_phy *phy); - -void tegra_usb_phy_preresume(struct tegra_usb_phy *phy); - -void tegra_usb_phy_postresume(struct tegra_usb_phy *phy); - -void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy, - enum tegra_usb_phy_port_speed port_speed); - -void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy); - -void tegra_usb_phy_close(struct tegra_usb_phy *phy); - -#endif /* __MACH_USB_PHY_H */ diff --git a/arch/arm/mach-tegra/usb_phy.c b/arch/arm/mach-tegra/usb_phy.c deleted file mode 100644 index 022b33a..0000000 --- a/arch/arm/mach-tegra/usb_phy.c +++ /dev/null @@ -1,817 +0,0 @@ -/* - * arch/arm/mach-tegra/usb_phy.c - * - * Copyright (C) 2010 Google, Inc. - * - * Author: - * Erik Gilling - * Benoit Goby - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define ULPI_VIEWPORT 0x170 - -#define USB_PORTSC1 0x184 -#define USB_PORTSC1_PTS(x) (((x) & 0x3) << 30) -#define USB_PORTSC1_PSPD(x) (((x) & 0x3) << 26) -#define USB_PORTSC1_PHCD (1 << 23) -#define USB_PORTSC1_WKOC (1 << 22) -#define USB_PORTSC1_WKDS (1 << 21) -#define USB_PORTSC1_WKCN (1 << 20) -#define USB_PORTSC1_PTC(x) (((x) & 0xf) << 16) -#define USB_PORTSC1_PP (1 << 12) -#define USB_PORTSC1_SUSP (1 << 7) -#define USB_PORTSC1_PE (1 << 2) -#define USB_PORTSC1_CCS (1 << 0) - -#define USB_SUSP_CTRL 0x400 -#define USB_WAKE_ON_CNNT_EN_DEV (1 << 3) -#define USB_WAKE_ON_DISCON_EN_DEV (1 << 4) -#define USB_SUSP_CLR (1 << 5) -#define USB_PHY_CLK_VALID (1 << 7) -#define UTMIP_RESET (1 << 11) -#define UHSIC_RESET (1 << 11) -#define UTMIP_PHY_ENABLE (1 << 12) -#define ULPI_PHY_ENABLE (1 << 13) -#define USB_SUSP_SET (1 << 14) -#define USB_WAKEUP_DEBOUNCE_COUNT(x) (((x) & 0x7) << 16) - -#define USB1_LEGACY_CTRL 0x410 -#define USB1_NO_LEGACY_MODE (1 << 0) -#define USB1_VBUS_SENSE_CTL_MASK (3 << 1) -#define USB1_VBUS_SENSE_CTL_VBUS_WAKEUP (0 << 1) -#define USB1_VBUS_SENSE_CTL_AB_SESS_VLD_OR_VBUS_WAKEUP \ - (1 << 1) -#define USB1_VBUS_SENSE_CTL_AB_SESS_VLD (2 << 1) -#define USB1_VBUS_SENSE_CTL_A_SESS_VLD (3 << 1) - -#define ULPI_TIMING_CTRL_0 0x424 -#define ULPI_OUTPUT_PINMUX_BYP (1 << 10) -#define ULPI_CLKOUT_PINMUX_BYP (1 << 11) - -#define ULPI_TIMING_CTRL_1 0x428 -#define ULPI_DATA_TRIMMER_LOAD (1 << 0) -#define ULPI_DATA_TRIMMER_SEL(x) (((x) & 0x7) << 1) -#define ULPI_STPDIRNXT_TRIMMER_LOAD (1 << 16) -#define ULPI_STPDIRNXT_TRIMMER_SEL(x) (((x) & 0x7) << 17) -#define ULPI_DIR_TRIMMER_LOAD (1 << 24) -#define ULPI_DIR_TRIMMER_SEL(x) (((x) & 0x7) << 25) - -#define UTMIP_PLL_CFG1 0x804 -#define UTMIP_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0) -#define UTMIP_PLLU_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 27) - -#define UTMIP_XCVR_CFG0 0x808 -#define UTMIP_XCVR_SETUP(x) (((x) & 0xf) << 0) -#define UTMIP_XCVR_LSRSLEW(x) (((x) & 0x3) << 8) -#define UTMIP_XCVR_LSFSLEW(x) (((x) & 0x3) << 10) -#define UTMIP_FORCE_PD_POWERDOWN (1 << 14) -#define UTMIP_FORCE_PD2_POWERDOWN (1 << 16) -#define UTMIP_FORCE_PDZI_POWERDOWN (1 << 18) -#define UTMIP_XCVR_HSSLEW_MSB(x) (((x) & 0x7f) << 25) - -#define UTMIP_BIAS_CFG0 0x80c -#define UTMIP_OTGPD (1 << 11) -#define UTMIP_BIASPD (1 << 10) - -#define UTMIP_HSRX_CFG0 0x810 -#define UTMIP_ELASTIC_LIMIT(x) (((x) & 0x1f) << 10) -#define UTMIP_IDLE_WAIT(x) (((x) & 0x1f) << 15) - -#define UTMIP_HSRX_CFG1 0x814 -#define UTMIP_HS_SYNC_START_DLY(x) (((x) & 0x1f) << 1) - -#define UTMIP_TX_CFG0 0x820 -#define UTMIP_FS_PREABMLE_J (1 << 19) -#define UTMIP_HS_DISCON_DISABLE (1 << 8) - -#define UTMIP_MISC_CFG0 0x824 -#define UTMIP_DPDM_OBSERVE (1 << 26) -#define UTMIP_DPDM_OBSERVE_SEL(x) (((x) & 0xf) << 27) -#define UTMIP_DPDM_OBSERVE_SEL_FS_J UTMIP_DPDM_OBSERVE_SEL(0xf) -#define UTMIP_DPDM_OBSERVE_SEL_FS_K UTMIP_DPDM_OBSERVE_SEL(0xe) -#define UTMIP_DPDM_OBSERVE_SEL_FS_SE1 UTMIP_DPDM_OBSERVE_SEL(0xd) -#define UTMIP_DPDM_OBSERVE_SEL_FS_SE0 UTMIP_DPDM_OBSERVE_SEL(0xc) -#define UTMIP_SUSPEND_EXIT_ON_EDGE (1 << 22) - -#define UTMIP_MISC_CFG1 0x828 -#define UTMIP_PLL_ACTIVE_DLY_COUNT(x) (((x) & 0x1f) << 18) -#define UTMIP_PLLU_STABLE_COUNT(x) (((x) & 0xfff) << 6) - -#define UTMIP_DEBOUNCE_CFG0 0x82c -#define UTMIP_BIAS_DEBOUNCE_A(x) (((x) & 0xffff) << 0) - -#define UTMIP_BAT_CHRG_CFG0 0x830 -#define UTMIP_PD_CHRG (1 << 0) - -#define UTMIP_SPARE_CFG0 0x834 -#define FUSE_SETUP_SEL (1 << 3) - -#define UTMIP_XCVR_CFG1 0x838 -#define UTMIP_FORCE_PDDISC_POWERDOWN (1 << 0) -#define UTMIP_FORCE_PDCHRP_POWERDOWN (1 << 2) -#define UTMIP_FORCE_PDDR_POWERDOWN (1 << 4) -#define UTMIP_XCVR_TERM_RANGE_ADJ(x) (((x) & 0xf) << 18) - -#define UTMIP_BIAS_CFG1 0x83c -#define UTMIP_BIAS_PDTRK_COUNT(x) (((x) & 0x1f) << 3) - -static DEFINE_SPINLOCK(utmip_pad_lock); -static int utmip_pad_count; - -struct tegra_xtal_freq { - int freq; - u8 enable_delay; - u8 stable_count; - u8 active_delay; - u8 xtal_freq_count; - u16 debounce; -}; - -static const struct tegra_xtal_freq tegra_freq_table[] = { - { - .freq = 12000000, - .enable_delay = 0x02, - .stable_count = 0x2F, - .active_delay = 0x04, - .xtal_freq_count = 0x76, - .debounce = 0x7530, - }, - { - .freq = 13000000, - .enable_delay = 0x02, - .stable_count = 0x33, - .active_delay = 0x05, - .xtal_freq_count = 0x7F, - .debounce = 0x7EF4, - }, - { - .freq = 19200000, - .enable_delay = 0x03, - .stable_count = 0x4B, - .active_delay = 0x06, - .xtal_freq_count = 0xBB, - .debounce = 0xBB80, - }, - { - .freq = 26000000, - .enable_delay = 0x04, - .stable_count = 0x66, - .active_delay = 0x09, - .xtal_freq_count = 0xFE, - .debounce = 0xFDE8, - }, -}; - -static struct tegra_utmip_config utmip_default[] = { - [0] = { - .hssync_start_delay = 9, - .idle_wait_delay = 17, - .elastic_limit = 16, - .term_range_adj = 6, - .xcvr_setup = 9, - .xcvr_lsfslew = 1, - .xcvr_lsrslew = 1, - }, - [2] = { - .hssync_start_delay = 9, - .idle_wait_delay = 17, - .elastic_limit = 16, - .term_range_adj = 6, - .xcvr_setup = 9, - .xcvr_lsfslew = 2, - .xcvr_lsrslew = 2, - }, -}; - -static inline bool phy_is_ulpi(struct tegra_usb_phy *phy) -{ - return (phy->instance == 1); -} - -static int utmip_pad_open(struct tegra_usb_phy *phy) -{ - phy->pad_clk = clk_get_sys("utmip-pad", NULL); - if (IS_ERR(phy->pad_clk)) { - pr_err("%s: can't get utmip pad clock\n", __func__); - return PTR_ERR(phy->pad_clk); - } - - if (phy->instance == 0) { - phy->pad_regs = phy->regs; - } else { - phy->pad_regs = ioremap(TEGRA_USB_BASE, TEGRA_USB_SIZE); - if (!phy->pad_regs) { - pr_err("%s: can't remap usb registers\n", __func__); - clk_put(phy->pad_clk); - return -ENOMEM; - } - } - return 0; -} - -static void utmip_pad_close(struct tegra_usb_phy *phy) -{ - if (phy->instance != 0) - iounmap(phy->pad_regs); - clk_put(phy->pad_clk); -} - -static void utmip_pad_power_on(struct tegra_usb_phy *phy) -{ - unsigned long val, flags; - void __iomem *base = phy->pad_regs; - - clk_prepare_enable(phy->pad_clk); - - spin_lock_irqsave(&utmip_pad_lock, flags); - - if (utmip_pad_count++ == 0) { - val = readl(base + UTMIP_BIAS_CFG0); - val &= ~(UTMIP_OTGPD | UTMIP_BIASPD); - writel(val, base + UTMIP_BIAS_CFG0); - } - - spin_unlock_irqrestore(&utmip_pad_lock, flags); - - clk_disable_unprepare(phy->pad_clk); -} - -static int utmip_pad_power_off(struct tegra_usb_phy *phy) -{ - unsigned long val, flags; - void __iomem *base = phy->pad_regs; - - if (!utmip_pad_count) { - pr_err("%s: utmip pad already powered off\n", __func__); - return -EINVAL; - } - - clk_prepare_enable(phy->pad_clk); - - spin_lock_irqsave(&utmip_pad_lock, flags); - - if (--utmip_pad_count == 0) { - val = readl(base + UTMIP_BIAS_CFG0); - val |= UTMIP_OTGPD | UTMIP_BIASPD; - writel(val, base + UTMIP_BIAS_CFG0); - } - - spin_unlock_irqrestore(&utmip_pad_lock, flags); - - clk_disable_unprepare(phy->pad_clk); - - return 0; -} - -static int utmi_wait_register(void __iomem *reg, u32 mask, u32 result) -{ - unsigned long timeout = 2000; - do { - if ((readl(reg) & mask) == result) - return 0; - udelay(1); - timeout--; - } while (timeout); - return -1; -} - -static void utmi_phy_clk_disable(struct tegra_usb_phy *phy) -{ - unsigned long val; - void __iomem *base = phy->regs; - - if (phy->instance == 0) { - val = readl(base + USB_SUSP_CTRL); - val |= USB_SUSP_SET; - writel(val, base + USB_SUSP_CTRL); - - udelay(10); - - val = readl(base + USB_SUSP_CTRL); - val &= ~USB_SUSP_SET; - writel(val, base + USB_SUSP_CTRL); - } - - if (phy->instance == 2) { - val = readl(base + USB_PORTSC1); - val |= USB_PORTSC1_PHCD; - writel(val, base + USB_PORTSC1); - } - - if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0) - pr_err("%s: timeout waiting for phy to stabilize\n", __func__); -} - -static void utmi_phy_clk_enable(struct tegra_usb_phy *phy) -{ - unsigned long val; - void __iomem *base = phy->regs; - - if (phy->instance == 0) { - val = readl(base + USB_SUSP_CTRL); - val |= USB_SUSP_CLR; - writel(val, base + USB_SUSP_CTRL); - - udelay(10); - - val = readl(base + USB_SUSP_CTRL); - val &= ~USB_SUSP_CLR; - writel(val, base + USB_SUSP_CTRL); - } - - if (phy->instance == 2) { - val = readl(base + USB_PORTSC1); - val &= ~USB_PORTSC1_PHCD; - writel(val, base + USB_PORTSC1); - } - - if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, - USB_PHY_CLK_VALID)) - pr_err("%s: timeout waiting for phy to stabilize\n", __func__); -} - -static int utmi_phy_power_on(struct tegra_usb_phy *phy) -{ - unsigned long val; - void __iomem *base = phy->regs; - struct tegra_utmip_config *config = phy->config; - - val = readl(base + USB_SUSP_CTRL); - val |= UTMIP_RESET; - writel(val, base + USB_SUSP_CTRL); - - if (phy->instance == 0) { - val = readl(base + USB1_LEGACY_CTRL); - val |= USB1_NO_LEGACY_MODE; - writel(val, base + USB1_LEGACY_CTRL); - } - - val = readl(base + UTMIP_TX_CFG0); - val &= ~UTMIP_FS_PREABMLE_J; - writel(val, base + UTMIP_TX_CFG0); - - val = readl(base + UTMIP_HSRX_CFG0); - val &= ~(UTMIP_IDLE_WAIT(~0) | UTMIP_ELASTIC_LIMIT(~0)); - val |= UTMIP_IDLE_WAIT(config->idle_wait_delay); - val |= UTMIP_ELASTIC_LIMIT(config->elastic_limit); - writel(val, base + UTMIP_HSRX_CFG0); - - val = readl(base + UTMIP_HSRX_CFG1); - val &= ~UTMIP_HS_SYNC_START_DLY(~0); - val |= UTMIP_HS_SYNC_START_DLY(config->hssync_start_delay); - writel(val, base + UTMIP_HSRX_CFG1); - - val = readl(base + UTMIP_DEBOUNCE_CFG0); - val &= ~UTMIP_BIAS_DEBOUNCE_A(~0); - val |= UTMIP_BIAS_DEBOUNCE_A(phy->freq->debounce); - writel(val, base + UTMIP_DEBOUNCE_CFG0); - - val = readl(base + UTMIP_MISC_CFG0); - val &= ~UTMIP_SUSPEND_EXIT_ON_EDGE; - writel(val, base + UTMIP_MISC_CFG0); - - val = readl(base + UTMIP_MISC_CFG1); - val &= ~(UTMIP_PLL_ACTIVE_DLY_COUNT(~0) | UTMIP_PLLU_STABLE_COUNT(~0)); - val |= UTMIP_PLL_ACTIVE_DLY_COUNT(phy->freq->active_delay) | - UTMIP_PLLU_STABLE_COUNT(phy->freq->stable_count); - writel(val, base + UTMIP_MISC_CFG1); - - val = readl(base + UTMIP_PLL_CFG1); - val &= ~(UTMIP_XTAL_FREQ_COUNT(~0) | UTMIP_PLLU_ENABLE_DLY_COUNT(~0)); - val |= UTMIP_XTAL_FREQ_COUNT(phy->freq->xtal_freq_count) | - UTMIP_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay); - writel(val, base + UTMIP_PLL_CFG1); - - if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) { - val = readl(base + USB_SUSP_CTRL); - val &= ~(USB_WAKE_ON_CNNT_EN_DEV | USB_WAKE_ON_DISCON_EN_DEV); - writel(val, base + USB_SUSP_CTRL); - } - - utmip_pad_power_on(phy); - - val = readl(base + UTMIP_XCVR_CFG0); - val &= ~(UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN | - UTMIP_FORCE_PDZI_POWERDOWN | UTMIP_XCVR_SETUP(~0) | - UTMIP_XCVR_LSFSLEW(~0) | UTMIP_XCVR_LSRSLEW(~0) | - UTMIP_XCVR_HSSLEW_MSB(~0)); - val |= UTMIP_XCVR_SETUP(config->xcvr_setup); - val |= UTMIP_XCVR_LSFSLEW(config->xcvr_lsfslew); - val |= UTMIP_XCVR_LSRSLEW(config->xcvr_lsrslew); - writel(val, base + UTMIP_XCVR_CFG0); - - val = readl(base + UTMIP_XCVR_CFG1); - val &= ~(UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN | - UTMIP_FORCE_PDDR_POWERDOWN | UTMIP_XCVR_TERM_RANGE_ADJ(~0)); - val |= UTMIP_XCVR_TERM_RANGE_ADJ(config->term_range_adj); - writel(val, base + UTMIP_XCVR_CFG1); - - val = readl(base + UTMIP_BAT_CHRG_CFG0); - val &= ~UTMIP_PD_CHRG; - writel(val, base + UTMIP_BAT_CHRG_CFG0); - - val = readl(base + UTMIP_BIAS_CFG1); - val &= ~UTMIP_BIAS_PDTRK_COUNT(~0); - val |= UTMIP_BIAS_PDTRK_COUNT(0x5); - writel(val, base + UTMIP_BIAS_CFG1); - - if (phy->instance == 0) { - val = readl(base + UTMIP_SPARE_CFG0); - if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) - val &= ~FUSE_SETUP_SEL; - else - val |= FUSE_SETUP_SEL; - writel(val, base + UTMIP_SPARE_CFG0); - } - - if (phy->instance == 2) { - val = readl(base + USB_SUSP_CTRL); - val |= UTMIP_PHY_ENABLE; - writel(val, base + USB_SUSP_CTRL); - } - - val = readl(base + USB_SUSP_CTRL); - val &= ~UTMIP_RESET; - writel(val, base + USB_SUSP_CTRL); - - if (phy->instance == 0) { - val = readl(base + USB1_LEGACY_CTRL); - val &= ~USB1_VBUS_SENSE_CTL_MASK; - val |= USB1_VBUS_SENSE_CTL_A_SESS_VLD; - writel(val, base + USB1_LEGACY_CTRL); - - val = readl(base + USB_SUSP_CTRL); - val &= ~USB_SUSP_SET; - writel(val, base + USB_SUSP_CTRL); - } - - utmi_phy_clk_enable(phy); - - if (phy->instance == 2) { - val = readl(base + USB_PORTSC1); - val &= ~USB_PORTSC1_PTS(~0); - writel(val, base + USB_PORTSC1); - } - - return 0; -} - -static void utmi_phy_power_off(struct tegra_usb_phy *phy) -{ - unsigned long val; - void __iomem *base = phy->regs; - - utmi_phy_clk_disable(phy); - - if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) { - val = readl(base + USB_SUSP_CTRL); - val &= ~USB_WAKEUP_DEBOUNCE_COUNT(~0); - val |= USB_WAKE_ON_CNNT_EN_DEV | USB_WAKEUP_DEBOUNCE_COUNT(5); - writel(val, base + USB_SUSP_CTRL); - } - - val = readl(base + USB_SUSP_CTRL); - val |= UTMIP_RESET; - writel(val, base + USB_SUSP_CTRL); - - val = readl(base + UTMIP_BAT_CHRG_CFG0); - val |= UTMIP_PD_CHRG; - writel(val, base + UTMIP_BAT_CHRG_CFG0); - - val = readl(base + UTMIP_XCVR_CFG0); - val |= UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN | - UTMIP_FORCE_PDZI_POWERDOWN; - writel(val, base + UTMIP_XCVR_CFG0); - - val = readl(base + UTMIP_XCVR_CFG1); - val |= UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN | - UTMIP_FORCE_PDDR_POWERDOWN; - writel(val, base + UTMIP_XCVR_CFG1); - - utmip_pad_power_off(phy); -} - -static void utmi_phy_preresume(struct tegra_usb_phy *phy) -{ - unsigned long val; - void __iomem *base = phy->regs; - - val = readl(base + UTMIP_TX_CFG0); - val |= UTMIP_HS_DISCON_DISABLE; - writel(val, base + UTMIP_TX_CFG0); -} - -static void utmi_phy_postresume(struct tegra_usb_phy *phy) -{ - unsigned long val; - void __iomem *base = phy->regs; - - val = readl(base + UTMIP_TX_CFG0); - val &= ~UTMIP_HS_DISCON_DISABLE; - writel(val, base + UTMIP_TX_CFG0); -} - -static void utmi_phy_restore_start(struct tegra_usb_phy *phy, - enum tegra_usb_phy_port_speed port_speed) -{ - unsigned long val; - void __iomem *base = phy->regs; - - val = readl(base + UTMIP_MISC_CFG0); - val &= ~UTMIP_DPDM_OBSERVE_SEL(~0); - if (port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW) - val |= UTMIP_DPDM_OBSERVE_SEL_FS_K; - else - val |= UTMIP_DPDM_OBSERVE_SEL_FS_J; - writel(val, base + UTMIP_MISC_CFG0); - udelay(1); - - val = readl(base + UTMIP_MISC_CFG0); - val |= UTMIP_DPDM_OBSERVE; - writel(val, base + UTMIP_MISC_CFG0); - udelay(10); -} - -static void utmi_phy_restore_end(struct tegra_usb_phy *phy) -{ - unsigned long val; - void __iomem *base = phy->regs; - - val = readl(base + UTMIP_MISC_CFG0); - val &= ~UTMIP_DPDM_OBSERVE; - writel(val, base + UTMIP_MISC_CFG0); - udelay(10); -} - -static int ulpi_phy_power_on(struct tegra_usb_phy *phy) -{ - int ret; - unsigned long val; - void __iomem *base = phy->regs; - struct tegra_ulpi_config *config = phy->config; - - gpio_direction_output(config->reset_gpio, 0); - msleep(5); - gpio_direction_output(config->reset_gpio, 1); - - clk_prepare_enable(phy->clk); - msleep(1); - - val = readl(base + USB_SUSP_CTRL); - val |= UHSIC_RESET; - writel(val, base + USB_SUSP_CTRL); - - val = readl(base + ULPI_TIMING_CTRL_0); - val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP; - writel(val, base + ULPI_TIMING_CTRL_0); - - val = readl(base + USB_SUSP_CTRL); - val |= ULPI_PHY_ENABLE; - writel(val, base + USB_SUSP_CTRL); - - val = 0; - writel(val, base + ULPI_TIMING_CTRL_1); - - val |= ULPI_DATA_TRIMMER_SEL(4); - val |= ULPI_STPDIRNXT_TRIMMER_SEL(4); - val |= ULPI_DIR_TRIMMER_SEL(4); - writel(val, base + ULPI_TIMING_CTRL_1); - udelay(10); - - val |= ULPI_DATA_TRIMMER_LOAD; - val |= ULPI_STPDIRNXT_TRIMMER_LOAD; - val |= ULPI_DIR_TRIMMER_LOAD; - writel(val, base + ULPI_TIMING_CTRL_1); - - /* Fix VbusInvalid due to floating VBUS */ - ret = usb_phy_io_write(phy->ulpi, 0x40, 0x08); - if (ret) { - pr_err("%s: ulpi write failed\n", __func__); - return ret; - } - - ret = usb_phy_io_write(phy->ulpi, 0x80, 0x0B); - if (ret) { - pr_err("%s: ulpi write failed\n", __func__); - return ret; - } - - val = readl(base + USB_PORTSC1); - val |= USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN; - writel(val, base + USB_PORTSC1); - - val = readl(base + USB_SUSP_CTRL); - val |= USB_SUSP_CLR; - writel(val, base + USB_SUSP_CTRL); - udelay(100); - - val = readl(base + USB_SUSP_CTRL); - val &= ~USB_SUSP_CLR; - writel(val, base + USB_SUSP_CTRL); - - return 0; -} - -static void ulpi_phy_power_off(struct tegra_usb_phy *phy) -{ - unsigned long val; - void __iomem *base = phy->regs; - struct tegra_ulpi_config *config = phy->config; - - /* Clear WKCN/WKDS/WKOC wake-on events that can cause the USB - * Controller to immediately bring the ULPI PHY out of low power - */ - val = readl(base + USB_PORTSC1); - val &= ~(USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN); - writel(val, base + USB_PORTSC1); - - gpio_direction_output(config->reset_gpio, 0); - clk_disable(phy->clk); -} - -struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, - void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode) -{ - struct tegra_usb_phy *phy; - struct tegra_ulpi_config *ulpi_config; - unsigned long parent_rate; - int i; - int err; - - phy = kmalloc(sizeof(struct tegra_usb_phy), GFP_KERNEL); - if (!phy) - return ERR_PTR(-ENOMEM); - - phy->instance = instance; - phy->regs = regs; - phy->config = config; - phy->mode = phy_mode; - - if (!phy->config) { - if (phy_is_ulpi(phy)) { - pr_err("%s: ulpi phy configuration missing", __func__); - err = -EINVAL; - goto err0; - } else { - phy->config = &utmip_default[instance]; - } - } - - phy->pll_u = clk_get_sys(NULL, "pll_u"); - if (IS_ERR(phy->pll_u)) { - pr_err("Can't get pll_u clock\n"); - err = PTR_ERR(phy->pll_u); - goto err0; - } - clk_prepare_enable(phy->pll_u); - - parent_rate = clk_get_rate(clk_get_parent(phy->pll_u)); - for (i = 0; i < ARRAY_SIZE(tegra_freq_table); i++) { - if (tegra_freq_table[i].freq == parent_rate) { - phy->freq = &tegra_freq_table[i]; - break; - } - } - if (!phy->freq) { - pr_err("invalid pll_u parent rate %ld\n", parent_rate); - err = -EINVAL; - goto err1; - } - - if (phy_is_ulpi(phy)) { - ulpi_config = config; - phy->clk = clk_get_sys(NULL, ulpi_config->clk); - if (IS_ERR(phy->clk)) { - pr_err("%s: can't get ulpi clock\n", __func__); - err = -ENXIO; - goto err1; - } - if (!gpio_is_valid(ulpi_config->reset_gpio)) - ulpi_config->reset_gpio = - of_get_named_gpio(dev->of_node, - "nvidia,phy-reset-gpio", 0); - if (!gpio_is_valid(ulpi_config->reset_gpio)) { - pr_err("%s: invalid reset gpio: %d\n", __func__, - ulpi_config->reset_gpio); - err = -EINVAL; - goto err1; - } - gpio_request(ulpi_config->reset_gpio, "ulpi_phy_reset_b"); - gpio_direction_output(ulpi_config->reset_gpio, 0); - phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0); - phy->ulpi->io_priv = regs + ULPI_VIEWPORT; - } else { - err = utmip_pad_open(phy); - if (err < 0) - goto err1; - } - - return phy; - -err1: - clk_disable_unprepare(phy->pll_u); - clk_put(phy->pll_u); -err0: - kfree(phy); - return ERR_PTR(err); -} -EXPORT_SYMBOL_GPL(tegra_usb_phy_open); - -int tegra_usb_phy_power_on(struct tegra_usb_phy *phy) -{ - if (phy_is_ulpi(phy)) - return ulpi_phy_power_on(phy); - else - return utmi_phy_power_on(phy); -} -EXPORT_SYMBOL_GPL(tegra_usb_phy_power_on); - -void tegra_usb_phy_power_off(struct tegra_usb_phy *phy) -{ - if (phy_is_ulpi(phy)) - ulpi_phy_power_off(phy); - else - utmi_phy_power_off(phy); -} -EXPORT_SYMBOL_GPL(tegra_usb_phy_power_off); - -void tegra_usb_phy_preresume(struct tegra_usb_phy *phy) -{ - if (!phy_is_ulpi(phy)) - utmi_phy_preresume(phy); -} -EXPORT_SYMBOL_GPL(tegra_usb_phy_preresume); - -void tegra_usb_phy_postresume(struct tegra_usb_phy *phy) -{ - if (!phy_is_ulpi(phy)) - utmi_phy_postresume(phy); -} -EXPORT_SYMBOL_GPL(tegra_usb_phy_postresume); - -void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy, - enum tegra_usb_phy_port_speed port_speed) -{ - if (!phy_is_ulpi(phy)) - utmi_phy_restore_start(phy, port_speed); -} -EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_start); - -void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy) -{ - if (!phy_is_ulpi(phy)) - utmi_phy_restore_end(phy); -} -EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_end); - -void tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy) -{ - if (!phy_is_ulpi(phy)) - utmi_phy_clk_disable(phy); -} -EXPORT_SYMBOL_GPL(tegra_usb_phy_clk_disable); - -void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy) -{ - if (!phy_is_ulpi(phy)) - utmi_phy_clk_enable(phy); -} -EXPORT_SYMBOL_GPL(tegra_usb_phy_clk_enable); - -void tegra_usb_phy_close(struct tegra_usb_phy *phy) -{ - if (phy_is_ulpi(phy)) - clk_put(phy->clk); - else - utmip_pad_close(phy); - clk_disable_unprepare(phy->pll_u); - clk_put(phy->pll_u); - kfree(phy); -} -EXPORT_SYMBOL_GPL(tegra_usb_phy_close); diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c index 950e95e..65408f7 100644 --- a/drivers/usb/host/ehci-tegra.c +++ b/drivers/usb/host/ehci-tegra.c @@ -27,7 +27,7 @@ #include #include -#include +#include #include #define TEGRA_USB_DMA_ALIGN 32 @@ -49,7 +49,7 @@ static void tegra_ehci_power_up(struct usb_hcd *hcd) clk_prepare_enable(tegra->emc_clk); clk_prepare_enable(tegra->clk); - tegra_usb_phy_power_on(tegra->phy); + usb_phy_set_suspend(&tegra->phy->u_phy, 0); tegra->host_resumed = 1; } @@ -58,7 +58,7 @@ static void tegra_ehci_power_down(struct usb_hcd *hcd) struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller); tegra->host_resumed = 0; - tegra_usb_phy_power_off(tegra->phy); + usb_phy_set_suspend(&tegra->phy->u_phy, 1); clk_disable_unprepare(tegra->clk); clk_disable_unprepare(tegra->emc_clk); } @@ -715,7 +715,9 @@ static int tegra_ehci_probe(struct platform_device *pdev) goto fail_phy; } - err = tegra_usb_phy_power_on(tegra->phy); + usb_phy_init(&tegra->phy->u_phy); + + err = usb_phy_set_suspend(&tegra->phy->u_phy, 0); if (err) { dev_err(&pdev->dev, "Failed to power on the phy\n"); goto fail; @@ -762,7 +764,7 @@ fail: usb_put_phy(tegra->transceiver); } #endif - tegra_usb_phy_close(tegra->phy); + usb_phy_shutdown(&tegra->phy->u_phy); fail_phy: iounmap(hcd->regs); fail_io: @@ -801,7 +803,7 @@ static int tegra_ehci_remove(struct platform_device *pdev) usb_remove_hcd(hcd); usb_put_hcd(hcd); - tegra_usb_phy_close(tegra->phy); + usb_phy_shutdown(&tegra->phy->u_phy); iounmap(hcd->regs); clk_disable_unprepare(tegra->clk); diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index cf38f08..bb948fb 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -6,3 +6,4 @@ ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG obj-$(CONFIG_USB_ISP1301) += isp1301.o obj-$(CONFIG_MV_U3D_PHY) += mv_u3d_phy.o +obj-$(CONFIG_USB_EHCI_TEGRA) += tegra_usb_phy.o diff --git a/drivers/usb/phy/tegra_usb_phy.c b/drivers/usb/phy/tegra_usb_phy.c new file mode 100644 index 0000000..4739903 --- /dev/null +++ b/drivers/usb/phy/tegra_usb_phy.c @@ -0,0 +1,839 @@ +/* + * Copyright (C) 2010 Google, Inc. + * + * Author: + * Erik Gilling + * Benoit Goby + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ULPI_VIEWPORT 0x170 + +#define USB_PORTSC1 0x184 +#define USB_PORTSC1_PTS(x) (((x) & 0x3) << 30) +#define USB_PORTSC1_PSPD(x) (((x) & 0x3) << 26) +#define USB_PORTSC1_PHCD (1 << 23) +#define USB_PORTSC1_WKOC (1 << 22) +#define USB_PORTSC1_WKDS (1 << 21) +#define USB_PORTSC1_WKCN (1 << 20) +#define USB_PORTSC1_PTC(x) (((x) & 0xf) << 16) +#define USB_PORTSC1_PP (1 << 12) +#define USB_PORTSC1_SUSP (1 << 7) +#define USB_PORTSC1_PE (1 << 2) +#define USB_PORTSC1_CCS (1 << 0) + +#define USB_SUSP_CTRL 0x400 +#define USB_WAKE_ON_CNNT_EN_DEV (1 << 3) +#define USB_WAKE_ON_DISCON_EN_DEV (1 << 4) +#define USB_SUSP_CLR (1 << 5) +#define USB_PHY_CLK_VALID (1 << 7) +#define UTMIP_RESET (1 << 11) +#define UHSIC_RESET (1 << 11) +#define UTMIP_PHY_ENABLE (1 << 12) +#define ULPI_PHY_ENABLE (1 << 13) +#define USB_SUSP_SET (1 << 14) +#define USB_WAKEUP_DEBOUNCE_COUNT(x) (((x) & 0x7) << 16) + +#define USB1_LEGACY_CTRL 0x410 +#define USB1_NO_LEGACY_MODE (1 << 0) +#define USB1_VBUS_SENSE_CTL_MASK (3 << 1) +#define USB1_VBUS_SENSE_CTL_VBUS_WAKEUP (0 << 1) +#define USB1_VBUS_SENSE_CTL_AB_SESS_VLD_OR_VBUS_WAKEUP \ + (1 << 1) +#define USB1_VBUS_SENSE_CTL_AB_SESS_VLD (2 << 1) +#define USB1_VBUS_SENSE_CTL_A_SESS_VLD (3 << 1) + +#define ULPI_TIMING_CTRL_0 0x424 +#define ULPI_OUTPUT_PINMUX_BYP (1 << 10) +#define ULPI_CLKOUT_PINMUX_BYP (1 << 11) + +#define ULPI_TIMING_CTRL_1 0x428 +#define ULPI_DATA_TRIMMER_LOAD (1 << 0) +#define ULPI_DATA_TRIMMER_SEL(x) (((x) & 0x7) << 1) +#define ULPI_STPDIRNXT_TRIMMER_LOAD (1 << 16) +#define ULPI_STPDIRNXT_TRIMMER_SEL(x) (((x) & 0x7) << 17) +#define ULPI_DIR_TRIMMER_LOAD (1 << 24) +#define ULPI_DIR_TRIMMER_SEL(x) (((x) & 0x7) << 25) + +#define UTMIP_PLL_CFG1 0x804 +#define UTMIP_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0) +#define UTMIP_PLLU_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 27) + +#define UTMIP_XCVR_CFG0 0x808 +#define UTMIP_XCVR_SETUP(x) (((x) & 0xf) << 0) +#define UTMIP_XCVR_LSRSLEW(x) (((x) & 0x3) << 8) +#define UTMIP_XCVR_LSFSLEW(x) (((x) & 0x3) << 10) +#define UTMIP_FORCE_PD_POWERDOWN (1 << 14) +#define UTMIP_FORCE_PD2_POWERDOWN (1 << 16) +#define UTMIP_FORCE_PDZI_POWERDOWN (1 << 18) +#define UTMIP_XCVR_HSSLEW_MSB(x) (((x) & 0x7f) << 25) + +#define UTMIP_BIAS_CFG0 0x80c +#define UTMIP_OTGPD (1 << 11) +#define UTMIP_BIASPD (1 << 10) + +#define UTMIP_HSRX_CFG0 0x810 +#define UTMIP_ELASTIC_LIMIT(x) (((x) & 0x1f) << 10) +#define UTMIP_IDLE_WAIT(x) (((x) & 0x1f) << 15) + +#define UTMIP_HSRX_CFG1 0x814 +#define UTMIP_HS_SYNC_START_DLY(x) (((x) & 0x1f) << 1) + +#define UTMIP_TX_CFG0 0x820 +#define UTMIP_FS_PREABMLE_J (1 << 19) +#define UTMIP_HS_DISCON_DISABLE (1 << 8) + +#define UTMIP_MISC_CFG0 0x824 +#define UTMIP_DPDM_OBSERVE (1 << 26) +#define UTMIP_DPDM_OBSERVE_SEL(x) (((x) & 0xf) << 27) +#define UTMIP_DPDM_OBSERVE_SEL_FS_J UTMIP_DPDM_OBSERVE_SEL(0xf) +#define UTMIP_DPDM_OBSERVE_SEL_FS_K UTMIP_DPDM_OBSERVE_SEL(0xe) +#define UTMIP_DPDM_OBSERVE_SEL_FS_SE1 UTMIP_DPDM_OBSERVE_SEL(0xd) +#define UTMIP_DPDM_OBSERVE_SEL_FS_SE0 UTMIP_DPDM_OBSERVE_SEL(0xc) +#define UTMIP_SUSPEND_EXIT_ON_EDGE (1 << 22) + +#define UTMIP_MISC_CFG1 0x828 +#define UTMIP_PLL_ACTIVE_DLY_COUNT(x) (((x) & 0x1f) << 18) +#define UTMIP_PLLU_STABLE_COUNT(x) (((x) & 0xfff) << 6) + +#define UTMIP_DEBOUNCE_CFG0 0x82c +#define UTMIP_BIAS_DEBOUNCE_A(x) (((x) & 0xffff) << 0) + +#define UTMIP_BAT_CHRG_CFG0 0x830 +#define UTMIP_PD_CHRG (1 << 0) + +#define UTMIP_SPARE_CFG0 0x834 +#define FUSE_SETUP_SEL (1 << 3) + +#define UTMIP_XCVR_CFG1 0x838 +#define UTMIP_FORCE_PDDISC_POWERDOWN (1 << 0) +#define UTMIP_FORCE_PDCHRP_POWERDOWN (1 << 2) +#define UTMIP_FORCE_PDDR_POWERDOWN (1 << 4) +#define UTMIP_XCVR_TERM_RANGE_ADJ(x) (((x) & 0xf) << 18) + +#define UTMIP_BIAS_CFG1 0x83c +#define UTMIP_BIAS_PDTRK_COUNT(x) (((x) & 0x1f) << 3) + +static DEFINE_SPINLOCK(utmip_pad_lock); +static int utmip_pad_count; + +struct tegra_xtal_freq { + int freq; + u8 enable_delay; + u8 stable_count; + u8 active_delay; + u8 xtal_freq_count; + u16 debounce; +}; + +static const struct tegra_xtal_freq tegra_freq_table[] = { + { + .freq = 12000000, + .enable_delay = 0x02, + .stable_count = 0x2F, + .active_delay = 0x04, + .xtal_freq_count = 0x76, + .debounce = 0x7530, + }, + { + .freq = 13000000, + .enable_delay = 0x02, + .stable_count = 0x33, + .active_delay = 0x05, + .xtal_freq_count = 0x7F, + .debounce = 0x7EF4, + }, + { + .freq = 19200000, + .enable_delay = 0x03, + .stable_count = 0x4B, + .active_delay = 0x06, + .xtal_freq_count = 0xBB, + .debounce = 0xBB80, + }, + { + .freq = 26000000, + .enable_delay = 0x04, + .stable_count = 0x66, + .active_delay = 0x09, + .xtal_freq_count = 0xFE, + .debounce = 0xFDE8, + }, +}; + +static struct tegra_utmip_config utmip_default[] = { + [0] = { + .hssync_start_delay = 9, + .idle_wait_delay = 17, + .elastic_limit = 16, + .term_range_adj = 6, + .xcvr_setup = 9, + .xcvr_lsfslew = 1, + .xcvr_lsrslew = 1, + }, + [2] = { + .hssync_start_delay = 9, + .idle_wait_delay = 17, + .elastic_limit = 16, + .term_range_adj = 6, + .xcvr_setup = 9, + .xcvr_lsfslew = 2, + .xcvr_lsrslew = 2, + }, +}; + +static inline bool phy_is_ulpi(struct tegra_usb_phy *phy) +{ + return (phy->instance == 1); +} + +static int utmip_pad_open(struct tegra_usb_phy *phy) +{ + phy->pad_clk = clk_get_sys("utmip-pad", NULL); + if (IS_ERR(phy->pad_clk)) { + pr_err("%s: can't get utmip pad clock\n", __func__); + return PTR_ERR(phy->pad_clk); + } + + if (phy->instance == 0) { + phy->pad_regs = phy->regs; + } else { + phy->pad_regs = ioremap(TEGRA_USB_BASE, TEGRA_USB_SIZE); + if (!phy->pad_regs) { + pr_err("%s: can't remap usb registers\n", __func__); + clk_put(phy->pad_clk); + return -ENOMEM; + } + } + return 0; +} + +static void utmip_pad_close(struct tegra_usb_phy *phy) +{ + if (phy->instance != 0) + iounmap(phy->pad_regs); + clk_put(phy->pad_clk); +} + +static void utmip_pad_power_on(struct tegra_usb_phy *phy) +{ + unsigned long val, flags; + void __iomem *base = phy->pad_regs; + + clk_prepare_enable(phy->pad_clk); + + spin_lock_irqsave(&utmip_pad_lock, flags); + + if (utmip_pad_count++ == 0) { + val = readl(base + UTMIP_BIAS_CFG0); + val &= ~(UTMIP_OTGPD | UTMIP_BIASPD); + writel(val, base + UTMIP_BIAS_CFG0); + } + + spin_unlock_irqrestore(&utmip_pad_lock, flags); + + clk_disable_unprepare(phy->pad_clk); +} + +static int utmip_pad_power_off(struct tegra_usb_phy *phy) +{ + unsigned long val, flags; + void __iomem *base = phy->pad_regs; + + if (!utmip_pad_count) { + pr_err("%s: utmip pad already powered off\n", __func__); + return -EINVAL; + } + + clk_prepare_enable(phy->pad_clk); + + spin_lock_irqsave(&utmip_pad_lock, flags); + + if (--utmip_pad_count == 0) { + val = readl(base + UTMIP_BIAS_CFG0); + val |= UTMIP_OTGPD | UTMIP_BIASPD; + writel(val, base + UTMIP_BIAS_CFG0); + } + + spin_unlock_irqrestore(&utmip_pad_lock, flags); + + clk_disable_unprepare(phy->pad_clk); + + return 0; +} + +static int utmi_wait_register(void __iomem *reg, u32 mask, u32 result) +{ + unsigned long timeout = 2000; + do { + if ((readl(reg) & mask) == result) + return 0; + udelay(1); + timeout--; + } while (timeout); + return -1; +} + +static void utmi_phy_clk_disable(struct tegra_usb_phy *phy) +{ + unsigned long val; + void __iomem *base = phy->regs; + + if (phy->instance == 0) { + val = readl(base + USB_SUSP_CTRL); + val |= USB_SUSP_SET; + writel(val, base + USB_SUSP_CTRL); + + udelay(10); + + val = readl(base + USB_SUSP_CTRL); + val &= ~USB_SUSP_SET; + writel(val, base + USB_SUSP_CTRL); + } + + if (phy->instance == 2) { + val = readl(base + USB_PORTSC1); + val |= USB_PORTSC1_PHCD; + writel(val, base + USB_PORTSC1); + } + + if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0) + pr_err("%s: timeout waiting for phy to stabilize\n", __func__); +} + +static void utmi_phy_clk_enable(struct tegra_usb_phy *phy) +{ + unsigned long val; + void __iomem *base = phy->regs; + + if (phy->instance == 0) { + val = readl(base + USB_SUSP_CTRL); + val |= USB_SUSP_CLR; + writel(val, base + USB_SUSP_CTRL); + + udelay(10); + + val = readl(base + USB_SUSP_CTRL); + val &= ~USB_SUSP_CLR; + writel(val, base + USB_SUSP_CTRL); + } + + if (phy->instance == 2) { + val = readl(base + USB_PORTSC1); + val &= ~USB_PORTSC1_PHCD; + writel(val, base + USB_PORTSC1); + } + + if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, + USB_PHY_CLK_VALID)) + pr_err("%s: timeout waiting for phy to stabilize\n", __func__); +} + +static int utmi_phy_power_on(struct tegra_usb_phy *phy) +{ + unsigned long val; + void __iomem *base = phy->regs; + struct tegra_utmip_config *config = phy->config; + + val = readl(base + USB_SUSP_CTRL); + val |= UTMIP_RESET; + writel(val, base + USB_SUSP_CTRL); + + if (phy->instance == 0) { + val = readl(base + USB1_LEGACY_CTRL); + val |= USB1_NO_LEGACY_MODE; + writel(val, base + USB1_LEGACY_CTRL); + } + + val = readl(base + UTMIP_TX_CFG0); + val &= ~UTMIP_FS_PREABMLE_J; + writel(val, base + UTMIP_TX_CFG0); + + val = readl(base + UTMIP_HSRX_CFG0); + val &= ~(UTMIP_IDLE_WAIT(~0) | UTMIP_ELASTIC_LIMIT(~0)); + val |= UTMIP_IDLE_WAIT(config->idle_wait_delay); + val |= UTMIP_ELASTIC_LIMIT(config->elastic_limit); + writel(val, base + UTMIP_HSRX_CFG0); + + val = readl(base + UTMIP_HSRX_CFG1); + val &= ~UTMIP_HS_SYNC_START_DLY(~0); + val |= UTMIP_HS_SYNC_START_DLY(config->hssync_start_delay); + writel(val, base + UTMIP_HSRX_CFG1); + + val = readl(base + UTMIP_DEBOUNCE_CFG0); + val &= ~UTMIP_BIAS_DEBOUNCE_A(~0); + val |= UTMIP_BIAS_DEBOUNCE_A(phy->freq->debounce); + writel(val, base + UTMIP_DEBOUNCE_CFG0); + + val = readl(base + UTMIP_MISC_CFG0); + val &= ~UTMIP_SUSPEND_EXIT_ON_EDGE; + writel(val, base + UTMIP_MISC_CFG0); + + val = readl(base + UTMIP_MISC_CFG1); + val &= ~(UTMIP_PLL_ACTIVE_DLY_COUNT(~0) | UTMIP_PLLU_STABLE_COUNT(~0)); + val |= UTMIP_PLL_ACTIVE_DLY_COUNT(phy->freq->active_delay) | + UTMIP_PLLU_STABLE_COUNT(phy->freq->stable_count); + writel(val, base + UTMIP_MISC_CFG1); + + val = readl(base + UTMIP_PLL_CFG1); + val &= ~(UTMIP_XTAL_FREQ_COUNT(~0) | UTMIP_PLLU_ENABLE_DLY_COUNT(~0)); + val |= UTMIP_XTAL_FREQ_COUNT(phy->freq->xtal_freq_count) | + UTMIP_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay); + writel(val, base + UTMIP_PLL_CFG1); + + if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) { + val = readl(base + USB_SUSP_CTRL); + val &= ~(USB_WAKE_ON_CNNT_EN_DEV | USB_WAKE_ON_DISCON_EN_DEV); + writel(val, base + USB_SUSP_CTRL); + } + + utmip_pad_power_on(phy); + + val = readl(base + UTMIP_XCVR_CFG0); + val &= ~(UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN | + UTMIP_FORCE_PDZI_POWERDOWN | UTMIP_XCVR_SETUP(~0) | + UTMIP_XCVR_LSFSLEW(~0) | UTMIP_XCVR_LSRSLEW(~0) | + UTMIP_XCVR_HSSLEW_MSB(~0)); + val |= UTMIP_XCVR_SETUP(config->xcvr_setup); + val |= UTMIP_XCVR_LSFSLEW(config->xcvr_lsfslew); + val |= UTMIP_XCVR_LSRSLEW(config->xcvr_lsrslew); + writel(val, base + UTMIP_XCVR_CFG0); + + val = readl(base + UTMIP_XCVR_CFG1); + val &= ~(UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN | + UTMIP_FORCE_PDDR_POWERDOWN | UTMIP_XCVR_TERM_RANGE_ADJ(~0)); + val |= UTMIP_XCVR_TERM_RANGE_ADJ(config->term_range_adj); + writel(val, base + UTMIP_XCVR_CFG1); + + val = readl(base + UTMIP_BAT_CHRG_CFG0); + val &= ~UTMIP_PD_CHRG; + writel(val, base + UTMIP_BAT_CHRG_CFG0); + + val = readl(base + UTMIP_BIAS_CFG1); + val &= ~UTMIP_BIAS_PDTRK_COUNT(~0); + val |= UTMIP_BIAS_PDTRK_COUNT(0x5); + writel(val, base + UTMIP_BIAS_CFG1); + + if (phy->instance == 0) { + val = readl(base + UTMIP_SPARE_CFG0); + if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) + val &= ~FUSE_SETUP_SEL; + else + val |= FUSE_SETUP_SEL; + writel(val, base + UTMIP_SPARE_CFG0); + } + + if (phy->instance == 2) { + val = readl(base + USB_SUSP_CTRL); + val |= UTMIP_PHY_ENABLE; + writel(val, base + USB_SUSP_CTRL); + } + + val = readl(base + USB_SUSP_CTRL); + val &= ~UTMIP_RESET; + writel(val, base + USB_SUSP_CTRL); + + if (phy->instance == 0) { + val = readl(base + USB1_LEGACY_CTRL); + val &= ~USB1_VBUS_SENSE_CTL_MASK; + val |= USB1_VBUS_SENSE_CTL_A_SESS_VLD; + writel(val, base + USB1_LEGACY_CTRL); + + val = readl(base + USB_SUSP_CTRL); + val &= ~USB_SUSP_SET; + writel(val, base + USB_SUSP_CTRL); + } + + utmi_phy_clk_enable(phy); + + if (phy->instance == 2) { + val = readl(base + USB_PORTSC1); + val &= ~USB_PORTSC1_PTS(~0); + writel(val, base + USB_PORTSC1); + } + + return 0; +} + +static int utmi_phy_power_off(struct tegra_usb_phy *phy) +{ + unsigned long val; + void __iomem *base = phy->regs; + + utmi_phy_clk_disable(phy); + + if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) { + val = readl(base + USB_SUSP_CTRL); + val &= ~USB_WAKEUP_DEBOUNCE_COUNT(~0); + val |= USB_WAKE_ON_CNNT_EN_DEV | USB_WAKEUP_DEBOUNCE_COUNT(5); + writel(val, base + USB_SUSP_CTRL); + } + + val = readl(base + USB_SUSP_CTRL); + val |= UTMIP_RESET; + writel(val, base + USB_SUSP_CTRL); + + val = readl(base + UTMIP_BAT_CHRG_CFG0); + val |= UTMIP_PD_CHRG; + writel(val, base + UTMIP_BAT_CHRG_CFG0); + + val = readl(base + UTMIP_XCVR_CFG0); + val |= UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN | + UTMIP_FORCE_PDZI_POWERDOWN; + writel(val, base + UTMIP_XCVR_CFG0); + + val = readl(base + UTMIP_XCVR_CFG1); + val |= UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN | + UTMIP_FORCE_PDDR_POWERDOWN; + writel(val, base + UTMIP_XCVR_CFG1); + + return utmip_pad_power_off(phy); +} + +static void utmi_phy_preresume(struct tegra_usb_phy *phy) +{ + unsigned long val; + void __iomem *base = phy->regs; + + val = readl(base + UTMIP_TX_CFG0); + val |= UTMIP_HS_DISCON_DISABLE; + writel(val, base + UTMIP_TX_CFG0); +} + +static void utmi_phy_postresume(struct tegra_usb_phy *phy) +{ + unsigned long val; + void __iomem *base = phy->regs; + + val = readl(base + UTMIP_TX_CFG0); + val &= ~UTMIP_HS_DISCON_DISABLE; + writel(val, base + UTMIP_TX_CFG0); +} + +static void utmi_phy_restore_start(struct tegra_usb_phy *phy, + enum tegra_usb_phy_port_speed port_speed) +{ + unsigned long val; + void __iomem *base = phy->regs; + + val = readl(base + UTMIP_MISC_CFG0); + val &= ~UTMIP_DPDM_OBSERVE_SEL(~0); + if (port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW) + val |= UTMIP_DPDM_OBSERVE_SEL_FS_K; + else + val |= UTMIP_DPDM_OBSERVE_SEL_FS_J; + writel(val, base + UTMIP_MISC_CFG0); + udelay(1); + + val = readl(base + UTMIP_MISC_CFG0); + val |= UTMIP_DPDM_OBSERVE; + writel(val, base + UTMIP_MISC_CFG0); + udelay(10); +} + +static void utmi_phy_restore_end(struct tegra_usb_phy *phy) +{ + unsigned long val; + void __iomem *base = phy->regs; + + val = readl(base + UTMIP_MISC_CFG0); + val &= ~UTMIP_DPDM_OBSERVE; + writel(val, base + UTMIP_MISC_CFG0); + udelay(10); +} + +static int ulpi_phy_power_on(struct tegra_usb_phy *phy) +{ + int ret; + unsigned long val; + void __iomem *base = phy->regs; + struct tegra_ulpi_config *config = phy->config; + + gpio_direction_output(config->reset_gpio, 0); + msleep(5); + gpio_direction_output(config->reset_gpio, 1); + + clk_prepare_enable(phy->clk); + msleep(1); + + val = readl(base + USB_SUSP_CTRL); + val |= UHSIC_RESET; + writel(val, base + USB_SUSP_CTRL); + + val = readl(base + ULPI_TIMING_CTRL_0); + val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP; + writel(val, base + ULPI_TIMING_CTRL_0); + + val = readl(base + USB_SUSP_CTRL); + val |= ULPI_PHY_ENABLE; + writel(val, base + USB_SUSP_CTRL); + + val = 0; + writel(val, base + ULPI_TIMING_CTRL_1); + + val |= ULPI_DATA_TRIMMER_SEL(4); + val |= ULPI_STPDIRNXT_TRIMMER_SEL(4); + val |= ULPI_DIR_TRIMMER_SEL(4); + writel(val, base + ULPI_TIMING_CTRL_1); + udelay(10); + + val |= ULPI_DATA_TRIMMER_LOAD; + val |= ULPI_STPDIRNXT_TRIMMER_LOAD; + val |= ULPI_DIR_TRIMMER_LOAD; + writel(val, base + ULPI_TIMING_CTRL_1); + + /* Fix VbusInvalid due to floating VBUS */ + ret = usb_phy_io_write(phy->ulpi, 0x40, 0x08); + if (ret) { + pr_err("%s: ulpi write failed\n", __func__); + return ret; + } + + ret = usb_phy_io_write(phy->ulpi, 0x80, 0x0B); + if (ret) { + pr_err("%s: ulpi write failed\n", __func__); + return ret; + } + + val = readl(base + USB_PORTSC1); + val |= USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN; + writel(val, base + USB_PORTSC1); + + val = readl(base + USB_SUSP_CTRL); + val |= USB_SUSP_CLR; + writel(val, base + USB_SUSP_CTRL); + udelay(100); + + val = readl(base + USB_SUSP_CTRL); + val &= ~USB_SUSP_CLR; + writel(val, base + USB_SUSP_CTRL); + + return 0; +} + +static int ulpi_phy_power_off(struct tegra_usb_phy *phy) +{ + unsigned long val; + void __iomem *base = phy->regs; + struct tegra_ulpi_config *config = phy->config; + + /* Clear WKCN/WKDS/WKOC wake-on events that can cause the USB + * Controller to immediately bring the ULPI PHY out of low power + */ + val = readl(base + USB_PORTSC1); + val &= ~(USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN); + writel(val, base + USB_PORTSC1); + + clk_disable(phy->clk); + return gpio_direction_output(config->reset_gpio, 0); +} + +static int tegra_phy_init(struct usb_phy *x) +{ + struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); + struct tegra_ulpi_config *ulpi_config; + int err; + + if (phy_is_ulpi(phy)) { + ulpi_config = phy->config; + phy->clk = clk_get_sys(NULL, ulpi_config->clk); + if (IS_ERR(phy->clk)) { + pr_err("%s: can't get ulpi clock\n", __func__); + err = -ENXIO; + goto err1; + } + if (!gpio_is_valid(ulpi_config->reset_gpio)) + ulpi_config->reset_gpio = + of_get_named_gpio(phy->dev->of_node, + "nvidia,phy-reset-gpio", 0); + if (!gpio_is_valid(ulpi_config->reset_gpio)) { + pr_err("%s: invalid reset gpio: %d\n", __func__, + ulpi_config->reset_gpio); + err = -EINVAL; + goto err1; + } + gpio_request(ulpi_config->reset_gpio, "ulpi_phy_reset_b"); + gpio_direction_output(ulpi_config->reset_gpio, 0); + phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0); + phy->ulpi->io_priv = phy->regs + ULPI_VIEWPORT; + } else { + err = utmip_pad_open(phy); + if (err < 0) + goto err1; + } + return 0; +err1: + clk_disable_unprepare(phy->pll_u); + clk_put(phy->pll_u); + return err; +} + +static void tegra_usb_phy_close(struct usb_phy *x) +{ + struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); + + if (phy_is_ulpi(phy)) + clk_put(phy->clk); + else + utmip_pad_close(phy); + clk_disable_unprepare(phy->pll_u); + clk_put(phy->pll_u); + kfree(phy); +} + +static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy) +{ + if (phy_is_ulpi(phy)) + return ulpi_phy_power_on(phy); + else + return utmi_phy_power_on(phy); +} + +static int tegra_usb_phy_power_off(struct tegra_usb_phy *phy) +{ + if (phy_is_ulpi(phy)) + return ulpi_phy_power_off(phy); + else + return utmi_phy_power_off(phy); +} + +static int tegra_usb_phy_suspend(struct usb_phy *x, int suspend) +{ + struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy); + if (suspend) + return tegra_usb_phy_power_off(phy); + else + return tegra_usb_phy_power_on(phy); +} + +struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, + void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode) +{ + struct tegra_usb_phy *phy; + unsigned long parent_rate; + int i; + int err; + + phy = kmalloc(sizeof(struct tegra_usb_phy), GFP_KERNEL); + if (!phy) + return ERR_PTR(-ENOMEM); + + phy->instance = instance; + phy->regs = regs; + phy->config = config; + phy->mode = phy_mode; + phy->dev = dev; + + if (!phy->config) { + if (phy_is_ulpi(phy)) { + pr_err("%s: ulpi phy configuration missing", __func__); + err = -EINVAL; + goto err0; + } else { + phy->config = &utmip_default[instance]; + } + } + + phy->pll_u = clk_get_sys(NULL, "pll_u"); + if (IS_ERR(phy->pll_u)) { + pr_err("Can't get pll_u clock\n"); + err = PTR_ERR(phy->pll_u); + goto err0; + } + clk_prepare_enable(phy->pll_u); + + parent_rate = clk_get_rate(clk_get_parent(phy->pll_u)); + for (i = 0; i < ARRAY_SIZE(tegra_freq_table); i++) { + if (tegra_freq_table[i].freq == parent_rate) { + phy->freq = &tegra_freq_table[i]; + break; + } + } + if (!phy->freq) { + pr_err("invalid pll_u parent rate %ld\n", parent_rate); + err = -EINVAL; + goto err1; + } + + phy->u_phy.init = tegra_phy_init; + phy->u_phy.shutdown = tegra_usb_phy_close; + phy->u_phy.set_suspend = tegra_usb_phy_suspend; + + return phy; + +err1: + clk_disable_unprepare(phy->pll_u); + clk_put(phy->pll_u); +err0: + kfree(phy); + return ERR_PTR(err); +} +EXPORT_SYMBOL_GPL(tegra_usb_phy_open); + +void tegra_usb_phy_preresume(struct tegra_usb_phy *phy) +{ + if (!phy_is_ulpi(phy)) + utmi_phy_preresume(phy); +} +EXPORT_SYMBOL_GPL(tegra_usb_phy_preresume); + +void tegra_usb_phy_postresume(struct tegra_usb_phy *phy) +{ + if (!phy_is_ulpi(phy)) + utmi_phy_postresume(phy); +} +EXPORT_SYMBOL_GPL(tegra_usb_phy_postresume); + +void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy, + enum tegra_usb_phy_port_speed port_speed) +{ + if (!phy_is_ulpi(phy)) + utmi_phy_restore_start(phy, port_speed); +} +EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_start); + +void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy) +{ + if (!phy_is_ulpi(phy)) + utmi_phy_restore_end(phy); +} +EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_end); + +void tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy) +{ + if (!phy_is_ulpi(phy)) + utmi_phy_clk_disable(phy); +} +EXPORT_SYMBOL_GPL(tegra_usb_phy_clk_disable); + +void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy) +{ + if (!phy_is_ulpi(phy)) + utmi_phy_clk_enable(phy); +} +EXPORT_SYMBOL_GPL(tegra_usb_phy_clk_enable); diff --git a/include/linux/usb/tegra_usb_phy.h b/include/linux/usb/tegra_usb_phy.h new file mode 100644 index 0000000..176b1ca --- /dev/null +++ b/include/linux/usb/tegra_usb_phy.h @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2010 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __TEGRA_USB_PHY_H +#define __TEGRA_USB_PHY_H + +#include +#include + +struct tegra_utmip_config { + u8 hssync_start_delay; + u8 elastic_limit; + u8 idle_wait_delay; + u8 term_range_adj; + u8 xcvr_setup; + u8 xcvr_lsfslew; + u8 xcvr_lsrslew; +}; + +struct tegra_ulpi_config { + int reset_gpio; + const char *clk; +}; + +enum tegra_usb_phy_port_speed { + TEGRA_USB_PHY_PORT_SPEED_FULL = 0, + TEGRA_USB_PHY_PORT_SPEED_LOW, + TEGRA_USB_PHY_PORT_SPEED_HIGH, +}; + +enum tegra_usb_phy_mode { + TEGRA_USB_PHY_MODE_DEVICE, + TEGRA_USB_PHY_MODE_HOST, +}; + +struct tegra_xtal_freq; + +struct tegra_usb_phy { + int instance; + const struct tegra_xtal_freq *freq; + void __iomem *regs; + void __iomem *pad_regs; + struct clk *clk; + struct clk *pll_u; + struct clk *pad_clk; + enum tegra_usb_phy_mode mode; + void *config; + struct usb_phy *ulpi; + struct usb_phy u_phy; + struct device *dev; +}; + +struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance, + void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode); + +void tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy); + +void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy); + +void tegra_usb_phy_preresume(struct tegra_usb_phy *phy); + +void tegra_usb_phy_postresume(struct tegra_usb_phy *phy); + +void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy, + enum tegra_usb_phy_port_speed port_speed); + +void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy); + +#endif /* __TEGRA_USB_PHY_H */ -- cgit v0.10.2 From 898d828b8b37c9f8f3d618d28d40109c275efa36 Mon Sep 17 00:00:00 2001 From: Peter Meerwald Date: Sat, 18 Aug 2012 15:53:12 +0200 Subject: usb host: fix spelling of provides in Kconfig Signed-off-by: Peter Meerwald Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index c3f619b..bef820a 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -418,7 +418,7 @@ config USB_OHCI_HCD_PLATFORM default n ---help--- Adds an OHCI host driver for a generic platform device, which - provieds a memory space and an irq. + provides a memory space and an irq. If unsure, say N. @@ -428,7 +428,7 @@ config USB_EHCI_HCD_PLATFORM default n ---help--- Adds an EHCI host driver for a generic platform device, which - provieds a memory space and an irq. + provides a memory space and an irq. If unsure, say N. -- cgit v0.10.2 From 47c56a1479373d46f90d2e301869b9952f632451 Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Sun, 19 Aug 2012 13:04:29 +0200 Subject: USB: isp1301: Remove unused static array and define This patch removes an unused statically defined array and an associated #define. Signed-off-by: Roland Stigge Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/phy/isp1301.c b/drivers/usb/phy/isp1301.c index b19f493..18dbf7e 100644 --- a/drivers/usb/phy/isp1301.c +++ b/drivers/usb/phy/isp1301.c @@ -15,12 +15,6 @@ #define DRV_NAME "isp1301" -#define ISP1301_I2C_ADDR 0x2C - -static const unsigned short normal_i2c[] = { - ISP1301_I2C_ADDR, ISP1301_I2C_ADDR + 1, I2C_CLIENT_END -}; - static const struct i2c_device_id isp1301_id[] = { { "isp1301", 0 }, { } -- cgit v0.10.2 From 697d5c004e390102efbf9320a5416873679bea81 Mon Sep 17 00:00:00 2001 From: "Shimoda, Yoshihiro" Date: Mon, 20 Aug 2012 18:39:23 +0900 Subject: usb: renesas_usbhs: modify the irq handler for sharing irq When IORESOURCE_IRQ_SHAREABLE is set, the irq handler may be called even if the interupt of the USB module doesn't happen. So, it may clear the interrupt flags by mistake. This patch fixes it. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c index 82a628f..35c5208 100644 --- a/drivers/usb/renesas_usbhs/mod.c +++ b/drivers/usb/renesas_usbhs/mod.c @@ -209,14 +209,18 @@ int usbhs_status_get_ctrl_stage(struct usbhs_irq_state *irq_state) return (int)irq_state->intsts0 & CTSQ_MASK; } -static void usbhs_status_get_each_irq(struct usbhs_priv *priv, - struct usbhs_irq_state *state) +static int usbhs_status_get_each_irq(struct usbhs_priv *priv, + struct usbhs_irq_state *state) { struct usbhs_mod *mod = usbhs_mod_get_current(priv); + u16 intenb0, intenb1; state->intsts0 = usbhs_read(priv, INTSTS0); state->intsts1 = usbhs_read(priv, INTSTS1); + intenb0 = usbhs_read(priv, INTENB0); + intenb1 = usbhs_read(priv, INTENB1); + /* mask */ if (mod) { state->brdysts = usbhs_read(priv, BRDYSTS); @@ -226,6 +230,20 @@ static void usbhs_status_get_each_irq(struct usbhs_priv *priv, state->bempsts &= mod->irq_bempsts; state->brdysts &= mod->irq_brdysts; } + + /* + * Check whether the irq enable registers and the irq status are set + * when IRQF_SHARED is set. + */ + if (priv->irqflags & IRQF_SHARED) { + if (!(intenb0 & state->intsts0) && + !(intenb1 & state->intsts1) && + !(state->bempsts) && + !(state->brdysts)) + return -EIO; + } + + return 0; } /* @@ -238,7 +256,8 @@ static irqreturn_t usbhs_interrupt(int irq, void *data) struct usbhs_priv *priv = data; struct usbhs_irq_state irq_state; - usbhs_status_get_each_irq(priv, &irq_state); + if (usbhs_status_get_each_irq(priv, &irq_state) < 0) + return IRQ_NONE; /* * clear interrupt -- cgit v0.10.2 From 67990472c77b06cc591dd59923542f64da91453d Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 21 Aug 2012 11:28:45 +0800 Subject: USB: mos7720: fix to use list_for_each_entry_safe() when delete items Since we will be removing items off the list using list_del() we need to use a safer version of the list_for_each_entry() macro aptly named list_for_each_entry_safe(). We should use the safe macro if the loop involves deletions of items. Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index a07dd3c..9817d9d 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -281,7 +281,7 @@ static void send_deferred_urbs(unsigned long _mos_parport) int ret_val; unsigned long flags; struct mos7715_parport *mos_parport = (void *)_mos_parport; - struct urbtracker *urbtrack; + struct urbtracker *urbtrack, *tmp; struct list_head *cursor, *next; /* if release function ran, game over */ @@ -312,7 +312,7 @@ static void send_deferred_urbs(unsigned long _mos_parport) /* move contents of deferred_urbs list to active_urbs list and submit */ list_for_each_safe(cursor, next, &mos_parport->deferred_urbs) list_move_tail(cursor, &mos_parport->active_urbs); - list_for_each_entry(urbtrack, &mos_parport->active_urbs, + list_for_each_entry_safe(urbtrack, tmp, &mos_parport->active_urbs, urblist_entry) { ret_val = usb_submit_urb(urbtrack->urb, GFP_ATOMIC); dbg("%s: urb submitted", __func__); -- cgit v0.10.2 From 3735ba8db8e6ea22ad3ff524328926d8d780a884 Mon Sep 17 00:00:00 2001 From: Shengzhou Liu Date: Wed, 22 Aug 2012 18:17:00 +0800 Subject: powerpc/usb: fix bug of CPU hang when missing USB PHY clock when missing USB PHY clock, kernel booting up will hang during USB initialization. We should check USBGP[PHY_CLK_VALID] bit to avoid CPU hanging in this case. Signed-off-by: Shengzhou Liu Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index b7451b2..11ff4b4 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -210,11 +210,11 @@ static void usb_hcd_fsl_remove(struct usb_hcd *hcd, usb_put_hcd(hcd); } -static void ehci_fsl_setup_phy(struct usb_hcd *hcd, +static int ehci_fsl_setup_phy(struct usb_hcd *hcd, enum fsl_usb2_phy_modes phy_mode, unsigned int port_offset) { - u32 portsc, temp; + u32 portsc; struct ehci_hcd *ehci = hcd_to_ehci(hcd); void __iomem *non_ehci = hcd->regs; struct device *dev = hcd->self.controller; @@ -232,9 +232,15 @@ static void ehci_fsl_setup_phy(struct usb_hcd *hcd, case FSL_USB2_PHY_ULPI: if (pdata->controller_ver) { /* controller version 1.6 or above */ - temp = in_be32(non_ehci + FSL_SOC_USB_CTRL); - out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | - USB_CTRL_USB_EN | ULPI_PHY_CLK_SEL); + setbits32(non_ehci + FSL_SOC_USB_CTRL, + ULPI_PHY_CLK_SEL); + /* + * Due to controller issue of PHY_CLK_VALID in ULPI + * mode, we set USB_CTRL_USB_EN before checking + * PHY_CLK_VALID, otherwise PHY_CLK_VALID doesn't work. + */ + clrsetbits_be32(non_ehci + FSL_SOC_USB_CTRL, + UTMI_PHY_EN, USB_CTRL_USB_EN); } portsc |= PORT_PTS_ULPI; break; @@ -247,9 +253,7 @@ static void ehci_fsl_setup_phy(struct usb_hcd *hcd, case FSL_USB2_PHY_UTMI: if (pdata->controller_ver) { /* controller version 1.6 or above */ - temp = in_be32(non_ehci + FSL_SOC_USB_CTRL); - out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | - UTMI_PHY_EN | USB_CTRL_USB_EN); + setbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN); mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI PHY CLK to become stable - 10ms*/ } @@ -262,23 +266,34 @@ static void ehci_fsl_setup_phy(struct usb_hcd *hcd, case FSL_USB2_PHY_NONE: break; } + + if ((pdata->controller_ver) && ((phy_mode == FSL_USB2_PHY_ULPI) || + (phy_mode == FSL_USB2_PHY_UTMI))) { + /* check PHY_CLK_VALID to get phy clk valid */ + if (!spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) & + PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0)) { + printk(KERN_WARNING "fsl-ehci: USB PHY clock invalid\n"); + return -EINVAL; + } + } + ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]); + + if (phy_mode != FSL_USB2_PHY_ULPI) + setbits32(non_ehci + FSL_SOC_USB_CTRL, USB_CTRL_USB_EN); + + return 0; } -static void ehci_fsl_usb_setup(struct ehci_hcd *ehci) +static int ehci_fsl_usb_setup(struct ehci_hcd *ehci) { struct usb_hcd *hcd = ehci_to_hcd(ehci); struct fsl_usb2_platform_data *pdata; void __iomem *non_ehci = hcd->regs; - u32 temp; pdata = hcd->self.controller->platform_data; - /* Enable PHY interface in the control reg. */ if (pdata->have_sysif_regs) { - temp = in_be32(non_ehci + FSL_SOC_USB_CTRL); - out_be32(non_ehci + FSL_SOC_USB_CTRL, temp | 0x00000004); - /* * Turn on cache snooping hardware, since some PowerPC platforms * wholly rely on hardware to deal with cache coherent @@ -293,7 +308,8 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci) if ((pdata->operating_mode == FSL_USB2_DR_HOST) || (pdata->operating_mode == FSL_USB2_DR_OTG)) - ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0); + if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0)) + return -EINVAL; if (pdata->operating_mode == FSL_USB2_MPH_HOST) { unsigned int chip, rev, svr; @@ -307,9 +323,12 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci) ehci->has_fsl_port_bug = 1; if (pdata->port_enables & FSL_USB2_PORT0_ENABLED) - ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0); + if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 0)) + return -EINVAL; + if (pdata->port_enables & FSL_USB2_PORT1_ENABLED) - ehci_fsl_setup_phy(hcd, pdata->phy_mode, 1); + if (ehci_fsl_setup_phy(hcd, pdata->phy_mode, 1)) + return -EINVAL; } if (pdata->have_sysif_regs) { @@ -322,12 +341,15 @@ static void ehci_fsl_usb_setup(struct ehci_hcd *ehci) #endif out_be32(non_ehci + FSL_SOC_USB_SICTRL, 0x00000001); } + + return 0; } /* called after powerup, by probe or system-pm "wakeup" */ static int ehci_fsl_reinit(struct ehci_hcd *ehci) { - ehci_fsl_usb_setup(ehci); + if (ehci_fsl_usb_setup(ehci)) + return -EINVAL; ehci_port_power(ehci, 0); return 0; diff --git a/drivers/usb/host/ehci-fsl.h b/drivers/usb/host/ehci-fsl.h index 8840368..dbd292e 100644 --- a/drivers/usb/host/ehci-fsl.h +++ b/drivers/usb/host/ehci-fsl.h @@ -61,4 +61,5 @@ #define PLL_RESET (1<<8) #define UTMI_PHY_EN (1<<9) #define ULPI_PHY_CLK_SEL (1<<10) +#define PHY_CLK_VALID (1<<17) #endif /* _EHCI_FSL_H */ diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h index 15be561..ccfc4bb 100644 --- a/include/linux/fsl_devices.h +++ b/include/linux/fsl_devices.h @@ -19,6 +19,7 @@ #define FSL_UTMI_PHY_DLY 10 /*As per P1010RM, delay for UTMI PHY CLK to become stable - 10ms*/ +#define FSL_USB_PHY_CLK_TIMEOUT 1000 /* uSec */ #define FSL_USB_VER_OLD 0 #define FSL_USB_VER_1_6 1 #define FSL_USB_VER_2_2 2 -- cgit v0.10.2 From a651684c100d47b34acb815d56c0c258565296dc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 22 Aug 2012 18:01:13 -0700 Subject: usb: renesas_usbhs: fixup DMA transport data alignment renesas_usbhs dma can transport 8byte alignment data, not 4byte. This patch fixup it. Reported-by: Sugnan Prabhu S Signed-off-by: Kuninori Morimoto Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/renesas_usbhs/fifo.c b/drivers/usb/renesas_usbhs/fifo.c index ecd1730..143c4e9 100644 --- a/drivers/usb/renesas_usbhs/fifo.c +++ b/drivers/usb/renesas_usbhs/fifo.c @@ -818,7 +818,7 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done) usbhs_pipe_is_dcp(pipe)) goto usbhsf_pio_prepare_push; - if (len % 4) /* 32bit alignment */ + if (len & 0x7) /* 8byte alignment */ goto usbhsf_pio_prepare_push; if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */ @@ -905,7 +905,7 @@ static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done) /* use PIO if packet is less than pio_dma_border */ len = usbhsf_fifo_rcv_len(priv, fifo); len = min(pkt->length - pkt->actual, len); - if (len % 4) /* 32bit alignment */ + if (len & 0x7) /* 8byte alignment */ goto usbhsf_pio_prepare_pop_unselect; if (len < usbhs_get_dparam(priv, pio_dma_border)) -- cgit v0.10.2 From 952230d774bb2ff0682d0b8108091ffa7c546f8e Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Thu, 23 Aug 2012 13:05:34 +0200 Subject: usb: ohci: Fix Kconfig dependency on USB_ISP1301 With "select USB_ISP1301 ...", it could happen that I2C isn't selected although USB_ISP1301 depends on it. Fixing with "depends on ..." and emulating the condition via "|| !()". Signed-off-by: Roland Stigge Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index bef820a..13cd6d5 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -292,7 +292,7 @@ config USB_OHCI_HCD depends on USB && USB_ARCH_HAS_OHCI select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 select USB_OTG_UTILS if ARCH_OMAP - select USB_ISP1301 if ARCH_LPC32XX || ARCH_PNX4008 + depends on USB_ISP1301 || !(ARCH_LPC32XX || ARCH_PNX4008) ---help--- The Open Host Controller Interface (OHCI) is a standard for accessing USB 1.1 host controller hardware. It does more in hardware than Intel's -- cgit v0.10.2 From 2ec15a6fbe931a8e0b45a3b26f59b9eb2701b4d1 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 25 Aug 2012 21:57:07 +0200 Subject: drivers/usb/host/ohci-nxp.c: adjust inconsistent IS_ERR and PTR_ERR Change the call to PTR_ERR to access the value just tested by IS_ERR. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression e,e1; @@ ( if (IS_ERR(e)) { ... PTR_ERR(e) ... } | if (IS_ERR(e=e1)) { ... PTR_ERR(e) ... } | *if (IS_ERR(e)) { ... * PTR_ERR(e1) ... } ) // Signed-off-by: Julia Lawall Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c index a446386..c60066a 100644 --- a/drivers/usb/host/ohci-nxp.c +++ b/drivers/usb/host/ohci-nxp.c @@ -355,7 +355,7 @@ static int __devinit usb_hcd_nxp_probe(struct platform_device *pdev) usb_otg_clk = clk_get(&pdev->dev, "ck_usb_otg"); if (IS_ERR(usb_otg_clk)) { dev_err(&pdev->dev, "failed to acquire USB DEV Clock\n"); - ret = PTR_ERR(usb_dev_clk); + ret = PTR_ERR(usb_otg_clk); goto out6; } -- cgit v0.10.2 From 1a35d9df80c0e45afd764f0214e41f27a8a2fce7 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 25 Aug 2012 21:57:06 +0200 Subject: drivers/usb/gadget/lpc32xx_udc.c: adjust inconsistent IS_ERR and PTR_ERR Change the call to PTR_ERR to access the value just tested by IS_ERR. The semantic match that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression e,e1; @@ ( if (IS_ERR(e)) { ... PTR_ERR(e) ... } | if (IS_ERR(e=e1)) { ... PTR_ERR(e) ... } | *if (IS_ERR(e)) { ... * PTR_ERR(e1) ... } ) // Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c index f1ec99e..3a6cdd0 100644 --- a/drivers/usb/gadget/lpc32xx_udc.c +++ b/drivers/usb/gadget/lpc32xx_udc.c @@ -3208,7 +3208,7 @@ static int __init lpc32xx_udc_probe(struct platform_device *pdev) udc->usb_otg_clk = clk_get(&pdev->dev, "ck_usb_otg"); if (IS_ERR(udc->usb_otg_clk)) { dev_err(udc->dev, "failed to acquire USB otg clock\n"); - retval = PTR_ERR(udc->usb_slv_clk); + retval = PTR_ERR(udc->usb_otg_clk); goto usb_otg_clk_get_fail; } -- cgit v0.10.2 From 49b5582893607e5dd120add693950b759bde176d Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 26 Aug 2012 09:44:45 +0800 Subject: usb: cdc-acm: remove duplicated include from cdc-acm.c Remove duplicated include. Signed-off-by: Wei Yongjun Acked-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index f763ed7..344a51d 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include -- cgit v0.10.2 From 027c5215a9b584ed2c7c23870221a4429d35a981 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 5 Sep 2012 14:41:44 +0800 Subject: USB: FHCI: use list_move_tail instead of list_del/list_add_tail Using list_move_tail() instead of list_del() + list_add_tail(). spatch with a semantic match is used to found this problem. (http://coccinelle.lip6.fr/) Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/fhci-sched.c b/drivers/usb/host/fhci-sched.c index 2dc8a40..8f18538 100644 --- a/drivers/usb/host/fhci-sched.c +++ b/drivers/usb/host/fhci-sched.c @@ -261,8 +261,7 @@ static void move_head_to_tail(struct list_head *list) struct list_head *node = list->next; if (!list_empty(list)) { - list_del(node); - list_add_tail(node, list); + list_move_tail(node, list); } } -- cgit v0.10.2 From 89bb957ec8b054ea9994974f03848cb2f129f50c Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 27 Aug 2012 15:07:17 +0800 Subject: USB: cp210x: remove useless set memory to zero use memset() The memory return by kzalloc() or kmem_cache_zalloc() has already be set to zero, so remove useless memset(0). spatch with a semantic match is used to found this problem. (http://coccinelle.lip6.fr/) Signed-off-by: Wei Yongjun Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 1e71079..3f86cf3 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -865,7 +865,6 @@ static int cp210x_startup(struct usb_serial *serial) if (!port_priv) return -ENOMEM; - memset(port_priv, 0x00, sizeof(*port_priv)); port_priv->bInterfaceNumber = serial->interface->cur_altsetting->desc.bInterfaceNumber; -- cgit v0.10.2 From 68a5059ecf82cc9d52a86fb523584b4d485f1bbe Mon Sep 17 00:00:00 2001 From: Cong Wang Date: Sun, 26 Aug 2012 14:40:07 +0800 Subject: block: remove the deprecated ub driver It was scheduled to be removed in 3.6. Acked-by: Pete Zaitcev Cc: Jens Axboe Cc: Sebastian Andrzej Siewior Signed-off-by: Cong Wang Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index afaff31..b9aa38b 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -495,17 +495,6 @@ Who: Bjorn Helgaas ---------------------------- -What: Low Performance USB Block driver ("CONFIG_BLK_DEV_UB") -When: 3.6 -Why: This driver provides support for USB storage devices like "USB - sticks". As of now, it is deactivated in Debian, Fedora and - Ubuntu. All current users can switch over to usb-storage - (CONFIG_USB_STORAGE) which only drawback is the additional SCSI - stack. -Who: Sebastian Andrzej Siewior - ----------------------------- - What: get_robust_list syscall When: 2013 Why: There appear to be no production users of the get_robust_list syscall, diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index a796407..f529407 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig @@ -353,18 +353,6 @@ config BLK_DEV_SX8 Use devices /dev/sx8/$N and /dev/sx8/$Np$M. -config BLK_DEV_UB - tristate "Low Performance USB Block driver (deprecated)" - depends on USB - help - This driver supports certain USB attached storage devices - such as flash keys. - - If you enable this driver, it is recommended to avoid conflicts - with usb-storage by enabling USB_LIBUSUAL. - - If unsure, say N. - config BLK_DEV_RAM tristate "RAM block device support" ---help--- diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 5b79505..17e82df 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -33,7 +33,6 @@ obj-$(CONFIG_VIRTIO_BLK) += virtio_blk.o obj-$(CONFIG_VIODASD) += viodasd.o obj-$(CONFIG_BLK_DEV_SX8) += sx8.o -obj-$(CONFIG_BLK_DEV_UB) += ub.o obj-$(CONFIG_BLK_DEV_HD) += hd.o obj-$(CONFIG_XEN_BLKDEV_FRONTEND) += xen-blkfront.o diff --git a/drivers/block/ub.c b/drivers/block/ub.c deleted file mode 100644 index fcec022..0000000 --- a/drivers/block/ub.c +++ /dev/null @@ -1,2474 +0,0 @@ -/* - * The low performance USB storage driver (ub). - * - * Copyright (c) 1999, 2000 Matthew Dharm (mdharm-usb@one-eyed-alien.net) - * Copyright (C) 2004 Pete Zaitcev (zaitcev@yahoo.com) - * - * This work is a part of Linux kernel, is derived from it, - * and is not licensed separately. See file COPYING for details. - * - * TODO (sorted by decreasing priority) - * -- Return sense now that rq allows it (we always auto-sense anyway). - * -- set readonly flag for CDs, set removable flag for CF readers - * -- do inquiry and verify we got a disk and not a tape (for LUN mismatch) - * -- verify the 13 conditions and do bulk resets - * -- highmem - * -- move top_sense and work_bcs into separate allocations (if they survive) - * for cache purists and esoteric architectures. - * -- Allocate structure for LUN 0 before the first ub_sync_tur, avoid NULL. ? - * -- prune comments, they are too volumnous - * -- Resove XXX's - * -- CLEAR, CLR2STS, CLRRS seem to be ripe for refactoring. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_NAME "ub" - -#define UB_MAJOR 180 - -/* - * The command state machine is the key model for understanding of this driver. - * - * The general rule is that all transitions are done towards the bottom - * of the diagram, thus preventing any loops. - * - * An exception to that is how the STAT state is handled. A counter allows it - * to be re-entered along the path marked with [C]. - * - * +--------+ - * ! INIT ! - * +--------+ - * ! - * ub_scsi_cmd_start fails ->--------------------------------------\ - * ! ! - * V ! - * +--------+ ! - * ! CMD ! ! - * +--------+ ! - * ! +--------+ ! - * was -EPIPE -->-------------------------------->! CLEAR ! ! - * ! +--------+ ! - * ! ! ! - * was error -->------------------------------------- ! --------->\ - * ! ! ! - * /--<-- cmd->dir == NONE ? ! ! - * ! ! ! ! - * ! V ! ! - * ! +--------+ ! ! - * ! ! DATA ! ! ! - * ! +--------+ ! ! - * ! ! +---------+ ! ! - * ! was -EPIPE -->--------------->! CLR2STS ! ! ! - * ! ! +---------+ ! ! - * ! ! ! ! ! - * ! ! was error -->---- ! --------->\ - * ! was error -->--------------------- ! ------------- ! --------->\ - * ! ! ! ! ! - * ! V ! ! ! - * \--->+--------+ ! ! ! - * ! STAT !<--------------------------/ ! ! - * /--->+--------+ ! ! - * ! ! ! ! - * [C] was -EPIPE -->-----------\ ! ! - * ! ! ! ! ! - * +<---- len == 0 ! ! ! - * ! ! ! ! ! - * ! was error -->--------------------------------------!---------->\ - * ! ! ! ! ! - * +<---- bad CSW ! ! ! - * +<---- bad tag ! ! ! - * ! ! V ! ! - * ! ! +--------+ ! ! - * ! ! ! CLRRS ! ! ! - * ! ! +--------+ ! ! - * ! ! ! ! ! - * \------- ! --------------------[C]--------\ ! ! - * ! ! ! ! - * cmd->error---\ +--------+ ! ! - * ! +--------------->! SENSE !<----------/ ! - * STAT_FAIL----/ +--------+ ! - * ! ! V - * ! V +--------+ - * \--------------------------------\--------------------->! DONE ! - * +--------+ - */ - -/* - * This many LUNs per USB device. - * Every one of them takes a host, see UB_MAX_HOSTS. - */ -#define UB_MAX_LUNS 9 - -/* - */ - -#define UB_PARTS_PER_LUN 8 - -#define UB_MAX_CDB_SIZE 16 /* Corresponds to Bulk */ - -#define UB_SENSE_SIZE 18 - -/* - */ -struct ub_dev; - -#define UB_MAX_REQ_SG 9 /* cdrecord requires 32KB and maybe a header */ -#define UB_MAX_SECTORS 64 - -/* - * A second is more than enough for a 32K transfer (UB_MAX_SECTORS) - * even if a webcam hogs the bus, but some devices need time to spin up. - */ -#define UB_URB_TIMEOUT (HZ*2) -#define UB_DATA_TIMEOUT (HZ*5) /* ZIP does spin-ups in the data phase */ -#define UB_STAT_TIMEOUT (HZ*5) /* Same spinups and eject for a dataless cmd. */ -#define UB_CTRL_TIMEOUT (HZ/2) /* 500ms ought to be enough to clear a stall */ - -/* - * An instance of a SCSI command in transit. - */ -#define UB_DIR_NONE 0 -#define UB_DIR_READ 1 -#define UB_DIR_ILLEGAL2 2 -#define UB_DIR_WRITE 3 - -#define UB_DIR_CHAR(c) (((c)==UB_DIR_WRITE)? 'w': \ - (((c)==UB_DIR_READ)? 'r': 'n')) - -enum ub_scsi_cmd_state { - UB_CMDST_INIT, /* Initial state */ - UB_CMDST_CMD, /* Command submitted */ - UB_CMDST_DATA, /* Data phase */ - UB_CMDST_CLR2STS, /* Clearing before requesting status */ - UB_CMDST_STAT, /* Status phase */ - UB_CMDST_CLEAR, /* Clearing a stall (halt, actually) */ - UB_CMDST_CLRRS, /* Clearing before retrying status */ - UB_CMDST_SENSE, /* Sending Request Sense */ - UB_CMDST_DONE /* Final state */ -}; - -struct ub_scsi_cmd { - unsigned char cdb[UB_MAX_CDB_SIZE]; - unsigned char cdb_len; - - unsigned char dir; /* 0 - none, 1 - read, 3 - write. */ - enum ub_scsi_cmd_state state; - unsigned int tag; - struct ub_scsi_cmd *next; - - int error; /* Return code - valid upon done */ - unsigned int act_len; /* Return size */ - unsigned char key, asc, ascq; /* May be valid if error==-EIO */ - - int stat_count; /* Retries getting status. */ - unsigned int timeo; /* jiffies until rq->timeout changes */ - - unsigned int len; /* Requested length */ - unsigned int current_sg; - unsigned int nsg; /* sgv[nsg] */ - struct scatterlist sgv[UB_MAX_REQ_SG]; - - struct ub_lun *lun; - void (*done)(struct ub_dev *, struct ub_scsi_cmd *); - void *back; -}; - -struct ub_request { - struct request *rq; - unsigned int current_try; - unsigned int nsg; /* sgv[nsg] */ - struct scatterlist sgv[UB_MAX_REQ_SG]; -}; - -/* - */ -struct ub_capacity { - unsigned long nsec; /* Linux size - 512 byte sectors */ - unsigned int bsize; /* Linux hardsect_size */ - unsigned int bshift; /* Shift between 512 and hard sects */ -}; - -/* - * This is a direct take-off from linux/include/completion.h - * The difference is that I do not wait on this thing, just poll. - * When I want to wait (ub_probe), I just use the stock completion. - * - * Note that INIT_COMPLETION takes no lock. It is correct. But why - * in the bloody hell that thing takes struct instead of pointer to struct - * is quite beyond me. I just copied it from the stock completion. - */ -struct ub_completion { - unsigned int done; - spinlock_t lock; -}; - -static DEFINE_MUTEX(ub_mutex); -static inline void ub_init_completion(struct ub_completion *x) -{ - x->done = 0; - spin_lock_init(&x->lock); -} - -#define UB_INIT_COMPLETION(x) ((x).done = 0) - -static void ub_complete(struct ub_completion *x) -{ - unsigned long flags; - - spin_lock_irqsave(&x->lock, flags); - x->done++; - spin_unlock_irqrestore(&x->lock, flags); -} - -static int ub_is_completed(struct ub_completion *x) -{ - unsigned long flags; - int ret; - - spin_lock_irqsave(&x->lock, flags); - ret = x->done; - spin_unlock_irqrestore(&x->lock, flags); - return ret; -} - -/* - */ -struct ub_scsi_cmd_queue { - int qlen, qmax; - struct ub_scsi_cmd *head, *tail; -}; - -/* - * The block device instance (one per LUN). - */ -struct ub_lun { - struct ub_dev *udev; - struct list_head link; - struct gendisk *disk; - int id; /* Host index */ - int num; /* LUN number */ - char name[16]; - - int changed; /* Media was changed */ - int removable; - int readonly; - - struct ub_request urq; - - /* Use Ingo's mempool if or when we have more than one command. */ - /* - * Currently we never need more than one command for the whole device. - * However, giving every LUN a command is a cheap and automatic way - * to enforce fairness between them. - */ - int cmda[1]; - struct ub_scsi_cmd cmdv[1]; - - struct ub_capacity capacity; -}; - -/* - * The USB device instance. - */ -struct ub_dev { - spinlock_t *lock; - atomic_t poison; /* The USB device is disconnected */ - int openc; /* protected by ub_lock! */ - /* kref is too implicit for our taste */ - int reset; /* Reset is running */ - int bad_resid; - unsigned int tagcnt; - char name[12]; - struct usb_device *dev; - struct usb_interface *intf; - - struct list_head luns; - - unsigned int send_bulk_pipe; /* cached pipe values */ - unsigned int recv_bulk_pipe; - unsigned int send_ctrl_pipe; - unsigned int recv_ctrl_pipe; - - struct tasklet_struct tasklet; - - struct ub_scsi_cmd_queue cmd_queue; - struct ub_scsi_cmd top_rqs_cmd; /* REQUEST SENSE */ - unsigned char top_sense[UB_SENSE_SIZE]; - - struct ub_completion work_done; - struct urb work_urb; - struct timer_list work_timer; - int last_pipe; /* What might need clearing */ - __le32 signature; /* Learned signature */ - struct bulk_cb_wrap work_bcb; - struct bulk_cs_wrap work_bcs; - struct usb_ctrlrequest work_cr; - - struct work_struct reset_work; - wait_queue_head_t reset_wait; -}; - -/* - */ -static void ub_cleanup(struct ub_dev *sc); -static int ub_request_fn_1(struct ub_lun *lun, struct request *rq); -static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, - struct ub_scsi_cmd *cmd, struct ub_request *urq); -static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, - struct ub_scsi_cmd *cmd, struct ub_request *urq); -static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd); -static void ub_end_rq(struct request *rq, unsigned int status); -static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun, - struct ub_request *urq, struct ub_scsi_cmd *cmd); -static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd); -static void ub_urb_complete(struct urb *urb); -static void ub_scsi_action(unsigned long _dev); -static void ub_scsi_dispatch(struct ub_dev *sc); -static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd); -static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd); -static void ub_state_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int rc); -static int __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd); -static void ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd); -static void ub_state_stat_counted(struct ub_dev *sc, struct ub_scsi_cmd *cmd); -static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd); -static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd, - int stalled_pipe); -static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd); -static void ub_reset_enter(struct ub_dev *sc, int try); -static void ub_reset_task(struct work_struct *work); -static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun); -static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun, - struct ub_capacity *ret); -static int ub_sync_reset(struct ub_dev *sc); -static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe); -static int ub_probe_lun(struct ub_dev *sc, int lnum); - -/* - */ -#ifdef CONFIG_USB_LIBUSUAL - -#define ub_usb_ids usb_storage_usb_ids -#else - -static const struct usb_device_id ub_usb_ids[] = { - { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, USB_SC_SCSI, USB_PR_BULK) }, - { } -}; - -MODULE_DEVICE_TABLE(usb, ub_usb_ids); -#endif /* CONFIG_USB_LIBUSUAL */ - -/* - * Find me a way to identify "next free minor" for add_disk(), - * and the array disappears the next day. However, the number of - * hosts has something to do with the naming and /proc/partitions. - * This has to be thought out in detail before changing. - * If UB_MAX_HOST was 1000, we'd use a bitmap. Or a better data structure. - */ -#define UB_MAX_HOSTS 26 -static char ub_hostv[UB_MAX_HOSTS]; - -#define UB_QLOCK_NUM 5 -static spinlock_t ub_qlockv[UB_QLOCK_NUM]; -static int ub_qlock_next = 0; - -static DEFINE_SPINLOCK(ub_lock); /* Locks globals and ->openc */ - -/* - * The id allocator. - * - * This also stores the host for indexing by minor, which is somewhat dirty. - */ -static int ub_id_get(void) -{ - unsigned long flags; - int i; - - spin_lock_irqsave(&ub_lock, flags); - for (i = 0; i < UB_MAX_HOSTS; i++) { - if (ub_hostv[i] == 0) { - ub_hostv[i] = 1; - spin_unlock_irqrestore(&ub_lock, flags); - return i; - } - } - spin_unlock_irqrestore(&ub_lock, flags); - return -1; -} - -static void ub_id_put(int id) -{ - unsigned long flags; - - if (id < 0 || id >= UB_MAX_HOSTS) { - printk(KERN_ERR DRV_NAME ": bad host ID %d\n", id); - return; - } - - spin_lock_irqsave(&ub_lock, flags); - if (ub_hostv[id] == 0) { - spin_unlock_irqrestore(&ub_lock, flags); - printk(KERN_ERR DRV_NAME ": freeing free host ID %d\n", id); - return; - } - ub_hostv[id] = 0; - spin_unlock_irqrestore(&ub_lock, flags); -} - -/* - * This is necessitated by the fact that blk_cleanup_queue does not - * necesserily destroy the queue. Instead, it may merely decrease q->refcnt. - * Since our blk_init_queue() passes a spinlock common with ub_dev, - * we have life time issues when ub_cleanup frees ub_dev. - */ -static spinlock_t *ub_next_lock(void) -{ - unsigned long flags; - spinlock_t *ret; - - spin_lock_irqsave(&ub_lock, flags); - ret = &ub_qlockv[ub_qlock_next]; - ub_qlock_next = (ub_qlock_next + 1) % UB_QLOCK_NUM; - spin_unlock_irqrestore(&ub_lock, flags); - return ret; -} - -/* - * Downcount for deallocation. This rides on two assumptions: - * - once something is poisoned, its refcount cannot grow - * - opens cannot happen at this time (del_gendisk was done) - * If the above is true, we can drop the lock, which we need for - * blk_cleanup_queue(): the silly thing may attempt to sleep. - * [Actually, it never needs to sleep for us, but it calls might_sleep()] - */ -static void ub_put(struct ub_dev *sc) -{ - unsigned long flags; - - spin_lock_irqsave(&ub_lock, flags); - --sc->openc; - if (sc->openc == 0 && atomic_read(&sc->poison)) { - spin_unlock_irqrestore(&ub_lock, flags); - ub_cleanup(sc); - } else { - spin_unlock_irqrestore(&ub_lock, flags); - } -} - -/* - * Final cleanup and deallocation. - */ -static void ub_cleanup(struct ub_dev *sc) -{ - struct list_head *p; - struct ub_lun *lun; - struct request_queue *q; - - while (!list_empty(&sc->luns)) { - p = sc->luns.next; - lun = list_entry(p, struct ub_lun, link); - list_del(p); - - /* I don't think queue can be NULL. But... Stolen from sx8.c */ - if ((q = lun->disk->queue) != NULL) - blk_cleanup_queue(q); - /* - * If we zero disk->private_data BEFORE put_disk, we have - * to check for NULL all over the place in open, release, - * check_media and revalidate, because the block level - * semaphore is well inside the put_disk. - * But we cannot zero after the call, because *disk is gone. - * The sd.c is blatantly racy in this area. - */ - /* disk->private_data = NULL; */ - put_disk(lun->disk); - lun->disk = NULL; - - ub_id_put(lun->id); - kfree(lun); - } - - usb_set_intfdata(sc->intf, NULL); - usb_put_intf(sc->intf); - usb_put_dev(sc->dev); - kfree(sc); -} - -/* - * The "command allocator". - */ -static struct ub_scsi_cmd *ub_get_cmd(struct ub_lun *lun) -{ - struct ub_scsi_cmd *ret; - - if (lun->cmda[0]) - return NULL; - ret = &lun->cmdv[0]; - lun->cmda[0] = 1; - return ret; -} - -static void ub_put_cmd(struct ub_lun *lun, struct ub_scsi_cmd *cmd) -{ - if (cmd != &lun->cmdv[0]) { - printk(KERN_WARNING "%s: releasing a foreign cmd %p\n", - lun->name, cmd); - return; - } - if (!lun->cmda[0]) { - printk(KERN_WARNING "%s: releasing a free cmd\n", lun->name); - return; - } - lun->cmda[0] = 0; -} - -/* - * The command queue. - */ -static void ub_cmdq_add(struct ub_dev *sc, struct ub_scsi_cmd *cmd) -{ - struct ub_scsi_cmd_queue *t = &sc->cmd_queue; - - if (t->qlen++ == 0) { - t->head = cmd; - t->tail = cmd; - } else { - t->tail->next = cmd; - t->tail = cmd; - } - - if (t->qlen > t->qmax) - t->qmax = t->qlen; -} - -static void ub_cmdq_insert(struct ub_dev *sc, struct ub_scsi_cmd *cmd) -{ - struct ub_scsi_cmd_queue *t = &sc->cmd_queue; - - if (t->qlen++ == 0) { - t->head = cmd; - t->tail = cmd; - } else { - cmd->next = t->head; - t->head = cmd; - } - - if (t->qlen > t->qmax) - t->qmax = t->qlen; -} - -static struct ub_scsi_cmd *ub_cmdq_pop(struct ub_dev *sc) -{ - struct ub_scsi_cmd_queue *t = &sc->cmd_queue; - struct ub_scsi_cmd *cmd; - - if (t->qlen == 0) - return NULL; - if (--t->qlen == 0) - t->tail = NULL; - cmd = t->head; - t->head = cmd->next; - cmd->next = NULL; - return cmd; -} - -#define ub_cmdq_peek(sc) ((sc)->cmd_queue.head) - -/* - * The request function is our main entry point - */ - -static void ub_request_fn(struct request_queue *q) -{ - struct ub_lun *lun = q->queuedata; - struct request *rq; - - while ((rq = blk_peek_request(q)) != NULL) { - if (ub_request_fn_1(lun, rq) != 0) { - blk_stop_queue(q); - break; - } - } -} - -static int ub_request_fn_1(struct ub_lun *lun, struct request *rq) -{ - struct ub_dev *sc = lun->udev; - struct ub_scsi_cmd *cmd; - struct ub_request *urq; - int n_elem; - - if (atomic_read(&sc->poison)) { - blk_start_request(rq); - ub_end_rq(rq, DID_NO_CONNECT << 16); - return 0; - } - - if (lun->changed && rq->cmd_type != REQ_TYPE_BLOCK_PC) { - blk_start_request(rq); - ub_end_rq(rq, SAM_STAT_CHECK_CONDITION); - return 0; - } - - if (lun->urq.rq != NULL) - return -1; - if ((cmd = ub_get_cmd(lun)) == NULL) - return -1; - memset(cmd, 0, sizeof(struct ub_scsi_cmd)); - - blk_start_request(rq); - - urq = &lun->urq; - memset(urq, 0, sizeof(struct ub_request)); - urq->rq = rq; - - /* - * get scatterlist from block layer - */ - sg_init_table(&urq->sgv[0], UB_MAX_REQ_SG); - n_elem = blk_rq_map_sg(lun->disk->queue, rq, &urq->sgv[0]); - if (n_elem < 0) { - /* Impossible, because blk_rq_map_sg should not hit ENOMEM. */ - printk(KERN_INFO "%s: failed request map (%d)\n", - lun->name, n_elem); - goto drop; - } - if (n_elem > UB_MAX_REQ_SG) { /* Paranoia */ - printk(KERN_WARNING "%s: request with %d segments\n", - lun->name, n_elem); - goto drop; - } - urq->nsg = n_elem; - - if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { - ub_cmd_build_packet(sc, lun, cmd, urq); - } else { - ub_cmd_build_block(sc, lun, cmd, urq); - } - cmd->state = UB_CMDST_INIT; - cmd->lun = lun; - cmd->done = ub_rw_cmd_done; - cmd->back = urq; - - cmd->tag = sc->tagcnt++; - if (ub_submit_scsi(sc, cmd) != 0) - goto drop; - - return 0; - -drop: - ub_put_cmd(lun, cmd); - ub_end_rq(rq, DID_ERROR << 16); - return 0; -} - -static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, - struct ub_scsi_cmd *cmd, struct ub_request *urq) -{ - struct request *rq = urq->rq; - unsigned int block, nblks; - - if (rq_data_dir(rq) == WRITE) - cmd->dir = UB_DIR_WRITE; - else - cmd->dir = UB_DIR_READ; - - cmd->nsg = urq->nsg; - memcpy(cmd->sgv, urq->sgv, sizeof(struct scatterlist) * cmd->nsg); - - /* - * build the command - * - * The call to blk_queue_logical_block_size() guarantees that request - * is aligned, but it is given in terms of 512 byte units, always. - */ - block = blk_rq_pos(rq) >> lun->capacity.bshift; - nblks = blk_rq_sectors(rq) >> lun->capacity.bshift; - - cmd->cdb[0] = (cmd->dir == UB_DIR_READ)? READ_10: WRITE_10; - /* 10-byte uses 4 bytes of LBA: 2147483648KB, 2097152MB, 2048GB */ - cmd->cdb[2] = block >> 24; - cmd->cdb[3] = block >> 16; - cmd->cdb[4] = block >> 8; - cmd->cdb[5] = block; - cmd->cdb[7] = nblks >> 8; - cmd->cdb[8] = nblks; - cmd->cdb_len = 10; - - cmd->len = blk_rq_bytes(rq); -} - -static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, - struct ub_scsi_cmd *cmd, struct ub_request *urq) -{ - struct request *rq = urq->rq; - - if (blk_rq_bytes(rq) == 0) { - cmd->dir = UB_DIR_NONE; - } else { - if (rq_data_dir(rq) == WRITE) - cmd->dir = UB_DIR_WRITE; - else - cmd->dir = UB_DIR_READ; - } - - cmd->nsg = urq->nsg; - memcpy(cmd->sgv, urq->sgv, sizeof(struct scatterlist) * cmd->nsg); - - memcpy(&cmd->cdb, rq->cmd, rq->cmd_len); - cmd->cdb_len = rq->cmd_len; - - cmd->len = blk_rq_bytes(rq); - - /* - * To reapply this to every URB is not as incorrect as it looks. - * In return, we avoid any complicated tracking calculations. - */ - cmd->timeo = rq->timeout; -} - -static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd) -{ - struct ub_lun *lun = cmd->lun; - struct ub_request *urq = cmd->back; - struct request *rq; - unsigned int scsi_status; - - rq = urq->rq; - - if (cmd->error == 0) { - if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { - if (cmd->act_len >= rq->resid_len) - rq->resid_len = 0; - else - rq->resid_len -= cmd->act_len; - scsi_status = 0; - } else { - if (cmd->act_len != cmd->len) { - scsi_status = SAM_STAT_CHECK_CONDITION; - } else { - scsi_status = 0; - } - } - } else { - if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { - /* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */ - memcpy(rq->sense, sc->top_sense, UB_SENSE_SIZE); - rq->sense_len = UB_SENSE_SIZE; - if (sc->top_sense[0] != 0) - scsi_status = SAM_STAT_CHECK_CONDITION; - else - scsi_status = DID_ERROR << 16; - } else { - if (cmd->error == -EIO && - (cmd->key == 0 || - cmd->key == MEDIUM_ERROR || - cmd->key == UNIT_ATTENTION)) { - if (ub_rw_cmd_retry(sc, lun, urq, cmd) == 0) - return; - } - scsi_status = SAM_STAT_CHECK_CONDITION; - } - } - - urq->rq = NULL; - - ub_put_cmd(lun, cmd); - ub_end_rq(rq, scsi_status); - blk_start_queue(lun->disk->queue); -} - -static void ub_end_rq(struct request *rq, unsigned int scsi_status) -{ - int error; - - if (scsi_status == 0) { - error = 0; - } else { - error = -EIO; - rq->errors = scsi_status; - } - __blk_end_request_all(rq, error); -} - -static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun, - struct ub_request *urq, struct ub_scsi_cmd *cmd) -{ - - if (atomic_read(&sc->poison)) - return -ENXIO; - - ub_reset_enter(sc, urq->current_try); - - if (urq->current_try >= 3) - return -EIO; - urq->current_try++; - - /* Remove this if anyone complains of flooding. */ - printk(KERN_DEBUG "%s: dir %c len/act %d/%d " - "[sense %x %02x %02x] retry %d\n", - sc->name, UB_DIR_CHAR(cmd->dir), cmd->len, cmd->act_len, - cmd->key, cmd->asc, cmd->ascq, urq->current_try); - - memset(cmd, 0, sizeof(struct ub_scsi_cmd)); - ub_cmd_build_block(sc, lun, cmd, urq); - - cmd->state = UB_CMDST_INIT; - cmd->lun = lun; - cmd->done = ub_rw_cmd_done; - cmd->back = urq; - - cmd->tag = sc->tagcnt++; - -#if 0 /* Wasteful */ - return ub_submit_scsi(sc, cmd); -#else - ub_cmdq_add(sc, cmd); - return 0; -#endif -} - -/* - * Submit a regular SCSI operation (not an auto-sense). - * - * The Iron Law of Good Submit Routine is: - * Zero return - callback is done, Nonzero return - callback is not done. - * No exceptions. - * - * Host is assumed locked. - */ -static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd) -{ - - if (cmd->state != UB_CMDST_INIT || - (cmd->dir != UB_DIR_NONE && cmd->len == 0)) { - return -EINVAL; - } - - ub_cmdq_add(sc, cmd); - /* - * We can call ub_scsi_dispatch(sc) right away here, but it's a little - * safer to jump to a tasklet, in case upper layers do something silly. - */ - tasklet_schedule(&sc->tasklet); - return 0; -} - -/* - * Submit the first URB for the queued command. - * This function does not deal with queueing in any way. - */ -static int ub_scsi_cmd_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd) -{ - struct bulk_cb_wrap *bcb; - int rc; - - bcb = &sc->work_bcb; - - /* - * ``If the allocation length is eighteen or greater, and a device - * server returns less than eithteen bytes of data, the application - * client should assume that the bytes not transferred would have been - * zeroes had the device server returned those bytes.'' - * - * We zero sense for all commands so that when a packet request - * fails it does not return a stale sense. - */ - memset(&sc->top_sense, 0, UB_SENSE_SIZE); - - /* set up the command wrapper */ - bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN); - bcb->Tag = cmd->tag; /* Endianness is not important */ - bcb->DataTransferLength = cpu_to_le32(cmd->len); - bcb->Flags = (cmd->dir == UB_DIR_READ) ? 0x80 : 0; - bcb->Lun = (cmd->lun != NULL) ? cmd->lun->num : 0; - bcb->Length = cmd->cdb_len; - - /* copy the command payload */ - memcpy(bcb->CDB, cmd->cdb, UB_MAX_CDB_SIZE); - - UB_INIT_COMPLETION(sc->work_done); - - sc->last_pipe = sc->send_bulk_pipe; - usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->send_bulk_pipe, - bcb, US_BULK_CB_WRAP_LEN, ub_urb_complete, sc); - - if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { - /* XXX Clear stalls */ - ub_complete(&sc->work_done); - return rc; - } - - sc->work_timer.expires = jiffies + UB_URB_TIMEOUT; - add_timer(&sc->work_timer); - - cmd->state = UB_CMDST_CMD; - return 0; -} - -/* - * Timeout handler. - */ -static void ub_urb_timeout(unsigned long arg) -{ - struct ub_dev *sc = (struct ub_dev *) arg; - unsigned long flags; - - spin_lock_irqsave(sc->lock, flags); - if (!ub_is_completed(&sc->work_done)) - usb_unlink_urb(&sc->work_urb); - spin_unlock_irqrestore(sc->lock, flags); -} - -/* - * Completion routine for the work URB. - * - * This can be called directly from usb_submit_urb (while we have - * the sc->lock taken) and from an interrupt (while we do NOT have - * the sc->lock taken). Therefore, bounce this off to a tasklet. - */ -static void ub_urb_complete(struct urb *urb) -{ - struct ub_dev *sc = urb->context; - - ub_complete(&sc->work_done); - tasklet_schedule(&sc->tasklet); -} - -static void ub_scsi_action(unsigned long _dev) -{ - struct ub_dev *sc = (struct ub_dev *) _dev; - unsigned long flags; - - spin_lock_irqsave(sc->lock, flags); - ub_scsi_dispatch(sc); - spin_unlock_irqrestore(sc->lock, flags); -} - -static void ub_scsi_dispatch(struct ub_dev *sc) -{ - struct ub_scsi_cmd *cmd; - int rc; - - while (!sc->reset && (cmd = ub_cmdq_peek(sc)) != NULL) { - if (cmd->state == UB_CMDST_DONE) { - ub_cmdq_pop(sc); - (*cmd->done)(sc, cmd); - } else if (cmd->state == UB_CMDST_INIT) { - if ((rc = ub_scsi_cmd_start(sc, cmd)) == 0) - break; - cmd->error = rc; - cmd->state = UB_CMDST_DONE; - } else { - if (!ub_is_completed(&sc->work_done)) - break; - del_timer(&sc->work_timer); - ub_scsi_urb_compl(sc, cmd); - } - } -} - -static void ub_scsi_urb_compl(struct ub_dev *sc, struct ub_scsi_cmd *cmd) -{ - struct urb *urb = &sc->work_urb; - struct bulk_cs_wrap *bcs; - int endp; - int len; - int rc; - - if (atomic_read(&sc->poison)) { - ub_state_done(sc, cmd, -ENODEV); - return; - } - - endp = usb_pipeendpoint(sc->last_pipe); - if (usb_pipein(sc->last_pipe)) - endp |= USB_DIR_IN; - - if (cmd->state == UB_CMDST_CLEAR) { - if (urb->status == -EPIPE) { - /* - * STALL while clearning STALL. - * The control pipe clears itself - nothing to do. - */ - printk(KERN_NOTICE "%s: stall on control pipe\n", - sc->name); - goto Bad_End; - } - - /* - * We ignore the result for the halt clear. - */ - - usb_reset_endpoint(sc->dev, endp); - - ub_state_sense(sc, cmd); - - } else if (cmd->state == UB_CMDST_CLR2STS) { - if (urb->status == -EPIPE) { - printk(KERN_NOTICE "%s: stall on control pipe\n", - sc->name); - goto Bad_End; - } - - /* - * We ignore the result for the halt clear. - */ - - usb_reset_endpoint(sc->dev, endp); - - ub_state_stat(sc, cmd); - - } else if (cmd->state == UB_CMDST_CLRRS) { - if (urb->status == -EPIPE) { - printk(KERN_NOTICE "%s: stall on control pipe\n", - sc->name); - goto Bad_End; - } - - /* - * We ignore the result for the halt clear. - */ - - usb_reset_endpoint(sc->dev, endp); - - ub_state_stat_counted(sc, cmd); - - } else if (cmd->state == UB_CMDST_CMD) { - switch (urb->status) { - case 0: - break; - case -EOVERFLOW: - goto Bad_End; - case -EPIPE: - rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe); - if (rc != 0) { - printk(KERN_NOTICE "%s: " - "unable to submit clear (%d)\n", - sc->name, rc); - /* - * This is typically ENOMEM or some other such shit. - * Retrying is pointless. Just do Bad End on it... - */ - ub_state_done(sc, cmd, rc); - return; - } - cmd->state = UB_CMDST_CLEAR; - return; - case -ESHUTDOWN: /* unplug */ - case -EILSEQ: /* unplug timeout on uhci */ - ub_state_done(sc, cmd, -ENODEV); - return; - default: - goto Bad_End; - } - if (urb->actual_length != US_BULK_CB_WRAP_LEN) { - goto Bad_End; - } - - if (cmd->dir == UB_DIR_NONE || cmd->nsg < 1) { - ub_state_stat(sc, cmd); - return; - } - - // udelay(125); // usb-storage has this - ub_data_start(sc, cmd); - - } else if (cmd->state == UB_CMDST_DATA) { - if (urb->status == -EPIPE) { - rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe); - if (rc != 0) { - printk(KERN_NOTICE "%s: " - "unable to submit clear (%d)\n", - sc->name, rc); - ub_state_done(sc, cmd, rc); - return; - } - cmd->state = UB_CMDST_CLR2STS; - return; - } - if (urb->status == -EOVERFLOW) { - /* - * A babble? Failure, but we must transfer CSW now. - */ - cmd->error = -EOVERFLOW; /* A cheap trick... */ - ub_state_stat(sc, cmd); - return; - } - - if (cmd->dir == UB_DIR_WRITE) { - /* - * Do not continue writes in case of a failure. - * Doing so would cause sectors to be mixed up, - * which is worse than sectors lost. - * - * We must try to read the CSW, or many devices - * get confused. - */ - len = urb->actual_length; - if (urb->status != 0 || - len != cmd->sgv[cmd->current_sg].length) { - cmd->act_len += len; - - cmd->error = -EIO; - ub_state_stat(sc, cmd); - return; - } - - } else { - /* - * If an error occurs on read, we record it, and - * continue to fetch data in order to avoid bubble. - * - * As a small shortcut, we stop if we detect that - * a CSW mixed into data. - */ - if (urb->status != 0) - cmd->error = -EIO; - - len = urb->actual_length; - if (urb->status != 0 || - len != cmd->sgv[cmd->current_sg].length) { - if ((len & 0x1FF) == US_BULK_CS_WRAP_LEN) - goto Bad_End; - } - } - - cmd->act_len += urb->actual_length; - - if (++cmd->current_sg < cmd->nsg) { - ub_data_start(sc, cmd); - return; - } - ub_state_stat(sc, cmd); - - } else if (cmd->state == UB_CMDST_STAT) { - if (urb->status == -EPIPE) { - rc = ub_submit_clear_stall(sc, cmd, sc->last_pipe); - if (rc != 0) { - printk(KERN_NOTICE "%s: " - "unable to submit clear (%d)\n", - sc->name, rc); - ub_state_done(sc, cmd, rc); - return; - } - - /* - * Having a stall when getting CSW is an error, so - * make sure uppper levels are not oblivious to it. - */ - cmd->error = -EIO; /* A cheap trick... */ - - cmd->state = UB_CMDST_CLRRS; - return; - } - - /* Catch everything, including -EOVERFLOW and other nasties. */ - if (urb->status != 0) - goto Bad_End; - - if (urb->actual_length == 0) { - ub_state_stat_counted(sc, cmd); - return; - } - - /* - * Check the returned Bulk protocol status. - * The status block has to be validated first. - */ - - bcs = &sc->work_bcs; - - if (sc->signature == cpu_to_le32(0)) { - /* - * This is the first reply, so do not perform the check. - * Instead, remember the signature the device uses - * for future checks. But do not allow a nul. - */ - sc->signature = bcs->Signature; - if (sc->signature == cpu_to_le32(0)) { - ub_state_stat_counted(sc, cmd); - return; - } - } else { - if (bcs->Signature != sc->signature) { - ub_state_stat_counted(sc, cmd); - return; - } - } - - if (bcs->Tag != cmd->tag) { - /* - * This usually happens when we disagree with the - * device's microcode about something. For instance, - * a few of them throw this after timeouts. They buffer - * commands and reply at commands we timed out before. - * Without flushing these replies we loop forever. - */ - ub_state_stat_counted(sc, cmd); - return; - } - - if (!sc->bad_resid) { - len = le32_to_cpu(bcs->Residue); - if (len != cmd->len - cmd->act_len) { - /* - * Only start ignoring if this cmd ended well. - */ - if (cmd->len == cmd->act_len) { - printk(KERN_NOTICE "%s: " - "bad residual %d of %d, ignoring\n", - sc->name, len, cmd->len); - sc->bad_resid = 1; - } - } - } - - switch (bcs->Status) { - case US_BULK_STAT_OK: - break; - case US_BULK_STAT_FAIL: - ub_state_sense(sc, cmd); - return; - case US_BULK_STAT_PHASE: - goto Bad_End; - default: - printk(KERN_INFO "%s: unknown CSW status 0x%x\n", - sc->name, bcs->Status); - ub_state_done(sc, cmd, -EINVAL); - return; - } - - /* Not zeroing error to preserve a babble indicator */ - if (cmd->error != 0) { - ub_state_sense(sc, cmd); - return; - } - cmd->state = UB_CMDST_DONE; - ub_cmdq_pop(sc); - (*cmd->done)(sc, cmd); - - } else if (cmd->state == UB_CMDST_SENSE) { - ub_state_done(sc, cmd, -EIO); - - } else { - printk(KERN_WARNING "%s: wrong command state %d\n", - sc->name, cmd->state); - ub_state_done(sc, cmd, -EINVAL); - return; - } - return; - -Bad_End: /* Little Excel is dead */ - ub_state_done(sc, cmd, -EIO); -} - -/* - * Factorization helper for the command state machine: - * Initiate a data segment transfer. - */ -static void ub_data_start(struct ub_dev *sc, struct ub_scsi_cmd *cmd) -{ - struct scatterlist *sg = &cmd->sgv[cmd->current_sg]; - int pipe; - int rc; - - UB_INIT_COMPLETION(sc->work_done); - - if (cmd->dir == UB_DIR_READ) - pipe = sc->recv_bulk_pipe; - else - pipe = sc->send_bulk_pipe; - sc->last_pipe = pipe; - usb_fill_bulk_urb(&sc->work_urb, sc->dev, pipe, sg_virt(sg), - sg->length, ub_urb_complete, sc); - - if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { - /* XXX Clear stalls */ - ub_complete(&sc->work_done); - ub_state_done(sc, cmd, rc); - return; - } - - if (cmd->timeo) - sc->work_timer.expires = jiffies + cmd->timeo; - else - sc->work_timer.expires = jiffies + UB_DATA_TIMEOUT; - add_timer(&sc->work_timer); - - cmd->state = UB_CMDST_DATA; -} - -/* - * Factorization helper for the command state machine: - * Finish the command. - */ -static void ub_state_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd, int rc) -{ - - cmd->error = rc; - cmd->state = UB_CMDST_DONE; - ub_cmdq_pop(sc); - (*cmd->done)(sc, cmd); -} - -/* - * Factorization helper for the command state machine: - * Submit a CSW read. - */ -static int __ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd) -{ - int rc; - - UB_INIT_COMPLETION(sc->work_done); - - sc->last_pipe = sc->recv_bulk_pipe; - usb_fill_bulk_urb(&sc->work_urb, sc->dev, sc->recv_bulk_pipe, - &sc->work_bcs, US_BULK_CS_WRAP_LEN, ub_urb_complete, sc); - - if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { - /* XXX Clear stalls */ - ub_complete(&sc->work_done); - ub_state_done(sc, cmd, rc); - return -1; - } - - if (cmd->timeo) - sc->work_timer.expires = jiffies + cmd->timeo; - else - sc->work_timer.expires = jiffies + UB_STAT_TIMEOUT; - add_timer(&sc->work_timer); - return 0; -} - -/* - * Factorization helper for the command state machine: - * Submit a CSW read and go to STAT state. - */ -static void ub_state_stat(struct ub_dev *sc, struct ub_scsi_cmd *cmd) -{ - - if (__ub_state_stat(sc, cmd) != 0) - return; - - cmd->stat_count = 0; - cmd->state = UB_CMDST_STAT; -} - -/* - * Factorization helper for the command state machine: - * Submit a CSW read and go to STAT state with counter (along [C] path). - */ -static void ub_state_stat_counted(struct ub_dev *sc, struct ub_scsi_cmd *cmd) -{ - - if (++cmd->stat_count >= 4) { - ub_state_sense(sc, cmd); - return; - } - - if (__ub_state_stat(sc, cmd) != 0) - return; - - cmd->state = UB_CMDST_STAT; -} - -/* - * Factorization helper for the command state machine: - * Submit a REQUEST SENSE and go to SENSE state. - */ -static void ub_state_sense(struct ub_dev *sc, struct ub_scsi_cmd *cmd) -{ - struct ub_scsi_cmd *scmd; - struct scatterlist *sg; - int rc; - - if (cmd->cdb[0] == REQUEST_SENSE) { - rc = -EPIPE; - goto error; - } - - scmd = &sc->top_rqs_cmd; - memset(scmd, 0, sizeof(struct ub_scsi_cmd)); - scmd->cdb[0] = REQUEST_SENSE; - scmd->cdb[4] = UB_SENSE_SIZE; - scmd->cdb_len = 6; - scmd->dir = UB_DIR_READ; - scmd->state = UB_CMDST_INIT; - scmd->nsg = 1; - sg = &scmd->sgv[0]; - sg_init_table(sg, UB_MAX_REQ_SG); - sg_set_page(sg, virt_to_page(sc->top_sense), UB_SENSE_SIZE, - (unsigned long)sc->top_sense & (PAGE_SIZE-1)); - scmd->len = UB_SENSE_SIZE; - scmd->lun = cmd->lun; - scmd->done = ub_top_sense_done; - scmd->back = cmd; - - scmd->tag = sc->tagcnt++; - - cmd->state = UB_CMDST_SENSE; - - ub_cmdq_insert(sc, scmd); - return; - -error: - ub_state_done(sc, cmd, rc); -} - -/* - * A helper for the command's state machine: - * Submit a stall clear. - */ -static int ub_submit_clear_stall(struct ub_dev *sc, struct ub_scsi_cmd *cmd, - int stalled_pipe) -{ - int endp; - struct usb_ctrlrequest *cr; - int rc; - - endp = usb_pipeendpoint(stalled_pipe); - if (usb_pipein (stalled_pipe)) - endp |= USB_DIR_IN; - - cr = &sc->work_cr; - cr->bRequestType = USB_RECIP_ENDPOINT; - cr->bRequest = USB_REQ_CLEAR_FEATURE; - cr->wValue = cpu_to_le16(USB_ENDPOINT_HALT); - cr->wIndex = cpu_to_le16(endp); - cr->wLength = cpu_to_le16(0); - - UB_INIT_COMPLETION(sc->work_done); - - usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe, - (unsigned char*) cr, NULL, 0, ub_urb_complete, sc); - - if ((rc = usb_submit_urb(&sc->work_urb, GFP_ATOMIC)) != 0) { - ub_complete(&sc->work_done); - return rc; - } - - sc->work_timer.expires = jiffies + UB_CTRL_TIMEOUT; - add_timer(&sc->work_timer); - return 0; -} - -/* - */ -static void ub_top_sense_done(struct ub_dev *sc, struct ub_scsi_cmd *scmd) -{ - unsigned char *sense = sc->top_sense; - struct ub_scsi_cmd *cmd; - - /* - * Find the command which triggered the unit attention or a check, - * save the sense into it, and advance its state machine. - */ - if ((cmd = ub_cmdq_peek(sc)) == NULL) { - printk(KERN_WARNING "%s: sense done while idle\n", sc->name); - return; - } - if (cmd != scmd->back) { - printk(KERN_WARNING "%s: " - "sense done for wrong command 0x%x\n", - sc->name, cmd->tag); - return; - } - if (cmd->state != UB_CMDST_SENSE) { - printk(KERN_WARNING "%s: sense done with bad cmd state %d\n", - sc->name, cmd->state); - return; - } - - /* - * Ignoring scmd->act_len, because the buffer was pre-zeroed. - */ - cmd->key = sense[2] & 0x0F; - cmd->asc = sense[12]; - cmd->ascq = sense[13]; - - ub_scsi_urb_compl(sc, cmd); -} - -/* - * Reset management - */ - -static void ub_reset_enter(struct ub_dev *sc, int try) -{ - - if (sc->reset) { - /* This happens often on multi-LUN devices. */ - return; - } - sc->reset = try + 1; - -#if 0 /* Not needed because the disconnect waits for us. */ - unsigned long flags; - spin_lock_irqsave(&ub_lock, flags); - sc->openc++; - spin_unlock_irqrestore(&ub_lock, flags); -#endif - -#if 0 /* We let them stop themselves. */ - struct ub_lun *lun; - list_for_each_entry(lun, &sc->luns, link) { - blk_stop_queue(lun->disk->queue); - } -#endif - - schedule_work(&sc->reset_work); -} - -static void ub_reset_task(struct work_struct *work) -{ - struct ub_dev *sc = container_of(work, struct ub_dev, reset_work); - unsigned long flags; - struct ub_lun *lun; - int rc; - - if (!sc->reset) { - printk(KERN_WARNING "%s: Running reset unrequested\n", - sc->name); - return; - } - - if (atomic_read(&sc->poison)) { - ; - } else if ((sc->reset & 1) == 0) { - ub_sync_reset(sc); - msleep(700); /* usb-storage sleeps 6s (!) */ - ub_probe_clear_stall(sc, sc->recv_bulk_pipe); - ub_probe_clear_stall(sc, sc->send_bulk_pipe); - } else if (sc->dev->actconfig->desc.bNumInterfaces != 1) { - ; - } else { - rc = usb_lock_device_for_reset(sc->dev, sc->intf); - if (rc < 0) { - printk(KERN_NOTICE - "%s: usb_lock_device_for_reset failed (%d)\n", - sc->name, rc); - } else { - rc = usb_reset_device(sc->dev); - if (rc < 0) { - printk(KERN_NOTICE "%s: " - "usb_lock_device_for_reset failed (%d)\n", - sc->name, rc); - } - usb_unlock_device(sc->dev); - } - } - - /* - * In theory, no commands can be running while reset is active, - * so nobody can ask for another reset, and so we do not need any - * queues of resets or anything. We do need a spinlock though, - * to interact with block layer. - */ - spin_lock_irqsave(sc->lock, flags); - sc->reset = 0; - tasklet_schedule(&sc->tasklet); - list_for_each_entry(lun, &sc->luns, link) { - blk_start_queue(lun->disk->queue); - } - wake_up(&sc->reset_wait); - spin_unlock_irqrestore(sc->lock, flags); -} - -/* - * XXX Reset brackets are too much hassle to implement, so just stub them - * in order to prevent forced unbinding (which deadlocks solid when our - * ->disconnect method waits for the reset to complete and this kills keventd). - * - * XXX Tell Alan to move usb_unlock_device inside of usb_reset_device, - * or else the post_reset is invoked, and restats I/O on a locked device. - */ -static int ub_pre_reset(struct usb_interface *iface) { - return 0; -} - -static int ub_post_reset(struct usb_interface *iface) { - return 0; -} - -/* - * This is called from a process context. - */ -static void ub_revalidate(struct ub_dev *sc, struct ub_lun *lun) -{ - - lun->readonly = 0; /* XXX Query this from the device */ - - lun->capacity.nsec = 0; - lun->capacity.bsize = 512; - lun->capacity.bshift = 0; - - if (ub_sync_tur(sc, lun) != 0) - return; /* Not ready */ - lun->changed = 0; - - if (ub_sync_read_cap(sc, lun, &lun->capacity) != 0) { - /* - * The retry here means something is wrong, either with the - * device, with the transport, or with our code. - * We keep this because sd.c has retries for capacity. - */ - if (ub_sync_read_cap(sc, lun, &lun->capacity) != 0) { - lun->capacity.nsec = 0; - lun->capacity.bsize = 512; - lun->capacity.bshift = 0; - } - } -} - -/* - * The open funcion. - * This is mostly needed to keep refcounting, but also to support - * media checks on removable media drives. - */ -static int ub_bd_open(struct block_device *bdev, fmode_t mode) -{ - struct ub_lun *lun = bdev->bd_disk->private_data; - struct ub_dev *sc = lun->udev; - unsigned long flags; - int rc; - - spin_lock_irqsave(&ub_lock, flags); - if (atomic_read(&sc->poison)) { - spin_unlock_irqrestore(&ub_lock, flags); - return -ENXIO; - } - sc->openc++; - spin_unlock_irqrestore(&ub_lock, flags); - - if (lun->removable || lun->readonly) - check_disk_change(bdev); - - /* - * The sd.c considers ->media_present and ->changed not equivalent, - * under some pretty murky conditions (a failure of READ CAPACITY). - * We may need it one day. - */ - if (lun->removable && lun->changed && !(mode & FMODE_NDELAY)) { - rc = -ENOMEDIUM; - goto err_open; - } - - if (lun->readonly && (mode & FMODE_WRITE)) { - rc = -EROFS; - goto err_open; - } - - return 0; - -err_open: - ub_put(sc); - return rc; -} - -static int ub_bd_unlocked_open(struct block_device *bdev, fmode_t mode) -{ - int ret; - - mutex_lock(&ub_mutex); - ret = ub_bd_open(bdev, mode); - mutex_unlock(&ub_mutex); - - return ret; -} - - -/* - */ -static int ub_bd_release(struct gendisk *disk, fmode_t mode) -{ - struct ub_lun *lun = disk->private_data; - struct ub_dev *sc = lun->udev; - - mutex_lock(&ub_mutex); - ub_put(sc); - mutex_unlock(&ub_mutex); - - return 0; -} - -/* - * The ioctl interface. - */ -static int ub_bd_ioctl(struct block_device *bdev, fmode_t mode, - unsigned int cmd, unsigned long arg) -{ - void __user *usermem = (void __user *) arg; - int ret; - - mutex_lock(&ub_mutex); - ret = scsi_cmd_blk_ioctl(bdev, mode, cmd, usermem); - mutex_unlock(&ub_mutex); - - return ret; -} - -/* - * This is called by check_disk_change if we reported a media change. - * The main onjective here is to discover the features of the media such as - * the capacity, read-only status, etc. USB storage generally does not - * need to be spun up, but if we needed it, this would be the place. - * - * This call can sleep. - * - * The return code is not used. - */ -static int ub_bd_revalidate(struct gendisk *disk) -{ - struct ub_lun *lun = disk->private_data; - - ub_revalidate(lun->udev, lun); - - /* XXX Support sector size switching like in sr.c */ - blk_queue_logical_block_size(disk->queue, lun->capacity.bsize); - set_capacity(disk, lun->capacity.nsec); - // set_disk_ro(sdkp->disk, lun->readonly); - - return 0; -} - -/* - * The check is called by the block layer to verify if the media - * is still available. It is supposed to be harmless, lightweight and - * non-intrusive in case the media was not changed. - * - * This call can sleep. - * - * The return code is bool! - */ -static unsigned int ub_bd_check_events(struct gendisk *disk, - unsigned int clearing) -{ - struct ub_lun *lun = disk->private_data; - - if (!lun->removable) - return 0; - - /* - * We clean checks always after every command, so this is not - * as dangerous as it looks. If the TEST_UNIT_READY fails here, - * the device is actually not ready with operator or software - * intervention required. One dangerous item might be a drive which - * spins itself down, and come the time to write dirty pages, this - * will fail, then block layer discards the data. Since we never - * spin drives up, such devices simply cannot be used with ub anyway. - */ - if (ub_sync_tur(lun->udev, lun) != 0) { - lun->changed = 1; - return DISK_EVENT_MEDIA_CHANGE; - } - - return lun->changed ? DISK_EVENT_MEDIA_CHANGE : 0; -} - -static const struct block_device_operations ub_bd_fops = { - .owner = THIS_MODULE, - .open = ub_bd_unlocked_open, - .release = ub_bd_release, - .ioctl = ub_bd_ioctl, - .check_events = ub_bd_check_events, - .revalidate_disk = ub_bd_revalidate, -}; - -/* - * Common ->done routine for commands executed synchronously. - */ -static void ub_probe_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd) -{ - struct completion *cop = cmd->back; - complete(cop); -} - -/* - * Test if the device has a check condition on it, synchronously. - */ -static int ub_sync_tur(struct ub_dev *sc, struct ub_lun *lun) -{ - struct ub_scsi_cmd *cmd; - enum { ALLOC_SIZE = sizeof(struct ub_scsi_cmd) }; - unsigned long flags; - struct completion compl; - int rc; - - init_completion(&compl); - - rc = -ENOMEM; - if ((cmd = kzalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL) - goto err_alloc; - - cmd->cdb[0] = TEST_UNIT_READY; - cmd->cdb_len = 6; - cmd->dir = UB_DIR_NONE; - cmd->state = UB_CMDST_INIT; - cmd->lun = lun; /* This may be NULL, but that's ok */ - cmd->done = ub_probe_done; - cmd->back = &compl; - - spin_lock_irqsave(sc->lock, flags); - cmd->tag = sc->tagcnt++; - - rc = ub_submit_scsi(sc, cmd); - spin_unlock_irqrestore(sc->lock, flags); - - if (rc != 0) - goto err_submit; - - wait_for_completion(&compl); - - rc = cmd->error; - - if (rc == -EIO && cmd->key != 0) /* Retries for benh's key */ - rc = cmd->key; - -err_submit: - kfree(cmd); -err_alloc: - return rc; -} - -/* - * Read the SCSI capacity synchronously (for probing). - */ -static int ub_sync_read_cap(struct ub_dev *sc, struct ub_lun *lun, - struct ub_capacity *ret) -{ - struct ub_scsi_cmd *cmd; - struct scatterlist *sg; - char *p; - enum { ALLOC_SIZE = sizeof(struct ub_scsi_cmd) + 8 }; - unsigned long flags; - unsigned int bsize, shift; - unsigned long nsec; - struct completion compl; - int rc; - - init_completion(&compl); - - rc = -ENOMEM; - if ((cmd = kzalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL) - goto err_alloc; - p = (char *)cmd + sizeof(struct ub_scsi_cmd); - - cmd->cdb[0] = 0x25; - cmd->cdb_len = 10; - cmd->dir = UB_DIR_READ; - cmd->state = UB_CMDST_INIT; - cmd->nsg = 1; - sg = &cmd->sgv[0]; - sg_init_table(sg, UB_MAX_REQ_SG); - sg_set_page(sg, virt_to_page(p), 8, (unsigned long)p & (PAGE_SIZE-1)); - cmd->len = 8; - cmd->lun = lun; - cmd->done = ub_probe_done; - cmd->back = &compl; - - spin_lock_irqsave(sc->lock, flags); - cmd->tag = sc->tagcnt++; - - rc = ub_submit_scsi(sc, cmd); - spin_unlock_irqrestore(sc->lock, flags); - - if (rc != 0) - goto err_submit; - - wait_for_completion(&compl); - - if (cmd->error != 0) { - rc = -EIO; - goto err_read; - } - if (cmd->act_len != 8) { - rc = -EIO; - goto err_read; - } - - /* sd.c special-cases sector size of 0 to mean 512. Needed? Safe? */ - nsec = be32_to_cpu(*(__be32 *)p) + 1; - bsize = be32_to_cpu(*(__be32 *)(p + 4)); - switch (bsize) { - case 512: shift = 0; break; - case 1024: shift = 1; break; - case 2048: shift = 2; break; - case 4096: shift = 3; break; - default: - rc = -EDOM; - goto err_inv_bsize; - } - - ret->bsize = bsize; - ret->bshift = shift; - ret->nsec = nsec << shift; - rc = 0; - -err_inv_bsize: -err_read: -err_submit: - kfree(cmd); -err_alloc: - return rc; -} - -/* - */ -static void ub_probe_urb_complete(struct urb *urb) -{ - struct completion *cop = urb->context; - complete(cop); -} - -static void ub_probe_timeout(unsigned long arg) -{ - struct completion *cop = (struct completion *) arg; - complete(cop); -} - -/* - * Reset with a Bulk reset. - */ -static int ub_sync_reset(struct ub_dev *sc) -{ - int ifnum = sc->intf->cur_altsetting->desc.bInterfaceNumber; - struct usb_ctrlrequest *cr; - struct completion compl; - struct timer_list timer; - int rc; - - init_completion(&compl); - - cr = &sc->work_cr; - cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE; - cr->bRequest = US_BULK_RESET_REQUEST; - cr->wValue = cpu_to_le16(0); - cr->wIndex = cpu_to_le16(ifnum); - cr->wLength = cpu_to_le16(0); - - usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe, - (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl); - - if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) { - printk(KERN_WARNING - "%s: Unable to submit a bulk reset (%d)\n", sc->name, rc); - return rc; - } - - init_timer(&timer); - timer.function = ub_probe_timeout; - timer.data = (unsigned long) &compl; - timer.expires = jiffies + UB_CTRL_TIMEOUT; - add_timer(&timer); - - wait_for_completion(&compl); - - del_timer_sync(&timer); - usb_kill_urb(&sc->work_urb); - - return sc->work_urb.status; -} - -/* - * Get number of LUNs by the way of Bulk GetMaxLUN command. - */ -static int ub_sync_getmaxlun(struct ub_dev *sc) -{ - int ifnum = sc->intf->cur_altsetting->desc.bInterfaceNumber; - unsigned char *p; - enum { ALLOC_SIZE = 1 }; - struct usb_ctrlrequest *cr; - struct completion compl; - struct timer_list timer; - int nluns; - int rc; - - init_completion(&compl); - - rc = -ENOMEM; - if ((p = kmalloc(ALLOC_SIZE, GFP_KERNEL)) == NULL) - goto err_alloc; - *p = 55; - - cr = &sc->work_cr; - cr->bRequestType = USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE; - cr->bRequest = US_BULK_GET_MAX_LUN; - cr->wValue = cpu_to_le16(0); - cr->wIndex = cpu_to_le16(ifnum); - cr->wLength = cpu_to_le16(1); - - usb_fill_control_urb(&sc->work_urb, sc->dev, sc->recv_ctrl_pipe, - (unsigned char*) cr, p, 1, ub_probe_urb_complete, &compl); - - if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) - goto err_submit; - - init_timer(&timer); - timer.function = ub_probe_timeout; - timer.data = (unsigned long) &compl; - timer.expires = jiffies + UB_CTRL_TIMEOUT; - add_timer(&timer); - - wait_for_completion(&compl); - - del_timer_sync(&timer); - usb_kill_urb(&sc->work_urb); - - if ((rc = sc->work_urb.status) < 0) - goto err_io; - - if (sc->work_urb.actual_length != 1) { - nluns = 0; - } else { - if ((nluns = *p) == 55) { - nluns = 0; - } else { - /* GetMaxLUN returns the maximum LUN number */ - nluns += 1; - if (nluns > UB_MAX_LUNS) - nluns = UB_MAX_LUNS; - } - } - - kfree(p); - return nluns; - -err_io: -err_submit: - kfree(p); -err_alloc: - return rc; -} - -/* - * Clear initial stalls. - */ -static int ub_probe_clear_stall(struct ub_dev *sc, int stalled_pipe) -{ - int endp; - struct usb_ctrlrequest *cr; - struct completion compl; - struct timer_list timer; - int rc; - - init_completion(&compl); - - endp = usb_pipeendpoint(stalled_pipe); - if (usb_pipein (stalled_pipe)) - endp |= USB_DIR_IN; - - cr = &sc->work_cr; - cr->bRequestType = USB_RECIP_ENDPOINT; - cr->bRequest = USB_REQ_CLEAR_FEATURE; - cr->wValue = cpu_to_le16(USB_ENDPOINT_HALT); - cr->wIndex = cpu_to_le16(endp); - cr->wLength = cpu_to_le16(0); - - usb_fill_control_urb(&sc->work_urb, sc->dev, sc->send_ctrl_pipe, - (unsigned char*) cr, NULL, 0, ub_probe_urb_complete, &compl); - - if ((rc = usb_submit_urb(&sc->work_urb, GFP_KERNEL)) != 0) { - printk(KERN_WARNING - "%s: Unable to submit a probe clear (%d)\n", sc->name, rc); - return rc; - } - - init_timer(&timer); - timer.function = ub_probe_timeout; - timer.data = (unsigned long) &compl; - timer.expires = jiffies + UB_CTRL_TIMEOUT; - add_timer(&timer); - - wait_for_completion(&compl); - - del_timer_sync(&timer); - usb_kill_urb(&sc->work_urb); - - usb_reset_endpoint(sc->dev, endp); - - return 0; -} - -/* - * Get the pipe settings. - */ -static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev, - struct usb_interface *intf) -{ - struct usb_host_interface *altsetting = intf->cur_altsetting; - struct usb_endpoint_descriptor *ep_in = NULL; - struct usb_endpoint_descriptor *ep_out = NULL; - struct usb_endpoint_descriptor *ep; - int i; - - /* - * Find the endpoints we need. - * We are expecting a minimum of 2 endpoints - in and out (bulk). - * We will ignore any others. - */ - for (i = 0; i < altsetting->desc.bNumEndpoints; i++) { - ep = &altsetting->endpoint[i].desc; - - /* Is it a BULK endpoint? */ - if (usb_endpoint_xfer_bulk(ep)) { - /* BULK in or out? */ - if (usb_endpoint_dir_in(ep)) { - if (ep_in == NULL) - ep_in = ep; - } else { - if (ep_out == NULL) - ep_out = ep; - } - } - } - - if (ep_in == NULL || ep_out == NULL) { - printk(KERN_NOTICE "%s: failed endpoint check\n", sc->name); - return -ENODEV; - } - - /* Calculate and store the pipe values */ - sc->send_ctrl_pipe = usb_sndctrlpipe(dev, 0); - sc->recv_ctrl_pipe = usb_rcvctrlpipe(dev, 0); - sc->send_bulk_pipe = usb_sndbulkpipe(dev, - usb_endpoint_num(ep_out)); - sc->recv_bulk_pipe = usb_rcvbulkpipe(dev, - usb_endpoint_num(ep_in)); - - return 0; -} - -/* - * Probing is done in the process context, which allows us to cheat - * and not to build a state machine for the discovery. - */ -static int ub_probe(struct usb_interface *intf, - const struct usb_device_id *dev_id) -{ - struct ub_dev *sc; - int nluns; - int rc; - int i; - - if (usb_usual_check_type(dev_id, USB_US_TYPE_UB)) - return -ENXIO; - - rc = -ENOMEM; - if ((sc = kzalloc(sizeof(struct ub_dev), GFP_KERNEL)) == NULL) - goto err_core; - sc->lock = ub_next_lock(); - INIT_LIST_HEAD(&sc->luns); - usb_init_urb(&sc->work_urb); - tasklet_init(&sc->tasklet, ub_scsi_action, (unsigned long)sc); - atomic_set(&sc->poison, 0); - INIT_WORK(&sc->reset_work, ub_reset_task); - init_waitqueue_head(&sc->reset_wait); - - init_timer(&sc->work_timer); - sc->work_timer.data = (unsigned long) sc; - sc->work_timer.function = ub_urb_timeout; - - ub_init_completion(&sc->work_done); - sc->work_done.done = 1; /* A little yuk, but oh well... */ - - sc->dev = interface_to_usbdev(intf); - sc->intf = intf; - // sc->ifnum = intf->cur_altsetting->desc.bInterfaceNumber; - usb_set_intfdata(intf, sc); - usb_get_dev(sc->dev); - /* - * Since we give the interface struct to the block level through - * disk->driverfs_dev, we have to pin it. Otherwise, block_uevent - * oopses on close after a disconnect (kernels 2.6.16 and up). - */ - usb_get_intf(sc->intf); - - snprintf(sc->name, 12, DRV_NAME "(%d.%d)", - sc->dev->bus->busnum, sc->dev->devnum); - - /* XXX Verify that we can handle the device (from descriptors) */ - - if (ub_get_pipes(sc, sc->dev, intf) != 0) - goto err_dev_desc; - - /* - * At this point, all USB initialization is done, do upper layer. - * We really hate halfway initialized structures, so from the - * invariants perspective, this ub_dev is fully constructed at - * this point. - */ - - /* - * This is needed to clear toggles. It is a problem only if we do - * `rmmod ub && modprobe ub` without disconnects, but we like that. - */ -#if 0 /* iPod Mini fails if we do this (big white iPod works) */ - ub_probe_clear_stall(sc, sc->recv_bulk_pipe); - ub_probe_clear_stall(sc, sc->send_bulk_pipe); -#endif - - /* - * The way this is used by the startup code is a little specific. - * A SCSI check causes a USB stall. Our common case code sees it - * and clears the check, after which the device is ready for use. - * But if a check was not present, any command other than - * TEST_UNIT_READY ends with a lockup (including REQUEST_SENSE). - * - * If we neglect to clear the SCSI check, the first real command fails - * (which is the capacity readout). We clear that and retry, but why - * causing spurious retries for no reason. - * - * Revalidation may start with its own TEST_UNIT_READY, but that one - * has to succeed, so we clear checks with an additional one here. - * In any case it's not our business how revaliadation is implemented. - */ - for (i = 0; i < 3; i++) { /* Retries for the schwag key from KS'04 */ - if ((rc = ub_sync_tur(sc, NULL)) <= 0) break; - if (rc != 0x6) break; - msleep(10); - } - - nluns = 1; - for (i = 0; i < 3; i++) { - if ((rc = ub_sync_getmaxlun(sc)) < 0) - break; - if (rc != 0) { - nluns = rc; - break; - } - msleep(100); - } - - for (i = 0; i < nluns; i++) { - ub_probe_lun(sc, i); - } - return 0; - -err_dev_desc: - usb_set_intfdata(intf, NULL); - usb_put_intf(sc->intf); - usb_put_dev(sc->dev); - kfree(sc); -err_core: - return rc; -} - -static int ub_probe_lun(struct ub_dev *sc, int lnum) -{ - struct ub_lun *lun; - struct request_queue *q; - struct gendisk *disk; - int rc; - - rc = -ENOMEM; - if ((lun = kzalloc(sizeof(struct ub_lun), GFP_KERNEL)) == NULL) - goto err_alloc; - lun->num = lnum; - - rc = -ENOSR; - if ((lun->id = ub_id_get()) == -1) - goto err_id; - - lun->udev = sc; - - snprintf(lun->name, 16, DRV_NAME "%c(%d.%d.%d)", - lun->id + 'a', sc->dev->bus->busnum, sc->dev->devnum, lun->num); - - lun->removable = 1; /* XXX Query this from the device */ - lun->changed = 1; /* ub_revalidate clears only */ - ub_revalidate(sc, lun); - - rc = -ENOMEM; - if ((disk = alloc_disk(UB_PARTS_PER_LUN)) == NULL) - goto err_diskalloc; - - sprintf(disk->disk_name, DRV_NAME "%c", lun->id + 'a'); - disk->major = UB_MAJOR; - disk->first_minor = lun->id * UB_PARTS_PER_LUN; - disk->fops = &ub_bd_fops; - disk->private_data = lun; - disk->driverfs_dev = &sc->intf->dev; - - rc = -ENOMEM; - if ((q = blk_init_queue(ub_request_fn, sc->lock)) == NULL) - goto err_blkqinit; - - disk->queue = q; - - blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH); - blk_queue_max_segments(q, UB_MAX_REQ_SG); - blk_queue_segment_boundary(q, 0xffffffff); /* Dubious. */ - blk_queue_max_hw_sectors(q, UB_MAX_SECTORS); - blk_queue_logical_block_size(q, lun->capacity.bsize); - - lun->disk = disk; - q->queuedata = lun; - list_add(&lun->link, &sc->luns); - - set_capacity(disk, lun->capacity.nsec); - if (lun->removable) - disk->flags |= GENHD_FL_REMOVABLE; - - add_disk(disk); - - return 0; - -err_blkqinit: - put_disk(disk); -err_diskalloc: - ub_id_put(lun->id); -err_id: - kfree(lun); -err_alloc: - return rc; -} - -static void ub_disconnect(struct usb_interface *intf) -{ - struct ub_dev *sc = usb_get_intfdata(intf); - struct ub_lun *lun; - unsigned long flags; - - /* - * Prevent ub_bd_release from pulling the rug from under us. - * XXX This is starting to look like a kref. - * XXX Why not to take this ref at probe time? - */ - spin_lock_irqsave(&ub_lock, flags); - sc->openc++; - spin_unlock_irqrestore(&ub_lock, flags); - - /* - * Fence stall clearings, operations triggered by unlinkings and so on. - * We do not attempt to unlink any URBs, because we do not trust the - * unlink paths in HC drivers. Also, we get -84 upon disconnect anyway. - */ - atomic_set(&sc->poison, 1); - - /* - * Wait for reset to end, if any. - */ - wait_event(sc->reset_wait, !sc->reset); - - /* - * Blow away queued commands. - * - * Actually, this never works, because before we get here - * the HCD terminates outstanding URB(s). It causes our - * SCSI command queue to advance, commands fail to submit, - * and the whole queue drains. So, we just use this code to - * print warnings. - */ - spin_lock_irqsave(sc->lock, flags); - { - struct ub_scsi_cmd *cmd; - int cnt = 0; - while ((cmd = ub_cmdq_peek(sc)) != NULL) { - cmd->error = -ENOTCONN; - cmd->state = UB_CMDST_DONE; - ub_cmdq_pop(sc); - (*cmd->done)(sc, cmd); - cnt++; - } - if (cnt != 0) { - printk(KERN_WARNING "%s: " - "%d was queued after shutdown\n", sc->name, cnt); - } - } - spin_unlock_irqrestore(sc->lock, flags); - - /* - * Unregister the upper layer. - */ - list_for_each_entry(lun, &sc->luns, link) { - del_gendisk(lun->disk); - /* - * I wish I could do: - * queue_flag_set(QUEUE_FLAG_DEAD, q); - * As it is, we rely on our internal poisoning and let - * the upper levels to spin furiously failing all the I/O. - */ - } - - /* - * Testing for -EINPROGRESS is always a bug, so we are bending - * the rules a little. - */ - spin_lock_irqsave(sc->lock, flags); - if (sc->work_urb.status == -EINPROGRESS) { /* janitors: ignore */ - printk(KERN_WARNING "%s: " - "URB is active after disconnect\n", sc->name); - } - spin_unlock_irqrestore(sc->lock, flags); - - /* - * There is virtually no chance that other CPU runs a timeout so long - * after ub_urb_complete should have called del_timer, but only if HCD - * didn't forget to deliver a callback on unlink. - */ - del_timer_sync(&sc->work_timer); - - /* - * At this point there must be no commands coming from anyone - * and no URBs left in transit. - */ - - ub_put(sc); -} - -static struct usb_driver ub_driver = { - .name = "ub", - .probe = ub_probe, - .disconnect = ub_disconnect, - .id_table = ub_usb_ids, - .pre_reset = ub_pre_reset, - .post_reset = ub_post_reset, -}; - -static int __init ub_init(void) -{ - int rc; - int i; - - pr_info("'Low Performance USB Block' driver is deprecated. " - "Please switch to usb-storage\n"); - for (i = 0; i < UB_QLOCK_NUM; i++) - spin_lock_init(&ub_qlockv[i]); - - if ((rc = register_blkdev(UB_MAJOR, DRV_NAME)) != 0) - goto err_regblkdev; - - if ((rc = usb_register(&ub_driver)) != 0) - goto err_register; - - usb_usual_set_present(USB_US_TYPE_UB); - return 0; - -err_register: - unregister_blkdev(UB_MAJOR, DRV_NAME); -err_regblkdev: - return rc; -} - -static void __exit ub_exit(void) -{ - usb_deregister(&ub_driver); - - unregister_blkdev(UB_MAJOR, DRV_NAME); - usb_usual_clear_present(USB_US_TYPE_UB); -} - -module_init(ub_init); -module_exit(ub_exit); - -MODULE_LICENSE("GPL"); -- cgit v0.10.2 From f61870ee6f8cc77a844e22f26c58028078df7167 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Tue, 28 Aug 2012 22:37:13 +0200 Subject: usb: remove libusual The "Low Performance USB Block driver" has been removed which a user of libusual. Now we have only the usb-storage driver as the only driver in tree. This makes libusual needless. This patch removes libusal, fixes up all users. The usual-table is now linked into usb-storage. usb_usual.h remains in public include directory because some staging users seem to need it. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/keucr/usb.c b/drivers/staging/keucr/usb.c index 4833034..55a0b82 100644 --- a/drivers/staging/keucr/usb.c +++ b/drivers/staging/keucr/usb.c @@ -320,7 +320,7 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id) us->subclass = idesc->bInterfaceSubClass; us->protocol = idesc->bInterfaceProtocol; - us->fflags = USB_US_ORIG_FLAGS(id->driver_info); + us->fflags = id->driver_info; us->Power_IsResum = false; if (us->fflags & US_FL_IGNORE_DEVICE) diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 7691c86..0ae7bb6 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -213,17 +213,3 @@ config USB_UAS say 'Y' or 'M' here and the kernel will use the right driver. If you compile this driver as a module, it will be named uas. - -config USB_LIBUSUAL - bool "The shared table of common (or usual) storage devices" - depends on USB - help - This module contains a table of common (or usual) devices - for usb-storage and ub drivers, and allows to switch binding - of these devices without rebuilding modules. - - Typical syntax of /etc/modprobe.d/*conf is: - - options libusual bias="ub" - - If unsure, say N. diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 82e6416..4cd5548 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -12,16 +12,9 @@ obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-y := scsiglue.o protocol.o transport.o usb.o usb-storage-y += initializers.o sierra_ms.o option_ms.o - +usb-storage-y += usual-tables.o usb-storage-$(CONFIG_USB_STORAGE_DEBUG) += debug.o -ifeq ($(CONFIG_USB_LIBUSUAL),) - usb-storage-y += usual-tables.o -else - obj-$(CONFIG_USB) += usb-libusual.o - usb-libusual-y := libusual.o usual-tables.o -endif - obj-$(CONFIG_USB_STORAGE_ALAUDA) += ums-alauda.o obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o obj-$(CONFIG_USB_STORAGE_DATAFAB) += ums-datafab.o diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c index bab8c8f..be5564c 100644 --- a/drivers/usb/storage/alauda.c +++ b/drivers/usb/storage/alauda.c @@ -137,7 +137,7 @@ static int init_alauda(struct us_data *us); vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + .driver_info = (flags) } static struct usb_device_id alauda_usb_ids[] = { # include "unusual_alauda.h" diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c index 5fe451d..070b5c0 100644 --- a/drivers/usb/storage/cypress_atacb.c +++ b/drivers/usb/storage/cypress_atacb.c @@ -41,7 +41,7 @@ MODULE_LICENSE("GPL"); vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + .driver_info = (flags) } static struct usb_device_id cypress_usb_ids[] = { # include "unusual_cypress.h" diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c index 35e9c51..494fee5 100644 --- a/drivers/usb/storage/datafab.c +++ b/drivers/usb/storage/datafab.c @@ -86,7 +86,7 @@ static int datafab_determine_lun(struct us_data *us, vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + .driver_info = (flags) } static struct usb_device_id datafab_usb_ids[] = { # include "unusual_datafab.h" diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c index 95edee5..118b134 100644 --- a/drivers/usb/storage/ene_ub6250.c +++ b/drivers/usb/storage/ene_ub6250.c @@ -52,7 +52,7 @@ MODULE_FIRMWARE(MS_RW_FIRMWARE); vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + .driver_info = (flags)} static struct usb_device_id ene_ub6250_usb_ids[] = { # include "unusual_ene_ub6250.h" diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c index 042cf9e..e6df087 100644 --- a/drivers/usb/storage/freecom.c +++ b/drivers/usb/storage/freecom.c @@ -117,7 +117,7 @@ static int init_freecom(struct us_data *us); vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + .driver_info = (flags) } static struct usb_device_id freecom_usb_ids[] = { # include "unusual_freecom.h" diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index 31fa24e..ecea478 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -74,7 +74,7 @@ static int isd200_Initialization(struct us_data *us); vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + .driver_info = (flags) } static struct usb_device_id isd200_usb_ids[] = { # include "unusual_isd200.h" @@ -83,7 +83,6 @@ static struct usb_device_id isd200_usb_ids[] = { MODULE_DEVICE_TABLE(usb, isd200_usb_ids); #undef UNUSUAL_DEV -#undef USUAL_DEV /* * The flags table @@ -105,8 +104,6 @@ static struct us_unusual_dev isd200_unusual_dev_list[] = { }; #undef UNUSUAL_DEV -#undef USUAL_DEV - /* Timeout defines (in Seconds) */ diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c index e3b9738..ddc7878 100644 --- a/drivers/usb/storage/jumpshot.c +++ b/drivers/usb/storage/jumpshot.c @@ -69,7 +69,7 @@ MODULE_LICENSE("GPL"); vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + .driver_info = (flags) } static struct usb_device_id jumpshot_usb_ids[] = { # include "unusual_jumpshot.h" diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c index a8708ea..f085ffb 100644 --- a/drivers/usb/storage/karma.c +++ b/drivers/usb/storage/karma.c @@ -57,7 +57,7 @@ static int rio_karma_init(struct us_data *us); vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + .driver_info = (flags) } static struct usb_device_id karma_usb_ids[] = { # include "unusual_karma.h" diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c deleted file mode 100644 index fe3ffe1..0000000 --- a/drivers/usb/storage/libusual.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - * libusual - * - * The libusual contains the table of devices common for ub and usb-storage. - */ -#include -#include -#include -#include -#include -#include -#include - -/* - */ -#define USU_MOD_FL_THREAD 1 /* Thread is running */ -#define USU_MOD_FL_PRESENT 2 /* The module is loaded */ - -struct mod_status { - unsigned long fls; -}; - -static struct mod_status stat[3]; -static DEFINE_SPINLOCK(usu_lock); - -/* - */ -#define USB_US_DEFAULT_BIAS USB_US_TYPE_STOR -static atomic_t usu_bias = ATOMIC_INIT(USB_US_DEFAULT_BIAS); - -#define BIAS_NAME_SIZE (sizeof("usb-storage")) -static const char *bias_names[3] = { "none", "usb-storage", "ub" }; - -static DEFINE_MUTEX(usu_probe_mutex); -static DECLARE_COMPLETION(usu_end_notify); -static atomic_t total_threads = ATOMIC_INIT(0); - -static int usu_probe_thread(void *arg); - -/* - * @type: the module type as an integer - */ -void usb_usual_set_present(int type) -{ - struct mod_status *st; - unsigned long flags; - - if (type <= 0 || type >= 3) - return; - st = &stat[type]; - spin_lock_irqsave(&usu_lock, flags); - st->fls |= USU_MOD_FL_PRESENT; - spin_unlock_irqrestore(&usu_lock, flags); -} -EXPORT_SYMBOL_GPL(usb_usual_set_present); - -void usb_usual_clear_present(int type) -{ - struct mod_status *st; - unsigned long flags; - - if (type <= 0 || type >= 3) - return; - st = &stat[type]; - spin_lock_irqsave(&usu_lock, flags); - st->fls &= ~USU_MOD_FL_PRESENT; - spin_unlock_irqrestore(&usu_lock, flags); -} -EXPORT_SYMBOL_GPL(usb_usual_clear_present); - -/* - * Match the calling driver type against the table. - * Returns: 0 if the device matches. - */ -int usb_usual_check_type(const struct usb_device_id *id, int caller_type) -{ - int id_type = USB_US_TYPE(id->driver_info); - - if (caller_type <= 0 || caller_type >= 3) - return -EINVAL; - - /* Drivers grab fixed assignment devices */ - if (id_type == caller_type) - return 0; - /* Drivers grab devices biased to them */ - if (id_type == USB_US_TYPE_NONE && caller_type == atomic_read(&usu_bias)) - return 0; - return -ENODEV; -} -EXPORT_SYMBOL_GPL(usb_usual_check_type); - -/* - */ -static int usu_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - int rc; - unsigned long type; - struct task_struct* task; - unsigned long flags; - - type = USB_US_TYPE(id->driver_info); - if (type == 0) - type = atomic_read(&usu_bias); - - spin_lock_irqsave(&usu_lock, flags); - if ((stat[type].fls & (USU_MOD_FL_THREAD|USU_MOD_FL_PRESENT)) != 0) { - spin_unlock_irqrestore(&usu_lock, flags); - return -ENXIO; - } - stat[type].fls |= USU_MOD_FL_THREAD; - spin_unlock_irqrestore(&usu_lock, flags); - - task = kthread_run(usu_probe_thread, (void*)type, "libusual_%ld", type); - if (IS_ERR(task)) { - rc = PTR_ERR(task); - printk(KERN_WARNING "libusual: " - "Unable to start the thread for %s: %d\n", - bias_names[type], rc); - spin_lock_irqsave(&usu_lock, flags); - stat[type].fls &= ~USU_MOD_FL_THREAD; - spin_unlock_irqrestore(&usu_lock, flags); - return rc; /* Not being -ENXIO causes a message printed */ - } - atomic_inc(&total_threads); - - return -ENXIO; -} - -static void usu_disconnect(struct usb_interface *intf) -{ - ; /* We should not be here. */ -} - -static struct usb_driver usu_driver = { - .name = "libusual", - .probe = usu_probe, - .disconnect = usu_disconnect, - .id_table = usb_storage_usb_ids, -}; - -/* - * A whole new thread for a purpose of request_module seems quite stupid. - * The request_module forks once inside again. However, if we attempt - * to load a storage module from our own modprobe thread, that module - * references our symbols, which cannot be resolved until our module is - * initialized. I wish there was a way to wait for the end of initialization. - * The module notifier reports MODULE_STATE_COMING only. - * So, we wait until module->init ends as the next best thing. - */ -static int usu_probe_thread(void *arg) -{ - int type = (unsigned long) arg; - struct mod_status *st = &stat[type]; - int rc; - unsigned long flags; - - mutex_lock(&usu_probe_mutex); - rc = request_module(bias_names[type]); - spin_lock_irqsave(&usu_lock, flags); - if (rc == 0 && (st->fls & USU_MOD_FL_PRESENT) == 0) { - /* - * This should not happen, but let us keep tabs on it. - */ - printk(KERN_NOTICE "libusual: " - "modprobe for %s succeeded, but module is not present\n", - bias_names[type]); - } - st->fls &= ~USU_MOD_FL_THREAD; - spin_unlock_irqrestore(&usu_lock, flags); - mutex_unlock(&usu_probe_mutex); - - complete_and_exit(&usu_end_notify, 0); -} - -/* - */ -static int __init usb_usual_init(void) -{ - int rc; - - mutex_lock(&usu_probe_mutex); - rc = usb_register(&usu_driver); - mutex_unlock(&usu_probe_mutex); - return rc; -} - -static void __exit usb_usual_exit(void) -{ - /* - * We do not check for any drivers present, because - * they keep us pinned with symbol references. - */ - - usb_deregister(&usu_driver); - - while (atomic_read(&total_threads) > 0) { - wait_for_completion(&usu_end_notify); - atomic_dec(&total_threads); - } -} - -/* - * Validate and accept the bias parameter. - */ -static int usu_set_bias(const char *bias_s, struct kernel_param *kp) -{ - int i; - int len; - int bias_n = 0; - - len = strlen(bias_s); - if (len == 0) - return -EDOM; - if (bias_s[len-1] == '\n') - --len; - - for (i = 1; i < 3; i++) { - if (strncmp(bias_s, bias_names[i], len) == 0) { - bias_n = i; - break; - } - } - if (bias_n == 0) - return -EINVAL; - - atomic_set(&usu_bias, bias_n); - return 0; -} - -static int usu_get_bias(char *buffer, struct kernel_param *kp) -{ - return strlen(strcpy(buffer, bias_names[atomic_read(&usu_bias)])); -} - -module_init(usb_usual_init); -module_exit(usb_usual_exit); - -module_param_call(bias, usu_set_bias, usu_get_bias, NULL, S_IRUGO|S_IWUSR); -__MODULE_PARM_TYPE(bias, "string"); -MODULE_PARM_DESC(bias, "Bias to usb-storage or ub"); - -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c index 886567a..cb79de6 100644 --- a/drivers/usb/storage/onetouch.c +++ b/drivers/usb/storage/onetouch.c @@ -67,7 +67,7 @@ struct usb_onetouch { vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + .driver_info = (flags) } static struct usb_device_id onetouch_usb_ids[] = { # include "unusual_onetouch.h" diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c index 63cf282..d36446d 100644 --- a/drivers/usb/storage/realtek_cr.c +++ b/drivers/usb/storage/realtek_cr.c @@ -172,7 +172,7 @@ static int init_realtek_cr(struct us_data *us); initFunction, flags) \ {\ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24)\ + .driver_info = (flags) \ } static const struct usb_device_id realtek_cr_ids[] = { diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index 3252a62..7bd54e0 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c @@ -69,7 +69,7 @@ static int usb_stor_sddr09_init(struct us_data *us); vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + .driver_info = (flags) } static struct usb_device_id sddr09_usb_ids[] = { # include "unusual_sddr09.h" diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c index c144078..d278c5a 100644 --- a/drivers/usb/storage/sddr55.c +++ b/drivers/usb/storage/sddr55.c @@ -46,7 +46,7 @@ MODULE_LICENSE("GPL"); vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + .driver_info = (flags) } static struct usb_device_id sddr55_usb_ids[] = { # include "unusual_sddr55.h" diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index fa1ceeb..daf2fc5 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -168,7 +168,7 @@ static int init_usbat_flash(struct us_data *us); vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + .driver_info = (flags) } static struct usb_device_id usbat_usb_ids[] = { # include "unusual_usbat.h" diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 62a31be..779cd95 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -2038,25 +2038,25 @@ UNUSUAL_DEV( 0xed10, 0x7636, 0x0001, 0x0001, USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), /* Control/Bulk transport for all SubClass values */ -USUAL_DEV(USB_SC_RBC, USB_PR_CB, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_8020, USB_PR_CB, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_QIC, USB_PR_CB, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_UFI, USB_PR_CB, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_8070, USB_PR_CB, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_SCSI, USB_PR_CB, USB_US_TYPE_STOR), +USUAL_DEV(USB_SC_RBC, USB_PR_CB), +USUAL_DEV(USB_SC_8020, USB_PR_CB), +USUAL_DEV(USB_SC_QIC, USB_PR_CB), +USUAL_DEV(USB_SC_UFI, USB_PR_CB), +USUAL_DEV(USB_SC_8070, USB_PR_CB), +USUAL_DEV(USB_SC_SCSI, USB_PR_CB), /* Control/Bulk/Interrupt transport for all SubClass values */ -USUAL_DEV(USB_SC_RBC, USB_PR_CBI, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_8020, USB_PR_CBI, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_QIC, USB_PR_CBI, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_UFI, USB_PR_CBI, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_8070, USB_PR_CBI, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_SCSI, USB_PR_CBI, USB_US_TYPE_STOR), +USUAL_DEV(USB_SC_RBC, USB_PR_CBI), +USUAL_DEV(USB_SC_8020, USB_PR_CBI), +USUAL_DEV(USB_SC_QIC, USB_PR_CBI), +USUAL_DEV(USB_SC_UFI, USB_PR_CBI), +USUAL_DEV(USB_SC_8070, USB_PR_CBI), +USUAL_DEV(USB_SC_SCSI, USB_PR_CBI), /* Bulk-only transport for all SubClass values */ -USUAL_DEV(USB_SC_RBC, USB_PR_BULK, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_8020, USB_PR_BULK, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_QIC, USB_PR_BULK, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_UFI, USB_PR_BULK, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_8070, USB_PR_BULK, USB_US_TYPE_STOR), -USUAL_DEV(USB_SC_SCSI, USB_PR_BULK, 0), +USUAL_DEV(USB_SC_RBC, USB_PR_BULK), +USUAL_DEV(USB_SC_8020, USB_PR_BULK), +USUAL_DEV(USB_SC_QIC, USB_PR_BULK), +USUAL_DEV(USB_SC_UFI, USB_PR_BULK), +USUAL_DEV(USB_SC_8070, USB_PR_BULK), +USUAL_DEV(USB_SC_SCSI, USB_PR_BULK), diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index d012fe4..12aa726 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -114,7 +114,7 @@ MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks"); #define COMPLIANT_DEV UNUSUAL_DEV -#define USUAL_DEV(use_protocol, use_transport, use_type) \ +#define USUAL_DEV(use_protocol, use_transport) \ { \ .useProtocol = use_protocol, \ .useTransport = use_transport, \ @@ -126,7 +126,7 @@ static struct us_unusual_dev us_unusual_dev_list[] = { }; static struct us_unusual_dev for_dynamic_ids = - USUAL_DEV(USB_SC_SCSI, USB_PR_BULK, 0); + USUAL_DEV(USB_SC_SCSI, USB_PR_BULK); #undef UNUSUAL_DEV #undef COMPLIANT_DEV @@ -564,7 +564,7 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id, us->protocol = (unusual_dev->useTransport == USB_PR_DEVICE) ? idesc->bInterfaceProtocol : unusual_dev->useTransport; - us->fflags = USB_US_ORIG_FLAGS(id->driver_info); + us->fflags = id->driver_info; adjust_quirks(us); if (us->fflags & US_FL_IGNORE_DEVICE) { @@ -1041,13 +1041,10 @@ static int storage_probe(struct usb_interface *intf, int size; /* - * If libusual is configured, let it decide whether a standard - * device should be handled by usb-storage or by ub. * If the device isn't standard (is handled by a subdriver * module) then don't accept it. */ - if (usb_usual_check_type(id, USB_US_TYPE_STOR) || - usb_usual_ignore_device(intf)) + if (usb_usual_ignore_device(intf)) return -ENXIO; /* @@ -1105,10 +1102,8 @@ static int __init usb_stor_init(void) /* register the driver, return usb_register return code if error */ retval = usb_register(&usb_storage_driver); - if (retval == 0) { + if (retval == 0) pr_info("USB Mass Storage support registered.\n"); - usb_usual_set_present(USB_US_TYPE_STOR); - } return retval; } @@ -1122,8 +1117,6 @@ static void __exit usb_stor_exit(void) */ US_DEBUGP("-- calling usb_deregister()\n"); usb_deregister(&usb_storage_driver) ; - - usb_usual_clear_present(USB_US_TYPE_STOR); } module_init(usb_stor_init); diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index b969279..b78a526 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -34,31 +34,23 @@ vendorName, productName, useProtocol, useTransport, \ initFunction, flags) \ { USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } - -#define COMPLIANT_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ - vendorName, productName, useProtocol, useTransport, \ - initFunction, flags) \ -{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ .driver_info = (flags) } -#define USUAL_DEV(useProto, useTrans, useType) \ -{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \ - .driver_info = ((useType)<<24) } +#define COMPLIANT_DEV UNUSUAL_DEV + +#define USUAL_DEV(useProto, useTrans) \ +{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans) } struct usb_device_id usb_storage_usb_ids[] = { # include "unusual_devs.h" { } /* Terminating entry */ }; -EXPORT_SYMBOL_GPL(usb_storage_usb_ids); - MODULE_DEVICE_TABLE(usb, usb_storage_usb_ids); #undef UNUSUAL_DEV #undef COMPLIANT_DEV #undef USUAL_DEV - /* * The table of devices to ignore */ @@ -95,7 +87,6 @@ static struct ignore_entry ignore_ids[] = { #undef UNUSUAL_DEV - /* Return an error if a device is in the ignore_ids list */ int usb_usual_ignore_device(struct usb_interface *intf) { @@ -115,4 +106,3 @@ int usb_usual_ignore_device(struct usb_interface *intf) } return 0; } -EXPORT_SYMBOL_GPL(usb_usual_ignore_device); diff --git a/include/linux/usb_usual.h b/include/linux/usb_usual.h index e84e769..bf99cd0 100644 --- a/include/linux/usb_usual.h +++ b/include/linux/usb_usual.h @@ -72,33 +72,9 @@ enum { US_DO_ALL_FLAGS }; #undef US_FLAG -/* - * The bias field for libusual and friends. - */ -#define USB_US_TYPE_NONE 0 -#define USB_US_TYPE_STOR 1 /* usb-storage */ -#define USB_US_TYPE_UB 2 /* ub */ - -#define USB_US_TYPE(flags) (((flags) >> 24) & 0xFF) -#define USB_US_ORIG_FLAGS(flags) ((flags) & 0x00FFFFFF) - #include -/* - */ extern int usb_usual_ignore_device(struct usb_interface *intf); extern struct usb_device_id usb_storage_usb_ids[]; -#ifdef CONFIG_USB_LIBUSUAL - -extern void usb_usual_set_present(int type); -extern void usb_usual_clear_present(int type); -extern int usb_usual_check_type(const struct usb_device_id *, int type); -#else - -#define usb_usual_set_present(t) do { } while(0) -#define usb_usual_clear_present(t) do { } while(0) -#define usb_usual_check_type(id, t) (0) -#endif /* CONFIG_USB_LIBUSUAL */ - #endif /* __LINUX_USB_USUAL_H */ -- cgit v0.10.2 From a4c3ddec5c5293953d8472eb151c48a3205b738b Mon Sep 17 00:00:00 2001 From: Venu Byravarasu Date: Thu, 6 Sep 2012 10:42:15 +0530 Subject: usb: phy: fix build break During phy interface separation from otg.h, as the enum "usb_otg_state" was having multiple otg states info and removal of member 'state' of this enum type from usb_phy struct did not generate any compilation issues, I removed member state from struct usb_phy. As this is causing build break in musb code, adding member 'state' to usb_phy structure. Signed-off-by: Venu Byravarasu Signed-off-by: Felipe Balbi diff --git a/include/linux/usb/otg.h b/include/linux/usb/otg.h index 65a2b6a..e8a5fe8 100644 --- a/include/linux/usb/otg.h +++ b/include/linux/usb/otg.h @@ -11,30 +11,6 @@ #include -/* OTG defines lots of enumeration states before device reset */ -enum usb_otg_state { - OTG_STATE_UNDEFINED = 0, - - /* single-role peripheral, and dual-role default-b */ - OTG_STATE_B_IDLE, - OTG_STATE_B_SRP_INIT, - OTG_STATE_B_PERIPHERAL, - - /* extra dual-role default-b states */ - OTG_STATE_B_WAIT_ACON, - OTG_STATE_B_HOST, - - /* dual-role default-a */ - OTG_STATE_A_IDLE, - OTG_STATE_A_WAIT_VRISE, - OTG_STATE_A_WAIT_BCON, - OTG_STATE_A_HOST, - OTG_STATE_A_SUSPEND, - OTG_STATE_A_PERIPHERAL, - OTG_STATE_A_WAIT_VFALL, - OTG_STATE_A_VBUS_ERR, -}; - struct usb_otg { u8 default_a; diff --git a/include/linux/usb/phy.h b/include/linux/usb/phy.h index 88fc160..06b5bae 100644 --- a/include/linux/usb/phy.h +++ b/include/linux/usb/phy.h @@ -26,6 +26,30 @@ enum usb_phy_type { USB_PHY_TYPE_USB3, }; +/* OTG defines lots of enumeration states before device reset */ +enum usb_otg_state { + OTG_STATE_UNDEFINED = 0, + + /* single-role peripheral, and dual-role default-b */ + OTG_STATE_B_IDLE, + OTG_STATE_B_SRP_INIT, + OTG_STATE_B_PERIPHERAL, + + /* extra dual-role default-b states */ + OTG_STATE_B_WAIT_ACON, + OTG_STATE_B_HOST, + + /* dual-role default-a */ + OTG_STATE_A_IDLE, + OTG_STATE_A_WAIT_VRISE, + OTG_STATE_A_WAIT_BCON, + OTG_STATE_A_HOST, + OTG_STATE_A_SUSPEND, + OTG_STATE_A_PERIPHERAL, + OTG_STATE_A_WAIT_VFALL, + OTG_STATE_A_VBUS_ERR, +}; + struct usb_phy; struct usb_otg; @@ -43,6 +67,7 @@ struct usb_phy { unsigned int flags; enum usb_phy_type type; + enum usb_otg_state state; enum usb_phy_events last_event; struct usb_otg *otg; -- cgit v0.10.2 From 657b306a7bdfca4ae1514b533a0e7c3c6d26dbc6 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Thu, 6 Sep 2012 20:27:06 +0530 Subject: usb: phy: add a new driver for omap usb2 phy All phy related programming like enabling/disabling the clocks, powering on/off the phy is taken care of by this driver. It is also used for OTG related functionality like srp. This also includes device tree support for usb2 phy driver and the documentation with device tree binding information is updated. Currently writing to control module register is taken care in this driver which will be removed once the control module driver is in place. Cc: Felipe Balbi Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi diff --git a/Documentation/devicetree/bindings/usb/usb-phy.txt b/Documentation/devicetree/bindings/usb/usb-phy.txt new file mode 100644 index 0000000..80d4148 --- /dev/null +++ b/Documentation/devicetree/bindings/usb/usb-phy.txt @@ -0,0 +1,17 @@ +USB PHY + +OMAP USB2 PHY + +Required properties: + - compatible: Should be "ti,omap-usb2" + - reg : Address and length of the register set for the device. Also +add the address of control module dev conf register until a driver for +control module is added + +This is usually a subnode of ocp2scp to which it is connected. + +usb2phy@4a0ad080 { + compatible = "ti,omap-usb2"; + reg = <0x4a0ad080 0x58>, + <0x4a002300 0x4>; +}; diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 2838adb..63c339b 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig @@ -4,6 +4,15 @@ comment "USB Physical Layer drivers" depends on USB || USB_GADGET +config OMAP_USB2 + tristate "OMAP USB2 PHY Driver" + select USB_OTG_UTILS + help + Enable this to support the transceiver that is part of SOC. This + driver takes care of all the PHY functionality apart from comparator. + The USB OTG controller communicates with the comparator using this + driver. + config USB_ISP1301 tristate "NXP ISP1301 USB transceiver support" depends on USB || USB_GADGET diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile index bb948fb..b069f29 100644 --- a/drivers/usb/phy/Makefile +++ b/drivers/usb/phy/Makefile @@ -4,6 +4,7 @@ ccflags-$(CONFIG_USB_DEBUG) := -DDEBUG +obj-$(CONFIG_OMAP_USB2) += omap-usb2.o obj-$(CONFIG_USB_ISP1301) += isp1301.o obj-$(CONFIG_MV_U3D_PHY) += mv_u3d_phy.o obj-$(CONFIG_USB_EHCI_TEGRA) += tegra_usb_phy.o diff --git a/drivers/usb/phy/omap-usb2.c b/drivers/usb/phy/omap-usb2.c new file mode 100644 index 0000000..15ab3d6 --- /dev/null +++ b/drivers/usb/phy/omap-usb2.c @@ -0,0 +1,271 @@ +/* + * omap-usb2.c - USB PHY, talking to musb controller in OMAP. + * + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Author: Kishon Vijay Abraham I + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * omap_usb2_set_comparator - links the comparator present in the sytem with + * this phy + * @comparator - the companion phy(comparator) for this phy + * + * The phy companion driver should call this API passing the phy_companion + * filled with set_vbus and start_srp to be used by usb phy. + * + * For use by phy companion driver + */ +int omap_usb2_set_comparator(struct phy_companion *comparator) +{ + struct omap_usb *phy; + struct usb_phy *x = usb_get_phy(USB_PHY_TYPE_USB2); + + if (IS_ERR(x)) + return -ENODEV; + + phy = phy_to_omapusb(x); + phy->comparator = comparator; + return 0; +} +EXPORT_SYMBOL_GPL(omap_usb2_set_comparator); + +/** + * omap_usb_phy_power - power on/off the phy using control module reg + * @phy: struct omap_usb * + * @on: 0 or 1, based on powering on or off the PHY + * + * XXX: Remove this function once control module driver gets merged + */ +static void omap_usb_phy_power(struct omap_usb *phy, int on) +{ + u32 val; + + if (on) { + val = readl(phy->control_dev); + if (val & PHY_PD) { + writel(~PHY_PD, phy->control_dev); + /* XXX: add proper documentation for this delay */ + mdelay(200); + } + } else { + writel(PHY_PD, phy->control_dev); + } +} + +static int omap_usb_set_vbus(struct usb_otg *otg, bool enabled) +{ + struct omap_usb *phy = phy_to_omapusb(otg->phy); + + if (!phy->comparator) + return -ENODEV; + + return phy->comparator->set_vbus(phy->comparator, enabled); +} + +static int omap_usb_start_srp(struct usb_otg *otg) +{ + struct omap_usb *phy = phy_to_omapusb(otg->phy); + + if (!phy->comparator) + return -ENODEV; + + return phy->comparator->start_srp(phy->comparator); +} + +static int omap_usb_set_host(struct usb_otg *otg, struct usb_bus *host) +{ + struct usb_phy *phy = otg->phy; + + otg->host = host; + if (!host) + phy->state = OTG_STATE_UNDEFINED; + + return 0; +} + +static int omap_usb_set_peripheral(struct usb_otg *otg, + struct usb_gadget *gadget) +{ + struct usb_phy *phy = otg->phy; + + otg->gadget = gadget; + if (!gadget) + phy->state = OTG_STATE_UNDEFINED; + + return 0; +} + +static int omap_usb2_suspend(struct usb_phy *x, int suspend) +{ + u32 ret; + struct omap_usb *phy = phy_to_omapusb(x); + + if (suspend && !phy->is_suspended) { + omap_usb_phy_power(phy, 0); + pm_runtime_put_sync(phy->dev); + phy->is_suspended = 1; + } else if (!suspend && phy->is_suspended) { + ret = pm_runtime_get_sync(phy->dev); + if (ret < 0) { + dev_err(phy->dev, "get_sync failed with err %d\n", + ret); + return ret; + } + omap_usb_phy_power(phy, 1); + phy->is_suspended = 0; + } + + return 0; +} + +static int __devinit omap_usb2_probe(struct platform_device *pdev) +{ + struct omap_usb *phy; + struct usb_otg *otg; + struct resource *res; + + phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); + if (!phy) { + dev_err(&pdev->dev, "unable to allocate memory for USB2 PHY\n"); + return -ENOMEM; + } + + otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL); + if (!otg) { + dev_err(&pdev->dev, "unable to allocate memory for USB OTG\n"); + return -ENOMEM; + } + + phy->dev = &pdev->dev; + + phy->phy.dev = phy->dev; + phy->phy.label = "omap-usb2"; + phy->phy.set_suspend = omap_usb2_suspend; + phy->phy.otg = otg; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + + phy->control_dev = devm_request_and_ioremap(&pdev->dev, res); + if (phy->control_dev == NULL) { + dev_err(&pdev->dev, "Failed to obtain io memory\n"); + return -ENXIO; + } + + phy->is_suspended = 1; + omap_usb_phy_power(phy, 0); + + otg->set_host = omap_usb_set_host; + otg->set_peripheral = omap_usb_set_peripheral; + otg->set_vbus = omap_usb_set_vbus; + otg->start_srp = omap_usb_start_srp; + otg->phy = &phy->phy; + + phy->wkupclk = devm_clk_get(phy->dev, "usb_phy_cm_clk32k"); + if (IS_ERR(phy->wkupclk)) { + dev_err(&pdev->dev, "unable to get usb_phy_cm_clk32k\n"); + return PTR_ERR(phy->wkupclk); + } + clk_prepare(phy->wkupclk); + + usb_add_phy(&phy->phy, USB_PHY_TYPE_USB2); + + platform_set_drvdata(pdev, phy); + + pm_runtime_enable(phy->dev); + + return 0; +} + +static int __devexit omap_usb2_remove(struct platform_device *pdev) +{ + struct omap_usb *phy = platform_get_drvdata(pdev); + + clk_unprepare(phy->wkupclk); + usb_remove_phy(&phy->phy); + + return 0; +} + +#ifdef CONFIG_PM_RUNTIME + +static int omap_usb2_runtime_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct omap_usb *phy = platform_get_drvdata(pdev); + + clk_disable(phy->wkupclk); + + return 0; +} + +static int omap_usb2_runtime_resume(struct device *dev) +{ + u32 ret = 0; + struct platform_device *pdev = to_platform_device(dev); + struct omap_usb *phy = platform_get_drvdata(pdev); + + ret = clk_enable(phy->wkupclk); + if (ret < 0) + dev_err(phy->dev, "Failed to enable wkupclk %d\n", ret); + + return ret; +} + +static const struct dev_pm_ops omap_usb2_pm_ops = { + SET_RUNTIME_PM_OPS(omap_usb2_runtime_suspend, omap_usb2_runtime_resume, + NULL) +}; + +#define DEV_PM_OPS (&omap_usb2_pm_ops) +#else +#define DEV_PM_OPS NULL +#endif + +#ifdef CONFIG_OF +static const struct of_device_id omap_usb2_id_table[] = { + { .compatible = "ti,omap-usb2" }, + {} +}; +MODULE_DEVICE_TABLE(of, omap_usb2_id_table); +#endif + +static struct platform_driver omap_usb2_driver = { + .probe = omap_usb2_probe, + .remove = __devexit_p(omap_usb2_remove), + .driver = { + .name = "omap-usb2", + .owner = THIS_MODULE, + .pm = DEV_PM_OPS, + .of_match_table = of_match_ptr(omap_usb2_id_table), + }, +}; + +module_platform_driver(omap_usb2_driver); + +MODULE_ALIAS("platform: omap_usb2"); +MODULE_AUTHOR("Texas Instruments Inc."); +MODULE_DESCRIPTION("OMAP USB2 phy driver"); +MODULE_LICENSE("GPL v2"); diff --git a/include/linux/usb/omap_usb.h b/include/linux/usb/omap_usb.h new file mode 100644 index 0000000..0ea17f8 --- /dev/null +++ b/include/linux/usb/omap_usb.h @@ -0,0 +1,46 @@ +/* + * omap_usb.h -- omap usb2 phy header file + * + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Author: Kishon Vijay Abraham I + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __DRIVERS_OMAP_USB2_H +#define __DRIVERS_OMAP_USB2_H + +#include + +struct omap_usb { + struct usb_phy phy; + struct phy_companion *comparator; + struct device *dev; + u32 __iomem *control_dev; + struct clk *wkupclk; + u8 is_suspended:1; +}; + +#define PHY_PD 0x1 + +#define phy_to_omapusb(x) container_of((x), struct omap_usb, phy) + +#if defined(CONFIG_OMAP_USB2) || defined(CONFIG_OMAP_USB2_MODULE) +extern int omap_usb2_set_comparator(struct phy_companion *comparator); +#else +static inline int omap_usb2_set_comparator(struct phy_companion *comparator) +{ + return -ENODEV; +} +#endif + +#endif /* __DRIVERS_OMAP_USB_H */ diff --git a/include/linux/usb/phy_companion.h b/include/linux/usb/phy_companion.h new file mode 100644 index 0000000..edd2ec2 --- /dev/null +++ b/include/linux/usb/phy_companion.h @@ -0,0 +1,34 @@ +/* + * phy-companion.h -- phy companion to indicate the comparator part of PHY + * + * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Author: Kishon Vijay Abraham I + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __DRIVERS_PHY_COMPANION_H +#define __DRIVERS_PHY_COMPANION_H + +#include + +/* phy_companion to take care of VBUS, ID and srp capabilities */ +struct phy_companion { + + /* effective for A-peripheral, ignored for B devices */ + int (*set_vbus)(struct phy_companion *x, bool enabled); + + /* for B devices only: start session with A-Host */ + int (*start_srp)(struct phy_companion *x); +}; + +#endif /* __DRIVERS_PHY_COMPANION_H */ -- cgit v0.10.2 From 0e98de67bacba812b1b465b90a3f940d24401c27 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Thu, 6 Sep 2012 20:27:07 +0530 Subject: usb: otg: make twl6030_usb as a comparator driver to omap_usb2 All the PHY configuration other than VBUS, ID GND and OTG SRP are removed from twl6030. The phy configurations are taken care by the dedicated usb2 phy driver. So twl6030 is made as comparator driver for VBUS and ID detection. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 13fd1ddf..d8c8a42 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -68,7 +68,7 @@ config TWL4030_USB config TWL6030_USB tristate "TWL6030 USB Transceiver Driver" - depends on TWL4030_CORE + depends on TWL4030_CORE && OMAP_USB2 select USB_OTG_UTILS help Enable this to support the USB OTG transceiver on TWL6030 diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c index 6907d8d..32525bb 100644 --- a/drivers/usb/otg/twl6030-usb.c +++ b/drivers/usb/otg/twl6030-usb.c @@ -25,8 +25,9 @@ #include #include #include -#include #include +#include +#include #include #include #include @@ -87,7 +88,7 @@ #define VBUS_DET BIT(2) struct twl6030_usb { - struct usb_phy phy; + struct phy_companion comparator; struct device *dev; /* for vbus reporting with irqs disabled */ @@ -107,7 +108,7 @@ struct twl6030_usb { unsigned long features; }; -#define phy_to_twl(x) container_of((x), struct twl6030_usb, phy) +#define comparator_to_twl(x) container_of((x), struct twl6030_usb, comparator) /*-------------------------------------------------------------------------*/ @@ -137,50 +138,9 @@ static inline u8 twl6030_readb(struct twl6030_usb *twl, u8 module, u8 address) return ret; } -static int twl6030_phy_init(struct usb_phy *x) +static int twl6030_start_srp(struct phy_companion *comparator) { - struct twl6030_usb *twl; - struct device *dev; - struct twl4030_usb_data *pdata; - - twl = phy_to_twl(x); - dev = twl->dev; - pdata = dev->platform_data; - - if (twl->linkstat == OMAP_MUSB_ID_GROUND) - pdata->phy_power(twl->dev, 1, 1); - else - pdata->phy_power(twl->dev, 0, 1); - - return 0; -} - -static void twl6030_phy_shutdown(struct usb_phy *x) -{ - struct twl6030_usb *twl; - struct device *dev; - struct twl4030_usb_data *pdata; - - twl = phy_to_twl(x); - dev = twl->dev; - pdata = dev->platform_data; - pdata->phy_power(twl->dev, 0, 0); -} - -static int twl6030_phy_suspend(struct usb_phy *x, int suspend) -{ - struct twl6030_usb *twl = phy_to_twl(x); - struct device *dev = twl->dev; - struct twl4030_usb_data *pdata = dev->platform_data; - - pdata->phy_suspend(dev, suspend); - - return 0; -} - -static int twl6030_start_srp(struct usb_otg *otg) -{ - struct twl6030_usb *twl = phy_to_twl(otg->phy); + struct twl6030_usb *twl = comparator_to_twl(comparator); twl6030_writeb(twl, TWL_MODULE_USB, 0x24, USB_VBUS_CTRL_SET); twl6030_writeb(twl, TWL_MODULE_USB, 0x84, USB_VBUS_CTRL_SET); @@ -313,23 +273,8 @@ static irqreturn_t twl6030_usbotg_irq(int irq, void *_twl) return IRQ_HANDLED; } -static int twl6030_set_peripheral(struct usb_otg *otg, - struct usb_gadget *gadget) +static int twl6030_enable_irq(struct twl6030_usb *twl) { - if (!otg) - return -ENODEV; - - otg->gadget = gadget; - if (!gadget) - otg->phy->state = OTG_STATE_UNDEFINED; - - return 0; -} - -static int twl6030_enable_irq(struct usb_phy *x) -{ - struct twl6030_usb *twl = phy_to_twl(x); - twl6030_writeb(twl, TWL_MODULE_USB, 0x1, USB_ID_INT_EN_HI_SET); twl6030_interrupt_unmask(0x05, REG_INT_MSK_LINE_C); twl6030_interrupt_unmask(0x05, REG_INT_MSK_STS_C); @@ -362,9 +307,9 @@ static void otg_set_vbus_work(struct work_struct *data) CHARGERUSB_CTRL1); } -static int twl6030_set_vbus(struct usb_otg *otg, bool enabled) +static int twl6030_set_vbus(struct phy_companion *comparator, bool enabled) { - struct twl6030_usb *twl = phy_to_twl(otg->phy); + struct twl6030_usb *twl = comparator_to_twl(comparator); twl->vbus_enable = enabled; schedule_work(&twl->set_vbus_work); @@ -372,23 +317,12 @@ static int twl6030_set_vbus(struct usb_otg *otg, bool enabled) return 0; } -static int twl6030_set_host(struct usb_otg *otg, struct usb_bus *host) -{ - if (!otg) - return -ENODEV; - - otg->host = host; - if (!host) - otg->phy->state = OTG_STATE_UNDEFINED; - return 0; -} - static int __devinit twl6030_usb_probe(struct platform_device *pdev) { + u32 ret; struct twl6030_usb *twl; int status, err; struct twl4030_usb_data *pdata; - struct usb_otg *otg; struct device *dev = &pdev->dev; pdata = dev->platform_data; @@ -396,28 +330,20 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) if (!twl) return -ENOMEM; - otg = devm_kzalloc(dev, sizeof *otg, GFP_KERNEL); - if (!otg) - return -ENOMEM; - twl->dev = &pdev->dev; twl->irq1 = platform_get_irq(pdev, 0); twl->irq2 = platform_get_irq(pdev, 1); twl->features = pdata->features; twl->linkstat = OMAP_MUSB_UNKNOWN; - twl->phy.dev = twl->dev; - twl->phy.label = "twl6030"; - twl->phy.otg = otg; - twl->phy.init = twl6030_phy_init; - twl->phy.shutdown = twl6030_phy_shutdown; - twl->phy.set_suspend = twl6030_phy_suspend; + twl->comparator.set_vbus = twl6030_set_vbus; + twl->comparator.start_srp = twl6030_start_srp; - otg->phy = &twl->phy; - otg->set_host = twl6030_set_host; - otg->set_peripheral = twl6030_set_peripheral; - otg->set_vbus = twl6030_set_vbus; - otg->start_srp = twl6030_start_srp; + ret = omap_usb2_set_comparator(&twl->comparator); + if (ret == -ENODEV) { + dev_info(&pdev->dev, "phy not ready, deferring probe"); + return -EPROBE_DEFER; + } /* init spinlock for workqueue */ spin_lock_init(&twl->lock); @@ -427,7 +353,6 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) dev_err(&pdev->dev, "ldo init failed\n"); return err; } - usb_add_phy(&twl->phy, USB_PHY_TYPE_USB2); platform_set_drvdata(pdev, twl); if (device_create_file(&pdev->dev, &dev_attr_vbus)) @@ -458,9 +383,7 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) } twl->asleep = 0; - pdata->phy_init(dev); - twl6030_phy_suspend(&twl->phy, 0); - twl6030_enable_irq(&twl->phy); + twl6030_enable_irq(twl); dev_info(&pdev->dev, "Initialized TWL6030 USB module\n"); return 0; @@ -470,10 +393,6 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev) { struct twl6030_usb *twl = platform_get_drvdata(pdev); - struct twl4030_usb_data *pdata; - struct device *dev = &pdev->dev; - pdata = dev->platform_data; - twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, REG_INT_MSK_LINE_C); twl6030_interrupt_mask(TWL6030_USBOTG_INT_MASK, @@ -481,7 +400,6 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev) free_irq(twl->irq1, twl); free_irq(twl->irq2, twl); regulator_put(twl->usb3v3); - pdata->phy_exit(twl->dev); device_remove_file(twl->dev, &dev_attr_vbus); cancel_work_sync(&twl->set_vbus_work); -- cgit v0.10.2 From ff0a1f39400a8d2c02343bd22d295517d72e58ec Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Thu, 6 Sep 2012 20:27:08 +0530 Subject: usb: twl6030: Add dt support for twl6030 usb Add device tree support for twl6030 usb driver. Update the Documentation with device tree binding information. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi diff --git a/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt b/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt new file mode 100644 index 0000000..930f9ff --- /dev/null +++ b/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt @@ -0,0 +1,21 @@ +USB COMPARATOR OF TWL CHIPS + +TWL6030 USB COMPARATOR + - compatible : Should be "ti,twl6030-usb" + - interrupts : Two interrupt numbers to the cpu should be specified. First + interrupt number is the otg interrupt number that raises ID interrupts when + the controller has to act as host and the second interrupt number is the + usb interrupt number that raises VBUS interrupts when the controller has to + act as device + - usb-supply : phandle to the regulator device tree node. It should be vusb + if it is twl6030 or ldousb if it is twl6025 subclass. + +twl6030-usb { + compatible = "ti,twl6030-usb"; + interrupts = < 4 10 >; +}; + +Board specific device node entry +&twl6030-usb { + usb-supply = <&vusb>; +}; diff --git a/drivers/usb/otg/twl6030-usb.c b/drivers/usb/otg/twl6030-usb.c index 32525bb..fcadef7 100644 --- a/drivers/usb/otg/twl6030-usb.c +++ b/drivers/usb/otg/twl6030-usb.c @@ -105,7 +105,7 @@ struct twl6030_usb { u8 asleep; bool irq_enabled; bool vbus_enable; - unsigned long features; + const char *regulator; }; #define comparator_to_twl(x) container_of((x), struct twl6030_usb, comparator) @@ -153,13 +153,6 @@ static int twl6030_start_srp(struct phy_companion *comparator) static int twl6030_usb_ldo_init(struct twl6030_usb *twl) { - char *regulator_name; - - if (twl->features & TWL6025_SUBCLASS) - regulator_name = "ldousb"; - else - regulator_name = "vusb"; - /* Set to OTG_REV 1.3 and turn on the ID_WAKEUP_COMP */ twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x1, TWL6030_BACKUP_REG); @@ -169,7 +162,7 @@ static int twl6030_usb_ldo_init(struct twl6030_usb *twl) /* Program MISC2 register and set bit VUSB_IN_VBAT */ twl6030_writeb(twl, TWL6030_MODULE_ID0 , 0x10, TWL6030_MISC2); - twl->usb3v3 = regulator_get(twl->dev, regulator_name); + twl->usb3v3 = regulator_get(twl->dev, twl->regulator); if (IS_ERR(twl->usb3v3)) return -ENODEV; @@ -322,9 +315,9 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) u32 ret; struct twl6030_usb *twl; int status, err; - struct twl4030_usb_data *pdata; - struct device *dev = &pdev->dev; - pdata = dev->platform_data; + struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct twl4030_usb_data *pdata = dev->platform_data; twl = devm_kzalloc(dev, sizeof *twl, GFP_KERNEL); if (!twl) @@ -333,7 +326,6 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) twl->dev = &pdev->dev; twl->irq1 = platform_get_irq(pdev, 0); twl->irq2 = platform_get_irq(pdev, 1); - twl->features = pdata->features; twl->linkstat = OMAP_MUSB_UNKNOWN; twl->comparator.set_vbus = twl6030_set_vbus; @@ -345,6 +337,18 @@ static int __devinit twl6030_usb_probe(struct platform_device *pdev) return -EPROBE_DEFER; } + if (np) { + twl->regulator = "usb"; + } else if (pdata) { + if (pdata->features & TWL6025_SUBCLASS) + twl->regulator = "ldousb"; + else + twl->regulator = "vusb"; + } else { + dev_err(&pdev->dev, "twl6030 initialized without pdata\n"); + return -EINVAL; + } + /* init spinlock for workqueue */ spin_lock_init(&twl->lock); @@ -406,12 +410,21 @@ static int __exit twl6030_usb_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id twl6030_usb_id_table[] = { + { .compatible = "ti,twl6030-usb" }, + {} +}; +MODULE_DEVICE_TABLE(of, twl6030_usb_id_table); +#endif + static struct platform_driver twl6030_usb_driver = { .probe = twl6030_usb_probe, .remove = __exit_p(twl6030_usb_remove), .driver = { .name = "twl6030_usb", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(twl6030_usb_id_table), }, }; -- cgit v0.10.2 From f8515f0639c337b6fac2f24073368ae834053a96 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Thu, 6 Sep 2012 20:27:09 +0530 Subject: usb: twl4030: Add device tree support for twl4030 usb Add device tree support for twl4030 usb driver. Update the Documentation with device tree binding information. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi diff --git a/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt b/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt index 930f9ff..36b9aed 100644 --- a/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt +++ b/Documentation/devicetree/bindings/usb/twlxxxx-usb.txt @@ -19,3 +19,22 @@ Board specific device node entry &twl6030-usb { usb-supply = <&vusb>; }; + +TWL4030 USB PHY AND COMPARATOR + - compatible : Should be "ti,twl4030-usb" + - interrupts : The interrupt numbers to the cpu should be specified. First + interrupt number is the otg interrupt number that raises ID interrupts + and VBUS interrupts. The second interrupt number is optional. + - -supply : phandle to the regulator device tree node. + should be vusb1v5, vusb1v8 and vusb3v1 + - usb_mode : The mode used by the phy to connect to the controller. "1" + specifies "ULPI" mode and "2" specifies "CEA2011_3PIN" mode. + +twl4030-usb { + compatible = "ti,twl4030-usb"; + interrupts = < 10 4 >; + usb1v5-supply = <&vusb1v5>; + usb1v8-supply = <&vusb1v8>; + usb3v1-supply = <&vusb3v1>; + usb_mode = <1>; +}; diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index 523cad5..f0d2e75 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c @@ -585,23 +585,28 @@ static int __devinit twl4030_usb_probe(struct platform_device *pdev) struct twl4030_usb *twl; int status, err; struct usb_otg *otg; - - if (!pdata) { - dev_dbg(&pdev->dev, "platform_data not available\n"); - return -EINVAL; - } + struct device_node *np = pdev->dev.of_node; twl = devm_kzalloc(&pdev->dev, sizeof *twl, GFP_KERNEL); if (!twl) return -ENOMEM; + if (np) + of_property_read_u32(np, "usb_mode", + (enum twl4030_usb_mode *)&twl->usb_mode); + else if (pdata) + twl->usb_mode = pdata->usb_mode; + else { + dev_err(&pdev->dev, "twl4030 initialized without pdata\n"); + return -EINVAL; + } + otg = devm_kzalloc(&pdev->dev, sizeof *otg, GFP_KERNEL); if (!otg) return -ENOMEM; twl->dev = &pdev->dev; twl->irq = platform_get_irq(pdev, 0); - twl->usb_mode = pdata->usb_mode; twl->vbus_supplied = false; twl->asleep = 1; twl->linkstat = OMAP_MUSB_UNKNOWN; @@ -690,12 +695,21 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev) return 0; } +#ifdef CONFIG_OF +static const struct of_device_id twl4030_usb_id_table[] = { + { .compatible = "ti,twl4030-usb" }, + {} +}; +MODULE_DEVICE_TABLE(of, twl4030_usb_id_table); +#endif + static struct platform_driver twl4030_usb_driver = { .probe = twl4030_usb_probe, .remove = __exit_p(twl4030_usb_remove), .driver = { .name = "twl4030_usb", .owner = THIS_MODULE, + .of_match_table = of_match_ptr(twl4030_usb_id_table), }, }; -- cgit v0.10.2 From c9e4412ab8eb8ef82d645d8749c4ce96ad490007 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Thu, 6 Sep 2012 20:27:10 +0530 Subject: arm: omap: phy: remove unused functions from omap-phy-internal.c All the unnessary functions in omap-phy-internal is removed. These functionality are now handled by omap-usb2 phy driver. Signed-off-by: Kishon Vijay Abraham I Acked-by: Tony Lindgren Signed-off-by: Felipe Balbi diff --git a/arch/arm/mach-omap2/omap_phy_internal.c b/arch/arm/mach-omap2/omap_phy_internal.c index d52651a..874aecc 100644 --- a/arch/arm/mach-omap2/omap_phy_internal.c +++ b/arch/arm/mach-omap2/omap_phy_internal.c @@ -31,144 +31,6 @@ #include #include "control.h" -/* OMAP control module register for UTMI PHY */ -#define CONTROL_DEV_CONF 0x300 -#define PHY_PD 0x1 - -#define USBOTGHS_CONTROL 0x33c -#define AVALID BIT(0) -#define BVALID BIT(1) -#define VBUSVALID BIT(2) -#define SESSEND BIT(3) -#define IDDIG BIT(4) - -static struct clk *phyclk, *clk48m, *clk32k; -static void __iomem *ctrl_base; -static int usbotghs_control; - -int omap4430_phy_init(struct device *dev) -{ - ctrl_base = ioremap(OMAP443X_SCM_BASE, SZ_1K); - if (!ctrl_base) { - pr_err("control module ioremap failed\n"); - return -ENOMEM; - } - /* Power down the phy */ - __raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF); - - if (!dev) { - iounmap(ctrl_base); - return 0; - } - - phyclk = clk_get(dev, "ocp2scp_usb_phy_ick"); - if (IS_ERR(phyclk)) { - dev_err(dev, "cannot clk_get ocp2scp_usb_phy_ick\n"); - iounmap(ctrl_base); - return PTR_ERR(phyclk); - } - - clk48m = clk_get(dev, "ocp2scp_usb_phy_phy_48m"); - if (IS_ERR(clk48m)) { - dev_err(dev, "cannot clk_get ocp2scp_usb_phy_phy_48m\n"); - clk_put(phyclk); - iounmap(ctrl_base); - return PTR_ERR(clk48m); - } - - clk32k = clk_get(dev, "usb_phy_cm_clk32k"); - if (IS_ERR(clk32k)) { - dev_err(dev, "cannot clk_get usb_phy_cm_clk32k\n"); - clk_put(phyclk); - clk_put(clk48m); - iounmap(ctrl_base); - return PTR_ERR(clk32k); - } - return 0; -} - -int omap4430_phy_set_clk(struct device *dev, int on) -{ - static int state; - - if (on && !state) { - /* Enable the phy clocks */ - clk_enable(phyclk); - clk_enable(clk48m); - clk_enable(clk32k); - state = 1; - } else if (state) { - /* Disable the phy clocks */ - clk_disable(phyclk); - clk_disable(clk48m); - clk_disable(clk32k); - state = 0; - } - return 0; -} - -int omap4430_phy_power(struct device *dev, int ID, int on) -{ - if (on) { - if (ID) - /* enable VBUS valid, IDDIG groung */ - __raw_writel(AVALID | VBUSVALID, ctrl_base + - USBOTGHS_CONTROL); - else - /* - * Enable VBUS Valid, AValid and IDDIG - * high impedance - */ - __raw_writel(IDDIG | AVALID | VBUSVALID, - ctrl_base + USBOTGHS_CONTROL); - } else { - /* Enable session END and IDIG to high impedance. */ - __raw_writel(SESSEND | IDDIG, ctrl_base + - USBOTGHS_CONTROL); - } - return 0; -} - -int omap4430_phy_suspend(struct device *dev, int suspend) -{ - if (suspend) { - /* Disable the clocks */ - omap4430_phy_set_clk(dev, 0); - /* Power down the phy */ - __raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF); - - /* save the context */ - usbotghs_control = __raw_readl(ctrl_base + USBOTGHS_CONTROL); - } else { - /* Enable the internel phy clcoks */ - omap4430_phy_set_clk(dev, 1); - /* power on the phy */ - if (__raw_readl(ctrl_base + CONTROL_DEV_CONF) & PHY_PD) { - __raw_writel(~PHY_PD, ctrl_base + CONTROL_DEV_CONF); - mdelay(200); - } - - /* restore the context */ - __raw_writel(usbotghs_control, ctrl_base + USBOTGHS_CONTROL); - } - - return 0; -} - -int omap4430_phy_exit(struct device *dev) -{ - if (ctrl_base) - iounmap(ctrl_base); - if (phyclk) - clk_put(phyclk); - if (clk48m) - clk_put(clk48m); - if (clk32k) - clk_put(clk32k); - - return 0; -} - void am35x_musb_reset(void) { u32 regval; diff --git a/arch/arm/mach-omap2/twl-common.c b/arch/arm/mach-omap2/twl-common.c index de47f17..e2cdf67 100644 --- a/arch/arm/mach-omap2/twl-common.c +++ b/arch/arm/mach-omap2/twl-common.c @@ -250,11 +250,6 @@ void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data, #if defined(CONFIG_ARCH_OMAP4) static struct twl4030_usb_data omap4_usb_pdata = { - .phy_init = omap4430_phy_init, - .phy_exit = omap4430_phy_exit, - .phy_power = omap4430_phy_power, - .phy_set_clock = omap4430_phy_set_clk, - .phy_suspend = omap4430_phy_suspend, }; static struct regulator_init_data omap4_vdac_idata = { diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c index c4a5768..e9b4b23 100644 --- a/arch/arm/mach-omap2/usb-musb.c +++ b/arch/arm/mach-omap2/usb-musb.c @@ -117,7 +117,4 @@ void __init usb_musb_init(struct omap_musb_board_data *musb_board_data) dev->dma_mask = &musb_dmamask; dev->coherent_dma_mask = musb_dmamask; put_device(dev); - - if (cpu_is_omap44xx()) - omap4430_phy_init(dev); } -- cgit v0.10.2 From ba2f9dff6c914b91005f687a9d75c8eac110d323 Mon Sep 17 00:00:00 2001 From: Andrew Lunn Date: Mon, 3 Sep 2012 20:21:15 +0200 Subject: USB: PLAT_ORION fulfils USB_ARCH_HAS_EHCI The various Orion SoCs, i.e. orion5x, kirkwood, dove, mv78xx0 and 370/XP have EHCI. Make sure USB_ARCH_HAS_EHCI reflects this. Reported-by: Sebastian Hesselbarth Signed-off-by: Andrew Lunn Acked-by: Jason Cooper Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 7065df6..2564b54 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -48,6 +48,7 @@ config USB_ARCH_HAS_EHCI default y if SPARC_LEON default y if ARCH_MMP default y if MACH_LOONGSON1 + default y if PLAT_ORION default PCI # some non-PCI HCDs implement xHCI -- cgit v0.10.2 From e4730931143398ec32088af32e985ec413739c10 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 6 Sep 2012 20:11:00 +0200 Subject: staging: ccg: Add a note about compatibility issues. The first item on the todo list is a new user interface. Put this information into Kconfig's help entry to people are not too confusing once an user API changes which does not happen in kernel otherwise. Cc: devel@driverdev.osuosl.org Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/staging/ccg/Kconfig b/drivers/staging/ccg/Kconfig index 1f00d70..df16665 100644 --- a/drivers/staging/ccg/Kconfig +++ b/drivers/staging/ccg/Kconfig @@ -17,4 +17,9 @@ config USB_G_CCG Configurable Composite Gadget can be compiled "M" only or not at all. + BIG FAT NOTE: DON'T RELY ON THIS USERINTERFACE HERE! AS PART + OF THE REWORK DONE HERE WILL BE A NEW USER INTERFACE WITHOUT ANY + COMPATIBILITY TO THIS SYSFS INTERFACE HERE. BE AWARE OF THIS + BEFORE SELECTING THIS. + endif # USB_GADGET -- cgit v0.10.2 From fac3a43e0ab20dbf5e845c6221ead0d073984f41 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 6 Sep 2012 20:11:01 +0200 Subject: usb: gadget: move bind callback into driver struct usb_composite_driver It was moved to be an argument in 07a18bd716ed5 ("usb gadget: don't save bind callback in struct usb_composite_driver"). The reason was to avoid the section missmatch. The warning was shown because ->bind is marked as __init becuase it is a one time init. The warning can be also suppresed by whitelisting the variable i.e. rename it to lets say _probe. Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 91411a6..402e5bd 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -32,7 +32,6 @@ #define USB_BUFSIZ 1024 static struct usb_composite_driver *composite; -static int (*composite_gadget_bind)(struct usb_composite_dev *cdev); /* Some systems will need runtime overrides for the product identifiers * published in the device descriptor, either numbers or strings or both. @@ -1468,7 +1467,7 @@ static int composite_bind(struct usb_gadget *gadget) * serial number), register function drivers, potentially update * power state and consumption, etc */ - status = composite_gadget_bind(cdev); + status = composite->bind(cdev); if (status < 0) goto fail; @@ -1621,7 +1620,9 @@ static struct usb_gadget_driver composite_driver = { int usb_composite_probe(struct usb_composite_driver *driver, int (*bind)(struct usb_composite_dev *cdev)) { - if (!driver || !driver->dev || !bind || composite) + if (!driver || !driver->dev || composite) + return -EINVAL; + if (!bind && !driver->bind) return -EINVAL; if (!driver->name) @@ -1632,7 +1633,8 @@ int usb_composite_probe(struct usb_composite_driver *driver, composite_driver.driver.name = driver->name; composite_driver.max_speed = driver->max_speed; composite = driver; - composite_gadget_bind = bind; + if (!driver->bind) + driver->bind = bind; return usb_gadget_probe_driver(&composite_driver, composite_bind); } diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 9d8c3b6..3153f73 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -257,12 +257,16 @@ void usb_remove_config(struct usb_composite_dev *, * not set. * @dev: Template descriptor for the device, including default device * identifiers. - * @strings: tables of strings, keyed by identifiers assigned during bind() + * @strings: tables of strings, keyed by identifiers assigned during @bind * and language IDs provided in control requests * @max_speed: Highest speed the driver supports. * @needs_serial: set to 1 if the gadget needs userspace to provide * a serial number. If one is not provided, warning will be printed. - * @unbind: Reverses bind; called as a side effect of unregistering + * @bind: (REQUIRED) Used to allocate resources that are shared across the + * whole device, such as string IDs, and add its configurations using + * @usb_add_config(). This may fail by returning a negative errno + * value; it should return zero on successful initialization. + * @unbind: Reverses @bind; called as a side effect of unregistering * this driver. * @disconnect: optional driver disconnect method * @suspend: Notifies when the host stops sending USB traffic, @@ -271,9 +275,9 @@ void usb_remove_config(struct usb_composite_dev *, * before function notifications * * Devices default to reporting self powered operation. Devices which rely - * on bus powered operation should report this in their @bind() method. + * on bus powered operation should report this in their @bind method. * - * Before returning from bind, various fields in the template descriptor + * Before returning from @bind, various fields in the template descriptor * may be overridden. These include the idVendor/idProduct/bcdDevice values * normally to bind the appropriate host side driver, and the three strings * (iManufacturer, iProduct, iSerialNumber) normally used to provide user @@ -291,6 +295,7 @@ struct usb_composite_driver { enum usb_device_speed max_speed; unsigned needs_serial:1; + int (*bind)(struct usb_composite_dev *cdev); int (*unbind)(struct usb_composite_dev *); void (*disconnect)(struct usb_composite_dev *); -- cgit v0.10.2 From 1e1a27c3258c769ea175780bb28d0c8fead79ff8 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 6 Sep 2012 20:11:02 +0200 Subject: usb: gadget: remove __devexit in f_uac2 avoids the following section missmatch |WARNING: drivers/usb/gadget/g_audio.o(.init.text+0x2e7): Section |mismatch in reference from the function afunc_bind() to the function |.devexit.text:snd_uac2_remove() |The function __init afunc_bind() references |a function __devexit snd_uac2_remove(). |This is often seen when error handling in the init function |uses functionality in the exit path. |The fix is often to remove the __devexit annotation of |snd_uac2_remove() so it may be used outside an exit section. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/f_uac2.c b/drivers/usb/gadget/f_uac2.c index e7cc4de..d3c6cff 100644 --- a/drivers/usb/gadget/f_uac2.c +++ b/drivers/usb/gadget/f_uac2.c @@ -463,7 +463,7 @@ snd_fail: return err; } -static int __devexit snd_uac2_remove(struct platform_device *pdev) +static int snd_uac2_remove(struct platform_device *pdev) { struct snd_card *card = platform_get_drvdata(pdev); -- cgit v0.10.2 From c2ec75c25112c9e0d9053f55ba8cf0a358d4a354 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 6 Sep 2012 20:11:03 +0200 Subject: usb: gadget: push all usb_composite_driver structs into __refdata As it turns out, Sam's comment was better than I initially assumed. This patch pushes as struct usb_composite_driver data structures into __refdata section to avoid a section missmatch report from modpost because the ->bind() can be marked __init. The only downside is that modpost does not check between ->bind() and other member. However, it is temporary. Cc: Sam Ravnborg Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/acm_ms.c b/drivers/usb/gadget/acm_ms.c index 75b8a69..dc5cd51 100644 --- a/drivers/usb/gadget/acm_ms.c +++ b/drivers/usb/gadget/acm_ms.c @@ -232,7 +232,7 @@ static int __exit acm_ms_unbind(struct usb_composite_dev *cdev) return 0; } -static struct usb_composite_driver acm_ms_driver = { +static __refdata struct usb_composite_driver acm_ms_driver = { .name = "g_acm_ms", .dev = &device_desc, .max_speed = USB_SPEED_SUPER, diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index 9889924..e539490 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c @@ -198,7 +198,7 @@ static int __exit audio_unbind(struct usb_composite_dev *cdev) return 0; } -static struct usb_composite_driver audio_driver = { +static __refdata struct usb_composite_driver audio_driver = { .name = "g_audio", .dev = &device_desc, .strings = audio_strings, diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index 725550f..00b65ac 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c @@ -232,7 +232,7 @@ static int __exit cdc_unbind(struct usb_composite_dev *cdev) return 0; } -static struct usb_composite_driver cdc_driver = { +static __refdata struct usb_composite_driver cdc_driver = { .name = "g_cdc", .dev = &device_desc, .strings = dev_strings, diff --git a/drivers/usb/gadget/dbgp.c b/drivers/usb/gadget/dbgp.c index 19d7bb0..2d2cff3 100644 --- a/drivers/usb/gadget/dbgp.c +++ b/drivers/usb/gadget/dbgp.c @@ -402,7 +402,7 @@ fail: return err; } -static struct usb_gadget_driver dbgp_driver = { +static __refdata struct usb_gadget_driver dbgp_driver = { .function = "dbgp", .max_speed = USB_SPEED_HIGH, .unbind = dbgp_unbind, diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index a28f6ff..49a7dac 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -388,7 +388,7 @@ static int __exit eth_unbind(struct usb_composite_dev *cdev) return 0; } -static struct usb_composite_driver eth_driver = { +static __refdata struct usb_composite_driver eth_driver = { .name = "g_ether", .dev = &device_desc, .strings = dev_strings, diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index a896d73..683234b 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -3603,7 +3603,7 @@ static void fsg_resume(struct usb_gadget *gadget) /*-------------------------------------------------------------------------*/ -static struct usb_gadget_driver fsg_driver = { +static __refdata struct usb_gadget_driver fsg_driver = { .max_speed = USB_SPEED_SUPER, .function = (char *) fsg_string_product, .unbind = fsg_unbind, diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index d3ace90..d1312c4 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -163,7 +163,7 @@ static int gfs_bind(struct usb_composite_dev *cdev); static int gfs_unbind(struct usb_composite_dev *cdev); static int gfs_do_config(struct usb_configuration *c); -static struct usb_composite_driver gfs_driver = { +static __refdata struct usb_composite_driver gfs_driver = { .name = DRIVER_NAME, .dev = &gfs_dev_desc, .strings = gfs_dev_strings, diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 681bd03..ae46f69 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -184,7 +184,7 @@ static int __init midi_bind(struct usb_composite_dev *cdev) return 0; } -static struct usb_composite_driver midi_driver = { +static __refdata struct usb_composite_driver midi_driver = { .name = (char *) longname, .dev = &device_desc, .strings = dev_strings, diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c index 3493adf..34e139e 100644 --- a/drivers/usb/gadget/hid.c +++ b/drivers/usb/gadget/hid.c @@ -242,7 +242,7 @@ static int __devexit hidg_plat_driver_remove(struct platform_device *pdev) /****************************** Some noise ******************************/ -static struct usb_composite_driver hidg_driver = { +static __refdata struct usb_composite_driver hidg_driver = { .name = "g_hid", .dev = &device_desc, .strings = dev_strings, diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c index 1f376eb..5df117e 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c @@ -156,7 +156,7 @@ static int __init msg_bind(struct usb_composite_dev *cdev) /****************************** Some noise ******************************/ -static struct usb_composite_driver msg_driver = { +static __refdata struct usb_composite_driver msg_driver = { .name = "g_mass_storage", .dev = &msg_device_desc, .iProduct = DRIVER_DESC, diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index c37fb33..7e5852a 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -338,7 +338,7 @@ static int __exit multi_unbind(struct usb_composite_dev *cdev) /****************************** Some noise ******************************/ -static struct usb_composite_driver multi_driver = { +static __refdata struct usb_composite_driver multi_driver = { .name = "g_multi", .dev = &device_desc, .strings = dev_strings, diff --git a/drivers/usb/gadget/ncm.c b/drivers/usb/gadget/ncm.c index 8953003..5079bf6 100644 --- a/drivers/usb/gadget/ncm.c +++ b/drivers/usb/gadget/ncm.c @@ -215,7 +215,7 @@ static int __exit gncm_unbind(struct usb_composite_dev *cdev) return 0; } -static struct usb_composite_driver ncm_driver = { +static __refdata struct usb_composite_driver ncm_driver = { .name = "g_ncm", .dev = &device_desc, .strings = dev_strings, diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index c7fb772..936d0af 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c @@ -237,7 +237,7 @@ static int __exit nokia_unbind(struct usb_composite_dev *cdev) return 0; } -static struct usb_composite_driver nokia_driver = { +static __refdata struct usb_composite_driver nokia_driver = { .name = "g_nokia", .dev = &device_desc, .strings = dev_strings, diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index f1f9290..0aab517 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -1269,7 +1269,7 @@ static int __init printer_bind(struct usb_composite_dev *cdev) return usb_add_config(cdev, &printer_cfg_driver, printer_bind_config); } -static struct usb_composite_driver printer_driver = { +static __refdata struct usb_composite_driver printer_driver = { .name = shortname, .dev = &device_desc, .strings = dev_strings, diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 665c074..7b0b6f4 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -238,7 +238,7 @@ fail: return status; } -static struct usb_composite_driver gserial_driver = { +static __refdata struct usb_composite_driver gserial_driver = { .name = "g_serial", .dev = &device_desc, .strings = dev_strings, diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c index 5444866..28fef844 100644 --- a/drivers/usb/gadget/tcm_usb_gadget.c +++ b/drivers/usb/gadget/tcm_usb_gadget.c @@ -2436,7 +2436,7 @@ static int usb_target_bind(struct usb_composite_dev *cdev) return 0; } -static struct usb_composite_driver usbg_driver = { +static __refdata struct usb_composite_driver usbg_driver = { .name = "g_target", .dev = &usbg_device_desc, .strings = usbg_strings, diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c index 120e134..d946f19 100644 --- a/drivers/usb/gadget/webcam.c +++ b/drivers/usb/gadget/webcam.c @@ -390,7 +390,7 @@ error: * Driver */ -static struct usb_composite_driver webcam_driver = { +static __refdata struct usb_composite_driver webcam_driver = { .name = "g_webcam", .dev = &webcam_device_descriptor, .strings = webcam_device_strings, diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 12ad516..5db33cb 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -334,7 +334,7 @@ static int zero_unbind(struct usb_composite_dev *cdev) return 0; } -static struct usb_composite_driver zero_driver = { +static __refdata struct usb_composite_driver zero_driver = { .name = "zero", .dev = &device_desc, .strings = dev_strings, -- cgit v0.10.2 From 03e42bd5937c4c24e411690ab165627e93c258b5 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 6 Sep 2012 20:11:04 +0200 Subject: usb: gadget: move bind() callback back to struct usb_composite_driver This partly reverts 07a18bd7 ("usb gadget: don't save bind callback in struct usb_composite_driver") and fixes new drivers. The section missmatch problems was solved by whitelisting structs in question via __ref. Cc: devel@driverdev.osuosl.org Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/staging/ccg/ccg.c b/drivers/staging/ccg/ccg.c index 6a7aab8..eadda55 100644 --- a/drivers/staging/ccg/ccg.c +++ b/drivers/staging/ccg/ccg.c @@ -1162,6 +1162,7 @@ static int ccg_usb_unbind(struct usb_composite_dev *cdev) static struct usb_composite_driver ccg_usb_driver = { .name = "configurable_usb", .dev = &device_desc, + .bind = ccg_bind, .unbind = ccg_usb_unbind, .needs_serial = true, .iManufacturer = "Linux Foundation", @@ -1275,7 +1276,7 @@ static int __init init(void) composite_driver.setup = ccg_setup; composite_driver.disconnect = ccg_disconnect; - err = usb_composite_probe(&ccg_usb_driver, ccg_bind); + err = usb_composite_probe(&ccg_usb_driver); if (err) { class_destroy(ccg_class); kfree(dev); diff --git a/drivers/usb/gadget/acm_ms.c b/drivers/usb/gadget/acm_ms.c index dc5cd51..65a2f3c 100644 --- a/drivers/usb/gadget/acm_ms.c +++ b/drivers/usb/gadget/acm_ms.c @@ -237,6 +237,7 @@ static __refdata struct usb_composite_driver acm_ms_driver = { .dev = &device_desc, .max_speed = USB_SPEED_SUPER, .strings = dev_strings, + .bind = acm_ms_bind, .unbind = __exit_p(acm_ms_unbind), }; @@ -246,7 +247,7 @@ MODULE_LICENSE("GPL v2"); static int __init init(void) { - return usb_composite_probe(&acm_ms_driver, acm_ms_bind); + return usb_composite_probe(&acm_ms_driver); } module_init(init); diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index e539490..dd339bc 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c @@ -203,12 +203,13 @@ static __refdata struct usb_composite_driver audio_driver = { .dev = &device_desc, .strings = audio_strings, .max_speed = USB_SPEED_HIGH, + .bind = audio_bind, .unbind = __exit_p(audio_unbind), }; static int __init init(void) { - return usb_composite_probe(&audio_driver, audio_bind); + return usb_composite_probe(&audio_driver); } module_init(init); diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index 00b65ac..b7d984b 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c @@ -237,6 +237,7 @@ static __refdata struct usb_composite_driver cdc_driver = { .dev = &device_desc, .strings = dev_strings, .max_speed = USB_SPEED_HIGH, + .bind = cdc_bind, .unbind = __exit_p(cdc_unbind), }; @@ -246,7 +247,7 @@ MODULE_LICENSE("GPL"); static int __init init(void) { - return usb_composite_probe(&cdc_driver, cdc_bind); + return usb_composite_probe(&cdc_driver); } module_init(init); diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 402e5bd..071d15c 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1617,12 +1617,9 @@ static struct usb_gadget_driver composite_driver = { * while it was binding. That would usually be done in order to wait for * some userspace participation. */ -int usb_composite_probe(struct usb_composite_driver *driver, - int (*bind)(struct usb_composite_dev *cdev)) +int usb_composite_probe(struct usb_composite_driver *driver) { - if (!driver || !driver->dev || composite) - return -EINVAL; - if (!bind && !driver->bind) + if (!driver || !driver->dev || composite || !driver->bind) return -EINVAL; if (!driver->name) @@ -1633,8 +1630,6 @@ int usb_composite_probe(struct usb_composite_driver *driver, composite_driver.driver.name = driver->name; composite_driver.max_speed = driver->max_speed; composite = driver; - if (!driver->bind) - driver->bind = bind; return usb_gadget_probe_driver(&composite_driver, composite_bind); } diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 49a7dac..4580ec0 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -393,6 +393,7 @@ static __refdata struct usb_composite_driver eth_driver = { .dev = &device_desc, .strings = dev_strings, .max_speed = USB_SPEED_SUPER, + .bind = eth_bind, .unbind = __exit_p(eth_unbind), }; @@ -402,7 +403,7 @@ MODULE_LICENSE("GPL"); static int __init init(void) { - return usb_composite_probe(ð_driver, eth_bind); + return usb_composite_probe(ð_driver); } module_init(init); diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index d1312c4..da9809f 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -168,6 +168,7 @@ static __refdata struct usb_composite_driver gfs_driver = { .dev = &gfs_dev_desc, .strings = gfs_dev_strings, .max_speed = USB_SPEED_HIGH, + .bind = gfs_bind, .unbind = gfs_unbind, .iProduct = DRIVER_DESC, }; @@ -268,7 +269,7 @@ static int functionfs_ready_callback(struct ffs_data *ffs) } gfs_registered = true; - ret = usb_composite_probe(&gfs_driver, gfs_bind); + ret = usb_composite_probe(&gfs_driver); if (unlikely(ret < 0)) gfs_registered = false; diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index ae46f69..1e3cd37 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -189,12 +189,13 @@ static __refdata struct usb_composite_driver midi_driver = { .dev = &device_desc, .strings = dev_strings, .max_speed = USB_SPEED_HIGH, + .bind = midi_bind, .unbind = __exit_p(midi_unbind), }; static int __init midi_init(void) { - return usb_composite_probe(&midi_driver, midi_bind); + return usb_composite_probe(&midi_driver); } module_init(midi_init); diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c index 34e139e..8502e56 100644 --- a/drivers/usb/gadget/hid.c +++ b/drivers/usb/gadget/hid.c @@ -247,6 +247,7 @@ static __refdata struct usb_composite_driver hidg_driver = { .dev = &device_desc, .strings = dev_strings, .max_speed = USB_SPEED_HIGH, + .bind = hid_bind, .unbind = __exit_p(hid_unbind), }; @@ -272,7 +273,7 @@ static int __init hidg_init(void) if (status < 0) return status; - status = usb_composite_probe(&hidg_driver, hid_bind); + status = usb_composite_probe(&hidg_driver); if (status < 0) platform_driver_unregister(&hidg_plat_driver); diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c index 5df117e..480edbc 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c @@ -162,6 +162,7 @@ static __refdata struct usb_composite_driver msg_driver = { .iProduct = DRIVER_DESC, .max_speed = USB_SPEED_SUPER, .needs_serial = 1, + .bind = msg_bind, }; MODULE_DESCRIPTION(DRIVER_DESC); @@ -170,7 +171,7 @@ MODULE_LICENSE("GPL"); static int __init msg_init(void) { - return usb_composite_probe(&msg_driver, msg_bind); + return usb_composite_probe(&msg_driver); } module_init(msg_init); diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index 7e5852a..13db7cc 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -343,6 +343,7 @@ static __refdata struct usb_composite_driver multi_driver = { .dev = &device_desc, .strings = dev_strings, .max_speed = USB_SPEED_HIGH, + .bind = multi_bind, .unbind = __exit_p(multi_unbind), .iProduct = DRIVER_DESC, .needs_serial = 1, @@ -351,7 +352,7 @@ static __refdata struct usb_composite_driver multi_driver = { static int __init multi_init(void) { - return usb_composite_probe(&multi_driver, multi_bind); + return usb_composite_probe(&multi_driver); } module_init(multi_init); diff --git a/drivers/usb/gadget/ncm.c b/drivers/usb/gadget/ncm.c index 5079bf6..9a20057 100644 --- a/drivers/usb/gadget/ncm.c +++ b/drivers/usb/gadget/ncm.c @@ -220,6 +220,7 @@ static __refdata struct usb_composite_driver ncm_driver = { .dev = &device_desc, .strings = dev_strings, .max_speed = USB_SPEED_HIGH, + .bind = gncm_bind, .unbind = __exit_p(gncm_unbind), }; @@ -229,7 +230,7 @@ MODULE_LICENSE("GPL"); static int __init init(void) { - return usb_composite_probe(&ncm_driver, gncm_bind); + return usb_composite_probe(&ncm_driver); } module_init(init); diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index 936d0af..a5b5e71 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c @@ -242,12 +242,13 @@ static __refdata struct usb_composite_driver nokia_driver = { .dev = &device_desc, .strings = dev_strings, .max_speed = USB_SPEED_HIGH, + .bind = nokia_bind, .unbind = __exit_p(nokia_unbind), }; static int __init nokia_init(void) { - return usb_composite_probe(&nokia_driver, nokia_bind); + return usb_composite_probe(&nokia_driver); } module_init(nokia_init); diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 0aab517..33c0c07 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -1274,6 +1274,7 @@ static __refdata struct usb_composite_driver printer_driver = { .dev = &device_desc, .strings = dev_strings, .max_speed = USB_SPEED_HIGH, + .bind = printer_bind, .unbind = printer_unbind, }; @@ -1297,7 +1298,7 @@ init(void) return status; } - status = usb_composite_probe(&printer_driver, printer_bind); + status = usb_composite_probe(&printer_driver); if (status) { class_destroy(usb_gadget_class); unregister_chrdev_region(g_printer_devno, 1); diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 7b0b6f4..ea3f8e9 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -243,6 +243,7 @@ static __refdata struct usb_composite_driver gserial_driver = { .dev = &device_desc, .strings = dev_strings, .max_speed = USB_SPEED_SUPER, + .bind = gs_bind, }; static int __init init(void) @@ -271,7 +272,7 @@ static int __init init(void) } strings_dev[STRING_DESCRIPTION_IDX].s = serial_config_driver.label; - return usb_composite_probe(&gserial_driver, gs_bind); + return usb_composite_probe(&gserial_driver); } module_init(init); diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c index 28fef844..35ca09a 100644 --- a/drivers/usb/gadget/tcm_usb_gadget.c +++ b/drivers/usb/gadget/tcm_usb_gadget.c @@ -2441,12 +2441,13 @@ static __refdata struct usb_composite_driver usbg_driver = { .dev = &usbg_device_desc, .strings = usbg_strings, .max_speed = USB_SPEED_SUPER, + .bind = usb_target_bind, .unbind = guas_unbind, }; static int usbg_attach(struct usbg_tpg *tpg) { - return usb_composite_probe(&usbg_driver, usb_target_bind); + return usb_composite_probe(&usbg_driver); } static void usbg_detach(struct usbg_tpg *tpg) diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c index d946f19..2a617c3 100644 --- a/drivers/usb/gadget/webcam.c +++ b/drivers/usb/gadget/webcam.c @@ -395,13 +395,14 @@ static __refdata struct usb_composite_driver webcam_driver = { .dev = &webcam_device_descriptor, .strings = webcam_device_strings, .max_speed = USB_SPEED_SUPER, + .bind = webcam_bind, .unbind = webcam_unbind, }; static int __init webcam_init(void) { - return usb_composite_probe(&webcam_driver, webcam_bind); + return usb_composite_probe(&webcam_driver); } static void __exit diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 5db33cb..90df613 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -339,6 +339,7 @@ static __refdata struct usb_composite_driver zero_driver = { .dev = &device_desc, .strings = dev_strings, .max_speed = USB_SPEED_SUPER, + .bind = zero_bind, .unbind = zero_unbind, .suspend = zero_suspend, .resume = zero_resume, @@ -349,7 +350,7 @@ MODULE_LICENSE("GPL"); static int __init init(void) { - return usb_composite_probe(&zero_driver, zero_bind); + return usb_composite_probe(&zero_driver); } module_init(init); diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 3153f73..19a5adf 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -305,8 +305,7 @@ struct usb_composite_driver { void (*resume)(struct usb_composite_dev *); }; -extern int usb_composite_probe(struct usb_composite_driver *driver, - int (*bind)(struct usb_composite_dev *cdev)); +extern int usb_composite_probe(struct usb_composite_driver *driver); extern void usb_composite_unregister(struct usb_composite_driver *driver); extern void usb_composite_setup_continue(struct usb_composite_dev *cdev); -- cgit v0.10.2 From 93952956c7078eb41058c5ccc5b34ae6cf59bb64 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 6 Sep 2012 20:11:05 +0200 Subject: usb: gadget: move bind() callback back to struct usb_gadget_driver This partly reverts 07a18bd7 ("usb gadget: don't save bind callback in struct usb_composite_driver") and fixes new drivers. The section missmatch problems was solved by whitelisting bind callback in modpost. Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 071d15c..2a345f2 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1585,6 +1585,7 @@ composite_resume(struct usb_gadget *gadget) /*-------------------------------------------------------------------------*/ static struct usb_gadget_driver composite_driver = { + .bind = composite_bind, .unbind = composite_unbind, .setup = composite_setup, @@ -1631,7 +1632,7 @@ int usb_composite_probe(struct usb_composite_driver *driver) composite_driver.max_speed = driver->max_speed; composite = driver; - return usb_gadget_probe_driver(&composite_driver, composite_bind); + return usb_gadget_probe_driver(&composite_driver); } /** diff --git a/drivers/usb/gadget/dbgp.c b/drivers/usb/gadget/dbgp.c index 2d2cff3..df9a010 100644 --- a/drivers/usb/gadget/dbgp.c +++ b/drivers/usb/gadget/dbgp.c @@ -405,6 +405,7 @@ fail: static __refdata struct usb_gadget_driver dbgp_driver = { .function = "dbgp", .max_speed = USB_SPEED_HIGH, + .bind = dbgp_bind, .unbind = dbgp_unbind, .setup = dbgp_setup, .disconnect = dbgp_disconnect, @@ -416,7 +417,7 @@ static __refdata struct usb_gadget_driver dbgp_driver = { static int __init dbgp_init(void) { - return usb_gadget_probe_driver(&dbgp_driver, dbgp_bind); + return usb_gadget_probe_driver(&dbgp_driver); } static void __exit dbgp_exit(void) diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 683234b..ce186fa 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -3606,6 +3606,7 @@ static void fsg_resume(struct usb_gadget *gadget) static __refdata struct usb_gadget_driver fsg_driver = { .max_speed = USB_SPEED_SUPER, .function = (char *) fsg_string_product, + .bind = fsg_bind, .unbind = fsg_unbind, .disconnect = fsg_disconnect, .setup = fsg_setup, @@ -3653,7 +3654,8 @@ static int __init fsg_init(void) if ((rc = fsg_alloc()) != 0) return rc; fsg = the_fsg; - if ((rc = usb_gadget_probe_driver(&fsg_driver, fsg_bind)) != 0) + rc = usb_gadget_probe_driver(&fsg_driver); + if (rc != 0) kref_put(&fsg->ref, fsg_release); return rc; } diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index ae13a10..2521804 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -1758,6 +1758,7 @@ gadgetfs_suspend (struct usb_gadget *gadget) static struct usb_gadget_driver gadgetfs_driver = { .function = (char *) driver_desc, + .bind = gadgetfs_bind, .unbind = gadgetfs_unbind, .setup = gadgetfs_setup, .disconnect = gadgetfs_disconnect, @@ -1780,6 +1781,7 @@ static int gadgetfs_probe (struct usb_gadget *gadget) static struct usb_gadget_driver probe_driver = { .max_speed = USB_SPEED_HIGH, + .bind = gadgetfs_probe, .unbind = gadgetfs_nop, .setup = (void *)gadgetfs_nop, .disconnect = gadgetfs_nop, @@ -1893,7 +1895,8 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) gadgetfs_driver.max_speed = USB_SPEED_HIGH; else gadgetfs_driver.max_speed = USB_SPEED_FULL; - value = usb_gadget_probe_driver(&gadgetfs_driver, gadgetfs_bind); + + value = usb_gadget_probe_driver(&gadgetfs_driver); if (value != 0) { kfree (dev->buf); dev->buf = NULL; @@ -2032,7 +2035,7 @@ gadgetfs_fill_super (struct super_block *sb, void *opts, int silent) return -ESRCH; /* fake probe to determine $CHIP */ - (void) usb_gadget_probe_driver(&probe_driver, gadgetfs_probe); + usb_gadget_probe_driver(&probe_driver); if (!CHIP) return -ENODEV; diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index bae243c..85e1e2f 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -311,13 +311,12 @@ EXPORT_SYMBOL_GPL(usb_del_gadget_udc); /* ------------------------------------------------------------------------- */ -int usb_gadget_probe_driver(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) +int usb_gadget_probe_driver(struct usb_gadget_driver *driver) { struct usb_udc *udc = NULL; int ret; - if (!driver || !bind || !driver->setup) + if (!driver || !driver->bind || !driver->setup) return -EINVAL; mutex_lock(&udc_lock); @@ -339,7 +338,7 @@ found: udc->dev.driver = &driver->driver; if (udc_is_newstyle(udc)) { - ret = bind(udc->gadget); + ret = driver->bind(udc->gadget); if (ret) goto err1; ret = usb_gadget_udc_start(udc->gadget, driver); @@ -350,7 +349,7 @@ found: usb_gadget_connect(udc->gadget); } else { - ret = usb_gadget_start(udc->gadget, driver, bind); + ret = usb_gadget_start(udc->gadget, driver, driver->bind); if (ret) goto err1; diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index d05b220..9eb4e71 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -766,6 +766,7 @@ static inline int usb_gadget_disconnect(struct usb_gadget *gadget) * when the host is disconnected. May be called in_interrupt; this * may not sleep. Some devices can't detect disconnect, so this might * not be called except as part of controller shutdown. + * @bind: the driver's bind callback * @unbind: Invoked when the driver is unbound from a gadget, * usually from rmmod (after a disconnect is reported). * Called in a context that permits sleeping. @@ -820,6 +821,7 @@ static inline int usb_gadget_disconnect(struct usb_gadget *gadget) struct usb_gadget_driver { char *function; enum usb_device_speed max_speed; + int (*bind)(struct usb_gadget *gadget); void (*unbind)(struct usb_gadget *); int (*setup)(struct usb_gadget *, const struct usb_ctrlrequest *); @@ -845,7 +847,6 @@ struct usb_gadget_driver { /** * usb_gadget_probe_driver - probe a gadget driver * @driver: the driver being registered - * @bind: the driver's bind callback * Context: can sleep * * Call this in your gadget driver's module initialization function, @@ -854,8 +855,7 @@ struct usb_gadget_driver { * registration call returns. It's expected that the @bind() function will * be in init sections. */ -int usb_gadget_probe_driver(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)); +int usb_gadget_probe_driver(struct usb_gadget_driver *driver); /** * usb_gadget_unregister_driver - unregister a gadget driver -- cgit v0.10.2 From e220ff75db3c1195814c2ad5ada11f71b011d000 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 6 Sep 2012 20:11:06 +0200 Subject: staging: ccg: include all sourced files This Android gadget includes a bunch of .c files. Fixing normal gadgets is not the real problem but this gadget is not always fixable since the problem here are fundumential / design. *I* wanted to get this removed but other people want to keep it even though there were reports that Android itself is not using it. Some poeple think that it is better to have this instead of nothing and other argue that they need sdb and mass storage gadget. The sdb function is not provided by ccg so I don't see the point of this. I don't see any logical reasoning behind it and I decided that it is time for retreat. This patch brings all dependencies of ccg into staging so I can do whatever I want in drivers/usb/gadget without breaking ccg. Cc: devel@driverdev.osuosl.org Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/staging/ccg/Makefile b/drivers/staging/ccg/Makefile index 693da63..814fa9d 100644 --- a/drivers/staging/ccg/Makefile +++ b/drivers/staging/ccg/Makefile @@ -1,4 +1,2 @@ g_ccg-y := ccg.o -ccflags-y += -Idrivers/usb/gadget - obj-$(CONFIG_USB_G_CCG) += g_ccg.o diff --git a/drivers/staging/ccg/ccg.c b/drivers/staging/ccg/ccg.c index eadda55..80feb95 100644 --- a/drivers/staging/ccg/ccg.c +++ b/drivers/staging/ccg/ccg.c @@ -32,7 +32,7 @@ #include #include -#include +#include "composite.h" #include #include "gadget_chips.h" @@ -44,19 +44,19 @@ * the runtime footprint, and giving us at least some parts of what * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ -#include "../../usb/gadget/usbstring.c" -#include "../../usb/gadget/config.c" -#include "../../usb/gadget/epautoconf.c" -#include "../../usb/gadget/composite.c" - -#include "../../usb/gadget/f_mass_storage.c" -#include "../../usb/gadget/u_serial.c" -#include "../../usb/gadget/f_acm.c" +#include "usbstring.c" +#include "config.c" +#include "epautoconf.c" +#include "composite.c" + +#include "f_mass_storage.c" +#include "u_serial.c" +#include "f_acm.c" #define USB_ETH_RNDIS y -#include "../../usb/gadget/f_rndis.c" -#include "../../usb/gadget/rndis.c" -#include "../../usb/gadget/u_ether.c" -#include "../../usb/gadget/f_fs.c" +#include "f_rndis.c" +#include "rndis.c" +#include "u_ether.c" +#include "f_fs.c" MODULE_AUTHOR("Mike Lockwood, Andrzej Pietrasiewicz"); MODULE_DESCRIPTION("Configurable Composite USB Gadget"); diff --git a/drivers/staging/ccg/composite.c b/drivers/staging/ccg/composite.c new file mode 100644 index 0000000..2a345f2 --- /dev/null +++ b/drivers/staging/ccg/composite.c @@ -0,0 +1,1687 @@ +/* + * composite.c - infrastructure for Composite USB Gadgets + * + * Copyright (C) 2006-2008 David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +/* #define VERBOSE_DEBUG */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * The code in this file is utility code, used to build a gadget driver + * from one or more "function" drivers, one or more "configuration" + * objects, and a "usb_composite_driver" by gluing them together along + * with the relevant device-wide data. + */ + +/* big enough to hold our biggest descriptor */ +#define USB_BUFSIZ 1024 + +static struct usb_composite_driver *composite; + +/* Some systems will need runtime overrides for the product identifiers + * published in the device descriptor, either numbers or strings or both. + * String parameters are in UTF-8 (superset of ASCII's 7 bit characters). + */ + +static ushort idVendor; +module_param(idVendor, ushort, 0644); +MODULE_PARM_DESC(idVendor, "USB Vendor ID"); + +static ushort idProduct; +module_param(idProduct, ushort, 0644); +MODULE_PARM_DESC(idProduct, "USB Product ID"); + +static ushort bcdDevice; +module_param(bcdDevice, ushort, 0644); +MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)"); + +static char *iManufacturer; +module_param(iManufacturer, charp, 0644); +MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string"); + +static char *iProduct; +module_param(iProduct, charp, 0644); +MODULE_PARM_DESC(iProduct, "USB Product string"); + +static char *iSerialNumber; +module_param(iSerialNumber, charp, 0644); +MODULE_PARM_DESC(iSerialNumber, "SerialNumber string"); + +static char composite_manufacturer[50]; + +/*-------------------------------------------------------------------------*/ +/** + * next_ep_desc() - advance to the next EP descriptor + * @t: currect pointer within descriptor array + * + * Return: next EP descriptor or NULL + * + * Iterate over @t until either EP descriptor found or + * NULL (that indicates end of list) encountered + */ +static struct usb_descriptor_header** +next_ep_desc(struct usb_descriptor_header **t) +{ + for (; *t; t++) { + if ((*t)->bDescriptorType == USB_DT_ENDPOINT) + return t; + } + return NULL; +} + +/* + * for_each_ep_desc()- iterate over endpoint descriptors in the + * descriptors list + * @start: pointer within descriptor array. + * @ep_desc: endpoint descriptor to use as the loop cursor + */ +#define for_each_ep_desc(start, ep_desc) \ + for (ep_desc = next_ep_desc(start); \ + ep_desc; ep_desc = next_ep_desc(ep_desc+1)) + +/** + * config_ep_by_speed() - configures the given endpoint + * according to gadget speed. + * @g: pointer to the gadget + * @f: usb function + * @_ep: the endpoint to configure + * + * Return: error code, 0 on success + * + * This function chooses the right descriptors for a given + * endpoint according to gadget speed and saves it in the + * endpoint desc field. If the endpoint already has a descriptor + * assigned to it - overwrites it with currently corresponding + * descriptor. The endpoint maxpacket field is updated according + * to the chosen descriptor. + * Note: the supplied function should hold all the descriptors + * for supported speeds + */ +int config_ep_by_speed(struct usb_gadget *g, + struct usb_function *f, + struct usb_ep *_ep) +{ + struct usb_composite_dev *cdev = get_gadget_data(g); + struct usb_endpoint_descriptor *chosen_desc = NULL; + struct usb_descriptor_header **speed_desc = NULL; + + struct usb_ss_ep_comp_descriptor *comp_desc = NULL; + int want_comp_desc = 0; + + struct usb_descriptor_header **d_spd; /* cursor for speed desc */ + + if (!g || !f || !_ep) + return -EIO; + + /* select desired speed */ + switch (g->speed) { + case USB_SPEED_SUPER: + if (gadget_is_superspeed(g)) { + speed_desc = f->ss_descriptors; + want_comp_desc = 1; + break; + } + /* else: Fall trough */ + case USB_SPEED_HIGH: + if (gadget_is_dualspeed(g)) { + speed_desc = f->hs_descriptors; + break; + } + /* else: fall through */ + default: + speed_desc = f->descriptors; + } + /* find descriptors */ + for_each_ep_desc(speed_desc, d_spd) { + chosen_desc = (struct usb_endpoint_descriptor *)*d_spd; + if (chosen_desc->bEndpointAddress == _ep->address) + goto ep_found; + } + return -EIO; + +ep_found: + /* commit results */ + _ep->maxpacket = usb_endpoint_maxp(chosen_desc); + _ep->desc = chosen_desc; + _ep->comp_desc = NULL; + _ep->maxburst = 0; + _ep->mult = 0; + if (!want_comp_desc) + return 0; + + /* + * Companion descriptor should follow EP descriptor + * USB 3.0 spec, #9.6.7 + */ + comp_desc = (struct usb_ss_ep_comp_descriptor *)*(++d_spd); + if (!comp_desc || + (comp_desc->bDescriptorType != USB_DT_SS_ENDPOINT_COMP)) + return -EIO; + _ep->comp_desc = comp_desc; + if (g->speed == USB_SPEED_SUPER) { + switch (usb_endpoint_type(_ep->desc)) { + case USB_ENDPOINT_XFER_ISOC: + /* mult: bits 1:0 of bmAttributes */ + _ep->mult = comp_desc->bmAttributes & 0x3; + case USB_ENDPOINT_XFER_BULK: + case USB_ENDPOINT_XFER_INT: + _ep->maxburst = comp_desc->bMaxBurst + 1; + break; + default: + if (comp_desc->bMaxBurst != 0) + ERROR(cdev, "ep0 bMaxBurst must be 0\n"); + _ep->maxburst = 1; + break; + } + } + return 0; +} + +/** + * usb_add_function() - add a function to a configuration + * @config: the configuration + * @function: the function being added + * Context: single threaded during gadget setup + * + * After initialization, each configuration must have one or more + * functions added to it. Adding a function involves calling its @bind() + * method to allocate resources such as interface and string identifiers + * and endpoints. + * + * This function returns the value of the function's bind(), which is + * zero for success else a negative errno value. + */ +int usb_add_function(struct usb_configuration *config, + struct usb_function *function) +{ + int value = -EINVAL; + + DBG(config->cdev, "adding '%s'/%p to config '%s'/%p\n", + function->name, function, + config->label, config); + + if (!function->set_alt || !function->disable) + goto done; + + function->config = config; + list_add_tail(&function->list, &config->functions); + + /* REVISIT *require* function->bind? */ + if (function->bind) { + value = function->bind(config, function); + if (value < 0) { + list_del(&function->list); + function->config = NULL; + } + } else + value = 0; + + /* We allow configurations that don't work at both speeds. + * If we run into a lowspeed Linux system, treat it the same + * as full speed ... it's the function drivers that will need + * to avoid bulk and ISO transfers. + */ + if (!config->fullspeed && function->descriptors) + config->fullspeed = true; + if (!config->highspeed && function->hs_descriptors) + config->highspeed = true; + if (!config->superspeed && function->ss_descriptors) + config->superspeed = true; + +done: + if (value) + DBG(config->cdev, "adding '%s'/%p --> %d\n", + function->name, function, value); + return value; +} + +/** + * usb_function_deactivate - prevent function and gadget enumeration + * @function: the function that isn't yet ready to respond + * + * Blocks response of the gadget driver to host enumeration by + * preventing the data line pullup from being activated. This is + * normally called during @bind() processing to change from the + * initial "ready to respond" state, or when a required resource + * becomes available. + * + * For example, drivers that serve as a passthrough to a userspace + * daemon can block enumeration unless that daemon (such as an OBEX, + * MTP, or print server) is ready to handle host requests. + * + * Not all systems support software control of their USB peripheral + * data pullups. + * + * Returns zero on success, else negative errno. + */ +int usb_function_deactivate(struct usb_function *function) +{ + struct usb_composite_dev *cdev = function->config->cdev; + unsigned long flags; + int status = 0; + + spin_lock_irqsave(&cdev->lock, flags); + + if (cdev->deactivations == 0) + status = usb_gadget_disconnect(cdev->gadget); + if (status == 0) + cdev->deactivations++; + + spin_unlock_irqrestore(&cdev->lock, flags); + return status; +} + +/** + * usb_function_activate - allow function and gadget enumeration + * @function: function on which usb_function_activate() was called + * + * Reverses effect of usb_function_deactivate(). If no more functions + * are delaying their activation, the gadget driver will respond to + * host enumeration procedures. + * + * Returns zero on success, else negative errno. + */ +int usb_function_activate(struct usb_function *function) +{ + struct usb_composite_dev *cdev = function->config->cdev; + unsigned long flags; + int status = 0; + + spin_lock_irqsave(&cdev->lock, flags); + + if (WARN_ON(cdev->deactivations == 0)) + status = -EINVAL; + else { + cdev->deactivations--; + if (cdev->deactivations == 0) + status = usb_gadget_connect(cdev->gadget); + } + + spin_unlock_irqrestore(&cdev->lock, flags); + return status; +} + +/** + * usb_interface_id() - allocate an unused interface ID + * @config: configuration associated with the interface + * @function: function handling the interface + * Context: single threaded during gadget setup + * + * usb_interface_id() is called from usb_function.bind() callbacks to + * allocate new interface IDs. The function driver will then store that + * ID in interface, association, CDC union, and other descriptors. It + * will also handle any control requests targeted at that interface, + * particularly changing its altsetting via set_alt(). There may + * also be class-specific or vendor-specific requests to handle. + * + * All interface identifier should be allocated using this routine, to + * ensure that for example different functions don't wrongly assign + * different meanings to the same identifier. Note that since interface + * identifiers are configuration-specific, functions used in more than + * one configuration (or more than once in a given configuration) need + * multiple versions of the relevant descriptors. + * + * Returns the interface ID which was allocated; or -ENODEV if no + * more interface IDs can be allocated. + */ +int usb_interface_id(struct usb_configuration *config, + struct usb_function *function) +{ + unsigned id = config->next_interface_id; + + if (id < MAX_CONFIG_INTERFACES) { + config->interface[id] = function; + config->next_interface_id = id + 1; + return id; + } + return -ENODEV; +} + +static int config_buf(struct usb_configuration *config, + enum usb_device_speed speed, void *buf, u8 type) +{ + struct usb_config_descriptor *c = buf; + void *next = buf + USB_DT_CONFIG_SIZE; + int len = USB_BUFSIZ - USB_DT_CONFIG_SIZE; + struct usb_function *f; + int status; + + /* write the config descriptor */ + c = buf; + c->bLength = USB_DT_CONFIG_SIZE; + c->bDescriptorType = type; + /* wTotalLength is written later */ + c->bNumInterfaces = config->next_interface_id; + c->bConfigurationValue = config->bConfigurationValue; + c->iConfiguration = config->iConfiguration; + c->bmAttributes = USB_CONFIG_ATT_ONE | config->bmAttributes; + c->bMaxPower = config->bMaxPower ? : (CONFIG_USB_GADGET_VBUS_DRAW / 2); + + /* There may be e.g. OTG descriptors */ + if (config->descriptors) { + status = usb_descriptor_fillbuf(next, len, + config->descriptors); + if (status < 0) + return status; + len -= status; + next += status; + } + + /* add each function's descriptors */ + list_for_each_entry(f, &config->functions, list) { + struct usb_descriptor_header **descriptors; + + switch (speed) { + case USB_SPEED_SUPER: + descriptors = f->ss_descriptors; + break; + case USB_SPEED_HIGH: + descriptors = f->hs_descriptors; + break; + default: + descriptors = f->descriptors; + } + + if (!descriptors) + continue; + status = usb_descriptor_fillbuf(next, len, + (const struct usb_descriptor_header **) descriptors); + if (status < 0) + return status; + len -= status; + next += status; + } + + len = next - buf; + c->wTotalLength = cpu_to_le16(len); + return len; +} + +static int config_desc(struct usb_composite_dev *cdev, unsigned w_value) +{ + struct usb_gadget *gadget = cdev->gadget; + struct usb_configuration *c; + u8 type = w_value >> 8; + enum usb_device_speed speed = USB_SPEED_UNKNOWN; + + if (gadget->speed == USB_SPEED_SUPER) + speed = gadget->speed; + else if (gadget_is_dualspeed(gadget)) { + int hs = 0; + if (gadget->speed == USB_SPEED_HIGH) + hs = 1; + if (type == USB_DT_OTHER_SPEED_CONFIG) + hs = !hs; + if (hs) + speed = USB_SPEED_HIGH; + + } + + /* This is a lookup by config *INDEX* */ + w_value &= 0xff; + list_for_each_entry(c, &cdev->configs, list) { + /* ignore configs that won't work at this speed */ + switch (speed) { + case USB_SPEED_SUPER: + if (!c->superspeed) + continue; + break; + case USB_SPEED_HIGH: + if (!c->highspeed) + continue; + break; + default: + if (!c->fullspeed) + continue; + } + + if (w_value == 0) + return config_buf(c, speed, cdev->req->buf, type); + w_value--; + } + return -EINVAL; +} + +static int count_configs(struct usb_composite_dev *cdev, unsigned type) +{ + struct usb_gadget *gadget = cdev->gadget; + struct usb_configuration *c; + unsigned count = 0; + int hs = 0; + int ss = 0; + + if (gadget_is_dualspeed(gadget)) { + if (gadget->speed == USB_SPEED_HIGH) + hs = 1; + if (gadget->speed == USB_SPEED_SUPER) + ss = 1; + if (type == USB_DT_DEVICE_QUALIFIER) + hs = !hs; + } + list_for_each_entry(c, &cdev->configs, list) { + /* ignore configs that won't work at this speed */ + if (ss) { + if (!c->superspeed) + continue; + } else if (hs) { + if (!c->highspeed) + continue; + } else { + if (!c->fullspeed) + continue; + } + count++; + } + return count; +} + +/** + * bos_desc() - prepares the BOS descriptor. + * @cdev: pointer to usb_composite device to generate the bos + * descriptor for + * + * This function generates the BOS (Binary Device Object) + * descriptor and its device capabilities descriptors. The BOS + * descriptor should be supported by a SuperSpeed device. + */ +static int bos_desc(struct usb_composite_dev *cdev) +{ + struct usb_ext_cap_descriptor *usb_ext; + struct usb_ss_cap_descriptor *ss_cap; + struct usb_dcd_config_params dcd_config_params; + struct usb_bos_descriptor *bos = cdev->req->buf; + + bos->bLength = USB_DT_BOS_SIZE; + bos->bDescriptorType = USB_DT_BOS; + + bos->wTotalLength = cpu_to_le16(USB_DT_BOS_SIZE); + bos->bNumDeviceCaps = 0; + + /* + * A SuperSpeed device shall include the USB2.0 extension descriptor + * and shall support LPM when operating in USB2.0 HS mode. + */ + usb_ext = cdev->req->buf + le16_to_cpu(bos->wTotalLength); + bos->bNumDeviceCaps++; + le16_add_cpu(&bos->wTotalLength, USB_DT_USB_EXT_CAP_SIZE); + usb_ext->bLength = USB_DT_USB_EXT_CAP_SIZE; + usb_ext->bDescriptorType = USB_DT_DEVICE_CAPABILITY; + usb_ext->bDevCapabilityType = USB_CAP_TYPE_EXT; + usb_ext->bmAttributes = cpu_to_le32(USB_LPM_SUPPORT); + + /* + * The Superspeed USB Capability descriptor shall be implemented by all + * SuperSpeed devices. + */ + ss_cap = cdev->req->buf + le16_to_cpu(bos->wTotalLength); + bos->bNumDeviceCaps++; + le16_add_cpu(&bos->wTotalLength, USB_DT_USB_SS_CAP_SIZE); + ss_cap->bLength = USB_DT_USB_SS_CAP_SIZE; + ss_cap->bDescriptorType = USB_DT_DEVICE_CAPABILITY; + ss_cap->bDevCapabilityType = USB_SS_CAP_TYPE; + ss_cap->bmAttributes = 0; /* LTM is not supported yet */ + ss_cap->wSpeedSupported = cpu_to_le16(USB_LOW_SPEED_OPERATION | + USB_FULL_SPEED_OPERATION | + USB_HIGH_SPEED_OPERATION | + USB_5GBPS_OPERATION); + ss_cap->bFunctionalitySupport = USB_LOW_SPEED_OPERATION; + + /* Get Controller configuration */ + if (cdev->gadget->ops->get_config_params) + cdev->gadget->ops->get_config_params(&dcd_config_params); + else { + dcd_config_params.bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT; + dcd_config_params.bU2DevExitLat = + cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT); + } + ss_cap->bU1devExitLat = dcd_config_params.bU1devExitLat; + ss_cap->bU2DevExitLat = dcd_config_params.bU2DevExitLat; + + return le16_to_cpu(bos->wTotalLength); +} + +static void device_qual(struct usb_composite_dev *cdev) +{ + struct usb_qualifier_descriptor *qual = cdev->req->buf; + + qual->bLength = sizeof(*qual); + qual->bDescriptorType = USB_DT_DEVICE_QUALIFIER; + /* POLICY: same bcdUSB and device type info at both speeds */ + qual->bcdUSB = cdev->desc.bcdUSB; + qual->bDeviceClass = cdev->desc.bDeviceClass; + qual->bDeviceSubClass = cdev->desc.bDeviceSubClass; + qual->bDeviceProtocol = cdev->desc.bDeviceProtocol; + /* ASSUME same EP0 fifo size at both speeds */ + qual->bMaxPacketSize0 = cdev->gadget->ep0->maxpacket; + qual->bNumConfigurations = count_configs(cdev, USB_DT_DEVICE_QUALIFIER); + qual->bRESERVED = 0; +} + +/*-------------------------------------------------------------------------*/ + +static void reset_config(struct usb_composite_dev *cdev) +{ + struct usb_function *f; + + DBG(cdev, "reset config\n"); + + list_for_each_entry(f, &cdev->config->functions, list) { + if (f->disable) + f->disable(f); + + bitmap_zero(f->endpoints, 32); + } + cdev->config = NULL; +} + +static int set_config(struct usb_composite_dev *cdev, + const struct usb_ctrlrequest *ctrl, unsigned number) +{ + struct usb_gadget *gadget = cdev->gadget; + struct usb_configuration *c = NULL; + int result = -EINVAL; + unsigned power = gadget_is_otg(gadget) ? 8 : 100; + int tmp; + + if (number) { + list_for_each_entry(c, &cdev->configs, list) { + if (c->bConfigurationValue == number) { + /* + * We disable the FDs of the previous + * configuration only if the new configuration + * is a valid one + */ + if (cdev->config) + reset_config(cdev); + result = 0; + break; + } + } + if (result < 0) + goto done; + } else { /* Zero configuration value - need to reset the config */ + if (cdev->config) + reset_config(cdev); + result = 0; + } + + INFO(cdev, "%s config #%d: %s\n", + usb_speed_string(gadget->speed), + number, c ? c->label : "unconfigured"); + + if (!c) + goto done; + + cdev->config = c; + + /* Initialize all interfaces by setting them to altsetting zero. */ + for (tmp = 0; tmp < MAX_CONFIG_INTERFACES; tmp++) { + struct usb_function *f = c->interface[tmp]; + struct usb_descriptor_header **descriptors; + + if (!f) + break; + + /* + * Record which endpoints are used by the function. This is used + * to dispatch control requests targeted at that endpoint to the + * function's setup callback instead of the current + * configuration's setup callback. + */ + switch (gadget->speed) { + case USB_SPEED_SUPER: + descriptors = f->ss_descriptors; + break; + case USB_SPEED_HIGH: + descriptors = f->hs_descriptors; + break; + default: + descriptors = f->descriptors; + } + + for (; *descriptors; ++descriptors) { + struct usb_endpoint_descriptor *ep; + int addr; + + if ((*descriptors)->bDescriptorType != USB_DT_ENDPOINT) + continue; + + ep = (struct usb_endpoint_descriptor *)*descriptors; + addr = ((ep->bEndpointAddress & 0x80) >> 3) + | (ep->bEndpointAddress & 0x0f); + set_bit(addr, f->endpoints); + } + + result = f->set_alt(f, tmp, 0); + if (result < 0) { + DBG(cdev, "interface %d (%s/%p) alt 0 --> %d\n", + tmp, f->name, f, result); + + reset_config(cdev); + goto done; + } + + if (result == USB_GADGET_DELAYED_STATUS) { + DBG(cdev, + "%s: interface %d (%s) requested delayed status\n", + __func__, tmp, f->name); + cdev->delayed_status++; + DBG(cdev, "delayed_status count %d\n", + cdev->delayed_status); + } + } + + /* when we return, be sure our power usage is valid */ + power = c->bMaxPower ? (2 * c->bMaxPower) : CONFIG_USB_GADGET_VBUS_DRAW; +done: + usb_gadget_vbus_draw(gadget, power); + if (result >= 0 && cdev->delayed_status) + result = USB_GADGET_DELAYED_STATUS; + return result; +} + +/** + * usb_add_config() - add a configuration to a device. + * @cdev: wraps the USB gadget + * @config: the configuration, with bConfigurationValue assigned + * @bind: the configuration's bind function + * Context: single threaded during gadget setup + * + * One of the main tasks of a composite @bind() routine is to + * add each of the configurations it supports, using this routine. + * + * This function returns the value of the configuration's @bind(), which + * is zero for success else a negative errno value. Binding configurations + * assigns global resources including string IDs, and per-configuration + * resources such as interface IDs and endpoints. + */ +int usb_add_config(struct usb_composite_dev *cdev, + struct usb_configuration *config, + int (*bind)(struct usb_configuration *)) +{ + int status = -EINVAL; + struct usb_configuration *c; + + DBG(cdev, "adding config #%u '%s'/%p\n", + config->bConfigurationValue, + config->label, config); + + if (!config->bConfigurationValue || !bind) + goto done; + + /* Prevent duplicate configuration identifiers */ + list_for_each_entry(c, &cdev->configs, list) { + if (c->bConfigurationValue == config->bConfigurationValue) { + status = -EBUSY; + goto done; + } + } + + config->cdev = cdev; + list_add_tail(&config->list, &cdev->configs); + + INIT_LIST_HEAD(&config->functions); + config->next_interface_id = 0; + memset(config->interface, 0, sizeof(config->interface)); + + status = bind(config); + if (status < 0) { + while (!list_empty(&config->functions)) { + struct usb_function *f; + + f = list_first_entry(&config->functions, + struct usb_function, list); + list_del(&f->list); + if (f->unbind) { + DBG(cdev, "unbind function '%s'/%p\n", + f->name, f); + f->unbind(config, f); + /* may free memory for "f" */ + } + } + list_del(&config->list); + config->cdev = NULL; + } else { + unsigned i; + + DBG(cdev, "cfg %d/%p speeds:%s%s%s\n", + config->bConfigurationValue, config, + config->superspeed ? " super" : "", + config->highspeed ? " high" : "", + config->fullspeed + ? (gadget_is_dualspeed(cdev->gadget) + ? " full" + : " full/low") + : ""); + + for (i = 0; i < MAX_CONFIG_INTERFACES; i++) { + struct usb_function *f = config->interface[i]; + + if (!f) + continue; + DBG(cdev, " interface %d = %s/%p\n", + i, f->name, f); + } + } + + /* set_alt(), or next bind(), sets up + * ep->driver_data as needed. + */ + usb_ep_autoconfig_reset(cdev->gadget); + +done: + if (status) + DBG(cdev, "added config '%s'/%u --> %d\n", config->label, + config->bConfigurationValue, status); + return status; +} + +static void remove_config(struct usb_composite_dev *cdev, + struct usb_configuration *config) +{ + while (!list_empty(&config->functions)) { + struct usb_function *f; + + f = list_first_entry(&config->functions, + struct usb_function, list); + list_del(&f->list); + if (f->unbind) { + DBG(cdev, "unbind function '%s'/%p\n", f->name, f); + f->unbind(config, f); + /* may free memory for "f" */ + } + } + list_del(&config->list); + if (config->unbind) { + DBG(cdev, "unbind config '%s'/%p\n", config->label, config); + config->unbind(config); + /* may free memory for "c" */ + } +} + +/** + * usb_remove_config() - remove a configuration from a device. + * @cdev: wraps the USB gadget + * @config: the configuration + * + * Drivers must call usb_gadget_disconnect before calling this function + * to disconnect the device from the host and make sure the host will not + * try to enumerate the device while we are changing the config list. + */ +void usb_remove_config(struct usb_composite_dev *cdev, + struct usb_configuration *config) +{ + unsigned long flags; + + spin_lock_irqsave(&cdev->lock, flags); + + if (cdev->config == config) + reset_config(cdev); + + spin_unlock_irqrestore(&cdev->lock, flags); + + remove_config(cdev, config); +} + +/*-------------------------------------------------------------------------*/ + +/* We support strings in multiple languages ... string descriptor zero + * says which languages are supported. The typical case will be that + * only one language (probably English) is used, with I18N handled on + * the host side. + */ + +static void collect_langs(struct usb_gadget_strings **sp, __le16 *buf) +{ + const struct usb_gadget_strings *s; + __le16 language; + __le16 *tmp; + + while (*sp) { + s = *sp; + language = cpu_to_le16(s->language); + for (tmp = buf; *tmp && tmp < &buf[126]; tmp++) { + if (*tmp == language) + goto repeat; + } + *tmp++ = language; +repeat: + sp++; + } +} + +static int lookup_string( + struct usb_gadget_strings **sp, + void *buf, + u16 language, + int id +) +{ + struct usb_gadget_strings *s; + int value; + + while (*sp) { + s = *sp++; + if (s->language != language) + continue; + value = usb_gadget_get_string(s, id, buf); + if (value > 0) + return value; + } + return -EINVAL; +} + +static int get_string(struct usb_composite_dev *cdev, + void *buf, u16 language, int id) +{ + struct usb_configuration *c; + struct usb_function *f; + int len; + const char *str; + + /* Yes, not only is USB's I18N support probably more than most + * folk will ever care about ... also, it's all supported here. + * (Except for UTF8 support for Unicode's "Astral Planes".) + */ + + /* 0 == report all available language codes */ + if (id == 0) { + struct usb_string_descriptor *s = buf; + struct usb_gadget_strings **sp; + + memset(s, 0, 256); + s->bDescriptorType = USB_DT_STRING; + + sp = composite->strings; + if (sp) + collect_langs(sp, s->wData); + + list_for_each_entry(c, &cdev->configs, list) { + sp = c->strings; + if (sp) + collect_langs(sp, s->wData); + + list_for_each_entry(f, &c->functions, list) { + sp = f->strings; + if (sp) + collect_langs(sp, s->wData); + } + } + + for (len = 0; len <= 126 && s->wData[len]; len++) + continue; + if (!len) + return -EINVAL; + + s->bLength = 2 * (len + 1); + return s->bLength; + } + + /* Otherwise, look up and return a specified string. First + * check if the string has not been overridden. + */ + if (cdev->manufacturer_override == id) + str = iManufacturer ?: composite->iManufacturer ?: + composite_manufacturer; + else if (cdev->product_override == id) + str = iProduct ?: composite->iProduct; + else if (cdev->serial_override == id) + str = iSerialNumber ?: composite->iSerialNumber; + else + str = NULL; + if (str) { + struct usb_gadget_strings strings = { + .language = language, + .strings = &(struct usb_string) { 0xff, str } + }; + return usb_gadget_get_string(&strings, 0xff, buf); + } + + /* String IDs are device-scoped, so we look up each string + * table we're told about. These lookups are infrequent; + * simpler-is-better here. + */ + if (composite->strings) { + len = lookup_string(composite->strings, buf, language, id); + if (len > 0) + return len; + } + list_for_each_entry(c, &cdev->configs, list) { + if (c->strings) { + len = lookup_string(c->strings, buf, language, id); + if (len > 0) + return len; + } + list_for_each_entry(f, &c->functions, list) { + if (!f->strings) + continue; + len = lookup_string(f->strings, buf, language, id); + if (len > 0) + return len; + } + } + return -EINVAL; +} + +/** + * usb_string_id() - allocate an unused string ID + * @cdev: the device whose string descriptor IDs are being allocated + * Context: single threaded during gadget setup + * + * @usb_string_id() is called from bind() callbacks to allocate + * string IDs. Drivers for functions, configurations, or gadgets will + * then store that ID in the appropriate descriptors and string table. + * + * All string identifier should be allocated using this, + * @usb_string_ids_tab() or @usb_string_ids_n() routine, to ensure + * that for example different functions don't wrongly assign different + * meanings to the same identifier. + */ +int usb_string_id(struct usb_composite_dev *cdev) +{ + if (cdev->next_string_id < 254) { + /* string id 0 is reserved by USB spec for list of + * supported languages */ + /* 255 reserved as well? -- mina86 */ + cdev->next_string_id++; + return cdev->next_string_id; + } + return -ENODEV; +} + +/** + * usb_string_ids() - allocate unused string IDs in batch + * @cdev: the device whose string descriptor IDs are being allocated + * @str: an array of usb_string objects to assign numbers to + * Context: single threaded during gadget setup + * + * @usb_string_ids() is called from bind() callbacks to allocate + * string IDs. Drivers for functions, configurations, or gadgets will + * then copy IDs from the string table to the appropriate descriptors + * and string table for other languages. + * + * All string identifier should be allocated using this, + * @usb_string_id() or @usb_string_ids_n() routine, to ensure that for + * example different functions don't wrongly assign different meanings + * to the same identifier. + */ +int usb_string_ids_tab(struct usb_composite_dev *cdev, struct usb_string *str) +{ + int next = cdev->next_string_id; + + for (; str->s; ++str) { + if (unlikely(next >= 254)) + return -ENODEV; + str->id = ++next; + } + + cdev->next_string_id = next; + + return 0; +} + +/** + * usb_string_ids_n() - allocate unused string IDs in batch + * @c: the device whose string descriptor IDs are being allocated + * @n: number of string IDs to allocate + * Context: single threaded during gadget setup + * + * Returns the first requested ID. This ID and next @n-1 IDs are now + * valid IDs. At least provided that @n is non-zero because if it + * is, returns last requested ID which is now very useful information. + * + * @usb_string_ids_n() is called from bind() callbacks to allocate + * string IDs. Drivers for functions, configurations, or gadgets will + * then store that ID in the appropriate descriptors and string table. + * + * All string identifier should be allocated using this, + * @usb_string_id() or @usb_string_ids_n() routine, to ensure that for + * example different functions don't wrongly assign different meanings + * to the same identifier. + */ +int usb_string_ids_n(struct usb_composite_dev *c, unsigned n) +{ + unsigned next = c->next_string_id; + if (unlikely(n > 254 || (unsigned)next + n > 254)) + return -ENODEV; + c->next_string_id += n; + return next + 1; +} + + +/*-------------------------------------------------------------------------*/ + +static void composite_setup_complete(struct usb_ep *ep, struct usb_request *req) +{ + if (req->status || req->actual != req->length) + DBG((struct usb_composite_dev *) ep->driver_data, + "setup complete --> %d, %d/%d\n", + req->status, req->actual, req->length); +} + +/* + * The setup() callback implements all the ep0 functionality that's + * not handled lower down, in hardware or the hardware driver(like + * device and endpoint feature flags, and their status). It's all + * housekeeping for the gadget function we're implementing. Most of + * the work is in config and function specific setup. + */ +static int +composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) +{ + struct usb_composite_dev *cdev = get_gadget_data(gadget); + struct usb_request *req = cdev->req; + int value = -EOPNOTSUPP; + int status = 0; + u16 w_index = le16_to_cpu(ctrl->wIndex); + u8 intf = w_index & 0xFF; + u16 w_value = le16_to_cpu(ctrl->wValue); + u16 w_length = le16_to_cpu(ctrl->wLength); + struct usb_function *f = NULL; + u8 endp; + + /* partial re-init of the response message; the function or the + * gadget might need to intercept e.g. a control-OUT completion + * when we delegate to it. + */ + req->zero = 0; + req->complete = composite_setup_complete; + req->length = 0; + gadget->ep0->driver_data = cdev; + + switch (ctrl->bRequest) { + + /* we handle all standard USB descriptors */ + case USB_REQ_GET_DESCRIPTOR: + if (ctrl->bRequestType != USB_DIR_IN) + goto unknown; + switch (w_value >> 8) { + + case USB_DT_DEVICE: + cdev->desc.bNumConfigurations = + count_configs(cdev, USB_DT_DEVICE); + cdev->desc.bMaxPacketSize0 = + cdev->gadget->ep0->maxpacket; + if (gadget_is_superspeed(gadget)) { + if (gadget->speed >= USB_SPEED_SUPER) { + cdev->desc.bcdUSB = cpu_to_le16(0x0300); + cdev->desc.bMaxPacketSize0 = 9; + } else { + cdev->desc.bcdUSB = cpu_to_le16(0x0210); + } + } + + value = min(w_length, (u16) sizeof cdev->desc); + memcpy(req->buf, &cdev->desc, value); + break; + case USB_DT_DEVICE_QUALIFIER: + if (!gadget_is_dualspeed(gadget) || + gadget->speed >= USB_SPEED_SUPER) + break; + device_qual(cdev); + value = min_t(int, w_length, + sizeof(struct usb_qualifier_descriptor)); + break; + case USB_DT_OTHER_SPEED_CONFIG: + if (!gadget_is_dualspeed(gadget) || + gadget->speed >= USB_SPEED_SUPER) + break; + /* FALLTHROUGH */ + case USB_DT_CONFIG: + value = config_desc(cdev, w_value); + if (value >= 0) + value = min(w_length, (u16) value); + break; + case USB_DT_STRING: + value = get_string(cdev, req->buf, + w_index, w_value & 0xff); + if (value >= 0) + value = min(w_length, (u16) value); + break; + case USB_DT_BOS: + if (gadget_is_superspeed(gadget)) { + value = bos_desc(cdev); + value = min(w_length, (u16) value); + } + break; + } + break; + + /* any number of configs can work */ + case USB_REQ_SET_CONFIGURATION: + if (ctrl->bRequestType != 0) + goto unknown; + if (gadget_is_otg(gadget)) { + if (gadget->a_hnp_support) + DBG(cdev, "HNP available\n"); + else if (gadget->a_alt_hnp_support) + DBG(cdev, "HNP on another port\n"); + else + VDBG(cdev, "HNP inactive\n"); + } + spin_lock(&cdev->lock); + value = set_config(cdev, ctrl, w_value); + spin_unlock(&cdev->lock); + break; + case USB_REQ_GET_CONFIGURATION: + if (ctrl->bRequestType != USB_DIR_IN) + goto unknown; + if (cdev->config) + *(u8 *)req->buf = cdev->config->bConfigurationValue; + else + *(u8 *)req->buf = 0; + value = min(w_length, (u16) 1); + break; + + /* function drivers must handle get/set altsetting; if there's + * no get() method, we know only altsetting zero works. + */ + case USB_REQ_SET_INTERFACE: + if (ctrl->bRequestType != USB_RECIP_INTERFACE) + goto unknown; + if (!cdev->config || intf >= MAX_CONFIG_INTERFACES) + break; + f = cdev->config->interface[intf]; + if (!f) + break; + if (w_value && !f->set_alt) + break; + value = f->set_alt(f, w_index, w_value); + if (value == USB_GADGET_DELAYED_STATUS) { + DBG(cdev, + "%s: interface %d (%s) requested delayed status\n", + __func__, intf, f->name); + cdev->delayed_status++; + DBG(cdev, "delayed_status count %d\n", + cdev->delayed_status); + } + break; + case USB_REQ_GET_INTERFACE: + if (ctrl->bRequestType != (USB_DIR_IN|USB_RECIP_INTERFACE)) + goto unknown; + if (!cdev->config || intf >= MAX_CONFIG_INTERFACES) + break; + f = cdev->config->interface[intf]; + if (!f) + break; + /* lots of interfaces only need altsetting zero... */ + value = f->get_alt ? f->get_alt(f, w_index) : 0; + if (value < 0) + break; + *((u8 *)req->buf) = value; + value = min(w_length, (u16) 1); + break; + + /* + * USB 3.0 additions: + * Function driver should handle get_status request. If such cb + * wasn't supplied we respond with default value = 0 + * Note: function driver should supply such cb only for the first + * interface of the function + */ + case USB_REQ_GET_STATUS: + if (!gadget_is_superspeed(gadget)) + goto unknown; + if (ctrl->bRequestType != (USB_DIR_IN | USB_RECIP_INTERFACE)) + goto unknown; + value = 2; /* This is the length of the get_status reply */ + put_unaligned_le16(0, req->buf); + if (!cdev->config || intf >= MAX_CONFIG_INTERFACES) + break; + f = cdev->config->interface[intf]; + if (!f) + break; + status = f->get_status ? f->get_status(f) : 0; + if (status < 0) + break; + put_unaligned_le16(status & 0x0000ffff, req->buf); + break; + /* + * Function drivers should handle SetFeature/ClearFeature + * (FUNCTION_SUSPEND) request. function_suspend cb should be supplied + * only for the first interface of the function + */ + case USB_REQ_CLEAR_FEATURE: + case USB_REQ_SET_FEATURE: + if (!gadget_is_superspeed(gadget)) + goto unknown; + if (ctrl->bRequestType != (USB_DIR_OUT | USB_RECIP_INTERFACE)) + goto unknown; + switch (w_value) { + case USB_INTRF_FUNC_SUSPEND: + if (!cdev->config || intf >= MAX_CONFIG_INTERFACES) + break; + f = cdev->config->interface[intf]; + if (!f) + break; + value = 0; + if (f->func_suspend) + value = f->func_suspend(f, w_index >> 8); + if (value < 0) { + ERROR(cdev, + "func_suspend() returned error %d\n", + value); + value = 0; + } + break; + } + break; + default: +unknown: + VDBG(cdev, + "non-core control req%02x.%02x v%04x i%04x l%d\n", + ctrl->bRequestType, ctrl->bRequest, + w_value, w_index, w_length); + + /* functions always handle their interfaces and endpoints... + * punt other recipients (other, WUSB, ...) to the current + * configuration code. + * + * REVISIT it could make sense to let the composite device + * take such requests too, if that's ever needed: to work + * in config 0, etc. + */ + switch (ctrl->bRequestType & USB_RECIP_MASK) { + case USB_RECIP_INTERFACE: + if (!cdev->config || intf >= MAX_CONFIG_INTERFACES) + break; + f = cdev->config->interface[intf]; + break; + + case USB_RECIP_ENDPOINT: + endp = ((w_index & 0x80) >> 3) | (w_index & 0x0f); + list_for_each_entry(f, &cdev->config->functions, list) { + if (test_bit(endp, f->endpoints)) + break; + } + if (&f->list == &cdev->config->functions) + f = NULL; + break; + } + + if (f && f->setup) + value = f->setup(f, ctrl); + else { + struct usb_configuration *c; + + c = cdev->config; + if (c && c->setup) + value = c->setup(c, ctrl); + } + + goto done; + } + + /* respond with data transfer before status phase? */ + if (value >= 0 && value != USB_GADGET_DELAYED_STATUS) { + req->length = value; + req->zero = value < w_length; + value = usb_ep_queue(gadget->ep0, req, GFP_ATOMIC); + if (value < 0) { + DBG(cdev, "ep_queue --> %d\n", value); + req->status = 0; + composite_setup_complete(gadget->ep0, req); + } + } else if (value == USB_GADGET_DELAYED_STATUS && w_length != 0) { + WARN(cdev, + "%s: Delayed status not supported for w_length != 0", + __func__); + } + +done: + /* device either stalls (value < 0) or reports success */ + return value; +} + +static void composite_disconnect(struct usb_gadget *gadget) +{ + struct usb_composite_dev *cdev = get_gadget_data(gadget); + unsigned long flags; + + /* REVISIT: should we have config and device level + * disconnect callbacks? + */ + spin_lock_irqsave(&cdev->lock, flags); + if (cdev->config) + reset_config(cdev); + if (composite->disconnect) + composite->disconnect(cdev); + spin_unlock_irqrestore(&cdev->lock, flags); +} + +/*-------------------------------------------------------------------------*/ + +static ssize_t composite_show_suspended(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct usb_gadget *gadget = dev_to_usb_gadget(dev); + struct usb_composite_dev *cdev = get_gadget_data(gadget); + + return sprintf(buf, "%d\n", cdev->suspended); +} + +static DEVICE_ATTR(suspended, 0444, composite_show_suspended, NULL); + +static void +composite_unbind(struct usb_gadget *gadget) +{ + struct usb_composite_dev *cdev = get_gadget_data(gadget); + + /* composite_disconnect() must already have been called + * by the underlying peripheral controller driver! + * so there's no i/o concurrency that could affect the + * state protected by cdev->lock. + */ + WARN_ON(cdev->config); + + while (!list_empty(&cdev->configs)) { + struct usb_configuration *c; + c = list_first_entry(&cdev->configs, + struct usb_configuration, list); + remove_config(cdev, c); + } + if (composite->unbind) + composite->unbind(cdev); + + if (cdev->req) { + kfree(cdev->req->buf); + usb_ep_free_request(gadget->ep0, cdev->req); + } + device_remove_file(&gadget->dev, &dev_attr_suspended); + kfree(cdev); + set_gadget_data(gadget, NULL); + composite = NULL; +} + +static u8 override_id(struct usb_composite_dev *cdev, u8 *desc) +{ + if (!*desc) { + int ret = usb_string_id(cdev); + if (unlikely(ret < 0)) + WARNING(cdev, "failed to override string ID\n"); + else + *desc = ret; + } + + return *desc; +} + +static int composite_bind(struct usb_gadget *gadget) +{ + struct usb_composite_dev *cdev; + int status = -ENOMEM; + + cdev = kzalloc(sizeof *cdev, GFP_KERNEL); + if (!cdev) + return status; + + spin_lock_init(&cdev->lock); + cdev->gadget = gadget; + set_gadget_data(gadget, cdev); + INIT_LIST_HEAD(&cdev->configs); + + /* preallocate control response and buffer */ + cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL); + if (!cdev->req) + goto fail; + cdev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL); + if (!cdev->req->buf) + goto fail; + cdev->req->complete = composite_setup_complete; + gadget->ep0->driver_data = cdev; + + cdev->bufsiz = USB_BUFSIZ; + cdev->driver = composite; + + /* + * As per USB compliance update, a device that is actively drawing + * more than 100mA from USB must report itself as bus-powered in + * the GetStatus(DEVICE) call. + */ + if (CONFIG_USB_GADGET_VBUS_DRAW <= USB_SELF_POWER_VBUS_MAX_DRAW) + usb_gadget_set_selfpowered(gadget); + + /* interface and string IDs start at zero via kzalloc. + * we force endpoints to start unassigned; few controller + * drivers will zero ep->driver_data. + */ + usb_ep_autoconfig_reset(cdev->gadget); + + /* composite gadget needs to assign strings for whole device (like + * serial number), register function drivers, potentially update + * power state and consumption, etc + */ + status = composite->bind(cdev); + if (status < 0) + goto fail; + + cdev->desc = *composite->dev; + + /* standardized runtime overrides for device ID data */ + if (idVendor) + cdev->desc.idVendor = cpu_to_le16(idVendor); + else + idVendor = le16_to_cpu(cdev->desc.idVendor); + if (idProduct) + cdev->desc.idProduct = cpu_to_le16(idProduct); + else + idProduct = le16_to_cpu(cdev->desc.idProduct); + if (bcdDevice) + cdev->desc.bcdDevice = cpu_to_le16(bcdDevice); + else + bcdDevice = le16_to_cpu(cdev->desc.bcdDevice); + + /* string overrides */ + if (iManufacturer || !cdev->desc.iManufacturer) { + if (!iManufacturer && !composite->iManufacturer && + !*composite_manufacturer) + snprintf(composite_manufacturer, + sizeof composite_manufacturer, + "%s %s with %s", + init_utsname()->sysname, + init_utsname()->release, + gadget->name); + + cdev->manufacturer_override = + override_id(cdev, &cdev->desc.iManufacturer); + } + + if (iProduct || (!cdev->desc.iProduct && composite->iProduct)) + cdev->product_override = + override_id(cdev, &cdev->desc.iProduct); + + if (iSerialNumber || + (!cdev->desc.iSerialNumber && composite->iSerialNumber)) + cdev->serial_override = + override_id(cdev, &cdev->desc.iSerialNumber); + + /* has userspace failed to provide a serial number? */ + if (composite->needs_serial && !cdev->desc.iSerialNumber) + WARNING(cdev, "userspace failed to provide iSerialNumber\n"); + + /* finish up */ + status = device_create_file(&gadget->dev, &dev_attr_suspended); + if (status) + goto fail; + + INFO(cdev, "%s ready\n", composite->name); + return 0; + +fail: + composite_unbind(gadget); + return status; +} + +/*-------------------------------------------------------------------------*/ + +static void +composite_suspend(struct usb_gadget *gadget) +{ + struct usb_composite_dev *cdev = get_gadget_data(gadget); + struct usb_function *f; + + /* REVISIT: should we have config level + * suspend/resume callbacks? + */ + DBG(cdev, "suspend\n"); + if (cdev->config) { + list_for_each_entry(f, &cdev->config->functions, list) { + if (f->suspend) + f->suspend(f); + } + } + if (composite->suspend) + composite->suspend(cdev); + + cdev->suspended = 1; + + usb_gadget_vbus_draw(gadget, 2); +} + +static void +composite_resume(struct usb_gadget *gadget) +{ + struct usb_composite_dev *cdev = get_gadget_data(gadget); + struct usb_function *f; + u8 maxpower; + + /* REVISIT: should we have config level + * suspend/resume callbacks? + */ + DBG(cdev, "resume\n"); + if (composite->resume) + composite->resume(cdev); + if (cdev->config) { + list_for_each_entry(f, &cdev->config->functions, list) { + if (f->resume) + f->resume(f); + } + + maxpower = cdev->config->bMaxPower; + + usb_gadget_vbus_draw(gadget, maxpower ? + (2 * maxpower) : CONFIG_USB_GADGET_VBUS_DRAW); + } + + cdev->suspended = 0; +} + +/*-------------------------------------------------------------------------*/ + +static struct usb_gadget_driver composite_driver = { + .bind = composite_bind, + .unbind = composite_unbind, + + .setup = composite_setup, + .disconnect = composite_disconnect, + + .suspend = composite_suspend, + .resume = composite_resume, + + .driver = { + .owner = THIS_MODULE, + }, +}; + +/** + * usb_composite_probe() - register a composite driver + * @driver: the driver to register + * @bind: the callback used to allocate resources that are shared across the + * whole device, such as string IDs, and add its configurations using + * @usb_add_config(). This may fail by returning a negative errno + * value; it should return zero on successful initialization. + * Context: single threaded during gadget setup + * + * This function is used to register drivers using the composite driver + * framework. The return value is zero, or a negative errno value. + * Those values normally come from the driver's @bind method, which does + * all the work of setting up the driver to match the hardware. + * + * On successful return, the gadget is ready to respond to requests from + * the host, unless one of its components invokes usb_gadget_disconnect() + * while it was binding. That would usually be done in order to wait for + * some userspace participation. + */ +int usb_composite_probe(struct usb_composite_driver *driver) +{ + if (!driver || !driver->dev || composite || !driver->bind) + return -EINVAL; + + if (!driver->name) + driver->name = "composite"; + if (!driver->iProduct) + driver->iProduct = driver->name; + composite_driver.function = (char *) driver->name; + composite_driver.driver.name = driver->name; + composite_driver.max_speed = driver->max_speed; + composite = driver; + + return usb_gadget_probe_driver(&composite_driver); +} + +/** + * usb_composite_unregister() - unregister a composite driver + * @driver: the driver to unregister + * + * This function is used to unregister drivers using the composite + * driver framework. + */ +void usb_composite_unregister(struct usb_composite_driver *driver) +{ + if (composite != driver) + return; + usb_gadget_unregister_driver(&composite_driver); +} + +/** + * usb_composite_setup_continue() - Continue with the control transfer + * @cdev: the composite device who's control transfer was kept waiting + * + * This function must be called by the USB function driver to continue + * with the control transfer's data/status stage in case it had requested to + * delay the data/status stages. A USB function's setup handler (e.g. set_alt()) + * can request the composite framework to delay the setup request's data/status + * stages by returning USB_GADGET_DELAYED_STATUS. + */ +void usb_composite_setup_continue(struct usb_composite_dev *cdev) +{ + int value; + struct usb_request *req = cdev->req; + unsigned long flags; + + DBG(cdev, "%s\n", __func__); + spin_lock_irqsave(&cdev->lock, flags); + + if (cdev->delayed_status == 0) { + WARN(cdev, "%s: Unexpected call\n", __func__); + + } else if (--cdev->delayed_status == 0) { + DBG(cdev, "%s: Completing delayed status\n", __func__); + req->length = 0; + value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); + if (value < 0) { + DBG(cdev, "ep_queue --> %d\n", value); + req->status = 0; + composite_setup_complete(cdev->gadget->ep0, req); + } + } + + spin_unlock_irqrestore(&cdev->lock, flags); +} + diff --git a/drivers/staging/ccg/composite.h b/drivers/staging/ccg/composite.h new file mode 100644 index 0000000..19a5adf --- /dev/null +++ b/drivers/staging/ccg/composite.h @@ -0,0 +1,395 @@ +/* + * composite.h -- framework for usb gadgets which are composite devices + * + * Copyright (C) 2006-2008 David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __LINUX_USB_COMPOSITE_H +#define __LINUX_USB_COMPOSITE_H + +/* + * This framework is an optional layer on top of the USB Gadget interface, + * making it easier to build (a) Composite devices, supporting multiple + * functions within any single configuration, and (b) Multi-configuration + * devices, also supporting multiple functions but without necessarily + * having more than one function per configuration. + * + * Example: a device with a single configuration supporting both network + * link and mass storage functions is a composite device. Those functions + * might alternatively be packaged in individual configurations, but in + * the composite model the host can use both functions at the same time. + */ + +#include +#include + +/* + * USB function drivers should return USB_GADGET_DELAYED_STATUS if they + * wish to delay the data/status stages of the control transfer till they + * are ready. The control transfer will then be kept from completing till + * all the function drivers that requested for USB_GADGET_DELAYED_STAUS + * invoke usb_composite_setup_continue(). + */ +#define USB_GADGET_DELAYED_STATUS 0x7fff /* Impossibly large value */ + +struct usb_configuration; + +/** + * struct usb_function - describes one function of a configuration + * @name: For diagnostics, identifies the function. + * @strings: tables of strings, keyed by identifiers assigned during bind() + * and by language IDs provided in control requests + * @descriptors: Table of full (or low) speed descriptors, using interface and + * string identifiers assigned during @bind(). If this pointer is null, + * the function will not be available at full speed (or at low speed). + * @hs_descriptors: Table of high speed descriptors, using interface and + * string identifiers assigned during @bind(). If this pointer is null, + * the function will not be available at high speed. + * @ss_descriptors: Table of super speed descriptors, using interface and + * string identifiers assigned during @bind(). If this + * pointer is null after initiation, the function will not + * be available at super speed. + * @config: assigned when @usb_add_function() is called; this is the + * configuration with which this function is associated. + * @bind: Before the gadget can register, all of its functions bind() to the + * available resources including string and interface identifiers used + * in interface or class descriptors; endpoints; I/O buffers; and so on. + * @unbind: Reverses @bind; called as a side effect of unregistering the + * driver which added this function. + * @set_alt: (REQUIRED) Reconfigures altsettings; function drivers may + * initialize usb_ep.driver data at this time (when it is used). + * Note that setting an interface to its current altsetting resets + * interface state, and that all interfaces have a disabled state. + * @get_alt: Returns the active altsetting. If this is not provided, + * then only altsetting zero is supported. + * @disable: (REQUIRED) Indicates the function should be disabled. Reasons + * include host resetting or reconfiguring the gadget, and disconnection. + * @setup: Used for interface-specific control requests. + * @suspend: Notifies functions when the host stops sending USB traffic. + * @resume: Notifies functions when the host restarts USB traffic. + * @get_status: Returns function status as a reply to + * GetStatus() request when the recepient is Interface. + * @func_suspend: callback to be called when + * SetFeature(FUNCTION_SUSPEND) is reseived + * + * A single USB function uses one or more interfaces, and should in most + * cases support operation at both full and high speeds. Each function is + * associated by @usb_add_function() with a one configuration; that function + * causes @bind() to be called so resources can be allocated as part of + * setting up a gadget driver. Those resources include endpoints, which + * should be allocated using @usb_ep_autoconfig(). + * + * To support dual speed operation, a function driver provides descriptors + * for both high and full speed operation. Except in rare cases that don't + * involve bulk endpoints, each speed needs different endpoint descriptors. + * + * Function drivers choose their own strategies for managing instance data. + * The simplest strategy just declares it "static', which means the function + * can only be activated once. If the function needs to be exposed in more + * than one configuration at a given speed, it needs to support multiple + * usb_function structures (one for each configuration). + * + * A more complex strategy might encapsulate a @usb_function structure inside + * a driver-specific instance structure to allows multiple activations. An + * example of multiple activations might be a CDC ACM function that supports + * two or more distinct instances within the same configuration, providing + * several independent logical data links to a USB host. + */ +struct usb_function { + const char *name; + struct usb_gadget_strings **strings; + struct usb_descriptor_header **descriptors; + struct usb_descriptor_header **hs_descriptors; + struct usb_descriptor_header **ss_descriptors; + + struct usb_configuration *config; + + /* REVISIT: bind() functions can be marked __init, which + * makes trouble for section mismatch analysis. See if + * we can't restructure things to avoid mismatching. + * Related: unbind() may kfree() but bind() won't... + */ + + /* configuration management: bind/unbind */ + int (*bind)(struct usb_configuration *, + struct usb_function *); + void (*unbind)(struct usb_configuration *, + struct usb_function *); + + /* runtime state management */ + int (*set_alt)(struct usb_function *, + unsigned interface, unsigned alt); + int (*get_alt)(struct usb_function *, + unsigned interface); + void (*disable)(struct usb_function *); + int (*setup)(struct usb_function *, + const struct usb_ctrlrequest *); + void (*suspend)(struct usb_function *); + void (*resume)(struct usb_function *); + + /* USB 3.0 additions */ + int (*get_status)(struct usb_function *); + int (*func_suspend)(struct usb_function *, + u8 suspend_opt); + /* private: */ + /* internals */ + struct list_head list; + DECLARE_BITMAP(endpoints, 32); +}; + +int usb_add_function(struct usb_configuration *, struct usb_function *); + +int usb_function_deactivate(struct usb_function *); +int usb_function_activate(struct usb_function *); + +int usb_interface_id(struct usb_configuration *, struct usb_function *); + +int config_ep_by_speed(struct usb_gadget *g, struct usb_function *f, + struct usb_ep *_ep); + +#define MAX_CONFIG_INTERFACES 16 /* arbitrary; max 255 */ + +/** + * struct usb_configuration - represents one gadget configuration + * @label: For diagnostics, describes the configuration. + * @strings: Tables of strings, keyed by identifiers assigned during @bind() + * and by language IDs provided in control requests. + * @descriptors: Table of descriptors preceding all function descriptors. + * Examples include OTG and vendor-specific descriptors. + * @unbind: Reverses @bind; called as a side effect of unregistering the + * driver which added this configuration. + * @setup: Used to delegate control requests that aren't handled by standard + * device infrastructure or directed at a specific interface. + * @bConfigurationValue: Copied into configuration descriptor. + * @iConfiguration: Copied into configuration descriptor. + * @bmAttributes: Copied into configuration descriptor. + * @bMaxPower: Copied into configuration descriptor. + * @cdev: assigned by @usb_add_config() before calling @bind(); this is + * the device associated with this configuration. + * + * Configurations are building blocks for gadget drivers structured around + * function drivers. Simple USB gadgets require only one function and one + * configuration, and handle dual-speed hardware by always providing the same + * functionality. Slightly more complex gadgets may have more than one + * single-function configuration at a given speed; or have configurations + * that only work at one speed. + * + * Composite devices are, by definition, ones with configurations which + * include more than one function. + * + * The lifecycle of a usb_configuration includes allocation, initialization + * of the fields described above, and calling @usb_add_config() to set up + * internal data and bind it to a specific device. The configuration's + * @bind() method is then used to initialize all the functions and then + * call @usb_add_function() for them. + * + * Those functions would normally be independent of each other, but that's + * not mandatory. CDC WMC devices are an example where functions often + * depend on other functions, with some functions subsidiary to others. + * Such interdependency may be managed in any way, so long as all of the + * descriptors complete by the time the composite driver returns from + * its bind() routine. + */ +struct usb_configuration { + const char *label; + struct usb_gadget_strings **strings; + const struct usb_descriptor_header **descriptors; + + /* REVISIT: bind() functions can be marked __init, which + * makes trouble for section mismatch analysis. See if + * we can't restructure things to avoid mismatching... + */ + + /* configuration management: unbind/setup */ + void (*unbind)(struct usb_configuration *); + int (*setup)(struct usb_configuration *, + const struct usb_ctrlrequest *); + + /* fields in the config descriptor */ + u8 bConfigurationValue; + u8 iConfiguration; + u8 bmAttributes; + u8 bMaxPower; + + struct usb_composite_dev *cdev; + + /* private: */ + /* internals */ + struct list_head list; + struct list_head functions; + u8 next_interface_id; + unsigned superspeed:1; + unsigned highspeed:1; + unsigned fullspeed:1; + struct usb_function *interface[MAX_CONFIG_INTERFACES]; +}; + +int usb_add_config(struct usb_composite_dev *, + struct usb_configuration *, + int (*)(struct usb_configuration *)); + +void usb_remove_config(struct usb_composite_dev *, + struct usb_configuration *); + +/** + * struct usb_composite_driver - groups configurations into a gadget + * @name: For diagnostics, identifies the driver. + * @iProduct: Used as iProduct override if @dev->iProduct is not set. + * If NULL value of @name is taken. + * @iManufacturer: Used as iManufacturer override if @dev->iManufacturer is + * not set. If NULL a default " with " value + * will be used. + * @iSerialNumber: Used as iSerialNumber override if @dev->iSerialNumber is + * not set. + * @dev: Template descriptor for the device, including default device + * identifiers. + * @strings: tables of strings, keyed by identifiers assigned during @bind + * and language IDs provided in control requests + * @max_speed: Highest speed the driver supports. + * @needs_serial: set to 1 if the gadget needs userspace to provide + * a serial number. If one is not provided, warning will be printed. + * @bind: (REQUIRED) Used to allocate resources that are shared across the + * whole device, such as string IDs, and add its configurations using + * @usb_add_config(). This may fail by returning a negative errno + * value; it should return zero on successful initialization. + * @unbind: Reverses @bind; called as a side effect of unregistering + * this driver. + * @disconnect: optional driver disconnect method + * @suspend: Notifies when the host stops sending USB traffic, + * after function notifications + * @resume: Notifies configuration when the host restarts USB traffic, + * before function notifications + * + * Devices default to reporting self powered operation. Devices which rely + * on bus powered operation should report this in their @bind method. + * + * Before returning from @bind, various fields in the template descriptor + * may be overridden. These include the idVendor/idProduct/bcdDevice values + * normally to bind the appropriate host side driver, and the three strings + * (iManufacturer, iProduct, iSerialNumber) normally used to provide user + * meaningful device identifiers. (The strings will not be defined unless + * they are defined in @dev and @strings.) The correct ep0 maxpacket size + * is also reported, as defined by the underlying controller driver. + */ +struct usb_composite_driver { + const char *name; + const char *iProduct; + const char *iManufacturer; + const char *iSerialNumber; + const struct usb_device_descriptor *dev; + struct usb_gadget_strings **strings; + enum usb_device_speed max_speed; + unsigned needs_serial:1; + + int (*bind)(struct usb_composite_dev *cdev); + int (*unbind)(struct usb_composite_dev *); + + void (*disconnect)(struct usb_composite_dev *); + + /* global suspend hooks */ + void (*suspend)(struct usb_composite_dev *); + void (*resume)(struct usb_composite_dev *); +}; + +extern int usb_composite_probe(struct usb_composite_driver *driver); +extern void usb_composite_unregister(struct usb_composite_driver *driver); +extern void usb_composite_setup_continue(struct usb_composite_dev *cdev); + + +/** + * struct usb_composite_device - represents one composite usb gadget + * @gadget: read-only, abstracts the gadget's usb peripheral controller + * @req: used for control responses; buffer is pre-allocated + * @bufsiz: size of buffer pre-allocated in @req + * @config: the currently active configuration + * + * One of these devices is allocated and initialized before the + * associated device driver's bind() is called. + * + * OPEN ISSUE: it appears that some WUSB devices will need to be + * built by combining a normal (wired) gadget with a wireless one. + * This revision of the gadget framework should probably try to make + * sure doing that won't hurt too much. + * + * One notion for how to handle Wireless USB devices involves: + * (a) a second gadget here, discovery mechanism TBD, but likely + * needing separate "register/unregister WUSB gadget" calls; + * (b) updates to usb_gadget to include flags "is it wireless", + * "is it wired", plus (presumably in a wrapper structure) + * bandgroup and PHY info; + * (c) presumably a wireless_ep wrapping a usb_ep, and reporting + * wireless-specific parameters like maxburst and maxsequence; + * (d) configurations that are specific to wireless links; + * (e) function drivers that understand wireless configs and will + * support wireless for (additional) function instances; + * (f) a function to support association setup (like CBAF), not + * necessarily requiring a wireless adapter; + * (g) composite device setup that can create one or more wireless + * configs, including appropriate association setup support; + * (h) more, TBD. + */ +struct usb_composite_dev { + struct usb_gadget *gadget; + struct usb_request *req; + unsigned bufsiz; + + struct usb_configuration *config; + + /* private: */ + /* internals */ + unsigned int suspended:1; + struct usb_device_descriptor desc; + struct list_head configs; + struct usb_composite_driver *driver; + u8 next_string_id; + u8 manufacturer_override; + u8 product_override; + u8 serial_override; + + /* the gadget driver won't enable the data pullup + * while the deactivation count is nonzero. + */ + unsigned deactivations; + + /* the composite driver won't complete the control transfer's + * data/status stages till delayed_status is zero. + */ + int delayed_status; + + /* protects deactivations and delayed_status counts*/ + spinlock_t lock; +}; + +extern int usb_string_id(struct usb_composite_dev *c); +extern int usb_string_ids_tab(struct usb_composite_dev *c, + struct usb_string *str); +extern int usb_string_ids_n(struct usb_composite_dev *c, unsigned n); + + +/* messaging utils */ +#define DBG(d, fmt, args...) \ + dev_dbg(&(d)->gadget->dev , fmt , ## args) +#define VDBG(d, fmt, args...) \ + dev_vdbg(&(d)->gadget->dev , fmt , ## args) +#define ERROR(d, fmt, args...) \ + dev_err(&(d)->gadget->dev , fmt , ## args) +#define WARNING(d, fmt, args...) \ + dev_warn(&(d)->gadget->dev , fmt , ## args) +#define INFO(d, fmt, args...) \ + dev_info(&(d)->gadget->dev , fmt , ## args) + +#endif /* __LINUX_USB_COMPOSITE_H */ diff --git a/drivers/staging/ccg/config.c b/drivers/staging/ccg/config.c new file mode 100644 index 0000000..7542a72 --- /dev/null +++ b/drivers/staging/ccg/config.c @@ -0,0 +1,158 @@ +/* + * usb/gadget/config.c -- simplify building config descriptors + * + * Copyright (C) 2003 David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + + +/** + * usb_descriptor_fillbuf - fill buffer with descriptors + * @buf: Buffer to be filled + * @buflen: Size of buf + * @src: Array of descriptor pointers, terminated by null pointer. + * + * Copies descriptors into the buffer, returning the length or a + * negative error code if they can't all be copied. Useful when + * assembling descriptors for an associated set of interfaces used + * as part of configuring a composite device; or in other cases where + * sets of descriptors need to be marshaled. + */ +int +usb_descriptor_fillbuf(void *buf, unsigned buflen, + const struct usb_descriptor_header **src) +{ + u8 *dest = buf; + + if (!src) + return -EINVAL; + + /* fill buffer from src[] until null descriptor ptr */ + for (; NULL != *src; src++) { + unsigned len = (*src)->bLength; + + if (len > buflen) + return -EINVAL; + memcpy(dest, *src, len); + buflen -= len; + dest += len; + } + return dest - (u8 *)buf; +} + + +/** + * usb_gadget_config_buf - builts a complete configuration descriptor + * @config: Header for the descriptor, including characteristics such + * as power requirements and number of interfaces. + * @desc: Null-terminated vector of pointers to the descriptors (interface, + * endpoint, etc) defining all functions in this device configuration. + * @buf: Buffer for the resulting configuration descriptor. + * @length: Length of buffer. If this is not big enough to hold the + * entire configuration descriptor, an error code will be returned. + * + * This copies descriptors into the response buffer, building a descriptor + * for that configuration. It returns the buffer length or a negative + * status code. The config.wTotalLength field is set to match the length + * of the result, but other descriptor fields (including power usage and + * interface count) must be set by the caller. + * + * Gadget drivers could use this when constructing a config descriptor + * in response to USB_REQ_GET_DESCRIPTOR. They will need to patch the + * resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed. + */ +int usb_gadget_config_buf( + const struct usb_config_descriptor *config, + void *buf, + unsigned length, + const struct usb_descriptor_header **desc +) +{ + struct usb_config_descriptor *cp = buf; + int len; + + /* config descriptor first */ + if (length < USB_DT_CONFIG_SIZE || !desc) + return -EINVAL; + *cp = *config; + + /* then interface/endpoint/class/vendor/... */ + len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf, + length - USB_DT_CONFIG_SIZE, desc); + if (len < 0) + return len; + len += USB_DT_CONFIG_SIZE; + if (len > 0xffff) + return -EINVAL; + + /* patch up the config descriptor */ + cp->bLength = USB_DT_CONFIG_SIZE; + cp->bDescriptorType = USB_DT_CONFIG; + cp->wTotalLength = cpu_to_le16(len); + cp->bmAttributes |= USB_CONFIG_ATT_ONE; + return len; +} + +/** + * usb_copy_descriptors - copy a vector of USB descriptors + * @src: null-terminated vector to copy + * Context: initialization code, which may sleep + * + * This makes a copy of a vector of USB descriptors. Its primary use + * is to support usb_function objects which can have multiple copies, + * each needing different descriptors. Functions may have static + * tables of descriptors, which are used as templates and customized + * with identifiers (for interfaces, strings, endpoints, and more) + * as needed by a given function instance. + */ +struct usb_descriptor_header ** +usb_copy_descriptors(struct usb_descriptor_header **src) +{ + struct usb_descriptor_header **tmp; + unsigned bytes; + unsigned n_desc; + void *mem; + struct usb_descriptor_header **ret; + + /* count descriptors and their sizes; then add vector size */ + for (bytes = 0, n_desc = 0, tmp = src; *tmp; tmp++, n_desc++) + bytes += (*tmp)->bLength; + bytes += (n_desc + 1) * sizeof(*tmp); + + mem = kmalloc(bytes, GFP_KERNEL); + if (!mem) + return NULL; + + /* fill in pointers starting at "tmp", + * to descriptors copied starting at "mem"; + * and return "ret" + */ + tmp = mem; + ret = mem; + mem += (n_desc + 1) * sizeof(*tmp); + while (*src) { + memcpy(mem, *src, (*src)->bLength); + *tmp = mem; + tmp++; + mem += (*src)->bLength; + src++; + } + *tmp = NULL; + + return ret; +} + diff --git a/drivers/staging/ccg/epautoconf.c b/drivers/staging/ccg/epautoconf.c new file mode 100644 index 0000000..51f3d42 --- /dev/null +++ b/drivers/staging/ccg/epautoconf.c @@ -0,0 +1,393 @@ +/* + * epautoconf.c -- endpoint autoconfiguration for usb gadget drivers + * + * Copyright (C) 2004 David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include "gadget_chips.h" + + +/* we must assign addresses for configurable endpoints (like net2280) */ +static unsigned epnum; + +// #define MANY_ENDPOINTS +#ifdef MANY_ENDPOINTS +/* more than 15 configurable endpoints */ +static unsigned in_epnum; +#endif + + +/* + * This should work with endpoints from controller drivers sharing the + * same endpoint naming convention. By example: + * + * - ep1, ep2, ... address is fixed, not direction or type + * - ep1in, ep2out, ... address and direction are fixed, not type + * - ep1-bulk, ep2-bulk, ... address and type are fixed, not direction + * - ep1in-bulk, ep2out-iso, ... all three are fixed + * - ep-* ... no functionality restrictions + * + * Type suffixes are "-bulk", "-iso", or "-int". Numbers are decimal. + * Less common restrictions are implied by gadget_is_*(). + * + * NOTE: each endpoint is unidirectional, as specified by its USB + * descriptor; and isn't specific to a configuration or altsetting. + */ +static int +ep_matches ( + struct usb_gadget *gadget, + struct usb_ep *ep, + struct usb_endpoint_descriptor *desc, + struct usb_ss_ep_comp_descriptor *ep_comp +) +{ + u8 type; + const char *tmp; + u16 max; + + int num_req_streams = 0; + + /* endpoint already claimed? */ + if (NULL != ep->driver_data) + return 0; + + /* only support ep0 for portable CONTROL traffic */ + type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + if (USB_ENDPOINT_XFER_CONTROL == type) + return 0; + + /* some other naming convention */ + if ('e' != ep->name[0]) + return 0; + + /* type-restriction: "-iso", "-bulk", or "-int". + * direction-restriction: "in", "out". + */ + if ('-' != ep->name[2]) { + tmp = strrchr (ep->name, '-'); + if (tmp) { + switch (type) { + case USB_ENDPOINT_XFER_INT: + /* bulk endpoints handle interrupt transfers, + * except the toggle-quirky iso-synch kind + */ + if ('s' == tmp[2]) // == "-iso" + return 0; + /* for now, avoid PXA "interrupt-in"; + * it's documented as never using DATA1. + */ + if (gadget_is_pxa (gadget) + && 'i' == tmp [1]) + return 0; + break; + case USB_ENDPOINT_XFER_BULK: + if ('b' != tmp[1]) // != "-bulk" + return 0; + break; + case USB_ENDPOINT_XFER_ISOC: + if ('s' != tmp[2]) // != "-iso" + return 0; + } + } else { + tmp = ep->name + strlen (ep->name); + } + + /* direction-restriction: "..in-..", "out-.." */ + tmp--; + if (!isdigit (*tmp)) { + if (desc->bEndpointAddress & USB_DIR_IN) { + if ('n' != *tmp) + return 0; + } else { + if ('t' != *tmp) + return 0; + } + } + } + + /* + * Get the number of required streams from the EP companion + * descriptor and see if the EP matches it + */ + if (usb_endpoint_xfer_bulk(desc)) { + if (ep_comp && gadget->max_speed >= USB_SPEED_SUPER) { + num_req_streams = ep_comp->bmAttributes & 0x1f; + if (num_req_streams > ep->max_streams) + return 0; + } + + } + + /* + * If the protocol driver hasn't yet decided on wMaxPacketSize + * and wants to know the maximum possible, provide the info. + */ + if (desc->wMaxPacketSize == 0) + desc->wMaxPacketSize = cpu_to_le16(ep->maxpacket); + + /* endpoint maxpacket size is an input parameter, except for bulk + * where it's an output parameter representing the full speed limit. + * the usb spec fixes high speed bulk maxpacket at 512 bytes. + */ + max = 0x7ff & usb_endpoint_maxp(desc); + switch (type) { + case USB_ENDPOINT_XFER_INT: + /* INT: limit 64 bytes full speed, 1024 high/super speed */ + if (!gadget_is_dualspeed(gadget) && max > 64) + return 0; + /* FALLTHROUGH */ + + case USB_ENDPOINT_XFER_ISOC: + /* ISO: limit 1023 bytes full speed, 1024 high/super speed */ + if (ep->maxpacket < max) + return 0; + if (!gadget_is_dualspeed(gadget) && max > 1023) + return 0; + + /* BOTH: "high bandwidth" works only at high speed */ + if ((desc->wMaxPacketSize & cpu_to_le16(3<<11))) { + if (!gadget_is_dualspeed(gadget)) + return 0; + /* configure your hardware with enough buffering!! */ + } + break; + } + + /* MATCH!! */ + + /* report address */ + desc->bEndpointAddress &= USB_DIR_IN; + if (isdigit (ep->name [2])) { + u8 num = simple_strtoul (&ep->name [2], NULL, 10); + desc->bEndpointAddress |= num; +#ifdef MANY_ENDPOINTS + } else if (desc->bEndpointAddress & USB_DIR_IN) { + if (++in_epnum > 15) + return 0; + desc->bEndpointAddress = USB_DIR_IN | in_epnum; +#endif + } else { + if (++epnum > 15) + return 0; + desc->bEndpointAddress |= epnum; + } + + /* report (variable) full speed bulk maxpacket */ + if ((USB_ENDPOINT_XFER_BULK == type) && !ep_comp) { + int size = ep->maxpacket; + + /* min() doesn't work on bitfields with gcc-3.5 */ + if (size > 64) + size = 64; + desc->wMaxPacketSize = cpu_to_le16(size); + } + ep->address = desc->bEndpointAddress; + return 1; +} + +static struct usb_ep * +find_ep (struct usb_gadget *gadget, const char *name) +{ + struct usb_ep *ep; + + list_for_each_entry (ep, &gadget->ep_list, ep_list) { + if (0 == strcmp (ep->name, name)) + return ep; + } + return NULL; +} + +/** + * usb_ep_autoconfig_ss() - choose an endpoint matching the ep + * descriptor and ep companion descriptor + * @gadget: The device to which the endpoint must belong. + * @desc: Endpoint descriptor, with endpoint direction and transfer mode + * initialized. For periodic transfers, the maximum packet + * size must also be initialized. This is modified on + * success. + * @ep_comp: Endpoint companion descriptor, with the required + * number of streams. Will be modified when the chosen EP + * supports a different number of streams. + * + * This routine replaces the usb_ep_autoconfig when needed + * superspeed enhancments. If such enhancemnets are required, + * the FD should call usb_ep_autoconfig_ss directly and provide + * the additional ep_comp parameter. + * + * By choosing an endpoint to use with the specified descriptor, + * this routine simplifies writing gadget drivers that work with + * multiple USB device controllers. The endpoint would be + * passed later to usb_ep_enable(), along with some descriptor. + * + * That second descriptor won't always be the same as the first one. + * For example, isochronous endpoints can be autoconfigured for high + * bandwidth, and then used in several lower bandwidth altsettings. + * Also, high and full speed descriptors will be different. + * + * Be sure to examine and test the results of autoconfiguration + * on your hardware. This code may not make the best choices + * about how to use the USB controller, and it can't know all + * the restrictions that may apply. Some combinations of driver + * and hardware won't be able to autoconfigure. + * + * On success, this returns an un-claimed usb_ep, and modifies the endpoint + * descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value + * is initialized as if the endpoint were used at full speed and + * the bmAttribute field in the ep companion descriptor is + * updated with the assigned number of streams if it is + * different from the original value. To prevent the endpoint + * from being returned by a later autoconfig call, claim it by + * assigning ep->driver_data to some non-null value. + * + * On failure, this returns a null endpoint descriptor. + */ +struct usb_ep *usb_ep_autoconfig_ss( + struct usb_gadget *gadget, + struct usb_endpoint_descriptor *desc, + struct usb_ss_ep_comp_descriptor *ep_comp +) +{ + struct usb_ep *ep; + u8 type; + + type = desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK; + + /* First, apply chip-specific "best usage" knowledge. + * This might make a good usb_gadget_ops hook ... + */ + if (gadget_is_net2280 (gadget) && type == USB_ENDPOINT_XFER_INT) { + /* ep-e, ep-f are PIO with only 64 byte fifos */ + ep = find_ep (gadget, "ep-e"); + if (ep && ep_matches(gadget, ep, desc, ep_comp)) + goto found_ep; + ep = find_ep (gadget, "ep-f"); + if (ep && ep_matches(gadget, ep, desc, ep_comp)) + goto found_ep; + + } else if (gadget_is_goku (gadget)) { + if (USB_ENDPOINT_XFER_INT == type) { + /* single buffering is enough */ + ep = find_ep(gadget, "ep3-bulk"); + if (ep && ep_matches(gadget, ep, desc, ep_comp)) + goto found_ep; + } else if (USB_ENDPOINT_XFER_BULK == type + && (USB_DIR_IN & desc->bEndpointAddress)) { + /* DMA may be available */ + ep = find_ep(gadget, "ep2-bulk"); + if (ep && ep_matches(gadget, ep, desc, + ep_comp)) + goto found_ep; + } + +#ifdef CONFIG_BLACKFIN + } else if (gadget_is_musbhdrc(gadget)) { + if ((USB_ENDPOINT_XFER_BULK == type) || + (USB_ENDPOINT_XFER_ISOC == type)) { + if (USB_DIR_IN & desc->bEndpointAddress) + ep = find_ep (gadget, "ep5in"); + else + ep = find_ep (gadget, "ep6out"); + } else if (USB_ENDPOINT_XFER_INT == type) { + if (USB_DIR_IN & desc->bEndpointAddress) + ep = find_ep(gadget, "ep1in"); + else + ep = find_ep(gadget, "ep2out"); + } else + ep = NULL; + if (ep && ep_matches(gadget, ep, desc, ep_comp)) + goto found_ep; +#endif + } + + /* Second, look at endpoints until an unclaimed one looks usable */ + list_for_each_entry (ep, &gadget->ep_list, ep_list) { + if (ep_matches(gadget, ep, desc, ep_comp)) + goto found_ep; + } + + /* Fail */ + return NULL; +found_ep: + ep->desc = NULL; + ep->comp_desc = NULL; + return ep; +} + +/** + * usb_ep_autoconfig() - choose an endpoint matching the + * descriptor + * @gadget: The device to which the endpoint must belong. + * @desc: Endpoint descriptor, with endpoint direction and transfer mode + * initialized. For periodic transfers, the maximum packet + * size must also be initialized. This is modified on success. + * + * By choosing an endpoint to use with the specified descriptor, this + * routine simplifies writing gadget drivers that work with multiple + * USB device controllers. The endpoint would be passed later to + * usb_ep_enable(), along with some descriptor. + * + * That second descriptor won't always be the same as the first one. + * For example, isochronous endpoints can be autoconfigured for high + * bandwidth, and then used in several lower bandwidth altsettings. + * Also, high and full speed descriptors will be different. + * + * Be sure to examine and test the results of autoconfiguration on your + * hardware. This code may not make the best choices about how to use the + * USB controller, and it can't know all the restrictions that may apply. + * Some combinations of driver and hardware won't be able to autoconfigure. + * + * On success, this returns an un-claimed usb_ep, and modifies the endpoint + * descriptor bEndpointAddress. For bulk endpoints, the wMaxPacket value + * is initialized as if the endpoint were used at full speed. To prevent + * the endpoint from being returned by a later autoconfig call, claim it + * by assigning ep->driver_data to some non-null value. + * + * On failure, this returns a null endpoint descriptor. + */ +struct usb_ep *usb_ep_autoconfig( + struct usb_gadget *gadget, + struct usb_endpoint_descriptor *desc +) +{ + return usb_ep_autoconfig_ss(gadget, desc, NULL); +} + + +/** + * usb_ep_autoconfig_reset - reset endpoint autoconfig state + * @gadget: device for which autoconfig state will be reset + * + * Use this for devices where one configuration may need to assign + * endpoint resources very differently from the next one. It clears + * state such as ep->driver_data and the record of assigned endpoints + * used by usb_ep_autoconfig(). + */ +void usb_ep_autoconfig_reset (struct usb_gadget *gadget) +{ + struct usb_ep *ep; + + list_for_each_entry (ep, &gadget->ep_list, ep_list) { + ep->driver_data = NULL; + } +#ifdef MANY_ENDPOINTS + in_epnum = 0; +#endif + epnum = 0; +} + diff --git a/drivers/staging/ccg/f_acm.c b/drivers/staging/ccg/f_acm.c new file mode 100644 index 0000000..d672250a --- /dev/null +++ b/drivers/staging/ccg/f_acm.c @@ -0,0 +1,814 @@ +/* + * f_acm.c -- USB CDC serial (ACM) function driver + * + * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com) + * Copyright (C) 2008 by David Brownell + * Copyright (C) 2008 by Nokia Corporation + * Copyright (C) 2009 by Samsung Electronics + * Author: Michal Nazarewicz (mina86@mina86.com) + * + * This software is distributed under the terms of the GNU General + * Public License ("GPL") as published by the Free Software Foundation, + * either version 2 of that License or (at your option) any later version. + */ + +/* #define VERBOSE_DEBUG */ + +#include +#include +#include + +#include "u_serial.h" +#include "gadget_chips.h" + + +/* + * This CDC ACM function support just wraps control functions and + * notifications around the generic serial-over-usb code. + * + * Because CDC ACM is standardized by the USB-IF, many host operating + * systems have drivers for it. Accordingly, ACM is the preferred + * interop solution for serial-port type connections. The control + * models are often not necessary, and in any case don't do much in + * this bare-bones implementation. + * + * Note that even MS-Windows has some support for ACM. However, that + * support is somewhat broken because when you use ACM in a composite + * device, having multiple interfaces confuses the poor OS. It doesn't + * seem to understand CDC Union descriptors. The new "association" + * descriptors (roughly equivalent to CDC Unions) may sometimes help. + */ + +struct f_acm { + struct gserial port; + u8 ctrl_id, data_id; + u8 port_num; + + u8 pending; + + /* lock is mostly for pending and notify_req ... they get accessed + * by callbacks both from tty (open/close/break) under its spinlock, + * and notify_req.complete() which can't use that lock. + */ + spinlock_t lock; + + struct usb_ep *notify; + struct usb_request *notify_req; + + struct usb_cdc_line_coding port_line_coding; /* 8-N-1 etc */ + + /* SetControlLineState request -- CDC 1.1 section 6.2.14 (INPUT) */ + u16 port_handshake_bits; +#define ACM_CTRL_RTS (1 << 1) /* unused with full duplex */ +#define ACM_CTRL_DTR (1 << 0) /* host is ready for data r/w */ + + /* SerialState notification -- CDC 1.1 section 6.3.5 (OUTPUT) */ + u16 serial_state; +#define ACM_CTRL_OVERRUN (1 << 6) +#define ACM_CTRL_PARITY (1 << 5) +#define ACM_CTRL_FRAMING (1 << 4) +#define ACM_CTRL_RI (1 << 3) +#define ACM_CTRL_BRK (1 << 2) +#define ACM_CTRL_DSR (1 << 1) +#define ACM_CTRL_DCD (1 << 0) +}; + +static inline struct f_acm *func_to_acm(struct usb_function *f) +{ + return container_of(f, struct f_acm, port.func); +} + +static inline struct f_acm *port_to_acm(struct gserial *p) +{ + return container_of(p, struct f_acm, port); +} + +/*-------------------------------------------------------------------------*/ + +/* notification endpoint uses smallish and infrequent fixed-size messages */ + +#define GS_LOG2_NOTIFY_INTERVAL 5 /* 1 << 5 == 32 msec */ +#define GS_NOTIFY_MAXPACKET 10 /* notification + 2 bytes */ + +/* interface and class descriptors: */ + +static struct usb_interface_assoc_descriptor +acm_iad_descriptor = { + .bLength = sizeof acm_iad_descriptor, + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + + /* .bFirstInterface = DYNAMIC, */ + .bInterfaceCount = 2, // control + data + .bFunctionClass = USB_CLASS_COMM, + .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, + .bFunctionProtocol = USB_CDC_ACM_PROTO_AT_V25TER, + /* .iFunction = DYNAMIC */ +}; + + +static struct usb_interface_descriptor acm_control_interface_desc = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + /* .bInterfaceNumber = DYNAMIC */ + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_COMM, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_ACM_PROTO_AT_V25TER, + /* .iInterface = DYNAMIC */ +}; + +static struct usb_interface_descriptor acm_data_interface_desc = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + /* .bInterfaceNumber = DYNAMIC */ + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_CDC_DATA, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + /* .iInterface = DYNAMIC */ +}; + +static struct usb_cdc_header_desc acm_header_desc = { + .bLength = sizeof(acm_header_desc), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_HEADER_TYPE, + .bcdCDC = cpu_to_le16(0x0110), +}; + +static struct usb_cdc_call_mgmt_descriptor +acm_call_mgmt_descriptor = { + .bLength = sizeof(acm_call_mgmt_descriptor), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE, + .bmCapabilities = 0, + /* .bDataInterface = DYNAMIC */ +}; + +static struct usb_cdc_acm_descriptor acm_descriptor = { + .bLength = sizeof(acm_descriptor), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_ACM_TYPE, + .bmCapabilities = USB_CDC_CAP_LINE, +}; + +static struct usb_cdc_union_desc acm_union_desc = { + .bLength = sizeof(acm_union_desc), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_UNION_TYPE, + /* .bMasterInterface0 = DYNAMIC */ + /* .bSlaveInterface0 = DYNAMIC */ +}; + +/* full speed support: */ + +static struct usb_endpoint_descriptor acm_fs_notify_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET), + .bInterval = 1 << GS_LOG2_NOTIFY_INTERVAL, +}; + +static struct usb_endpoint_descriptor acm_fs_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, +}; + +static struct usb_endpoint_descriptor acm_fs_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, +}; + +static struct usb_descriptor_header *acm_fs_function[] = { + (struct usb_descriptor_header *) &acm_iad_descriptor, + (struct usb_descriptor_header *) &acm_control_interface_desc, + (struct usb_descriptor_header *) &acm_header_desc, + (struct usb_descriptor_header *) &acm_call_mgmt_descriptor, + (struct usb_descriptor_header *) &acm_descriptor, + (struct usb_descriptor_header *) &acm_union_desc, + (struct usb_descriptor_header *) &acm_fs_notify_desc, + (struct usb_descriptor_header *) &acm_data_interface_desc, + (struct usb_descriptor_header *) &acm_fs_in_desc, + (struct usb_descriptor_header *) &acm_fs_out_desc, + NULL, +}; + +/* high speed support: */ + +static struct usb_endpoint_descriptor acm_hs_notify_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET), + .bInterval = GS_LOG2_NOTIFY_INTERVAL+4, +}; + +static struct usb_endpoint_descriptor acm_hs_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(512), +}; + +static struct usb_endpoint_descriptor acm_hs_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(512), +}; + +static struct usb_descriptor_header *acm_hs_function[] = { + (struct usb_descriptor_header *) &acm_iad_descriptor, + (struct usb_descriptor_header *) &acm_control_interface_desc, + (struct usb_descriptor_header *) &acm_header_desc, + (struct usb_descriptor_header *) &acm_call_mgmt_descriptor, + (struct usb_descriptor_header *) &acm_descriptor, + (struct usb_descriptor_header *) &acm_union_desc, + (struct usb_descriptor_header *) &acm_hs_notify_desc, + (struct usb_descriptor_header *) &acm_data_interface_desc, + (struct usb_descriptor_header *) &acm_hs_in_desc, + (struct usb_descriptor_header *) &acm_hs_out_desc, + NULL, +}; + +static struct usb_endpoint_descriptor acm_ss_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +static struct usb_endpoint_descriptor acm_ss_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +static struct usb_ss_ep_comp_descriptor acm_ss_bulk_comp_desc = { + .bLength = sizeof acm_ss_bulk_comp_desc, + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, +}; + +static struct usb_descriptor_header *acm_ss_function[] = { + (struct usb_descriptor_header *) &acm_iad_descriptor, + (struct usb_descriptor_header *) &acm_control_interface_desc, + (struct usb_descriptor_header *) &acm_header_desc, + (struct usb_descriptor_header *) &acm_call_mgmt_descriptor, + (struct usb_descriptor_header *) &acm_descriptor, + (struct usb_descriptor_header *) &acm_union_desc, + (struct usb_descriptor_header *) &acm_hs_notify_desc, + (struct usb_descriptor_header *) &acm_ss_bulk_comp_desc, + (struct usb_descriptor_header *) &acm_data_interface_desc, + (struct usb_descriptor_header *) &acm_ss_in_desc, + (struct usb_descriptor_header *) &acm_ss_bulk_comp_desc, + (struct usb_descriptor_header *) &acm_ss_out_desc, + (struct usb_descriptor_header *) &acm_ss_bulk_comp_desc, + NULL, +}; + +/* string descriptors: */ + +#define ACM_CTRL_IDX 0 +#define ACM_DATA_IDX 1 +#define ACM_IAD_IDX 2 + +/* static strings, in UTF-8 */ +static struct usb_string acm_string_defs[] = { + [ACM_CTRL_IDX].s = "CDC Abstract Control Model (ACM)", + [ACM_DATA_IDX].s = "CDC ACM Data", + [ACM_IAD_IDX ].s = "CDC Serial", + { /* ZEROES END LIST */ }, +}; + +static struct usb_gadget_strings acm_string_table = { + .language = 0x0409, /* en-us */ + .strings = acm_string_defs, +}; + +static struct usb_gadget_strings *acm_strings[] = { + &acm_string_table, + NULL, +}; + +/*-------------------------------------------------------------------------*/ + +/* ACM control ... data handling is delegated to tty library code. + * The main task of this function is to activate and deactivate + * that code based on device state; track parameters like line + * speed, handshake state, and so on; and issue notifications. + */ + +static void acm_complete_set_line_coding(struct usb_ep *ep, + struct usb_request *req) +{ + struct f_acm *acm = ep->driver_data; + struct usb_composite_dev *cdev = acm->port.func.config->cdev; + + if (req->status != 0) { + DBG(cdev, "acm ttyGS%d completion, err %d\n", + acm->port_num, req->status); + return; + } + + /* normal completion */ + if (req->actual != sizeof(acm->port_line_coding)) { + DBG(cdev, "acm ttyGS%d short resp, len %d\n", + acm->port_num, req->actual); + usb_ep_set_halt(ep); + } else { + struct usb_cdc_line_coding *value = req->buf; + + /* REVISIT: we currently just remember this data. + * If we change that, (a) validate it first, then + * (b) update whatever hardware needs updating, + * (c) worry about locking. This is information on + * the order of 9600-8-N-1 ... most of which means + * nothing unless we control a real RS232 line. + */ + acm->port_line_coding = *value; + } +} + +static int acm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) +{ + struct f_acm *acm = func_to_acm(f); + struct usb_composite_dev *cdev = f->config->cdev; + struct usb_request *req = cdev->req; + int value = -EOPNOTSUPP; + u16 w_index = le16_to_cpu(ctrl->wIndex); + u16 w_value = le16_to_cpu(ctrl->wValue); + u16 w_length = le16_to_cpu(ctrl->wLength); + + /* composite driver infrastructure handles everything except + * CDC class messages; interface activation uses set_alt(). + * + * Note CDC spec table 4 lists the ACM request profile. It requires + * encapsulated command support ... we don't handle any, and respond + * to them by stalling. Options include get/set/clear comm features + * (not that useful) and SEND_BREAK. + */ + switch ((ctrl->bRequestType << 8) | ctrl->bRequest) { + + /* SET_LINE_CODING ... just read and save what the host sends */ + case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) + | USB_CDC_REQ_SET_LINE_CODING: + if (w_length != sizeof(struct usb_cdc_line_coding) + || w_index != acm->ctrl_id) + goto invalid; + + value = w_length; + cdev->gadget->ep0->driver_data = acm; + req->complete = acm_complete_set_line_coding; + break; + + /* GET_LINE_CODING ... return what host sent, or initial value */ + case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) + | USB_CDC_REQ_GET_LINE_CODING: + if (w_index != acm->ctrl_id) + goto invalid; + + value = min_t(unsigned, w_length, + sizeof(struct usb_cdc_line_coding)); + memcpy(req->buf, &acm->port_line_coding, value); + break; + + /* SET_CONTROL_LINE_STATE ... save what the host sent */ + case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) + | USB_CDC_REQ_SET_CONTROL_LINE_STATE: + if (w_index != acm->ctrl_id) + goto invalid; + + value = 0; + + /* FIXME we should not allow data to flow until the + * host sets the ACM_CTRL_DTR bit; and when it clears + * that bit, we should return to that no-flow state. + */ + acm->port_handshake_bits = w_value; + break; + + default: +invalid: + VDBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n", + ctrl->bRequestType, ctrl->bRequest, + w_value, w_index, w_length); + } + + /* respond with data transfer or status phase? */ + if (value >= 0) { + DBG(cdev, "acm ttyGS%d req%02x.%02x v%04x i%04x l%d\n", + acm->port_num, ctrl->bRequestType, ctrl->bRequest, + w_value, w_index, w_length); + req->zero = 0; + req->length = value; + value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); + if (value < 0) + ERROR(cdev, "acm response on ttyGS%d, err %d\n", + acm->port_num, value); + } + + /* device either stalls (value < 0) or reports success */ + return value; +} + +static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt) +{ + struct f_acm *acm = func_to_acm(f); + struct usb_composite_dev *cdev = f->config->cdev; + + /* we know alt == 0, so this is an activation or a reset */ + + if (intf == acm->ctrl_id) { + if (acm->notify->driver_data) { + VDBG(cdev, "reset acm control interface %d\n", intf); + usb_ep_disable(acm->notify); + } else { + VDBG(cdev, "init acm ctrl interface %d\n", intf); + if (config_ep_by_speed(cdev->gadget, f, acm->notify)) + return -EINVAL; + } + usb_ep_enable(acm->notify); + acm->notify->driver_data = acm; + + } else if (intf == acm->data_id) { + if (acm->port.in->driver_data) { + DBG(cdev, "reset acm ttyGS%d\n", acm->port_num); + gserial_disconnect(&acm->port); + } + if (!acm->port.in->desc || !acm->port.out->desc) { + DBG(cdev, "activate acm ttyGS%d\n", acm->port_num); + if (config_ep_by_speed(cdev->gadget, f, + acm->port.in) || + config_ep_by_speed(cdev->gadget, f, + acm->port.out)) { + acm->port.in->desc = NULL; + acm->port.out->desc = NULL; + return -EINVAL; + } + } + gserial_connect(&acm->port, acm->port_num); + + } else + return -EINVAL; + + return 0; +} + +static void acm_disable(struct usb_function *f) +{ + struct f_acm *acm = func_to_acm(f); + struct usb_composite_dev *cdev = f->config->cdev; + + DBG(cdev, "acm ttyGS%d deactivated\n", acm->port_num); + gserial_disconnect(&acm->port); + usb_ep_disable(acm->notify); + acm->notify->driver_data = NULL; +} + +/*-------------------------------------------------------------------------*/ + +/** + * acm_cdc_notify - issue CDC notification to host + * @acm: wraps host to be notified + * @type: notification type + * @value: Refer to cdc specs, wValue field. + * @data: data to be sent + * @length: size of data + * Context: irqs blocked, acm->lock held, acm_notify_req non-null + * + * Returns zero on success or a negative errno. + * + * See section 6.3.5 of the CDC 1.1 specification for information + * about the only notification we issue: SerialState change. + */ +static int acm_cdc_notify(struct f_acm *acm, u8 type, u16 value, + void *data, unsigned length) +{ + struct usb_ep *ep = acm->notify; + struct usb_request *req; + struct usb_cdc_notification *notify; + const unsigned len = sizeof(*notify) + length; + void *buf; + int status; + + req = acm->notify_req; + acm->notify_req = NULL; + acm->pending = false; + + req->length = len; + notify = req->buf; + buf = notify + 1; + + notify->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS + | USB_RECIP_INTERFACE; + notify->bNotificationType = type; + notify->wValue = cpu_to_le16(value); + notify->wIndex = cpu_to_le16(acm->ctrl_id); + notify->wLength = cpu_to_le16(length); + memcpy(buf, data, length); + + /* ep_queue() can complete immediately if it fills the fifo... */ + spin_unlock(&acm->lock); + status = usb_ep_queue(ep, req, GFP_ATOMIC); + spin_lock(&acm->lock); + + if (status < 0) { + ERROR(acm->port.func.config->cdev, + "acm ttyGS%d can't notify serial state, %d\n", + acm->port_num, status); + acm->notify_req = req; + } + + return status; +} + +static int acm_notify_serial_state(struct f_acm *acm) +{ + struct usb_composite_dev *cdev = acm->port.func.config->cdev; + int status; + + spin_lock(&acm->lock); + if (acm->notify_req) { + DBG(cdev, "acm ttyGS%d serial state %04x\n", + acm->port_num, acm->serial_state); + status = acm_cdc_notify(acm, USB_CDC_NOTIFY_SERIAL_STATE, + 0, &acm->serial_state, sizeof(acm->serial_state)); + } else { + acm->pending = true; + status = 0; + } + spin_unlock(&acm->lock); + return status; +} + +static void acm_cdc_notify_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct f_acm *acm = req->context; + u8 doit = false; + + /* on this call path we do NOT hold the port spinlock, + * which is why ACM needs its own spinlock + */ + spin_lock(&acm->lock); + if (req->status != -ESHUTDOWN) + doit = acm->pending; + acm->notify_req = req; + spin_unlock(&acm->lock); + + if (doit) + acm_notify_serial_state(acm); +} + +/* connect == the TTY link is open */ + +static void acm_connect(struct gserial *port) +{ + struct f_acm *acm = port_to_acm(port); + + acm->serial_state |= ACM_CTRL_DSR | ACM_CTRL_DCD; + acm_notify_serial_state(acm); +} + +static void acm_disconnect(struct gserial *port) +{ + struct f_acm *acm = port_to_acm(port); + + acm->serial_state &= ~(ACM_CTRL_DSR | ACM_CTRL_DCD); + acm_notify_serial_state(acm); +} + +static int acm_send_break(struct gserial *port, int duration) +{ + struct f_acm *acm = port_to_acm(port); + u16 state; + + state = acm->serial_state; + state &= ~ACM_CTRL_BRK; + if (duration) + state |= ACM_CTRL_BRK; + + acm->serial_state = state; + return acm_notify_serial_state(acm); +} + +/*-------------------------------------------------------------------------*/ + +/* ACM function driver setup/binding */ +static int +acm_bind(struct usb_configuration *c, struct usb_function *f) +{ + struct usb_composite_dev *cdev = c->cdev; + struct f_acm *acm = func_to_acm(f); + int status; + struct usb_ep *ep; + + /* allocate instance-specific interface IDs, and patch descriptors */ + status = usb_interface_id(c, f); + if (status < 0) + goto fail; + acm->ctrl_id = status; + acm_iad_descriptor.bFirstInterface = status; + + acm_control_interface_desc.bInterfaceNumber = status; + acm_union_desc .bMasterInterface0 = status; + + status = usb_interface_id(c, f); + if (status < 0) + goto fail; + acm->data_id = status; + + acm_data_interface_desc.bInterfaceNumber = status; + acm_union_desc.bSlaveInterface0 = status; + acm_call_mgmt_descriptor.bDataInterface = status; + + status = -ENODEV; + + /* allocate instance-specific endpoints */ + ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_in_desc); + if (!ep) + goto fail; + acm->port.in = ep; + ep->driver_data = cdev; /* claim */ + + ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_out_desc); + if (!ep) + goto fail; + acm->port.out = ep; + ep->driver_data = cdev; /* claim */ + + ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_notify_desc); + if (!ep) + goto fail; + acm->notify = ep; + ep->driver_data = cdev; /* claim */ + + /* allocate notification */ + acm->notify_req = gs_alloc_req(ep, + sizeof(struct usb_cdc_notification) + 2, + GFP_KERNEL); + if (!acm->notify_req) + goto fail; + + acm->notify_req->complete = acm_cdc_notify_complete; + acm->notify_req->context = acm; + + /* copy descriptors */ + f->descriptors = usb_copy_descriptors(acm_fs_function); + if (!f->descriptors) + goto fail; + + /* support all relevant hardware speeds... we expect that when + * hardware is dual speed, all bulk-capable endpoints work at + * both speeds + */ + if (gadget_is_dualspeed(c->cdev->gadget)) { + acm_hs_in_desc.bEndpointAddress = + acm_fs_in_desc.bEndpointAddress; + acm_hs_out_desc.bEndpointAddress = + acm_fs_out_desc.bEndpointAddress; + acm_hs_notify_desc.bEndpointAddress = + acm_fs_notify_desc.bEndpointAddress; + + /* copy descriptors */ + f->hs_descriptors = usb_copy_descriptors(acm_hs_function); + } + if (gadget_is_superspeed(c->cdev->gadget)) { + acm_ss_in_desc.bEndpointAddress = + acm_fs_in_desc.bEndpointAddress; + acm_ss_out_desc.bEndpointAddress = + acm_fs_out_desc.bEndpointAddress; + + /* copy descriptors, and track endpoint copies */ + f->ss_descriptors = usb_copy_descriptors(acm_ss_function); + if (!f->ss_descriptors) + goto fail; + } + + DBG(cdev, "acm ttyGS%d: %s speed IN/%s OUT/%s NOTIFY/%s\n", + acm->port_num, + gadget_is_superspeed(c->cdev->gadget) ? "super" : + gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", + acm->port.in->name, acm->port.out->name, + acm->notify->name); + return 0; + +fail: + if (acm->notify_req) + gs_free_req(acm->notify, acm->notify_req); + + /* we might as well release our claims on endpoints */ + if (acm->notify) + acm->notify->driver_data = NULL; + if (acm->port.out) + acm->port.out->driver_data = NULL; + if (acm->port.in) + acm->port.in->driver_data = NULL; + + ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status); + + return status; +} + +static void +acm_unbind(struct usb_configuration *c, struct usb_function *f) +{ + struct f_acm *acm = func_to_acm(f); + + if (gadget_is_dualspeed(c->cdev->gadget)) + usb_free_descriptors(f->hs_descriptors); + if (gadget_is_superspeed(c->cdev->gadget)) + usb_free_descriptors(f->ss_descriptors); + usb_free_descriptors(f->descriptors); + gs_free_req(acm->notify, acm->notify_req); + kfree(acm); +} + +/* Some controllers can't support CDC ACM ... */ +static inline bool can_support_cdc(struct usb_configuration *c) +{ + /* everything else is *probably* fine ... */ + return true; +} + +/** + * acm_bind_config - add a CDC ACM function to a configuration + * @c: the configuration to support the CDC ACM instance + * @port_num: /dev/ttyGS* port this interface will use + * Context: single threaded during gadget setup + * + * Returns zero on success, else negative errno. + * + * Caller must have called @gserial_setup() with enough ports to + * handle all the ones it binds. Caller is also responsible + * for calling @gserial_cleanup() before module unload. + */ +int acm_bind_config(struct usb_configuration *c, u8 port_num) +{ + struct f_acm *acm; + int status; + + if (!can_support_cdc(c)) + return -EINVAL; + + /* REVISIT might want instance-specific strings to help + * distinguish instances ... + */ + + /* maybe allocate device-global string IDs, and patch descriptors */ + if (acm_string_defs[ACM_CTRL_IDX].id == 0) { + status = usb_string_id(c->cdev); + if (status < 0) + return status; + acm_string_defs[ACM_CTRL_IDX].id = status; + + acm_control_interface_desc.iInterface = status; + + status = usb_string_id(c->cdev); + if (status < 0) + return status; + acm_string_defs[ACM_DATA_IDX].id = status; + + acm_data_interface_desc.iInterface = status; + + status = usb_string_id(c->cdev); + if (status < 0) + return status; + acm_string_defs[ACM_IAD_IDX].id = status; + + acm_iad_descriptor.iFunction = status; + } + + /* allocate and initialize one new instance */ + acm = kzalloc(sizeof *acm, GFP_KERNEL); + if (!acm) + return -ENOMEM; + + spin_lock_init(&acm->lock); + + acm->port_num = port_num; + + acm->port.connect = acm_connect; + acm->port.disconnect = acm_disconnect; + acm->port.send_break = acm_send_break; + + acm->port.func.name = "acm"; + acm->port.func.strings = acm_strings; + /* descriptors are per-instance copies */ + acm->port.func.bind = acm_bind; + acm->port.func.unbind = acm_unbind; + acm->port.func.set_alt = acm_set_alt; + acm->port.func.setup = acm_setup; + acm->port.func.disable = acm_disable; + + status = usb_add_function(c, &acm->port.func); + if (status) + kfree(acm); + return status; +} diff --git a/drivers/staging/ccg/f_fs.c b/drivers/staging/ccg/f_fs.c new file mode 100644 index 0000000..8adc79d --- /dev/null +++ b/drivers/staging/ccg/f_fs.c @@ -0,0 +1,2455 @@ +/* + * f_fs.c -- user mode file system API for USB composite function controllers + * + * Copyright (C) 2010 Samsung Electronics + * Author: Michal Nazarewicz + * + * Based on inode.c (GadgetFS) which was: + * Copyright (C) 2003-2004 David Brownell + * Copyright (C) 2003 Agilent Technologies + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +/* #define DEBUG */ +/* #define VERBOSE_DEBUG */ + +#include +#include +#include +#include +#include + +#include +#include + + +#define FUNCTIONFS_MAGIC 0xa647361 /* Chosen by a honest dice roll ;) */ + + +/* Debugging ****************************************************************/ + +#ifdef VERBOSE_DEBUG +# define pr_vdebug pr_debug +# define ffs_dump_mem(prefix, ptr, len) \ + print_hex_dump_bytes(pr_fmt(prefix ": "), DUMP_PREFIX_NONE, ptr, len) +#else +# define pr_vdebug(...) do { } while (0) +# define ffs_dump_mem(prefix, ptr, len) do { } while (0) +#endif /* VERBOSE_DEBUG */ + +#define ENTER() pr_vdebug("%s()\n", __func__) + + +/* The data structure and setup file ****************************************/ + +enum ffs_state { + /* + * Waiting for descriptors and strings. + * + * In this state no open(2), read(2) or write(2) on epfiles + * may succeed (which should not be the problem as there + * should be no such files opened in the first place). + */ + FFS_READ_DESCRIPTORS, + FFS_READ_STRINGS, + + /* + * We've got descriptors and strings. We are or have called + * functionfs_ready_callback(). functionfs_bind() may have + * been called but we don't know. + * + * This is the only state in which operations on epfiles may + * succeed. + */ + FFS_ACTIVE, + + /* + * All endpoints have been closed. This state is also set if + * we encounter an unrecoverable error. The only + * unrecoverable error is situation when after reading strings + * from user space we fail to initialise epfiles or + * functionfs_ready_callback() returns with error (<0). + * + * In this state no open(2), read(2) or write(2) (both on ep0 + * as well as epfile) may succeed (at this point epfiles are + * unlinked and all closed so this is not a problem; ep0 is + * also closed but ep0 file exists and so open(2) on ep0 must + * fail). + */ + FFS_CLOSING +}; + + +enum ffs_setup_state { + /* There is no setup request pending. */ + FFS_NO_SETUP, + /* + * User has read events and there was a setup request event + * there. The next read/write on ep0 will handle the + * request. + */ + FFS_SETUP_PENDING, + /* + * There was event pending but before user space handled it + * some other event was introduced which canceled existing + * setup. If this state is set read/write on ep0 return + * -EIDRM. This state is only set when adding event. + */ + FFS_SETUP_CANCELED +}; + + + +struct ffs_epfile; +struct ffs_function; + +struct ffs_data { + struct usb_gadget *gadget; + + /* + * Protect access read/write operations, only one read/write + * at a time. As a consequence protects ep0req and company. + * While setup request is being processed (queued) this is + * held. + */ + struct mutex mutex; + + /* + * Protect access to endpoint related structures (basically + * usb_ep_queue(), usb_ep_dequeue(), etc. calls) except for + * endpoint zero. + */ + spinlock_t eps_lock; + + /* + * XXX REVISIT do we need our own request? Since we are not + * handling setup requests immediately user space may be so + * slow that another setup will be sent to the gadget but this + * time not to us but another function and then there could be + * a race. Is that the case? Or maybe we can use cdev->req + * after all, maybe we just need some spinlock for that? + */ + struct usb_request *ep0req; /* P: mutex */ + struct completion ep0req_completion; /* P: mutex */ + int ep0req_status; /* P: mutex */ + + /* reference counter */ + atomic_t ref; + /* how many files are opened (EP0 and others) */ + atomic_t opened; + + /* EP0 state */ + enum ffs_state state; + + /* + * Possible transitions: + * + FFS_NO_SETUP -> FFS_SETUP_PENDING -- P: ev.waitq.lock + * happens only in ep0 read which is P: mutex + * + FFS_SETUP_PENDING -> FFS_NO_SETUP -- P: ev.waitq.lock + * happens only in ep0 i/o which is P: mutex + * + FFS_SETUP_PENDING -> FFS_SETUP_CANCELED -- P: ev.waitq.lock + * + FFS_SETUP_CANCELED -> FFS_NO_SETUP -- cmpxchg + */ + enum ffs_setup_state setup_state; + +#define FFS_SETUP_STATE(ffs) \ + ((enum ffs_setup_state)cmpxchg(&(ffs)->setup_state, \ + FFS_SETUP_CANCELED, FFS_NO_SETUP)) + + /* Events & such. */ + struct { + u8 types[4]; + unsigned short count; + /* XXX REVISIT need to update it in some places, or do we? */ + unsigned short can_stall; + struct usb_ctrlrequest setup; + + wait_queue_head_t waitq; + } ev; /* the whole structure, P: ev.waitq.lock */ + + /* Flags */ + unsigned long flags; +#define FFS_FL_CALL_CLOSED_CALLBACK 0 +#define FFS_FL_BOUND 1 + + /* Active function */ + struct ffs_function *func; + + /* + * Device name, write once when file system is mounted. + * Intended for user to read if she wants. + */ + const char *dev_name; + /* Private data for our user (ie. gadget). Managed by user. */ + void *private_data; + + /* filled by __ffs_data_got_descs() */ + /* + * Real descriptors are 16 bytes after raw_descs (so you need + * to skip 16 bytes (ie. ffs->raw_descs + 16) to get to the + * first full speed descriptor). raw_descs_length and + * raw_fs_descs_length do not have those 16 bytes added. + */ + const void *raw_descs; + unsigned raw_descs_length; + unsigned raw_fs_descs_length; + unsigned fs_descs_count; + unsigned hs_descs_count; + + unsigned short strings_count; + unsigned short interfaces_count; + unsigned short eps_count; + unsigned short _pad1; + + /* filled by __ffs_data_got_strings() */ + /* ids in stringtabs are set in functionfs_bind() */ + const void *raw_strings; + struct usb_gadget_strings **stringtabs; + + /* + * File system's super block, write once when file system is + * mounted. + */ + struct super_block *sb; + + /* File permissions, written once when fs is mounted */ + struct ffs_file_perms { + umode_t mode; + uid_t uid; + gid_t gid; + } file_perms; + + /* + * The endpoint files, filled by ffs_epfiles_create(), + * destroyed by ffs_epfiles_destroy(). + */ + struct ffs_epfile *epfiles; +}; + +/* Reference counter handling */ +static void ffs_data_get(struct ffs_data *ffs); +static void ffs_data_put(struct ffs_data *ffs); +/* Creates new ffs_data object. */ +static struct ffs_data *__must_check ffs_data_new(void) __attribute__((malloc)); + +/* Opened counter handling. */ +static void ffs_data_opened(struct ffs_data *ffs); +static void ffs_data_closed(struct ffs_data *ffs); + +/* Called with ffs->mutex held; take over ownership of data. */ +static int __must_check +__ffs_data_got_descs(struct ffs_data *ffs, char *data, size_t len); +static int __must_check +__ffs_data_got_strings(struct ffs_data *ffs, char *data, size_t len); + + +/* The function structure ***************************************************/ + +struct ffs_ep; + +struct ffs_function { + struct usb_configuration *conf; + struct usb_gadget *gadget; + struct ffs_data *ffs; + + struct ffs_ep *eps; + u8 eps_revmap[16]; + short *interfaces_nums; + + struct usb_function function; +}; + + +static struct ffs_function *ffs_func_from_usb(struct usb_function *f) +{ + return container_of(f, struct ffs_function, function); +} + +static void ffs_func_free(struct ffs_function *func); + +static void ffs_func_eps_disable(struct ffs_function *func); +static int __must_check ffs_func_eps_enable(struct ffs_function *func); + +static int ffs_func_bind(struct usb_configuration *, + struct usb_function *); +static void ffs_func_unbind(struct usb_configuration *, + struct usb_function *); +static int ffs_func_set_alt(struct usb_function *, unsigned, unsigned); +static void ffs_func_disable(struct usb_function *); +static int ffs_func_setup(struct usb_function *, + const struct usb_ctrlrequest *); +static void ffs_func_suspend(struct usb_function *); +static void ffs_func_resume(struct usb_function *); + + +static int ffs_func_revmap_ep(struct ffs_function *func, u8 num); +static int ffs_func_revmap_intf(struct ffs_function *func, u8 intf); + + +/* The endpoints structures *************************************************/ + +struct ffs_ep { + struct usb_ep *ep; /* P: ffs->eps_lock */ + struct usb_request *req; /* P: epfile->mutex */ + + /* [0]: full speed, [1]: high speed */ + struct usb_endpoint_descriptor *descs[2]; + + u8 num; + + int status; /* P: epfile->mutex */ +}; + +struct ffs_epfile { + /* Protects ep->ep and ep->req. */ + struct mutex mutex; + wait_queue_head_t wait; + + struct ffs_data *ffs; + struct ffs_ep *ep; /* P: ffs->eps_lock */ + + struct dentry *dentry; + + char name[5]; + + unsigned char in; /* P: ffs->eps_lock */ + unsigned char isoc; /* P: ffs->eps_lock */ + + unsigned char _pad; +}; + +static int __must_check ffs_epfiles_create(struct ffs_data *ffs); +static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count); + +static struct inode *__must_check +ffs_sb_create_file(struct super_block *sb, const char *name, void *data, + const struct file_operations *fops, + struct dentry **dentry_p); + + +/* Misc helper functions ****************************************************/ + +static int ffs_mutex_lock(struct mutex *mutex, unsigned nonblock) + __attribute__((warn_unused_result, nonnull)); +static char *ffs_prepare_buffer(const char * __user buf, size_t len) + __attribute__((warn_unused_result, nonnull)); + + +/* Control file aka ep0 *****************************************************/ + +static void ffs_ep0_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct ffs_data *ffs = req->context; + + complete_all(&ffs->ep0req_completion); +} + +static int __ffs_ep0_queue_wait(struct ffs_data *ffs, char *data, size_t len) +{ + struct usb_request *req = ffs->ep0req; + int ret; + + req->zero = len < le16_to_cpu(ffs->ev.setup.wLength); + + spin_unlock_irq(&ffs->ev.waitq.lock); + + req->buf = data; + req->length = len; + + /* + * UDC layer requires to provide a buffer even for ZLP, but should + * not use it at all. Let's provide some poisoned pointer to catch + * possible bug in the driver. + */ + if (req->buf == NULL) + req->buf = (void *)0xDEADBABE; + + INIT_COMPLETION(ffs->ep0req_completion); + + ret = usb_ep_queue(ffs->gadget->ep0, req, GFP_ATOMIC); + if (unlikely(ret < 0)) + return ret; + + ret = wait_for_completion_interruptible(&ffs->ep0req_completion); + if (unlikely(ret)) { + usb_ep_dequeue(ffs->gadget->ep0, req); + return -EINTR; + } + + ffs->setup_state = FFS_NO_SETUP; + return ffs->ep0req_status; +} + +static int __ffs_ep0_stall(struct ffs_data *ffs) +{ + if (ffs->ev.can_stall) { + pr_vdebug("ep0 stall\n"); + usb_ep_set_halt(ffs->gadget->ep0); + ffs->setup_state = FFS_NO_SETUP; + return -EL2HLT; + } else { + pr_debug("bogus ep0 stall!\n"); + return -ESRCH; + } +} + +static ssize_t ffs_ep0_write(struct file *file, const char __user *buf, + size_t len, loff_t *ptr) +{ + struct ffs_data *ffs = file->private_data; + ssize_t ret; + char *data; + + ENTER(); + + /* Fast check if setup was canceled */ + if (FFS_SETUP_STATE(ffs) == FFS_SETUP_CANCELED) + return -EIDRM; + + /* Acquire mutex */ + ret = ffs_mutex_lock(&ffs->mutex, file->f_flags & O_NONBLOCK); + if (unlikely(ret < 0)) + return ret; + + /* Check state */ + switch (ffs->state) { + case FFS_READ_DESCRIPTORS: + case FFS_READ_STRINGS: + /* Copy data */ + if (unlikely(len < 16)) { + ret = -EINVAL; + break; + } + + data = ffs_prepare_buffer(buf, len); + if (IS_ERR(data)) { + ret = PTR_ERR(data); + break; + } + + /* Handle data */ + if (ffs->state == FFS_READ_DESCRIPTORS) { + pr_info("read descriptors\n"); + ret = __ffs_data_got_descs(ffs, data, len); + if (unlikely(ret < 0)) + break; + + ffs->state = FFS_READ_STRINGS; + ret = len; + } else { + pr_info("read strings\n"); + ret = __ffs_data_got_strings(ffs, data, len); + if (unlikely(ret < 0)) + break; + + ret = ffs_epfiles_create(ffs); + if (unlikely(ret)) { + ffs->state = FFS_CLOSING; + break; + } + + ffs->state = FFS_ACTIVE; + mutex_unlock(&ffs->mutex); + + ret = functionfs_ready_callback(ffs); + if (unlikely(ret < 0)) { + ffs->state = FFS_CLOSING; + return ret; + } + + set_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags); + return len; + } + break; + + case FFS_ACTIVE: + data = NULL; + /* + * We're called from user space, we can use _irq + * rather then _irqsave + */ + spin_lock_irq(&ffs->ev.waitq.lock); + switch (FFS_SETUP_STATE(ffs)) { + case FFS_SETUP_CANCELED: + ret = -EIDRM; + goto done_spin; + + case FFS_NO_SETUP: + ret = -ESRCH; + goto done_spin; + + case FFS_SETUP_PENDING: + break; + } + + /* FFS_SETUP_PENDING */ + if (!(ffs->ev.setup.bRequestType & USB_DIR_IN)) { + spin_unlock_irq(&ffs->ev.waitq.lock); + ret = __ffs_ep0_stall(ffs); + break; + } + + /* FFS_SETUP_PENDING and not stall */ + len = min(len, (size_t)le16_to_cpu(ffs->ev.setup.wLength)); + + spin_unlock_irq(&ffs->ev.waitq.lock); + + data = ffs_prepare_buffer(buf, len); + if (IS_ERR(data)) { + ret = PTR_ERR(data); + break; + } + + spin_lock_irq(&ffs->ev.waitq.lock); + + /* + * We are guaranteed to be still in FFS_ACTIVE state + * but the state of setup could have changed from + * FFS_SETUP_PENDING to FFS_SETUP_CANCELED so we need + * to check for that. If that happened we copied data + * from user space in vain but it's unlikely. + * + * For sure we are not in FFS_NO_SETUP since this is + * the only place FFS_SETUP_PENDING -> FFS_NO_SETUP + * transition can be performed and it's protected by + * mutex. + */ + if (FFS_SETUP_STATE(ffs) == FFS_SETUP_CANCELED) { + ret = -EIDRM; +done_spin: + spin_unlock_irq(&ffs->ev.waitq.lock); + } else { + /* unlocks spinlock */ + ret = __ffs_ep0_queue_wait(ffs, data, len); + } + kfree(data); + break; + + default: + ret = -EBADFD; + break; + } + + mutex_unlock(&ffs->mutex); + return ret; +} + +static ssize_t __ffs_ep0_read_events(struct ffs_data *ffs, char __user *buf, + size_t n) +{ + /* + * We are holding ffs->ev.waitq.lock and ffs->mutex and we need + * to release them. + */ + struct usb_functionfs_event events[n]; + unsigned i = 0; + + memset(events, 0, sizeof events); + + do { + events[i].type = ffs->ev.types[i]; + if (events[i].type == FUNCTIONFS_SETUP) { + events[i].u.setup = ffs->ev.setup; + ffs->setup_state = FFS_SETUP_PENDING; + } + } while (++i < n); + + if (n < ffs->ev.count) { + ffs->ev.count -= n; + memmove(ffs->ev.types, ffs->ev.types + n, + ffs->ev.count * sizeof *ffs->ev.types); + } else { + ffs->ev.count = 0; + } + + spin_unlock_irq(&ffs->ev.waitq.lock); + mutex_unlock(&ffs->mutex); + + return unlikely(__copy_to_user(buf, events, sizeof events)) + ? -EFAULT : sizeof events; +} + +static ssize_t ffs_ep0_read(struct file *file, char __user *buf, + size_t len, loff_t *ptr) +{ + struct ffs_data *ffs = file->private_data; + char *data = NULL; + size_t n; + int ret; + + ENTER(); + + /* Fast check if setup was canceled */ + if (FFS_SETUP_STATE(ffs) == FFS_SETUP_CANCELED) + return -EIDRM; + + /* Acquire mutex */ + ret = ffs_mutex_lock(&ffs->mutex, file->f_flags & O_NONBLOCK); + if (unlikely(ret < 0)) + return ret; + + /* Check state */ + if (ffs->state != FFS_ACTIVE) { + ret = -EBADFD; + goto done_mutex; + } + + /* + * We're called from user space, we can use _irq rather then + * _irqsave + */ + spin_lock_irq(&ffs->ev.waitq.lock); + + switch (FFS_SETUP_STATE(ffs)) { + case FFS_SETUP_CANCELED: + ret = -EIDRM; + break; + + case FFS_NO_SETUP: + n = len / sizeof(struct usb_functionfs_event); + if (unlikely(!n)) { + ret = -EINVAL; + break; + } + + if ((file->f_flags & O_NONBLOCK) && !ffs->ev.count) { + ret = -EAGAIN; + break; + } + + if (wait_event_interruptible_exclusive_locked_irq(ffs->ev.waitq, + ffs->ev.count)) { + ret = -EINTR; + break; + } + + return __ffs_ep0_read_events(ffs, buf, + min(n, (size_t)ffs->ev.count)); + + case FFS_SETUP_PENDING: + if (ffs->ev.setup.bRequestType & USB_DIR_IN) { + spin_unlock_irq(&ffs->ev.waitq.lock); + ret = __ffs_ep0_stall(ffs); + goto done_mutex; + } + + len = min(len, (size_t)le16_to_cpu(ffs->ev.setup.wLength)); + + spin_unlock_irq(&ffs->ev.waitq.lock); + + if (likely(len)) { + data = kmalloc(len, GFP_KERNEL); + if (unlikely(!data)) { + ret = -ENOMEM; + goto done_mutex; + } + } + + spin_lock_irq(&ffs->ev.waitq.lock); + + /* See ffs_ep0_write() */ + if (FFS_SETUP_STATE(ffs) == FFS_SETUP_CANCELED) { + ret = -EIDRM; + break; + } + + /* unlocks spinlock */ + ret = __ffs_ep0_queue_wait(ffs, data, len); + if (likely(ret > 0) && unlikely(__copy_to_user(buf, data, len))) + ret = -EFAULT; + goto done_mutex; + + default: + ret = -EBADFD; + break; + } + + spin_unlock_irq(&ffs->ev.waitq.lock); +done_mutex: + mutex_unlock(&ffs->mutex); + kfree(data); + return ret; +} + +static int ffs_ep0_open(struct inode *inode, struct file *file) +{ + struct ffs_data *ffs = inode->i_private; + + ENTER(); + + if (unlikely(ffs->state == FFS_CLOSING)) + return -EBUSY; + + file->private_data = ffs; + ffs_data_opened(ffs); + + return 0; +} + +static int ffs_ep0_release(struct inode *inode, struct file *file) +{ + struct ffs_data *ffs = file->private_data; + + ENTER(); + + ffs_data_closed(ffs); + + return 0; +} + +static long ffs_ep0_ioctl(struct file *file, unsigned code, unsigned long value) +{ + struct ffs_data *ffs = file->private_data; + struct usb_gadget *gadget = ffs->gadget; + long ret; + + ENTER(); + + if (code == FUNCTIONFS_INTERFACE_REVMAP) { + struct ffs_function *func = ffs->func; + ret = func ? ffs_func_revmap_intf(func, value) : -ENODEV; + } else if (gadget && gadget->ops->ioctl) { + ret = gadget->ops->ioctl(gadget, code, value); + } else { + ret = -ENOTTY; + } + + return ret; +} + +static const struct file_operations ffs_ep0_operations = { + .owner = THIS_MODULE, + .llseek = no_llseek, + + .open = ffs_ep0_open, + .write = ffs_ep0_write, + .read = ffs_ep0_read, + .release = ffs_ep0_release, + .unlocked_ioctl = ffs_ep0_ioctl, +}; + + +/* "Normal" endpoints operations ********************************************/ + +static void ffs_epfile_io_complete(struct usb_ep *_ep, struct usb_request *req) +{ + ENTER(); + if (likely(req->context)) { + struct ffs_ep *ep = _ep->driver_data; + ep->status = req->status ? req->status : req->actual; + complete(req->context); + } +} + +static ssize_t ffs_epfile_io(struct file *file, + char __user *buf, size_t len, int read) +{ + struct ffs_epfile *epfile = file->private_data; + struct ffs_ep *ep; + char *data = NULL; + ssize_t ret; + int halt; + + goto first_try; + do { + spin_unlock_irq(&epfile->ffs->eps_lock); + mutex_unlock(&epfile->mutex); + +first_try: + /* Are we still active? */ + if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) { + ret = -ENODEV; + goto error; + } + + /* Wait for endpoint to be enabled */ + ep = epfile->ep; + if (!ep) { + if (file->f_flags & O_NONBLOCK) { + ret = -EAGAIN; + goto error; + } + + if (wait_event_interruptible(epfile->wait, + (ep = epfile->ep))) { + ret = -EINTR; + goto error; + } + } + + /* Do we halt? */ + halt = !read == !epfile->in; + if (halt && epfile->isoc) { + ret = -EINVAL; + goto error; + } + + /* Allocate & copy */ + if (!halt && !data) { + data = kzalloc(len, GFP_KERNEL); + if (unlikely(!data)) + return -ENOMEM; + + if (!read && + unlikely(__copy_from_user(data, buf, len))) { + ret = -EFAULT; + goto error; + } + } + + /* We will be using request */ + ret = ffs_mutex_lock(&epfile->mutex, + file->f_flags & O_NONBLOCK); + if (unlikely(ret)) + goto error; + + /* + * We're called from user space, we can use _irq rather then + * _irqsave + */ + spin_lock_irq(&epfile->ffs->eps_lock); + + /* + * While we were acquiring mutex endpoint got disabled + * or changed? + */ + } while (unlikely(epfile->ep != ep)); + + /* Halt */ + if (unlikely(halt)) { + if (likely(epfile->ep == ep) && !WARN_ON(!ep->ep)) + usb_ep_set_halt(ep->ep); + spin_unlock_irq(&epfile->ffs->eps_lock); + ret = -EBADMSG; + } else { + /* Fire the request */ + DECLARE_COMPLETION_ONSTACK(done); + + struct usb_request *req = ep->req; + req->context = &done; + req->complete = ffs_epfile_io_complete; + req->buf = data; + req->length = len; + + ret = usb_ep_queue(ep->ep, req, GFP_ATOMIC); + + spin_unlock_irq(&epfile->ffs->eps_lock); + + if (unlikely(ret < 0)) { + /* nop */ + } else if (unlikely(wait_for_completion_interruptible(&done))) { + ret = -EINTR; + usb_ep_dequeue(ep->ep, req); + } else { + ret = ep->status; + if (read && ret > 0 && + unlikely(copy_to_user(buf, data, ret))) + ret = -EFAULT; + } + } + + mutex_unlock(&epfile->mutex); +error: + kfree(data); + return ret; +} + +static ssize_t +ffs_epfile_write(struct file *file, const char __user *buf, size_t len, + loff_t *ptr) +{ + ENTER(); + + return ffs_epfile_io(file, (char __user *)buf, len, 0); +} + +static ssize_t +ffs_epfile_read(struct file *file, char __user *buf, size_t len, loff_t *ptr) +{ + ENTER(); + + return ffs_epfile_io(file, buf, len, 1); +} + +static int +ffs_epfile_open(struct inode *inode, struct file *file) +{ + struct ffs_epfile *epfile = inode->i_private; + + ENTER(); + + if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) + return -ENODEV; + + file->private_data = epfile; + ffs_data_opened(epfile->ffs); + + return 0; +} + +static int +ffs_epfile_release(struct inode *inode, struct file *file) +{ + struct ffs_epfile *epfile = inode->i_private; + + ENTER(); + + ffs_data_closed(epfile->ffs); + + return 0; +} + +static long ffs_epfile_ioctl(struct file *file, unsigned code, + unsigned long value) +{ + struct ffs_epfile *epfile = file->private_data; + int ret; + + ENTER(); + + if (WARN_ON(epfile->ffs->state != FFS_ACTIVE)) + return -ENODEV; + + spin_lock_irq(&epfile->ffs->eps_lock); + if (likely(epfile->ep)) { + switch (code) { + case FUNCTIONFS_FIFO_STATUS: + ret = usb_ep_fifo_status(epfile->ep->ep); + break; + case FUNCTIONFS_FIFO_FLUSH: + usb_ep_fifo_flush(epfile->ep->ep); + ret = 0; + break; + case FUNCTIONFS_CLEAR_HALT: + ret = usb_ep_clear_halt(epfile->ep->ep); + break; + case FUNCTIONFS_ENDPOINT_REVMAP: + ret = epfile->ep->num; + break; + default: + ret = -ENOTTY; + } + } else { + ret = -ENODEV; + } + spin_unlock_irq(&epfile->ffs->eps_lock); + + return ret; +} + +static const struct file_operations ffs_epfile_operations = { + .owner = THIS_MODULE, + .llseek = no_llseek, + + .open = ffs_epfile_open, + .write = ffs_epfile_write, + .read = ffs_epfile_read, + .release = ffs_epfile_release, + .unlocked_ioctl = ffs_epfile_ioctl, +}; + + +/* File system and super block operations ***********************************/ + +/* + * Mounting the file system creates a controller file, used first for + * function configuration then later for event monitoring. + */ + +static struct inode *__must_check +ffs_sb_make_inode(struct super_block *sb, void *data, + const struct file_operations *fops, + const struct inode_operations *iops, + struct ffs_file_perms *perms) +{ + struct inode *inode; + + ENTER(); + + inode = new_inode(sb); + + if (likely(inode)) { + struct timespec current_time = CURRENT_TIME; + + inode->i_ino = get_next_ino(); + inode->i_mode = perms->mode; + inode->i_uid = perms->uid; + inode->i_gid = perms->gid; + inode->i_atime = current_time; + inode->i_mtime = current_time; + inode->i_ctime = current_time; + inode->i_private = data; + if (fops) + inode->i_fop = fops; + if (iops) + inode->i_op = iops; + } + + return inode; +} + +/* Create "regular" file */ +static struct inode *ffs_sb_create_file(struct super_block *sb, + const char *name, void *data, + const struct file_operations *fops, + struct dentry **dentry_p) +{ + struct ffs_data *ffs = sb->s_fs_info; + struct dentry *dentry; + struct inode *inode; + + ENTER(); + + dentry = d_alloc_name(sb->s_root, name); + if (unlikely(!dentry)) + return NULL; + + inode = ffs_sb_make_inode(sb, data, fops, NULL, &ffs->file_perms); + if (unlikely(!inode)) { + dput(dentry); + return NULL; + } + + d_add(dentry, inode); + if (dentry_p) + *dentry_p = dentry; + + return inode; +} + +/* Super block */ +static const struct super_operations ffs_sb_operations = { + .statfs = simple_statfs, + .drop_inode = generic_delete_inode, +}; + +struct ffs_sb_fill_data { + struct ffs_file_perms perms; + umode_t root_mode; + const char *dev_name; + union { + /* set by ffs_fs_mount(), read by ffs_sb_fill() */ + void *private_data; + /* set by ffs_sb_fill(), read by ffs_fs_mount */ + struct ffs_data *ffs_data; + }; +}; + +static int ffs_sb_fill(struct super_block *sb, void *_data, int silent) +{ + struct ffs_sb_fill_data *data = _data; + struct inode *inode; + struct ffs_data *ffs; + + ENTER(); + + /* Initialise data */ + ffs = ffs_data_new(); + if (unlikely(!ffs)) + goto Enomem; + + ffs->sb = sb; + ffs->dev_name = kstrdup(data->dev_name, GFP_KERNEL); + if (unlikely(!ffs->dev_name)) + goto Enomem; + ffs->file_perms = data->perms; + ffs->private_data = data->private_data; + + /* used by the caller of this function */ + data->ffs_data = ffs; + + sb->s_fs_info = ffs; + sb->s_blocksize = PAGE_CACHE_SIZE; + sb->s_blocksize_bits = PAGE_CACHE_SHIFT; + sb->s_magic = FUNCTIONFS_MAGIC; + sb->s_op = &ffs_sb_operations; + sb->s_time_gran = 1; + + /* Root inode */ + data->perms.mode = data->root_mode; + inode = ffs_sb_make_inode(sb, NULL, + &simple_dir_operations, + &simple_dir_inode_operations, + &data->perms); + sb->s_root = d_make_root(inode); + if (unlikely(!sb->s_root)) + goto Enomem; + + /* EP0 file */ + if (unlikely(!ffs_sb_create_file(sb, "ep0", ffs, + &ffs_ep0_operations, NULL))) + goto Enomem; + + return 0; + +Enomem: + return -ENOMEM; +} + +static int ffs_fs_parse_opts(struct ffs_sb_fill_data *data, char *opts) +{ + ENTER(); + + if (!opts || !*opts) + return 0; + + for (;;) { + char *end, *eq, *comma; + unsigned long value; + + /* Option limit */ + comma = strchr(opts, ','); + if (comma) + *comma = 0; + + /* Value limit */ + eq = strchr(opts, '='); + if (unlikely(!eq)) { + pr_err("'=' missing in %s\n", opts); + return -EINVAL; + } + *eq = 0; + + /* Parse value */ + value = simple_strtoul(eq + 1, &end, 0); + if (unlikely(*end != ',' && *end != 0)) { + pr_err("%s: invalid value: %s\n", opts, eq + 1); + return -EINVAL; + } + + /* Interpret option */ + switch (eq - opts) { + case 5: + if (!memcmp(opts, "rmode", 5)) + data->root_mode = (value & 0555) | S_IFDIR; + else if (!memcmp(opts, "fmode", 5)) + data->perms.mode = (value & 0666) | S_IFREG; + else + goto invalid; + break; + + case 4: + if (!memcmp(opts, "mode", 4)) { + data->root_mode = (value & 0555) | S_IFDIR; + data->perms.mode = (value & 0666) | S_IFREG; + } else { + goto invalid; + } + break; + + case 3: + if (!memcmp(opts, "uid", 3)) + data->perms.uid = value; + else if (!memcmp(opts, "gid", 3)) + data->perms.gid = value; + else + goto invalid; + break; + + default: +invalid: + pr_err("%s: invalid option\n", opts); + return -EINVAL; + } + + /* Next iteration */ + if (!comma) + break; + opts = comma + 1; + } + + return 0; +} + +/* "mount -t functionfs dev_name /dev/function" ends up here */ + +static struct dentry * +ffs_fs_mount(struct file_system_type *t, int flags, + const char *dev_name, void *opts) +{ + struct ffs_sb_fill_data data = { + .perms = { + .mode = S_IFREG | 0600, + .uid = 0, + .gid = 0 + }, + .root_mode = S_IFDIR | 0500, + }; + struct dentry *rv; + int ret; + void *ffs_dev; + + ENTER(); + + ret = ffs_fs_parse_opts(&data, opts); + if (unlikely(ret < 0)) + return ERR_PTR(ret); + + ffs_dev = functionfs_acquire_dev_callback(dev_name); + if (IS_ERR(ffs_dev)) + return ffs_dev; + + data.dev_name = dev_name; + data.private_data = ffs_dev; + rv = mount_nodev(t, flags, &data, ffs_sb_fill); + + /* data.ffs_data is set by ffs_sb_fill */ + if (IS_ERR(rv)) + functionfs_release_dev_callback(data.ffs_data); + + return rv; +} + +static void +ffs_fs_kill_sb(struct super_block *sb) +{ + ENTER(); + + kill_litter_super(sb); + if (sb->s_fs_info) { + functionfs_release_dev_callback(sb->s_fs_info); + ffs_data_put(sb->s_fs_info); + } +} + +static struct file_system_type ffs_fs_type = { + .owner = THIS_MODULE, + .name = "functionfs", + .mount = ffs_fs_mount, + .kill_sb = ffs_fs_kill_sb, +}; + + +/* Driver's main init/cleanup functions *************************************/ + +static int functionfs_init(void) +{ + int ret; + + ENTER(); + + ret = register_filesystem(&ffs_fs_type); + if (likely(!ret)) + pr_info("file system registered\n"); + else + pr_err("failed registering file system (%d)\n", ret); + + return ret; +} + +static void functionfs_cleanup(void) +{ + ENTER(); + + pr_info("unloading\n"); + unregister_filesystem(&ffs_fs_type); +} + + +/* ffs_data and ffs_function construction and destruction code **************/ + +static void ffs_data_clear(struct ffs_data *ffs); +static void ffs_data_reset(struct ffs_data *ffs); + +static void ffs_data_get(struct ffs_data *ffs) +{ + ENTER(); + + atomic_inc(&ffs->ref); +} + +static void ffs_data_opened(struct ffs_data *ffs) +{ + ENTER(); + + atomic_inc(&ffs->ref); + atomic_inc(&ffs->opened); +} + +static void ffs_data_put(struct ffs_data *ffs) +{ + ENTER(); + + if (unlikely(atomic_dec_and_test(&ffs->ref))) { + pr_info("%s(): freeing\n", __func__); + ffs_data_clear(ffs); + BUG_ON(waitqueue_active(&ffs->ev.waitq) || + waitqueue_active(&ffs->ep0req_completion.wait)); + kfree(ffs->dev_name); + kfree(ffs); + } +} + +static void ffs_data_closed(struct ffs_data *ffs) +{ + ENTER(); + + if (atomic_dec_and_test(&ffs->opened)) { + ffs->state = FFS_CLOSING; + ffs_data_reset(ffs); + } + + ffs_data_put(ffs); +} + +static struct ffs_data *ffs_data_new(void) +{ + struct ffs_data *ffs = kzalloc(sizeof *ffs, GFP_KERNEL); + if (unlikely(!ffs)) + return 0; + + ENTER(); + + atomic_set(&ffs->ref, 1); + atomic_set(&ffs->opened, 0); + ffs->state = FFS_READ_DESCRIPTORS; + mutex_init(&ffs->mutex); + spin_lock_init(&ffs->eps_lock); + init_waitqueue_head(&ffs->ev.waitq); + init_completion(&ffs->ep0req_completion); + + /* XXX REVISIT need to update it in some places, or do we? */ + ffs->ev.can_stall = 1; + + return ffs; +} + +static void ffs_data_clear(struct ffs_data *ffs) +{ + ENTER(); + + if (test_and_clear_bit(FFS_FL_CALL_CLOSED_CALLBACK, &ffs->flags)) + functionfs_closed_callback(ffs); + + BUG_ON(ffs->gadget); + + if (ffs->epfiles) + ffs_epfiles_destroy(ffs->epfiles, ffs->eps_count); + + kfree(ffs->raw_descs); + kfree(ffs->raw_strings); + kfree(ffs->stringtabs); +} + +static void ffs_data_reset(struct ffs_data *ffs) +{ + ENTER(); + + ffs_data_clear(ffs); + + ffs->epfiles = NULL; + ffs->raw_descs = NULL; + ffs->raw_strings = NULL; + ffs->stringtabs = NULL; + + ffs->raw_descs_length = 0; + ffs->raw_fs_descs_length = 0; + ffs->fs_descs_count = 0; + ffs->hs_descs_count = 0; + + ffs->strings_count = 0; + ffs->interfaces_count = 0; + ffs->eps_count = 0; + + ffs->ev.count = 0; + + ffs->state = FFS_READ_DESCRIPTORS; + ffs->setup_state = FFS_NO_SETUP; + ffs->flags = 0; +} + + +static int functionfs_bind(struct ffs_data *ffs, struct usb_composite_dev *cdev) +{ + struct usb_gadget_strings **lang; + int first_id; + + ENTER(); + + if (WARN_ON(ffs->state != FFS_ACTIVE + || test_and_set_bit(FFS_FL_BOUND, &ffs->flags))) + return -EBADFD; + + first_id = usb_string_ids_n(cdev, ffs->strings_count); + if (unlikely(first_id < 0)) + return first_id; + + ffs->ep0req = usb_ep_alloc_request(cdev->gadget->ep0, GFP_KERNEL); + if (unlikely(!ffs->ep0req)) + return -ENOMEM; + ffs->ep0req->complete = ffs_ep0_complete; + ffs->ep0req->context = ffs; + + lang = ffs->stringtabs; + for (lang = ffs->stringtabs; *lang; ++lang) { + struct usb_string *str = (*lang)->strings; + int id = first_id; + for (; str->s; ++id, ++str) + str->id = id; + } + + ffs->gadget = cdev->gadget; + ffs_data_get(ffs); + return 0; +} + +static void functionfs_unbind(struct ffs_data *ffs) +{ + ENTER(); + + if (!WARN_ON(!ffs->gadget)) { + usb_ep_free_request(ffs->gadget->ep0, ffs->ep0req); + ffs->ep0req = NULL; + ffs->gadget = NULL; + ffs_data_put(ffs); + clear_bit(FFS_FL_BOUND, &ffs->flags); + } +} + +static int ffs_epfiles_create(struct ffs_data *ffs) +{ + struct ffs_epfile *epfile, *epfiles; + unsigned i, count; + + ENTER(); + + count = ffs->eps_count; + epfiles = kcalloc(count, sizeof(*epfiles), GFP_KERNEL); + if (!epfiles) + return -ENOMEM; + + epfile = epfiles; + for (i = 1; i <= count; ++i, ++epfile) { + epfile->ffs = ffs; + mutex_init(&epfile->mutex); + init_waitqueue_head(&epfile->wait); + sprintf(epfiles->name, "ep%u", i); + if (!unlikely(ffs_sb_create_file(ffs->sb, epfiles->name, epfile, + &ffs_epfile_operations, + &epfile->dentry))) { + ffs_epfiles_destroy(epfiles, i - 1); + return -ENOMEM; + } + } + + ffs->epfiles = epfiles; + return 0; +} + +static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count) +{ + struct ffs_epfile *epfile = epfiles; + + ENTER(); + + for (; count; --count, ++epfile) { + BUG_ON(mutex_is_locked(&epfile->mutex) || + waitqueue_active(&epfile->wait)); + if (epfile->dentry) { + d_delete(epfile->dentry); + dput(epfile->dentry); + epfile->dentry = NULL; + } + } + + kfree(epfiles); +} + +static int functionfs_bind_config(struct usb_composite_dev *cdev, + struct usb_configuration *c, + struct ffs_data *ffs) +{ + struct ffs_function *func; + int ret; + + ENTER(); + + func = kzalloc(sizeof *func, GFP_KERNEL); + if (unlikely(!func)) + return -ENOMEM; + + func->function.name = "Function FS Gadget"; + func->function.strings = ffs->stringtabs; + + func->function.bind = ffs_func_bind; + func->function.unbind = ffs_func_unbind; + func->function.set_alt = ffs_func_set_alt; + func->function.disable = ffs_func_disable; + func->function.setup = ffs_func_setup; + func->function.suspend = ffs_func_suspend; + func->function.resume = ffs_func_resume; + + func->conf = c; + func->gadget = cdev->gadget; + func->ffs = ffs; + ffs_data_get(ffs); + + ret = usb_add_function(c, &func->function); + if (unlikely(ret)) + ffs_func_free(func); + + return ret; +} + +static void ffs_func_free(struct ffs_function *func) +{ + struct ffs_ep *ep = func->eps; + unsigned count = func->ffs->eps_count; + unsigned long flags; + + ENTER(); + + /* cleanup after autoconfig */ + spin_lock_irqsave(&func->ffs->eps_lock, flags); + do { + if (ep->ep && ep->req) + usb_ep_free_request(ep->ep, ep->req); + ep->req = NULL; + ++ep; + } while (--count); + spin_unlock_irqrestore(&func->ffs->eps_lock, flags); + + ffs_data_put(func->ffs); + + kfree(func->eps); + /* + * eps and interfaces_nums are allocated in the same chunk so + * only one free is required. Descriptors are also allocated + * in the same chunk. + */ + + kfree(func); +} + +static void ffs_func_eps_disable(struct ffs_function *func) +{ + struct ffs_ep *ep = func->eps; + struct ffs_epfile *epfile = func->ffs->epfiles; + unsigned count = func->ffs->eps_count; + unsigned long flags; + + spin_lock_irqsave(&func->ffs->eps_lock, flags); + do { + /* pending requests get nuked */ + if (likely(ep->ep)) + usb_ep_disable(ep->ep); + epfile->ep = NULL; + + ++ep; + ++epfile; + } while (--count); + spin_unlock_irqrestore(&func->ffs->eps_lock, flags); +} + +static int ffs_func_eps_enable(struct ffs_function *func) +{ + struct ffs_data *ffs = func->ffs; + struct ffs_ep *ep = func->eps; + struct ffs_epfile *epfile = ffs->epfiles; + unsigned count = ffs->eps_count; + unsigned long flags; + int ret = 0; + + spin_lock_irqsave(&func->ffs->eps_lock, flags); + do { + struct usb_endpoint_descriptor *ds; + ds = ep->descs[ep->descs[1] ? 1 : 0]; + + ep->ep->driver_data = ep; + ep->ep->desc = ds; + ret = usb_ep_enable(ep->ep); + if (likely(!ret)) { + epfile->ep = ep; + epfile->in = usb_endpoint_dir_in(ds); + epfile->isoc = usb_endpoint_xfer_isoc(ds); + } else { + break; + } + + wake_up(&epfile->wait); + + ++ep; + ++epfile; + } while (--count); + spin_unlock_irqrestore(&func->ffs->eps_lock, flags); + + return ret; +} + + +/* Parsing and building descriptors and strings *****************************/ + +/* + * This validates if data pointed by data is a valid USB descriptor as + * well as record how many interfaces, endpoints and strings are + * required by given configuration. Returns address after the + * descriptor or NULL if data is invalid. + */ + +enum ffs_entity_type { + FFS_DESCRIPTOR, FFS_INTERFACE, FFS_STRING, FFS_ENDPOINT +}; + +typedef int (*ffs_entity_callback)(enum ffs_entity_type entity, + u8 *valuep, + struct usb_descriptor_header *desc, + void *priv); + +static int __must_check ffs_do_desc(char *data, unsigned len, + ffs_entity_callback entity, void *priv) +{ + struct usb_descriptor_header *_ds = (void *)data; + u8 length; + int ret; + + ENTER(); + + /* At least two bytes are required: length and type */ + if (len < 2) { + pr_vdebug("descriptor too short\n"); + return -EINVAL; + } + + /* If we have at least as many bytes as the descriptor takes? */ + length = _ds->bLength; + if (len < length) { + pr_vdebug("descriptor longer then available data\n"); + return -EINVAL; + } + +#define __entity_check_INTERFACE(val) 1 +#define __entity_check_STRING(val) (val) +#define __entity_check_ENDPOINT(val) ((val) & USB_ENDPOINT_NUMBER_MASK) +#define __entity(type, val) do { \ + pr_vdebug("entity " #type "(%02x)\n", (val)); \ + if (unlikely(!__entity_check_ ##type(val))) { \ + pr_vdebug("invalid entity's value\n"); \ + return -EINVAL; \ + } \ + ret = entity(FFS_ ##type, &val, _ds, priv); \ + if (unlikely(ret < 0)) { \ + pr_debug("entity " #type "(%02x); ret = %d\n", \ + (val), ret); \ + return ret; \ + } \ + } while (0) + + /* Parse descriptor depending on type. */ + switch (_ds->bDescriptorType) { + case USB_DT_DEVICE: + case USB_DT_CONFIG: + case USB_DT_STRING: + case USB_DT_DEVICE_QUALIFIER: + /* function can't have any of those */ + pr_vdebug("descriptor reserved for gadget: %d\n", + _ds->bDescriptorType); + return -EINVAL; + + case USB_DT_INTERFACE: { + struct usb_interface_descriptor *ds = (void *)_ds; + pr_vdebug("interface descriptor\n"); + if (length != sizeof *ds) + goto inv_length; + + __entity(INTERFACE, ds->bInterfaceNumber); + if (ds->iInterface) + __entity(STRING, ds->iInterface); + } + break; + + case USB_DT_ENDPOINT: { + struct usb_endpoint_descriptor *ds = (void *)_ds; + pr_vdebug("endpoint descriptor\n"); + if (length != USB_DT_ENDPOINT_SIZE && + length != USB_DT_ENDPOINT_AUDIO_SIZE) + goto inv_length; + __entity(ENDPOINT, ds->bEndpointAddress); + } + break; + + case HID_DT_HID: + pr_vdebug("hid descriptor\n"); + if (length != sizeof(struct hid_descriptor)) + goto inv_length; + break; + + case USB_DT_OTG: + if (length != sizeof(struct usb_otg_descriptor)) + goto inv_length; + break; + + case USB_DT_INTERFACE_ASSOCIATION: { + struct usb_interface_assoc_descriptor *ds = (void *)_ds; + pr_vdebug("interface association descriptor\n"); + if (length != sizeof *ds) + goto inv_length; + if (ds->iFunction) + __entity(STRING, ds->iFunction); + } + break; + + case USB_DT_OTHER_SPEED_CONFIG: + case USB_DT_INTERFACE_POWER: + case USB_DT_DEBUG: + case USB_DT_SECURITY: + case USB_DT_CS_RADIO_CONTROL: + /* TODO */ + pr_vdebug("unimplemented descriptor: %d\n", _ds->bDescriptorType); + return -EINVAL; + + default: + /* We should never be here */ + pr_vdebug("unknown descriptor: %d\n", _ds->bDescriptorType); + return -EINVAL; + +inv_length: + pr_vdebug("invalid length: %d (descriptor %d)\n", + _ds->bLength, _ds->bDescriptorType); + return -EINVAL; + } + +#undef __entity +#undef __entity_check_DESCRIPTOR +#undef __entity_check_INTERFACE +#undef __entity_check_STRING +#undef __entity_check_ENDPOINT + + return length; +} + +static int __must_check ffs_do_descs(unsigned count, char *data, unsigned len, + ffs_entity_callback entity, void *priv) +{ + const unsigned _len = len; + unsigned long num = 0; + + ENTER(); + + for (;;) { + int ret; + + if (num == count) + data = NULL; + + /* Record "descriptor" entity */ + ret = entity(FFS_DESCRIPTOR, (u8 *)num, (void *)data, priv); + if (unlikely(ret < 0)) { + pr_debug("entity DESCRIPTOR(%02lx); ret = %d\n", + num, ret); + return ret; + } + + if (!data) + return _len - len; + + ret = ffs_do_desc(data, len, entity, priv); + if (unlikely(ret < 0)) { + pr_debug("%s returns %d\n", __func__, ret); + return ret; + } + + len -= ret; + data += ret; + ++num; + } +} + +static int __ffs_data_do_entity(enum ffs_entity_type type, + u8 *valuep, struct usb_descriptor_header *desc, + void *priv) +{ + struct ffs_data *ffs = priv; + + ENTER(); + + switch (type) { + case FFS_DESCRIPTOR: + break; + + case FFS_INTERFACE: + /* + * Interfaces are indexed from zero so if we + * encountered interface "n" then there are at least + * "n+1" interfaces. + */ + if (*valuep >= ffs->interfaces_count) + ffs->interfaces_count = *valuep + 1; + break; + + case FFS_STRING: + /* + * Strings are indexed from 1 (0 is magic ;) reserved + * for languages list or some such) + */ + if (*valuep > ffs->strings_count) + ffs->strings_count = *valuep; + break; + + case FFS_ENDPOINT: + /* Endpoints are indexed from 1 as well. */ + if ((*valuep & USB_ENDPOINT_NUMBER_MASK) > ffs->eps_count) + ffs->eps_count = (*valuep & USB_ENDPOINT_NUMBER_MASK); + break; + } + + return 0; +} + +static int __ffs_data_got_descs(struct ffs_data *ffs, + char *const _data, size_t len) +{ + unsigned fs_count, hs_count; + int fs_len, ret = -EINVAL; + char *data = _data; + + ENTER(); + + if (unlikely(get_unaligned_le32(data) != FUNCTIONFS_DESCRIPTORS_MAGIC || + get_unaligned_le32(data + 4) != len)) + goto error; + fs_count = get_unaligned_le32(data + 8); + hs_count = get_unaligned_le32(data + 12); + + if (!fs_count && !hs_count) + goto einval; + + data += 16; + len -= 16; + + if (likely(fs_count)) { + fs_len = ffs_do_descs(fs_count, data, len, + __ffs_data_do_entity, ffs); + if (unlikely(fs_len < 0)) { + ret = fs_len; + goto error; + } + + data += fs_len; + len -= fs_len; + } else { + fs_len = 0; + } + + if (likely(hs_count)) { + ret = ffs_do_descs(hs_count, data, len, + __ffs_data_do_entity, ffs); + if (unlikely(ret < 0)) + goto error; + } else { + ret = 0; + } + + if (unlikely(len != ret)) + goto einval; + + ffs->raw_fs_descs_length = fs_len; + ffs->raw_descs_length = fs_len + ret; + ffs->raw_descs = _data; + ffs->fs_descs_count = fs_count; + ffs->hs_descs_count = hs_count; + + return 0; + +einval: + ret = -EINVAL; +error: + kfree(_data); + return ret; +} + +static int __ffs_data_got_strings(struct ffs_data *ffs, + char *const _data, size_t len) +{ + u32 str_count, needed_count, lang_count; + struct usb_gadget_strings **stringtabs, *t; + struct usb_string *strings, *s; + const char *data = _data; + + ENTER(); + + if (unlikely(get_unaligned_le32(data) != FUNCTIONFS_STRINGS_MAGIC || + get_unaligned_le32(data + 4) != len)) + goto error; + str_count = get_unaligned_le32(data + 8); + lang_count = get_unaligned_le32(data + 12); + + /* if one is zero the other must be zero */ + if (unlikely(!str_count != !lang_count)) + goto error; + + /* Do we have at least as many strings as descriptors need? */ + needed_count = ffs->strings_count; + if (unlikely(str_count < needed_count)) + goto error; + + /* + * If we don't need any strings just return and free all + * memory. + */ + if (!needed_count) { + kfree(_data); + return 0; + } + + /* Allocate everything in one chunk so there's less maintenance. */ + { + struct { + struct usb_gadget_strings *stringtabs[lang_count + 1]; + struct usb_gadget_strings stringtab[lang_count]; + struct usb_string strings[lang_count*(needed_count+1)]; + } *d; + unsigned i = 0; + + d = kmalloc(sizeof *d, GFP_KERNEL); + if (unlikely(!d)) { + kfree(_data); + return -ENOMEM; + } + + stringtabs = d->stringtabs; + t = d->stringtab; + i = lang_count; + do { + *stringtabs++ = t++; + } while (--i); + *stringtabs = NULL; + + stringtabs = d->stringtabs; + t = d->stringtab; + s = d->strings; + strings = s; + } + + /* For each language */ + data += 16; + len -= 16; + + do { /* lang_count > 0 so we can use do-while */ + unsigned needed = needed_count; + + if (unlikely(len < 3)) + goto error_free; + t->language = get_unaligned_le16(data); + t->strings = s; + ++t; + + data += 2; + len -= 2; + + /* For each string */ + do { /* str_count > 0 so we can use do-while */ + size_t length = strnlen(data, len); + + if (unlikely(length == len)) + goto error_free; + + /* + * User may provide more strings then we need, + * if that's the case we simply ignore the + * rest + */ + if (likely(needed)) { + /* + * s->id will be set while adding + * function to configuration so for + * now just leave garbage here. + */ + s->s = data; + --needed; + ++s; + } + + data += length + 1; + len -= length + 1; + } while (--str_count); + + s->id = 0; /* terminator */ + s->s = NULL; + ++s; + + } while (--lang_count); + + /* Some garbage left? */ + if (unlikely(len)) + goto error_free; + + /* Done! */ + ffs->stringtabs = stringtabs; + ffs->raw_strings = _data; + + return 0; + +error_free: + kfree(stringtabs); +error: + kfree(_data); + return -EINVAL; +} + + +/* Events handling and management *******************************************/ + +static void __ffs_event_add(struct ffs_data *ffs, + enum usb_functionfs_event_type type) +{ + enum usb_functionfs_event_type rem_type1, rem_type2 = type; + int neg = 0; + + /* + * Abort any unhandled setup + * + * We do not need to worry about some cmpxchg() changing value + * of ffs->setup_state without holding the lock because when + * state is FFS_SETUP_PENDING cmpxchg() in several places in + * the source does nothing. + */ + if (ffs->setup_state == FFS_SETUP_PENDING) + ffs->setup_state = FFS_SETUP_CANCELED; + + switch (type) { + case FUNCTIONFS_RESUME: + rem_type2 = FUNCTIONFS_SUSPEND; + /* FALL THROUGH */ + case FUNCTIONFS_SUSPEND: + case FUNCTIONFS_SETUP: + rem_type1 = type; + /* Discard all similar events */ + break; + + case FUNCTIONFS_BIND: + case FUNCTIONFS_UNBIND: + case FUNCTIONFS_DISABLE: + case FUNCTIONFS_ENABLE: + /* Discard everything other then power management. */ + rem_type1 = FUNCTIONFS_SUSPEND; + rem_type2 = FUNCTIONFS_RESUME; + neg = 1; + break; + + default: + BUG(); + } + + { + u8 *ev = ffs->ev.types, *out = ev; + unsigned n = ffs->ev.count; + for (; n; --n, ++ev) + if ((*ev == rem_type1 || *ev == rem_type2) == neg) + *out++ = *ev; + else + pr_vdebug("purging event %d\n", *ev); + ffs->ev.count = out - ffs->ev.types; + } + + pr_vdebug("adding event %d\n", type); + ffs->ev.types[ffs->ev.count++] = type; + wake_up_locked(&ffs->ev.waitq); +} + +static void ffs_event_add(struct ffs_data *ffs, + enum usb_functionfs_event_type type) +{ + unsigned long flags; + spin_lock_irqsave(&ffs->ev.waitq.lock, flags); + __ffs_event_add(ffs, type); + spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags); +} + + +/* Bind/unbind USB function hooks *******************************************/ + +static int __ffs_func_bind_do_descs(enum ffs_entity_type type, u8 *valuep, + struct usb_descriptor_header *desc, + void *priv) +{ + struct usb_endpoint_descriptor *ds = (void *)desc; + struct ffs_function *func = priv; + struct ffs_ep *ffs_ep; + + /* + * If hs_descriptors is not NULL then we are reading hs + * descriptors now + */ + const int isHS = func->function.hs_descriptors != NULL; + unsigned idx; + + if (type != FFS_DESCRIPTOR) + return 0; + + if (isHS) + func->function.hs_descriptors[(long)valuep] = desc; + else + func->function.descriptors[(long)valuep] = desc; + + if (!desc || desc->bDescriptorType != USB_DT_ENDPOINT) + return 0; + + idx = (ds->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK) - 1; + ffs_ep = func->eps + idx; + + if (unlikely(ffs_ep->descs[isHS])) { + pr_vdebug("two %sspeed descriptors for EP %d\n", + isHS ? "high" : "full", + ds->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + return -EINVAL; + } + ffs_ep->descs[isHS] = ds; + + ffs_dump_mem(": Original ep desc", ds, ds->bLength); + if (ffs_ep->ep) { + ds->bEndpointAddress = ffs_ep->descs[0]->bEndpointAddress; + if (!ds->wMaxPacketSize) + ds->wMaxPacketSize = ffs_ep->descs[0]->wMaxPacketSize; + } else { + struct usb_request *req; + struct usb_ep *ep; + + pr_vdebug("autoconfig\n"); + ep = usb_ep_autoconfig(func->gadget, ds); + if (unlikely(!ep)) + return -ENOTSUPP; + ep->driver_data = func->eps + idx; + + req = usb_ep_alloc_request(ep, GFP_KERNEL); + if (unlikely(!req)) + return -ENOMEM; + + ffs_ep->ep = ep; + ffs_ep->req = req; + func->eps_revmap[ds->bEndpointAddress & + USB_ENDPOINT_NUMBER_MASK] = idx + 1; + } + ffs_dump_mem(": Rewritten ep desc", ds, ds->bLength); + + return 0; +} + +static int __ffs_func_bind_do_nums(enum ffs_entity_type type, u8 *valuep, + struct usb_descriptor_header *desc, + void *priv) +{ + struct ffs_function *func = priv; + unsigned idx; + u8 newValue; + + switch (type) { + default: + case FFS_DESCRIPTOR: + /* Handled in previous pass by __ffs_func_bind_do_descs() */ + return 0; + + case FFS_INTERFACE: + idx = *valuep; + if (func->interfaces_nums[idx] < 0) { + int id = usb_interface_id(func->conf, &func->function); + if (unlikely(id < 0)) + return id; + func->interfaces_nums[idx] = id; + } + newValue = func->interfaces_nums[idx]; + break; + + case FFS_STRING: + /* String' IDs are allocated when fsf_data is bound to cdev */ + newValue = func->ffs->stringtabs[0]->strings[*valuep - 1].id; + break; + + case FFS_ENDPOINT: + /* + * USB_DT_ENDPOINT are handled in + * __ffs_func_bind_do_descs(). + */ + if (desc->bDescriptorType == USB_DT_ENDPOINT) + return 0; + + idx = (*valuep & USB_ENDPOINT_NUMBER_MASK) - 1; + if (unlikely(!func->eps[idx].ep)) + return -EINVAL; + + { + struct usb_endpoint_descriptor **descs; + descs = func->eps[idx].descs; + newValue = descs[descs[0] ? 0 : 1]->bEndpointAddress; + } + break; + } + + pr_vdebug("%02x -> %02x\n", *valuep, newValue); + *valuep = newValue; + return 0; +} + +static int ffs_func_bind(struct usb_configuration *c, + struct usb_function *f) +{ + struct ffs_function *func = ffs_func_from_usb(f); + struct ffs_data *ffs = func->ffs; + + const int full = !!func->ffs->fs_descs_count; + const int high = gadget_is_dualspeed(func->gadget) && + func->ffs->hs_descs_count; + + int ret; + + /* Make it a single chunk, less management later on */ + struct { + struct ffs_ep eps[ffs->eps_count]; + struct usb_descriptor_header + *fs_descs[full ? ffs->fs_descs_count + 1 : 0]; + struct usb_descriptor_header + *hs_descs[high ? ffs->hs_descs_count + 1 : 0]; + short inums[ffs->interfaces_count]; + char raw_descs[high ? ffs->raw_descs_length + : ffs->raw_fs_descs_length]; + } *data; + + ENTER(); + + /* Only high speed but not supported by gadget? */ + if (unlikely(!(full | high))) + return -ENOTSUPP; + + /* Allocate */ + data = kmalloc(sizeof *data, GFP_KERNEL); + if (unlikely(!data)) + return -ENOMEM; + + /* Zero */ + memset(data->eps, 0, sizeof data->eps); + memcpy(data->raw_descs, ffs->raw_descs + 16, sizeof data->raw_descs); + memset(data->inums, 0xff, sizeof data->inums); + for (ret = ffs->eps_count; ret; --ret) + data->eps[ret].num = -1; + + /* Save pointers */ + func->eps = data->eps; + func->interfaces_nums = data->inums; + + /* + * Go through all the endpoint descriptors and allocate + * endpoints first, so that later we can rewrite the endpoint + * numbers without worrying that it may be described later on. + */ + if (likely(full)) { + func->function.descriptors = data->fs_descs; + ret = ffs_do_descs(ffs->fs_descs_count, + data->raw_descs, + sizeof data->raw_descs, + __ffs_func_bind_do_descs, func); + if (unlikely(ret < 0)) + goto error; + } else { + ret = 0; + } + + if (likely(high)) { + func->function.hs_descriptors = data->hs_descs; + ret = ffs_do_descs(ffs->hs_descs_count, + data->raw_descs + ret, + (sizeof data->raw_descs) - ret, + __ffs_func_bind_do_descs, func); + } + + /* + * Now handle interface numbers allocation and interface and + * endpoint numbers rewriting. We can do that in one go + * now. + */ + ret = ffs_do_descs(ffs->fs_descs_count + + (high ? ffs->hs_descs_count : 0), + data->raw_descs, sizeof data->raw_descs, + __ffs_func_bind_do_nums, func); + if (unlikely(ret < 0)) + goto error; + + /* And we're done */ + ffs_event_add(ffs, FUNCTIONFS_BIND); + return 0; + +error: + /* XXX Do we need to release all claimed endpoints here? */ + return ret; +} + + +/* Other USB function hooks *************************************************/ + +static void ffs_func_unbind(struct usb_configuration *c, + struct usb_function *f) +{ + struct ffs_function *func = ffs_func_from_usb(f); + struct ffs_data *ffs = func->ffs; + + ENTER(); + + if (ffs->func == func) { + ffs_func_eps_disable(func); + ffs->func = NULL; + } + + ffs_event_add(ffs, FUNCTIONFS_UNBIND); + + ffs_func_free(func); +} + +static int ffs_func_set_alt(struct usb_function *f, + unsigned interface, unsigned alt) +{ + struct ffs_function *func = ffs_func_from_usb(f); + struct ffs_data *ffs = func->ffs; + int ret = 0, intf; + + if (alt != (unsigned)-1) { + intf = ffs_func_revmap_intf(func, interface); + if (unlikely(intf < 0)) + return intf; + } + + if (ffs->func) + ffs_func_eps_disable(ffs->func); + + if (ffs->state != FFS_ACTIVE) + return -ENODEV; + + if (alt == (unsigned)-1) { + ffs->func = NULL; + ffs_event_add(ffs, FUNCTIONFS_DISABLE); + return 0; + } + + ffs->func = func; + ret = ffs_func_eps_enable(func); + if (likely(ret >= 0)) + ffs_event_add(ffs, FUNCTIONFS_ENABLE); + return ret; +} + +static void ffs_func_disable(struct usb_function *f) +{ + ffs_func_set_alt(f, 0, (unsigned)-1); +} + +static int ffs_func_setup(struct usb_function *f, + const struct usb_ctrlrequest *creq) +{ + struct ffs_function *func = ffs_func_from_usb(f); + struct ffs_data *ffs = func->ffs; + unsigned long flags; + int ret; + + ENTER(); + + pr_vdebug("creq->bRequestType = %02x\n", creq->bRequestType); + pr_vdebug("creq->bRequest = %02x\n", creq->bRequest); + pr_vdebug("creq->wValue = %04x\n", le16_to_cpu(creq->wValue)); + pr_vdebug("creq->wIndex = %04x\n", le16_to_cpu(creq->wIndex)); + pr_vdebug("creq->wLength = %04x\n", le16_to_cpu(creq->wLength)); + + /* + * Most requests directed to interface go through here + * (notable exceptions are set/get interface) so we need to + * handle them. All other either handled by composite or + * passed to usb_configuration->setup() (if one is set). No + * matter, we will handle requests directed to endpoint here + * as well (as it's straightforward) but what to do with any + * other request? + */ + if (ffs->state != FFS_ACTIVE) + return -ENODEV; + + switch (creq->bRequestType & USB_RECIP_MASK) { + case USB_RECIP_INTERFACE: + ret = ffs_func_revmap_intf(func, le16_to_cpu(creq->wIndex)); + if (unlikely(ret < 0)) + return ret; + break; + + case USB_RECIP_ENDPOINT: + ret = ffs_func_revmap_ep(func, le16_to_cpu(creq->wIndex)); + if (unlikely(ret < 0)) + return ret; + break; + + default: + return -EOPNOTSUPP; + } + + spin_lock_irqsave(&ffs->ev.waitq.lock, flags); + ffs->ev.setup = *creq; + ffs->ev.setup.wIndex = cpu_to_le16(ret); + __ffs_event_add(ffs, FUNCTIONFS_SETUP); + spin_unlock_irqrestore(&ffs->ev.waitq.lock, flags); + + return 0; +} + +static void ffs_func_suspend(struct usb_function *f) +{ + ENTER(); + ffs_event_add(ffs_func_from_usb(f)->ffs, FUNCTIONFS_SUSPEND); +} + +static void ffs_func_resume(struct usb_function *f) +{ + ENTER(); + ffs_event_add(ffs_func_from_usb(f)->ffs, FUNCTIONFS_RESUME); +} + + +/* Endpoint and interface numbers reverse mapping ***************************/ + +static int ffs_func_revmap_ep(struct ffs_function *func, u8 num) +{ + num = func->eps_revmap[num & USB_ENDPOINT_NUMBER_MASK]; + return num ? num : -EDOM; +} + +static int ffs_func_revmap_intf(struct ffs_function *func, u8 intf) +{ + short *nums = func->interfaces_nums; + unsigned count = func->ffs->interfaces_count; + + for (; count; --count, ++nums) { + if (*nums >= 0 && *nums == intf) + return nums - func->interfaces_nums; + } + + return -EDOM; +} + + +/* Misc helper functions ****************************************************/ + +static int ffs_mutex_lock(struct mutex *mutex, unsigned nonblock) +{ + return nonblock + ? likely(mutex_trylock(mutex)) ? 0 : -EAGAIN + : mutex_lock_interruptible(mutex); +} + +static char *ffs_prepare_buffer(const char * __user buf, size_t len) +{ + char *data; + + if (unlikely(!len)) + return NULL; + + data = kmalloc(len, GFP_KERNEL); + if (unlikely(!data)) + return ERR_PTR(-ENOMEM); + + if (unlikely(__copy_from_user(data, buf, len))) { + kfree(data); + return ERR_PTR(-EFAULT); + } + + pr_vdebug("Buffer from user space:\n"); + ffs_dump_mem("", data, len); + + return data; +} diff --git a/drivers/staging/ccg/f_mass_storage.c b/drivers/staging/ccg/f_mass_storage.c new file mode 100644 index 0000000..4f1142e --- /dev/null +++ b/drivers/staging/ccg/f_mass_storage.c @@ -0,0 +1,3135 @@ +/* + * f_mass_storage.c -- Mass Storage USB Composite Function + * + * Copyright (C) 2003-2008 Alan Stern + * Copyright (C) 2009 Samsung Electronics + * Author: Michal Nazarewicz + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the above-listed copyright holders may not be used + * to endorse or promote products derived from this software without + * specific prior written permission. + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * The Mass Storage Function acts as a USB Mass Storage device, + * appearing to the host as a disk drive or as a CD-ROM drive. In + * addition to providing an example of a genuinely useful composite + * function for a USB device, it also illustrates a technique of + * double-buffering for increased throughput. + * + * For more information about MSF and in particular its module + * parameters and sysfs interface read the + * file. + */ + +/* + * MSF is configured by specifying a fsg_config structure. It has the + * following fields: + * + * nluns Number of LUNs function have (anywhere from 1 + * to FSG_MAX_LUNS which is 8). + * luns An array of LUN configuration values. This + * should be filled for each LUN that + * function will include (ie. for "nluns" + * LUNs). Each element of the array has + * the following fields: + * ->filename The path to the backing file for the LUN. + * Required if LUN is not marked as + * removable. + * ->ro Flag specifying access to the LUN shall be + * read-only. This is implied if CD-ROM + * emulation is enabled as well as when + * it was impossible to open "filename" + * in R/W mode. + * ->removable Flag specifying that LUN shall be indicated as + * being removable. + * ->cdrom Flag specifying that LUN shall be reported as + * being a CD-ROM. + * ->nofua Flag specifying that FUA flag in SCSI WRITE(10,12) + * commands for this LUN shall be ignored. + * + * vendor_name + * product_name + * release Information used as a reply to INQUIRY + * request. To use default set to NULL, + * NULL, 0xffff respectively. The first + * field should be 8 and the second 16 + * characters or less. + * + * can_stall Set to permit function to halt bulk endpoints. + * Disabled on some USB devices known not + * to work correctly. You should set it + * to true. + * + * If "removable" is not set for a LUN then a backing file must be + * specified. If it is set, then NULL filename means the LUN's medium + * is not loaded (an empty string as "filename" in the fsg_config + * structure causes error). The CD-ROM emulation includes a single + * data track and no audio tracks; hence there need be only one + * backing file per LUN. + * + * This function is heavily based on "File-backed Storage Gadget" by + * Alan Stern which in turn is heavily based on "Gadget Zero" by David + * Brownell. The driver's SCSI command interface was based on the + * "Information technology - Small Computer System Interface - 2" + * document from X3T9.2 Project 375D, Revision 10L, 7-SEP-93, + * available at . + * The single exception is opcode 0x23 (READ FORMAT CAPACITIES), which + * was based on the "Universal Serial Bus Mass Storage Class UFI + * Command Specification" document, Revision 1.0, December 14, 1998, + * available at + * . + */ + +/* + * Driver Design + * + * The MSF is fairly straightforward. There is a main kernel + * thread that handles most of the work. Interrupt routines field + * callbacks from the controller driver: bulk- and interrupt-request + * completion notifications, endpoint-0 events, and disconnect events. + * Completion events are passed to the main thread by wakeup calls. Many + * ep0 requests are handled at interrupt time, but SetInterface, + * SetConfiguration, and device reset requests are forwarded to the + * thread in the form of "exceptions" using SIGUSR1 signals (since they + * should interrupt any ongoing file I/O operations). + * + * The thread's main routine implements the standard command/data/status + * parts of a SCSI interaction. It and its subroutines are full of tests + * for pending signals/exceptions -- all this polling is necessary since + * the kernel has no setjmp/longjmp equivalents. (Maybe this is an + * indication that the driver really wants to be running in userspace.) + * An important point is that so long as the thread is alive it keeps an + * open reference to the backing file. This will prevent unmounting + * the backing file's underlying filesystem and could cause problems + * during system shutdown, for example. To prevent such problems, the + * thread catches INT, TERM, and KILL signals and converts them into + * an EXIT exception. + * + * In normal operation the main thread is started during the gadget's + * fsg_bind() callback and stopped during fsg_unbind(). But it can + * also exit when it receives a signal, and there's no point leaving + * the gadget running when the thread is dead. As of this moment, MSF + * provides no way to deregister the gadget when thread dies -- maybe + * a callback functions is needed. + * + * To provide maximum throughput, the driver uses a circular pipeline of + * buffer heads (struct fsg_buffhd). In principle the pipeline can be + * arbitrarily long; in practice the benefits don't justify having more + * than 2 stages (i.e., double buffering). But it helps to think of the + * pipeline as being a long one. Each buffer head contains a bulk-in and + * a bulk-out request pointer (since the buffer can be used for both + * output and input -- directions always are given from the host's + * point of view) as well as a pointer to the buffer and various state + * variables. + * + * Use of the pipeline follows a simple protocol. There is a variable + * (fsg->next_buffhd_to_fill) that points to the next buffer head to use. + * At any time that buffer head may still be in use from an earlier + * request, so each buffer head has a state variable indicating whether + * it is EMPTY, FULL, or BUSY. Typical use involves waiting for the + * buffer head to be EMPTY, filling the buffer either by file I/O or by + * USB I/O (during which the buffer head is BUSY), and marking the buffer + * head FULL when the I/O is complete. Then the buffer will be emptied + * (again possibly by USB I/O, during which it is marked BUSY) and + * finally marked EMPTY again (possibly by a completion routine). + * + * A module parameter tells the driver to avoid stalling the bulk + * endpoints wherever the transport specification allows. This is + * necessary for some UDCs like the SuperH, which cannot reliably clear a + * halt on a bulk endpoint. However, under certain circumstances the + * Bulk-only specification requires a stall. In such cases the driver + * will halt the endpoint and set a flag indicating that it should clear + * the halt in software during the next device reset. Hopefully this + * will permit everything to work correctly. Furthermore, although the + * specification allows the bulk-out endpoint to halt when the host sends + * too much data, implementing this would cause an unavoidable race. + * The driver will always use the "no-stall" approach for OUT transfers. + * + * One subtle point concerns sending status-stage responses for ep0 + * requests. Some of these requests, such as device reset, can involve + * interrupting an ongoing file I/O operation, which might take an + * arbitrarily long time. During that delay the host might give up on + * the original ep0 request and issue a new one. When that happens the + * driver should not notify the host about completion of the original + * request, as the host will no longer be waiting for it. So the driver + * assigns to each ep0 request a unique tag, and it keeps track of the + * tag value of the request associated with a long-running exception + * (device-reset, interface-change, or configuration-change). When the + * exception handler is finished, the status-stage response is submitted + * only if the current ep0 request tag is equal to the exception request + * tag. Thus only the most recently received ep0 request will get a + * status-stage response. + * + * Warning: This driver source file is too long. It ought to be split up + * into a header file plus about 3 separate .c files, to handle the details + * of the Gadget, USB Mass Storage, and SCSI protocols. + */ + + +/* #define VERBOSE_DEBUG */ +/* #define DUMP_MSGS */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "gadget_chips.h" + + +/*------------------------------------------------------------------------*/ + +#define FSG_DRIVER_DESC "Mass Storage Function" +#define FSG_DRIVER_VERSION "2009/09/11" + +static const char fsg_string_interface[] = "Mass Storage"; + +#define FSG_NO_DEVICE_STRINGS 1 +#define FSG_NO_OTG 1 +#define FSG_NO_INTR_EP 1 + +#include "storage_common.c" + + +/*-------------------------------------------------------------------------*/ + +struct fsg_dev; +struct fsg_common; + +/* FSF callback functions */ +struct fsg_operations { + /* + * Callback function to call when thread exits. If no + * callback is set or it returns value lower then zero MSF + * will force eject all LUNs it operates on (including those + * marked as non-removable or with prevent_medium_removal flag + * set). + */ + int (*thread_exits)(struct fsg_common *common); + + /* + * Called prior to ejection. Negative return means error, + * zero means to continue with ejection, positive means not to + * eject. + */ + int (*pre_eject)(struct fsg_common *common, + struct fsg_lun *lun, int num); + /* + * Called after ejection. Negative return means error, zero + * or positive is just a success. + */ + int (*post_eject)(struct fsg_common *common, + struct fsg_lun *lun, int num); +}; + +/* Data shared by all the FSG instances. */ +struct fsg_common { + struct usb_gadget *gadget; + struct usb_composite_dev *cdev; + struct fsg_dev *fsg, *new_fsg; + wait_queue_head_t fsg_wait; + + /* filesem protects: backing files in use */ + struct rw_semaphore filesem; + + /* lock protects: state, all the req_busy's */ + spinlock_t lock; + + struct usb_ep *ep0; /* Copy of gadget->ep0 */ + struct usb_request *ep0req; /* Copy of cdev->req */ + unsigned int ep0_req_tag; + + struct fsg_buffhd *next_buffhd_to_fill; + struct fsg_buffhd *next_buffhd_to_drain; + struct fsg_buffhd *buffhds; + + int cmnd_size; + u8 cmnd[MAX_COMMAND_SIZE]; + + unsigned int nluns; + unsigned int lun; + struct fsg_lun *luns; + struct fsg_lun *curlun; + + unsigned int bulk_out_maxpacket; + enum fsg_state state; /* For exception handling */ + unsigned int exception_req_tag; + + enum data_direction data_dir; + u32 data_size; + u32 data_size_from_cmnd; + u32 tag; + u32 residue; + u32 usb_amount_left; + + unsigned int can_stall:1; + unsigned int free_storage_on_release:1; + unsigned int phase_error:1; + unsigned int short_packet_received:1; + unsigned int bad_lun_okay:1; + unsigned int running:1; + + int thread_wakeup_needed; + struct completion thread_notifier; + struct task_struct *thread_task; + + /* Callback functions. */ + const struct fsg_operations *ops; + /* Gadget's private data. */ + void *private_data; + + /* + * Vendor (8 chars), product (16 chars), release (4 + * hexadecimal digits) and NUL byte + */ + char inquiry_string[8 + 16 + 4 + 1]; + + struct kref ref; +}; + +struct fsg_config { + unsigned nluns; + struct fsg_lun_config { + const char *filename; + char ro; + char removable; + char cdrom; + char nofua; + } luns[FSG_MAX_LUNS]; + + /* Callback functions. */ + const struct fsg_operations *ops; + /* Gadget's private data. */ + void *private_data; + + const char *vendor_name; /* 8 characters or less */ + const char *product_name; /* 16 characters or less */ + u16 release; + + char can_stall; +}; + +struct fsg_dev { + struct usb_function function; + struct usb_gadget *gadget; /* Copy of cdev->gadget */ + struct fsg_common *common; + + u16 interface_number; + + unsigned int bulk_in_enabled:1; + unsigned int bulk_out_enabled:1; + + unsigned long atomic_bitflags; +#define IGNORE_BULK_OUT 0 + + struct usb_ep *bulk_in; + struct usb_ep *bulk_out; +}; + +static inline int __fsg_is_set(struct fsg_common *common, + const char *func, unsigned line) +{ + if (common->fsg) + return 1; + ERROR(common, "common->fsg is NULL in %s at %u\n", func, line); + WARN_ON(1); + return 0; +} + +#define fsg_is_set(common) likely(__fsg_is_set(common, __func__, __LINE__)) + +static inline struct fsg_dev *fsg_from_func(struct usb_function *f) +{ + return container_of(f, struct fsg_dev, function); +} + +typedef void (*fsg_routine_t)(struct fsg_dev *); + +static int exception_in_progress(struct fsg_common *common) +{ + return common->state > FSG_STATE_IDLE; +} + +/* Make bulk-out requests be divisible by the maxpacket size */ +static void set_bulk_out_req_length(struct fsg_common *common, + struct fsg_buffhd *bh, unsigned int length) +{ + unsigned int rem; + + bh->bulk_out_intended_length = length; + rem = length % common->bulk_out_maxpacket; + if (rem > 0) + length += common->bulk_out_maxpacket - rem; + bh->outreq->length = length; +} + + +/*-------------------------------------------------------------------------*/ + +static int fsg_set_halt(struct fsg_dev *fsg, struct usb_ep *ep) +{ + const char *name; + + if (ep == fsg->bulk_in) + name = "bulk-in"; + else if (ep == fsg->bulk_out) + name = "bulk-out"; + else + name = ep->name; + DBG(fsg, "%s set halt\n", name); + return usb_ep_set_halt(ep); +} + + +/*-------------------------------------------------------------------------*/ + +/* These routines may be called in process context or in_irq */ + +/* Caller must hold fsg->lock */ +static void wakeup_thread(struct fsg_common *common) +{ + /* Tell the main thread that something has happened */ + common->thread_wakeup_needed = 1; + if (common->thread_task) + wake_up_process(common->thread_task); +} + +static void raise_exception(struct fsg_common *common, enum fsg_state new_state) +{ + unsigned long flags; + + /* + * Do nothing if a higher-priority exception is already in progress. + * If a lower-or-equal priority exception is in progress, preempt it + * and notify the main thread by sending it a signal. + */ + spin_lock_irqsave(&common->lock, flags); + if (common->state <= new_state) { + common->exception_req_tag = common->ep0_req_tag; + common->state = new_state; + if (common->thread_task) + send_sig_info(SIGUSR1, SEND_SIG_FORCED, + common->thread_task); + } + spin_unlock_irqrestore(&common->lock, flags); +} + + +/*-------------------------------------------------------------------------*/ + +static int ep0_queue(struct fsg_common *common) +{ + int rc; + + rc = usb_ep_queue(common->ep0, common->ep0req, GFP_ATOMIC); + common->ep0->driver_data = common; + if (rc != 0 && rc != -ESHUTDOWN) { + /* We can't do much more than wait for a reset */ + WARNING(common, "error in submission: %s --> %d\n", + common->ep0->name, rc); + } + return rc; +} + + +/*-------------------------------------------------------------------------*/ + +/* Completion handlers. These always run in_irq. */ + +static void bulk_in_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct fsg_common *common = ep->driver_data; + struct fsg_buffhd *bh = req->context; + + if (req->status || req->actual != req->length) + DBG(common, "%s --> %d, %u/%u\n", __func__, + req->status, req->actual, req->length); + if (req->status == -ECONNRESET) /* Request was cancelled */ + usb_ep_fifo_flush(ep); + + /* Hold the lock while we update the request and buffer states */ + smp_wmb(); + spin_lock(&common->lock); + bh->inreq_busy = 0; + bh->state = BUF_STATE_EMPTY; + wakeup_thread(common); + spin_unlock(&common->lock); +} + +static void bulk_out_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct fsg_common *common = ep->driver_data; + struct fsg_buffhd *bh = req->context; + + dump_msg(common, "bulk-out", req->buf, req->actual); + if (req->status || req->actual != bh->bulk_out_intended_length) + DBG(common, "%s --> %d, %u/%u\n", __func__, + req->status, req->actual, bh->bulk_out_intended_length); + if (req->status == -ECONNRESET) /* Request was cancelled */ + usb_ep_fifo_flush(ep); + + /* Hold the lock while we update the request and buffer states */ + smp_wmb(); + spin_lock(&common->lock); + bh->outreq_busy = 0; + bh->state = BUF_STATE_FULL; + wakeup_thread(common); + spin_unlock(&common->lock); +} + +static int fsg_setup(struct usb_function *f, + const struct usb_ctrlrequest *ctrl) +{ + struct fsg_dev *fsg = fsg_from_func(f); + struct usb_request *req = fsg->common->ep0req; + u16 w_index = le16_to_cpu(ctrl->wIndex); + u16 w_value = le16_to_cpu(ctrl->wValue); + u16 w_length = le16_to_cpu(ctrl->wLength); + + if (!fsg_is_set(fsg->common)) + return -EOPNOTSUPP; + + ++fsg->common->ep0_req_tag; /* Record arrival of a new request */ + req->context = NULL; + req->length = 0; + dump_msg(fsg, "ep0-setup", (u8 *) ctrl, sizeof(*ctrl)); + + switch (ctrl->bRequest) { + + case US_BULK_RESET_REQUEST: + if (ctrl->bRequestType != + (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) + break; + if (w_index != fsg->interface_number || w_value != 0 || + w_length != 0) + return -EDOM; + + /* + * Raise an exception to stop the current operation + * and reinitialize our state. + */ + DBG(fsg, "bulk reset request\n"); + raise_exception(fsg->common, FSG_STATE_RESET); + return DELAYED_STATUS; + + case US_BULK_GET_MAX_LUN: + if (ctrl->bRequestType != + (USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE)) + break; + if (w_index != fsg->interface_number || w_value != 0 || + w_length != 1) + return -EDOM; + VDBG(fsg, "get max LUN\n"); + *(u8 *)req->buf = fsg->common->nluns - 1; + + /* Respond with data/status */ + req->length = min((u16)1, w_length); + return ep0_queue(fsg->common); + } + + VDBG(fsg, + "unknown class-specific control req %02x.%02x v%04x i%04x l%u\n", + ctrl->bRequestType, ctrl->bRequest, + le16_to_cpu(ctrl->wValue), w_index, w_length); + return -EOPNOTSUPP; +} + + +/*-------------------------------------------------------------------------*/ + +/* All the following routines run in process context */ + +/* Use this for bulk or interrupt transfers, not ep0 */ +static void start_transfer(struct fsg_dev *fsg, struct usb_ep *ep, + struct usb_request *req, int *pbusy, + enum fsg_buffer_state *state) +{ + int rc; + + if (ep == fsg->bulk_in) + dump_msg(fsg, "bulk-in", req->buf, req->length); + + spin_lock_irq(&fsg->common->lock); + *pbusy = 1; + *state = BUF_STATE_BUSY; + spin_unlock_irq(&fsg->common->lock); + rc = usb_ep_queue(ep, req, GFP_KERNEL); + if (rc != 0) { + *pbusy = 0; + *state = BUF_STATE_EMPTY; + + /* We can't do much more than wait for a reset */ + + /* + * Note: currently the net2280 driver fails zero-length + * submissions if DMA is enabled. + */ + if (rc != -ESHUTDOWN && + !(rc == -EOPNOTSUPP && req->length == 0)) + WARNING(fsg, "error in submission: %s --> %d\n", + ep->name, rc); + } +} + +static bool start_in_transfer(struct fsg_common *common, struct fsg_buffhd *bh) +{ + if (!fsg_is_set(common)) + return false; + start_transfer(common->fsg, common->fsg->bulk_in, + bh->inreq, &bh->inreq_busy, &bh->state); + return true; +} + +static bool start_out_transfer(struct fsg_common *common, struct fsg_buffhd *bh) +{ + if (!fsg_is_set(common)) + return false; + start_transfer(common->fsg, common->fsg->bulk_out, + bh->outreq, &bh->outreq_busy, &bh->state); + return true; +} + +static int sleep_thread(struct fsg_common *common) +{ + int rc = 0; + + /* Wait until a signal arrives or we are woken up */ + for (;;) { + try_to_freeze(); + set_current_state(TASK_INTERRUPTIBLE); + if (signal_pending(current)) { + rc = -EINTR; + break; + } + if (common->thread_wakeup_needed) + break; + schedule(); + } + __set_current_state(TASK_RUNNING); + common->thread_wakeup_needed = 0; + return rc; +} + + +/*-------------------------------------------------------------------------*/ + +static int do_read(struct fsg_common *common) +{ + struct fsg_lun *curlun = common->curlun; + u32 lba; + struct fsg_buffhd *bh; + int rc; + u32 amount_left; + loff_t file_offset, file_offset_tmp; + unsigned int amount; + ssize_t nread; + + /* + * Get the starting Logical Block Address and check that it's + * not too big. + */ + if (common->cmnd[0] == READ_6) + lba = get_unaligned_be24(&common->cmnd[1]); + else { + lba = get_unaligned_be32(&common->cmnd[2]); + + /* + * We allow DPO (Disable Page Out = don't save data in the + * cache) and FUA (Force Unit Access = don't read from the + * cache), but we don't implement them. + */ + if ((common->cmnd[1] & ~0x18) != 0) { + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + } + if (lba >= curlun->num_sectors) { + curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + return -EINVAL; + } + file_offset = ((loff_t) lba) << curlun->blkbits; + + /* Carry out the file reads */ + amount_left = common->data_size_from_cmnd; + if (unlikely(amount_left == 0)) + return -EIO; /* No default reply */ + + for (;;) { + /* + * Figure out how much we need to read: + * Try to read the remaining amount. + * But don't read more than the buffer size. + * And don't try to read past the end of the file. + */ + amount = min(amount_left, FSG_BUFLEN); + amount = min((loff_t)amount, + curlun->file_length - file_offset); + + /* Wait for the next buffer to become available */ + bh = common->next_buffhd_to_fill; + while (bh->state != BUF_STATE_EMPTY) { + rc = sleep_thread(common); + if (rc) + return rc; + } + + /* + * If we were asked to read past the end of file, + * end with an empty buffer. + */ + if (amount == 0) { + curlun->sense_data = + SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + curlun->sense_data_info = + file_offset >> curlun->blkbits; + curlun->info_valid = 1; + bh->inreq->length = 0; + bh->state = BUF_STATE_FULL; + break; + } + + /* Perform the read */ + file_offset_tmp = file_offset; + nread = vfs_read(curlun->filp, + (char __user *)bh->buf, + amount, &file_offset_tmp); + VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, + (unsigned long long)file_offset, (int)nread); + if (signal_pending(current)) + return -EINTR; + + if (nread < 0) { + LDBG(curlun, "error in file read: %d\n", (int)nread); + nread = 0; + } else if (nread < amount) { + LDBG(curlun, "partial file read: %d/%u\n", + (int)nread, amount); + nread = round_down(nread, curlun->blksize); + } + file_offset += nread; + amount_left -= nread; + common->residue -= nread; + + /* + * Except at the end of the transfer, nread will be + * equal to the buffer size, which is divisible by the + * bulk-in maxpacket size. + */ + bh->inreq->length = nread; + bh->state = BUF_STATE_FULL; + + /* If an error occurred, report it and its position */ + if (nread < amount) { + curlun->sense_data = SS_UNRECOVERED_READ_ERROR; + curlun->sense_data_info = + file_offset >> curlun->blkbits; + curlun->info_valid = 1; + break; + } + + if (amount_left == 0) + break; /* No more left to read */ + + /* Send this buffer and go read some more */ + bh->inreq->zero = 0; + if (!start_in_transfer(common, bh)) + /* Don't know what to do if common->fsg is NULL */ + return -EIO; + common->next_buffhd_to_fill = bh->next; + } + + return -EIO; /* No default reply */ +} + + +/*-------------------------------------------------------------------------*/ + +static int do_write(struct fsg_common *common) +{ + struct fsg_lun *curlun = common->curlun; + u32 lba; + struct fsg_buffhd *bh; + int get_some_more; + u32 amount_left_to_req, amount_left_to_write; + loff_t usb_offset, file_offset, file_offset_tmp; + unsigned int amount; + ssize_t nwritten; + int rc; + + if (curlun->ro) { + curlun->sense_data = SS_WRITE_PROTECTED; + return -EINVAL; + } + spin_lock(&curlun->filp->f_lock); + curlun->filp->f_flags &= ~O_SYNC; /* Default is not to wait */ + spin_unlock(&curlun->filp->f_lock); + + /* + * Get the starting Logical Block Address and check that it's + * not too big + */ + if (common->cmnd[0] == WRITE_6) + lba = get_unaligned_be24(&common->cmnd[1]); + else { + lba = get_unaligned_be32(&common->cmnd[2]); + + /* + * We allow DPO (Disable Page Out = don't save data in the + * cache) and FUA (Force Unit Access = write directly to the + * medium). We don't implement DPO; we implement FUA by + * performing synchronous output. + */ + if (common->cmnd[1] & ~0x18) { + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + if (!curlun->nofua && (common->cmnd[1] & 0x08)) { /* FUA */ + spin_lock(&curlun->filp->f_lock); + curlun->filp->f_flags |= O_SYNC; + spin_unlock(&curlun->filp->f_lock); + } + } + if (lba >= curlun->num_sectors) { + curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + return -EINVAL; + } + + /* Carry out the file writes */ + get_some_more = 1; + file_offset = usb_offset = ((loff_t) lba) << curlun->blkbits; + amount_left_to_req = common->data_size_from_cmnd; + amount_left_to_write = common->data_size_from_cmnd; + + while (amount_left_to_write > 0) { + + /* Queue a request for more data from the host */ + bh = common->next_buffhd_to_fill; + if (bh->state == BUF_STATE_EMPTY && get_some_more) { + + /* + * Figure out how much we want to get: + * Try to get the remaining amount, + * but not more than the buffer size. + */ + amount = min(amount_left_to_req, FSG_BUFLEN); + + /* Beyond the end of the backing file? */ + if (usb_offset >= curlun->file_length) { + get_some_more = 0; + curlun->sense_data = + SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + curlun->sense_data_info = + usb_offset >> curlun->blkbits; + curlun->info_valid = 1; + continue; + } + + /* Get the next buffer */ + usb_offset += amount; + common->usb_amount_left -= amount; + amount_left_to_req -= amount; + if (amount_left_to_req == 0) + get_some_more = 0; + + /* + * Except at the end of the transfer, amount will be + * equal to the buffer size, which is divisible by + * the bulk-out maxpacket size. + */ + set_bulk_out_req_length(common, bh, amount); + if (!start_out_transfer(common, bh)) + /* Dunno what to do if common->fsg is NULL */ + return -EIO; + common->next_buffhd_to_fill = bh->next; + continue; + } + + /* Write the received data to the backing file */ + bh = common->next_buffhd_to_drain; + if (bh->state == BUF_STATE_EMPTY && !get_some_more) + break; /* We stopped early */ + if (bh->state == BUF_STATE_FULL) { + smp_rmb(); + common->next_buffhd_to_drain = bh->next; + bh->state = BUF_STATE_EMPTY; + + /* Did something go wrong with the transfer? */ + if (bh->outreq->status != 0) { + curlun->sense_data = SS_COMMUNICATION_FAILURE; + curlun->sense_data_info = + file_offset >> curlun->blkbits; + curlun->info_valid = 1; + break; + } + + amount = bh->outreq->actual; + if (curlun->file_length - file_offset < amount) { + LERROR(curlun, + "write %u @ %llu beyond end %llu\n", + amount, (unsigned long long)file_offset, + (unsigned long long)curlun->file_length); + amount = curlun->file_length - file_offset; + } + + /* Don't accept excess data. The spec doesn't say + * what to do in this case. We'll ignore the error. + */ + amount = min(amount, bh->bulk_out_intended_length); + + /* Don't write a partial block */ + amount = round_down(amount, curlun->blksize); + if (amount == 0) + goto empty_write; + + /* Perform the write */ + file_offset_tmp = file_offset; + nwritten = vfs_write(curlun->filp, + (char __user *)bh->buf, + amount, &file_offset_tmp); + VLDBG(curlun, "file write %u @ %llu -> %d\n", amount, + (unsigned long long)file_offset, (int)nwritten); + if (signal_pending(current)) + return -EINTR; /* Interrupted! */ + + if (nwritten < 0) { + LDBG(curlun, "error in file write: %d\n", + (int)nwritten); + nwritten = 0; + } else if (nwritten < amount) { + LDBG(curlun, "partial file write: %d/%u\n", + (int)nwritten, amount); + nwritten = round_down(nwritten, curlun->blksize); + } + file_offset += nwritten; + amount_left_to_write -= nwritten; + common->residue -= nwritten; + + /* If an error occurred, report it and its position */ + if (nwritten < amount) { + curlun->sense_data = SS_WRITE_ERROR; + curlun->sense_data_info = + file_offset >> curlun->blkbits; + curlun->info_valid = 1; + break; + } + + empty_write: + /* Did the host decide to stop early? */ + if (bh->outreq->actual < bh->bulk_out_intended_length) { + common->short_packet_received = 1; + break; + } + continue; + } + + /* Wait for something to happen */ + rc = sleep_thread(common); + if (rc) + return rc; + } + + return -EIO; /* No default reply */ +} + + +/*-------------------------------------------------------------------------*/ + +static int do_synchronize_cache(struct fsg_common *common) +{ + struct fsg_lun *curlun = common->curlun; + int rc; + + /* We ignore the requested LBA and write out all file's + * dirty data buffers. */ + rc = fsg_lun_fsync_sub(curlun); + if (rc) + curlun->sense_data = SS_WRITE_ERROR; + return 0; +} + + +/*-------------------------------------------------------------------------*/ + +static void invalidate_sub(struct fsg_lun *curlun) +{ + struct file *filp = curlun->filp; + struct inode *inode = filp->f_path.dentry->d_inode; + unsigned long rc; + + rc = invalidate_mapping_pages(inode->i_mapping, 0, -1); + VLDBG(curlun, "invalidate_mapping_pages -> %ld\n", rc); +} + +static int do_verify(struct fsg_common *common) +{ + struct fsg_lun *curlun = common->curlun; + u32 lba; + u32 verification_length; + struct fsg_buffhd *bh = common->next_buffhd_to_fill; + loff_t file_offset, file_offset_tmp; + u32 amount_left; + unsigned int amount; + ssize_t nread; + + /* + * Get the starting Logical Block Address and check that it's + * not too big. + */ + lba = get_unaligned_be32(&common->cmnd[2]); + if (lba >= curlun->num_sectors) { + curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + return -EINVAL; + } + + /* + * We allow DPO (Disable Page Out = don't save data in the + * cache) but we don't implement it. + */ + if (common->cmnd[1] & ~0x10) { + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + + verification_length = get_unaligned_be16(&common->cmnd[7]); + if (unlikely(verification_length == 0)) + return -EIO; /* No default reply */ + + /* Prepare to carry out the file verify */ + amount_left = verification_length << curlun->blkbits; + file_offset = ((loff_t) lba) << curlun->blkbits; + + /* Write out all the dirty buffers before invalidating them */ + fsg_lun_fsync_sub(curlun); + if (signal_pending(current)) + return -EINTR; + + invalidate_sub(curlun); + if (signal_pending(current)) + return -EINTR; + + /* Just try to read the requested blocks */ + while (amount_left > 0) { + /* + * Figure out how much we need to read: + * Try to read the remaining amount, but not more than + * the buffer size. + * And don't try to read past the end of the file. + */ + amount = min(amount_left, FSG_BUFLEN); + amount = min((loff_t)amount, + curlun->file_length - file_offset); + if (amount == 0) { + curlun->sense_data = + SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + curlun->sense_data_info = + file_offset >> curlun->blkbits; + curlun->info_valid = 1; + break; + } + + /* Perform the read */ + file_offset_tmp = file_offset; + nread = vfs_read(curlun->filp, + (char __user *) bh->buf, + amount, &file_offset_tmp); + VLDBG(curlun, "file read %u @ %llu -> %d\n", amount, + (unsigned long long) file_offset, + (int) nread); + if (signal_pending(current)) + return -EINTR; + + if (nread < 0) { + LDBG(curlun, "error in file verify: %d\n", (int)nread); + nread = 0; + } else if (nread < amount) { + LDBG(curlun, "partial file verify: %d/%u\n", + (int)nread, amount); + nread = round_down(nread, curlun->blksize); + } + if (nread == 0) { + curlun->sense_data = SS_UNRECOVERED_READ_ERROR; + curlun->sense_data_info = + file_offset >> curlun->blkbits; + curlun->info_valid = 1; + break; + } + file_offset += nread; + amount_left -= nread; + } + return 0; +} + + +/*-------------------------------------------------------------------------*/ + +static int do_inquiry(struct fsg_common *common, struct fsg_buffhd *bh) +{ + struct fsg_lun *curlun = common->curlun; + u8 *buf = (u8 *) bh->buf; + + if (!curlun) { /* Unsupported LUNs are okay */ + common->bad_lun_okay = 1; + memset(buf, 0, 36); + buf[0] = 0x7f; /* Unsupported, no device-type */ + buf[4] = 31; /* Additional length */ + return 36; + } + + buf[0] = curlun->cdrom ? TYPE_ROM : TYPE_DISK; + buf[1] = curlun->removable ? 0x80 : 0; + buf[2] = 2; /* ANSI SCSI level 2 */ + buf[3] = 2; /* SCSI-2 INQUIRY data format */ + buf[4] = 31; /* Additional length */ + buf[5] = 0; /* No special options */ + buf[6] = 0; + buf[7] = 0; + memcpy(buf + 8, common->inquiry_string, sizeof common->inquiry_string); + return 36; +} + +static int do_request_sense(struct fsg_common *common, struct fsg_buffhd *bh) +{ + struct fsg_lun *curlun = common->curlun; + u8 *buf = (u8 *) bh->buf; + u32 sd, sdinfo; + int valid; + + /* + * From the SCSI-2 spec., section 7.9 (Unit attention condition): + * + * If a REQUEST SENSE command is received from an initiator + * with a pending unit attention condition (before the target + * generates the contingent allegiance condition), then the + * target shall either: + * a) report any pending sense data and preserve the unit + * attention condition on the logical unit, or, + * b) report the unit attention condition, may discard any + * pending sense data, and clear the unit attention + * condition on the logical unit for that initiator. + * + * FSG normally uses option a); enable this code to use option b). + */ +#if 0 + if (curlun && curlun->unit_attention_data != SS_NO_SENSE) { + curlun->sense_data = curlun->unit_attention_data; + curlun->unit_attention_data = SS_NO_SENSE; + } +#endif + + if (!curlun) { /* Unsupported LUNs are okay */ + common->bad_lun_okay = 1; + sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; + sdinfo = 0; + valid = 0; + } else { + sd = curlun->sense_data; + sdinfo = curlun->sense_data_info; + valid = curlun->info_valid << 7; + curlun->sense_data = SS_NO_SENSE; + curlun->sense_data_info = 0; + curlun->info_valid = 0; + } + + memset(buf, 0, 18); + buf[0] = valid | 0x70; /* Valid, current error */ + buf[2] = SK(sd); + put_unaligned_be32(sdinfo, &buf[3]); /* Sense information */ + buf[7] = 18 - 8; /* Additional sense length */ + buf[12] = ASC(sd); + buf[13] = ASCQ(sd); + return 18; +} + +static int do_read_capacity(struct fsg_common *common, struct fsg_buffhd *bh) +{ + struct fsg_lun *curlun = common->curlun; + u32 lba = get_unaligned_be32(&common->cmnd[2]); + int pmi = common->cmnd[8]; + u8 *buf = (u8 *)bh->buf; + + /* Check the PMI and LBA fields */ + if (pmi > 1 || (pmi == 0 && lba != 0)) { + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + + put_unaligned_be32(curlun->num_sectors - 1, &buf[0]); + /* Max logical block */ + put_unaligned_be32(curlun->blksize, &buf[4]);/* Block length */ + return 8; +} + +static int do_read_header(struct fsg_common *common, struct fsg_buffhd *bh) +{ + struct fsg_lun *curlun = common->curlun; + int msf = common->cmnd[1] & 0x02; + u32 lba = get_unaligned_be32(&common->cmnd[2]); + u8 *buf = (u8 *)bh->buf; + + if (common->cmnd[1] & ~0x02) { /* Mask away MSF */ + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + if (lba >= curlun->num_sectors) { + curlun->sense_data = SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE; + return -EINVAL; + } + + memset(buf, 0, 8); + buf[0] = 0x01; /* 2048 bytes of user data, rest is EC */ + store_cdrom_address(&buf[4], msf, lba); + return 8; +} + +static int do_read_toc(struct fsg_common *common, struct fsg_buffhd *bh) +{ + struct fsg_lun *curlun = common->curlun; + int msf = common->cmnd[1] & 0x02; + int start_track = common->cmnd[6]; + u8 *buf = (u8 *)bh->buf; + + if ((common->cmnd[1] & ~0x02) != 0 || /* Mask away MSF */ + start_track > 1) { + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + + memset(buf, 0, 20); + buf[1] = (20-2); /* TOC data length */ + buf[2] = 1; /* First track number */ + buf[3] = 1; /* Last track number */ + buf[5] = 0x16; /* Data track, copying allowed */ + buf[6] = 0x01; /* Only track is number 1 */ + store_cdrom_address(&buf[8], msf, 0); + + buf[13] = 0x16; /* Lead-out track is data */ + buf[14] = 0xAA; /* Lead-out track number */ + store_cdrom_address(&buf[16], msf, curlun->num_sectors); + return 20; +} + +static int do_mode_sense(struct fsg_common *common, struct fsg_buffhd *bh) +{ + struct fsg_lun *curlun = common->curlun; + int mscmnd = common->cmnd[0]; + u8 *buf = (u8 *) bh->buf; + u8 *buf0 = buf; + int pc, page_code; + int changeable_values, all_pages; + int valid_page = 0; + int len, limit; + + if ((common->cmnd[1] & ~0x08) != 0) { /* Mask away DBD */ + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + pc = common->cmnd[2] >> 6; + page_code = common->cmnd[2] & 0x3f; + if (pc == 3) { + curlun->sense_data = SS_SAVING_PARAMETERS_NOT_SUPPORTED; + return -EINVAL; + } + changeable_values = (pc == 1); + all_pages = (page_code == 0x3f); + + /* + * Write the mode parameter header. Fixed values are: default + * medium type, no cache control (DPOFUA), and no block descriptors. + * The only variable value is the WriteProtect bit. We will fill in + * the mode data length later. + */ + memset(buf, 0, 8); + if (mscmnd == MODE_SENSE) { + buf[2] = (curlun->ro ? 0x80 : 0x00); /* WP, DPOFUA */ + buf += 4; + limit = 255; + } else { /* MODE_SENSE_10 */ + buf[3] = (curlun->ro ? 0x80 : 0x00); /* WP, DPOFUA */ + buf += 8; + limit = 65535; /* Should really be FSG_BUFLEN */ + } + + /* No block descriptors */ + + /* + * The mode pages, in numerical order. The only page we support + * is the Caching page. + */ + if (page_code == 0x08 || all_pages) { + valid_page = 1; + buf[0] = 0x08; /* Page code */ + buf[1] = 10; /* Page length */ + memset(buf+2, 0, 10); /* None of the fields are changeable */ + + if (!changeable_values) { + buf[2] = 0x04; /* Write cache enable, */ + /* Read cache not disabled */ + /* No cache retention priorities */ + put_unaligned_be16(0xffff, &buf[4]); + /* Don't disable prefetch */ + /* Minimum prefetch = 0 */ + put_unaligned_be16(0xffff, &buf[8]); + /* Maximum prefetch */ + put_unaligned_be16(0xffff, &buf[10]); + /* Maximum prefetch ceiling */ + } + buf += 12; + } + + /* + * Check that a valid page was requested and the mode data length + * isn't too long. + */ + len = buf - buf0; + if (!valid_page || len > limit) { + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + + /* Store the mode data length */ + if (mscmnd == MODE_SENSE) + buf0[0] = len - 1; + else + put_unaligned_be16(len - 2, buf0); + return len; +} + +static int do_start_stop(struct fsg_common *common) +{ + struct fsg_lun *curlun = common->curlun; + int loej, start; + + if (!curlun) { + return -EINVAL; + } else if (!curlun->removable) { + curlun->sense_data = SS_INVALID_COMMAND; + return -EINVAL; + } else if ((common->cmnd[1] & ~0x01) != 0 || /* Mask away Immed */ + (common->cmnd[4] & ~0x03) != 0) { /* Mask LoEj, Start */ + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + + loej = common->cmnd[4] & 0x02; + start = common->cmnd[4] & 0x01; + + /* + * Our emulation doesn't support mounting; the medium is + * available for use as soon as it is loaded. + */ + if (start) { + if (!fsg_lun_is_open(curlun)) { + curlun->sense_data = SS_MEDIUM_NOT_PRESENT; + return -EINVAL; + } + return 0; + } + + /* Are we allowed to unload the media? */ + if (curlun->prevent_medium_removal) { + LDBG(curlun, "unload attempt prevented\n"); + curlun->sense_data = SS_MEDIUM_REMOVAL_PREVENTED; + return -EINVAL; + } + + if (!loej) + return 0; + + /* Simulate an unload/eject */ + if (common->ops && common->ops->pre_eject) { + int r = common->ops->pre_eject(common, curlun, + curlun - common->luns); + if (unlikely(r < 0)) + return r; + else if (r) + return 0; + } + + up_read(&common->filesem); + down_write(&common->filesem); + fsg_lun_close(curlun); + up_write(&common->filesem); + down_read(&common->filesem); + + return common->ops && common->ops->post_eject + ? min(0, common->ops->post_eject(common, curlun, + curlun - common->luns)) + : 0; +} + +static int do_prevent_allow(struct fsg_common *common) +{ + struct fsg_lun *curlun = common->curlun; + int prevent; + + if (!common->curlun) { + return -EINVAL; + } else if (!common->curlun->removable) { + common->curlun->sense_data = SS_INVALID_COMMAND; + return -EINVAL; + } + + prevent = common->cmnd[4] & 0x01; + if ((common->cmnd[4] & ~0x01) != 0) { /* Mask away Prevent */ + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + + if (curlun->prevent_medium_removal && !prevent) + fsg_lun_fsync_sub(curlun); + curlun->prevent_medium_removal = prevent; + return 0; +} + +static int do_read_format_capacities(struct fsg_common *common, + struct fsg_buffhd *bh) +{ + struct fsg_lun *curlun = common->curlun; + u8 *buf = (u8 *) bh->buf; + + buf[0] = buf[1] = buf[2] = 0; + buf[3] = 8; /* Only the Current/Maximum Capacity Descriptor */ + buf += 4; + + put_unaligned_be32(curlun->num_sectors, &buf[0]); + /* Number of blocks */ + put_unaligned_be32(curlun->blksize, &buf[4]);/* Block length */ + buf[4] = 0x02; /* Current capacity */ + return 12; +} + +static int do_mode_select(struct fsg_common *common, struct fsg_buffhd *bh) +{ + struct fsg_lun *curlun = common->curlun; + + /* We don't support MODE SELECT */ + if (curlun) + curlun->sense_data = SS_INVALID_COMMAND; + return -EINVAL; +} + + +/*-------------------------------------------------------------------------*/ + +static int halt_bulk_in_endpoint(struct fsg_dev *fsg) +{ + int rc; + + rc = fsg_set_halt(fsg, fsg->bulk_in); + if (rc == -EAGAIN) + VDBG(fsg, "delayed bulk-in endpoint halt\n"); + while (rc != 0) { + if (rc != -EAGAIN) { + WARNING(fsg, "usb_ep_set_halt -> %d\n", rc); + rc = 0; + break; + } + + /* Wait for a short time and then try again */ + if (msleep_interruptible(100) != 0) + return -EINTR; + rc = usb_ep_set_halt(fsg->bulk_in); + } + return rc; +} + +static int wedge_bulk_in_endpoint(struct fsg_dev *fsg) +{ + int rc; + + DBG(fsg, "bulk-in set wedge\n"); + rc = usb_ep_set_wedge(fsg->bulk_in); + if (rc == -EAGAIN) + VDBG(fsg, "delayed bulk-in endpoint wedge\n"); + while (rc != 0) { + if (rc != -EAGAIN) { + WARNING(fsg, "usb_ep_set_wedge -> %d\n", rc); + rc = 0; + break; + } + + /* Wait for a short time and then try again */ + if (msleep_interruptible(100) != 0) + return -EINTR; + rc = usb_ep_set_wedge(fsg->bulk_in); + } + return rc; +} + +static int throw_away_data(struct fsg_common *common) +{ + struct fsg_buffhd *bh; + u32 amount; + int rc; + + for (bh = common->next_buffhd_to_drain; + bh->state != BUF_STATE_EMPTY || common->usb_amount_left > 0; + bh = common->next_buffhd_to_drain) { + + /* Throw away the data in a filled buffer */ + if (bh->state == BUF_STATE_FULL) { + smp_rmb(); + bh->state = BUF_STATE_EMPTY; + common->next_buffhd_to_drain = bh->next; + + /* A short packet or an error ends everything */ + if (bh->outreq->actual < bh->bulk_out_intended_length || + bh->outreq->status != 0) { + raise_exception(common, + FSG_STATE_ABORT_BULK_OUT); + return -EINTR; + } + continue; + } + + /* Try to submit another request if we need one */ + bh = common->next_buffhd_to_fill; + if (bh->state == BUF_STATE_EMPTY + && common->usb_amount_left > 0) { + amount = min(common->usb_amount_left, FSG_BUFLEN); + + /* + * Except at the end of the transfer, amount will be + * equal to the buffer size, which is divisible by + * the bulk-out maxpacket size. + */ + set_bulk_out_req_length(common, bh, amount); + if (!start_out_transfer(common, bh)) + /* Dunno what to do if common->fsg is NULL */ + return -EIO; + common->next_buffhd_to_fill = bh->next; + common->usb_amount_left -= amount; + continue; + } + + /* Otherwise wait for something to happen */ + rc = sleep_thread(common); + if (rc) + return rc; + } + return 0; +} + +static int finish_reply(struct fsg_common *common) +{ + struct fsg_buffhd *bh = common->next_buffhd_to_fill; + int rc = 0; + + switch (common->data_dir) { + case DATA_DIR_NONE: + break; /* Nothing to send */ + + /* + * If we don't know whether the host wants to read or write, + * this must be CB or CBI with an unknown command. We mustn't + * try to send or receive any data. So stall both bulk pipes + * if we can and wait for a reset. + */ + case DATA_DIR_UNKNOWN: + if (!common->can_stall) { + /* Nothing */ + } else if (fsg_is_set(common)) { + fsg_set_halt(common->fsg, common->fsg->bulk_out); + rc = halt_bulk_in_endpoint(common->fsg); + } else { + /* Don't know what to do if common->fsg is NULL */ + rc = -EIO; + } + break; + + /* All but the last buffer of data must have already been sent */ + case DATA_DIR_TO_HOST: + if (common->data_size == 0) { + /* Nothing to send */ + + /* Don't know what to do if common->fsg is NULL */ + } else if (!fsg_is_set(common)) { + rc = -EIO; + + /* If there's no residue, simply send the last buffer */ + } else if (common->residue == 0) { + bh->inreq->zero = 0; + if (!start_in_transfer(common, bh)) + return -EIO; + common->next_buffhd_to_fill = bh->next; + + /* + * For Bulk-only, mark the end of the data with a short + * packet. If we are allowed to stall, halt the bulk-in + * endpoint. (Note: This violates the Bulk-Only Transport + * specification, which requires us to pad the data if we + * don't halt the endpoint. Presumably nobody will mind.) + */ + } else { + bh->inreq->zero = 1; + if (!start_in_transfer(common, bh)) + rc = -EIO; + common->next_buffhd_to_fill = bh->next; + if (common->can_stall) + rc = halt_bulk_in_endpoint(common->fsg); + } + break; + + /* + * We have processed all we want from the data the host has sent. + * There may still be outstanding bulk-out requests. + */ + case DATA_DIR_FROM_HOST: + if (common->residue == 0) { + /* Nothing to receive */ + + /* Did the host stop sending unexpectedly early? */ + } else if (common->short_packet_received) { + raise_exception(common, FSG_STATE_ABORT_BULK_OUT); + rc = -EINTR; + + /* + * We haven't processed all the incoming data. Even though + * we may be allowed to stall, doing so would cause a race. + * The controller may already have ACK'ed all the remaining + * bulk-out packets, in which case the host wouldn't see a + * STALL. Not realizing the endpoint was halted, it wouldn't + * clear the halt -- leading to problems later on. + */ +#if 0 + } else if (common->can_stall) { + if (fsg_is_set(common)) + fsg_set_halt(common->fsg, + common->fsg->bulk_out); + raise_exception(common, FSG_STATE_ABORT_BULK_OUT); + rc = -EINTR; +#endif + + /* + * We can't stall. Read in the excess data and throw it + * all away. + */ + } else { + rc = throw_away_data(common); + } + break; + } + return rc; +} + +static int send_status(struct fsg_common *common) +{ + struct fsg_lun *curlun = common->curlun; + struct fsg_buffhd *bh; + struct bulk_cs_wrap *csw; + int rc; + u8 status = US_BULK_STAT_OK; + u32 sd, sdinfo = 0; + + /* Wait for the next buffer to become available */ + bh = common->next_buffhd_to_fill; + while (bh->state != BUF_STATE_EMPTY) { + rc = sleep_thread(common); + if (rc) + return rc; + } + + if (curlun) { + sd = curlun->sense_data; + sdinfo = curlun->sense_data_info; + } else if (common->bad_lun_okay) + sd = SS_NO_SENSE; + else + sd = SS_LOGICAL_UNIT_NOT_SUPPORTED; + + if (common->phase_error) { + DBG(common, "sending phase-error status\n"); + status = US_BULK_STAT_PHASE; + sd = SS_INVALID_COMMAND; + } else if (sd != SS_NO_SENSE) { + DBG(common, "sending command-failure status\n"); + status = US_BULK_STAT_FAIL; + VDBG(common, " sense data: SK x%02x, ASC x%02x, ASCQ x%02x;" + " info x%x\n", + SK(sd), ASC(sd), ASCQ(sd), sdinfo); + } + + /* Store and send the Bulk-only CSW */ + csw = (void *)bh->buf; + + csw->Signature = cpu_to_le32(US_BULK_CS_SIGN); + csw->Tag = common->tag; + csw->Residue = cpu_to_le32(common->residue); + csw->Status = status; + + bh->inreq->length = US_BULK_CS_WRAP_LEN; + bh->inreq->zero = 0; + if (!start_in_transfer(common, bh)) + /* Don't know what to do if common->fsg is NULL */ + return -EIO; + + common->next_buffhd_to_fill = bh->next; + return 0; +} + + +/*-------------------------------------------------------------------------*/ + +/* + * Check whether the command is properly formed and whether its data size + * and direction agree with the values we already have. + */ +static int check_command(struct fsg_common *common, int cmnd_size, + enum data_direction data_dir, unsigned int mask, + int needs_medium, const char *name) +{ + int i; + int lun = common->cmnd[1] >> 5; + static const char dirletter[4] = {'u', 'o', 'i', 'n'}; + char hdlen[20]; + struct fsg_lun *curlun; + + hdlen[0] = 0; + if (common->data_dir != DATA_DIR_UNKNOWN) + sprintf(hdlen, ", H%c=%u", dirletter[(int) common->data_dir], + common->data_size); + VDBG(common, "SCSI command: %s; Dc=%d, D%c=%u; Hc=%d%s\n", + name, cmnd_size, dirletter[(int) data_dir], + common->data_size_from_cmnd, common->cmnd_size, hdlen); + + /* + * We can't reply at all until we know the correct data direction + * and size. + */ + if (common->data_size_from_cmnd == 0) + data_dir = DATA_DIR_NONE; + if (common->data_size < common->data_size_from_cmnd) { + /* + * Host data size < Device data size is a phase error. + * Carry out the command, but only transfer as much as + * we are allowed. + */ + common->data_size_from_cmnd = common->data_size; + common->phase_error = 1; + } + common->residue = common->data_size; + common->usb_amount_left = common->data_size; + + /* Conflicting data directions is a phase error */ + if (common->data_dir != data_dir && common->data_size_from_cmnd > 0) { + common->phase_error = 1; + return -EINVAL; + } + + /* Verify the length of the command itself */ + if (cmnd_size != common->cmnd_size) { + + /* + * Special case workaround: There are plenty of buggy SCSI + * implementations. Many have issues with cbw->Length + * field passing a wrong command size. For those cases we + * always try to work around the problem by using the length + * sent by the host side provided it is at least as large + * as the correct command length. + * Examples of such cases would be MS-Windows, which issues + * REQUEST SENSE with cbw->Length == 12 where it should + * be 6, and xbox360 issuing INQUIRY, TEST UNIT READY and + * REQUEST SENSE with cbw->Length == 10 where it should + * be 6 as well. + */ + if (cmnd_size <= common->cmnd_size) { + DBG(common, "%s is buggy! Expected length %d " + "but we got %d\n", name, + cmnd_size, common->cmnd_size); + cmnd_size = common->cmnd_size; + } else { + common->phase_error = 1; + return -EINVAL; + } + } + + /* Check that the LUN values are consistent */ + if (common->lun != lun) + DBG(common, "using LUN %d from CBW, not LUN %d from CDB\n", + common->lun, lun); + + /* Check the LUN */ + curlun = common->curlun; + if (curlun) { + if (common->cmnd[0] != REQUEST_SENSE) { + curlun->sense_data = SS_NO_SENSE; + curlun->sense_data_info = 0; + curlun->info_valid = 0; + } + } else { + common->bad_lun_okay = 0; + + /* + * INQUIRY and REQUEST SENSE commands are explicitly allowed + * to use unsupported LUNs; all others may not. + */ + if (common->cmnd[0] != INQUIRY && + common->cmnd[0] != REQUEST_SENSE) { + DBG(common, "unsupported LUN %d\n", common->lun); + return -EINVAL; + } + } + + /* + * If a unit attention condition exists, only INQUIRY and + * REQUEST SENSE commands are allowed; anything else must fail. + */ + if (curlun && curlun->unit_attention_data != SS_NO_SENSE && + common->cmnd[0] != INQUIRY && + common->cmnd[0] != REQUEST_SENSE) { + curlun->sense_data = curlun->unit_attention_data; + curlun->unit_attention_data = SS_NO_SENSE; + return -EINVAL; + } + + /* Check that only command bytes listed in the mask are non-zero */ + common->cmnd[1] &= 0x1f; /* Mask away the LUN */ + for (i = 1; i < cmnd_size; ++i) { + if (common->cmnd[i] && !(mask & (1 << i))) { + if (curlun) + curlun->sense_data = SS_INVALID_FIELD_IN_CDB; + return -EINVAL; + } + } + + /* If the medium isn't mounted and the command needs to access + * it, return an error. */ + if (curlun && !fsg_lun_is_open(curlun) && needs_medium) { + curlun->sense_data = SS_MEDIUM_NOT_PRESENT; + return -EINVAL; + } + + return 0; +} + +/* wrapper of check_command for data size in blocks handling */ +static int check_command_size_in_blocks(struct fsg_common *common, + int cmnd_size, enum data_direction data_dir, + unsigned int mask, int needs_medium, const char *name) +{ + if (common->curlun) + common->data_size_from_cmnd <<= common->curlun->blkbits; + return check_command(common, cmnd_size, data_dir, + mask, needs_medium, name); +} + +static int do_scsi_command(struct fsg_common *common) +{ + struct fsg_buffhd *bh; + int rc; + int reply = -EINVAL; + int i; + static char unknown[16]; + + dump_cdb(common); + + /* Wait for the next buffer to become available for data or status */ + bh = common->next_buffhd_to_fill; + common->next_buffhd_to_drain = bh; + while (bh->state != BUF_STATE_EMPTY) { + rc = sleep_thread(common); + if (rc) + return rc; + } + common->phase_error = 0; + common->short_packet_received = 0; + + down_read(&common->filesem); /* We're using the backing file */ + switch (common->cmnd[0]) { + + case INQUIRY: + common->data_size_from_cmnd = common->cmnd[4]; + reply = check_command(common, 6, DATA_DIR_TO_HOST, + (1<<4), 0, + "INQUIRY"); + if (reply == 0) + reply = do_inquiry(common, bh); + break; + + case MODE_SELECT: + common->data_size_from_cmnd = common->cmnd[4]; + reply = check_command(common, 6, DATA_DIR_FROM_HOST, + (1<<1) | (1<<4), 0, + "MODE SELECT(6)"); + if (reply == 0) + reply = do_mode_select(common, bh); + break; + + case MODE_SELECT_10: + common->data_size_from_cmnd = + get_unaligned_be16(&common->cmnd[7]); + reply = check_command(common, 10, DATA_DIR_FROM_HOST, + (1<<1) | (3<<7), 0, + "MODE SELECT(10)"); + if (reply == 0) + reply = do_mode_select(common, bh); + break; + + case MODE_SENSE: + common->data_size_from_cmnd = common->cmnd[4]; + reply = check_command(common, 6, DATA_DIR_TO_HOST, + (1<<1) | (1<<2) | (1<<4), 0, + "MODE SENSE(6)"); + if (reply == 0) + reply = do_mode_sense(common, bh); + break; + + case MODE_SENSE_10: + common->data_size_from_cmnd = + get_unaligned_be16(&common->cmnd[7]); + reply = check_command(common, 10, DATA_DIR_TO_HOST, + (1<<1) | (1<<2) | (3<<7), 0, + "MODE SENSE(10)"); + if (reply == 0) + reply = do_mode_sense(common, bh); + break; + + case ALLOW_MEDIUM_REMOVAL: + common->data_size_from_cmnd = 0; + reply = check_command(common, 6, DATA_DIR_NONE, + (1<<4), 0, + "PREVENT-ALLOW MEDIUM REMOVAL"); + if (reply == 0) + reply = do_prevent_allow(common); + break; + + case READ_6: + i = common->cmnd[4]; + common->data_size_from_cmnd = (i == 0) ? 256 : i; + reply = check_command_size_in_blocks(common, 6, + DATA_DIR_TO_HOST, + (7<<1) | (1<<4), 1, + "READ(6)"); + if (reply == 0) + reply = do_read(common); + break; + + case READ_10: + common->data_size_from_cmnd = + get_unaligned_be16(&common->cmnd[7]); + reply = check_command_size_in_blocks(common, 10, + DATA_DIR_TO_HOST, + (1<<1) | (0xf<<2) | (3<<7), 1, + "READ(10)"); + if (reply == 0) + reply = do_read(common); + break; + + case READ_12: + common->data_size_from_cmnd = + get_unaligned_be32(&common->cmnd[6]); + reply = check_command_size_in_blocks(common, 12, + DATA_DIR_TO_HOST, + (1<<1) | (0xf<<2) | (0xf<<6), 1, + "READ(12)"); + if (reply == 0) + reply = do_read(common); + break; + + case READ_CAPACITY: + common->data_size_from_cmnd = 8; + reply = check_command(common, 10, DATA_DIR_TO_HOST, + (0xf<<2) | (1<<8), 1, + "READ CAPACITY"); + if (reply == 0) + reply = do_read_capacity(common, bh); + break; + + case READ_HEADER: + if (!common->curlun || !common->curlun->cdrom) + goto unknown_cmnd; + common->data_size_from_cmnd = + get_unaligned_be16(&common->cmnd[7]); + reply = check_command(common, 10, DATA_DIR_TO_HOST, + (3<<7) | (0x1f<<1), 1, + "READ HEADER"); + if (reply == 0) + reply = do_read_header(common, bh); + break; + + case READ_TOC: + if (!common->curlun || !common->curlun->cdrom) + goto unknown_cmnd; + common->data_size_from_cmnd = + get_unaligned_be16(&common->cmnd[7]); + reply = check_command(common, 10, DATA_DIR_TO_HOST, + (7<<6) | (1<<1), 1, + "READ TOC"); + if (reply == 0) + reply = do_read_toc(common, bh); + break; + + case READ_FORMAT_CAPACITIES: + common->data_size_from_cmnd = + get_unaligned_be16(&common->cmnd[7]); + reply = check_command(common, 10, DATA_DIR_TO_HOST, + (3<<7), 1, + "READ FORMAT CAPACITIES"); + if (reply == 0) + reply = do_read_format_capacities(common, bh); + break; + + case REQUEST_SENSE: + common->data_size_from_cmnd = common->cmnd[4]; + reply = check_command(common, 6, DATA_DIR_TO_HOST, + (1<<4), 0, + "REQUEST SENSE"); + if (reply == 0) + reply = do_request_sense(common, bh); + break; + + case START_STOP: + common->data_size_from_cmnd = 0; + reply = check_command(common, 6, DATA_DIR_NONE, + (1<<1) | (1<<4), 0, + "START-STOP UNIT"); + if (reply == 0) + reply = do_start_stop(common); + break; + + case SYNCHRONIZE_CACHE: + common->data_size_from_cmnd = 0; + reply = check_command(common, 10, DATA_DIR_NONE, + (0xf<<2) | (3<<7), 1, + "SYNCHRONIZE CACHE"); + if (reply == 0) + reply = do_synchronize_cache(common); + break; + + case TEST_UNIT_READY: + common->data_size_from_cmnd = 0; + reply = check_command(common, 6, DATA_DIR_NONE, + 0, 1, + "TEST UNIT READY"); + break; + + /* + * Although optional, this command is used by MS-Windows. We + * support a minimal version: BytChk must be 0. + */ + case VERIFY: + common->data_size_from_cmnd = 0; + reply = check_command(common, 10, DATA_DIR_NONE, + (1<<1) | (0xf<<2) | (3<<7), 1, + "VERIFY"); + if (reply == 0) + reply = do_verify(common); + break; + + case WRITE_6: + i = common->cmnd[4]; + common->data_size_from_cmnd = (i == 0) ? 256 : i; + reply = check_command_size_in_blocks(common, 6, + DATA_DIR_FROM_HOST, + (7<<1) | (1<<4), 1, + "WRITE(6)"); + if (reply == 0) + reply = do_write(common); + break; + + case WRITE_10: + common->data_size_from_cmnd = + get_unaligned_be16(&common->cmnd[7]); + reply = check_command_size_in_blocks(common, 10, + DATA_DIR_FROM_HOST, + (1<<1) | (0xf<<2) | (3<<7), 1, + "WRITE(10)"); + if (reply == 0) + reply = do_write(common); + break; + + case WRITE_12: + common->data_size_from_cmnd = + get_unaligned_be32(&common->cmnd[6]); + reply = check_command_size_in_blocks(common, 12, + DATA_DIR_FROM_HOST, + (1<<1) | (0xf<<2) | (0xf<<6), 1, + "WRITE(12)"); + if (reply == 0) + reply = do_write(common); + break; + + /* + * Some mandatory commands that we recognize but don't implement. + * They don't mean much in this setting. It's left as an exercise + * for anyone interested to implement RESERVE and RELEASE in terms + * of Posix locks. + */ + case FORMAT_UNIT: + case RELEASE: + case RESERVE: + case SEND_DIAGNOSTIC: + /* Fall through */ + + default: +unknown_cmnd: + common->data_size_from_cmnd = 0; + sprintf(unknown, "Unknown x%02x", common->cmnd[0]); + reply = check_command(common, common->cmnd_size, + DATA_DIR_UNKNOWN, ~0, 0, unknown); + if (reply == 0) { + common->curlun->sense_data = SS_INVALID_COMMAND; + reply = -EINVAL; + } + break; + } + up_read(&common->filesem); + + if (reply == -EINTR || signal_pending(current)) + return -EINTR; + + /* Set up the single reply buffer for finish_reply() */ + if (reply == -EINVAL) + reply = 0; /* Error reply length */ + if (reply >= 0 && common->data_dir == DATA_DIR_TO_HOST) { + reply = min((u32)reply, common->data_size_from_cmnd); + bh->inreq->length = reply; + bh->state = BUF_STATE_FULL; + common->residue -= reply; + } /* Otherwise it's already set */ + + return 0; +} + + +/*-------------------------------------------------------------------------*/ + +static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) +{ + struct usb_request *req = bh->outreq; + struct bulk_cb_wrap *cbw = req->buf; + struct fsg_common *common = fsg->common; + + /* Was this a real packet? Should it be ignored? */ + if (req->status || test_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags)) + return -EINVAL; + + /* Is the CBW valid? */ + if (req->actual != US_BULK_CB_WRAP_LEN || + cbw->Signature != cpu_to_le32( + US_BULK_CB_SIGN)) { + DBG(fsg, "invalid CBW: len %u sig 0x%x\n", + req->actual, + le32_to_cpu(cbw->Signature)); + + /* + * The Bulk-only spec says we MUST stall the IN endpoint + * (6.6.1), so it's unavoidable. It also says we must + * retain this state until the next reset, but there's + * no way to tell the controller driver it should ignore + * Clear-Feature(HALT) requests. + * + * We aren't required to halt the OUT endpoint; instead + * we can simply accept and discard any data received + * until the next reset. + */ + wedge_bulk_in_endpoint(fsg); + set_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); + return -EINVAL; + } + + /* Is the CBW meaningful? */ + if (cbw->Lun >= FSG_MAX_LUNS || cbw->Flags & ~US_BULK_FLAG_IN || + cbw->Length <= 0 || cbw->Length > MAX_COMMAND_SIZE) { + DBG(fsg, "non-meaningful CBW: lun = %u, flags = 0x%x, " + "cmdlen %u\n", + cbw->Lun, cbw->Flags, cbw->Length); + + /* + * We can do anything we want here, so let's stall the + * bulk pipes if we are allowed to. + */ + if (common->can_stall) { + fsg_set_halt(fsg, fsg->bulk_out); + halt_bulk_in_endpoint(fsg); + } + return -EINVAL; + } + + /* Save the command for later */ + common->cmnd_size = cbw->Length; + memcpy(common->cmnd, cbw->CDB, common->cmnd_size); + if (cbw->Flags & US_BULK_FLAG_IN) + common->data_dir = DATA_DIR_TO_HOST; + else + common->data_dir = DATA_DIR_FROM_HOST; + common->data_size = le32_to_cpu(cbw->DataTransferLength); + if (common->data_size == 0) + common->data_dir = DATA_DIR_NONE; + common->lun = cbw->Lun; + if (common->lun >= 0 && common->lun < common->nluns) + common->curlun = &common->luns[common->lun]; + else + common->curlun = NULL; + common->tag = cbw->Tag; + return 0; +} + +static int get_next_command(struct fsg_common *common) +{ + struct fsg_buffhd *bh; + int rc = 0; + + /* Wait for the next buffer to become available */ + bh = common->next_buffhd_to_fill; + while (bh->state != BUF_STATE_EMPTY) { + rc = sleep_thread(common); + if (rc) + return rc; + } + + /* Queue a request to read a Bulk-only CBW */ + set_bulk_out_req_length(common, bh, US_BULK_CB_WRAP_LEN); + if (!start_out_transfer(common, bh)) + /* Don't know what to do if common->fsg is NULL */ + return -EIO; + + /* + * We will drain the buffer in software, which means we + * can reuse it for the next filling. No need to advance + * next_buffhd_to_fill. + */ + + /* Wait for the CBW to arrive */ + while (bh->state != BUF_STATE_FULL) { + rc = sleep_thread(common); + if (rc) + return rc; + } + smp_rmb(); + rc = fsg_is_set(common) ? received_cbw(common->fsg, bh) : -EIO; + bh->state = BUF_STATE_EMPTY; + + return rc; +} + + +/*-------------------------------------------------------------------------*/ + +static int alloc_request(struct fsg_common *common, struct usb_ep *ep, + struct usb_request **preq) +{ + *preq = usb_ep_alloc_request(ep, GFP_ATOMIC); + if (*preq) + return 0; + ERROR(common, "can't allocate request for %s\n", ep->name); + return -ENOMEM; +} + +/* Reset interface setting and re-init endpoint state (toggle etc). */ +static int do_set_interface(struct fsg_common *common, struct fsg_dev *new_fsg) +{ + struct fsg_dev *fsg; + int i, rc = 0; + + if (common->running) + DBG(common, "reset interface\n"); + +reset: + /* Deallocate the requests */ + if (common->fsg) { + fsg = common->fsg; + + for (i = 0; i < fsg_num_buffers; ++i) { + struct fsg_buffhd *bh = &common->buffhds[i]; + + if (bh->inreq) { + usb_ep_free_request(fsg->bulk_in, bh->inreq); + bh->inreq = NULL; + } + if (bh->outreq) { + usb_ep_free_request(fsg->bulk_out, bh->outreq); + bh->outreq = NULL; + } + } + + /* Disable the endpoints */ + if (fsg->bulk_in_enabled) { + usb_ep_disable(fsg->bulk_in); + fsg->bulk_in_enabled = 0; + } + if (fsg->bulk_out_enabled) { + usb_ep_disable(fsg->bulk_out); + fsg->bulk_out_enabled = 0; + } + + common->fsg = NULL; + wake_up(&common->fsg_wait); + } + + common->running = 0; + if (!new_fsg || rc) + return rc; + + common->fsg = new_fsg; + fsg = common->fsg; + + /* Enable the endpoints */ + rc = config_ep_by_speed(common->gadget, &(fsg->function), fsg->bulk_in); + if (rc) + goto reset; + rc = usb_ep_enable(fsg->bulk_in); + if (rc) + goto reset; + fsg->bulk_in->driver_data = common; + fsg->bulk_in_enabled = 1; + + rc = config_ep_by_speed(common->gadget, &(fsg->function), + fsg->bulk_out); + if (rc) + goto reset; + rc = usb_ep_enable(fsg->bulk_out); + if (rc) + goto reset; + fsg->bulk_out->driver_data = common; + fsg->bulk_out_enabled = 1; + common->bulk_out_maxpacket = usb_endpoint_maxp(fsg->bulk_out->desc); + clear_bit(IGNORE_BULK_OUT, &fsg->atomic_bitflags); + + /* Allocate the requests */ + for (i = 0; i < fsg_num_buffers; ++i) { + struct fsg_buffhd *bh = &common->buffhds[i]; + + rc = alloc_request(common, fsg->bulk_in, &bh->inreq); + if (rc) + goto reset; + rc = alloc_request(common, fsg->bulk_out, &bh->outreq); + if (rc) + goto reset; + bh->inreq->buf = bh->outreq->buf = bh->buf; + bh->inreq->context = bh->outreq->context = bh; + bh->inreq->complete = bulk_in_complete; + bh->outreq->complete = bulk_out_complete; + } + + common->running = 1; + for (i = 0; i < common->nluns; ++i) + common->luns[i].unit_attention_data = SS_RESET_OCCURRED; + return rc; +} + + +/****************************** ALT CONFIGS ******************************/ + +static int fsg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) +{ + struct fsg_dev *fsg = fsg_from_func(f); + fsg->common->new_fsg = fsg; + raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); + return USB_GADGET_DELAYED_STATUS; +} + +static void fsg_disable(struct usb_function *f) +{ + struct fsg_dev *fsg = fsg_from_func(f); + fsg->common->new_fsg = NULL; + raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); +} + + +/*-------------------------------------------------------------------------*/ + +static void handle_exception(struct fsg_common *common) +{ + siginfo_t info; + int i; + struct fsg_buffhd *bh; + enum fsg_state old_state; + struct fsg_lun *curlun; + unsigned int exception_req_tag; + + /* + * Clear the existing signals. Anything but SIGUSR1 is converted + * into a high-priority EXIT exception. + */ + for (;;) { + int sig = + dequeue_signal_lock(current, ¤t->blocked, &info); + if (!sig) + break; + if (sig != SIGUSR1) { + if (common->state < FSG_STATE_EXIT) + DBG(common, "Main thread exiting on signal\n"); + raise_exception(common, FSG_STATE_EXIT); + } + } + + /* Cancel all the pending transfers */ + if (likely(common->fsg)) { + for (i = 0; i < fsg_num_buffers; ++i) { + bh = &common->buffhds[i]; + if (bh->inreq_busy) + usb_ep_dequeue(common->fsg->bulk_in, bh->inreq); + if (bh->outreq_busy) + usb_ep_dequeue(common->fsg->bulk_out, + bh->outreq); + } + + /* Wait until everything is idle */ + for (;;) { + int num_active = 0; + for (i = 0; i < fsg_num_buffers; ++i) { + bh = &common->buffhds[i]; + num_active += bh->inreq_busy + bh->outreq_busy; + } + if (num_active == 0) + break; + if (sleep_thread(common)) + return; + } + + /* Clear out the controller's fifos */ + if (common->fsg->bulk_in_enabled) + usb_ep_fifo_flush(common->fsg->bulk_in); + if (common->fsg->bulk_out_enabled) + usb_ep_fifo_flush(common->fsg->bulk_out); + } + + /* + * Reset the I/O buffer states and pointers, the SCSI + * state, and the exception. Then invoke the handler. + */ + spin_lock_irq(&common->lock); + + for (i = 0; i < fsg_num_buffers; ++i) { + bh = &common->buffhds[i]; + bh->state = BUF_STATE_EMPTY; + } + common->next_buffhd_to_fill = &common->buffhds[0]; + common->next_buffhd_to_drain = &common->buffhds[0]; + exception_req_tag = common->exception_req_tag; + old_state = common->state; + + if (old_state == FSG_STATE_ABORT_BULK_OUT) + common->state = FSG_STATE_STATUS_PHASE; + else { + for (i = 0; i < common->nluns; ++i) { + curlun = &common->luns[i]; + curlun->prevent_medium_removal = 0; + curlun->sense_data = SS_NO_SENSE; + curlun->unit_attention_data = SS_NO_SENSE; + curlun->sense_data_info = 0; + curlun->info_valid = 0; + } + common->state = FSG_STATE_IDLE; + } + spin_unlock_irq(&common->lock); + + /* Carry out any extra actions required for the exception */ + switch (old_state) { + case FSG_STATE_ABORT_BULK_OUT: + send_status(common); + spin_lock_irq(&common->lock); + if (common->state == FSG_STATE_STATUS_PHASE) + common->state = FSG_STATE_IDLE; + spin_unlock_irq(&common->lock); + break; + + case FSG_STATE_RESET: + /* + * In case we were forced against our will to halt a + * bulk endpoint, clear the halt now. (The SuperH UDC + * requires this.) + */ + if (!fsg_is_set(common)) + break; + if (test_and_clear_bit(IGNORE_BULK_OUT, + &common->fsg->atomic_bitflags)) + usb_ep_clear_halt(common->fsg->bulk_in); + + if (common->ep0_req_tag == exception_req_tag) + ep0_queue(common); /* Complete the status stage */ + + /* + * Technically this should go here, but it would only be + * a waste of time. Ditto for the INTERFACE_CHANGE and + * CONFIG_CHANGE cases. + */ + /* for (i = 0; i < common->nluns; ++i) */ + /* common->luns[i].unit_attention_data = */ + /* SS_RESET_OCCURRED; */ + break; + + case FSG_STATE_CONFIG_CHANGE: + do_set_interface(common, common->new_fsg); + if (common->new_fsg) + usb_composite_setup_continue(common->cdev); + break; + + case FSG_STATE_EXIT: + case FSG_STATE_TERMINATED: + do_set_interface(common, NULL); /* Free resources */ + spin_lock_irq(&common->lock); + common->state = FSG_STATE_TERMINATED; /* Stop the thread */ + spin_unlock_irq(&common->lock); + break; + + case FSG_STATE_INTERFACE_CHANGE: + case FSG_STATE_DISCONNECT: + case FSG_STATE_COMMAND_PHASE: + case FSG_STATE_DATA_PHASE: + case FSG_STATE_STATUS_PHASE: + case FSG_STATE_IDLE: + break; + } +} + + +/*-------------------------------------------------------------------------*/ + +static int fsg_main_thread(void *common_) +{ + struct fsg_common *common = common_; + + /* + * Allow the thread to be killed by a signal, but set the signal mask + * to block everything but INT, TERM, KILL, and USR1. + */ + allow_signal(SIGINT); + allow_signal(SIGTERM); + allow_signal(SIGKILL); + allow_signal(SIGUSR1); + + /* Allow the thread to be frozen */ + set_freezable(); + + /* + * Arrange for userspace references to be interpreted as kernel + * pointers. That way we can pass a kernel pointer to a routine + * that expects a __user pointer and it will work okay. + */ + set_fs(get_ds()); + + /* The main loop */ + while (common->state != FSG_STATE_TERMINATED) { + if (exception_in_progress(common) || signal_pending(current)) { + handle_exception(common); + continue; + } + + if (!common->running) { + sleep_thread(common); + continue; + } + + if (get_next_command(common)) + continue; + + spin_lock_irq(&common->lock); + if (!exception_in_progress(common)) + common->state = FSG_STATE_DATA_PHASE; + spin_unlock_irq(&common->lock); + + if (do_scsi_command(common) || finish_reply(common)) + continue; + + spin_lock_irq(&common->lock); + if (!exception_in_progress(common)) + common->state = FSG_STATE_STATUS_PHASE; + spin_unlock_irq(&common->lock); + + if (send_status(common)) + continue; + + spin_lock_irq(&common->lock); + if (!exception_in_progress(common)) + common->state = FSG_STATE_IDLE; + spin_unlock_irq(&common->lock); + } + + spin_lock_irq(&common->lock); + common->thread_task = NULL; + spin_unlock_irq(&common->lock); + + if (!common->ops || !common->ops->thread_exits + || common->ops->thread_exits(common) < 0) { + struct fsg_lun *curlun = common->luns; + unsigned i = common->nluns; + + down_write(&common->filesem); + for (; i--; ++curlun) { + if (!fsg_lun_is_open(curlun)) + continue; + + fsg_lun_close(curlun); + curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT; + } + up_write(&common->filesem); + } + + /* Let fsg_unbind() know the thread has exited */ + complete_and_exit(&common->thread_notifier, 0); +} + + +/*************************** DEVICE ATTRIBUTES ***************************/ + +static DEVICE_ATTR(ro, 0644, fsg_show_ro, fsg_store_ro); +static DEVICE_ATTR(nofua, 0644, fsg_show_nofua, fsg_store_nofua); +static DEVICE_ATTR(file, 0644, fsg_show_file, fsg_store_file); + +static struct device_attribute dev_attr_ro_cdrom = + __ATTR(ro, 0444, fsg_show_ro, NULL); +static struct device_attribute dev_attr_file_nonremovable = + __ATTR(file, 0444, fsg_show_file, NULL); + + +/****************************** FSG COMMON ******************************/ + +static void fsg_common_release(struct kref *ref); + +static void fsg_lun_release(struct device *dev) +{ + /* Nothing needs to be done */ +} + +static inline void fsg_common_get(struct fsg_common *common) +{ + kref_get(&common->ref); +} + +static inline void fsg_common_put(struct fsg_common *common) +{ + kref_put(&common->ref, fsg_common_release); +} + +static struct fsg_common *fsg_common_init(struct fsg_common *common, + struct usb_composite_dev *cdev, + struct fsg_config *cfg) +{ + struct usb_gadget *gadget = cdev->gadget; + struct fsg_buffhd *bh; + struct fsg_lun *curlun; + struct fsg_lun_config *lcfg; + int nluns, i, rc; + char *pathbuf; + + rc = fsg_num_buffers_validate(); + if (rc != 0) + return ERR_PTR(rc); + + /* Find out how many LUNs there should be */ + nluns = cfg->nluns; + if (nluns < 1 || nluns > FSG_MAX_LUNS) { + dev_err(&gadget->dev, "invalid number of LUNs: %u\n", nluns); + return ERR_PTR(-EINVAL); + } + + /* Allocate? */ + if (!common) { + common = kzalloc(sizeof *common, GFP_KERNEL); + if (!common) + return ERR_PTR(-ENOMEM); + common->free_storage_on_release = 1; + } else { + memset(common, 0, sizeof *common); + common->free_storage_on_release = 0; + } + + common->buffhds = kcalloc(fsg_num_buffers, + sizeof *(common->buffhds), GFP_KERNEL); + if (!common->buffhds) { + if (common->free_storage_on_release) + kfree(common); + return ERR_PTR(-ENOMEM); + } + + common->ops = cfg->ops; + common->private_data = cfg->private_data; + + common->gadget = gadget; + common->ep0 = gadget->ep0; + common->ep0req = cdev->req; + common->cdev = cdev; + + /* Maybe allocate device-global string IDs, and patch descriptors */ + if (fsg_strings[FSG_STRING_INTERFACE].id == 0) { + rc = usb_string_id(cdev); + if (unlikely(rc < 0)) + goto error_release; + fsg_strings[FSG_STRING_INTERFACE].id = rc; + fsg_intf_desc.iInterface = rc; + } + + /* + * Create the LUNs, open their backing files, and register the + * LUN devices in sysfs. + */ + curlun = kcalloc(nluns, sizeof(*curlun), GFP_KERNEL); + if (unlikely(!curlun)) { + rc = -ENOMEM; + goto error_release; + } + common->luns = curlun; + + init_rwsem(&common->filesem); + + for (i = 0, lcfg = cfg->luns; i < nluns; ++i, ++curlun, ++lcfg) { + curlun->cdrom = !!lcfg->cdrom; + curlun->ro = lcfg->cdrom || lcfg->ro; + curlun->initially_ro = curlun->ro; + curlun->removable = lcfg->removable; + curlun->dev.release = fsg_lun_release; + curlun->dev.parent = &gadget->dev; + /* curlun->dev.driver = &fsg_driver.driver; XXX */ + dev_set_drvdata(&curlun->dev, &common->filesem); + dev_set_name(&curlun->dev, "lun%d", i); + + rc = device_register(&curlun->dev); + if (rc) { + INFO(common, "failed to register LUN%d: %d\n", i, rc); + common->nluns = i; + put_device(&curlun->dev); + goto error_release; + } + + rc = device_create_file(&curlun->dev, + curlun->cdrom + ? &dev_attr_ro_cdrom + : &dev_attr_ro); + if (rc) + goto error_luns; + rc = device_create_file(&curlun->dev, + curlun->removable + ? &dev_attr_file + : &dev_attr_file_nonremovable); + if (rc) + goto error_luns; + rc = device_create_file(&curlun->dev, &dev_attr_nofua); + if (rc) + goto error_luns; + + if (lcfg->filename) { + rc = fsg_lun_open(curlun, lcfg->filename); + if (rc) + goto error_luns; + } else if (!curlun->removable) { + ERROR(common, "no file given for LUN%d\n", i); + rc = -EINVAL; + goto error_luns; + } + } + common->nluns = nluns; + + /* Data buffers cyclic list */ + bh = common->buffhds; + i = fsg_num_buffers; + goto buffhds_first_it; + do { + bh->next = bh + 1; + ++bh; +buffhds_first_it: + bh->buf = kmalloc(FSG_BUFLEN, GFP_KERNEL); + if (unlikely(!bh->buf)) { + rc = -ENOMEM; + goto error_release; + } + } while (--i); + bh->next = common->buffhds; + + /* Prepare inquiryString */ + if (cfg->release != 0xffff) { + i = cfg->release; + } else { + i = usb_gadget_controller_number(gadget); + if (i >= 0) { + i = 0x0300 + i; + } else { + WARNING(common, "controller '%s' not recognized\n", + gadget->name); + i = 0x0399; + } + } + snprintf(common->inquiry_string, sizeof common->inquiry_string, + "%-8s%-16s%04x", cfg->vendor_name ?: "Linux", + /* Assume product name dependent on the first LUN */ + cfg->product_name ?: (common->luns->cdrom + ? "File-Stor Gadget" + : "File-CD Gadget"), + i); + + /* + * Some peripheral controllers are known not to be able to + * halt bulk endpoints correctly. If one of them is present, + * disable stalls. + */ + common->can_stall = cfg->can_stall && + !(gadget_is_at91(common->gadget)); + + spin_lock_init(&common->lock); + kref_init(&common->ref); + + /* Tell the thread to start working */ + common->thread_task = + kthread_create(fsg_main_thread, common, "file-storage"); + if (IS_ERR(common->thread_task)) { + rc = PTR_ERR(common->thread_task); + goto error_release; + } + init_completion(&common->thread_notifier); + init_waitqueue_head(&common->fsg_wait); + + /* Information */ + INFO(common, FSG_DRIVER_DESC ", version: " FSG_DRIVER_VERSION "\n"); + INFO(common, "Number of LUNs=%d\n", common->nluns); + + pathbuf = kmalloc(PATH_MAX, GFP_KERNEL); + for (i = 0, nluns = common->nluns, curlun = common->luns; + i < nluns; + ++curlun, ++i) { + char *p = "(no medium)"; + if (fsg_lun_is_open(curlun)) { + p = "(error)"; + if (pathbuf) { + p = d_path(&curlun->filp->f_path, + pathbuf, PATH_MAX); + if (IS_ERR(p)) + p = "(error)"; + } + } + LINFO(curlun, "LUN: %s%s%sfile: %s\n", + curlun->removable ? "removable " : "", + curlun->ro ? "read only " : "", + curlun->cdrom ? "CD-ROM " : "", + p); + } + kfree(pathbuf); + + DBG(common, "I/O thread pid: %d\n", task_pid_nr(common->thread_task)); + + wake_up_process(common->thread_task); + + return common; + +error_luns: + common->nluns = i + 1; +error_release: + common->state = FSG_STATE_TERMINATED; /* The thread is dead */ + /* Call fsg_common_release() directly, ref might be not initialised. */ + fsg_common_release(&common->ref); + return ERR_PTR(rc); +} + +static void fsg_common_release(struct kref *ref) +{ + struct fsg_common *common = container_of(ref, struct fsg_common, ref); + + /* If the thread isn't already dead, tell it to exit now */ + if (common->state != FSG_STATE_TERMINATED) { + raise_exception(common, FSG_STATE_EXIT); + wait_for_completion(&common->thread_notifier); + } + + if (likely(common->luns)) { + struct fsg_lun *lun = common->luns; + unsigned i = common->nluns; + + /* In error recovery common->nluns may be zero. */ + for (; i; --i, ++lun) { + device_remove_file(&lun->dev, &dev_attr_nofua); + device_remove_file(&lun->dev, + lun->cdrom + ? &dev_attr_ro_cdrom + : &dev_attr_ro); + device_remove_file(&lun->dev, + lun->removable + ? &dev_attr_file + : &dev_attr_file_nonremovable); + fsg_lun_close(lun); + device_unregister(&lun->dev); + } + + kfree(common->luns); + } + + { + struct fsg_buffhd *bh = common->buffhds; + unsigned i = fsg_num_buffers; + do { + kfree(bh->buf); + } while (++bh, --i); + } + + kfree(common->buffhds); + if (common->free_storage_on_release) + kfree(common); +} + + +/*-------------------------------------------------------------------------*/ + +static void fsg_unbind(struct usb_configuration *c, struct usb_function *f) +{ + struct fsg_dev *fsg = fsg_from_func(f); + struct fsg_common *common = fsg->common; + + DBG(fsg, "unbind\n"); + if (fsg->common->fsg == fsg) { + fsg->common->new_fsg = NULL; + raise_exception(fsg->common, FSG_STATE_CONFIG_CHANGE); + /* FIXME: make interruptible or killable somehow? */ + wait_event(common->fsg_wait, common->fsg != fsg); + } + + fsg_common_put(common); + usb_free_descriptors(fsg->function.descriptors); + usb_free_descriptors(fsg->function.hs_descriptors); + usb_free_descriptors(fsg->function.ss_descriptors); + kfree(fsg); +} + +static int fsg_bind(struct usb_configuration *c, struct usb_function *f) +{ + struct fsg_dev *fsg = fsg_from_func(f); + struct usb_gadget *gadget = c->cdev->gadget; + int i; + struct usb_ep *ep; + + fsg->gadget = gadget; + + /* New interface */ + i = usb_interface_id(c, f); + if (i < 0) + return i; + fsg_intf_desc.bInterfaceNumber = i; + fsg->interface_number = i; + + /* Find all the endpoints we will use */ + ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_in_desc); + if (!ep) + goto autoconf_fail; + ep->driver_data = fsg->common; /* claim the endpoint */ + fsg->bulk_in = ep; + + ep = usb_ep_autoconfig(gadget, &fsg_fs_bulk_out_desc); + if (!ep) + goto autoconf_fail; + ep->driver_data = fsg->common; /* claim the endpoint */ + fsg->bulk_out = ep; + + /* Copy descriptors */ + f->descriptors = usb_copy_descriptors(fsg_fs_function); + if (unlikely(!f->descriptors)) + return -ENOMEM; + + if (gadget_is_dualspeed(gadget)) { + /* Assume endpoint addresses are the same for both speeds */ + fsg_hs_bulk_in_desc.bEndpointAddress = + fsg_fs_bulk_in_desc.bEndpointAddress; + fsg_hs_bulk_out_desc.bEndpointAddress = + fsg_fs_bulk_out_desc.bEndpointAddress; + f->hs_descriptors = usb_copy_descriptors(fsg_hs_function); + if (unlikely(!f->hs_descriptors)) { + usb_free_descriptors(f->descriptors); + return -ENOMEM; + } + } + + if (gadget_is_superspeed(gadget)) { + unsigned max_burst; + + /* Calculate bMaxBurst, we know packet size is 1024 */ + max_burst = min_t(unsigned, FSG_BUFLEN / 1024, 15); + + fsg_ss_bulk_in_desc.bEndpointAddress = + fsg_fs_bulk_in_desc.bEndpointAddress; + fsg_ss_bulk_in_comp_desc.bMaxBurst = max_burst; + + fsg_ss_bulk_out_desc.bEndpointAddress = + fsg_fs_bulk_out_desc.bEndpointAddress; + fsg_ss_bulk_out_comp_desc.bMaxBurst = max_burst; + + f->ss_descriptors = usb_copy_descriptors(fsg_ss_function); + if (unlikely(!f->ss_descriptors)) { + usb_free_descriptors(f->hs_descriptors); + usb_free_descriptors(f->descriptors); + return -ENOMEM; + } + } + + return 0; + +autoconf_fail: + ERROR(fsg, "unable to autoconfigure all endpoints\n"); + return -ENOTSUPP; +} + + +/****************************** ADD FUNCTION ******************************/ + +static struct usb_gadget_strings *fsg_strings_array[] = { + &fsg_stringtab, + NULL, +}; + +static int fsg_bind_config(struct usb_composite_dev *cdev, + struct usb_configuration *c, + struct fsg_common *common) +{ + struct fsg_dev *fsg; + int rc; + + fsg = kzalloc(sizeof *fsg, GFP_KERNEL); + if (unlikely(!fsg)) + return -ENOMEM; + + fsg->function.name = FSG_DRIVER_DESC; + fsg->function.strings = fsg_strings_array; + fsg->function.bind = fsg_bind; + fsg->function.unbind = fsg_unbind; + fsg->function.setup = fsg_setup; + fsg->function.set_alt = fsg_set_alt; + fsg->function.disable = fsg_disable; + + fsg->common = common; + /* + * Our caller holds a reference to common structure so we + * don't have to be worry about it being freed until we return + * from this function. So instead of incrementing counter now + * and decrement in error recovery we increment it only when + * call to usb_add_function() was successful. + */ + + rc = usb_add_function(c, &fsg->function); + if (unlikely(rc)) + kfree(fsg); + else + fsg_common_get(fsg->common); + return rc; +} + + +/************************* Module parameters *************************/ + +struct fsg_module_parameters { + char *file[FSG_MAX_LUNS]; + bool ro[FSG_MAX_LUNS]; + bool removable[FSG_MAX_LUNS]; + bool cdrom[FSG_MAX_LUNS]; + bool nofua[FSG_MAX_LUNS]; + + unsigned int file_count, ro_count, removable_count, cdrom_count; + unsigned int nofua_count; + unsigned int luns; /* nluns */ + bool stall; /* can_stall */ +}; + +#define _FSG_MODULE_PARAM_ARRAY(prefix, params, name, type, desc) \ + module_param_array_named(prefix ## name, params.name, type, \ + &prefix ## params.name ## _count, \ + S_IRUGO); \ + MODULE_PARM_DESC(prefix ## name, desc) + +#define _FSG_MODULE_PARAM(prefix, params, name, type, desc) \ + module_param_named(prefix ## name, params.name, type, \ + S_IRUGO); \ + MODULE_PARM_DESC(prefix ## name, desc) + +#define FSG_MODULE_PARAMETERS(prefix, params) \ + _FSG_MODULE_PARAM_ARRAY(prefix, params, file, charp, \ + "names of backing files or devices"); \ + _FSG_MODULE_PARAM_ARRAY(prefix, params, ro, bool, \ + "true to force read-only"); \ + _FSG_MODULE_PARAM_ARRAY(prefix, params, removable, bool, \ + "true to simulate removable media"); \ + _FSG_MODULE_PARAM_ARRAY(prefix, params, cdrom, bool, \ + "true to simulate CD-ROM instead of disk"); \ + _FSG_MODULE_PARAM_ARRAY(prefix, params, nofua, bool, \ + "true to ignore SCSI WRITE(10,12) FUA bit"); \ + _FSG_MODULE_PARAM(prefix, params, luns, uint, \ + "number of LUNs"); \ + _FSG_MODULE_PARAM(prefix, params, stall, bool, \ + "false to prevent bulk stalls") + +static void +fsg_config_from_params(struct fsg_config *cfg, + const struct fsg_module_parameters *params) +{ + struct fsg_lun_config *lun; + unsigned i; + + /* Configure LUNs */ + cfg->nluns = + min(params->luns ?: (params->file_count ?: 1u), + (unsigned)FSG_MAX_LUNS); + for (i = 0, lun = cfg->luns; i < cfg->nluns; ++i, ++lun) { + lun->ro = !!params->ro[i]; + lun->cdrom = !!params->cdrom[i]; + lun->removable = !!params->removable[i]; + lun->filename = + params->file_count > i && params->file[i][0] + ? params->file[i] + : 0; + } + + /* Let MSF use defaults */ + cfg->vendor_name = 0; + cfg->product_name = 0; + cfg->release = 0xffff; + + cfg->ops = NULL; + cfg->private_data = NULL; + + /* Finalise */ + cfg->can_stall = params->stall; +} + +static inline struct fsg_common * +fsg_common_from_params(struct fsg_common *common, + struct usb_composite_dev *cdev, + const struct fsg_module_parameters *params) + __attribute__((unused)); +static inline struct fsg_common * +fsg_common_from_params(struct fsg_common *common, + struct usb_composite_dev *cdev, + const struct fsg_module_parameters *params) +{ + struct fsg_config cfg; + fsg_config_from_params(&cfg, params); + return fsg_common_init(common, cdev, &cfg); +} diff --git a/drivers/staging/ccg/f_rndis.c b/drivers/staging/ccg/f_rndis.c new file mode 100644 index 0000000..b1681e4 --- /dev/null +++ b/drivers/staging/ccg/f_rndis.c @@ -0,0 +1,918 @@ +/* + * f_rndis.c -- RNDIS link function driver + * + * Copyright (C) 2003-2005,2008 David Brownell + * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger + * Copyright (C) 2008 Nokia Corporation + * Copyright (C) 2009 Samsung Electronics + * Author: Michal Nazarewicz (mina86@mina86.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +/* #define VERBOSE_DEBUG */ + +#include +#include +#include +#include + +#include + +#include "u_ether.h" +#include "rndis.h" + + +/* + * This function is an RNDIS Ethernet port -- a Microsoft protocol that's + * been promoted instead of the standard CDC Ethernet. The published RNDIS + * spec is ambiguous, incomplete, and needlessly complex. Variants such as + * ActiveSync have even worse status in terms of specification. + * + * In short: it's a protocol controlled by (and for) Microsoft, not for an + * Open ecosystem or markets. Linux supports it *only* because Microsoft + * doesn't support the CDC Ethernet standard. + * + * The RNDIS data transfer model is complex, with multiple Ethernet packets + * per USB message, and out of band data. The control model is built around + * what's essentially an "RNDIS RPC" protocol. It's all wrapped in a CDC ACM + * (modem, not Ethernet) veneer, with those ACM descriptors being entirely + * useless (they're ignored). RNDIS expects to be the only function in its + * configuration, so it's no real help if you need composite devices; and + * it expects to be the first configuration too. + * + * There is a single technical advantage of RNDIS over CDC Ethernet, if you + * discount the fluff that its RPC can be made to deliver: it doesn't need + * a NOP altsetting for the data interface. That lets it work on some of the + * "so smart it's stupid" hardware which takes over configuration changes + * from the software, and adds restrictions like "no altsettings". + * + * Unfortunately MSFT's RNDIS drivers are buggy. They hang or oops, and + * have all sorts of contrary-to-specification oddities that can prevent + * them from working sanely. Since bugfixes (or accurate specs, letting + * Linux work around those bugs) are unlikely to ever come from MSFT, you + * may want to avoid using RNDIS on purely operational grounds. + * + * Omissions from the RNDIS 1.0 specification include: + * + * - Power management ... references data that's scattered around lots + * of other documentation, which is incorrect/incomplete there too. + * + * - There are various undocumented protocol requirements, like the need + * to send garbage in some control-OUT messages. + * + * - MS-Windows drivers sometimes emit undocumented requests. + */ + +struct f_rndis { + struct gether port; + u8 ctrl_id, data_id; + u8 ethaddr[ETH_ALEN]; + u32 vendorID; + const char *manufacturer; + int config; + + struct usb_ep *notify; + struct usb_request *notify_req; + atomic_t notify_count; +}; + +static inline struct f_rndis *func_to_rndis(struct usb_function *f) +{ + return container_of(f, struct f_rndis, port.func); +} + +/* peak (theoretical) bulk transfer rate in bits-per-second */ +static unsigned int bitrate(struct usb_gadget *g) +{ + if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER) + return 13 * 1024 * 8 * 1000 * 8; + else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) + return 13 * 512 * 8 * 1000 * 8; + else + return 19 * 64 * 1 * 1000 * 8; +} + +/*-------------------------------------------------------------------------*/ + +/* + */ + +#define LOG2_STATUS_INTERVAL_MSEC 5 /* 1 << 5 == 32 msec */ +#define STATUS_BYTECOUNT 8 /* 8 bytes data */ + + +/* interface descriptor: */ + +static struct usb_interface_descriptor rndis_control_intf = { + .bLength = sizeof rndis_control_intf, + .bDescriptorType = USB_DT_INTERFACE, + + /* .bInterfaceNumber = DYNAMIC */ + /* status endpoint is optional; this could be patched later */ + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_COMM, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_ACM_PROTO_VENDOR, + /* .iInterface = DYNAMIC */ +}; + +static struct usb_cdc_header_desc header_desc = { + .bLength = sizeof header_desc, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_HEADER_TYPE, + + .bcdCDC = cpu_to_le16(0x0110), +}; + +static struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor = { + .bLength = sizeof call_mgmt_descriptor, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE, + + .bmCapabilities = 0x00, + .bDataInterface = 0x01, +}; + +static struct usb_cdc_acm_descriptor rndis_acm_descriptor = { + .bLength = sizeof rndis_acm_descriptor, + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_ACM_TYPE, + + .bmCapabilities = 0x00, +}; + +static struct usb_cdc_union_desc rndis_union_desc = { + .bLength = sizeof(rndis_union_desc), + .bDescriptorType = USB_DT_CS_INTERFACE, + .bDescriptorSubType = USB_CDC_UNION_TYPE, + /* .bMasterInterface0 = DYNAMIC */ + /* .bSlaveInterface0 = DYNAMIC */ +}; + +/* the data interface has two bulk endpoints */ + +static struct usb_interface_descriptor rndis_data_intf = { + .bLength = sizeof rndis_data_intf, + .bDescriptorType = USB_DT_INTERFACE, + + /* .bInterfaceNumber = DYNAMIC */ + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_CDC_DATA, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + /* .iInterface = DYNAMIC */ +}; + + +static struct usb_interface_assoc_descriptor +rndis_iad_descriptor = { + .bLength = sizeof rndis_iad_descriptor, + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + + .bFirstInterface = 0, /* XXX, hardcoded */ + .bInterfaceCount = 2, // control + data + .bFunctionClass = USB_CLASS_COMM, + .bFunctionSubClass = USB_CDC_SUBCLASS_ETHERNET, + .bFunctionProtocol = USB_CDC_PROTO_NONE, + /* .iFunction = DYNAMIC */ +}; + +/* full speed support: */ + +static struct usb_endpoint_descriptor fs_notify_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT), + .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC, +}; + +static struct usb_endpoint_descriptor fs_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, +}; + +static struct usb_endpoint_descriptor fs_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, +}; + +static struct usb_descriptor_header *eth_fs_function[] = { + (struct usb_descriptor_header *) &rndis_iad_descriptor, + + /* control interface matches ACM, not Ethernet */ + (struct usb_descriptor_header *) &rndis_control_intf, + (struct usb_descriptor_header *) &header_desc, + (struct usb_descriptor_header *) &call_mgmt_descriptor, + (struct usb_descriptor_header *) &rndis_acm_descriptor, + (struct usb_descriptor_header *) &rndis_union_desc, + (struct usb_descriptor_header *) &fs_notify_desc, + + /* data interface has no altsetting */ + (struct usb_descriptor_header *) &rndis_data_intf, + (struct usb_descriptor_header *) &fs_in_desc, + (struct usb_descriptor_header *) &fs_out_desc, + NULL, +}; + +/* high speed support: */ + +static struct usb_endpoint_descriptor hs_notify_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT), + .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4, +}; + +static struct usb_endpoint_descriptor hs_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(512), +}; + +static struct usb_endpoint_descriptor hs_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(512), +}; + +static struct usb_descriptor_header *eth_hs_function[] = { + (struct usb_descriptor_header *) &rndis_iad_descriptor, + + /* control interface matches ACM, not Ethernet */ + (struct usb_descriptor_header *) &rndis_control_intf, + (struct usb_descriptor_header *) &header_desc, + (struct usb_descriptor_header *) &call_mgmt_descriptor, + (struct usb_descriptor_header *) &rndis_acm_descriptor, + (struct usb_descriptor_header *) &rndis_union_desc, + (struct usb_descriptor_header *) &hs_notify_desc, + + /* data interface has no altsetting */ + (struct usb_descriptor_header *) &rndis_data_intf, + (struct usb_descriptor_header *) &hs_in_desc, + (struct usb_descriptor_header *) &hs_out_desc, + NULL, +}; + +/* super speed support: */ + +static struct usb_endpoint_descriptor ss_notify_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT), + .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4, +}; + +static struct usb_ss_ep_comp_descriptor ss_intr_comp_desc = { + .bLength = sizeof ss_intr_comp_desc, + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + /* the following 3 values can be tweaked if necessary */ + /* .bMaxBurst = 0, */ + /* .bmAttributes = 0, */ + .wBytesPerInterval = cpu_to_le16(STATUS_BYTECOUNT), +}; + +static struct usb_endpoint_descriptor ss_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +static struct usb_endpoint_descriptor ss_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +static struct usb_ss_ep_comp_descriptor ss_bulk_comp_desc = { + .bLength = sizeof ss_bulk_comp_desc, + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + /* the following 2 values can be tweaked if necessary */ + /* .bMaxBurst = 0, */ + /* .bmAttributes = 0, */ +}; + +static struct usb_descriptor_header *eth_ss_function[] = { + (struct usb_descriptor_header *) &rndis_iad_descriptor, + + /* control interface matches ACM, not Ethernet */ + (struct usb_descriptor_header *) &rndis_control_intf, + (struct usb_descriptor_header *) &header_desc, + (struct usb_descriptor_header *) &call_mgmt_descriptor, + (struct usb_descriptor_header *) &rndis_acm_descriptor, + (struct usb_descriptor_header *) &rndis_union_desc, + (struct usb_descriptor_header *) &ss_notify_desc, + (struct usb_descriptor_header *) &ss_intr_comp_desc, + + /* data interface has no altsetting */ + (struct usb_descriptor_header *) &rndis_data_intf, + (struct usb_descriptor_header *) &ss_in_desc, + (struct usb_descriptor_header *) &ss_bulk_comp_desc, + (struct usb_descriptor_header *) &ss_out_desc, + (struct usb_descriptor_header *) &ss_bulk_comp_desc, + NULL, +}; + +/* string descriptors: */ + +static struct usb_string rndis_string_defs[] = { + [0].s = "RNDIS Communications Control", + [1].s = "RNDIS Ethernet Data", + [2].s = "RNDIS", + { } /* end of list */ +}; + +static struct usb_gadget_strings rndis_string_table = { + .language = 0x0409, /* en-us */ + .strings = rndis_string_defs, +}; + +static struct usb_gadget_strings *rndis_strings[] = { + &rndis_string_table, + NULL, +}; + +/*-------------------------------------------------------------------------*/ + +static struct sk_buff *rndis_add_header(struct gether *port, + struct sk_buff *skb) +{ + struct sk_buff *skb2; + + skb2 = skb_realloc_headroom(skb, sizeof(struct rndis_packet_msg_type)); + if (skb2) + rndis_add_hdr(skb2); + + dev_kfree_skb_any(skb); + return skb2; +} + +static void rndis_response_available(void *_rndis) +{ + struct f_rndis *rndis = _rndis; + struct usb_request *req = rndis->notify_req; + struct usb_composite_dev *cdev = rndis->port.func.config->cdev; + __le32 *data = req->buf; + int status; + + if (atomic_inc_return(&rndis->notify_count) != 1) + return; + + /* Send RNDIS RESPONSE_AVAILABLE notification; a + * USB_CDC_NOTIFY_RESPONSE_AVAILABLE "should" work too + * + * This is the only notification defined by RNDIS. + */ + data[0] = cpu_to_le32(1); + data[1] = cpu_to_le32(0); + + status = usb_ep_queue(rndis->notify, req, GFP_ATOMIC); + if (status) { + atomic_dec(&rndis->notify_count); + DBG(cdev, "notify/0 --> %d\n", status); + } +} + +static void rndis_response_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct f_rndis *rndis = req->context; + struct usb_composite_dev *cdev = rndis->port.func.config->cdev; + int status = req->status; + + /* after TX: + * - USB_CDC_GET_ENCAPSULATED_RESPONSE (ep0/control) + * - RNDIS_RESPONSE_AVAILABLE (status/irq) + */ + switch (status) { + case -ECONNRESET: + case -ESHUTDOWN: + /* connection gone */ + atomic_set(&rndis->notify_count, 0); + break; + default: + DBG(cdev, "RNDIS %s response error %d, %d/%d\n", + ep->name, status, + req->actual, req->length); + /* FALLTHROUGH */ + case 0: + if (ep != rndis->notify) + break; + + /* handle multiple pending RNDIS_RESPONSE_AVAILABLE + * notifications by resending until we're done + */ + if (atomic_dec_and_test(&rndis->notify_count)) + break; + status = usb_ep_queue(rndis->notify, req, GFP_ATOMIC); + if (status) { + atomic_dec(&rndis->notify_count); + DBG(cdev, "notify/1 --> %d\n", status); + } + break; + } +} + +static void rndis_command_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct f_rndis *rndis = req->context; + struct usb_composite_dev *cdev = rndis->port.func.config->cdev; + int status; + + /* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */ +// spin_lock(&dev->lock); + status = rndis_msg_parser(rndis->config, (u8 *) req->buf); + if (status < 0) + ERROR(cdev, "RNDIS command error %d, %d/%d\n", + status, req->actual, req->length); +// spin_unlock(&dev->lock); +} + +static int +rndis_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) +{ + struct f_rndis *rndis = func_to_rndis(f); + struct usb_composite_dev *cdev = f->config->cdev; + struct usb_request *req = cdev->req; + int value = -EOPNOTSUPP; + u16 w_index = le16_to_cpu(ctrl->wIndex); + u16 w_value = le16_to_cpu(ctrl->wValue); + u16 w_length = le16_to_cpu(ctrl->wLength); + + /* composite driver infrastructure handles everything except + * CDC class messages; interface activation uses set_alt(). + */ + switch ((ctrl->bRequestType << 8) | ctrl->bRequest) { + + /* RNDIS uses the CDC command encapsulation mechanism to implement + * an RPC scheme, with much getting/setting of attributes by OID. + */ + case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) + | USB_CDC_SEND_ENCAPSULATED_COMMAND: + if (w_value || w_index != rndis->ctrl_id) + goto invalid; + /* read the request; process it later */ + value = w_length; + req->complete = rndis_command_complete; + req->context = rndis; + /* later, rndis_response_available() sends a notification */ + break; + + case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) + | USB_CDC_GET_ENCAPSULATED_RESPONSE: + if (w_value || w_index != rndis->ctrl_id) + goto invalid; + else { + u8 *buf; + u32 n; + + /* return the result */ + buf = rndis_get_next_response(rndis->config, &n); + if (buf) { + memcpy(req->buf, buf, n); + req->complete = rndis_response_complete; + req->context = rndis; + rndis_free_response(rndis->config, buf); + value = n; + } + /* else stalls ... spec says to avoid that */ + } + break; + + default: +invalid: + VDBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n", + ctrl->bRequestType, ctrl->bRequest, + w_value, w_index, w_length); + } + + /* respond with data transfer or status phase? */ + if (value >= 0) { + DBG(cdev, "rndis req%02x.%02x v%04x i%04x l%d\n", + ctrl->bRequestType, ctrl->bRequest, + w_value, w_index, w_length); + req->zero = (value < w_length); + req->length = value; + value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); + if (value < 0) + ERROR(cdev, "rndis response on err %d\n", value); + } + + /* device either stalls (value < 0) or reports success */ + return value; +} + + +static int rndis_set_alt(struct usb_function *f, unsigned intf, unsigned alt) +{ + struct f_rndis *rndis = func_to_rndis(f); + struct usb_composite_dev *cdev = f->config->cdev; + + /* we know alt == 0 */ + + if (intf == rndis->ctrl_id) { + if (rndis->notify->driver_data) { + VDBG(cdev, "reset rndis control %d\n", intf); + usb_ep_disable(rndis->notify); + } + if (!rndis->notify->desc) { + VDBG(cdev, "init rndis ctrl %d\n", intf); + if (config_ep_by_speed(cdev->gadget, f, rndis->notify)) + goto fail; + } + usb_ep_enable(rndis->notify); + rndis->notify->driver_data = rndis; + + } else if (intf == rndis->data_id) { + struct net_device *net; + + if (rndis->port.in_ep->driver_data) { + DBG(cdev, "reset rndis\n"); + gether_disconnect(&rndis->port); + } + + if (!rndis->port.in_ep->desc || !rndis->port.out_ep->desc) { + DBG(cdev, "init rndis\n"); + if (config_ep_by_speed(cdev->gadget, f, + rndis->port.in_ep) || + config_ep_by_speed(cdev->gadget, f, + rndis->port.out_ep)) { + rndis->port.in_ep->desc = NULL; + rndis->port.out_ep->desc = NULL; + goto fail; + } + } + + /* Avoid ZLPs; they can be troublesome. */ + rndis->port.is_zlp_ok = false; + + /* RNDIS should be in the "RNDIS uninitialized" state, + * either never activated or after rndis_uninit(). + * + * We don't want data to flow here until a nonzero packet + * filter is set, at which point it enters "RNDIS data + * initialized" state ... but we do want the endpoints + * to be activated. It's a strange little state. + * + * REVISIT the RNDIS gadget code has done this wrong for a + * very long time. We need another call to the link layer + * code -- gether_updown(...bool) maybe -- to do it right. + */ + rndis->port.cdc_filter = 0; + + DBG(cdev, "RNDIS RX/TX early activation ... \n"); + net = gether_connect(&rndis->port); + if (IS_ERR(net)) + return PTR_ERR(net); + + rndis_set_param_dev(rndis->config, net, + &rndis->port.cdc_filter); + } else + goto fail; + + return 0; +fail: + return -EINVAL; +} + +static void rndis_disable(struct usb_function *f) +{ + struct f_rndis *rndis = func_to_rndis(f); + struct usb_composite_dev *cdev = f->config->cdev; + + if (!rndis->notify->driver_data) + return; + + DBG(cdev, "rndis deactivated\n"); + + rndis_uninit(rndis->config); + gether_disconnect(&rndis->port); + + usb_ep_disable(rndis->notify); + rndis->notify->driver_data = NULL; +} + +/*-------------------------------------------------------------------------*/ + +/* + * This isn't quite the same mechanism as CDC Ethernet, since the + * notification scheme passes less data, but the same set of link + * states must be tested. A key difference is that altsettings are + * not used to tell whether the link should send packets or not. + */ + +static void rndis_open(struct gether *geth) +{ + struct f_rndis *rndis = func_to_rndis(&geth->func); + struct usb_composite_dev *cdev = geth->func.config->cdev; + + DBG(cdev, "%s\n", __func__); + + rndis_set_param_medium(rndis->config, RNDIS_MEDIUM_802_3, + bitrate(cdev->gadget) / 100); + rndis_signal_connect(rndis->config); +} + +static void rndis_close(struct gether *geth) +{ + struct f_rndis *rndis = func_to_rndis(&geth->func); + + DBG(geth->func.config->cdev, "%s\n", __func__); + + rndis_set_param_medium(rndis->config, RNDIS_MEDIUM_802_3, 0); + rndis_signal_disconnect(rndis->config); +} + +/*-------------------------------------------------------------------------*/ + +/* ethernet function driver setup/binding */ + +static int +rndis_bind(struct usb_configuration *c, struct usb_function *f) +{ + struct usb_composite_dev *cdev = c->cdev; + struct f_rndis *rndis = func_to_rndis(f); + int status; + struct usb_ep *ep; + + /* allocate instance-specific interface IDs */ + status = usb_interface_id(c, f); + if (status < 0) + goto fail; + rndis->ctrl_id = status; + rndis_iad_descriptor.bFirstInterface = status; + + rndis_control_intf.bInterfaceNumber = status; + rndis_union_desc.bMasterInterface0 = status; + + status = usb_interface_id(c, f); + if (status < 0) + goto fail; + rndis->data_id = status; + + rndis_data_intf.bInterfaceNumber = status; + rndis_union_desc.bSlaveInterface0 = status; + + status = -ENODEV; + + /* allocate instance-specific endpoints */ + ep = usb_ep_autoconfig(cdev->gadget, &fs_in_desc); + if (!ep) + goto fail; + rndis->port.in_ep = ep; + ep->driver_data = cdev; /* claim */ + + ep = usb_ep_autoconfig(cdev->gadget, &fs_out_desc); + if (!ep) + goto fail; + rndis->port.out_ep = ep; + ep->driver_data = cdev; /* claim */ + + /* NOTE: a status/notification endpoint is, strictly speaking, + * optional. We don't treat it that way though! It's simpler, + * and some newer profiles don't treat it as optional. + */ + ep = usb_ep_autoconfig(cdev->gadget, &fs_notify_desc); + if (!ep) + goto fail; + rndis->notify = ep; + ep->driver_data = cdev; /* claim */ + + status = -ENOMEM; + + /* allocate notification request and buffer */ + rndis->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL); + if (!rndis->notify_req) + goto fail; + rndis->notify_req->buf = kmalloc(STATUS_BYTECOUNT, GFP_KERNEL); + if (!rndis->notify_req->buf) + goto fail; + rndis->notify_req->length = STATUS_BYTECOUNT; + rndis->notify_req->context = rndis; + rndis->notify_req->complete = rndis_response_complete; + + /* copy descriptors, and track endpoint copies */ + f->descriptors = usb_copy_descriptors(eth_fs_function); + if (!f->descriptors) + goto fail; + + /* support all relevant hardware speeds... we expect that when + * hardware is dual speed, all bulk-capable endpoints work at + * both speeds + */ + if (gadget_is_dualspeed(c->cdev->gadget)) { + hs_in_desc.bEndpointAddress = + fs_in_desc.bEndpointAddress; + hs_out_desc.bEndpointAddress = + fs_out_desc.bEndpointAddress; + hs_notify_desc.bEndpointAddress = + fs_notify_desc.bEndpointAddress; + + /* copy descriptors, and track endpoint copies */ + f->hs_descriptors = usb_copy_descriptors(eth_hs_function); + if (!f->hs_descriptors) + goto fail; + } + + if (gadget_is_superspeed(c->cdev->gadget)) { + ss_in_desc.bEndpointAddress = + fs_in_desc.bEndpointAddress; + ss_out_desc.bEndpointAddress = + fs_out_desc.bEndpointAddress; + ss_notify_desc.bEndpointAddress = + fs_notify_desc.bEndpointAddress; + + /* copy descriptors, and track endpoint copies */ + f->ss_descriptors = usb_copy_descriptors(eth_ss_function); + if (!f->ss_descriptors) + goto fail; + } + + rndis->port.open = rndis_open; + rndis->port.close = rndis_close; + + status = rndis_register(rndis_response_available, rndis); + if (status < 0) + goto fail; + rndis->config = status; + + rndis_set_param_medium(rndis->config, RNDIS_MEDIUM_802_3, 0); + rndis_set_host_mac(rndis->config, rndis->ethaddr); + + if (rndis->manufacturer && rndis->vendorID && + rndis_set_param_vendor(rndis->config, rndis->vendorID, + rndis->manufacturer)) + goto fail; + + /* NOTE: all that is done without knowing or caring about + * the network link ... which is unavailable to this code + * until we're activated via set_alt(). + */ + + DBG(cdev, "RNDIS: %s speed IN/%s OUT/%s NOTIFY/%s\n", + gadget_is_superspeed(c->cdev->gadget) ? "super" : + gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", + rndis->port.in_ep->name, rndis->port.out_ep->name, + rndis->notify->name); + return 0; + +fail: + if (gadget_is_superspeed(c->cdev->gadget) && f->ss_descriptors) + usb_free_descriptors(f->ss_descriptors); + if (gadget_is_dualspeed(c->cdev->gadget) && f->hs_descriptors) + usb_free_descriptors(f->hs_descriptors); + if (f->descriptors) + usb_free_descriptors(f->descriptors); + + if (rndis->notify_req) { + kfree(rndis->notify_req->buf); + usb_ep_free_request(rndis->notify, rndis->notify_req); + } + + /* we might as well release our claims on endpoints */ + if (rndis->notify) + rndis->notify->driver_data = NULL; + if (rndis->port.out_ep->desc) + rndis->port.out_ep->driver_data = NULL; + if (rndis->port.in_ep->desc) + rndis->port.in_ep->driver_data = NULL; + + ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); + + return status; +} + +static void +rndis_unbind(struct usb_configuration *c, struct usb_function *f) +{ + struct f_rndis *rndis = func_to_rndis(f); + + rndis_deregister(rndis->config); + rndis_exit(); + rndis_string_defs[0].id = 0; + + if (gadget_is_superspeed(c->cdev->gadget)) + usb_free_descriptors(f->ss_descriptors); + if (gadget_is_dualspeed(c->cdev->gadget)) + usb_free_descriptors(f->hs_descriptors); + usb_free_descriptors(f->descriptors); + + kfree(rndis->notify_req->buf); + usb_ep_free_request(rndis->notify, rndis->notify_req); + + kfree(rndis); +} + +/* Some controllers can't support RNDIS ... */ +static inline bool can_support_rndis(struct usb_configuration *c) +{ + /* everything else is *presumably* fine */ + return true; +} + +int +rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], + u32 vendorID, const char *manufacturer) +{ + struct f_rndis *rndis; + int status; + + if (!can_support_rndis(c) || !ethaddr) + return -EINVAL; + + /* maybe allocate device-global string IDs */ + if (rndis_string_defs[0].id == 0) { + + /* ... and setup RNDIS itself */ + status = rndis_init(); + if (status < 0) + return status; + + /* control interface label */ + status = usb_string_id(c->cdev); + if (status < 0) + return status; + rndis_string_defs[0].id = status; + rndis_control_intf.iInterface = status; + + /* data interface label */ + status = usb_string_id(c->cdev); + if (status < 0) + return status; + rndis_string_defs[1].id = status; + rndis_data_intf.iInterface = status; + + /* IAD iFunction label */ + status = usb_string_id(c->cdev); + if (status < 0) + return status; + rndis_string_defs[2].id = status; + rndis_iad_descriptor.iFunction = status; + } + + /* allocate and initialize one new instance */ + status = -ENOMEM; + rndis = kzalloc(sizeof *rndis, GFP_KERNEL); + if (!rndis) + goto fail; + + memcpy(rndis->ethaddr, ethaddr, ETH_ALEN); + rndis->vendorID = vendorID; + rndis->manufacturer = manufacturer; + + /* RNDIS activates when the host changes this filter */ + rndis->port.cdc_filter = 0; + + /* RNDIS has special (and complex) framing */ + rndis->port.header_len = sizeof(struct rndis_packet_msg_type); + rndis->port.wrap = rndis_add_header; + rndis->port.unwrap = rndis_rm_hdr; + + rndis->port.func.name = "rndis"; + rndis->port.func.strings = rndis_strings; + /* descriptors are per-instance copies */ + rndis->port.func.bind = rndis_bind; + rndis->port.func.unbind = rndis_unbind; + rndis->port.func.set_alt = rndis_set_alt; + rndis->port.func.setup = rndis_setup; + rndis->port.func.disable = rndis_disable; + + status = usb_add_function(c, &rndis->port.func); + if (status) { + kfree(rndis); +fail: + rndis_exit(); + } + return status; +} diff --git a/drivers/staging/ccg/gadget_chips.h b/drivers/staging/ccg/gadget_chips.h new file mode 100644 index 0000000..0ccca58 --- /dev/null +++ b/drivers/staging/ccg/gadget_chips.h @@ -0,0 +1,150 @@ +/* + * USB device controllers have lots of quirks. Use these macros in + * gadget drivers or other code that needs to deal with them, and which + * autoconfigures instead of using early binding to the hardware. + * + * This SHOULD eventually work like the ARM mach_is_*() stuff, driven by + * some config file that gets updated as new hardware is supported. + * (And avoiding all runtime comparisons in typical one-choice configs!) + * + * NOTE: some of these controller drivers may not be available yet. + * Some are available on 2.4 kernels; several are available, but not + * yet pushed in the 2.6 mainline tree. + */ + +#ifndef __GADGET_CHIPS_H +#define __GADGET_CHIPS_H + +/* + * NOTICE: the entries below are alphabetical and should be kept + * that way. + * + * Always be sure to add new entries to the correct position or + * accept the bashing later. + * + * If you have forgotten the alphabetical order let VIM/EMACS + * do that for you. + */ +#define gadget_is_amd5536udc(g) (!strcmp("amd5536udc", (g)->name)) +#define gadget_is_at91(g) (!strcmp("at91_udc", (g)->name)) +#define gadget_is_atmel_usba(g) (!strcmp("atmel_usba_udc", (g)->name)) +#define gadget_is_bcm63xx(g) (!strcmp("bcm63xx_udc", (g)->name)) +#define gadget_is_ci13xxx_msm(g) (!strcmp("ci13xxx_msm", (g)->name)) +#define gadget_is_ci13xxx_pci(g) (!strcmp("ci13xxx_pci", (g)->name)) +#define gadget_is_dummy(g) (!strcmp("dummy_udc", (g)->name)) +#define gadget_is_dwc3(g) (!strcmp("dwc3-gadget", (g)->name)) +#define gadget_is_fsl_qe(g) (!strcmp("fsl_qe_udc", (g)->name)) +#define gadget_is_fsl_usb2(g) (!strcmp("fsl-usb2-udc", (g)->name)) +#define gadget_is_goku(g) (!strcmp("goku_udc", (g)->name)) +#define gadget_is_imx(g) (!strcmp("imx_udc", (g)->name)) +#define gadget_is_langwell(g) (!strcmp("langwell_udc", (g)->name)) +#define gadget_is_lpc32xx(g) (!strcmp("lpc32xx_udc", (g)->name)) +#define gadget_is_m66592(g) (!strcmp("m66592_udc", (g)->name)) +#define gadget_is_musbhdrc(g) (!strcmp("musb-hdrc", (g)->name)) +#define gadget_is_net2272(g) (!strcmp("net2272", (g)->name)) +#define gadget_is_net2280(g) (!strcmp("net2280", (g)->name)) +#define gadget_is_omap(g) (!strcmp("omap_udc", (g)->name)) +#define gadget_is_pch(g) (!strcmp("pch_udc", (g)->name)) +#define gadget_is_pxa(g) (!strcmp("pxa25x_udc", (g)->name)) +#define gadget_is_pxa27x(g) (!strcmp("pxa27x_udc", (g)->name)) +#define gadget_is_r8a66597(g) (!strcmp("r8a66597_udc", (g)->name)) +#define gadget_is_renesas_usbhs(g) (!strcmp("renesas_usbhs_udc", (g)->name)) +#define gadget_is_s3c2410(g) (!strcmp("s3c2410_udc", (g)->name)) +#define gadget_is_s3c_hsotg(g) (!strcmp("s3c-hsotg", (g)->name)) +#define gadget_is_s3c_hsudc(g) (!strcmp("s3c-hsudc", (g)->name)) + +/** + * usb_gadget_controller_number - support bcdDevice id convention + * @gadget: the controller being driven + * + * Return a 2-digit BCD value associated with the peripheral controller, + * suitable for use as part of a bcdDevice value, or a negative error code. + * + * NOTE: this convention is purely optional, and has no meaning in terms of + * any USB specification. If you want to use a different convention in your + * gadget driver firmware -- maybe a more formal revision ID -- feel free. + * + * Hosts see these bcdDevice numbers, and are allowed (but not encouraged!) + * to change their behavior accordingly. For example it might help avoiding + * some chip bug. + */ +static inline int usb_gadget_controller_number(struct usb_gadget *gadget) +{ + if (gadget_is_net2280(gadget)) + return 0x01; + else if (gadget_is_dummy(gadget)) + return 0x02; + else if (gadget_is_pxa(gadget)) + return 0x03; + else if (gadget_is_goku(gadget)) + return 0x06; + else if (gadget_is_omap(gadget)) + return 0x08; + else if (gadget_is_pxa27x(gadget)) + return 0x11; + else if (gadget_is_s3c2410(gadget)) + return 0x12; + else if (gadget_is_at91(gadget)) + return 0x13; + else if (gadget_is_imx(gadget)) + return 0x14; + else if (gadget_is_musbhdrc(gadget)) + return 0x16; + else if (gadget_is_atmel_usba(gadget)) + return 0x18; + else if (gadget_is_fsl_usb2(gadget)) + return 0x19; + else if (gadget_is_amd5536udc(gadget)) + return 0x20; + else if (gadget_is_m66592(gadget)) + return 0x21; + else if (gadget_is_fsl_qe(gadget)) + return 0x22; + else if (gadget_is_ci13xxx_pci(gadget)) + return 0x23; + else if (gadget_is_langwell(gadget)) + return 0x24; + else if (gadget_is_r8a66597(gadget)) + return 0x25; + else if (gadget_is_s3c_hsotg(gadget)) + return 0x26; + else if (gadget_is_pch(gadget)) + return 0x27; + else if (gadget_is_ci13xxx_msm(gadget)) + return 0x28; + else if (gadget_is_renesas_usbhs(gadget)) + return 0x29; + else if (gadget_is_s3c_hsudc(gadget)) + return 0x30; + else if (gadget_is_net2272(gadget)) + return 0x31; + else if (gadget_is_dwc3(gadget)) + return 0x32; + else if (gadget_is_lpc32xx(gadget)) + return 0x33; + else if (gadget_is_bcm63xx(gadget)) + return 0x34; + + return -ENOENT; +} + + +/** + * gadget_supports_altsettings - return true if altsettings work + * @gadget: the gadget in question + */ +static inline bool gadget_supports_altsettings(struct usb_gadget *gadget) +{ + /* PXA 21x/25x/26x has no altsettings at all */ + if (gadget_is_pxa(gadget)) + return false; + + /* PXA 27x and 3xx have *broken* altsetting support */ + if (gadget_is_pxa27x(gadget)) + return false; + + /* Everything else is *presumably* fine ... */ + return true; +} + +#endif /* __GADGET_CHIPS_H */ diff --git a/drivers/staging/ccg/ndis.h b/drivers/staging/ccg/ndis.h new file mode 100644 index 0000000..a19f72d --- /dev/null +++ b/drivers/staging/ccg/ndis.h @@ -0,0 +1,47 @@ +/* + * ndis.h + * + * ntddndis.h modified by Benedikt Spranger + * + * Thanks to the cygwin development team, + * espacially to Casper S. Hornstrup + * + * THIS SOFTWARE IS NOT COPYRIGHTED + * + * This source code is offered for use in the public domain. You may + * use, modify or distribute it freely. + */ + +#ifndef _LINUX_NDIS_H +#define _LINUX_NDIS_H + +enum NDIS_DEVICE_POWER_STATE { + NdisDeviceStateUnspecified = 0, + NdisDeviceStateD0, + NdisDeviceStateD1, + NdisDeviceStateD2, + NdisDeviceStateD3, + NdisDeviceStateMaximum +}; + +struct NDIS_PM_WAKE_UP_CAPABILITIES { + enum NDIS_DEVICE_POWER_STATE MinMagicPacketWakeUp; + enum NDIS_DEVICE_POWER_STATE MinPatternWakeUp; + enum NDIS_DEVICE_POWER_STATE MinLinkChangeWakeUp; +}; + +struct NDIS_PNP_CAPABILITIES { + __le32 Flags; + struct NDIS_PM_WAKE_UP_CAPABILITIES WakeUpCapabilities; +}; + +struct NDIS_PM_PACKET_PATTERN { + __le32 Priority; + __le32 Reserved; + __le32 MaskSize; + __le32 PatternOffset; + __le32 PatternSize; + __le32 PatternFlags; +}; + +#endif /* _LINUX_NDIS_H */ diff --git a/drivers/staging/ccg/rndis.c b/drivers/staging/ccg/rndis.c new file mode 100644 index 0000000..e4192b8 --- /dev/null +++ b/drivers/staging/ccg/rndis.c @@ -0,0 +1,1175 @@ +/* + * RNDIS MSG parser + * + * Authors: Benedikt Spranger, Pengutronix + * Robert Schwebel, Pengutronix + * + * 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. + * + * This software was originally developed in conformance with + * Microsoft's Remote NDIS Specification License Agreement. + * + * 03/12/2004 Kai-Uwe Bloem + * Fixed message length bug in init_response + * + * 03/25/2004 Kai-Uwe Bloem + * Fixed rndis_rm_hdr length bug. + * + * Copyright (C) 2004 by David Brownell + * updates to merge with Linux 2.6, better match RNDIS spec + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +#undef VERBOSE_DEBUG + +#include "rndis.h" + + +/* The driver for your USB chip needs to support ep0 OUT to work with + * RNDIS, plus all three CDC Ethernet endpoints (interrupt not optional). + * + * Windows hosts need an INF file like Documentation/usb/linux.inf + * and will be happier if you provide the host_addr module parameter. + */ + +#if 0 +static int rndis_debug = 0; +module_param (rndis_debug, int, 0); +MODULE_PARM_DESC (rndis_debug, "enable debugging"); +#else +#define rndis_debug 0 +#endif + +#define RNDIS_MAX_CONFIGS 1 + + +static rndis_params rndis_per_dev_params[RNDIS_MAX_CONFIGS]; + +/* Driver Version */ +static const __le32 rndis_driver_version = cpu_to_le32(1); + +/* Function Prototypes */ +static rndis_resp_t *rndis_add_response(int configNr, u32 length); + + +/* supported OIDs */ +static const u32 oid_supported_list[] = +{ + /* the general stuff */ + RNDIS_OID_GEN_SUPPORTED_LIST, + RNDIS_OID_GEN_HARDWARE_STATUS, + RNDIS_OID_GEN_MEDIA_SUPPORTED, + RNDIS_OID_GEN_MEDIA_IN_USE, + RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE, + RNDIS_OID_GEN_LINK_SPEED, + RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE, + RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE, + RNDIS_OID_GEN_VENDOR_ID, + RNDIS_OID_GEN_VENDOR_DESCRIPTION, + RNDIS_OID_GEN_VENDOR_DRIVER_VERSION, + RNDIS_OID_GEN_CURRENT_PACKET_FILTER, + RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE, + RNDIS_OID_GEN_MEDIA_CONNECT_STATUS, + RNDIS_OID_GEN_PHYSICAL_MEDIUM, + + /* the statistical stuff */ + RNDIS_OID_GEN_XMIT_OK, + RNDIS_OID_GEN_RCV_OK, + RNDIS_OID_GEN_XMIT_ERROR, + RNDIS_OID_GEN_RCV_ERROR, + RNDIS_OID_GEN_RCV_NO_BUFFER, +#ifdef RNDIS_OPTIONAL_STATS + RNDIS_OID_GEN_DIRECTED_BYTES_XMIT, + RNDIS_OID_GEN_DIRECTED_FRAMES_XMIT, + RNDIS_OID_GEN_MULTICAST_BYTES_XMIT, + RNDIS_OID_GEN_MULTICAST_FRAMES_XMIT, + RNDIS_OID_GEN_BROADCAST_BYTES_XMIT, + RNDIS_OID_GEN_BROADCAST_FRAMES_XMIT, + RNDIS_OID_GEN_DIRECTED_BYTES_RCV, + RNDIS_OID_GEN_DIRECTED_FRAMES_RCV, + RNDIS_OID_GEN_MULTICAST_BYTES_RCV, + RNDIS_OID_GEN_MULTICAST_FRAMES_RCV, + RNDIS_OID_GEN_BROADCAST_BYTES_RCV, + RNDIS_OID_GEN_BROADCAST_FRAMES_RCV, + RNDIS_OID_GEN_RCV_CRC_ERROR, + RNDIS_OID_GEN_TRANSMIT_QUEUE_LENGTH, +#endif /* RNDIS_OPTIONAL_STATS */ + + /* mandatory 802.3 */ + /* the general stuff */ + RNDIS_OID_802_3_PERMANENT_ADDRESS, + RNDIS_OID_802_3_CURRENT_ADDRESS, + RNDIS_OID_802_3_MULTICAST_LIST, + RNDIS_OID_802_3_MAC_OPTIONS, + RNDIS_OID_802_3_MAXIMUM_LIST_SIZE, + + /* the statistical stuff */ + RNDIS_OID_802_3_RCV_ERROR_ALIGNMENT, + RNDIS_OID_802_3_XMIT_ONE_COLLISION, + RNDIS_OID_802_3_XMIT_MORE_COLLISIONS, +#ifdef RNDIS_OPTIONAL_STATS + RNDIS_OID_802_3_XMIT_DEFERRED, + RNDIS_OID_802_3_XMIT_MAX_COLLISIONS, + RNDIS_OID_802_3_RCV_OVERRUN, + RNDIS_OID_802_3_XMIT_UNDERRUN, + RNDIS_OID_802_3_XMIT_HEARTBEAT_FAILURE, + RNDIS_OID_802_3_XMIT_TIMES_CRS_LOST, + RNDIS_OID_802_3_XMIT_LATE_COLLISIONS, +#endif /* RNDIS_OPTIONAL_STATS */ + +#ifdef RNDIS_PM + /* PM and wakeup are "mandatory" for USB, but the RNDIS specs + * don't say what they mean ... and the NDIS specs are often + * confusing and/or ambiguous in this context. (That is, more + * so than their specs for the other OIDs.) + * + * FIXME someone who knows what these should do, please + * implement them! + */ + + /* power management */ + OID_PNP_CAPABILITIES, + OID_PNP_QUERY_POWER, + OID_PNP_SET_POWER, + +#ifdef RNDIS_WAKEUP + /* wake up host */ + OID_PNP_ENABLE_WAKE_UP, + OID_PNP_ADD_WAKE_UP_PATTERN, + OID_PNP_REMOVE_WAKE_UP_PATTERN, +#endif /* RNDIS_WAKEUP */ +#endif /* RNDIS_PM */ +}; + + +/* NDIS Functions */ +static int gen_ndis_query_resp(int configNr, u32 OID, u8 *buf, + unsigned buf_len, rndis_resp_t *r) +{ + int retval = -ENOTSUPP; + u32 length = 4; /* usually */ + __le32 *outbuf; + int i, count; + rndis_query_cmplt_type *resp; + struct net_device *net; + struct rtnl_link_stats64 temp; + const struct rtnl_link_stats64 *stats; + + if (!r) return -ENOMEM; + resp = (rndis_query_cmplt_type *)r->buf; + + if (!resp) return -ENOMEM; + + if (buf_len && rndis_debug > 1) { + pr_debug("query OID %08x value, len %d:\n", OID, buf_len); + for (i = 0; i < buf_len; i += 16) { + pr_debug("%03d: %08x %08x %08x %08x\n", i, + get_unaligned_le32(&buf[i]), + get_unaligned_le32(&buf[i + 4]), + get_unaligned_le32(&buf[i + 8]), + get_unaligned_le32(&buf[i + 12])); + } + } + + /* response goes here, right after the header */ + outbuf = (__le32 *)&resp[1]; + resp->InformationBufferOffset = cpu_to_le32(16); + + net = rndis_per_dev_params[configNr].dev; + stats = dev_get_stats(net, &temp); + + switch (OID) { + + /* general oids (table 4-1) */ + + /* mandatory */ + case RNDIS_OID_GEN_SUPPORTED_LIST: + pr_debug("%s: RNDIS_OID_GEN_SUPPORTED_LIST\n", __func__); + length = sizeof(oid_supported_list); + count = length / sizeof(u32); + for (i = 0; i < count; i++) + outbuf[i] = cpu_to_le32(oid_supported_list[i]); + retval = 0; + break; + + /* mandatory */ + case RNDIS_OID_GEN_HARDWARE_STATUS: + pr_debug("%s: RNDIS_OID_GEN_HARDWARE_STATUS\n", __func__); + /* Bogus question! + * Hardware must be ready to receive high level protocols. + * BTW: + * reddite ergo quae sunt Caesaris Caesari + * et quae sunt Dei Deo! + */ + *outbuf = cpu_to_le32(0); + retval = 0; + break; + + /* mandatory */ + case RNDIS_OID_GEN_MEDIA_SUPPORTED: + pr_debug("%s: RNDIS_OID_GEN_MEDIA_SUPPORTED\n", __func__); + *outbuf = cpu_to_le32(rndis_per_dev_params[configNr].medium); + retval = 0; + break; + + /* mandatory */ + case RNDIS_OID_GEN_MEDIA_IN_USE: + pr_debug("%s: RNDIS_OID_GEN_MEDIA_IN_USE\n", __func__); + /* one medium, one transport... (maybe you do it better) */ + *outbuf = cpu_to_le32(rndis_per_dev_params[configNr].medium); + retval = 0; + break; + + /* mandatory */ + case RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE: + pr_debug("%s: RNDIS_OID_GEN_MAXIMUM_FRAME_SIZE\n", __func__); + if (rndis_per_dev_params[configNr].dev) { + *outbuf = cpu_to_le32( + rndis_per_dev_params[configNr].dev->mtu); + retval = 0; + } + break; + + /* mandatory */ + case RNDIS_OID_GEN_LINK_SPEED: + if (rndis_debug > 1) + pr_debug("%s: RNDIS_OID_GEN_LINK_SPEED\n", __func__); + if (rndis_per_dev_params[configNr].media_state + == RNDIS_MEDIA_STATE_DISCONNECTED) + *outbuf = cpu_to_le32(0); + else + *outbuf = cpu_to_le32( + rndis_per_dev_params[configNr].speed); + retval = 0; + break; + + /* mandatory */ + case RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE: + pr_debug("%s: RNDIS_OID_GEN_TRANSMIT_BLOCK_SIZE\n", __func__); + if (rndis_per_dev_params[configNr].dev) { + *outbuf = cpu_to_le32( + rndis_per_dev_params[configNr].dev->mtu); + retval = 0; + } + break; + + /* mandatory */ + case RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE: + pr_debug("%s: RNDIS_OID_GEN_RECEIVE_BLOCK_SIZE\n", __func__); + if (rndis_per_dev_params[configNr].dev) { + *outbuf = cpu_to_le32( + rndis_per_dev_params[configNr].dev->mtu); + retval = 0; + } + break; + + /* mandatory */ + case RNDIS_OID_GEN_VENDOR_ID: + pr_debug("%s: RNDIS_OID_GEN_VENDOR_ID\n", __func__); + *outbuf = cpu_to_le32( + rndis_per_dev_params[configNr].vendorID); + retval = 0; + break; + + /* mandatory */ + case RNDIS_OID_GEN_VENDOR_DESCRIPTION: + pr_debug("%s: RNDIS_OID_GEN_VENDOR_DESCRIPTION\n", __func__); + if (rndis_per_dev_params[configNr].vendorDescr) { + length = strlen(rndis_per_dev_params[configNr]. + vendorDescr); + memcpy(outbuf, + rndis_per_dev_params[configNr].vendorDescr, + length); + } else { + outbuf[0] = 0; + } + retval = 0; + break; + + case RNDIS_OID_GEN_VENDOR_DRIVER_VERSION: + pr_debug("%s: RNDIS_OID_GEN_VENDOR_DRIVER_VERSION\n", __func__); + /* Created as LE */ + *outbuf = rndis_driver_version; + retval = 0; + break; + + /* mandatory */ + case RNDIS_OID_GEN_CURRENT_PACKET_FILTER: + pr_debug("%s: RNDIS_OID_GEN_CURRENT_PACKET_FILTER\n", __func__); + *outbuf = cpu_to_le32(*rndis_per_dev_params[configNr].filter); + retval = 0; + break; + + /* mandatory */ + case RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE: + pr_debug("%s: RNDIS_OID_GEN_MAXIMUM_TOTAL_SIZE\n", __func__); + *outbuf = cpu_to_le32(RNDIS_MAX_TOTAL_SIZE); + retval = 0; + break; + + /* mandatory */ + case RNDIS_OID_GEN_MEDIA_CONNECT_STATUS: + if (rndis_debug > 1) + pr_debug("%s: RNDIS_OID_GEN_MEDIA_CONNECT_STATUS\n", __func__); + *outbuf = cpu_to_le32(rndis_per_dev_params[configNr] + .media_state); + retval = 0; + break; + + case RNDIS_OID_GEN_PHYSICAL_MEDIUM: + pr_debug("%s: RNDIS_OID_GEN_PHYSICAL_MEDIUM\n", __func__); + *outbuf = cpu_to_le32(0); + retval = 0; + break; + + /* The RNDIS specification is incomplete/wrong. Some versions + * of MS-Windows expect OIDs that aren't specified there. Other + * versions emit undefined RNDIS messages. DOCUMENT ALL THESE! + */ + case RNDIS_OID_GEN_MAC_OPTIONS: /* from WinME */ + pr_debug("%s: RNDIS_OID_GEN_MAC_OPTIONS\n", __func__); + *outbuf = cpu_to_le32( + RNDIS_MAC_OPTION_RECEIVE_SERIALIZED + | RNDIS_MAC_OPTION_FULL_DUPLEX); + retval = 0; + break; + + /* statistics OIDs (table 4-2) */ + + /* mandatory */ + case RNDIS_OID_GEN_XMIT_OK: + if (rndis_debug > 1) + pr_debug("%s: RNDIS_OID_GEN_XMIT_OK\n", __func__); + if (stats) { + *outbuf = cpu_to_le32(stats->tx_packets + - stats->tx_errors - stats->tx_dropped); + retval = 0; + } + break; + + /* mandatory */ + case RNDIS_OID_GEN_RCV_OK: + if (rndis_debug > 1) + pr_debug("%s: RNDIS_OID_GEN_RCV_OK\n", __func__); + if (stats) { + *outbuf = cpu_to_le32(stats->rx_packets + - stats->rx_errors - stats->rx_dropped); + retval = 0; + } + break; + + /* mandatory */ + case RNDIS_OID_GEN_XMIT_ERROR: + if (rndis_debug > 1) + pr_debug("%s: RNDIS_OID_GEN_XMIT_ERROR\n", __func__); + if (stats) { + *outbuf = cpu_to_le32(stats->tx_errors); + retval = 0; + } + break; + + /* mandatory */ + case RNDIS_OID_GEN_RCV_ERROR: + if (rndis_debug > 1) + pr_debug("%s: RNDIS_OID_GEN_RCV_ERROR\n", __func__); + if (stats) { + *outbuf = cpu_to_le32(stats->rx_errors); + retval = 0; + } + break; + + /* mandatory */ + case RNDIS_OID_GEN_RCV_NO_BUFFER: + pr_debug("%s: RNDIS_OID_GEN_RCV_NO_BUFFER\n", __func__); + if (stats) { + *outbuf = cpu_to_le32(stats->rx_dropped); + retval = 0; + } + break; + + /* ieee802.3 OIDs (table 4-3) */ + + /* mandatory */ + case RNDIS_OID_802_3_PERMANENT_ADDRESS: + pr_debug("%s: RNDIS_OID_802_3_PERMANENT_ADDRESS\n", __func__); + if (rndis_per_dev_params[configNr].dev) { + length = ETH_ALEN; + memcpy(outbuf, + rndis_per_dev_params[configNr].host_mac, + length); + retval = 0; + } + break; + + /* mandatory */ + case RNDIS_OID_802_3_CURRENT_ADDRESS: + pr_debug("%s: RNDIS_OID_802_3_CURRENT_ADDRESS\n", __func__); + if (rndis_per_dev_params[configNr].dev) { + length = ETH_ALEN; + memcpy(outbuf, + rndis_per_dev_params [configNr].host_mac, + length); + retval = 0; + } + break; + + /* mandatory */ + case RNDIS_OID_802_3_MULTICAST_LIST: + pr_debug("%s: RNDIS_OID_802_3_MULTICAST_LIST\n", __func__); + /* Multicast base address only */ + *outbuf = cpu_to_le32(0xE0000000); + retval = 0; + break; + + /* mandatory */ + case RNDIS_OID_802_3_MAXIMUM_LIST_SIZE: + pr_debug("%s: RNDIS_OID_802_3_MAXIMUM_LIST_SIZE\n", __func__); + /* Multicast base address only */ + *outbuf = cpu_to_le32(1); + retval = 0; + break; + + case RNDIS_OID_802_3_MAC_OPTIONS: + pr_debug("%s: RNDIS_OID_802_3_MAC_OPTIONS\n", __func__); + *outbuf = cpu_to_le32(0); + retval = 0; + break; + + /* ieee802.3 statistics OIDs (table 4-4) */ + + /* mandatory */ + case RNDIS_OID_802_3_RCV_ERROR_ALIGNMENT: + pr_debug("%s: RNDIS_OID_802_3_RCV_ERROR_ALIGNMENT\n", __func__); + if (stats) { + *outbuf = cpu_to_le32(stats->rx_frame_errors); + retval = 0; + } + break; + + /* mandatory */ + case RNDIS_OID_802_3_XMIT_ONE_COLLISION: + pr_debug("%s: RNDIS_OID_802_3_XMIT_ONE_COLLISION\n", __func__); + *outbuf = cpu_to_le32(0); + retval = 0; + break; + + /* mandatory */ + case RNDIS_OID_802_3_XMIT_MORE_COLLISIONS: + pr_debug("%s: RNDIS_OID_802_3_XMIT_MORE_COLLISIONS\n", __func__); + *outbuf = cpu_to_le32(0); + retval = 0; + break; + + default: + pr_warning("%s: query unknown OID 0x%08X\n", + __func__, OID); + } + if (retval < 0) + length = 0; + + resp->InformationBufferLength = cpu_to_le32(length); + r->length = length + sizeof(*resp); + resp->MessageLength = cpu_to_le32(r->length); + return retval; +} + +static int gen_ndis_set_resp(u8 configNr, u32 OID, u8 *buf, u32 buf_len, + rndis_resp_t *r) +{ + rndis_set_cmplt_type *resp; + int i, retval = -ENOTSUPP; + struct rndis_params *params; + + if (!r) + return -ENOMEM; + resp = (rndis_set_cmplt_type *)r->buf; + if (!resp) + return -ENOMEM; + + if (buf_len && rndis_debug > 1) { + pr_debug("set OID %08x value, len %d:\n", OID, buf_len); + for (i = 0; i < buf_len; i += 16) { + pr_debug("%03d: %08x %08x %08x %08x\n", i, + get_unaligned_le32(&buf[i]), + get_unaligned_le32(&buf[i + 4]), + get_unaligned_le32(&buf[i + 8]), + get_unaligned_le32(&buf[i + 12])); + } + } + + params = &rndis_per_dev_params[configNr]; + switch (OID) { + case RNDIS_OID_GEN_CURRENT_PACKET_FILTER: + + /* these NDIS_PACKET_TYPE_* bitflags are shared with + * cdc_filter; it's not RNDIS-specific + * NDIS_PACKET_TYPE_x == USB_CDC_PACKET_TYPE_x for x in: + * PROMISCUOUS, DIRECTED, + * MULTICAST, ALL_MULTICAST, BROADCAST + */ + *params->filter = (u16)get_unaligned_le32(buf); + pr_debug("%s: RNDIS_OID_GEN_CURRENT_PACKET_FILTER %08x\n", + __func__, *params->filter); + + /* this call has a significant side effect: it's + * what makes the packet flow start and stop, like + * activating the CDC Ethernet altsetting. + */ + retval = 0; + if (*params->filter) { + 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 RNDIS_OID_802_3_MULTICAST_LIST: + /* I think we can ignore this */ + pr_debug("%s: RNDIS_OID_802_3_MULTICAST_LIST\n", __func__); + retval = 0; + break; + + default: + pr_warning("%s: set unknown OID 0x%08X, size %d\n", + __func__, OID, buf_len); + } + + return retval; +} + +/* + * Response Functions + */ + +static int rndis_init_response(int configNr, rndis_init_msg_type *buf) +{ + rndis_init_cmplt_type *resp; + rndis_resp_t *r; + struct rndis_params *params = rndis_per_dev_params + configNr; + + if (!params->dev) + return -ENOTSUPP; + + r = rndis_add_response(configNr, sizeof(rndis_init_cmplt_type)); + if (!r) + return -ENOMEM; + resp = (rndis_init_cmplt_type *)r->buf; + + resp->MessageType = cpu_to_le32(RNDIS_MSG_INIT_C); + resp->MessageLength = cpu_to_le32(52); + resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ + resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS); + resp->MajorVersion = cpu_to_le32(RNDIS_MAJOR_VERSION); + resp->MinorVersion = cpu_to_le32(RNDIS_MINOR_VERSION); + resp->DeviceFlags = cpu_to_le32(RNDIS_DF_CONNECTIONLESS); + resp->Medium = cpu_to_le32(RNDIS_MEDIUM_802_3); + resp->MaxPacketsPerTransfer = cpu_to_le32(1); + resp->MaxTransferSize = cpu_to_le32( + params->dev->mtu + + sizeof(struct ethhdr) + + sizeof(struct rndis_packet_msg_type) + + 22); + resp->PacketAlignmentFactor = cpu_to_le32(0); + resp->AFListOffset = cpu_to_le32(0); + resp->AFListSize = cpu_to_le32(0); + + params->resp_avail(params->v); + return 0; +} + +static int rndis_query_response(int configNr, rndis_query_msg_type *buf) +{ + rndis_query_cmplt_type *resp; + rndis_resp_t *r; + struct rndis_params *params = rndis_per_dev_params + configNr; + + /* pr_debug("%s: OID = %08X\n", __func__, cpu_to_le32(buf->OID)); */ + if (!params->dev) + return -ENOTSUPP; + + /* + * we need more memory: + * gen_ndis_query_resp expects enough space for + * rndis_query_cmplt_type followed by data. + * oid_supported_list is the largest data reply + */ + r = rndis_add_response(configNr, + sizeof(oid_supported_list) + sizeof(rndis_query_cmplt_type)); + if (!r) + return -ENOMEM; + resp = (rndis_query_cmplt_type *)r->buf; + + resp->MessageType = cpu_to_le32(RNDIS_MSG_QUERY_C); + resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ + + if (gen_ndis_query_resp(configNr, le32_to_cpu(buf->OID), + le32_to_cpu(buf->InformationBufferOffset) + + 8 + (u8 *)buf, + le32_to_cpu(buf->InformationBufferLength), + r)) { + /* OID not supported */ + resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED); + resp->MessageLength = cpu_to_le32(sizeof *resp); + resp->InformationBufferLength = cpu_to_le32(0); + resp->InformationBufferOffset = cpu_to_le32(0); + } else + resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS); + + params->resp_avail(params->v); + return 0; +} + +static int rndis_set_response(int configNr, rndis_set_msg_type *buf) +{ + u32 BufLength, BufOffset; + rndis_set_cmplt_type *resp; + rndis_resp_t *r; + struct rndis_params *params = rndis_per_dev_params + configNr; + + r = rndis_add_response(configNr, sizeof(rndis_set_cmplt_type)); + if (!r) + return -ENOMEM; + resp = (rndis_set_cmplt_type *)r->buf; + + BufLength = le32_to_cpu(buf->InformationBufferLength); + BufOffset = le32_to_cpu(buf->InformationBufferOffset); + +#ifdef VERBOSE_DEBUG + pr_debug("%s: Length: %d\n", __func__, BufLength); + pr_debug("%s: Offset: %d\n", __func__, BufOffset); + pr_debug("%s: InfoBuffer: ", __func__); + + for (i = 0; i < BufLength; i++) { + pr_debug("%02x ", *(((u8 *) buf) + i + 8 + BufOffset)); + } + + pr_debug("\n"); +#endif + + resp->MessageType = cpu_to_le32(RNDIS_MSG_SET_C); + resp->MessageLength = cpu_to_le32(16); + resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ + if (gen_ndis_set_resp(configNr, le32_to_cpu(buf->OID), + ((u8 *)buf) + 8 + BufOffset, BufLength, r)) + resp->Status = cpu_to_le32(RNDIS_STATUS_NOT_SUPPORTED); + else + resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS); + + params->resp_avail(params->v); + return 0; +} + +static int rndis_reset_response(int configNr, rndis_reset_msg_type *buf) +{ + rndis_reset_cmplt_type *resp; + rndis_resp_t *r; + struct rndis_params *params = rndis_per_dev_params + configNr; + + r = rndis_add_response(configNr, sizeof(rndis_reset_cmplt_type)); + if (!r) + return -ENOMEM; + resp = (rndis_reset_cmplt_type *)r->buf; + + resp->MessageType = cpu_to_le32(RNDIS_MSG_RESET_C); + resp->MessageLength = cpu_to_le32(16); + resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS); + /* resent information */ + resp->AddressingReset = cpu_to_le32(1); + + params->resp_avail(params->v); + return 0; +} + +static int rndis_keepalive_response(int configNr, + rndis_keepalive_msg_type *buf) +{ + rndis_keepalive_cmplt_type *resp; + rndis_resp_t *r; + struct rndis_params *params = rndis_per_dev_params + configNr; + + /* host "should" check only in RNDIS_DATA_INITIALIZED state */ + + r = rndis_add_response(configNr, sizeof(rndis_keepalive_cmplt_type)); + if (!r) + return -ENOMEM; + resp = (rndis_keepalive_cmplt_type *)r->buf; + + resp->MessageType = cpu_to_le32(RNDIS_MSG_KEEPALIVE_C); + resp->MessageLength = cpu_to_le32(16); + resp->RequestID = buf->RequestID; /* Still LE in msg buffer */ + resp->Status = cpu_to_le32(RNDIS_STATUS_SUCCESS); + + params->resp_avail(params->v); + return 0; +} + + +/* + * Device to Host Comunication + */ +static int rndis_indicate_status_msg(int configNr, u32 status) +{ + rndis_indicate_status_msg_type *resp; + rndis_resp_t *r; + struct rndis_params *params = rndis_per_dev_params + configNr; + + if (params->state == RNDIS_UNINITIALIZED) + return -ENOTSUPP; + + r = rndis_add_response(configNr, + sizeof(rndis_indicate_status_msg_type)); + if (!r) + return -ENOMEM; + resp = (rndis_indicate_status_msg_type *)r->buf; + + resp->MessageType = cpu_to_le32(RNDIS_MSG_INDICATE); + resp->MessageLength = cpu_to_le32(20); + resp->Status = cpu_to_le32(status); + resp->StatusBufferLength = cpu_to_le32(0); + resp->StatusBufferOffset = cpu_to_le32(0); + + params->resp_avail(params->v); + return 0; +} + +int rndis_signal_connect(int configNr) +{ + rndis_per_dev_params[configNr].media_state + = RNDIS_MEDIA_STATE_CONNECTED; + return rndis_indicate_status_msg(configNr, + RNDIS_STATUS_MEDIA_CONNECT); +} + +int rndis_signal_disconnect(int configNr) +{ + rndis_per_dev_params[configNr].media_state + = RNDIS_MEDIA_STATE_DISCONNECTED; + return rndis_indicate_status_msg(configNr, + RNDIS_STATUS_MEDIA_DISCONNECT); +} + +void rndis_uninit(int configNr) +{ + u8 *buf; + u32 length; + + if (configNr >= RNDIS_MAX_CONFIGS) + return; + rndis_per_dev_params[configNr].state = RNDIS_UNINITIALIZED; + + /* drain the response queue */ + while ((buf = rndis_get_next_response(configNr, &length))) + rndis_free_response(configNr, buf); +} + +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; + __le32 *tmp; + struct rndis_params *params; + + if (!buf) + return -ENOMEM; + + tmp = (__le32 *)buf; + MsgType = get_unaligned_le32(tmp++); + MsgLength = get_unaligned_le32(tmp++); + + if (configNr >= RNDIS_MAX_CONFIGS) + return -ENOTSUPP; + params = &rndis_per_dev_params[configNr]; + + /* NOTE: RNDIS is *EXTREMELY* chatty ... Windows constantly polls for + * rx/tx statistics and link status, in addition to KEEPALIVE traffic + * and normal HC level polling to see if there's any IN traffic. + */ + + /* For USB: responses may take up to 10 seconds */ + switch (MsgType) { + case RNDIS_MSG_INIT: + pr_debug("%s: RNDIS_MSG_INIT\n", + __func__); + params->state = RNDIS_INITIALIZED; + return rndis_init_response(configNr, + (rndis_init_msg_type *)buf); + + case RNDIS_MSG_HALT: + pr_debug("%s: RNDIS_MSG_HALT\n", + __func__); + params->state = RNDIS_UNINITIALIZED; + if (params->dev) { + netif_carrier_off(params->dev); + netif_stop_queue(params->dev); + } + return 0; + + case RNDIS_MSG_QUERY: + return rndis_query_response(configNr, + (rndis_query_msg_type *)buf); + + case RNDIS_MSG_SET: + return rndis_set_response(configNr, + (rndis_set_msg_type *)buf); + + case RNDIS_MSG_RESET: + pr_debug("%s: RNDIS_MSG_RESET\n", + __func__); + return rndis_reset_response(configNr, + (rndis_reset_msg_type *)buf); + + case RNDIS_MSG_KEEPALIVE: + /* For USB: host does this every 5 seconds */ + if (rndis_debug > 1) + pr_debug("%s: RNDIS_MSG_KEEPALIVE\n", + __func__); + return rndis_keepalive_response(configNr, + (rndis_keepalive_msg_type *) + buf); + + default: + /* At least Windows XP emits some undefined RNDIS messages. + * In one case those messages seemed to relate to the host + * suspending itself. + */ + pr_warning("%s: unknown RNDIS message 0x%08X len %d\n", + __func__, MsgType, MsgLength); + print_hex_dump_bytes(__func__, DUMP_PREFIX_OFFSET, + buf, MsgLength); + break; + } + + return -ENOTSUPP; +} + +int rndis_register(void (*resp_avail)(void *v), void *v) +{ + u8 i; + + if (!resp_avail) + return -EINVAL; + + for (i = 0; i < RNDIS_MAX_CONFIGS; i++) { + if (!rndis_per_dev_params[i].used) { + rndis_per_dev_params[i].used = 1; + rndis_per_dev_params[i].resp_avail = resp_avail; + rndis_per_dev_params[i].v = v; + pr_debug("%s: configNr = %d\n", __func__, i); + return i; + } + } + pr_debug("failed\n"); + + return -ENODEV; +} + +void rndis_deregister(int configNr) +{ + pr_debug("%s:\n", __func__); + + if (configNr >= RNDIS_MAX_CONFIGS) return; + rndis_per_dev_params[configNr].used = 0; +} + +int rndis_set_param_dev(u8 configNr, struct net_device *dev, u16 *cdc_filter) +{ + pr_debug("%s:\n", __func__); + if (!dev) + return -EINVAL; + if (configNr >= RNDIS_MAX_CONFIGS) return -1; + + rndis_per_dev_params[configNr].dev = dev; + rndis_per_dev_params[configNr].filter = cdc_filter; + + return 0; +} + +int rndis_set_param_vendor(u8 configNr, u32 vendorID, const char *vendorDescr) +{ + pr_debug("%s:\n", __func__); + if (!vendorDescr) return -1; + if (configNr >= RNDIS_MAX_CONFIGS) return -1; + + rndis_per_dev_params[configNr].vendorID = vendorID; + rndis_per_dev_params[configNr].vendorDescr = vendorDescr; + + return 0; +} + +int rndis_set_param_medium(u8 configNr, u32 medium, u32 speed) +{ + pr_debug("%s: %u %u\n", __func__, medium, speed); + if (configNr >= RNDIS_MAX_CONFIGS) return -1; + + rndis_per_dev_params[configNr].medium = medium; + rndis_per_dev_params[configNr].speed = speed; + + return 0; +} + +void rndis_add_hdr(struct sk_buff *skb) +{ + struct rndis_packet_msg_type *header; + + if (!skb) + return; + header = (void *)skb_push(skb, sizeof(*header)); + memset(header, 0, sizeof *header); + header->MessageType = cpu_to_le32(RNDIS_MSG_PACKET); + header->MessageLength = cpu_to_le32(skb->len); + header->DataOffset = cpu_to_le32(36); + header->DataLength = cpu_to_le32(skb->len - sizeof(*header)); +} + +void rndis_free_response(int configNr, u8 *buf) +{ + rndis_resp_t *r; + struct list_head *act, *tmp; + + list_for_each_safe(act, tmp, + &(rndis_per_dev_params[configNr].resp_queue)) + { + r = list_entry(act, rndis_resp_t, list); + if (r && r->buf == buf) { + list_del(&r->list); + kfree(r); + } + } +} + +u8 *rndis_get_next_response(int configNr, u32 *length) +{ + rndis_resp_t *r; + struct list_head *act, *tmp; + + if (!length) return NULL; + + list_for_each_safe(act, tmp, + &(rndis_per_dev_params[configNr].resp_queue)) + { + r = list_entry(act, rndis_resp_t, list); + if (!r->send) { + r->send = 1; + *length = r->length; + return r->buf; + } + } + + return NULL; +} + +static rndis_resp_t *rndis_add_response(int configNr, u32 length) +{ + rndis_resp_t *r; + + /* NOTE: this gets copied into ether.c USB_BUFSIZ bytes ... */ + r = kmalloc(sizeof(rndis_resp_t) + length, GFP_ATOMIC); + if (!r) return NULL; + + r->buf = (u8 *)(r + 1); + r->length = length; + r->send = 0; + + list_add_tail(&r->list, + &(rndis_per_dev_params[configNr].resp_queue)); + return r; +} + +int rndis_rm_hdr(struct gether *port, + struct sk_buff *skb, + struct sk_buff_head *list) +{ + /* tmp points to a struct rndis_packet_msg_type */ + __le32 *tmp = (void *)skb->data; + + /* MessageType, MessageLength */ + if (cpu_to_le32(RNDIS_MSG_PACKET) + != get_unaligned(tmp++)) { + dev_kfree_skb_any(skb); + return -EINVAL; + } + tmp++; + + /* DataOffset, DataLength */ + if (!skb_pull(skb, get_unaligned_le32(tmp++) + 8)) { + dev_kfree_skb_any(skb); + return -EOVERFLOW; + } + skb_trim(skb, get_unaligned_le32(tmp++)); + + skb_queue_tail(list, skb); + return 0; +} + +#ifdef CONFIG_USB_GADGET_DEBUG_FILES + +static int rndis_proc_show(struct seq_file *m, void *v) +{ + rndis_params *param = m->private; + + seq_printf(m, + "Config Nr. %d\n" + "used : %s\n" + "state : %s\n" + "medium : 0x%08X\n" + "speed : %d\n" + "cable : %s\n" + "vendor ID : 0x%08X\n" + "vendor : %s\n", + param->confignr, (param->used) ? "y" : "n", + ({ 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", + param->vendorID, param->vendorDescr); + return 0; +} + +static ssize_t rndis_proc_write(struct file *file, const char __user *buffer, + size_t count, loff_t *ppos) +{ + rndis_params *p = PDE(file->f_path.dentry->d_inode)->data; + u32 speed = 0; + int i, fl_speed = 0; + + for (i = 0; i < count; i++) { + char c; + if (get_user(c, buffer)) + return -EFAULT; + switch (c) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + fl_speed = 1; + speed = speed * 10 + c - '0'; + break; + case 'C': + case 'c': + rndis_signal_connect(p->confignr); + break; + case 'D': + case 'd': + rndis_signal_disconnect(p->confignr); + break; + default: + if (fl_speed) p->speed = speed; + else pr_debug("%c is not valid\n", c); + break; + } + + buffer++; + } + + return count; +} + +static int rndis_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, rndis_proc_show, PDE(inode)->data); +} + +static const struct file_operations rndis_proc_fops = { + .owner = THIS_MODULE, + .open = rndis_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, + .write = rndis_proc_write, +}; + +#define NAME_TEMPLATE "driver/rndis-%03d" + +static struct proc_dir_entry *rndis_connect_state [RNDIS_MAX_CONFIGS]; + +#endif /* CONFIG_USB_GADGET_DEBUG_FILES */ + + +int rndis_init(void) +{ + u8 i; + + for (i = 0; i < RNDIS_MAX_CONFIGS; i++) { +#ifdef CONFIG_USB_GADGET_DEBUG_FILES + char name [20]; + + sprintf(name, NAME_TEMPLATE, i); + rndis_connect_state[i] = proc_create_data(name, 0660, NULL, + &rndis_proc_fops, + (void *)(rndis_per_dev_params + i)); + if (!rndis_connect_state[i]) { + pr_debug("%s: remove entries", __func__); + while (i) { + sprintf(name, NAME_TEMPLATE, --i); + remove_proc_entry(name, NULL); + } + pr_debug("\n"); + return -EIO; + } +#endif + rndis_per_dev_params[i].confignr = i; + rndis_per_dev_params[i].used = 0; + rndis_per_dev_params[i].state = RNDIS_UNINITIALIZED; + rndis_per_dev_params[i].media_state + = RNDIS_MEDIA_STATE_DISCONNECTED; + INIT_LIST_HEAD(&(rndis_per_dev_params[i].resp_queue)); + } + + return 0; +} + +void rndis_exit(void) +{ +#ifdef CONFIG_USB_GADGET_DEBUG_FILES + u8 i; + char name[20]; + + for (i = 0; i < RNDIS_MAX_CONFIGS; i++) { + sprintf(name, NAME_TEMPLATE, i); + remove_proc_entry(name, NULL); + } +#endif +} diff --git a/drivers/staging/ccg/rndis.h b/drivers/staging/ccg/rndis.h new file mode 100644 index 0000000..0647f2f --- /dev/null +++ b/drivers/staging/ccg/rndis.h @@ -0,0 +1,222 @@ +/* + * RNDIS Definitions for Remote NDIS + * + * Authors: Benedikt Spranger, Pengutronix + * Robert Schwebel, Pengutronix + * + * 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. + * + * This software was originally developed in conformance with + * Microsoft's Remote NDIS Specification License Agreement. + */ + +#ifndef _LINUX_RNDIS_H +#define _LINUX_RNDIS_H + +#include +#include "ndis.h" + +#define RNDIS_MAXIMUM_FRAME_SIZE 1518 +#define RNDIS_MAX_TOTAL_SIZE 1558 + +typedef struct rndis_init_msg_type +{ + __le32 MessageType; + __le32 MessageLength; + __le32 RequestID; + __le32 MajorVersion; + __le32 MinorVersion; + __le32 MaxTransferSize; +} rndis_init_msg_type; + +typedef struct rndis_init_cmplt_type +{ + __le32 MessageType; + __le32 MessageLength; + __le32 RequestID; + __le32 Status; + __le32 MajorVersion; + __le32 MinorVersion; + __le32 DeviceFlags; + __le32 Medium; + __le32 MaxPacketsPerTransfer; + __le32 MaxTransferSize; + __le32 PacketAlignmentFactor; + __le32 AFListOffset; + __le32 AFListSize; +} rndis_init_cmplt_type; + +typedef struct rndis_halt_msg_type +{ + __le32 MessageType; + __le32 MessageLength; + __le32 RequestID; +} rndis_halt_msg_type; + +typedef struct rndis_query_msg_type +{ + __le32 MessageType; + __le32 MessageLength; + __le32 RequestID; + __le32 OID; + __le32 InformationBufferLength; + __le32 InformationBufferOffset; + __le32 DeviceVcHandle; +} rndis_query_msg_type; + +typedef struct rndis_query_cmplt_type +{ + __le32 MessageType; + __le32 MessageLength; + __le32 RequestID; + __le32 Status; + __le32 InformationBufferLength; + __le32 InformationBufferOffset; +} rndis_query_cmplt_type; + +typedef struct rndis_set_msg_type +{ + __le32 MessageType; + __le32 MessageLength; + __le32 RequestID; + __le32 OID; + __le32 InformationBufferLength; + __le32 InformationBufferOffset; + __le32 DeviceVcHandle; +} rndis_set_msg_type; + +typedef struct rndis_set_cmplt_type +{ + __le32 MessageType; + __le32 MessageLength; + __le32 RequestID; + __le32 Status; +} rndis_set_cmplt_type; + +typedef struct rndis_reset_msg_type +{ + __le32 MessageType; + __le32 MessageLength; + __le32 Reserved; +} rndis_reset_msg_type; + +typedef struct rndis_reset_cmplt_type +{ + __le32 MessageType; + __le32 MessageLength; + __le32 Status; + __le32 AddressingReset; +} rndis_reset_cmplt_type; + +typedef struct rndis_indicate_status_msg_type +{ + __le32 MessageType; + __le32 MessageLength; + __le32 Status; + __le32 StatusBufferLength; + __le32 StatusBufferOffset; +} rndis_indicate_status_msg_type; + +typedef struct rndis_keepalive_msg_type +{ + __le32 MessageType; + __le32 MessageLength; + __le32 RequestID; +} rndis_keepalive_msg_type; + +typedef struct rndis_keepalive_cmplt_type +{ + __le32 MessageType; + __le32 MessageLength; + __le32 RequestID; + __le32 Status; +} rndis_keepalive_cmplt_type; + +struct rndis_packet_msg_type +{ + __le32 MessageType; + __le32 MessageLength; + __le32 DataOffset; + __le32 DataLength; + __le32 OOBDataOffset; + __le32 OOBDataLength; + __le32 NumOOBDataElements; + __le32 PerPacketInfoOffset; + __le32 PerPacketInfoLength; + __le32 VcHandle; + __le32 Reserved; +} __attribute__ ((packed)); + +struct rndis_config_parameter +{ + __le32 ParameterNameOffset; + __le32 ParameterNameLength; + __le32 ParameterType; + __le32 ParameterValueOffset; + __le32 ParameterValueLength; +}; + +/* implementation specific */ +enum rndis_state +{ + RNDIS_UNINITIALIZED, + RNDIS_INITIALIZED, + RNDIS_DATA_INITIALIZED, +}; + +typedef struct rndis_resp_t +{ + struct list_head list; + u8 *buf; + u32 length; + int send; +} rndis_resp_t; + +typedef struct rndis_params +{ + u8 confignr; + u8 used; + u16 saved_filter; + enum rndis_state state; + u32 medium; + u32 speed; + u32 media_state; + + const u8 *host_mac; + u16 *filter; + struct net_device *dev; + + u32 vendorID; + const char *vendorDescr; + void (*resp_avail)(void *v); + void *v; + struct list_head resp_queue; +} rndis_params; + +/* RNDIS Message parser and other useless functions */ +int rndis_msg_parser (u8 configNr, u8 *buf); +int rndis_register(void (*resp_avail)(void *v), void *v); +void rndis_deregister (int configNr); +int rndis_set_param_dev (u8 configNr, struct net_device *dev, + u16 *cdc_filter); +int rndis_set_param_vendor (u8 configNr, u32 vendorID, + const char *vendorDescr); +int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed); +void rndis_add_hdr (struct sk_buff *skb); +int rndis_rm_hdr(struct gether *port, struct sk_buff *skb, + struct sk_buff_head *list); +u8 *rndis_get_next_response (int configNr, u32 *length); +void rndis_free_response (int configNr, u8 *buf); + +void rndis_uninit (int configNr); +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 rndis_init(void); +void rndis_exit (void); + +#endif /* _LINUX_RNDIS_H */ diff --git a/drivers/staging/ccg/storage_common.c b/drivers/staging/ccg/storage_common.c new file mode 100644 index 0000000..8d9bcd8 --- /dev/null +++ b/drivers/staging/ccg/storage_common.c @@ -0,0 +1,893 @@ +/* + * storage_common.c -- Common definitions for mass storage functionality + * + * Copyright (C) 2003-2008 Alan Stern + * Copyeight (C) 2009 Samsung Electronics + * Author: Michal Nazarewicz (mina86@mina86.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +/* + * This file requires the following identifiers used in USB strings to + * be defined (each of type pointer to char): + * - fsg_string_manufacturer -- name of the manufacturer + * - fsg_string_product -- name of the product + * - fsg_string_config -- name of the configuration + * - fsg_string_interface -- name of the interface + * The first four are only needed when FSG_DESCRIPTORS_DEVICE_STRINGS + * macro is defined prior to including this file. + */ + +/* + * When FSG_NO_INTR_EP is defined fsg_fs_intr_in_desc and + * fsg_hs_intr_in_desc objects as well as + * FSG_FS_FUNCTION_PRE_EP_ENTRIES and FSG_HS_FUNCTION_PRE_EP_ENTRIES + * macros are not defined. + * + * When FSG_NO_DEVICE_STRINGS is defined FSG_STRING_MANUFACTURER, + * FSG_STRING_PRODUCT, FSG_STRING_SERIAL and FSG_STRING_CONFIG are not + * defined (as well as corresponding entries in string tables are + * missing) and FSG_STRING_INTERFACE has value of zero. + * + * When FSG_NO_OTG is defined fsg_otg_desc won't be defined. + */ + +/* + * When USB_GADGET_DEBUG_FILES is defined the module param num_buffers + * sets the number of pipeline buffers (length of the fsg_buffhd array). + * The valid range of num_buffers is: num >= 2 && num <= 4. + */ + + +#include +#include +#include + + +/* + * Thanks to NetChip Technologies for donating this product ID. + * + * DO NOT REUSE THESE IDs with any other driver!! Ever!! + * Instead: allocate your own, using normal USB-IF procedures. + */ +#define FSG_VENDOR_ID 0x0525 /* NetChip */ +#define FSG_PRODUCT_ID 0xa4a5 /* Linux-USB File-backed Storage Gadget */ + + +/*-------------------------------------------------------------------------*/ + + +#ifndef DEBUG +#undef VERBOSE_DEBUG +#undef DUMP_MSGS +#endif /* !DEBUG */ + +#ifdef VERBOSE_DEBUG +#define VLDBG LDBG +#else +#define VLDBG(lun, fmt, args...) do { } while (0) +#endif /* VERBOSE_DEBUG */ + +#define LDBG(lun, fmt, args...) dev_dbg (&(lun)->dev, fmt, ## args) +#define LERROR(lun, fmt, args...) dev_err (&(lun)->dev, fmt, ## args) +#define LWARN(lun, fmt, args...) dev_warn(&(lun)->dev, fmt, ## args) +#define LINFO(lun, fmt, args...) dev_info(&(lun)->dev, fmt, ## args) + +/* + * Keep those macros in sync with those in + * include/linux/usb/composite.h or else GCC will complain. If they + * are identical (the same names of arguments, white spaces in the + * same places) GCC will allow redefinition otherwise (even if some + * white space is removed or added) warning will be issued. + * + * Those macros are needed here because File Storage Gadget does not + * include the composite.h header. For composite gadgets those macros + * are redundant since composite.h is included any way. + * + * One could check whether those macros are already defined (which + * would indicate composite.h had been included) or not (which would + * indicate we were in FSG) but this is not done because a warning is + * desired if definitions here differ from the ones in composite.h. + * + * We want the definitions to match and be the same in File Storage + * Gadget as well as Mass Storage Function (and so composite gadgets + * using MSF). If someone changes them in composite.h it will produce + * a warning in this file when building MSF. + */ +#define DBG(d, fmt, args...) dev_dbg(&(d)->gadget->dev , fmt , ## args) +#define VDBG(d, fmt, args...) dev_vdbg(&(d)->gadget->dev , fmt , ## args) +#define ERROR(d, fmt, args...) dev_err(&(d)->gadget->dev , fmt , ## args) +#define WARNING(d, fmt, args...) dev_warn(&(d)->gadget->dev , fmt , ## args) +#define INFO(d, fmt, args...) dev_info(&(d)->gadget->dev , fmt , ## args) + + + +#ifdef DUMP_MSGS + +# define dump_msg(fsg, /* const char * */ label, \ + /* const u8 * */ buf, /* unsigned */ length) do { \ + if (length < 512) { \ + DBG(fsg, "%s, length %u:\n", label, length); \ + print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, \ + 16, 1, buf, length, 0); \ + } \ +} while (0) + +# define dump_cdb(fsg) do { } while (0) + +#else + +# define dump_msg(fsg, /* const char * */ label, \ + /* const u8 * */ buf, /* unsigned */ length) do { } while (0) + +# ifdef VERBOSE_DEBUG + +# define dump_cdb(fsg) \ + print_hex_dump(KERN_DEBUG, "SCSI CDB: ", DUMP_PREFIX_NONE, \ + 16, 1, (fsg)->cmnd, (fsg)->cmnd_size, 0) \ + +# else + +# define dump_cdb(fsg) do { } while (0) + +# endif /* VERBOSE_DEBUG */ + +#endif /* DUMP_MSGS */ + +/*-------------------------------------------------------------------------*/ + +/* CBI Interrupt data structure */ +struct interrupt_data { + u8 bType; + u8 bValue; +}; + +#define CBI_INTERRUPT_DATA_LEN 2 + +/* CBI Accept Device-Specific Command request */ +#define USB_CBI_ADSC_REQUEST 0x00 + + +/* Length of a SCSI Command Data Block */ +#define MAX_COMMAND_SIZE 16 + +/* SCSI Sense Key/Additional Sense Code/ASC Qualifier values */ +#define SS_NO_SENSE 0 +#define SS_COMMUNICATION_FAILURE 0x040800 +#define SS_INVALID_COMMAND 0x052000 +#define SS_INVALID_FIELD_IN_CDB 0x052400 +#define SS_LOGICAL_BLOCK_ADDRESS_OUT_OF_RANGE 0x052100 +#define SS_LOGICAL_UNIT_NOT_SUPPORTED 0x052500 +#define SS_MEDIUM_NOT_PRESENT 0x023a00 +#define SS_MEDIUM_REMOVAL_PREVENTED 0x055302 +#define SS_NOT_READY_TO_READY_TRANSITION 0x062800 +#define SS_RESET_OCCURRED 0x062900 +#define SS_SAVING_PARAMETERS_NOT_SUPPORTED 0x053900 +#define SS_UNRECOVERED_READ_ERROR 0x031100 +#define SS_WRITE_ERROR 0x030c02 +#define SS_WRITE_PROTECTED 0x072700 + +#define SK(x) ((u8) ((x) >> 16)) /* Sense Key byte, etc. */ +#define ASC(x) ((u8) ((x) >> 8)) +#define ASCQ(x) ((u8) (x)) + + +/*-------------------------------------------------------------------------*/ + + +struct fsg_lun { + struct file *filp; + loff_t file_length; + loff_t num_sectors; + + unsigned int initially_ro:1; + unsigned int ro:1; + unsigned int removable:1; + unsigned int cdrom:1; + unsigned int prevent_medium_removal:1; + unsigned int registered:1; + unsigned int info_valid:1; + unsigned int nofua:1; + + u32 sense_data; + u32 sense_data_info; + u32 unit_attention_data; + + unsigned int blkbits; /* Bits of logical block size of bound block device */ + unsigned int blksize; /* logical block size of bound block device */ + struct device dev; +}; + +#define fsg_lun_is_open(curlun) ((curlun)->filp != NULL) + +static struct fsg_lun *fsg_lun_from_dev(struct device *dev) +{ + return container_of(dev, struct fsg_lun, dev); +} + + +/* Big enough to hold our biggest descriptor */ +#define EP0_BUFSIZE 256 +#define DELAYED_STATUS (EP0_BUFSIZE + 999) /* An impossibly large value */ + +#ifdef CONFIG_USB_GADGET_DEBUG_FILES + +static unsigned int fsg_num_buffers = CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS; +module_param_named(num_buffers, fsg_num_buffers, uint, S_IRUGO); +MODULE_PARM_DESC(num_buffers, "Number of pipeline buffers"); + +#else + +/* + * Number of buffers we will use. + * 2 is usually enough for good buffering pipeline + */ +#define fsg_num_buffers CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS + +#endif /* CONFIG_USB_DEBUG */ + +/* check if fsg_num_buffers is within a valid range */ +static inline int fsg_num_buffers_validate(void) +{ + if (fsg_num_buffers >= 2 && fsg_num_buffers <= 4) + return 0; + pr_err("fsg_num_buffers %u is out of range (%d to %d)\n", + fsg_num_buffers, 2 ,4); + return -EINVAL; +} + +/* Default size of buffer length. */ +#define FSG_BUFLEN ((u32)16384) + +/* Maximal number of LUNs supported in mass storage function */ +#define FSG_MAX_LUNS 8 + +enum fsg_buffer_state { + BUF_STATE_EMPTY = 0, + BUF_STATE_FULL, + BUF_STATE_BUSY +}; + +struct fsg_buffhd { + void *buf; + enum fsg_buffer_state state; + struct fsg_buffhd *next; + + /* + * The NetChip 2280 is faster, and handles some protocol faults + * better, if we don't submit any short bulk-out read requests. + * So we will record the intended request length here. + */ + unsigned int bulk_out_intended_length; + + struct usb_request *inreq; + int inreq_busy; + struct usb_request *outreq; + int outreq_busy; +}; + +enum fsg_state { + /* This one isn't used anywhere */ + FSG_STATE_COMMAND_PHASE = -10, + FSG_STATE_DATA_PHASE, + FSG_STATE_STATUS_PHASE, + + FSG_STATE_IDLE = 0, + FSG_STATE_ABORT_BULK_OUT, + FSG_STATE_RESET, + FSG_STATE_INTERFACE_CHANGE, + FSG_STATE_CONFIG_CHANGE, + FSG_STATE_DISCONNECT, + FSG_STATE_EXIT, + FSG_STATE_TERMINATED +}; + +enum data_direction { + DATA_DIR_UNKNOWN = 0, + DATA_DIR_FROM_HOST, + DATA_DIR_TO_HOST, + DATA_DIR_NONE +}; + + +/*-------------------------------------------------------------------------*/ + + +static inline u32 get_unaligned_be24(u8 *buf) +{ + return 0xffffff & (u32) get_unaligned_be32(buf - 1); +} + + +/*-------------------------------------------------------------------------*/ + + +enum { +#ifndef FSG_NO_DEVICE_STRINGS + FSG_STRING_MANUFACTURER = 1, + FSG_STRING_PRODUCT, + FSG_STRING_SERIAL, + FSG_STRING_CONFIG, +#endif + FSG_STRING_INTERFACE +}; + + +#ifndef FSG_NO_OTG +static struct usb_otg_descriptor +fsg_otg_desc = { + .bLength = sizeof fsg_otg_desc, + .bDescriptorType = USB_DT_OTG, + + .bmAttributes = USB_OTG_SRP, +}; +#endif + +/* There is only one interface. */ + +static struct usb_interface_descriptor +fsg_intf_desc = { + .bLength = sizeof fsg_intf_desc, + .bDescriptorType = USB_DT_INTERFACE, + + .bNumEndpoints = 2, /* Adjusted during fsg_bind() */ + .bInterfaceClass = USB_CLASS_MASS_STORAGE, + .bInterfaceSubClass = USB_SC_SCSI, /* Adjusted during fsg_bind() */ + .bInterfaceProtocol = USB_PR_BULK, /* Adjusted during fsg_bind() */ + .iInterface = FSG_STRING_INTERFACE, +}; + +/* + * Three full-speed endpoint descriptors: bulk-in, bulk-out, and + * interrupt-in. + */ + +static struct usb_endpoint_descriptor +fsg_fs_bulk_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + /* wMaxPacketSize set by autoconfiguration */ +}; + +static struct usb_endpoint_descriptor +fsg_fs_bulk_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_OUT, + .bmAttributes = USB_ENDPOINT_XFER_BULK, + /* wMaxPacketSize set by autoconfiguration */ +}; + +#ifndef FSG_NO_INTR_EP + +static struct usb_endpoint_descriptor +fsg_fs_intr_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + .bEndpointAddress = USB_DIR_IN, + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = cpu_to_le16(2), + .bInterval = 32, /* frames -> 32 ms */ +}; + +#ifndef FSG_NO_OTG +# define FSG_FS_FUNCTION_PRE_EP_ENTRIES 2 +#else +# define FSG_FS_FUNCTION_PRE_EP_ENTRIES 1 +#endif + +#endif + +static struct usb_descriptor_header *fsg_fs_function[] = { +#ifndef FSG_NO_OTG + (struct usb_descriptor_header *) &fsg_otg_desc, +#endif + (struct usb_descriptor_header *) &fsg_intf_desc, + (struct usb_descriptor_header *) &fsg_fs_bulk_in_desc, + (struct usb_descriptor_header *) &fsg_fs_bulk_out_desc, +#ifndef FSG_NO_INTR_EP + (struct usb_descriptor_header *) &fsg_fs_intr_in_desc, +#endif + NULL, +}; + + +/* + * USB 2.0 devices need to expose both high speed and full speed + * descriptors, unless they only run at full speed. + * + * That means alternate endpoint descriptors (bigger packets) + * and a "device qualifier" ... plus more construction options + * for the configuration descriptor. + */ +static struct usb_endpoint_descriptor +fsg_hs_bulk_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + /* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */ + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(512), +}; + +static struct usb_endpoint_descriptor +fsg_hs_bulk_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + /* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */ + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(512), + .bInterval = 1, /* NAK every 1 uframe */ +}; + +#ifndef FSG_NO_INTR_EP + +static struct usb_endpoint_descriptor +fsg_hs_intr_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + /* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */ + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = cpu_to_le16(2), + .bInterval = 9, /* 2**(9-1) = 256 uframes -> 32 ms */ +}; + +#ifndef FSG_NO_OTG +# define FSG_HS_FUNCTION_PRE_EP_ENTRIES 2 +#else +# define FSG_HS_FUNCTION_PRE_EP_ENTRIES 1 +#endif + +#endif + +static struct usb_descriptor_header *fsg_hs_function[] = { +#ifndef FSG_NO_OTG + (struct usb_descriptor_header *) &fsg_otg_desc, +#endif + (struct usb_descriptor_header *) &fsg_intf_desc, + (struct usb_descriptor_header *) &fsg_hs_bulk_in_desc, + (struct usb_descriptor_header *) &fsg_hs_bulk_out_desc, +#ifndef FSG_NO_INTR_EP + (struct usb_descriptor_header *) &fsg_hs_intr_in_desc, +#endif + NULL, +}; + +static struct usb_endpoint_descriptor +fsg_ss_bulk_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + /* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */ + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc = { + .bLength = sizeof(fsg_ss_bulk_in_comp_desc), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + /*.bMaxBurst = DYNAMIC, */ +}; + +static struct usb_endpoint_descriptor +fsg_ss_bulk_out_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + /* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */ + .bmAttributes = USB_ENDPOINT_XFER_BULK, + .wMaxPacketSize = cpu_to_le16(1024), +}; + +static struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = { + .bLength = sizeof(fsg_ss_bulk_in_comp_desc), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + /*.bMaxBurst = DYNAMIC, */ +}; + +#ifndef FSG_NO_INTR_EP + +static struct usb_endpoint_descriptor +fsg_ss_intr_in_desc = { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + + /* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */ + .bmAttributes = USB_ENDPOINT_XFER_INT, + .wMaxPacketSize = cpu_to_le16(2), + .bInterval = 9, /* 2**(9-1) = 256 uframes -> 32 ms */ +}; + +static struct usb_ss_ep_comp_descriptor fsg_ss_intr_in_comp_desc = { + .bLength = sizeof(fsg_ss_bulk_in_comp_desc), + .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, + + .wBytesPerInterval = cpu_to_le16(2), +}; + +#ifndef FSG_NO_OTG +# define FSG_SS_FUNCTION_PRE_EP_ENTRIES 2 +#else +# define FSG_SS_FUNCTION_PRE_EP_ENTRIES 1 +#endif + +#endif + +static __maybe_unused struct usb_ext_cap_descriptor fsg_ext_cap_desc = { + .bLength = USB_DT_USB_EXT_CAP_SIZE, + .bDescriptorType = USB_DT_DEVICE_CAPABILITY, + .bDevCapabilityType = USB_CAP_TYPE_EXT, + + .bmAttributes = cpu_to_le32(USB_LPM_SUPPORT), +}; + +static __maybe_unused struct usb_ss_cap_descriptor fsg_ss_cap_desc = { + .bLength = USB_DT_USB_SS_CAP_SIZE, + .bDescriptorType = USB_DT_DEVICE_CAPABILITY, + .bDevCapabilityType = USB_SS_CAP_TYPE, + + /* .bmAttributes = LTM is not supported yet */ + + .wSpeedSupported = cpu_to_le16(USB_LOW_SPEED_OPERATION + | USB_FULL_SPEED_OPERATION + | USB_HIGH_SPEED_OPERATION + | USB_5GBPS_OPERATION), + .bFunctionalitySupport = USB_LOW_SPEED_OPERATION, + .bU1devExitLat = USB_DEFAULT_U1_DEV_EXIT_LAT, + .bU2DevExitLat = cpu_to_le16(USB_DEFAULT_U2_DEV_EXIT_LAT), +}; + +static __maybe_unused struct usb_bos_descriptor fsg_bos_desc = { + .bLength = USB_DT_BOS_SIZE, + .bDescriptorType = USB_DT_BOS, + + .wTotalLength = cpu_to_le16(USB_DT_BOS_SIZE + + USB_DT_USB_EXT_CAP_SIZE + + USB_DT_USB_SS_CAP_SIZE), + + .bNumDeviceCaps = 2, +}; + +static struct usb_descriptor_header *fsg_ss_function[] = { +#ifndef FSG_NO_OTG + (struct usb_descriptor_header *) &fsg_otg_desc, +#endif + (struct usb_descriptor_header *) &fsg_intf_desc, + (struct usb_descriptor_header *) &fsg_ss_bulk_in_desc, + (struct usb_descriptor_header *) &fsg_ss_bulk_in_comp_desc, + (struct usb_descriptor_header *) &fsg_ss_bulk_out_desc, + (struct usb_descriptor_header *) &fsg_ss_bulk_out_comp_desc, +#ifndef FSG_NO_INTR_EP + (struct usb_descriptor_header *) &fsg_ss_intr_in_desc, + (struct usb_descriptor_header *) &fsg_ss_intr_in_comp_desc, +#endif + NULL, +}; + +/* Maxpacket and other transfer characteristics vary by speed. */ +static __maybe_unused struct usb_endpoint_descriptor * +fsg_ep_desc(struct usb_gadget *g, struct usb_endpoint_descriptor *fs, + struct usb_endpoint_descriptor *hs, + struct usb_endpoint_descriptor *ss) +{ + if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER) + return ss; + else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH) + return hs; + return fs; +} + + +/* Static strings, in UTF-8 (for simplicity we use only ASCII characters) */ +static struct usb_string fsg_strings[] = { +#ifndef FSG_NO_DEVICE_STRINGS + {FSG_STRING_MANUFACTURER, fsg_string_manufacturer}, + {FSG_STRING_PRODUCT, fsg_string_product}, + {FSG_STRING_SERIAL, ""}, + {FSG_STRING_CONFIG, fsg_string_config}, +#endif + {FSG_STRING_INTERFACE, fsg_string_interface}, + {} +}; + +static struct usb_gadget_strings fsg_stringtab = { + .language = 0x0409, /* en-us */ + .strings = fsg_strings, +}; + + + /*-------------------------------------------------------------------------*/ + +/* + * If the next two routines are called while the gadget is registered, + * the caller must own fsg->filesem for writing. + */ + +static void fsg_lun_close(struct fsg_lun *curlun) +{ + if (curlun->filp) { + LDBG(curlun, "close backing file\n"); + fput(curlun->filp); + curlun->filp = NULL; + } +} + + +static int fsg_lun_open(struct fsg_lun *curlun, const char *filename) +{ + int ro; + struct file *filp = NULL; + int rc = -EINVAL; + struct inode *inode = NULL; + loff_t size; + loff_t num_sectors; + loff_t min_sectors; + unsigned int blkbits; + unsigned int blksize; + + /* R/W if we can, R/O if we must */ + ro = curlun->initially_ro; + if (!ro) { + filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0); + if (PTR_ERR(filp) == -EROFS || PTR_ERR(filp) == -EACCES) + ro = 1; + } + if (ro) + filp = filp_open(filename, O_RDONLY | O_LARGEFILE, 0); + if (IS_ERR(filp)) { + LINFO(curlun, "unable to open backing file: %s\n", filename); + return PTR_ERR(filp); + } + + if (!(filp->f_mode & FMODE_WRITE)) + ro = 1; + + inode = filp->f_path.dentry->d_inode; + if ((!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))) { + LINFO(curlun, "invalid file type: %s\n", filename); + goto out; + } + + /* + * If we can't read the file, it's no good. + * If we can't write the file, use it read-only. + */ + if (!(filp->f_op->read || filp->f_op->aio_read)) { + LINFO(curlun, "file not readable: %s\n", filename); + goto out; + } + if (!(filp->f_op->write || filp->f_op->aio_write)) + ro = 1; + + size = i_size_read(inode->i_mapping->host); + if (size < 0) { + LINFO(curlun, "unable to find file size: %s\n", filename); + rc = (int) size; + goto out; + } + + if (curlun->cdrom) { + blksize = 2048; + blkbits = 11; + } else if (inode->i_bdev) { + blksize = bdev_logical_block_size(inode->i_bdev); + blkbits = blksize_bits(blksize); + } else { + blksize = 512; + blkbits = 9; + } + + num_sectors = size >> blkbits; /* File size in logic-block-size blocks */ + min_sectors = 1; + if (curlun->cdrom) { + min_sectors = 300; /* Smallest track is 300 frames */ + if (num_sectors >= 256*60*75) { + num_sectors = 256*60*75 - 1; + LINFO(curlun, "file too big: %s\n", filename); + LINFO(curlun, "using only first %d blocks\n", + (int) num_sectors); + } + } + if (num_sectors < min_sectors) { + LINFO(curlun, "file too small: %s\n", filename); + rc = -ETOOSMALL; + goto out; + } + + if (fsg_lun_is_open(curlun)) + fsg_lun_close(curlun); + + curlun->blksize = blksize; + curlun->blkbits = blkbits; + curlun->ro = ro; + curlun->filp = filp; + curlun->file_length = size; + curlun->num_sectors = num_sectors; + LDBG(curlun, "open backing file: %s\n", filename); + return 0; + +out: + fput(filp); + return rc; +} + + +/*-------------------------------------------------------------------------*/ + +/* + * Sync the file data, don't bother with the metadata. + * This code was copied from fs/buffer.c:sys_fdatasync(). + */ +static int fsg_lun_fsync_sub(struct fsg_lun *curlun) +{ + struct file *filp = curlun->filp; + + if (curlun->ro || !filp) + return 0; + return vfs_fsync(filp, 1); +} + +static void store_cdrom_address(u8 *dest, int msf, u32 addr) +{ + if (msf) { + /* Convert to Minutes-Seconds-Frames */ + addr >>= 2; /* Convert to 2048-byte frames */ + addr += 2*75; /* Lead-in occupies 2 seconds */ + dest[3] = addr % 75; /* Frames */ + addr /= 75; + dest[2] = addr % 60; /* Seconds */ + addr /= 60; + dest[1] = addr; /* Minutes */ + dest[0] = 0; /* Reserved */ + } else { + /* Absolute sector */ + put_unaligned_be32(addr, dest); + } +} + + +/*-------------------------------------------------------------------------*/ + + +static ssize_t fsg_show_ro(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct fsg_lun *curlun = fsg_lun_from_dev(dev); + + return sprintf(buf, "%d\n", fsg_lun_is_open(curlun) + ? curlun->ro + : curlun->initially_ro); +} + +static ssize_t fsg_show_nofua(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct fsg_lun *curlun = fsg_lun_from_dev(dev); + + return sprintf(buf, "%u\n", curlun->nofua); +} + +static ssize_t fsg_show_file(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct fsg_lun *curlun = fsg_lun_from_dev(dev); + struct rw_semaphore *filesem = dev_get_drvdata(dev); + char *p; + ssize_t rc; + + down_read(filesem); + if (fsg_lun_is_open(curlun)) { /* Get the complete pathname */ + p = d_path(&curlun->filp->f_path, buf, PAGE_SIZE - 1); + if (IS_ERR(p)) + rc = PTR_ERR(p); + else { + rc = strlen(p); + memmove(buf, p, rc); + buf[rc] = '\n'; /* Add a newline */ + buf[++rc] = 0; + } + } else { /* No file, return 0 bytes */ + *buf = 0; + rc = 0; + } + up_read(filesem); + return rc; +} + + +static ssize_t fsg_store_ro(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + ssize_t rc; + struct fsg_lun *curlun = fsg_lun_from_dev(dev); + struct rw_semaphore *filesem = dev_get_drvdata(dev); + unsigned ro; + + rc = kstrtouint(buf, 2, &ro); + if (rc) + return rc; + + /* + * Allow the write-enable status to change only while the + * backing file is closed. + */ + down_read(filesem); + if (fsg_lun_is_open(curlun)) { + LDBG(curlun, "read-only status change prevented\n"); + rc = -EBUSY; + } else { + curlun->ro = ro; + curlun->initially_ro = ro; + LDBG(curlun, "read-only status set to %d\n", curlun->ro); + rc = count; + } + up_read(filesem); + return rc; +} + +static ssize_t fsg_store_nofua(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fsg_lun *curlun = fsg_lun_from_dev(dev); + unsigned nofua; + int ret; + + ret = kstrtouint(buf, 2, &nofua); + if (ret) + return ret; + + /* Sync data when switching from async mode to sync */ + if (!nofua && curlun->nofua) + fsg_lun_fsync_sub(curlun); + + curlun->nofua = nofua; + + return count; +} + +static ssize_t fsg_store_file(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct fsg_lun *curlun = fsg_lun_from_dev(dev); + struct rw_semaphore *filesem = dev_get_drvdata(dev); + int rc = 0; + + if (curlun->prevent_medium_removal && fsg_lun_is_open(curlun)) { + LDBG(curlun, "eject attempt prevented\n"); + return -EBUSY; /* "Door is locked" */ + } + + /* Remove a trailing newline */ + if (count > 0 && buf[count-1] == '\n') + ((char *) buf)[count-1] = 0; /* Ugh! */ + + /* Load new medium */ + down_write(filesem); + if (count > 0 && buf[0]) { + /* fsg_lun_open() will close existing file if any. */ + rc = fsg_lun_open(curlun, buf); + if (rc == 0) + curlun->unit_attention_data = + SS_NOT_READY_TO_READY_TRANSITION; + } else if (fsg_lun_is_open(curlun)) { + fsg_lun_close(curlun); + curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT; + } + up_write(filesem); + return (rc < 0 ? rc : count); +} diff --git a/drivers/staging/ccg/u_ether.c b/drivers/staging/ccg/u_ether.c new file mode 100644 index 0000000..1154a99 --- /dev/null +++ b/drivers/staging/ccg/u_ether.c @@ -0,0 +1,986 @@ +/* + * u_ether.c -- Ethernet-over-USB link layer utilities for Gadget stack + * + * Copyright (C) 2003-2005,2008 David Brownell + * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger + * Copyright (C) 2008 Nokia Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +/* #define VERBOSE_DEBUG */ + +#include +#include +#include +#include +#include +#include + +#include "u_ether.h" + + +/* + * This component encapsulates the Ethernet link glue needed to provide + * one (!) network link through the USB gadget stack, normally "usb0". + * + * The control and data models are handled by the function driver which + * connects to this code; such as CDC Ethernet (ECM or EEM), + * "CDC Subset", or RNDIS. That includes all descriptor and endpoint + * management. + * + * Link level addressing is handled by this component using module + * parameters; if no such parameters are provided, random link level + * addresses are used. Each end of the link uses one address. The + * host end address is exported in various ways, and is often recorded + * in configuration databases. + * + * The driver which assembles each configuration using such a link is + * responsible for ensuring that each configuration includes at most one + * instance of is network link. (The network layer provides ways for + * this single "physical" link to be used by multiple virtual links.) + */ + +#define UETH__VERSION "29-May-2008" + +struct eth_dev { + /* lock is held while accessing port_usb + * or updating its backlink port_usb->ioport + */ + spinlock_t lock; + struct gether *port_usb; + + struct net_device *net; + struct usb_gadget *gadget; + + spinlock_t req_lock; /* guard {rx,tx}_reqs */ + struct list_head tx_reqs, rx_reqs; + atomic_t tx_qlen; + + struct sk_buff_head rx_frames; + + unsigned header_len; + struct sk_buff *(*wrap)(struct gether *, struct sk_buff *skb); + int (*unwrap)(struct gether *, + struct sk_buff *skb, + struct sk_buff_head *list); + + struct work_struct work; + + unsigned long todo; +#define WORK_RX_MEMORY 0 + + bool zlp; + u8 host_mac[ETH_ALEN]; +}; + +/*-------------------------------------------------------------------------*/ + +#define RX_EXTRA 20 /* bytes guarding against rx overflows */ + +#define DEFAULT_QLEN 2 /* double buffering by default */ + +static unsigned qmult = 5; +module_param(qmult, uint, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(qmult, "queue length multiplier at high/super speed"); + +/* for dual-speed hardware, use deeper queues at high/super speed */ +static inline int qlen(struct usb_gadget *gadget) +{ + if (gadget_is_dualspeed(gadget) && (gadget->speed == USB_SPEED_HIGH || + gadget->speed == USB_SPEED_SUPER)) + return qmult * DEFAULT_QLEN; + else + return DEFAULT_QLEN; +} + +/*-------------------------------------------------------------------------*/ + +/* REVISIT there must be a better way than having two sets + * of debug calls ... + */ + +#undef DBG +#undef VDBG +#undef ERROR +#undef INFO + +#define xprintk(d, level, fmt, args...) \ + printk(level "%s: " fmt , (d)->net->name , ## args) + +#ifdef DEBUG +#undef DEBUG +#define DBG(dev, fmt, args...) \ + xprintk(dev , KERN_DEBUG , fmt , ## args) +#else +#define DBG(dev, fmt, args...) \ + do { } while (0) +#endif /* DEBUG */ + +#ifdef VERBOSE_DEBUG +#define VDBG DBG +#else +#define VDBG(dev, fmt, args...) \ + do { } while (0) +#endif /* DEBUG */ + +#define ERROR(dev, fmt, args...) \ + xprintk(dev , KERN_ERR , fmt , ## args) +#define INFO(dev, fmt, args...) \ + xprintk(dev , KERN_INFO , fmt , ## args) + +/*-------------------------------------------------------------------------*/ + +/* NETWORK DRIVER HOOKUP (to the layer above this driver) */ + +static int ueth_change_mtu(struct net_device *net, int new_mtu) +{ + struct eth_dev *dev = netdev_priv(net); + unsigned long flags; + int status = 0; + + /* don't change MTU on "live" link (peer won't know) */ + spin_lock_irqsave(&dev->lock, flags); + if (dev->port_usb) + status = -EBUSY; + else if (new_mtu <= ETH_HLEN || new_mtu > ETH_FRAME_LEN) + status = -ERANGE; + else + net->mtu = new_mtu; + spin_unlock_irqrestore(&dev->lock, flags); + + return status; +} + +static void eth_get_drvinfo(struct net_device *net, struct ethtool_drvinfo *p) +{ + struct eth_dev *dev = netdev_priv(net); + + strlcpy(p->driver, "g_ether", sizeof p->driver); + strlcpy(p->version, UETH__VERSION, sizeof p->version); + strlcpy(p->fw_version, dev->gadget->name, sizeof p->fw_version); + strlcpy(p->bus_info, dev_name(&dev->gadget->dev), sizeof p->bus_info); +} + +/* REVISIT can also support: + * - WOL (by tracking suspends and issuing remote wakeup) + * - msglevel (implies updated messaging) + * - ... probably more ethtool ops + */ + +static const struct ethtool_ops ops = { + .get_drvinfo = eth_get_drvinfo, + .get_link = ethtool_op_get_link, +}; + +static void defer_kevent(struct eth_dev *dev, int flag) +{ + if (test_and_set_bit(flag, &dev->todo)) + return; + if (!schedule_work(&dev->work)) + ERROR(dev, "kevent %d may have been dropped\n", flag); + else + DBG(dev, "kevent %d scheduled\n", flag); +} + +static void rx_complete(struct usb_ep *ep, struct usb_request *req); + +static int +rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) +{ + struct sk_buff *skb; + int retval = -ENOMEM; + size_t size = 0; + struct usb_ep *out; + unsigned long flags; + + spin_lock_irqsave(&dev->lock, flags); + if (dev->port_usb) + out = dev->port_usb->out_ep; + else + out = NULL; + spin_unlock_irqrestore(&dev->lock, flags); + + if (!out) + return -ENOTCONN; + + + /* Padding up to RX_EXTRA handles minor disagreements with host. + * Normally we use the USB "terminate on short read" convention; + * so allow up to (N*maxpacket), since that memory is normally + * already allocated. Some hardware doesn't deal well with short + * reads (e.g. DMA must be N*maxpacket), so for now don't trim a + * byte off the end (to force hardware errors on overflow). + * + * RNDIS uses internal framing, and explicitly allows senders to + * pad to end-of-packet. That's potentially nice for speed, but + * means receivers can't recover lost synch on their own (because + * new packets don't only start after a short RX). + */ + size += sizeof(struct ethhdr) + dev->net->mtu + RX_EXTRA; + size += dev->port_usb->header_len; + size += out->maxpacket - 1; + size -= size % out->maxpacket; + + if (dev->port_usb->is_fixed) + size = max_t(size_t, size, dev->port_usb->fixed_out_len); + + skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags); + if (skb == NULL) { + DBG(dev, "no rx skb\n"); + goto enomem; + } + + /* Some platforms perform better when IP packets are aligned, + * but on at least one, checksumming fails otherwise. Note: + * RNDIS headers involve variable numbers of LE32 values. + */ + skb_reserve(skb, NET_IP_ALIGN); + + req->buf = skb->data; + req->length = size; + req->complete = rx_complete; + req->context = skb; + + retval = usb_ep_queue(out, req, gfp_flags); + if (retval == -ENOMEM) +enomem: + defer_kevent(dev, WORK_RX_MEMORY); + if (retval) { + DBG(dev, "rx submit --> %d\n", retval); + if (skb) + dev_kfree_skb_any(skb); + spin_lock_irqsave(&dev->req_lock, flags); + list_add(&req->list, &dev->rx_reqs); + spin_unlock_irqrestore(&dev->req_lock, flags); + } + return retval; +} + +static void rx_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct sk_buff *skb = req->context, *skb2; + struct eth_dev *dev = ep->driver_data; + int status = req->status; + + switch (status) { + + /* normal completion */ + case 0: + skb_put(skb, req->actual); + + if (dev->unwrap) { + unsigned long flags; + + spin_lock_irqsave(&dev->lock, flags); + if (dev->port_usb) { + status = dev->unwrap(dev->port_usb, + skb, + &dev->rx_frames); + } else { + dev_kfree_skb_any(skb); + status = -ENOTCONN; + } + spin_unlock_irqrestore(&dev->lock, flags); + } else { + skb_queue_tail(&dev->rx_frames, skb); + } + skb = NULL; + + skb2 = skb_dequeue(&dev->rx_frames); + while (skb2) { + if (status < 0 + || ETH_HLEN > skb2->len + || skb2->len > ETH_FRAME_LEN) { + dev->net->stats.rx_errors++; + dev->net->stats.rx_length_errors++; + DBG(dev, "rx length %d\n", skb2->len); + dev_kfree_skb_any(skb2); + goto next_frame; + } + skb2->protocol = eth_type_trans(skb2, dev->net); + dev->net->stats.rx_packets++; + dev->net->stats.rx_bytes += skb2->len; + + /* no buffer copies needed, unless hardware can't + * use skb buffers. + */ + status = netif_rx(skb2); +next_frame: + skb2 = skb_dequeue(&dev->rx_frames); + } + break; + + /* software-driven interface shutdown */ + case -ECONNRESET: /* unlink */ + case -ESHUTDOWN: /* disconnect etc */ + VDBG(dev, "rx shutdown, code %d\n", status); + goto quiesce; + + /* for hardware automagic (such as pxa) */ + case -ECONNABORTED: /* endpoint reset */ + DBG(dev, "rx %s reset\n", ep->name); + defer_kevent(dev, WORK_RX_MEMORY); +quiesce: + dev_kfree_skb_any(skb); + goto clean; + + /* data overrun */ + case -EOVERFLOW: + dev->net->stats.rx_over_errors++; + /* FALLTHROUGH */ + + default: + dev->net->stats.rx_errors++; + DBG(dev, "rx status %d\n", status); + break; + } + + if (skb) + dev_kfree_skb_any(skb); + if (!netif_running(dev->net)) { +clean: + spin_lock(&dev->req_lock); + list_add(&req->list, &dev->rx_reqs); + spin_unlock(&dev->req_lock); + req = NULL; + } + if (req) + rx_submit(dev, req, GFP_ATOMIC); +} + +static int prealloc(struct list_head *list, struct usb_ep *ep, unsigned n) +{ + unsigned i; + struct usb_request *req; + + if (!n) + return -ENOMEM; + + /* queue/recycle up to N requests */ + i = n; + list_for_each_entry(req, list, list) { + if (i-- == 0) + goto extra; + } + while (i--) { + req = usb_ep_alloc_request(ep, GFP_ATOMIC); + if (!req) + return list_empty(list) ? -ENOMEM : 0; + list_add(&req->list, list); + } + return 0; + +extra: + /* free extras */ + for (;;) { + struct list_head *next; + + next = req->list.next; + list_del(&req->list); + usb_ep_free_request(ep, req); + + if (next == list) + break; + + req = container_of(next, struct usb_request, list); + } + return 0; +} + +static int alloc_requests(struct eth_dev *dev, struct gether *link, unsigned n) +{ + int status; + + spin_lock(&dev->req_lock); + status = prealloc(&dev->tx_reqs, link->in_ep, n); + if (status < 0) + goto fail; + status = prealloc(&dev->rx_reqs, link->out_ep, n); + if (status < 0) + goto fail; + goto done; +fail: + DBG(dev, "can't alloc requests\n"); +done: + spin_unlock(&dev->req_lock); + return status; +} + +static void rx_fill(struct eth_dev *dev, gfp_t gfp_flags) +{ + struct usb_request *req; + unsigned long flags; + + /* fill unused rxq slots with some skb */ + spin_lock_irqsave(&dev->req_lock, flags); + while (!list_empty(&dev->rx_reqs)) { + req = container_of(dev->rx_reqs.next, + struct usb_request, list); + list_del_init(&req->list); + spin_unlock_irqrestore(&dev->req_lock, flags); + + if (rx_submit(dev, req, gfp_flags) < 0) { + defer_kevent(dev, WORK_RX_MEMORY); + return; + } + + spin_lock_irqsave(&dev->req_lock, flags); + } + spin_unlock_irqrestore(&dev->req_lock, flags); +} + +static void eth_work(struct work_struct *work) +{ + struct eth_dev *dev = container_of(work, struct eth_dev, work); + + if (test_and_clear_bit(WORK_RX_MEMORY, &dev->todo)) { + if (netif_running(dev->net)) + rx_fill(dev, GFP_KERNEL); + } + + if (dev->todo) + DBG(dev, "work done, flags = 0x%lx\n", dev->todo); +} + +static void tx_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct sk_buff *skb = req->context; + struct eth_dev *dev = ep->driver_data; + + switch (req->status) { + default: + dev->net->stats.tx_errors++; + VDBG(dev, "tx err %d\n", req->status); + /* FALLTHROUGH */ + case -ECONNRESET: /* unlink */ + case -ESHUTDOWN: /* disconnect etc */ + break; + case 0: + dev->net->stats.tx_bytes += skb->len; + } + dev->net->stats.tx_packets++; + + spin_lock(&dev->req_lock); + list_add(&req->list, &dev->tx_reqs); + spin_unlock(&dev->req_lock); + dev_kfree_skb_any(skb); + + atomic_dec(&dev->tx_qlen); + if (netif_carrier_ok(dev->net)) + netif_wake_queue(dev->net); +} + +static inline int is_promisc(u16 cdc_filter) +{ + return cdc_filter & USB_CDC_PACKET_TYPE_PROMISCUOUS; +} + +static netdev_tx_t eth_start_xmit(struct sk_buff *skb, + struct net_device *net) +{ + struct eth_dev *dev = netdev_priv(net); + int length = skb->len; + int retval; + struct usb_request *req = NULL; + unsigned long flags; + struct usb_ep *in; + u16 cdc_filter; + + spin_lock_irqsave(&dev->lock, flags); + if (dev->port_usb) { + in = dev->port_usb->in_ep; + cdc_filter = dev->port_usb->cdc_filter; + } else { + in = NULL; + cdc_filter = 0; + } + spin_unlock_irqrestore(&dev->lock, flags); + + if (!in) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + + /* apply outgoing CDC or RNDIS filters */ + if (!is_promisc(cdc_filter)) { + u8 *dest = skb->data; + + if (is_multicast_ether_addr(dest)) { + u16 type; + + /* ignores USB_CDC_PACKET_TYPE_MULTICAST and host + * SET_ETHERNET_MULTICAST_FILTERS requests + */ + if (is_broadcast_ether_addr(dest)) + type = USB_CDC_PACKET_TYPE_BROADCAST; + else + type = USB_CDC_PACKET_TYPE_ALL_MULTICAST; + if (!(cdc_filter & type)) { + dev_kfree_skb_any(skb); + return NETDEV_TX_OK; + } + } + /* ignores USB_CDC_PACKET_TYPE_DIRECTED */ + } + + spin_lock_irqsave(&dev->req_lock, flags); + /* + * this freelist can be empty if an interrupt triggered disconnect() + * and reconfigured the gadget (shutting down this queue) after the + * network stack decided to xmit but before we got the spinlock. + */ + if (list_empty(&dev->tx_reqs)) { + spin_unlock_irqrestore(&dev->req_lock, flags); + return NETDEV_TX_BUSY; + } + + req = container_of(dev->tx_reqs.next, struct usb_request, list); + list_del(&req->list); + + /* temporarily stop TX queue when the freelist empties */ + if (list_empty(&dev->tx_reqs)) + netif_stop_queue(net); + spin_unlock_irqrestore(&dev->req_lock, flags); + + /* no buffer copies needed, unless the network stack did it + * or the hardware can't use skb buffers. + * or there's not enough space for extra headers we need + */ + if (dev->wrap) { + unsigned long flags; + + spin_lock_irqsave(&dev->lock, flags); + if (dev->port_usb) + skb = dev->wrap(dev->port_usb, skb); + spin_unlock_irqrestore(&dev->lock, flags); + if (!skb) + goto drop; + + length = skb->len; + } + req->buf = skb->data; + req->context = skb; + req->complete = tx_complete; + + /* NCM requires no zlp if transfer is dwNtbInMaxSize */ + if (dev->port_usb->is_fixed && + length == dev->port_usb->fixed_in_len && + (length % in->maxpacket) == 0) + req->zero = 0; + else + req->zero = 1; + + /* use zlp framing on tx for strict CDC-Ether conformance, + * though any robust network rx path ignores extra padding. + * and some hardware doesn't like to write zlps. + */ + if (req->zero && !dev->zlp && (length % in->maxpacket) == 0) + length++; + + req->length = length; + + /* throttle high/super speed IRQ rate back slightly */ + if (gadget_is_dualspeed(dev->gadget)) + req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH || + dev->gadget->speed == USB_SPEED_SUPER) + ? ((atomic_read(&dev->tx_qlen) % qmult) != 0) + : 0; + + retval = usb_ep_queue(in, req, GFP_ATOMIC); + switch (retval) { + default: + DBG(dev, "tx queue err %d\n", retval); + break; + case 0: + net->trans_start = jiffies; + atomic_inc(&dev->tx_qlen); + } + + if (retval) { + dev_kfree_skb_any(skb); +drop: + dev->net->stats.tx_dropped++; + spin_lock_irqsave(&dev->req_lock, flags); + if (list_empty(&dev->tx_reqs)) + netif_start_queue(net); + list_add(&req->list, &dev->tx_reqs); + spin_unlock_irqrestore(&dev->req_lock, flags); + } + return NETDEV_TX_OK; +} + +/*-------------------------------------------------------------------------*/ + +static void eth_start(struct eth_dev *dev, gfp_t gfp_flags) +{ + DBG(dev, "%s\n", __func__); + + /* fill the rx queue */ + rx_fill(dev, gfp_flags); + + /* and open the tx floodgates */ + atomic_set(&dev->tx_qlen, 0); + netif_wake_queue(dev->net); +} + +static int eth_open(struct net_device *net) +{ + struct eth_dev *dev = netdev_priv(net); + struct gether *link; + + DBG(dev, "%s\n", __func__); + if (netif_carrier_ok(dev->net)) + eth_start(dev, GFP_KERNEL); + + spin_lock_irq(&dev->lock); + link = dev->port_usb; + if (link && link->open) + link->open(link); + spin_unlock_irq(&dev->lock); + + return 0; +} + +static int eth_stop(struct net_device *net) +{ + struct eth_dev *dev = netdev_priv(net); + unsigned long flags; + + VDBG(dev, "%s\n", __func__); + netif_stop_queue(net); + + DBG(dev, "stop stats: rx/tx %ld/%ld, errs %ld/%ld\n", + dev->net->stats.rx_packets, dev->net->stats.tx_packets, + dev->net->stats.rx_errors, dev->net->stats.tx_errors + ); + + /* ensure there are no more active requests */ + spin_lock_irqsave(&dev->lock, flags); + if (dev->port_usb) { + struct gether *link = dev->port_usb; + + if (link->close) + link->close(link); + + /* NOTE: we have no abort-queue primitive we could use + * to cancel all pending I/O. Instead, we disable then + * reenable the endpoints ... this idiom may leave toggle + * wrong, but that's a self-correcting error. + * + * REVISIT: we *COULD* just let the transfers complete at + * their own pace; the network stack can handle old packets. + * For the moment we leave this here, since it works. + */ + usb_ep_disable(link->in_ep); + usb_ep_disable(link->out_ep); + if (netif_carrier_ok(net)) { + DBG(dev, "host still using in/out endpoints\n"); + usb_ep_enable(link->in_ep); + usb_ep_enable(link->out_ep); + } + } + spin_unlock_irqrestore(&dev->lock, flags); + + return 0; +} + +/*-------------------------------------------------------------------------*/ + +/* initial value, changed by "ifconfig usb0 hw ether xx:xx:xx:xx:xx:xx" */ +static char *dev_addr; +module_param(dev_addr, charp, S_IRUGO); +MODULE_PARM_DESC(dev_addr, "Device Ethernet Address"); + +/* this address is invisible to ifconfig */ +static char *host_addr; +module_param(host_addr, charp, S_IRUGO); +MODULE_PARM_DESC(host_addr, "Host Ethernet Address"); + +static int get_ether_addr(const char *str, u8 *dev_addr) +{ + if (str) { + unsigned i; + + for (i = 0; i < 6; i++) { + unsigned char num; + + if ((*str == '.') || (*str == ':')) + str++; + num = hex_to_bin(*str++) << 4; + num |= hex_to_bin(*str++); + dev_addr [i] = num; + } + if (is_valid_ether_addr(dev_addr)) + return 0; + } + eth_random_addr(dev_addr); + return 1; +} + +static struct eth_dev *the_dev; + +static const struct net_device_ops eth_netdev_ops = { + .ndo_open = eth_open, + .ndo_stop = eth_stop, + .ndo_start_xmit = eth_start_xmit, + .ndo_change_mtu = ueth_change_mtu, + .ndo_set_mac_address = eth_mac_addr, + .ndo_validate_addr = eth_validate_addr, +}; + +static struct device_type gadget_type = { + .name = "gadget", +}; + +/** + * gether_setup_name - initialize one ethernet-over-usb link + * @g: gadget to associated with these links + * @ethaddr: NULL, or a buffer in which the ethernet address of the + * host side of the link is recorded + * @netname: name for network device (for example, "usb") + * Context: may sleep + * + * This sets up the single network link that may be exported by a + * gadget driver using this framework. The link layer addresses are + * set up using module parameters. + * + * Returns negative errno, or zero on success + */ +int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN], + const char *netname) +{ + struct eth_dev *dev; + struct net_device *net; + int status; + + if (the_dev) + return -EBUSY; + + net = alloc_etherdev(sizeof *dev); + if (!net) + return -ENOMEM; + + dev = netdev_priv(net); + spin_lock_init(&dev->lock); + spin_lock_init(&dev->req_lock); + INIT_WORK(&dev->work, eth_work); + INIT_LIST_HEAD(&dev->tx_reqs); + INIT_LIST_HEAD(&dev->rx_reqs); + + skb_queue_head_init(&dev->rx_frames); + + /* network device setup */ + dev->net = net; + snprintf(net->name, sizeof(net->name), "%s%%d", netname); + + if (get_ether_addr(dev_addr, net->dev_addr)) + dev_warn(&g->dev, + "using random %s ethernet address\n", "self"); + if (get_ether_addr(host_addr, dev->host_mac)) + dev_warn(&g->dev, + "using random %s ethernet address\n", "host"); + + if (ethaddr) + memcpy(ethaddr, dev->host_mac, ETH_ALEN); + + net->netdev_ops = ð_netdev_ops; + + SET_ETHTOOL_OPS(net, &ops); + + dev->gadget = g; + SET_NETDEV_DEV(net, &g->dev); + SET_NETDEV_DEVTYPE(net, &gadget_type); + + status = register_netdev(net); + if (status < 0) { + dev_dbg(&g->dev, "register_netdev failed, %d\n", status); + free_netdev(net); + } else { + INFO(dev, "MAC %pM\n", net->dev_addr); + INFO(dev, "HOST MAC %pM\n", dev->host_mac); + + the_dev = dev; + + /* two kinds of host-initiated state changes: + * - iff DATA transfer is active, carrier is "on" + * - tx queueing enabled if open *and* carrier is "on" + */ + netif_carrier_off(net); + } + + return status; +} + +/** + * gether_cleanup - remove Ethernet-over-USB device + * Context: may sleep + * + * This is called to free all resources allocated by @gether_setup(). + */ +void gether_cleanup(void) +{ + if (!the_dev) + return; + + unregister_netdev(the_dev->net); + flush_work_sync(&the_dev->work); + free_netdev(the_dev->net); + + the_dev = NULL; +} + + +/** + * gether_connect - notify network layer that USB link is active + * @link: the USB link, set up with endpoints, descriptors matching + * current device speed, and any framing wrapper(s) set up. + * Context: irqs blocked + * + * This is called to activate endpoints and let the network layer know + * the connection is active ("carrier detect"). It may cause the I/O + * queues to open and start letting network packets flow, but will in + * any case activate the endpoints so that they respond properly to the + * USB host. + * + * Verify net_device pointer returned using IS_ERR(). If it doesn't + * indicate some error code (negative errno), ep->driver_data values + * have been overwritten. + */ +struct net_device *gether_connect(struct gether *link) +{ + struct eth_dev *dev = the_dev; + int result = 0; + + if (!dev) + return ERR_PTR(-EINVAL); + + link->in_ep->driver_data = dev; + result = usb_ep_enable(link->in_ep); + if (result != 0) { + DBG(dev, "enable %s --> %d\n", + link->in_ep->name, result); + goto fail0; + } + + link->out_ep->driver_data = dev; + result = usb_ep_enable(link->out_ep); + if (result != 0) { + DBG(dev, "enable %s --> %d\n", + link->out_ep->name, result); + goto fail1; + } + + if (result == 0) + result = alloc_requests(dev, link, qlen(dev->gadget)); + + if (result == 0) { + dev->zlp = link->is_zlp_ok; + DBG(dev, "qlen %d\n", qlen(dev->gadget)); + + dev->header_len = link->header_len; + dev->unwrap = link->unwrap; + dev->wrap = link->wrap; + + spin_lock(&dev->lock); + dev->port_usb = link; + link->ioport = dev; + if (netif_running(dev->net)) { + if (link->open) + link->open(link); + } else { + if (link->close) + link->close(link); + } + spin_unlock(&dev->lock); + + netif_carrier_on(dev->net); + if (netif_running(dev->net)) + eth_start(dev, GFP_ATOMIC); + + /* on error, disable any endpoints */ + } else { + (void) usb_ep_disable(link->out_ep); +fail1: + (void) usb_ep_disable(link->in_ep); + } +fail0: + /* caller is responsible for cleanup on error */ + if (result < 0) + return ERR_PTR(result); + return dev->net; +} + +/** + * gether_disconnect - notify network layer that USB link is inactive + * @link: the USB link, on which gether_connect() was called + * Context: irqs blocked + * + * This is called to deactivate endpoints and let the network layer know + * the connection went inactive ("no carrier"). + * + * On return, the state is as if gether_connect() had never been called. + * The endpoints are inactive, and accordingly without active USB I/O. + * Pointers to endpoint descriptors and endpoint private data are nulled. + */ +void gether_disconnect(struct gether *link) +{ + struct eth_dev *dev = link->ioport; + struct usb_request *req; + + WARN_ON(!dev); + if (!dev) + return; + + DBG(dev, "%s\n", __func__); + + netif_stop_queue(dev->net); + netif_carrier_off(dev->net); + + /* disable endpoints, forcing (synchronous) completion + * of all pending i/o. then free the request objects + * and forget about the endpoints. + */ + usb_ep_disable(link->in_ep); + spin_lock(&dev->req_lock); + while (!list_empty(&dev->tx_reqs)) { + req = container_of(dev->tx_reqs.next, + struct usb_request, list); + list_del(&req->list); + + spin_unlock(&dev->req_lock); + usb_ep_free_request(link->in_ep, req); + spin_lock(&dev->req_lock); + } + spin_unlock(&dev->req_lock); + link->in_ep->driver_data = NULL; + link->in_ep->desc = NULL; + + usb_ep_disable(link->out_ep); + spin_lock(&dev->req_lock); + while (!list_empty(&dev->rx_reqs)) { + req = container_of(dev->rx_reqs.next, + struct usb_request, list); + list_del(&req->list); + + spin_unlock(&dev->req_lock); + usb_ep_free_request(link->out_ep, req); + spin_lock(&dev->req_lock); + } + spin_unlock(&dev->req_lock); + link->out_ep->driver_data = NULL; + link->out_ep->desc = NULL; + + /* finish forgetting about this USB link episode */ + dev->header_len = 0; + dev->unwrap = NULL; + dev->wrap = NULL; + + spin_lock(&dev->lock); + dev->port_usb = NULL; + link->ioport = NULL; + spin_unlock(&dev->lock); +} diff --git a/drivers/staging/ccg/u_ether.h b/drivers/staging/ccg/u_ether.h new file mode 100644 index 0000000..6f4a162 --- /dev/null +++ b/drivers/staging/ccg/u_ether.h @@ -0,0 +1,154 @@ +/* + * u_ether.h -- interface to USB gadget "ethernet link" utilities + * + * Copyright (C) 2003-2005,2008 David Brownell + * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger + * Copyright (C) 2008 Nokia Corporation + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#ifndef __U_ETHER_H +#define __U_ETHER_H + +#include +#include +#include +#include + +#include "gadget_chips.h" + + +/* + * This represents the USB side of an "ethernet" link, managed by a USB + * function which provides control and (maybe) framing. Two functions + * in different configurations could share the same ethernet link/netdev, + * using different host interaction models. + * + * There is a current limitation that only one instance of this link may + * be present in any given configuration. When that's a problem, network + * layer facilities can be used to package multiple logical links on this + * single "physical" one. + */ +struct gether { + struct usb_function func; + + /* updated by gether_{connect,disconnect} */ + struct eth_dev *ioport; + + /* endpoints handle full and/or high speeds */ + struct usb_ep *in_ep; + struct usb_ep *out_ep; + + bool is_zlp_ok; + + u16 cdc_filter; + + /* hooks for added framing, as needed for RNDIS and EEM. */ + u32 header_len; + /* NCM requires fixed size bundles */ + bool is_fixed; + u32 fixed_out_len; + u32 fixed_in_len; + struct sk_buff *(*wrap)(struct gether *port, + struct sk_buff *skb); + int (*unwrap)(struct gether *port, + struct sk_buff *skb, + struct sk_buff_head *list); + + /* called on network open/close */ + void (*open)(struct gether *); + void (*close)(struct gether *); +}; + +#define DEFAULT_FILTER (USB_CDC_PACKET_TYPE_BROADCAST \ + |USB_CDC_PACKET_TYPE_ALL_MULTICAST \ + |USB_CDC_PACKET_TYPE_PROMISCUOUS \ + |USB_CDC_PACKET_TYPE_DIRECTED) + +/* variant of gether_setup that allows customizing network device name */ +int gether_setup_name(struct usb_gadget *g, u8 ethaddr[ETH_ALEN], + const char *netname); + +/* netdev setup/teardown as directed by the gadget driver */ +/* gether_setup - initialize one ethernet-over-usb link + * @g: gadget to associated with these links + * @ethaddr: NULL, or a buffer in which the ethernet address of the + * host side of the link is recorded + * Context: may sleep + * + * This sets up the single network link that may be exported by a + * gadget driver using this framework. The link layer addresses are + * set up using module parameters. + * + * Returns negative errno, or zero on success + */ +static inline int gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN]) +{ + return gether_setup_name(g, ethaddr, "usb"); +} + +void gether_cleanup(void); + +/* connect/disconnect is handled by individual functions */ +struct net_device *gether_connect(struct gether *); +void gether_disconnect(struct gether *); + +/* Some controllers can't support CDC Ethernet (ECM) ... */ +static inline bool can_support_ecm(struct usb_gadget *gadget) +{ + if (!gadget_supports_altsettings(gadget)) + return false; + + /* Everything else is *presumably* fine ... but this is a bit + * chancy, so be **CERTAIN** there are no hardware issues with + * your controller. Add it above if it can't handle CDC. + */ + return true; +} + +/* each configuration may bind one instance of an ethernet link */ +int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); +int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); +int ncm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); +int eem_bind_config(struct usb_configuration *c); + +#ifdef USB_ETH_RNDIS + +int rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], + u32 vendorID, const char *manufacturer); + +#else + +static inline int +rndis_bind_config_vendor(struct usb_configuration *c, u8 ethaddr[ETH_ALEN], + u32 vendorID, const char *manufacturer) +{ + return 0; +} + +#endif + +/** + * rndis_bind_config - add RNDIS network link to a configuration + * @c: the configuration to support the network link + * @ethaddr: a buffer in which the ethernet address of the host side + * side of the link was recorded + * Context: single threaded during gadget setup + * + * Returns zero on success, else negative errno. + * + * Caller must have called @gether_setup(). Caller is also responsible + * for calling @gether_cleanup() before module unload. + */ +static inline int rndis_bind_config(struct usb_configuration *c, + u8 ethaddr[ETH_ALEN]) +{ + return rndis_bind_config_vendor(c, ethaddr, 0, NULL); +} + + +#endif /* __U_ETHER_H */ diff --git a/drivers/staging/ccg/u_serial.c b/drivers/staging/ccg/u_serial.c new file mode 100644 index 0000000..5b3f5ff --- /dev/null +++ b/drivers/staging/ccg/u_serial.c @@ -0,0 +1,1341 @@ +/* + * u_serial.c - utilities for USB gadget "serial port"/TTY support + * + * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com) + * Copyright (C) 2008 David Brownell + * Copyright (C) 2008 by Nokia Corporation + * + * This code also borrows from usbserial.c, which is + * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com) + * Copyright (C) 2000 Peter Berger (pberger@brimson.com) + * Copyright (C) 2000 Al Borchers (alborchers@steinerpoint.com) + * + * This software is distributed under the terms of the GNU General + * Public License ("GPL") as published by the Free Software Foundation, + * either version 2 of that License or (at your option) any later version. + */ + +/* #define VERBOSE_DEBUG */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "u_serial.h" + + +/* + * This component encapsulates the TTY layer glue needed to provide basic + * "serial port" functionality through the USB gadget stack. Each such + * port is exposed through a /dev/ttyGS* node. + * + * After initialization (gserial_setup), these TTY port devices stay + * available until they are removed (gserial_cleanup). Each one may be + * connected to a USB function (gserial_connect), or disconnected (with + * gserial_disconnect) when the USB host issues a config change event. + * Data can only flow when the port is connected to the host. + * + * A given TTY port can be made available in multiple configurations. + * For example, each one might expose a ttyGS0 node which provides a + * login application. In one case that might use CDC ACM interface 0, + * while another configuration might use interface 3 for that. The + * work to handle that (including descriptor management) is not part + * of this component. + * + * Configurations may expose more than one TTY port. For example, if + * ttyGS0 provides login service, then ttyGS1 might provide dialer access + * for a telephone or fax link. And ttyGS2 might be something that just + * needs a simple byte stream interface for some messaging protocol that + * is managed in userspace ... OBEX, PTP, and MTP have been mentioned. + */ + +#define PREFIX "ttyGS" + +/* + * gserial is the lifecycle interface, used by USB functions + * gs_port is the I/O nexus, used by the tty driver + * tty_struct links to the tty/filesystem framework + * + * gserial <---> gs_port ... links will be null when the USB link is + * inactive; managed by gserial_{connect,disconnect}(). each gserial + * instance can wrap its own USB control protocol. + * gserial->ioport == usb_ep->driver_data ... gs_port + * gs_port->port_usb ... gserial + * + * gs_port <---> tty_struct ... links will be null when the TTY file + * isn't opened; managed by gs_open()/gs_close() + * gserial->port_tty ... tty_struct + * tty_struct->driver_data ... gserial + */ + +/* RX and TX queues can buffer QUEUE_SIZE packets before they hit the + * next layer of buffering. For TX that's a circular buffer; for RX + * consider it a NOP. A third layer is provided by the TTY code. + */ +#define QUEUE_SIZE 16 +#define WRITE_BUF_SIZE 8192 /* TX only */ + +/* circular buffer */ +struct gs_buf { + unsigned buf_size; + char *buf_buf; + char *buf_get; + char *buf_put; +}; + +/* + * The port structure holds info for each port, one for each minor number + * (and thus for each /dev/ node). + */ +struct gs_port { + struct tty_port port; + spinlock_t port_lock; /* guard port_* access */ + + struct gserial *port_usb; + + bool openclose; /* open/close in progress */ + u8 port_num; + + struct list_head read_pool; + int read_started; + int read_allocated; + struct list_head read_queue; + unsigned n_read; + struct tasklet_struct push; + + struct list_head write_pool; + int write_started; + int write_allocated; + struct gs_buf port_write_buf; + wait_queue_head_t drain_wait; /* wait while writes drain */ + + /* REVISIT this state ... */ + struct usb_cdc_line_coding port_line_coding; /* 8-N-1 etc */ +}; + +/* increase N_PORTS if you need more */ +#define N_PORTS 4 +static struct portmaster { + struct mutex lock; /* protect open/close */ + struct gs_port *port; +} ports[N_PORTS]; +static unsigned n_ports; + +#define GS_CLOSE_TIMEOUT 15 /* seconds */ + + + +#ifdef VERBOSE_DEBUG +#define pr_vdebug(fmt, arg...) \ + pr_debug(fmt, ##arg) +#else +#define pr_vdebug(fmt, arg...) \ + ({ if (0) pr_debug(fmt, ##arg); }) +#endif + +/*-------------------------------------------------------------------------*/ + +/* Circular Buffer */ + +/* + * gs_buf_alloc + * + * Allocate a circular buffer and all associated memory. + */ +static int gs_buf_alloc(struct gs_buf *gb, unsigned size) +{ + gb->buf_buf = kmalloc(size, GFP_KERNEL); + if (gb->buf_buf == NULL) + return -ENOMEM; + + gb->buf_size = size; + gb->buf_put = gb->buf_buf; + gb->buf_get = gb->buf_buf; + + return 0; +} + +/* + * gs_buf_free + * + * Free the buffer and all associated memory. + */ +static void gs_buf_free(struct gs_buf *gb) +{ + kfree(gb->buf_buf); + gb->buf_buf = NULL; +} + +/* + * gs_buf_clear + * + * Clear out all data in the circular buffer. + */ +static void gs_buf_clear(struct gs_buf *gb) +{ + gb->buf_get = gb->buf_put; + /* equivalent to a get of all data available */ +} + +/* + * gs_buf_data_avail + * + * Return the number of bytes of data written into the circular + * buffer. + */ +static unsigned gs_buf_data_avail(struct gs_buf *gb) +{ + return (gb->buf_size + gb->buf_put - gb->buf_get) % gb->buf_size; +} + +/* + * gs_buf_space_avail + * + * Return the number of bytes of space available in the circular + * buffer. + */ +static unsigned gs_buf_space_avail(struct gs_buf *gb) +{ + return (gb->buf_size + gb->buf_get - gb->buf_put - 1) % gb->buf_size; +} + +/* + * gs_buf_put + * + * Copy data data from a user buffer and put it into the circular buffer. + * Restrict to the amount of space available. + * + * Return the number of bytes copied. + */ +static unsigned +gs_buf_put(struct gs_buf *gb, const char *buf, unsigned count) +{ + unsigned len; + + len = gs_buf_space_avail(gb); + if (count > len) + count = len; + + if (count == 0) + return 0; + + len = gb->buf_buf + gb->buf_size - gb->buf_put; + if (count > len) { + memcpy(gb->buf_put, buf, len); + memcpy(gb->buf_buf, buf+len, count - len); + gb->buf_put = gb->buf_buf + count - len; + } else { + memcpy(gb->buf_put, buf, count); + if (count < len) + gb->buf_put += count; + else /* count == len */ + gb->buf_put = gb->buf_buf; + } + + return count; +} + +/* + * gs_buf_get + * + * Get data from the circular buffer and copy to the given buffer. + * Restrict to the amount of data available. + * + * Return the number of bytes copied. + */ +static unsigned +gs_buf_get(struct gs_buf *gb, char *buf, unsigned count) +{ + unsigned len; + + len = gs_buf_data_avail(gb); + if (count > len) + count = len; + + if (count == 0) + return 0; + + len = gb->buf_buf + gb->buf_size - gb->buf_get; + if (count > len) { + memcpy(buf, gb->buf_get, len); + memcpy(buf+len, gb->buf_buf, count - len); + gb->buf_get = gb->buf_buf + count - len; + } else { + memcpy(buf, gb->buf_get, count); + if (count < len) + gb->buf_get += count; + else /* count == len */ + gb->buf_get = gb->buf_buf; + } + + return count; +} + +/*-------------------------------------------------------------------------*/ + +/* I/O glue between TTY (upper) and USB function (lower) driver layers */ + +/* + * gs_alloc_req + * + * Allocate a usb_request and its buffer. Returns a pointer to the + * usb_request or NULL if there is an error. + */ +struct usb_request * +gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t kmalloc_flags) +{ + struct usb_request *req; + + req = usb_ep_alloc_request(ep, kmalloc_flags); + + if (req != NULL) { + req->length = len; + req->buf = kmalloc(len, kmalloc_flags); + if (req->buf == NULL) { + usb_ep_free_request(ep, req); + return NULL; + } + } + + return req; +} + +/* + * gs_free_req + * + * Free a usb_request and its buffer. + */ +void gs_free_req(struct usb_ep *ep, struct usb_request *req) +{ + kfree(req->buf); + usb_ep_free_request(ep, req); +} + +/* + * gs_send_packet + * + * If there is data to send, a packet is built in the given + * buffer and the size is returned. If there is no data to + * send, 0 is returned. + * + * Called with port_lock held. + */ +static unsigned +gs_send_packet(struct gs_port *port, char *packet, unsigned size) +{ + unsigned len; + + len = gs_buf_data_avail(&port->port_write_buf); + if (len < size) + size = len; + if (size != 0) + size = gs_buf_get(&port->port_write_buf, packet, size); + return size; +} + +/* + * gs_start_tx + * + * This function finds available write requests, calls + * gs_send_packet to fill these packets with data, and + * continues until either there are no more write requests + * available or no more data to send. This function is + * run whenever data arrives or write requests are available. + * + * Context: caller owns port_lock; port_usb is non-null. + */ +static int gs_start_tx(struct gs_port *port) +/* +__releases(&port->port_lock) +__acquires(&port->port_lock) +*/ +{ + struct list_head *pool = &port->write_pool; + struct usb_ep *in = port->port_usb->in; + int status = 0; + bool do_tty_wake = false; + + while (!list_empty(pool)) { + struct usb_request *req; + int len; + + if (port->write_started >= QUEUE_SIZE) + break; + + req = list_entry(pool->next, struct usb_request, list); + len = gs_send_packet(port, req->buf, in->maxpacket); + if (len == 0) { + wake_up_interruptible(&port->drain_wait); + break; + } + do_tty_wake = true; + + req->length = len; + list_del(&req->list); + req->zero = (gs_buf_data_avail(&port->port_write_buf) == 0); + + pr_vdebug(PREFIX "%d: tx len=%d, 0x%02x 0x%02x 0x%02x ...\n", + port->port_num, len, *((u8 *)req->buf), + *((u8 *)req->buf+1), *((u8 *)req->buf+2)); + + /* Drop lock while we call out of driver; completions + * could be issued while we do so. Disconnection may + * happen too; maybe immediately before we queue this! + * + * NOTE that we may keep sending data for a while after + * the TTY closed (dev->ioport->port_tty is NULL). + */ + spin_unlock(&port->port_lock); + status = usb_ep_queue(in, req, GFP_ATOMIC); + spin_lock(&port->port_lock); + + if (status) { + pr_debug("%s: %s %s err %d\n", + __func__, "queue", in->name, status); + list_add(&req->list, pool); + break; + } + + port->write_started++; + + /* abort immediately after disconnect */ + if (!port->port_usb) + break; + } + + if (do_tty_wake && port->port.tty) + tty_wakeup(port->port.tty); + return status; +} + +/* + * Context: caller owns port_lock, and port_usb is set + */ +static unsigned gs_start_rx(struct gs_port *port) +/* +__releases(&port->port_lock) +__acquires(&port->port_lock) +*/ +{ + struct list_head *pool = &port->read_pool; + struct usb_ep *out = port->port_usb->out; + + while (!list_empty(pool)) { + struct usb_request *req; + int status; + struct tty_struct *tty; + + /* no more rx if closed */ + tty = port->port.tty; + if (!tty) + break; + + if (port->read_started >= QUEUE_SIZE) + break; + + req = list_entry(pool->next, struct usb_request, list); + list_del(&req->list); + req->length = out->maxpacket; + + /* drop lock while we call out; the controller driver + * may need to call us back (e.g. for disconnect) + */ + spin_unlock(&port->port_lock); + status = usb_ep_queue(out, req, GFP_ATOMIC); + spin_lock(&port->port_lock); + + if (status) { + pr_debug("%s: %s %s err %d\n", + __func__, "queue", out->name, status); + list_add(&req->list, pool); + break; + } + port->read_started++; + + /* abort immediately after disconnect */ + if (!port->port_usb) + break; + } + return port->read_started; +} + +/* + * RX tasklet takes data out of the RX queue and hands it up to the TTY + * layer until it refuses to take any more data (or is throttled back). + * Then it issues reads for any further data. + * + * If the RX queue becomes full enough that no usb_request is queued, + * the OUT endpoint may begin NAKing as soon as its FIFO fills up. + * So QUEUE_SIZE packets plus however many the FIFO holds (usually two) + * can be buffered before the TTY layer's buffers (currently 64 KB). + */ +static void gs_rx_push(unsigned long _port) +{ + struct gs_port *port = (void *)_port; + struct tty_struct *tty; + struct list_head *queue = &port->read_queue; + bool disconnect = false; + bool do_push = false; + + /* hand any queued data to the tty */ + spin_lock_irq(&port->port_lock); + tty = port->port.tty; + while (!list_empty(queue)) { + struct usb_request *req; + + req = list_first_entry(queue, struct usb_request, list); + + /* discard data if tty was closed */ + if (!tty) + goto recycle; + + /* leave data queued if tty was rx throttled */ + if (test_bit(TTY_THROTTLED, &tty->flags)) + break; + + switch (req->status) { + case -ESHUTDOWN: + disconnect = true; + pr_vdebug(PREFIX "%d: shutdown\n", port->port_num); + break; + + default: + /* presumably a transient fault */ + pr_warning(PREFIX "%d: unexpected RX status %d\n", + port->port_num, req->status); + /* FALLTHROUGH */ + case 0: + /* normal completion */ + break; + } + + /* push data to (open) tty */ + if (req->actual) { + char *packet = req->buf; + unsigned size = req->actual; + unsigned n; + int count; + + /* we may have pushed part of this packet already... */ + n = port->n_read; + if (n) { + packet += n; + size -= n; + } + + count = tty_insert_flip_string(tty, packet, size); + if (count) + do_push = true; + if (count != size) { + /* stop pushing; TTY layer can't handle more */ + port->n_read += count; + pr_vdebug(PREFIX "%d: rx block %d/%d\n", + port->port_num, + count, req->actual); + break; + } + port->n_read = 0; + } +recycle: + list_move(&req->list, &port->read_pool); + port->read_started--; + } + + /* Push from tty to ldisc; without low_latency set this is handled by + * a workqueue, so we won't get callbacks and can hold port_lock + */ + if (tty && do_push) + tty_flip_buffer_push(tty); + + + /* We want our data queue to become empty ASAP, keeping data + * in the tty and ldisc (not here). If we couldn't push any + * this time around, there may be trouble unless there's an + * implicit tty_unthrottle() call on its way... + * + * REVISIT we should probably add a timer to keep the tasklet + * from starving ... but it's not clear that case ever happens. + */ + if (!list_empty(queue) && tty) { + if (!test_bit(TTY_THROTTLED, &tty->flags)) { + if (do_push) + tasklet_schedule(&port->push); + else + pr_warning(PREFIX "%d: RX not scheduled?\n", + port->port_num); + } + } + + /* If we're still connected, refill the USB RX queue. */ + if (!disconnect && port->port_usb) + gs_start_rx(port); + + spin_unlock_irq(&port->port_lock); +} + +static void gs_read_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct gs_port *port = ep->driver_data; + + /* Queue all received data until the tty layer is ready for it. */ + spin_lock(&port->port_lock); + list_add_tail(&req->list, &port->read_queue); + tasklet_schedule(&port->push); + spin_unlock(&port->port_lock); +} + +static void gs_write_complete(struct usb_ep *ep, struct usb_request *req) +{ + struct gs_port *port = ep->driver_data; + + spin_lock(&port->port_lock); + list_add(&req->list, &port->write_pool); + port->write_started--; + + switch (req->status) { + default: + /* presumably a transient fault */ + pr_warning("%s: unexpected %s status %d\n", + __func__, ep->name, req->status); + /* FALL THROUGH */ + case 0: + /* normal completion */ + gs_start_tx(port); + break; + + case -ESHUTDOWN: + /* disconnect */ + pr_vdebug("%s: %s shutdown\n", __func__, ep->name); + break; + } + + spin_unlock(&port->port_lock); +} + +static void gs_free_requests(struct usb_ep *ep, struct list_head *head, + int *allocated) +{ + struct usb_request *req; + + while (!list_empty(head)) { + req = list_entry(head->next, struct usb_request, list); + list_del(&req->list); + gs_free_req(ep, req); + if (allocated) + (*allocated)--; + } +} + +static int gs_alloc_requests(struct usb_ep *ep, struct list_head *head, + void (*fn)(struct usb_ep *, struct usb_request *), + int *allocated) +{ + int i; + struct usb_request *req; + int n = allocated ? QUEUE_SIZE - *allocated : QUEUE_SIZE; + + /* Pre-allocate up to QUEUE_SIZE transfers, but if we can't + * do quite that many this time, don't fail ... we just won't + * be as speedy as we might otherwise be. + */ + for (i = 0; i < n; i++) { + req = gs_alloc_req(ep, ep->maxpacket, GFP_ATOMIC); + if (!req) + return list_empty(head) ? -ENOMEM : 0; + req->complete = fn; + list_add_tail(&req->list, head); + if (allocated) + (*allocated)++; + } + return 0; +} + +/** + * gs_start_io - start USB I/O streams + * @dev: encapsulates endpoints to use + * Context: holding port_lock; port_tty and port_usb are non-null + * + * We only start I/O when something is connected to both sides of + * this port. If nothing is listening on the host side, we may + * be pointlessly filling up our TX buffers and FIFO. + */ +static int gs_start_io(struct gs_port *port) +{ + struct list_head *head = &port->read_pool; + struct usb_ep *ep = port->port_usb->out; + int status; + unsigned started; + + /* Allocate RX and TX I/O buffers. We can't easily do this much + * earlier (with GFP_KERNEL) because the requests are coupled to + * endpoints, as are the packet sizes we'll be using. Different + * configurations may use different endpoints with a given port; + * and high speed vs full speed changes packet sizes too. + */ + status = gs_alloc_requests(ep, head, gs_read_complete, + &port->read_allocated); + if (status) + return status; + + status = gs_alloc_requests(port->port_usb->in, &port->write_pool, + gs_write_complete, &port->write_allocated); + if (status) { + gs_free_requests(ep, head, &port->read_allocated); + return status; + } + + /* queue read requests */ + port->n_read = 0; + started = gs_start_rx(port); + + /* unblock any pending writes into our circular buffer */ + if (started) { + tty_wakeup(port->port.tty); + } else { + gs_free_requests(ep, head, &port->read_allocated); + gs_free_requests(port->port_usb->in, &port->write_pool, + &port->write_allocated); + status = -EIO; + } + + return status; +} + +/*-------------------------------------------------------------------------*/ + +/* TTY Driver */ + +/* + * gs_open sets up the link between a gs_port and its associated TTY. + * That link is broken *only* by TTY close(), and all driver methods + * know that. + */ +static int gs_open(struct tty_struct *tty, struct file *file) +{ + int port_num = tty->index; + struct gs_port *port; + int status; + + do { + mutex_lock(&ports[port_num].lock); + port = ports[port_num].port; + if (!port) + status = -ENODEV; + else { + spin_lock_irq(&port->port_lock); + + /* already open? Great. */ + if (port->port.count) { + status = 0; + port->port.count++; + + /* currently opening/closing? wait ... */ + } else if (port->openclose) { + status = -EBUSY; + + /* ... else we do the work */ + } else { + status = -EAGAIN; + port->openclose = true; + } + spin_unlock_irq(&port->port_lock); + } + mutex_unlock(&ports[port_num].lock); + + switch (status) { + default: + /* fully handled */ + return status; + case -EAGAIN: + /* must do the work */ + break; + case -EBUSY: + /* wait for EAGAIN task to finish */ + msleep(1); + /* REVISIT could have a waitchannel here, if + * concurrent open performance is important + */ + break; + } + } while (status != -EAGAIN); + + /* Do the "real open" */ + spin_lock_irq(&port->port_lock); + + /* allocate circular buffer on first open */ + if (port->port_write_buf.buf_buf == NULL) { + + spin_unlock_irq(&port->port_lock); + status = gs_buf_alloc(&port->port_write_buf, WRITE_BUF_SIZE); + spin_lock_irq(&port->port_lock); + + if (status) { + pr_debug("gs_open: ttyGS%d (%p,%p) no buffer\n", + port->port_num, tty, file); + port->openclose = false; + goto exit_unlock_port; + } + } + + /* REVISIT if REMOVED (ports[].port NULL), abort the open + * to let rmmod work faster (but this way isn't wrong). + */ + + /* REVISIT maybe wait for "carrier detect" */ + + tty->driver_data = port; + port->port.tty = tty; + + port->port.count = 1; + port->openclose = false; + + /* if connected, start the I/O stream */ + if (port->port_usb) { + struct gserial *gser = port->port_usb; + + pr_debug("gs_open: start ttyGS%d\n", port->port_num); + gs_start_io(port); + + if (gser->connect) + gser->connect(gser); + } + + pr_debug("gs_open: ttyGS%d (%p,%p)\n", port->port_num, tty, file); + + status = 0; + +exit_unlock_port: + spin_unlock_irq(&port->port_lock); + return status; +} + +static int gs_writes_finished(struct gs_port *p) +{ + int cond; + + /* return true on disconnect or empty buffer */ + spin_lock_irq(&p->port_lock); + cond = (p->port_usb == NULL) || !gs_buf_data_avail(&p->port_write_buf); + spin_unlock_irq(&p->port_lock); + + return cond; +} + +static void gs_close(struct tty_struct *tty, struct file *file) +{ + struct gs_port *port = tty->driver_data; + struct gserial *gser; + + spin_lock_irq(&port->port_lock); + + if (port->port.count != 1) { + if (port->port.count == 0) + WARN_ON(1); + else + --port->port.count; + goto exit; + } + + pr_debug("gs_close: ttyGS%d (%p,%p) ...\n", port->port_num, tty, file); + + /* mark port as closing but in use; we can drop port lock + * and sleep if necessary + */ + port->openclose = true; + port->port.count = 0; + + gser = port->port_usb; + if (gser && gser->disconnect) + gser->disconnect(gser); + + /* wait for circular write buffer to drain, disconnect, or at + * most GS_CLOSE_TIMEOUT seconds; then discard the rest + */ + if (gs_buf_data_avail(&port->port_write_buf) > 0 && gser) { + spin_unlock_irq(&port->port_lock); + wait_event_interruptible_timeout(port->drain_wait, + gs_writes_finished(port), + GS_CLOSE_TIMEOUT * HZ); + spin_lock_irq(&port->port_lock); + gser = port->port_usb; + } + + /* Iff we're disconnected, there can be no I/O in flight so it's + * ok to free the circular buffer; else just scrub it. And don't + * let the push tasklet fire again until we're re-opened. + */ + if (gser == NULL) + gs_buf_free(&port->port_write_buf); + else + gs_buf_clear(&port->port_write_buf); + + tty->driver_data = NULL; + port->port.tty = NULL; + + port->openclose = false; + + pr_debug("gs_close: ttyGS%d (%p,%p) done!\n", + port->port_num, tty, file); + + wake_up_interruptible(&port->port.close_wait); +exit: + spin_unlock_irq(&port->port_lock); +} + +static int gs_write(struct tty_struct *tty, const unsigned char *buf, int count) +{ + struct gs_port *port = tty->driver_data; + unsigned long flags; + int status; + + pr_vdebug("gs_write: ttyGS%d (%p) writing %d bytes\n", + port->port_num, tty, count); + + spin_lock_irqsave(&port->port_lock, flags); + if (count) + count = gs_buf_put(&port->port_write_buf, buf, count); + /* treat count == 0 as flush_chars() */ + if (port->port_usb) + status = gs_start_tx(port); + spin_unlock_irqrestore(&port->port_lock, flags); + + return count; +} + +static int gs_put_char(struct tty_struct *tty, unsigned char ch) +{ + struct gs_port *port = tty->driver_data; + unsigned long flags; + int status; + + pr_vdebug("gs_put_char: (%d,%p) char=0x%x, called from %pf\n", + port->port_num, tty, ch, __builtin_return_address(0)); + + spin_lock_irqsave(&port->port_lock, flags); + status = gs_buf_put(&port->port_write_buf, &ch, 1); + spin_unlock_irqrestore(&port->port_lock, flags); + + return status; +} + +static void gs_flush_chars(struct tty_struct *tty) +{ + struct gs_port *port = tty->driver_data; + unsigned long flags; + + pr_vdebug("gs_flush_chars: (%d,%p)\n", port->port_num, tty); + + spin_lock_irqsave(&port->port_lock, flags); + if (port->port_usb) + gs_start_tx(port); + spin_unlock_irqrestore(&port->port_lock, flags); +} + +static int gs_write_room(struct tty_struct *tty) +{ + struct gs_port *port = tty->driver_data; + unsigned long flags; + int room = 0; + + spin_lock_irqsave(&port->port_lock, flags); + if (port->port_usb) + room = gs_buf_space_avail(&port->port_write_buf); + spin_unlock_irqrestore(&port->port_lock, flags); + + pr_vdebug("gs_write_room: (%d,%p) room=%d\n", + port->port_num, tty, room); + + return room; +} + +static int gs_chars_in_buffer(struct tty_struct *tty) +{ + struct gs_port *port = tty->driver_data; + unsigned long flags; + int chars = 0; + + spin_lock_irqsave(&port->port_lock, flags); + chars = gs_buf_data_avail(&port->port_write_buf); + spin_unlock_irqrestore(&port->port_lock, flags); + + pr_vdebug("gs_chars_in_buffer: (%d,%p) chars=%d\n", + port->port_num, tty, chars); + + return chars; +} + +/* undo side effects of setting TTY_THROTTLED */ +static void gs_unthrottle(struct tty_struct *tty) +{ + struct gs_port *port = tty->driver_data; + unsigned long flags; + + spin_lock_irqsave(&port->port_lock, flags); + if (port->port_usb) { + /* Kickstart read queue processing. We don't do xon/xoff, + * rts/cts, or other handshaking with the host, but if the + * read queue backs up enough we'll be NAKing OUT packets. + */ + tasklet_schedule(&port->push); + pr_vdebug(PREFIX "%d: unthrottle\n", port->port_num); + } + spin_unlock_irqrestore(&port->port_lock, flags); +} + +static int gs_break_ctl(struct tty_struct *tty, int duration) +{ + struct gs_port *port = tty->driver_data; + int status = 0; + struct gserial *gser; + + pr_vdebug("gs_break_ctl: ttyGS%d, send break (%d) \n", + port->port_num, duration); + + spin_lock_irq(&port->port_lock); + gser = port->port_usb; + if (gser && gser->send_break) + status = gser->send_break(gser, duration); + spin_unlock_irq(&port->port_lock); + + return status; +} + +static const struct tty_operations gs_tty_ops = { + .open = gs_open, + .close = gs_close, + .write = gs_write, + .put_char = gs_put_char, + .flush_chars = gs_flush_chars, + .write_room = gs_write_room, + .chars_in_buffer = gs_chars_in_buffer, + .unthrottle = gs_unthrottle, + .break_ctl = gs_break_ctl, +}; + +/*-------------------------------------------------------------------------*/ + +static struct tty_driver *gs_tty_driver; + +static int +gs_port_alloc(unsigned port_num, struct usb_cdc_line_coding *coding) +{ + struct gs_port *port; + + port = kzalloc(sizeof(struct gs_port), GFP_KERNEL); + if (port == NULL) + return -ENOMEM; + + tty_port_init(&port->port); + spin_lock_init(&port->port_lock); + init_waitqueue_head(&port->drain_wait); + + tasklet_init(&port->push, gs_rx_push, (unsigned long) port); + + INIT_LIST_HEAD(&port->read_pool); + INIT_LIST_HEAD(&port->read_queue); + INIT_LIST_HEAD(&port->write_pool); + + port->port_num = port_num; + port->port_line_coding = *coding; + + ports[port_num].port = port; + + return 0; +} + +/** + * gserial_setup - initialize TTY driver for one or more ports + * @g: gadget to associate with these ports + * @count: how many ports to support + * Context: may sleep + * + * The TTY stack needs to know in advance how many devices it should + * plan to manage. Use this call to set up the ports you will be + * exporting through USB. Later, connect them to functions based + * on what configuration is activated by the USB host; and disconnect + * them as appropriate. + * + * An example would be a two-configuration device in which both + * configurations expose port 0, but through different functions. + * One configuration could even expose port 1 while the other + * one doesn't. + * + * Returns negative errno or zero. + */ +int gserial_setup(struct usb_gadget *g, unsigned count) +{ + unsigned i; + struct usb_cdc_line_coding coding; + int status; + + if (count == 0 || count > N_PORTS) + return -EINVAL; + + gs_tty_driver = alloc_tty_driver(count); + if (!gs_tty_driver) + return -ENOMEM; + + gs_tty_driver->driver_name = "g_serial"; + gs_tty_driver->name = PREFIX; + /* uses dynamically assigned dev_t values */ + + gs_tty_driver->type = TTY_DRIVER_TYPE_SERIAL; + gs_tty_driver->subtype = SERIAL_TYPE_NORMAL; + gs_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; + gs_tty_driver->init_termios = tty_std_termios; + + /* 9600-8-N-1 ... matches defaults expected by "usbser.sys" on + * MS-Windows. Otherwise, most of these flags shouldn't affect + * anything unless we were to actually hook up to a serial line. + */ + gs_tty_driver->init_termios.c_cflag = + B9600 | CS8 | CREAD | HUPCL | CLOCAL; + gs_tty_driver->init_termios.c_ispeed = 9600; + gs_tty_driver->init_termios.c_ospeed = 9600; + + coding.dwDTERate = cpu_to_le32(9600); + coding.bCharFormat = 8; + coding.bParityType = USB_CDC_NO_PARITY; + coding.bDataBits = USB_CDC_1_STOP_BITS; + + tty_set_operations(gs_tty_driver, &gs_tty_ops); + + /* make devices be openable */ + for (i = 0; i < count; i++) { + mutex_init(&ports[i].lock); + status = gs_port_alloc(i, &coding); + if (status) { + count = i; + goto fail; + } + } + n_ports = count; + + /* export the driver ... */ + status = tty_register_driver(gs_tty_driver); + if (status) { + pr_err("%s: cannot register, err %d\n", + __func__, status); + goto fail; + } + + /* ... and sysfs class devices, so mdev/udev make /dev/ttyGS* */ + for (i = 0; i < count; i++) { + struct device *tty_dev; + + tty_dev = tty_register_device(gs_tty_driver, i, &g->dev); + if (IS_ERR(tty_dev)) + pr_warning("%s: no classdev for port %d, err %ld\n", + __func__, i, PTR_ERR(tty_dev)); + } + + pr_debug("%s: registered %d ttyGS* device%s\n", __func__, + count, (count == 1) ? "" : "s"); + + return status; +fail: + while (count--) + kfree(ports[count].port); + put_tty_driver(gs_tty_driver); + gs_tty_driver = NULL; + return status; +} + +static int gs_closed(struct gs_port *port) +{ + int cond; + + spin_lock_irq(&port->port_lock); + cond = (port->port.count == 0) && !port->openclose; + spin_unlock_irq(&port->port_lock); + return cond; +} + +/** + * gserial_cleanup - remove TTY-over-USB driver and devices + * Context: may sleep + * + * This is called to free all resources allocated by @gserial_setup(). + * Accordingly, it may need to wait until some open /dev/ files have + * closed. + * + * The caller must have issued @gserial_disconnect() for any ports + * that had previously been connected, so that there is never any + * I/O pending when it's called. + */ +void gserial_cleanup(void) +{ + unsigned i; + struct gs_port *port; + + if (!gs_tty_driver) + return; + + /* start sysfs and /dev/ttyGS* node removal */ + for (i = 0; i < n_ports; i++) + tty_unregister_device(gs_tty_driver, i); + + for (i = 0; i < n_ports; i++) { + /* prevent new opens */ + mutex_lock(&ports[i].lock); + port = ports[i].port; + ports[i].port = NULL; + mutex_unlock(&ports[i].lock); + + tasklet_kill(&port->push); + + /* wait for old opens to finish */ + wait_event(port->port.close_wait, gs_closed(port)); + + WARN_ON(port->port_usb != NULL); + + kfree(port); + } + n_ports = 0; + + tty_unregister_driver(gs_tty_driver); + put_tty_driver(gs_tty_driver); + gs_tty_driver = NULL; + + pr_debug("%s: cleaned up ttyGS* support\n", __func__); +} + +/** + * gserial_connect - notify TTY I/O glue that USB link is active + * @gser: the function, set up with endpoints and descriptors + * @port_num: which port is active + * Context: any (usually from irq) + * + * This is called activate endpoints and let the TTY layer know that + * the connection is active ... not unlike "carrier detect". It won't + * necessarily start I/O queues; unless the TTY is held open by any + * task, there would be no point. However, the endpoints will be + * activated so the USB host can perform I/O, subject to basic USB + * hardware flow control. + * + * Caller needs to have set up the endpoints and USB function in @dev + * before calling this, as well as the appropriate (speed-specific) + * endpoint descriptors, and also have set up the TTY driver by calling + * @gserial_setup(). + * + * Returns negative errno or zero. + * On success, ep->driver_data will be overwritten. + */ +int gserial_connect(struct gserial *gser, u8 port_num) +{ + struct gs_port *port; + unsigned long flags; + int status; + + if (!gs_tty_driver || port_num >= n_ports) + return -ENXIO; + + /* we "know" gserial_cleanup() hasn't been called */ + port = ports[port_num].port; + + /* activate the endpoints */ + status = usb_ep_enable(gser->in); + if (status < 0) + return status; + gser->in->driver_data = port; + + status = usb_ep_enable(gser->out); + if (status < 0) + goto fail_out; + gser->out->driver_data = port; + + /* then tell the tty glue that I/O can work */ + spin_lock_irqsave(&port->port_lock, flags); + gser->ioport = port; + port->port_usb = gser; + + /* REVISIT unclear how best to handle this state... + * we don't really couple it with the Linux TTY. + */ + gser->port_line_coding = port->port_line_coding; + + /* REVISIT if waiting on "carrier detect", signal. */ + + /* if it's already open, start I/O ... and notify the serial + * protocol about open/close status (connect/disconnect). + */ + if (port->port.count) { + pr_debug("gserial_connect: start ttyGS%d\n", port->port_num); + gs_start_io(port); + if (gser->connect) + gser->connect(gser); + } else { + if (gser->disconnect) + gser->disconnect(gser); + } + + spin_unlock_irqrestore(&port->port_lock, flags); + + return status; + +fail_out: + usb_ep_disable(gser->in); + gser->in->driver_data = NULL; + return status; +} + +/** + * gserial_disconnect - notify TTY I/O glue that USB link is inactive + * @gser: the function, on which gserial_connect() was called + * Context: any (usually from irq) + * + * This is called to deactivate endpoints and let the TTY layer know + * that the connection went inactive ... not unlike "hangup". + * + * On return, the state is as if gserial_connect() had never been called; + * there is no active USB I/O on these endpoints. + */ +void gserial_disconnect(struct gserial *gser) +{ + struct gs_port *port = gser->ioport; + unsigned long flags; + + if (!port) + return; + + /* tell the TTY glue not to do I/O here any more */ + spin_lock_irqsave(&port->port_lock, flags); + + /* REVISIT as above: how best to track this? */ + port->port_line_coding = gser->port_line_coding; + + port->port_usb = NULL; + gser->ioport = NULL; + if (port->port.count > 0 || port->openclose) { + wake_up_interruptible(&port->drain_wait); + if (port->port.tty) + tty_hangup(port->port.tty); + } + spin_unlock_irqrestore(&port->port_lock, flags); + + /* disable endpoints, aborting down any active I/O */ + usb_ep_disable(gser->out); + gser->out->driver_data = NULL; + + usb_ep_disable(gser->in); + gser->in->driver_data = NULL; + + /* finally, free any unused/unusable I/O buffers */ + spin_lock_irqsave(&port->port_lock, flags); + if (port->port.count == 0 && !port->openclose) + gs_buf_free(&port->port_write_buf); + gs_free_requests(gser->out, &port->read_pool, NULL); + gs_free_requests(gser->out, &port->read_queue, NULL); + gs_free_requests(gser->in, &port->write_pool, NULL); + + port->read_allocated = port->read_started = + port->write_allocated = port->write_started = 0; + + spin_unlock_irqrestore(&port->port_lock, flags); +} diff --git a/drivers/staging/ccg/u_serial.h b/drivers/staging/ccg/u_serial.h new file mode 100644 index 0000000..9b0fe64 --- /dev/null +++ b/drivers/staging/ccg/u_serial.h @@ -0,0 +1,65 @@ +/* + * u_serial.h - interface to USB gadget "serial port"/TTY utilities + * + * Copyright (C) 2008 David Brownell + * Copyright (C) 2008 by Nokia Corporation + * + * This software is distributed under the terms of the GNU General + * Public License ("GPL") as published by the Free Software Foundation, + * either version 2 of that License or (at your option) any later version. + */ + +#ifndef __U_SERIAL_H +#define __U_SERIAL_H + +#include +#include + +/* + * One non-multiplexed "serial" I/O port ... there can be several of these + * on any given USB peripheral device, if it provides enough endpoints. + * + * The "u_serial" utility component exists to do one thing: manage TTY + * style I/O using the USB peripheral endpoints listed here, including + * hookups to sysfs and /dev for each logical "tty" device. + * + * REVISIT at least ACM could support tiocmget() if needed. + * + * REVISIT someday, allow multiplexing several TTYs over these endpoints. + */ +struct gserial { + struct usb_function func; + + /* port is managed by gserial_{connect,disconnect} */ + struct gs_port *ioport; + + struct usb_ep *in; + struct usb_ep *out; + + /* REVISIT avoid this CDC-ACM support harder ... */ + struct usb_cdc_line_coding port_line_coding; /* 9600-8-N-1 etc */ + + /* notification callbacks */ + void (*connect)(struct gserial *p); + void (*disconnect)(struct gserial *p); + int (*send_break)(struct gserial *p, int duration); +}; + +/* utilities to allocate/free request and buffer */ +struct usb_request *gs_alloc_req(struct usb_ep *ep, unsigned len, gfp_t flags); +void gs_free_req(struct usb_ep *, struct usb_request *req); + +/* port setup/teardown is handled by gadget driver */ +int gserial_setup(struct usb_gadget *g, unsigned n_ports); +void gserial_cleanup(void); + +/* connect/disconnect is handled by individual functions */ +int gserial_connect(struct gserial *, u8 port_num); +void gserial_disconnect(struct gserial *); + +/* functions are bound to configurations by a config or gadget driver */ +int acm_bind_config(struct usb_configuration *c, u8 port_num); +int gser_bind_config(struct usb_configuration *c, u8 port_num); +int obex_bind_config(struct usb_configuration *c, u8 port_num); + +#endif /* __U_SERIAL_H */ diff --git a/drivers/staging/ccg/usbstring.c b/drivers/staging/ccg/usbstring.c new file mode 100644 index 0000000..4d25b90 --- /dev/null +++ b/drivers/staging/ccg/usbstring.c @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2003 David Brownell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 2.1 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + + +/** + * usb_gadget_get_string - fill out a string descriptor + * @table: of c strings encoded using UTF-8 + * @id: string id, from low byte of wValue in get string descriptor + * @buf: at least 256 bytes, must be 16-bit aligned + * + * Finds the UTF-8 string matching the ID, and converts it into a + * string descriptor in utf16-le. + * Returns length of descriptor (always even) or negative errno + * + * If your driver needs stings in multiple languages, you'll probably + * "switch (wIndex) { ... }" in your ep0 string descriptor logic, + * using this routine after choosing which set of UTF-8 strings to use. + * Note that US-ASCII is a strict subset of UTF-8; any string bytes with + * the eighth bit set will be multibyte UTF-8 characters, not ISO-8859/1 + * characters (which are also widely used in C strings). + */ +int +usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf) +{ + struct usb_string *s; + int len; + + /* descriptor 0 has the language id */ + if (id == 0) { + buf [0] = 4; + buf [1] = USB_DT_STRING; + buf [2] = (u8) table->language; + buf [3] = (u8) (table->language >> 8); + return 4; + } + for (s = table->strings; s && s->s; s++) + if (s->id == id) + break; + + /* unrecognized: stall. */ + if (!s || !s->s) + return -EINVAL; + + /* string descriptors have length, tag, then UTF16-LE text */ + len = min ((size_t) 126, strlen (s->s)); + len = utf8s_to_utf16s(s->s, len, UTF16_LITTLE_ENDIAN, + (wchar_t *) &buf[2], 126); + if (len < 0) + return -EINVAL; + buf [0] = (len + 1) * 2; + buf [1] = USB_DT_STRING; + return buf [0]; +} + -- cgit v0.10.2 From ffe0b335062505a98d7296dae2c2a197713f87e0 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 7 Sep 2012 09:53:17 +0200 Subject: usb: gadget: remove global variable composite in composite.c This patch removes the global variable composite in composite.c. The private data which was saved there is now passed via an additional argument to the bind() function in struct usb_gadget_driver. Only the "old-style" UDC drivers have to be touched here, new style are doing it right because this change is made in udc-core. Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/staging/ccg/composite.c b/drivers/staging/ccg/composite.c index 2a345f2..228b457 100644 --- a/drivers/staging/ccg/composite.c +++ b/drivers/staging/ccg/composite.c @@ -1422,7 +1422,8 @@ static u8 override_id(struct usb_composite_dev *cdev, u8 *desc) return *desc; } -static int composite_bind(struct usb_gadget *gadget) +static int composite_bind(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { struct usb_composite_dev *cdev; int status = -ENOMEM; diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index 187d211..fc0ec5e 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -1401,7 +1401,7 @@ static int udc_wakeup(struct usb_gadget *gadget) } static int amd5536_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)); + int (*bind)(struct usb_gadget *, struct usb_gadget_driver *)); static int amd5536_stop(struct usb_gadget_driver *driver); /* gadget operations */ static const struct usb_gadget_ops udc_ops = { @@ -1914,7 +1914,7 @@ static int setup_ep0(struct udc *dev) /* Called by gadget driver to register itself */ static int amd5536_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) + int (*bind)(struct usb_gadget *, struct usb_gadget_driver *)) { struct udc *dev = udc; int retval; @@ -1932,7 +1932,7 @@ static int amd5536_start(struct usb_gadget_driver *driver, dev->driver = driver; dev->gadget.dev.driver = &driver->driver; - retval = bind(&dev->gadget); + retval = bind(&dev->gadget, driver); /* Some gadget drivers use both ep0 directions. * NOTE: to gadget driver, ep0 is just one endpoint... diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 2a345f2..0b6ee20 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -31,8 +31,6 @@ /* big enough to hold our biggest descriptor */ #define USB_BUFSIZ 1024 -static struct usb_composite_driver *composite; - /* Some systems will need runtime overrides for the product identifiers * published in the device descriptor, either numbers or strings or both. * String parameters are in UTF-8 (superset of ASCII's 7 bit characters). @@ -889,6 +887,7 @@ static int lookup_string( static int get_string(struct usb_composite_dev *cdev, void *buf, u16 language, int id) { + struct usb_composite_driver *composite = cdev->driver; struct usb_configuration *c; struct usb_function *f; int len; @@ -1359,8 +1358,8 @@ static void composite_disconnect(struct usb_gadget *gadget) spin_lock_irqsave(&cdev->lock, flags); if (cdev->config) reset_config(cdev); - if (composite->disconnect) - composite->disconnect(cdev); + if (cdev->driver->disconnect) + cdev->driver->disconnect(cdev); spin_unlock_irqrestore(&cdev->lock, flags); } @@ -1396,8 +1395,8 @@ composite_unbind(struct usb_gadget *gadget) struct usb_configuration, list); remove_config(cdev, c); } - if (composite->unbind) - composite->unbind(cdev); + if (cdev->driver->unbind) + cdev->driver->unbind(cdev); if (cdev->req) { kfree(cdev->req->buf); @@ -1406,7 +1405,6 @@ composite_unbind(struct usb_gadget *gadget) device_remove_file(&gadget->dev, &dev_attr_suspended); kfree(cdev); set_gadget_data(gadget, NULL); - composite = NULL; } static u8 override_id(struct usb_composite_dev *cdev, u8 *desc) @@ -1422,9 +1420,16 @@ static u8 override_id(struct usb_composite_dev *cdev, u8 *desc) return *desc; } -static int composite_bind(struct usb_gadget *gadget) +static struct usb_composite_driver *to_cdriver(struct usb_gadget_driver *gdrv) +{ + return container_of(gdrv, struct usb_composite_driver, gadget_driver); +} + +static int composite_bind(struct usb_gadget *gadget, + struct usb_gadget_driver *gdriver) { struct usb_composite_dev *cdev; + struct usb_composite_driver *composite = to_cdriver(gdriver); int status = -ENOMEM; cdev = kzalloc(sizeof *cdev, GFP_KERNEL); @@ -1546,8 +1551,8 @@ composite_suspend(struct usb_gadget *gadget) f->suspend(f); } } - if (composite->suspend) - composite->suspend(cdev); + if (cdev->driver->suspend) + cdev->driver->suspend(cdev); cdev->suspended = 1; @@ -1565,8 +1570,8 @@ composite_resume(struct usb_gadget *gadget) * suspend/resume callbacks? */ DBG(cdev, "resume\n"); - if (composite->resume) - composite->resume(cdev); + if (cdev->driver->resume) + cdev->driver->resume(cdev); if (cdev->config) { list_for_each_entry(f, &cdev->config->functions, list) { if (f->resume) @@ -1584,7 +1589,7 @@ composite_resume(struct usb_gadget *gadget) /*-------------------------------------------------------------------------*/ -static struct usb_gadget_driver composite_driver = { +static const struct usb_gadget_driver composite_driver_template = { .bind = composite_bind, .unbind = composite_unbind, @@ -1620,19 +1625,24 @@ static struct usb_gadget_driver composite_driver = { */ int usb_composite_probe(struct usb_composite_driver *driver) { - if (!driver || !driver->dev || composite || !driver->bind) + struct usb_gadget_driver *gadget_driver; + + if (!driver || !driver->dev || !driver->bind) return -EINVAL; if (!driver->name) driver->name = "composite"; if (!driver->iProduct) driver->iProduct = driver->name; - composite_driver.function = (char *) driver->name; - composite_driver.driver.name = driver->name; - composite_driver.max_speed = driver->max_speed; - composite = driver; - return usb_gadget_probe_driver(&composite_driver); + driver->gadget_driver = composite_driver_template; + gadget_driver = &driver->gadget_driver; + + gadget_driver->function = (char *) driver->name; + gadget_driver->driver.name = driver->name; + gadget_driver->max_speed = driver->max_speed; + + return usb_gadget_probe_driver(gadget_driver); } /** @@ -1644,9 +1654,7 @@ int usb_composite_probe(struct usb_composite_driver *driver) */ void usb_composite_unregister(struct usb_composite_driver *driver) { - if (composite != driver) - return; - usb_gadget_unregister_driver(&composite_driver); + usb_gadget_unregister_driver(&driver->gadget_driver); } /** diff --git a/drivers/usb/gadget/dbgp.c b/drivers/usb/gadget/dbgp.c index df9a010..cc17465 100644 --- a/drivers/usb/gadget/dbgp.c +++ b/drivers/usb/gadget/dbgp.c @@ -292,7 +292,8 @@ fail_1: return -ENODEV; } -static int __init dbgp_bind(struct usb_gadget *gadget) +static int __init dbgp_bind(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { int err, stp; diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index ce186fa..cdacae7 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -3331,7 +3331,8 @@ static int __init check_parameters(struct fsg_dev *fsg) } -static int __init fsg_bind(struct usb_gadget *gadget) +static int __init fsg_bind(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { struct fsg_dev *fsg = the_fsg; int rc; diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index 3def828..6ae70cb 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c @@ -1255,7 +1255,7 @@ static int fsl_pullup(struct usb_gadget *gadget, int is_on) } static int fsl_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)); + int (*bind)(struct usb_gadget *, struct usb_gadget_driver *)); static int fsl_stop(struct usb_gadget_driver *driver); /* defined in gadget.h */ static struct usb_gadget_ops fsl_gadget_ops = { @@ -1951,7 +1951,7 @@ static irqreturn_t fsl_udc_irq(int irq, void *_udc) * Called by initialization code of gadget drivers *----------------------------------------------------------------*/ static int fsl_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) + int (*bind)(struct usb_gadget *, struct usb_gadget_driver *)) { int retval = -ENODEV; unsigned long flags = 0; @@ -1976,7 +1976,7 @@ static int fsl_start(struct usb_gadget_driver *driver, spin_unlock_irqrestore(&udc_controller->lock, flags); /* bind udc driver to gadget driver */ - retval = bind(&udc_controller->gadget); + retval = bind(&udc_controller->gadget, driver); if (retval) { VDBG("bind to %s --> %d", driver->driver.name, retval); udc_controller->gadget.dev.driver = NULL; diff --git a/drivers/usb/gadget/fusb300_udc.c b/drivers/usb/gadget/fusb300_udc.c index cdd9454..72cd5e6 100644 --- a/drivers/usb/gadget/fusb300_udc.c +++ b/drivers/usb/gadget/fusb300_udc.c @@ -1311,7 +1311,7 @@ static void init_controller(struct fusb300 *fusb300) static struct fusb300 *the_controller; static int fusb300_udc_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) + int (*bind)(struct usb_gadget *, struct usb_gadget_driver *)) { struct fusb300 *fusb300 = the_controller; int retval; @@ -1339,7 +1339,7 @@ static int fusb300_udc_start(struct usb_gadget_driver *driver, goto error; } - retval = bind(&fusb300->gadget); + retval = bind(&fusb300->gadget, driver); if (retval) { pr_err("bind to driver error (%d)\n", retval); device_del(&fusb300->gadget.dev); diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 9fd7886..51037cb 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -994,7 +994,7 @@ static int goku_get_frame(struct usb_gadget *_gadget) } static int goku_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)); + int (*bind)(struct usb_gadget *, struct usb_gadget_driver *)); static int goku_stop(struct usb_gadget_driver *driver); static const struct usb_gadget_ops goku_ops = { @@ -1348,7 +1348,7 @@ static struct goku_udc *the_controller; * the driver might get unbound. */ static int goku_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) + int (*bind)(struct usb_gadget *, struct usb_gadget_driver *)) { struct goku_udc *dev = the_controller; int retval; @@ -1368,7 +1368,7 @@ static int goku_start(struct usb_gadget_driver *driver, driver->driver.bus = NULL; dev->driver = driver; dev->gadget.dev.driver = &driver->driver; - retval = bind(&dev->gadget); + retval = bind(&dev->gadget, driver); if (retval) { DBG(dev, "bind to driver %s --> error %d\n", driver->driver.name, retval); diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 2521804..4bb6d53 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -1679,8 +1679,8 @@ gadgetfs_unbind (struct usb_gadget *gadget) static struct dev_data *the_device; -static int -gadgetfs_bind (struct usb_gadget *gadget) +static int gadgetfs_bind(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { struct dev_data *dev = the_device; @@ -1773,7 +1773,8 @@ static struct usb_gadget_driver gadgetfs_driver = { static void gadgetfs_nop(struct usb_gadget *arg) { } -static int gadgetfs_probe (struct usb_gadget *gadget) +static int gadgetfs_probe(struct usb_gadget *gadget, + struct usb_gadget_driver *driver) { CHIP = gadget->name; return -EISNAM; diff --git a/drivers/usb/gadget/m66592-udc.c b/drivers/usb/gadget/m66592-udc.c index cf6bd62..b6401f1 100644 --- a/drivers/usb/gadget/m66592-udc.c +++ b/drivers/usb/gadget/m66592-udc.c @@ -1466,7 +1466,7 @@ static struct usb_ep_ops m66592_ep_ops = { static struct m66592 *the_controller; static int m66592_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) + int (*bind)(struct usb_gadget *, struct usb_gadget_driver *)) { struct m66592 *m66592 = the_controller; int retval; @@ -1492,7 +1492,7 @@ static int m66592_start(struct usb_gadget_driver *driver, goto error; } - retval = bind(&m66592->gadget); + retval = bind(&m66592->gadget, driver); if (retval) { pr_err("bind to driver error (%d)\n", retval); device_del(&m66592->gadget.dev); diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index ad91de4..ea45224 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c @@ -1269,7 +1269,7 @@ static int mv_udc_pullup(struct usb_gadget *gadget, int is_on) } static int mv_udc_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)); + int (*bind)(struct usb_gadget *, struct usb_gadget_driver *)); static int mv_udc_stop(struct usb_gadget_driver *driver); /* device controller usb_gadget_ops structure */ static const struct usb_gadget_ops mv_ops = { @@ -1374,7 +1374,7 @@ static void stop_activity(struct mv_udc *udc, struct usb_gadget_driver *driver) } static int mv_udc_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) + int (*bind)(struct usb_gadget *, struct usb_gadget_driver *)) { struct mv_udc *udc = the_controller; int retval = 0; @@ -1399,7 +1399,7 @@ static int mv_udc_start(struct usb_gadget_driver *driver, spin_unlock_irqrestore(&udc->lock, flags); - retval = bind(&udc->gadget); + retval = bind(&udc->gadget, driver); if (retval) { dev_err(&udc->dev->dev, "bind to driver %s --> %d\n", driver->driver.name, retval); diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index f9132ad..2a4749c 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c @@ -1308,7 +1308,7 @@ static int omap_pullup(struct usb_gadget *gadget, int is_on) } static int omap_udc_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)); + int (*bind)(struct usb_gadget *, struct usb_gadget_driver *)); static int omap_udc_stop(struct usb_gadget_driver *driver); static struct usb_gadget_ops omap_gadget_ops = { @@ -2040,7 +2040,7 @@ static inline int machine_without_vbus_sense(void) } static int omap_udc_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) + int (*bind)(struct usb_gadget *, struct usb_gadget_driver *)) { int status = -ENODEV; struct omap_ep *ep; @@ -2082,7 +2082,7 @@ static int omap_udc_start(struct usb_gadget_driver *driver, if (udc->dc_clk != NULL) omap_udc_enable_clock(1); - status = bind(&udc->gadget); + status = bind(&udc->gadget, driver); if (status) { DBG("bind to %s --> %d\n", driver->driver.name, status); udc->gadget.dev.driver = NULL; diff --git a/drivers/usb/gadget/pch_udc.c b/drivers/usb/gadget/pch_udc.c index f4fb71c..6490c00 100644 --- a/drivers/usb/gadget/pch_udc.c +++ b/drivers/usb/gadget/pch_udc.c @@ -1236,7 +1236,7 @@ static int pch_udc_pcd_vbus_draw(struct usb_gadget *gadget, unsigned int mA) } static int pch_udc_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)); + int (*bind)(struct usb_gadget *, struct usb_gadget_driver *)); static int pch_udc_stop(struct usb_gadget_driver *driver); static const struct usb_gadget_ops pch_udc_ops = { .get_frame = pch_udc_pcd_get_frame, @@ -2982,7 +2982,7 @@ static int init_dma_pools(struct pch_udc_dev *dev) } static int pch_udc_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) + int (*bind)(struct usb_gadget *, struct usb_gadget_driver *)) { struct pch_udc_dev *dev = pch_udc; int retval; @@ -3006,7 +3006,7 @@ static int pch_udc_start(struct usb_gadget_driver *driver, dev->gadget.dev.driver = &driver->driver; /* Invoke the bind routine of the gadget driver */ - retval = bind(&dev->gadget); + retval = bind(&dev->gadget, driver); if (retval) { dev_err(&dev->pdev->dev, "%s: binding to %s returning %d\n", diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index c246c08..8efbf08 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -999,7 +999,7 @@ static int pxa25x_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA) } static int pxa25x_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)); + int (*bind)(struct usb_gadget *, struct usb_gadget_driver *)); static int pxa25x_stop(struct usb_gadget_driver *driver); static const struct usb_gadget_ops pxa25x_udc_ops = { @@ -1257,7 +1257,7 @@ static void udc_enable (struct pxa25x_udc *dev) * the driver might get unbound. */ static int pxa25x_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) + int (*bind)(struct usb_gadget *, struct usb_gadget_driver *)) { struct pxa25x_udc *dev = the_controller; int retval; @@ -1285,7 +1285,7 @@ fail: dev->gadget.dev.driver = NULL; return retval; } - retval = bind(&dev->gadget); + retval = bind(&dev->gadget, driver); if (retval) { DMSG("bind to driver %s --> error %d\n", driver->driver.name, retval); diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 644b430..979ddad 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -1672,7 +1672,7 @@ static int pxa_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA) } static int pxa27x_udc_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)); + int (*bind)(struct usb_gadget *, struct usb_gadget_driver *)); static int pxa27x_udc_stop(struct usb_gadget_driver *driver); static const struct usb_gadget_ops pxa_udc_ops = { @@ -1803,7 +1803,7 @@ static void udc_enable(struct pxa_udc *udc) * Returns 0 if no error, -EINVAL, -ENODEV, -EBUSY otherwise */ static int pxa27x_udc_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) + int (*bind)(struct usb_gadget *, struct usb_gadget_driver *)) { struct pxa_udc *udc = the_controller; int retval; @@ -1826,7 +1826,7 @@ static int pxa27x_udc_start(struct usb_gadget_driver *driver, dev_err(udc->dev, "device_add error %d\n", retval); goto add_fail; } - retval = bind(&udc->gadget); + retval = bind(&udc->gadget, driver); if (retval) { dev_err(udc->dev, "bind to driver %s --> error %d\n", driver->driver.name, retval); diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index b627c9b..c33e942 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -1539,7 +1539,7 @@ static int s3c2410_vbus_draw(struct usb_gadget *_gadget, unsigned ma) } static int s3c2410_udc_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)); + int (*bind)(struct usb_gadget *, struct usb_gadget_driver *)); static int s3c2410_udc_stop(struct usb_gadget_driver *driver); static const struct usb_gadget_ops s3c2410_ops = { @@ -1665,7 +1665,7 @@ static void s3c2410_udc_enable(struct s3c2410_udc *dev) } static int s3c2410_udc_start(struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) + int (*bind)(struct usb_gadget *, struct usb_gadget_driver *)) { struct s3c2410_udc *udc = the_controller; int retval; @@ -1705,7 +1705,7 @@ static int s3c2410_udc_start(struct usb_gadget_driver *driver, dprintk(DEBUG_NORMAL, "binding gadget driver '%s'\n", driver->driver.name); - retval = bind(&udc->gadget); + retval = bind(&udc->gadget, driver); if (retval) { device_del(&udc->gadget.dev); goto register_error; diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 85e1e2f..f3cd969 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c @@ -118,7 +118,7 @@ EXPORT_SYMBOL_GPL(usb_gadget_unmap_request); */ static inline int usb_gadget_start(struct usb_gadget *gadget, struct usb_gadget_driver *driver, - int (*bind)(struct usb_gadget *)) + int (*bind)(struct usb_gadget *, struct usb_gadget_driver *)) { return gadget->ops->start(driver, bind); } @@ -338,7 +338,7 @@ found: udc->dev.driver = &driver->driver; if (udc_is_newstyle(udc)) { - ret = driver->bind(udc->gadget); + ret = driver->bind(udc->gadget, driver); if (ret) goto err1; ret = usb_gadget_udc_start(udc->gadget, driver); diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 19a5adf..43d6b9c 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -303,6 +303,7 @@ struct usb_composite_driver { /* global suspend hooks */ void (*suspend)(struct usb_composite_dev *); void (*resume)(struct usb_composite_dev *); + struct usb_gadget_driver gadget_driver; }; extern int usb_composite_probe(struct usb_composite_driver *driver); diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 9eb4e71..822c1b8 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -474,7 +474,8 @@ struct usb_gadget_ops { /* Those two are deprecated */ int (*start)(struct usb_gadget_driver *, - int (*bind)(struct usb_gadget *)); + int (*bind)(struct usb_gadget *, + struct usb_gadget_driver *driver)); int (*stop)(struct usb_gadget_driver *); }; @@ -821,7 +822,8 @@ static inline int usb_gadget_disconnect(struct usb_gadget *gadget) struct usb_gadget_driver { char *function; enum usb_device_speed max_speed; - int (*bind)(struct usb_gadget *gadget); + int (*bind)(struct usb_gadget *gadget, + struct usb_gadget_driver *driver); void (*unbind)(struct usb_gadget *); int (*setup)(struct usb_gadget *, const struct usb_ctrlrequest *); -- cgit v0.10.2 From 4001a7a163d8e49eb9baf294527ad2ed50202e22 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 6 Sep 2012 20:11:08 +0200 Subject: usb: gadget: pxa25x: make it compile with debug again |drivers/usb/gadget/pxa25x_udc.h: In function 'dump_state': |drivers/usb/gadget/pxa25x_udc.h:228:20: error: invalid type argument of '->' (have 'struct usb_ep') Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/pxa25x_udc.h b/drivers/usb/gadget/pxa25x_udc.h index 861f4df..2eca1e7 100644 --- a/drivers/usb/gadget/pxa25x_udc.h +++ b/drivers/usb/gadget/pxa25x_udc.h @@ -225,7 +225,7 @@ dump_state(struct pxa25x_udc *dev) dev->stats.read.bytes, dev->stats.read.ops); for (i = 1; i < PXA_UDC_NUM_ENDPOINTS; i++) { - if (dev->ep [i].desc == NULL) + if (dev->ep[i].ep.desc == NULL) continue; DMSG ("udccs%d = %02x\n", i, *dev->ep->reg_udccs); } -- cgit v0.10.2 From a84d9e5361bcfbff1c84481bd9c04fc58a56d83b Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 6 Sep 2012 20:11:09 +0200 Subject: usb: gadget: start with libcomposite This patch aims to be simple. It removes #include usbstribgs.c line from each gadget and creates libcomposite.ko which has only one member, that is usbstribgs.c. Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 75b76d5..a53be32 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -494,6 +494,12 @@ endmenu # # USB Gadget Drivers # + +# composite based drivers +config USB_LIBCOMPOSITE + tristate + depends on USB_GADGET + choice tristate "USB Gadget Drivers" default USB_ETH @@ -517,6 +523,7 @@ choice config USB_ZERO tristate "Gadget Zero (DEVELOPMENT)" + select USB_LIBCOMPOSITE help Gadget Zero is a two-configuration device. It either sinks and sources bulk data; or it loops back a configurable number of @@ -552,6 +559,7 @@ config USB_ZERO_HNPTEST config USB_AUDIO tristate "Audio Gadget (EXPERIMENTAL)" depends on SND + select USB_LIBCOMPOSITE select SND_PCM help This Gadget Audio driver is compatible with USB Audio Class @@ -580,6 +588,7 @@ config GADGET_UAC1 config USB_ETH tristate "Ethernet Gadget (with CDC Ethernet support)" depends on NET + select USB_LIBCOMPOSITE select CRC32 help This driver implements Ethernet style communication, in one of @@ -615,6 +624,7 @@ config USB_ETH config USB_ETH_RNDIS bool "RNDIS support" depends on USB_ETH + select USB_LIBCOMPOSITE default y help Microsoft Windows XP bundles the "Remote NDIS" (RNDIS) protocol, @@ -633,6 +643,7 @@ config USB_ETH_RNDIS config USB_ETH_EEM bool "Ethernet Emulation Model (EEM) support" depends on USB_ETH + select USB_LIBCOMPOSITE default n help CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM @@ -649,6 +660,7 @@ config USB_ETH_EEM config USB_G_NCM tristate "Network Control Model (NCM) support" depends on NET + select USB_LIBCOMPOSITE select CRC32 help This driver implements USB CDC NCM subclass standard. NCM is @@ -678,6 +690,7 @@ config USB_GADGETFS config USB_FUNCTIONFS tristate "Function Filesystem (EXPERIMENTAL)" depends on EXPERIMENTAL + select USB_LIBCOMPOSITE select USB_FUNCTIONFS_GENERIC if !(USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS) help The Function Filesystem (FunctionFS) lets one create USB @@ -741,6 +754,7 @@ config USB_FILE_STORAGE_TEST config USB_MASS_STORAGE tristate "Mass Storage Gadget" depends on BLOCK + select USB_LIBCOMPOSITE help The Mass Storage Gadget acts as a USB Mass Storage disk drive. As its storage repository it can use a regular file or a block @@ -756,6 +770,7 @@ config USB_MASS_STORAGE config USB_GADGET_TARGET tristate "USB Gadget Target Fabric Module" depends on TARGET_CORE + select USB_LIBCOMPOSITE help This fabric is an USB gadget. Two USB protocols are supported that is BBB or BOT (Bulk Only Transport) and UAS (USB Attached SCSI). BOT is @@ -765,6 +780,7 @@ config USB_GADGET_TARGET config USB_G_SERIAL tristate "Serial Gadget (with CDC ACM and CDC OBEX support)" + select USB_LIBCOMPOSITE help The Serial Gadget talks to the Linux-USB generic serial driver. This driver supports a CDC-ACM module option, which can be used @@ -785,6 +801,7 @@ config USB_G_SERIAL config USB_MIDI_GADGET tristate "MIDI Gadget (EXPERIMENTAL)" depends on SND && EXPERIMENTAL + select USB_LIBCOMPOSITE select SND_RAWMIDI help The MIDI Gadget acts as a USB Audio device, with one MIDI @@ -798,6 +815,7 @@ config USB_MIDI_GADGET config USB_G_PRINTER tristate "Printer Gadget" + select USB_LIBCOMPOSITE help The Printer Gadget channels data between the USB host and a userspace program driving the print engine. The user space @@ -814,6 +832,7 @@ config USB_G_PRINTER config USB_CDC_COMPOSITE tristate "CDC Composite Device (Ethernet and ACM)" depends on NET + select USB_LIBCOMPOSITE help This driver provides two functions in one configuration: a CDC Ethernet (ECM) link, and a CDC ACM (serial port) link. @@ -828,6 +847,7 @@ config USB_CDC_COMPOSITE config USB_G_NOKIA tristate "Nokia composite gadget" depends on PHONET + select USB_LIBCOMPOSITE help The Nokia composite gadget provides support for acm, obex and phonet in only one composite gadget driver. @@ -838,6 +858,7 @@ config USB_G_NOKIA config USB_G_ACM_MS tristate "CDC Composite Device (ACM and mass storage)" depends on BLOCK + select USB_LIBCOMPOSITE help This driver provides two functions in one configuration: a mass storage, and a CDC ACM (serial port) link. @@ -849,6 +870,7 @@ config USB_G_MULTI tristate "Multifunction Composite Gadget (EXPERIMENTAL)" depends on BLOCK && NET select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS + select USB_LIBCOMPOSITE help The Multifunction Composite Gadget provides Ethernet (RNDIS and/or CDC Ethernet), mass storage and ACM serial link @@ -889,6 +911,7 @@ config USB_G_MULTI_CDC config USB_G_HID tristate "HID Gadget" + select USB_LIBCOMPOSITE help The HID gadget driver provides generic emulation of USB Human Interface Devices (HID). @@ -899,8 +922,10 @@ config USB_G_HID Say "y" to link the driver statically, or "m" to build a dynamically linked module called "g_hid". +# Standalone / single function gadgets config USB_G_DBGP tristate "EHCI Debug Device Gadget" + select USB_LIBCOMPOSITE help This gadget emulates an EHCI Debug device. This is useful when you want to interact with an EHCI Debug Port. diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index d84f923..eadbc86 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -4,6 +4,8 @@ ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG obj-$(CONFIG_USB_GADGET) += udc-core.o +obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o +libcomposite-y := usbstring.o obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o obj-$(CONFIG_USB_NET2272) += net2272.o obj-$(CONFIG_USB_NET2280) += net2280.o diff --git a/drivers/usb/gadget/acm_ms.c b/drivers/usb/gadget/acm_ms.c index 65a2f3c..9820960 100644 --- a/drivers/usb/gadget/acm_ms.c +++ b/drivers/usb/gadget/acm_ms.c @@ -42,7 +42,6 @@ */ #include "composite.c" -#include "usbstring.c" #include "config.c" #include "epautoconf.c" #include "u_serial.c" diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index dd339bc..76e54b4 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c @@ -27,7 +27,6 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" -#include "usbstring.c" #include "config.c" #include "epautoconf.c" diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index b7d984b..74a9c7f 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c @@ -44,7 +44,6 @@ */ #include "composite.c" -#include "usbstring.c" #include "config.c" #include "epautoconf.c" #include "u_serial.c" diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 4580ec0..e16094e 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -103,7 +103,6 @@ static inline bool has_rndis(void) * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" -#include "usbstring.c" #include "config.c" #include "epautoconf.c" diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index cdacae7..8d0166b 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -265,7 +265,6 @@ * the runtime footprint, and giving us at least some parts of what * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ -#include "usbstring.c" #include "config.c" #include "epautoconf.c" diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index da9809f..407b5cc 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -24,7 +24,6 @@ */ #include "composite.c" -#include "usbstring.c" #include "config.c" #include "epautoconf.c" diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 1e3cd37..135b390 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -38,7 +38,6 @@ #include "gadget_chips.h" #include "composite.c" -#include "usbstring.c" #include "config.c" #include "epautoconf.c" #include "f_midi.c" diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c index 8502e56..effda2e 100644 --- a/drivers/usb/gadget/hid.c +++ b/drivers/usb/gadget/hid.c @@ -35,7 +35,6 @@ */ #include "composite.c" -#include "usbstring.c" #include "config.c" #include "epautoconf.c" diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c index 480edbc..a7f32c3 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c @@ -49,7 +49,6 @@ */ #include "composite.c" -#include "usbstring.c" #include "config.c" #include "epautoconf.c" #include "f_mass_storage.c" diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index 13db7cc..71c1fab 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -44,7 +44,6 @@ MODULE_LICENSE("GPL"); */ #include "composite.c" -#include "usbstring.c" #include "config.c" #include "epautoconf.c" diff --git a/drivers/usb/gadget/ncm.c b/drivers/usb/gadget/ncm.c index 9a20057..d7e6b1e 100644 --- a/drivers/usb/gadget/ncm.c +++ b/drivers/usb/gadget/ncm.c @@ -37,7 +37,6 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" -#include "usbstring.c" #include "config.c" #include "epautoconf.c" diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index a5b5e71..474c77c 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c @@ -39,7 +39,6 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" -#include "usbstring.c" #include "config.c" #include "epautoconf.c" diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 33c0c07..c55e7d9 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -52,7 +52,6 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" -#include "usbstring.c" #include "config.c" #include "epautoconf.c" diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index ea3f8e9..88baa9e 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -38,7 +38,6 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" -#include "usbstring.c" #include "config.c" #include "epautoconf.c" diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c index 35ca09a..327af68 100644 --- a/drivers/usb/gadget/tcm_usb_gadget.c +++ b/drivers/usb/gadget/tcm_usb_gadget.c @@ -25,7 +25,6 @@ #include #include -#include "usbstring.c" #include "epautoconf.c" #include "config.c" #include "composite.c" diff --git a/drivers/usb/gadget/usbstring.c b/drivers/usb/gadget/usbstring.c index 4d25b90..24e9bbd 100644 --- a/drivers/usb/gadget/usbstring.c +++ b/drivers/usb/gadget/usbstring.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -68,4 +69,5 @@ usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf) buf [1] = USB_DT_STRING; return buf [0]; } - +EXPORT_SYMBOL_GPL(usb_gadget_get_string); +MODULE_LICENSE("GPL"); diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c index 2a617c3..dc8fd5c 100644 --- a/drivers/usb/gadget/webcam.c +++ b/drivers/usb/gadget/webcam.c @@ -24,7 +24,6 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" -#include "usbstring.c" #include "config.c" #include "epautoconf.c" diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 90df613..4469be8 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -59,7 +59,6 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" -#include "usbstring.c" #include "config.c" #include "epautoconf.c" -- cgit v0.10.2 From 0ba16dea72a457bf65fc06ef60165c994e2f7420 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 6 Sep 2012 20:11:10 +0200 Subject: usb: gadget: libcomposite: move config.c into libcomposite This patch moves config.c into libcomposite and updates all gadgets. Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index eadbc86..9515ed0 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -5,7 +5,7 @@ ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG obj-$(CONFIG_USB_GADGET) += udc-core.o obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o -libcomposite-y := usbstring.o +libcomposite-y := usbstring.o config.o obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o obj-$(CONFIG_USB_NET2272) += net2272.o obj-$(CONFIG_USB_NET2280) += net2280.o diff --git a/drivers/usb/gadget/acm_ms.c b/drivers/usb/gadget/acm_ms.c index 9820960..3078d79 100644 --- a/drivers/usb/gadget/acm_ms.c +++ b/drivers/usb/gadget/acm_ms.c @@ -42,7 +42,6 @@ */ #include "composite.c" -#include "config.c" #include "epautoconf.c" #include "u_serial.c" #include "f_acm.c" diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index 76e54b4..9e85df2 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c @@ -27,7 +27,6 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" -#include "config.c" #include "epautoconf.c" /* string IDs are assigned dynamically */ diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index 74a9c7f..d06d079 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c @@ -44,7 +44,6 @@ */ #include "composite.c" -#include "config.c" #include "epautoconf.c" #include "u_serial.c" #include "f_acm.c" diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c index 7542a72..e3a9892 100644 --- a/drivers/usb/gadget/config.c +++ b/drivers/usb/gadget/config.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -53,7 +54,7 @@ usb_descriptor_fillbuf(void *buf, unsigned buflen, } return dest - (u8 *)buf; } - +EXPORT_SYMBOL_GPL(usb_descriptor_fillbuf); /** * usb_gadget_config_buf - builts a complete configuration descriptor @@ -106,6 +107,7 @@ int usb_gadget_config_buf( cp->bmAttributes |= USB_CONFIG_ATT_ONE; return len; } +EXPORT_SYMBOL_GPL(usb_gadget_config_buf); /** * usb_copy_descriptors - copy a vector of USB descriptors @@ -155,4 +157,4 @@ usb_copy_descriptors(struct usb_descriptor_header **src) return ret; } - +EXPORT_SYMBOL_GPL(usb_copy_descriptors); diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index e16094e..557021e 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -103,7 +103,6 @@ static inline bool has_rndis(void) * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" -#include "config.c" #include "epautoconf.c" #include "f_ecm.c" diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 8d0166b..77cf108 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -265,7 +265,6 @@ * the runtime footprint, and giving us at least some parts of what * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ -#include "config.c" #include "epautoconf.c" /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 407b5cc..2409570 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -24,7 +24,6 @@ */ #include "composite.c" -#include "config.c" #include "epautoconf.c" #if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 135b390..68a79b4 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -38,7 +38,6 @@ #include "gadget_chips.h" #include "composite.c" -#include "config.c" #include "epautoconf.c" #include "f_midi.c" diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c index effda2e..917c6ed 100644 --- a/drivers/usb/gadget/hid.c +++ b/drivers/usb/gadget/hid.c @@ -35,7 +35,6 @@ */ #include "composite.c" -#include "config.c" #include "epautoconf.c" #include "f_hid.c" diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c index a7f32c3..9675e61 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c @@ -49,7 +49,6 @@ */ #include "composite.c" -#include "config.c" #include "epautoconf.c" #include "f_mass_storage.c" diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index 71c1fab..6b6c128 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -44,7 +44,6 @@ MODULE_LICENSE("GPL"); */ #include "composite.c" -#include "config.c" #include "epautoconf.c" #include "f_mass_storage.c" diff --git a/drivers/usb/gadget/ncm.c b/drivers/usb/gadget/ncm.c index d7e6b1e..ce8d08e 100644 --- a/drivers/usb/gadget/ncm.c +++ b/drivers/usb/gadget/ncm.c @@ -37,7 +37,6 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" -#include "config.c" #include "epautoconf.c" #include "f_ncm.c" diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index 474c77c..e2f4b9b 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c @@ -39,7 +39,6 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" -#include "config.c" #include "epautoconf.c" #include "u_serial.c" diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index c55e7d9..310b22d 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -52,7 +52,6 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" -#include "config.c" #include "epautoconf.c" /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 88baa9e..39990be 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -38,7 +38,6 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" -#include "config.c" #include "epautoconf.c" #include "f_acm.c" diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c index 327af68..926e0fa 100644 --- a/drivers/usb/gadget/tcm_usb_gadget.c +++ b/drivers/usb/gadget/tcm_usb_gadget.c @@ -26,7 +26,6 @@ #include #include "epautoconf.c" -#include "config.c" #include "composite.c" #include "tcm_usb_gadget.h" diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c index dc8fd5c..5e500e8 100644 --- a/drivers/usb/gadget/webcam.c +++ b/drivers/usb/gadget/webcam.c @@ -24,7 +24,6 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" -#include "config.c" #include "epautoconf.c" #include "uvc_queue.c" diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 4469be8..e39a3b5 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -59,7 +59,6 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" -#include "config.c" #include "epautoconf.c" #include "f_sourcesink.c" -- cgit v0.10.2 From e87bb7118c4f752de4616a7ab56c51ed3e7f6f53 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 6 Sep 2012 20:11:11 +0200 Subject: usb: gadget: move global vars from epautoconf into struct usb_gadget epautoconf has two global variables which count the endpoint number of last assigned endpoint. This patch removes the global variable and keeps it as per (UDC) gadget. While here, the ifdef is removed and now the in and outpoint are enumerated unconditionally. The dwc3 for instance supports 32 endpoints in total. Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index 51f3d42..d5a905d 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -22,17 +22,6 @@ #include "gadget_chips.h" - -/* we must assign addresses for configurable endpoints (like net2280) */ -static unsigned epnum; - -// #define MANY_ENDPOINTS -#ifdef MANY_ENDPOINTS -/* more than 15 configurable endpoints */ -static unsigned in_epnum; -#endif - - /* * This should work with endpoints from controller drivers sharing the * same endpoint naming convention. By example: @@ -176,16 +165,14 @@ ep_matches ( if (isdigit (ep->name [2])) { u8 num = simple_strtoul (&ep->name [2], NULL, 10); desc->bEndpointAddress |= num; -#ifdef MANY_ENDPOINTS } else if (desc->bEndpointAddress & USB_DIR_IN) { - if (++in_epnum > 15) + if (++gadget->in_epnum > 15) return 0; - desc->bEndpointAddress = USB_DIR_IN | in_epnum; -#endif + desc->bEndpointAddress = USB_DIR_IN | gadget->in_epnum; } else { - if (++epnum > 15) + if (++gadget->out_epnum > 15) return 0; - desc->bEndpointAddress |= epnum; + desc->bEndpointAddress |= gadget->out_epnum; } /* report (variable) full speed bulk maxpacket */ @@ -385,9 +372,7 @@ void usb_ep_autoconfig_reset (struct usb_gadget *gadget) list_for_each_entry (ep, &gadget->ep_list, ep_list) { ep->driver_data = NULL; } -#ifdef MANY_ENDPOINTS - in_epnum = 0; -#endif - epnum = 0; + gadget->in_epnum = 0; + gadget->out_epnum = 0; } diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h index 822c1b8..5b6e508 100644 --- a/include/linux/usb/gadget.h +++ b/include/linux/usb/gadget.h @@ -503,6 +503,8 @@ struct usb_gadget_ops { * @name: Identifies the controller hardware type. Used in diagnostics * and sometimes configuration. * @dev: Driver model state for this abstract device. + * @out_epnum: last used out ep number + * @in_epnum: last used in ep number * * Gadgets have a mostly-portable "gadget driver" implementing device * functions, handling all usb configurations and interfaces. Gadget @@ -537,6 +539,8 @@ struct usb_gadget { unsigned a_alt_hnp_support:1; const char *name; struct device dev; + unsigned out_epnum; + unsigned in_epnum; }; static inline void set_gadget_data(struct usb_gadget *gadget, void *data) -- cgit v0.10.2 From dc995fc27c2e1c8edebfb2405ede23bd38153f7f Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 6 Sep 2012 20:11:12 +0200 Subject: usb: gadget: libcomposite: add epautoconf.c to libcomposite This patch adds epautoconf.c into libcomposite and updates all gadgets. Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 9515ed0..23d705f 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -5,7 +5,7 @@ ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG obj-$(CONFIG_USB_GADGET) += udc-core.o obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o -libcomposite-y := usbstring.o config.o +libcomposite-y := usbstring.o config.o epautoconf.o obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o obj-$(CONFIG_USB_NET2272) += net2272.o obj-$(CONFIG_USB_NET2280) += net2280.o diff --git a/drivers/usb/gadget/acm_ms.c b/drivers/usb/gadget/acm_ms.c index 3078d79..5db661d 100644 --- a/drivers/usb/gadget/acm_ms.c +++ b/drivers/usb/gadget/acm_ms.c @@ -42,7 +42,6 @@ */ #include "composite.c" -#include "epautoconf.c" #include "u_serial.c" #include "f_acm.c" #include "f_mass_storage.c" diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index 9e85df2..689d142 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c @@ -14,6 +14,7 @@ #include #include +#include "gadget_chips.h" #define DRIVER_DESC "Linux USB Audio Gadget" #define DRIVER_VERSION "Feb 2, 2012" @@ -27,7 +28,6 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" -#include "epautoconf.c" /* string IDs are assigned dynamically */ diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index d06d079..8e386cf 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c @@ -44,7 +44,6 @@ */ #include "composite.c" -#include "epautoconf.c" #include "u_serial.c" #include "f_acm.c" #include "f_ecm.c" diff --git a/drivers/usb/gadget/dbgp.c b/drivers/usb/gadget/dbgp.c index cc17465..87d1650 100644 --- a/drivers/usb/gadget/dbgp.c +++ b/drivers/usb/gadget/dbgp.c @@ -13,9 +13,6 @@ #include #include -/* See comments in "zero.c" */ -#include "epautoconf.c" - #ifdef CONFIG_USB_G_DBGP_SERIAL #include "u_serial.c" #endif diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index d5a905d..a777f7b 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -10,6 +10,7 @@ */ #include +#include #include #include #include @@ -315,6 +316,7 @@ found_ep: ep->comp_desc = NULL; return ep; } +EXPORT_SYMBOL_GPL(usb_ep_autoconfig_ss); /** * usb_ep_autoconfig() - choose an endpoint matching the @@ -354,7 +356,7 @@ struct usb_ep *usb_ep_autoconfig( { return usb_ep_autoconfig_ss(gadget, desc, NULL); } - +EXPORT_SYMBOL_GPL(usb_ep_autoconfig); /** * usb_ep_autoconfig_reset - reset endpoint autoconfig state @@ -375,4 +377,4 @@ void usb_ep_autoconfig_reset (struct usb_gadget *gadget) gadget->in_epnum = 0; gadget->out_epnum = 0; } - +EXPORT_SYMBOL_GPL(usb_ep_autoconfig_reset); diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 557021e..39eb718 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -103,7 +103,6 @@ static inline bool has_rndis(void) * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" -#include "epautoconf.c" #include "f_ecm.c" #include "f_subset.c" diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 77cf108..ce362f7 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -256,19 +256,6 @@ #include "gadget_chips.h" - - -/* - * Kbuild is not very cooperative with respect to linking separately - * compiled library objects into one module. So for now we won't use - * separate compilation ... ensuring init/exit sections work to shrink - * the runtime footprint, and giving us at least some parts of what - * a "gcc --combine ... part1.c part2.c part3.c ... " build would. - */ -#include "epautoconf.c" - -/*-------------------------------------------------------------------------*/ - #define DRIVER_DESC "File-backed Storage Gadget" #define DRIVER_NAME "g_file_storage" #define DRIVER_VERSION "1 September 2010" diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 2409570..c3a583e 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -24,7 +24,6 @@ */ #include "composite.c" -#include "epautoconf.c" #if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS # if defined USB_ETH_RNDIS diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index 0ccca58..ba4e302 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h @@ -15,6 +15,8 @@ #ifndef __GADGET_CHIPS_H #define __GADGET_CHIPS_H +#include + /* * NOTICE: the entries below are alphabetical and should be kept * that way. diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 68a79b4..0c70708 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -38,7 +38,6 @@ #include "gadget_chips.h" #include "composite.c" -#include "epautoconf.c" #include "f_midi.c" /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c index 917c6ed..4880cdd 100644 --- a/drivers/usb/gadget/hid.c +++ b/drivers/usb/gadget/hid.c @@ -16,6 +16,7 @@ #include #include +#include "gadget_chips.h" #define DRIVER_DESC "HID Gadget" #define DRIVER_VERSION "2010/03/16" @@ -35,7 +36,6 @@ */ #include "composite.c" -#include "epautoconf.c" #include "f_hid.c" diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c index 9675e61..0b0f008 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c @@ -49,7 +49,6 @@ */ #include "composite.c" -#include "epautoconf.c" #include "f_mass_storage.c" /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index 6b6c128..72fb301 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -44,7 +44,6 @@ MODULE_LICENSE("GPL"); */ #include "composite.c" -#include "epautoconf.c" #include "f_mass_storage.c" diff --git a/drivers/usb/gadget/ncm.c b/drivers/usb/gadget/ncm.c index ce8d08e..69b660b 100644 --- a/drivers/usb/gadget/ncm.c +++ b/drivers/usb/gadget/ncm.c @@ -37,7 +37,6 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" -#include "epautoconf.c" #include "f_ncm.c" #include "u_ether.c" diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index e2f4b9b..6834c62 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c @@ -39,7 +39,6 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" -#include "epautoconf.c" #include "u_serial.c" #include "f_acm.c" diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 310b22d..3d3d20d 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -52,7 +52,6 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" -#include "epautoconf.c" /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 39990be..098c3d0 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -38,7 +38,6 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" -#include "epautoconf.c" #include "f_acm.c" #include "f_obex.c" diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c index 926e0fa..e64a759 100644 --- a/drivers/usb/gadget/tcm_usb_gadget.c +++ b/drivers/usb/gadget/tcm_usb_gadget.c @@ -25,7 +25,6 @@ #include #include -#include "epautoconf.c" #include "composite.c" #include "tcm_usb_gadget.h" diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c index 5e500e8..66dfca8 100644 --- a/drivers/usb/gadget/webcam.c +++ b/drivers/usb/gadget/webcam.c @@ -24,7 +24,6 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" -#include "epautoconf.c" #include "uvc_queue.c" #include "uvc_video.c" diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index e39a3b5..9a9adee 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -59,7 +59,6 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" -#include "epautoconf.c" #include "f_sourcesink.c" #include "f_loopback.c" -- cgit v0.10.2 From e13f17ff8854e04cfc6b9f981a974f55d8da9b92 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 10 Sep 2012 15:01:51 +0200 Subject: usb: gadget: move USB_BUFSIZ into global composite.h This patch moves USB_BUFSIZ into global header file as USB_COMP_EP0_BUFSIZ. There is currently only one user (f_sourcesink) besides composite which need it. Ideally f_sourcesink would have its own ep0 buffer. Lets keep it that way it was for now. Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 0b6ee20..52689ee 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -28,9 +28,6 @@ * with the relevant device-wide data. */ -/* big enough to hold our biggest descriptor */ -#define USB_BUFSIZ 1024 - /* Some systems will need runtime overrides for the product identifiers * published in the device descriptor, either numbers or strings or both. * String parameters are in UTF-8 (superset of ASCII's 7 bit characters). @@ -355,10 +352,11 @@ static int config_buf(struct usb_configuration *config, { struct usb_config_descriptor *c = buf; void *next = buf + USB_DT_CONFIG_SIZE; - int len = USB_BUFSIZ - USB_DT_CONFIG_SIZE; + int len; struct usb_function *f; int status; + len = USB_COMP_EP0_BUFSIZ - USB_DT_CONFIG_SIZE; /* write the config descriptor */ c = buf; c->bLength = USB_DT_CONFIG_SIZE; @@ -1445,13 +1443,13 @@ static int composite_bind(struct usb_gadget *gadget, cdev->req = usb_ep_alloc_request(gadget->ep0, GFP_KERNEL); if (!cdev->req) goto fail; - cdev->req->buf = kmalloc(USB_BUFSIZ, GFP_KERNEL); + cdev->req->buf = kmalloc(USB_COMP_EP0_BUFSIZ, GFP_KERNEL); if (!cdev->req->buf) goto fail; cdev->req->complete = composite_setup_complete; gadget->ep0->driver_data = cdev; - cdev->bufsiz = USB_BUFSIZ; + cdev->bufsiz = USB_COMP_EP0_BUFSIZ; cdev->driver = composite; /* diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c index 5c1b68b..3c126fd 100644 --- a/drivers/usb/gadget/f_sourcesink.c +++ b/drivers/usb/gadget/f_sourcesink.c @@ -795,7 +795,7 @@ static int sourcesink_setup(struct usb_configuration *c, u16 w_value = le16_to_cpu(ctrl->wValue); u16 w_length = le16_to_cpu(ctrl->wLength); - req->length = USB_BUFSIZ; + req->length = USB_COMP_EP0_BUFSIZ; /* composite driver infrastructure handles everything except * the two control test requests. diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 43d6b9c..89d91b6 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -46,6 +46,9 @@ */ #define USB_GADGET_DELAYED_STATUS 0x7fff /* Impossibly large value */ +/* big enough to hold our biggest descriptor */ +#define USB_COMP_EP0_BUFSIZ 1024 + struct usb_configuration; /** -- cgit v0.10.2 From 40bfef0535e8a10486c9d81fd2f55e3b9dc71db6 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 10 Sep 2012 15:01:52 +0200 Subject: usb: gadget: remove bufsiz from struct usb_composite_dev there is no read user of bufsiz, its content is available via USB_COMP_EP0_BUFSIZ. Remove it. Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 52689ee..16b353f 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1449,7 +1449,6 @@ static int composite_bind(struct usb_gadget *gadget, cdev->req->complete = composite_setup_complete; gadget->ep0->driver_data = cdev; - cdev->bufsiz = USB_COMP_EP0_BUFSIZ; cdev->driver = composite; /* diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 89d91b6..e970fba 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -318,7 +318,6 @@ extern void usb_composite_setup_continue(struct usb_composite_dev *cdev); * struct usb_composite_device - represents one composite usb gadget * @gadget: read-only, abstracts the gadget's usb peripheral controller * @req: used for control responses; buffer is pre-allocated - * @bufsiz: size of buffer pre-allocated in @req * @config: the currently active configuration * * One of these devices is allocated and initialized before the @@ -349,7 +348,6 @@ extern void usb_composite_setup_continue(struct usb_composite_dev *cdev); struct usb_composite_dev { struct usb_gadget *gadget; struct usb_request *req; - unsigned bufsiz; struct usb_configuration *config; -- cgit v0.10.2 From 72258493ec4f77a772d05a8df5ee663e1e24154b Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 6 Sep 2012 20:11:15 +0200 Subject: usb: gadget: make composite module options readonly only This is a partly revert of 4fffd6e5 ("usb: gadget: composite: make module parameters accessible at runtime"). It is not possible to change the VID or other property for a gadget right now. This change has been made for Anrdoid gadget which has this functionality in its copy of the file. This function is executed currently only once and most caller in tree are __init. Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 16b353f..8d81a5c 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -34,27 +34,27 @@ */ static ushort idVendor; -module_param(idVendor, ushort, 0644); +module_param(idVendor, ushort, S_IRUGO); MODULE_PARM_DESC(idVendor, "USB Vendor ID"); static ushort idProduct; -module_param(idProduct, ushort, 0644); +module_param(idProduct, ushort, S_IRUGO); MODULE_PARM_DESC(idProduct, "USB Product ID"); static ushort bcdDevice; -module_param(bcdDevice, ushort, 0644); +module_param(bcdDevice, ushort, S_IRUGO); MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)"); static char *iManufacturer; -module_param(iManufacturer, charp, 0644); +module_param(iManufacturer, charp, S_IRUGO); MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string"); static char *iProduct; -module_param(iProduct, charp, 0644); +module_param(iProduct, charp, S_IRUGO); MODULE_PARM_DESC(iProduct, "USB Product string"); static char *iSerialNumber; -module_param(iSerialNumber, charp, 0644); +module_param(iSerialNumber, charp, S_IRUGO); MODULE_PARM_DESC(iSerialNumber, "SerialNumber string"); static char composite_manufacturer[50]; @@ -1478,16 +1478,12 @@ static int composite_bind(struct usb_gadget *gadget, /* standardized runtime overrides for device ID data */ if (idVendor) cdev->desc.idVendor = cpu_to_le16(idVendor); - else - idVendor = le16_to_cpu(cdev->desc.idVendor); + if (idProduct) cdev->desc.idProduct = cpu_to_le16(idProduct); - else - idProduct = le16_to_cpu(cdev->desc.idProduct); + if (bcdDevice) cdev->desc.bcdDevice = cpu_to_le16(bcdDevice); - else - bcdDevice = le16_to_cpu(cdev->desc.bcdDevice); /* string overrides */ if (iManufacturer || !cdev->desc.iManufacturer) { -- cgit v0.10.2 From e1f15ccbae40b55a4e2591373ea5f1808cf29855 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 6 Sep 2012 20:11:16 +0200 Subject: usb: gadget: use usb_string_ids_tab instead multiple usb_string_id() Using usb_string_ids_tab() instead multiple calls of usb_string_id() seems to be handy. It also allows to add string without many checks. Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/acm_ms.c b/drivers/usb/gadget/acm_ms.c index 5db661d..ea349ba 100644 --- a/drivers/usb/gadget/acm_ms.c +++ b/drivers/usb/gadget/acm_ms.c @@ -192,17 +192,11 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev) snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", init_utsname()->sysname, init_utsname()->release, gadget->name); - status = usb_string_id(cdev); + status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) goto fail1; - strings_dev[STRING_MANUFACTURER_IDX].id = status; - device_desc.iManufacturer = status; - - status = usb_string_id(cdev); - if (status < 0) - goto fail1; - strings_dev[STRING_PRODUCT_IDX].id = status; - device_desc.iProduct = status; + device_desc.iManufacturer = strings_dev[STRING_MANUFACTURER_IDX].id; + device_desc.iProduct = strings_dev[STRING_PRODUCT_IDX].id; /* register our configuration */ status = usb_add_config(cdev, &acm_ms_config_driver, acm_ms_do_config); diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index 689d142..5702ce3 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c @@ -165,17 +165,11 @@ static int __init audio_bind(struct usb_composite_dev *cdev) snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", init_utsname()->sysname, init_utsname()->release, cdev->gadget->name); - status = usb_string_id(cdev); + status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) goto fail; - strings_dev[STRING_MANUFACTURER_IDX].id = status; - device_desc.iManufacturer = status; - - status = usb_string_id(cdev); - if (status < 0) - goto fail; - strings_dev[STRING_PRODUCT_IDX].id = status; - device_desc.iProduct = status; + device_desc.iManufacturer = strings_dev[STRING_MANUFACTURER_IDX].id; + device_desc.iProduct = strings_dev[STRING_PRODUCT_IDX].id; status = usb_add_config(cdev, &audio_config_driver, audio_do_config); if (status < 0) diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index 8e386cf..3b89fe2 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c @@ -193,17 +193,11 @@ static int __init cdc_bind(struct usb_composite_dev *cdev) snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", init_utsname()->sysname, init_utsname()->release, gadget->name); - status = usb_string_id(cdev); + status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) goto fail1; - strings_dev[STRING_MANUFACTURER_IDX].id = status; - device_desc.iManufacturer = status; - - status = usb_string_id(cdev); - if (status < 0) - goto fail1; - strings_dev[STRING_PRODUCT_IDX].id = status; - device_desc.iProduct = status; + device_desc.iManufacturer = strings_dev[STRING_MANUFACTURER_IDX].id; + device_desc.iProduct = strings_dev[STRING_PRODUCT_IDX].id; /* register our configuration */ status = usb_add_config(cdev, &cdc_config_driver, cdc_do_config); diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 39eb718..004c6ed 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -345,17 +345,11 @@ static int __init eth_bind(struct usb_composite_dev *cdev) snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", init_utsname()->sysname, init_utsname()->release, gadget->name); - status = usb_string_id(cdev); + status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) goto fail; - strings_dev[STRING_MANUFACTURER_IDX].id = status; - device_desc.iManufacturer = status; - - status = usb_string_id(cdev); - if (status < 0) - goto fail; - strings_dev[STRING_PRODUCT_IDX].id = status; - device_desc.iProduct = status; + device_desc.iManufacturer = strings_dev[STRING_MANUFACTURER_IDX].id; + device_desc.iProduct = strings_dev[STRING_PRODUCT_IDX].id; /* register our configuration(s); RNDIS first, if it's used */ if (has_rndis()) { diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 0c70708..68f8c03 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -140,25 +140,12 @@ static int __init midi_bind(struct usb_composite_dev *cdev) struct usb_gadget *gadget = cdev->gadget; int gcnum, status; - status = usb_string_id(cdev); + status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) return status; - strings_dev[STRING_MANUFACTURER_IDX].id = status; - device_desc.iManufacturer = status; - - status = usb_string_id(cdev); - if (status < 0) - return status; - strings_dev[STRING_PRODUCT_IDX].id = status; - device_desc.iProduct = status; - - /* config description */ - status = usb_string_id(cdev); - if (status < 0) - return status; - strings_dev[STRING_DESCRIPTION_IDX].id = status; - - midi_config.iConfiguration = status; + device_desc.iManufacturer = strings_dev[STRING_MANUFACTURER_IDX].id; + device_desc.iProduct = strings_dev[STRING_PRODUCT_IDX].id; + midi_config.iConfiguration = strings_dev[STRING_DESCRIPTION_IDX].id; gcnum = usb_gadget_controller_number(gadget); if (gcnum < 0) { diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c index 4880cdd..1e3f03b 100644 --- a/drivers/usb/gadget/hid.c +++ b/drivers/usb/gadget/hid.c @@ -176,17 +176,12 @@ static int __init hid_bind(struct usb_composite_dev *cdev) snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", init_utsname()->sysname, init_utsname()->release, gadget->name); - status = usb_string_id(cdev); - if (status < 0) - return status; - strings_dev[STRING_MANUFACTURER_IDX].id = status; - device_desc.iManufacturer = status; - status = usb_string_id(cdev); + status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) return status; - strings_dev[STRING_PRODUCT_IDX].id = status; - device_desc.iProduct = status; + device_desc.iManufacturer = strings_dev[STRING_MANUFACTURER_IDX].id; + device_desc.iProduct = strings_dev[STRING_PRODUCT_IDX].id; /* register our configuration */ status = usb_add_config(cdev, &config_driver, do_config); diff --git a/drivers/usb/gadget/ncm.c b/drivers/usb/gadget/ncm.c index 69b660b..6c7e159 100644 --- a/drivers/usb/gadget/ncm.c +++ b/drivers/usb/gadget/ncm.c @@ -180,17 +180,11 @@ static int __init gncm_bind(struct usb_composite_dev *cdev) snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", init_utsname()->sysname, init_utsname()->release, gadget->name); - status = usb_string_id(cdev); + status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) goto fail; - strings_dev[STRING_MANUFACTURER_IDX].id = status; - device_desc.iManufacturer = status; - - status = usb_string_id(cdev); - if (status < 0) - goto fail; - strings_dev[STRING_PRODUCT_IDX].id = status; - device_desc.iProduct = status; + device_desc.iManufacturer = strings_dev[STRING_MANUFACTURER_IDX].id; + device_desc.iProduct = strings_dev[STRING_PRODUCT_IDX].id; status = usb_add_config(cdev, &ncm_config_driver, ncm_do_config); diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index 6834c62..b089313 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c @@ -164,26 +164,12 @@ static int __init nokia_bind(struct usb_composite_dev *cdev) if (status < 0) goto err_ether; - status = usb_string_id(cdev); + status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) goto err_usb; - strings_dev[STRING_MANUFACTURER_IDX].id = status; - - device_desc.iManufacturer = status; - - status = usb_string_id(cdev); - if (status < 0) - goto err_usb; - strings_dev[STRING_PRODUCT_IDX].id = status; - - device_desc.iProduct = status; - - /* config description */ - status = usb_string_id(cdev); - if (status < 0) - goto err_usb; - strings_dev[STRING_DESCRIPTION_IDX].id = status; - + device_desc.iManufacturer = strings_dev[STRING_MANUFACTURER_IDX].id; + device_desc.iProduct = strings_dev[STRING_PRODUCT_IDX].id; + status = strings_dev[STRING_DESCRIPTION_IDX].id; nokia_config_500ma_driver.iConfiguration = status; nokia_config_100ma_driver.iConfiguration = status; diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 098c3d0..9962504 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -175,26 +175,12 @@ static int __init gs_bind(struct usb_composite_dev *cdev) snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", init_utsname()->sysname, init_utsname()->release, gadget->name); - status = usb_string_id(cdev); + status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) goto fail; - strings_dev[STRING_MANUFACTURER_IDX].id = status; - - device_desc.iManufacturer = status; - - status = usb_string_id(cdev); - if (status < 0) - goto fail; - strings_dev[STRING_PRODUCT_IDX].id = status; - - device_desc.iProduct = status; - - /* config description */ - status = usb_string_id(cdev); - if (status < 0) - goto fail; - strings_dev[STRING_DESCRIPTION_IDX].id = status; - + device_desc.iManufacturer = strings_dev[STRING_MANUFACTURER_IDX].id; + device_desc.iProduct = strings_dev[STRING_PRODUCT_IDX].id; + status = strings_dev[STRING_DESCRIPTION_IDX].id; serial_config_driver.iConfiguration = status; /* set up other descriptors */ diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c index 66dfca8..d44a451 100644 --- a/drivers/usb/gadget/webcam.c +++ b/drivers/usb/gadget/webcam.c @@ -355,20 +355,15 @@ webcam_bind(struct usb_composite_dev *cdev) /* Allocate string descriptor numbers ... note that string contents * can be overridden by the composite_dev glue. */ - if ((ret = usb_string_id(cdev)) < 0) + ret = usb_string_ids_tab(cdev, webcam_strings); + if (ret < 0) goto error; - webcam_strings[STRING_MANUFACTURER_IDX].id = ret; - webcam_device_descriptor.iManufacturer = ret; - - if ((ret = usb_string_id(cdev)) < 0) - goto error; - webcam_strings[STRING_PRODUCT_IDX].id = ret; - webcam_device_descriptor.iProduct = ret; - - if ((ret = usb_string_id(cdev)) < 0) - goto error; - webcam_strings[STRING_DESCRIPTION_IDX].id = ret; - webcam_config_driver.iConfiguration = ret; + webcam_device_descriptor.iManufacturer = + webcam_strings[STRING_MANUFACTURER_IDX].id; + webcam_device_descriptor.iProduct = + webcam_strings[STRING_PRODUCT_IDX].id; + webcam_config_driver.iConfiguration = + webcam_strings[STRING_DESCRIPTION_IDX].id; /* Register our configuration. */ if ((ret = usb_add_config(cdev, &webcam_config_driver, diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 9a9adee..dbc336e 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -264,28 +264,18 @@ static int __init zero_bind(struct usb_composite_dev *cdev) { int gcnum; struct usb_gadget *gadget = cdev->gadget; - int id; + int status; /* Allocate string descriptor numbers ... note that string * contents can be overridden by the composite_dev glue. */ - id = usb_string_id(cdev); - if (id < 0) - return id; - strings_dev[STRING_MANUFACTURER_IDX].id = id; - device_desc.iManufacturer = id; - - id = usb_string_id(cdev); - if (id < 0) - return id; - strings_dev[STRING_PRODUCT_IDX].id = id; - device_desc.iProduct = id; - - id = usb_string_id(cdev); - if (id < 0) - return id; - strings_dev[STRING_SERIAL_IDX].id = id; - device_desc.iSerialNumber = id; + status = usb_string_ids_tab(cdev, strings_dev); + if (status < 0) + return status; + + device_desc.iManufacturer = strings_dev[STRING_MANUFACTURER_IDX].id; + device_desc.iProduct = strings_dev[STRING_PRODUCT_IDX].id; + device_desc.iSerialNumber = strings_dev[STRING_SERIAL_IDX].id; setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev); -- cgit v0.10.2 From 5a175bb84d7344fbe5e26cf61b597129e7c80564 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 6 Sep 2012 20:11:17 +0200 Subject: usb: gadget: make g_printer enumerate again This was broken in 2e87edf49 ("usb: gadget: make g_printer use composite"). The USB-strings were not setup properly and were not used. No function was added which results in an empty USB config. While fixing this, the interface number is now auto generated and not hard coded to 0. Cc: stable@vger.kernel.org # v3.5 Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 3d3d20d..51b6e7b 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -138,18 +138,14 @@ module_param(qlen, uint, S_IRUGO|S_IWUSR); * descriptors are built on demand. */ -#define STRING_MANUFACTURER 1 -#define STRING_PRODUCT 2 -#define STRING_SERIALNUM 3 +#define STRING_MANUFACTURER 0 +#define STRING_PRODUCT 1 +#define STRING_SERIALNUM 2 /* holds our biggest descriptor */ #define USB_DESC_BUFSIZE 256 #define USB_BUFSIZE 8192 -/* This device advertises one configuration. */ -#define DEV_CONFIG_VALUE 1 -#define PRINTER_INTERFACE 0 - static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, @@ -159,16 +155,12 @@ static struct usb_device_descriptor device_desc = { .bDeviceProtocol = 0, .idVendor = cpu_to_le16(PRINTER_VENDOR_NUM), .idProduct = cpu_to_le16(PRINTER_PRODUCT_NUM), - .iManufacturer = STRING_MANUFACTURER, - .iProduct = STRING_PRODUCT, - .iSerialNumber = STRING_SERIALNUM, .bNumConfigurations = 1 }; static struct usb_interface_descriptor intf_desc = { .bLength = sizeof intf_desc, .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = PRINTER_INTERFACE, .bNumEndpoints = 2, .bInterfaceClass = USB_CLASS_PRINTER, .bInterfaceSubClass = 1, /* Printer Sub-Class */ @@ -257,9 +249,9 @@ static char pnp_string [1024] = /* static strings, in UTF-8 */ static struct usb_string strings [] = { - { STRING_MANUFACTURER, manufacturer, }, - { STRING_PRODUCT, product_desc, }, - { STRING_SERIALNUM, serial_num, }, + [STRING_MANUFACTURER].s = manufacturer, + [STRING_PRODUCT].s = product_desc, + [STRING_SERIALNUM].s = serial_num, { } /* end of list */ }; @@ -868,25 +860,13 @@ static int set_interface(struct printer_dev *dev, unsigned number) int result = 0; /* Free the current interface */ - switch (dev->interface) { - case PRINTER_INTERFACE: - printer_reset_interface(dev); - break; - } + printer_reset_interface(dev); - switch (number) { - case PRINTER_INTERFACE: - result = set_printer_interface(dev); - if (result) { - printer_reset_interface(dev); - } else { - dev->interface = PRINTER_INTERFACE; - } - break; - default: - result = -EINVAL; - /* FALL THROUGH */ - } + result = set_printer_interface(dev); + if (result) + printer_reset_interface(dev); + else + dev->interface = number; if (!result) INFO(dev, "Using interface %x\n", number); @@ -969,7 +949,7 @@ static int printer_func_setup(struct usb_function *f, switch (ctrl->bRequest) { case 0: /* Get the IEEE-1284 PNP String */ /* Only one printer interface is supported. */ - if ((wIndex>>8) != PRINTER_INTERFACE) + if ((wIndex>>8) != dev->interface) break; value = (pnp_string[0]<<8)|pnp_string[1]; @@ -980,7 +960,7 @@ static int printer_func_setup(struct usb_function *f, case 1: /* Get Port Status */ /* Only one printer interface is supported. */ - if (wIndex != PRINTER_INTERFACE) + if (wIndex != dev->interface) break; *(u8 *)req->buf = dev->printer_status; @@ -989,7 +969,7 @@ static int printer_func_setup(struct usb_function *f, case 2: /* Soft Reset */ /* Only one printer interface is supported. */ - if (wIndex != PRINTER_INTERFACE) + if (wIndex != dev->interface) break; printer_soft_reset(dev); @@ -1017,6 +997,37 @@ unknown: static int __init printer_func_bind(struct usb_configuration *c, struct usb_function *f) { + struct printer_dev *dev = container_of(f, struct printer_dev, function); + struct usb_composite_dev *cdev = c->cdev; + struct usb_ep *in_ep, *out_ep; + int id; + + id = usb_interface_id(c, f); + if (id < 0) + return id; + intf_desc.bInterfaceNumber = id; + + /* all we really need is bulk IN/OUT */ + in_ep = usb_ep_autoconfig(cdev->gadget, &fs_ep_in_desc); + if (!in_ep) { +autoconf_fail: + dev_err(&cdev->gadget->dev, "can't autoconfigure on %s\n", + cdev->gadget->name); + return -ENODEV; + } + in_ep->driver_data = in_ep; /* claim */ + + out_ep = usb_ep_autoconfig(cdev->gadget, &fs_ep_out_desc); + if (!out_ep) + goto autoconf_fail; + out_ep->driver_data = out_ep; /* claim */ + + /* assumes that all endpoints are dual-speed */ + hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress; + hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress; + + dev->in_ep = in_ep; + dev->out_ep = out_ep; return 0; } @@ -1032,7 +1043,8 @@ static int printer_func_set_alt(struct usb_function *f, int ret = -ENOTSUPP; if (!alt) - ret = set_interface(dev, PRINTER_INTERFACE); + ret = set_interface(dev, intf); + return ret; } @@ -1104,13 +1116,14 @@ static int __init printer_bind_config(struct usb_configuration *c) { struct usb_gadget *gadget = c->cdev->gadget; struct printer_dev *dev; - struct usb_ep *in_ep, *out_ep; int status = -ENOMEM; int gcnum; size_t len; u32 i; struct usb_request *req; + usb_ep_autoconfig_reset(gadget); + dev = &usb_printer_gadget; dev->function.name = shortname; @@ -1122,6 +1135,10 @@ static int __init printer_bind_config(struct usb_configuration *c) dev->function.set_alt = printer_func_set_alt; dev->function.disable = printer_func_disable; + status = usb_add_function(c, &dev->function); + if (status) + return status; + /* Setup the sysfs files for the printer gadget. */ dev->pdev = device_create(usb_gadget_class, NULL, g_printer_devno, NULL, "g_printer"); @@ -1166,26 +1183,6 @@ static int __init printer_bind_config(struct usb_configuration *c) pnp_string[0] = (len >> 8) & 0xFF; pnp_string[1] = len & 0xFF; - /* all we really need is bulk IN/OUT */ - usb_ep_autoconfig_reset(gadget); - in_ep = usb_ep_autoconfig(gadget, &fs_ep_in_desc); - if (!in_ep) { -autoconf_fail: - dev_err(&gadget->dev, "can't autoconfigure on %s\n", - gadget->name); - return -ENODEV; - } - in_ep->driver_data = in_ep; /* claim */ - - out_ep = usb_ep_autoconfig(gadget, &fs_ep_out_desc); - if (!out_ep) - goto autoconf_fail; - out_ep->driver_data = out_ep; /* claim */ - - /* assumes that all endpoints are dual-speed */ - hs_ep_in_desc.bEndpointAddress = fs_ep_in_desc.bEndpointAddress; - hs_ep_out_desc.bEndpointAddress = fs_ep_out_desc.bEndpointAddress; - usb_gadget_set_selfpowered(gadget); if (gadget->is_otg) { @@ -1212,9 +1209,6 @@ autoconf_fail: dev->current_rx_bytes = 0; dev->current_rx_buf = NULL; - dev->in_ep = in_ep; - dev->out_ep = out_ep; - for (i = 0; i < QLEN; i++) { req = printer_req_alloc(dev->in_ep, USB_BUFSIZE, GFP_KERNEL); if (!req) { @@ -1247,8 +1241,6 @@ autoconf_fail: dev->gadget = gadget; INFO(dev, "%s, version: " DRIVER_VERSION "\n", driver_desc); - INFO(dev, "using %s, OUT %s IN %s\n", gadget->name, out_ep->name, - in_ep->name); return 0; fail: @@ -1263,7 +1255,17 @@ static int printer_unbind(struct usb_composite_dev *cdev) static int __init printer_bind(struct usb_composite_dev *cdev) { - return usb_add_config(cdev, &printer_cfg_driver, printer_bind_config); + int ret; + + ret = usb_string_ids_tab(cdev, strings); + if (ret < 0) + return ret; + device_desc.iManufacturer = strings[STRING_MANUFACTURER].id; + device_desc.iProduct = strings[STRING_PRODUCT].id; + device_desc.iSerialNumber = strings[STRING_SERIALNUM].id; + + ret = usb_add_config(cdev, &printer_cfg_driver, printer_bind_config); + return ret; } static __refdata struct usb_composite_driver printer_driver = { -- cgit v0.10.2 From 18786da4853017d983ff6911648543ca617c12d1 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 6 Sep 2012 20:11:18 +0200 Subject: usb: gadget: initialize the strings in tcm_usb_gadget properly I have no idea what I've been thinking while I was doing this in the first place. Now the strings are initialized properly and reported by lsusb. Cc: stable@vger.kernel.org # v3.5 Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c index e64a759..2f49808 100644 --- a/drivers/usb/gadget/tcm_usb_gadget.c +++ b/drivers/usb/gadget/tcm_usb_gadget.c @@ -1974,7 +1974,6 @@ static struct usb_interface_descriptor bot_intf_desc = { .bInterfaceClass = USB_CLASS_MASS_STORAGE, .bInterfaceSubClass = USB_SC_SCSI, .bInterfaceProtocol = USB_PR_BULK, - .iInterface = USB_G_STR_INT_UAS, }; static struct usb_interface_descriptor uasp_intf_desc = { @@ -1985,7 +1984,6 @@ static struct usb_interface_descriptor uasp_intf_desc = { .bInterfaceClass = USB_CLASS_MASS_STORAGE, .bInterfaceSubClass = USB_SC_SCSI, .bInterfaceProtocol = USB_PR_UAS, - .iInterface = USB_G_STR_INT_BBB, }; static struct usb_endpoint_descriptor uasp_bi_desc = { @@ -2206,20 +2204,16 @@ static struct usb_device_descriptor usbg_device_desc = { .bDeviceClass = USB_CLASS_PER_INTERFACE, .idVendor = cpu_to_le16(UAS_VENDOR_ID), .idProduct = cpu_to_le16(UAS_PRODUCT_ID), - .iManufacturer = USB_G_STR_MANUFACTOR, - .iProduct = USB_G_STR_PRODUCT, - .iSerialNumber = USB_G_STR_SERIAL, - .bNumConfigurations = 1, }; static struct usb_string usbg_us_strings[] = { - { USB_G_STR_MANUFACTOR, "Target Manufactor"}, - { USB_G_STR_PRODUCT, "Target Product"}, - { USB_G_STR_SERIAL, "000000000001"}, - { USB_G_STR_CONFIG, "default config"}, - { USB_G_STR_INT_UAS, "USB Attached SCSI"}, - { USB_G_STR_INT_BBB, "Bulk Only Transport"}, + [USB_G_STR_MANUFACTOR].s = "Target Manufactor", + [USB_G_STR_PRODUCT].s = "Target Product", + [USB_G_STR_SERIAL].s = "000000000001", + [USB_G_STR_CONFIG].s = "default config", + [USB_G_STR_INT_UAS].s = "USB Attached SCSI", + [USB_G_STR_INT_BBB].s = "Bulk Only Transport", { }, }; @@ -2241,7 +2235,6 @@ static int guas_unbind(struct usb_composite_dev *cdev) static struct usb_configuration usbg_config_driver = { .label = "Linux Target", .bConfigurationValue = 1, - .iConfiguration = USB_G_STR_CONFIG, .bmAttributes = USB_CONFIG_ATT_SELFPOWER, }; @@ -2414,6 +2407,9 @@ static int usbg_cfg_bind(struct usb_configuration *c) fu->function.disable = usbg_disable; fu->tpg = the_only_tpg_I_currently_have; + bot_intf_desc.iInterface = usbg_us_strings[USB_G_STR_INT_BBB].id; + uasp_intf_desc.iInterface = usbg_us_strings[USB_G_STR_INT_UAS].id; + ret = usb_add_function(c, &fu->function); if (ret) goto err; @@ -2428,6 +2424,17 @@ static int usb_target_bind(struct usb_composite_dev *cdev) { int ret; + ret = usb_string_ids_tab(cdev, usbg_us_strings); + if (ret) + return ret; + + usbg_device_desc.iManufacturer = + usbg_us_strings[USB_G_STR_MANUFACTOR].id; + usbg_device_desc.iProduct = usbg_us_strings[USB_G_STR_PRODUCT].id; + usbg_device_desc.iSerialNumber = usbg_us_strings[USB_G_STR_SERIAL].id; + usbg_config_driver.iConfiguration = + usbg_us_strings[USB_G_STR_CONFIG].id; + ret = usb_add_config(cdev, &usbg_config_driver, usbg_cfg_bind); return 0; diff --git a/drivers/usb/gadget/tcm_usb_gadget.h b/drivers/usb/gadget/tcm_usb_gadget.h index bb18999..9d32ec3 100644 --- a/drivers/usb/gadget/tcm_usb_gadget.h +++ b/drivers/usb/gadget/tcm_usb_gadget.h @@ -16,12 +16,14 @@ #define UASP_SS_EP_COMP_LOG_STREAMS 4 #define UASP_SS_EP_COMP_NUM_STREAMS (1 << UASP_SS_EP_COMP_LOG_STREAMS) -#define USB_G_STR_MANUFACTOR 1 -#define USB_G_STR_PRODUCT 2 -#define USB_G_STR_SERIAL 3 -#define USB_G_STR_CONFIG 4 -#define USB_G_STR_INT_UAS 5 -#define USB_G_STR_INT_BBB 6 +enum { + USB_G_STR_MANUFACTOR, + USB_G_STR_PRODUCT, + USB_G_STR_SERIAL, + USB_G_STR_CONFIG, + USB_G_STR_INT_UAS, + USB_G_STR_INT_BBB, +}; #define USB_G_ALT_INT_BBB 0 #define USB_G_ALT_INT_UAS 1 -- cgit v0.10.2 From 3b4a3fc0ba83265c0bfcfdfc3416e65e47441747 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 6 Sep 2012 20:11:19 +0200 Subject: usb: gadget: move usb_gadget_controller_number() into a .c file and libcomposite After I moved the function from the header file to the c file I see: | $ size drivers/usb/gadget/gadget_chips.o | text data bss dec hex filename | 1048 0 0 1048 418 drivers/usb/gadget/gadget_chips.o That is almost a KiB which is removed from each user. As Felipe pointed out, the function / usage is very dumb actually. This is used for the following reasons: - epautoconf ep hint (could provide a per-gadget callback) - miss-features. currently the missing altsetting on pxa's and something ZLP related on musbhdrc (looks like an optimisation which could be implemented in musb itself if it is correct) - unique BCD accross all UDCs. Not sure how important this is. Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 23d705f..4fec0e8 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -5,7 +5,7 @@ ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG obj-$(CONFIG_USB_GADGET) += udc-core.o obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o -libcomposite-y := usbstring.o config.o epautoconf.o +libcomposite-y := usbstring.o config.o epautoconf.o gadget_chips.o obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o obj-$(CONFIG_USB_NET2272) += net2272.o obj-$(CONFIG_USB_NET2280) += net2280.o diff --git a/drivers/usb/gadget/gadget_chips.c b/drivers/usb/gadget/gadget_chips.c new file mode 100644 index 0000000..6387d43 --- /dev/null +++ b/drivers/usb/gadget/gadget_chips.c @@ -0,0 +1,94 @@ +/* + * USB device controllers have lots of quirks. Use these macros in + * gadget drivers or other code that needs to deal with them, and which + * autoconfigures instead of using early binding to the hardware. + * + * This SHOULD eventually work like the ARM mach_is_*() stuff, driven by + * some config file that gets updated as new hardware is supported. + * (And avoiding all runtime comparisons in typical one-choice configs!) + * + * NOTE: some of these controller drivers may not be available yet. + * Some are available on 2.4 kernels; several are available, but not + * yet pushed in the 2.6 mainline tree. + */ + +#include +#include + +#include "gadget_chips.h" + +/** + * usb_gadget_controller_number - support bcdDevice id convention + * @gadget: the controller being driven + * + * Return a 2-digit BCD value associated with the peripheral controller, + * suitable for use as part of a bcdDevice value, or a negative error code. + * + * NOTE: this convention is purely optional, and has no meaning in terms of + * any USB specification. If you want to use a different convention in your + * gadget driver firmware -- maybe a more formal revision ID -- feel free. + * + * Hosts see these bcdDevice numbers, and are allowed (but not encouraged!) + * to change their behavior accordingly. For example it might help avoiding + * some chip bug. + */ +int usb_gadget_controller_number(struct usb_gadget *gadget) +{ + if (gadget_is_net2280(gadget)) + return 0x01; + else if (gadget_is_dummy(gadget)) + return 0x02; + else if (gadget_is_pxa(gadget)) + return 0x03; + else if (gadget_is_goku(gadget)) + return 0x06; + else if (gadget_is_omap(gadget)) + return 0x08; + else if (gadget_is_pxa27x(gadget)) + return 0x11; + else if (gadget_is_s3c2410(gadget)) + return 0x12; + else if (gadget_is_at91(gadget)) + return 0x13; + else if (gadget_is_imx(gadget)) + return 0x14; + else if (gadget_is_musbhdrc(gadget)) + return 0x16; + else if (gadget_is_atmel_usba(gadget)) + return 0x18; + else if (gadget_is_fsl_usb2(gadget)) + return 0x19; + else if (gadget_is_amd5536udc(gadget)) + return 0x20; + else if (gadget_is_m66592(gadget)) + return 0x21; + else if (gadget_is_fsl_qe(gadget)) + return 0x22; + else if (gadget_is_ci13xxx_pci(gadget)) + return 0x23; + else if (gadget_is_langwell(gadget)) + return 0x24; + else if (gadget_is_r8a66597(gadget)) + return 0x25; + else if (gadget_is_s3c_hsotg(gadget)) + return 0x26; + else if (gadget_is_pch(gadget)) + return 0x27; + else if (gadget_is_ci13xxx_msm(gadget)) + return 0x28; + else if (gadget_is_renesas_usbhs(gadget)) + return 0x29; + else if (gadget_is_s3c_hsudc(gadget)) + return 0x30; + else if (gadget_is_net2272(gadget)) + return 0x31; + else if (gadget_is_dwc3(gadget)) + return 0x32; + else if (gadget_is_lpc32xx(gadget)) + return 0x33; + else if (gadget_is_bcm63xx(gadget)) + return 0x34; + + return -ENOENT; +} +EXPORT_SYMBOL_GPL(usb_gadget_controller_number); diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index ba4e302..c7055cd 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h @@ -55,81 +55,7 @@ #define gadget_is_s3c_hsotg(g) (!strcmp("s3c-hsotg", (g)->name)) #define gadget_is_s3c_hsudc(g) (!strcmp("s3c-hsudc", (g)->name)) -/** - * usb_gadget_controller_number - support bcdDevice id convention - * @gadget: the controller being driven - * - * Return a 2-digit BCD value associated with the peripheral controller, - * suitable for use as part of a bcdDevice value, or a negative error code. - * - * NOTE: this convention is purely optional, and has no meaning in terms of - * any USB specification. If you want to use a different convention in your - * gadget driver firmware -- maybe a more formal revision ID -- feel free. - * - * Hosts see these bcdDevice numbers, and are allowed (but not encouraged!) - * to change their behavior accordingly. For example it might help avoiding - * some chip bug. - */ -static inline int usb_gadget_controller_number(struct usb_gadget *gadget) -{ - if (gadget_is_net2280(gadget)) - return 0x01; - else if (gadget_is_dummy(gadget)) - return 0x02; - else if (gadget_is_pxa(gadget)) - return 0x03; - else if (gadget_is_goku(gadget)) - return 0x06; - else if (gadget_is_omap(gadget)) - return 0x08; - else if (gadget_is_pxa27x(gadget)) - return 0x11; - else if (gadget_is_s3c2410(gadget)) - return 0x12; - else if (gadget_is_at91(gadget)) - return 0x13; - else if (gadget_is_imx(gadget)) - return 0x14; - else if (gadget_is_musbhdrc(gadget)) - return 0x16; - else if (gadget_is_atmel_usba(gadget)) - return 0x18; - else if (gadget_is_fsl_usb2(gadget)) - return 0x19; - else if (gadget_is_amd5536udc(gadget)) - return 0x20; - else if (gadget_is_m66592(gadget)) - return 0x21; - else if (gadget_is_fsl_qe(gadget)) - return 0x22; - else if (gadget_is_ci13xxx_pci(gadget)) - return 0x23; - else if (gadget_is_langwell(gadget)) - return 0x24; - else if (gadget_is_r8a66597(gadget)) - return 0x25; - else if (gadget_is_s3c_hsotg(gadget)) - return 0x26; - else if (gadget_is_pch(gadget)) - return 0x27; - else if (gadget_is_ci13xxx_msm(gadget)) - return 0x28; - else if (gadget_is_renesas_usbhs(gadget)) - return 0x29; - else if (gadget_is_s3c_hsudc(gadget)) - return 0x30; - else if (gadget_is_net2272(gadget)) - return 0x31; - else if (gadget_is_dwc3(gadget)) - return 0x32; - else if (gadget_is_lpc32xx(gadget)) - return 0x33; - else if (gadget_is_bcm63xx(gadget)) - return 0x34; - - return -ENOENT; -} - +int usb_gadget_controller_number(struct usb_gadget *gadget); /** * gadget_supports_altsettings - return true if altsettings work -- cgit v0.10.2 From 7d16e8d3eb704f5f6eb5a271d5758b495634e8e6 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 10 Sep 2012 15:01:53 +0200 Subject: usb: gadget: push VID/PID/USB BCD module option into gadgets This patch moves the module options idVendor, idProduct and bcdDevice from composite.c into each gadgets. This ensures compatibility with current gadgets and removes the global variable which brings me step closer towards composite.c in libcomposite Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/acm_ms.c b/drivers/usb/gadget/acm_ms.c index ea349ba..7bd6b71 100644 --- a/drivers/usb/gadget/acm_ms.c +++ b/drivers/usb/gadget/acm_ms.c @@ -47,6 +47,7 @@ #include "f_mass_storage.c" /*-------------------------------------------------------------------------*/ +USB_GADGET_COMPOSITE_OPTIONS(); static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, @@ -203,6 +204,7 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev) if (status < 0) goto fail1; + usb_composite_overwrite_options(cdev, &coverwrite); dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n", DRIVER_DESC); fsg_common_put(&fsg_common); diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index 5702ce3..55b593c 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c @@ -13,6 +13,7 @@ #include #include +#include #include "gadget_chips.h" #define DRIVER_DESC "Linux USB Audio Gadget" @@ -28,6 +29,7 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ #include "composite.c" +USB_GADGET_COMPOSITE_OPTIONS(); /* string IDs are assigned dynamically */ @@ -174,6 +176,7 @@ static int __init audio_bind(struct usb_composite_dev *cdev) status = usb_add_config(cdev, &audio_config_driver, audio_do_config); if (status < 0) goto fail; + usb_composite_overwrite_options(cdev, &coverwrite); INFO(cdev, "%s, version: %s\n", DRIVER_DESC, DRIVER_VERSION); return 0; diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index 3b89fe2..93a7580 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c @@ -34,6 +34,7 @@ #define CDC_PRODUCT_NUM 0xa4aa /* CDC Composite: ECM + ACM */ /*-------------------------------------------------------------------------*/ +USB_GADGET_COMPOSITE_OPTIONS(); /* * Kbuild is not very cooperative with respect to linking separately @@ -204,6 +205,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev) if (status < 0) goto fail1; + usb_composite_overwrite_options(cdev, &coverwrite); dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n", DRIVER_DESC); diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 8d81a5c..317a5ec 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -32,19 +32,6 @@ * published in the device descriptor, either numbers or strings or both. * String parameters are in UTF-8 (superset of ASCII's 7 bit characters). */ - -static ushort idVendor; -module_param(idVendor, ushort, S_IRUGO); -MODULE_PARM_DESC(idVendor, "USB Vendor ID"); - -static ushort idProduct; -module_param(idProduct, ushort, S_IRUGO); -MODULE_PARM_DESC(idProduct, "USB Product ID"); - -static ushort bcdDevice; -module_param(bcdDevice, ushort, S_IRUGO); -MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)"); - static char *iManufacturer; module_param(iManufacturer, charp, S_IRUGO); MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string"); @@ -1418,6 +1405,30 @@ static u8 override_id(struct usb_composite_dev *cdev, u8 *desc) return *desc; } +static void update_unchanged_dev_desc(struct usb_device_descriptor *new, + const struct usb_device_descriptor *old) +{ + __le16 idVendor; + __le16 idProduct; + __le16 bcdDevice; + + /* + * these variables may have been set in + * usb_composite_overwrite_options() + */ + idVendor = new->idVendor; + idProduct = new->idProduct; + bcdDevice = new->bcdDevice; + + *new = *old; + if (idVendor) + new->idVendor = idVendor; + if (idProduct) + new->idProduct = idProduct; + if (bcdDevice) + new->bcdDevice = bcdDevice; +} + static struct usb_composite_driver *to_cdriver(struct usb_gadget_driver *gdrv) { return container_of(gdrv, struct usb_composite_driver, gadget_driver); @@ -1473,17 +1484,7 @@ static int composite_bind(struct usb_gadget *gadget, if (status < 0) goto fail; - cdev->desc = *composite->dev; - - /* standardized runtime overrides for device ID data */ - if (idVendor) - cdev->desc.idVendor = cpu_to_le16(idVendor); - - if (idProduct) - cdev->desc.idProduct = cpu_to_le16(idProduct); - - if (bcdDevice) - cdev->desc.bcdDevice = cpu_to_le16(bcdDevice); + update_unchanged_dev_desc(&cdev->desc, composite->dev); /* string overrides */ if (iManufacturer || !cdev->desc.iManufacturer) { @@ -1686,3 +1687,17 @@ void usb_composite_setup_continue(struct usb_composite_dev *cdev) spin_unlock_irqrestore(&cdev->lock, flags); } +void usb_composite_overwrite_options(struct usb_composite_dev *cdev, + struct usb_composite_overwrite *covr) +{ + struct usb_device_descriptor *desc = &cdev->desc; + + if (covr->idVendor) + desc->idVendor = cpu_to_le16(covr->idVendor); + + if (covr->idProduct) + desc->idProduct = cpu_to_le16(covr->idProduct); + + if (covr->bcdDevice) + desc->bcdDevice = cpu_to_le16(covr->bcdDevice); +} diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 004c6ed..709ef22 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -114,6 +114,7 @@ static inline bool has_rndis(void) #include "u_ether.c" /*-------------------------------------------------------------------------*/ +USB_GADGET_COMPOSITE_OPTIONS(); /* DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! * Instead: allocate your own, using normal USB-IF procedures. @@ -363,6 +364,7 @@ static int __init eth_bind(struct usb_composite_dev *cdev) if (status < 0) goto fail; + usb_composite_overwrite_options(cdev, &coverwrite); dev_info(&gadget->dev, "%s, version: " DRIVER_VERSION "\n", DRIVER_DESC); diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index c3a583e..a44ed66 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -73,6 +73,8 @@ struct gfs_ffs_obj { struct ffs_data *ffs_data; }; +USB_GADGET_COMPOSITE_OPTIONS(); + static struct usb_device_descriptor gfs_dev_desc = { .bLength = sizeof gfs_dev_desc, .bDescriptorType = USB_DT_DEVICE, @@ -377,7 +379,7 @@ static int gfs_bind(struct usb_composite_dev *cdev) if (unlikely(ret < 0)) goto error_unbind; } - + usb_composite_overwrite_options(cdev, &coverwrite); return 0; error_unbind: diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 68f8c03..01b31e2 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -48,6 +48,8 @@ MODULE_LICENSE("GPL v2"); static const char shortname[] = "g_midi"; static const char longname[] = "MIDI Gadget"; +USB_GADGET_COMPOSITE_OPTIONS(); + static int index = SNDRV_DEFAULT_IDX1; module_param(index, int, S_IRUGO); MODULE_PARM_DESC(index, "Index value for the USB MIDI Gadget adapter."); @@ -163,7 +165,7 @@ static int __init midi_bind(struct usb_composite_dev *cdev) status = usb_add_config(cdev, &midi_config, midi_bind_config); if (status < 0) return status; - + usb_composite_overwrite_options(cdev, &coverwrite); pr_info("%s\n", longname); return 0; } diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c index 1e3f03b..59fe7ee 100644 --- a/drivers/usb/gadget/hid.c +++ b/drivers/usb/gadget/hid.c @@ -48,6 +48,7 @@ struct hidg_func_node { static LIST_HEAD(hidg_func_list); /*-------------------------------------------------------------------------*/ +USB_GADGET_COMPOSITE_OPTIONS(); static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, @@ -188,6 +189,7 @@ static int __init hid_bind(struct usb_composite_dev *cdev) if (status < 0) return status; + usb_composite_overwrite_options(cdev, &coverwrite); dev_info(&gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); return 0; diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c index 0b0f008..8ffbade 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c @@ -52,6 +52,7 @@ #include "f_mass_storage.c" /*-------------------------------------------------------------------------*/ +USB_GADGET_COMPOSITE_OPTIONS(); static struct usb_device_descriptor msg_device_desc = { .bLength = sizeof msg_device_desc, @@ -143,7 +144,7 @@ static int __init msg_bind(struct usb_composite_dev *cdev) status = usb_add_config(cdev, &msg_config_driver, msg_do_config); if (status < 0) return status; - + usb_composite_overwrite_options(cdev, &coverwrite); dev_info(&cdev->gadget->dev, DRIVER_DESC ", version: " DRIVER_VERSION "\n"); set_bit(0, &msg_registered); diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index 72fb301..6016887 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -58,7 +58,7 @@ MODULE_LICENSE("GPL"); #endif #include "u_ether.c" - +USB_GADGET_COMPOSITE_OPTIONS(); /***************************** Device Descriptor ****************************/ @@ -307,6 +307,7 @@ static int __ref multi_bind(struct usb_composite_dev *cdev) status = cdc_config_register(cdev); if (unlikely(status < 0)) goto fail2; + usb_composite_overwrite_options(cdev, &coverwrite); /* we're done */ dev_info(&gadget->dev, DRIVER_DESC "\n"); diff --git a/drivers/usb/gadget/ncm.c b/drivers/usb/gadget/ncm.c index 6c7e159..8537cd9 100644 --- a/drivers/usb/gadget/ncm.c +++ b/drivers/usb/gadget/ncm.c @@ -54,6 +54,7 @@ #define CDC_PRODUCT_NUM 0xa4a1 /* Linux-USB Ethernet Gadget */ /*-------------------------------------------------------------------------*/ +USB_GADGET_COMPOSITE_OPTIONS(); static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, @@ -191,6 +192,7 @@ static int __init gncm_bind(struct usb_composite_dev *cdev) if (status < 0) goto fail; + usb_composite_overwrite_options(cdev, &coverwrite); dev_info(&gadget->dev, "%s\n", DRIVER_DESC); return 0; diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index b089313..5ed927b 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c @@ -49,6 +49,7 @@ #include "u_ether.c" /*-------------------------------------------------------------------------*/ +USB_GADGET_COMPOSITE_OPTIONS(); #define NOKIA_VENDOR_ID 0x0421 /* Nokia */ #define NOKIA_PRODUCT_ID 0x01c8 /* Nokia Gadget */ @@ -197,6 +198,7 @@ static int __init nokia_bind(struct usb_composite_dev *cdev) if (status < 0) goto err_usb; + usb_composite_overwrite_options(cdev, &coverwrite); dev_info(&gadget->dev, "%s\n", NOKIA_LONG_NAME); return 0; diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 51b6e7b..3fa4d80 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -54,6 +54,7 @@ #include "composite.c" /*-------------------------------------------------------------------------*/ +USB_GADGET_COMPOSITE_OPTIONS(); #define DRIVER_DESC "Printer Gadget" #define DRIVER_VERSION "2007 OCT 06" @@ -1265,6 +1266,9 @@ static int __init printer_bind(struct usb_composite_dev *cdev) device_desc.iSerialNumber = strings[STRING_SERIALNUM].id; ret = usb_add_config(cdev, &printer_cfg_driver, printer_bind_config); + if (ret) + return ret; + usb_composite_overwrite_options(cdev, &coverwrite); return ret; } diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 9962504..27b5ce9 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -45,6 +45,7 @@ #include "u_serial.c" /*-------------------------------------------------------------------------*/ +USB_GADGET_COMPOSITE_OPTIONS(); /* Thanks to NetChip Technologies for donating this product ID. * @@ -212,6 +213,7 @@ static int __init gs_bind(struct usb_composite_dev *cdev) if (status < 0) goto fail; + usb_composite_overwrite_options(cdev, &coverwrite); INFO(cdev, "%s\n", GS_VERSION_NAME); return 0; diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c index 2f49808..fa3137e 100644 --- a/drivers/usb/gadget/tcm_usb_gadget.c +++ b/drivers/usb/gadget/tcm_usb_gadget.c @@ -29,6 +29,8 @@ #include "tcm_usb_gadget.h" +USB_GADGET_COMPOSITE_OPTIONS(); + static struct target_fabric_configfs *usbg_fabric_configfs; static inline struct f_uas *to_f_uas(struct usb_function *f) @@ -2437,6 +2439,9 @@ static int usb_target_bind(struct usb_composite_dev *cdev) ret = usb_add_config(cdev, &usbg_config_driver, usbg_cfg_bind); + if (ret) + return ret; + usb_composite_overwrite_options(cdev, &coverwrite); return 0; } diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c index d44a451..3060064 100644 --- a/drivers/usb/gadget/webcam.c +++ b/drivers/usb/gadget/webcam.c @@ -30,6 +30,7 @@ #include "uvc_v4l2.c" #include "f_uvc.c" +USB_GADGET_COMPOSITE_OPTIONS(); /* -------------------------------------------------------------------------- * Device descriptor */ @@ -370,6 +371,7 @@ webcam_bind(struct usb_composite_dev *cdev) webcam_config_bind)) < 0) goto error; + usb_composite_overwrite_options(cdev, &coverwrite); INFO(cdev, "Webcam Video Gadget\n"); return 0; diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index dbc336e..2b31a4a 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -64,6 +64,7 @@ #include "f_loopback.c" /*-------------------------------------------------------------------------*/ +USB_GADGET_COMPOSITE_OPTIONS(); #define DRIVER_VERSION "Cinco de Mayo 2008" @@ -305,6 +306,7 @@ static int __init zero_bind(struct usb_composite_dev *cdev) longname, gadget->name); device_desc.bcdDevice = cpu_to_le16(0x9999); } + usb_composite_overwrite_options(cdev, &coverwrite); INFO(cdev, "%s, version: " DRIVER_VERSION "\n", longname); diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index e970fba..7651e5b 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -381,6 +381,30 @@ extern int usb_string_ids_tab(struct usb_composite_dev *c, struct usb_string *str); extern int usb_string_ids_n(struct usb_composite_dev *c, unsigned n); +/* + * Some systems will need runtime overrides for the product identifiers + * published in the device descriptor, either numbers or strings or both. + * String parameters are in UTF-8 (superset of ASCII's 7 bit characters). + */ +struct usb_composite_overwrite { + u16 idVendor; + u16 idProduct; + u16 bcdDevice; +}; +#define USB_GADGET_COMPOSITE_OPTIONS() \ + static struct usb_composite_overwrite coverwrite; \ + \ + module_param_named(idVendor, coverwrite.idVendor, ushort, S_IRUGO); \ + MODULE_PARM_DESC(idVendor, "USB Vendor ID"); \ + \ + module_param_named(idProduct, coverwrite.idProduct, ushort, S_IRUGO); \ + MODULE_PARM_DESC(idProduct, "USB Product ID"); \ + \ + module_param_named(bcdDevice, coverwrite.bcdDevice, ushort, S_IRUGO); \ + MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)") + +void usb_composite_overwrite_options(struct usb_composite_dev *cdev, + struct usb_composite_overwrite *covr); /* messaging utils */ #define DBG(d, fmt, args...) \ -- cgit v0.10.2 From 276e2e4f1f3e07a0ad891bf757dbcfd655ff5f91 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 6 Sep 2012 20:11:21 +0200 Subject: =?UTF-8?q?usb:=20gadget:=20make=20sure=20each=20gadget=20is=20usi?= =?UTF-8?q?ng=20same=20index=20for=20Product,=20Serial,=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The index in usb_string array is defined by the gadget. The gadget can choose which index entry it assigns for the serial number and which the product name. The gadget has just to ensure that the descriptor contains the proper string id which is assigned by composite. If the composite layer knows the index of the "default" information which will be overwritten by module parameters, it can be used later to overwrite it. Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/acm_ms.c b/drivers/usb/gadget/acm_ms.c index 7bd6b71..35db6aa 100644 --- a/drivers/usb/gadget/acm_ms.c +++ b/drivers/usb/gadget/acm_ms.c @@ -90,14 +90,12 @@ static const struct usb_descriptor_header *otg_desc[] = { /* string IDs are assigned dynamically */ -#define STRING_MANUFACTURER_IDX 0 -#define STRING_PRODUCT_IDX 1 - static char manufacturer[50]; static struct usb_string strings_dev[] = { - [STRING_MANUFACTURER_IDX].s = manufacturer, - [STRING_PRODUCT_IDX].s = DRIVER_DESC, + [USB_GADGET_MANUFACTURER_IDX].s = manufacturer, + [USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC, + [USB_GADGET_SERIAL_IDX].s = "", { } /* end of list */ }; @@ -196,8 +194,8 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev) status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) goto fail1; - device_desc.iManufacturer = strings_dev[STRING_MANUFACTURER_IDX].id; - device_desc.iProduct = strings_dev[STRING_PRODUCT_IDX].id; + device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; + device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; /* register our configuration */ status = usb_add_config(cdev, &acm_ms_config_driver, acm_ms_do_config); diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index 55b593c..8857b6e 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c @@ -33,14 +33,12 @@ USB_GADGET_COMPOSITE_OPTIONS(); /* string IDs are assigned dynamically */ -#define STRING_MANUFACTURER_IDX 0 -#define STRING_PRODUCT_IDX 1 - static char manufacturer[50]; static struct usb_string strings_dev[] = { - [STRING_MANUFACTURER_IDX].s = manufacturer, - [STRING_PRODUCT_IDX].s = DRIVER_DESC, + [USB_GADGET_MANUFACTURER_IDX].s = manufacturer, + [USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC, + [USB_GADGET_SERIAL_IDX].s = "", { } /* end of list */ }; @@ -170,8 +168,8 @@ static int __init audio_bind(struct usb_composite_dev *cdev) status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) goto fail; - device_desc.iManufacturer = strings_dev[STRING_MANUFACTURER_IDX].id; - device_desc.iProduct = strings_dev[STRING_PRODUCT_IDX].id; + device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; + device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; status = usb_add_config(cdev, &audio_config_driver, audio_do_config); if (status < 0) diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index 93a7580..8966bde 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c @@ -90,15 +90,12 @@ static const struct usb_descriptor_header *otg_desc[] = { /* string IDs are assigned dynamically */ - -#define STRING_MANUFACTURER_IDX 0 -#define STRING_PRODUCT_IDX 1 - static char manufacturer[50]; static struct usb_string strings_dev[] = { - [STRING_MANUFACTURER_IDX].s = manufacturer, - [STRING_PRODUCT_IDX].s = DRIVER_DESC, + [USB_GADGET_MANUFACTURER_IDX].s = manufacturer, + [USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC, + [USB_GADGET_SERIAL_IDX].s = "", { } /* end of list */ }; @@ -197,8 +194,8 @@ static int __init cdc_bind(struct usb_composite_dev *cdev) status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) goto fail1; - device_desc.iManufacturer = strings_dev[STRING_MANUFACTURER_IDX].id; - device_desc.iProduct = strings_dev[STRING_PRODUCT_IDX].id; + device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; + device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; /* register our configuration */ status = usb_add_config(cdev, &cdc_config_driver, cdc_do_config); diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 709ef22..dd5e00d 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -193,17 +193,13 @@ static const struct usb_descriptor_header *otg_desc[] = { NULL, }; - /* string IDs are assigned dynamically */ - -#define STRING_MANUFACTURER_IDX 0 -#define STRING_PRODUCT_IDX 1 - static char manufacturer[50]; static struct usb_string strings_dev[] = { - [STRING_MANUFACTURER_IDX].s = manufacturer, - [STRING_PRODUCT_IDX].s = PREFIX DRIVER_DESC, + [USB_GADGET_MANUFACTURER_IDX].s = manufacturer, + [USB_GADGET_PRODUCT_IDX].s = PREFIX DRIVER_DESC, + [USB_GADGET_SERIAL_IDX].s = "", { } /* end of list */ }; @@ -349,8 +345,8 @@ static int __init eth_bind(struct usb_composite_dev *cdev) status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) goto fail; - device_desc.iManufacturer = strings_dev[STRING_MANUFACTURER_IDX].id; - device_desc.iProduct = strings_dev[STRING_PRODUCT_IDX].id; + device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; + device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; /* register our configuration(s); RNDIS first, if it's used */ if (has_rndis()) { diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index a44ed66..16d1887 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -116,6 +116,9 @@ static const struct usb_descriptor_header *gfs_otg_desc[] = { /* String IDs are assigned dynamically */ static struct usb_string gfs_strings[] = { + [USB_GADGET_MANUFACTURER_IDX].s = "", + [USB_GADGET_PRODUCT_IDX].s = "", + [USB_GADGET_SERIAL_IDX].s = "", #ifdef CONFIG_USB_FUNCTIONFS_RNDIS { .s = "FunctionFS + RNDIS" }, #endif @@ -369,9 +372,10 @@ static int gfs_bind(struct usb_composite_dev *cdev) for (i = 0; i < ARRAY_SIZE(gfs_configurations); ++i) { struct gfs_configuration *c = gfs_configurations + i; + int sid = USB_GADGET_FIRST_AVAIL_IDX + i; - c->c.label = gfs_strings[i].s; - c->c.iConfiguration = gfs_strings[i].id; + c->c.label = gfs_strings[sid].s; + c->c.iConfiguration = gfs_strings[sid].id; c->c.bConfigurationValue = 1 + i; c->c.bmAttributes = USB_CONFIG_ATT_SELFPOWER; diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 01b31e2..2ee3a74 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -84,9 +84,7 @@ MODULE_PARM_DESC(out_ports, "Number of MIDI output ports"); /* string IDs are assigned dynamically */ -#define STRING_MANUFACTURER_IDX 0 -#define STRING_PRODUCT_IDX 1 -#define STRING_DESCRIPTION_IDX 2 +#define STRING_DESCRIPTION_IDX USB_GADGET_FIRST_AVAIL_IDX static struct usb_device_descriptor device_desc = { .bLength = USB_DT_DEVICE_SIZE, @@ -101,8 +99,9 @@ static struct usb_device_descriptor device_desc = { }; static struct usb_string strings_dev[] = { - [STRING_MANUFACTURER_IDX].s = "Grey Innovation", - [STRING_PRODUCT_IDX].s = "MIDI Gadget", + [USB_GADGET_MANUFACTURER_IDX].s = "Grey Innovation", + [USB_GADGET_PRODUCT_IDX].s = "MIDI Gadget", + [USB_GADGET_SERIAL_IDX].s = "", [STRING_DESCRIPTION_IDX].s = "MIDI", { } /* end of list */ }; @@ -145,8 +144,8 @@ static int __init midi_bind(struct usb_composite_dev *cdev) status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) return status; - device_desc.iManufacturer = strings_dev[STRING_MANUFACTURER_IDX].id; - device_desc.iProduct = strings_dev[STRING_PRODUCT_IDX].id; + device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; + device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; midi_config.iConfiguration = strings_dev[STRING_DESCRIPTION_IDX].id; gcnum = usb_gadget_controller_number(gadget); diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c index 59fe7ee..16caf50 100644 --- a/drivers/usb/gadget/hid.c +++ b/drivers/usb/gadget/hid.c @@ -91,15 +91,12 @@ static const struct usb_descriptor_header *otg_desc[] = { /* string IDs are assigned dynamically */ - -#define STRING_MANUFACTURER_IDX 0 -#define STRING_PRODUCT_IDX 1 - static char manufacturer[50]; static struct usb_string strings_dev[] = { - [STRING_MANUFACTURER_IDX].s = manufacturer, - [STRING_PRODUCT_IDX].s = DRIVER_DESC, + [USB_GADGET_MANUFACTURER_IDX].s = manufacturer, + [USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC, + [USB_GADGET_SERIAL_IDX].s = "", { } /* end of list */ }; @@ -181,8 +178,8 @@ static int __init hid_bind(struct usb_composite_dev *cdev) status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) return status; - device_desc.iManufacturer = strings_dev[STRING_MANUFACTURER_IDX].id; - device_desc.iProduct = strings_dev[STRING_PRODUCT_IDX].id; + device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; + device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; /* register our configuration */ status = usb_add_config(cdev, &config_driver, do_config); diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index 6016887..94b35e5 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -109,21 +109,16 @@ static const struct usb_descriptor_header *otg_desc[] = { enum { -#ifdef CONFIG_USB_G_MULTI_RNDIS - MULTI_STRING_RNDIS_CONFIG_IDX, -#endif -#ifdef CONFIG_USB_G_MULTI_CDC + MULTI_STRING_RNDIS_CONFIG_IDX = USB_GADGET_FIRST_AVAIL_IDX, MULTI_STRING_CDC_CONFIG_IDX, -#endif }; static struct usb_string strings_dev[] = { -#ifdef CONFIG_USB_G_MULTI_RNDIS + [USB_GADGET_MANUFACTURER_IDX].s = "", + [USB_GADGET_PRODUCT_IDX].s = "", + [USB_GADGET_SERIAL_IDX].s = "", [MULTI_STRING_RNDIS_CONFIG_IDX].s = "Multifunction with RNDIS", -#endif -#ifdef CONFIG_USB_G_MULTI_CDC [MULTI_STRING_CDC_CONFIG_IDX].s = "Multifunction with CDC ECM", -#endif { } /* end of list */ }; diff --git a/drivers/usb/gadget/ncm.c b/drivers/usb/gadget/ncm.c index 8537cd9..1a26452 100644 --- a/drivers/usb/gadget/ncm.c +++ b/drivers/usb/gadget/ncm.c @@ -97,15 +97,12 @@ static const struct usb_descriptor_header *otg_desc[] = { /* string IDs are assigned dynamically */ - -#define STRING_MANUFACTURER_IDX 0 -#define STRING_PRODUCT_IDX 1 - static char manufacturer[50]; static struct usb_string strings_dev[] = { - [STRING_MANUFACTURER_IDX].s = manufacturer, - [STRING_PRODUCT_IDX].s = DRIVER_DESC, + [USB_GADGET_MANUFACTURER_IDX].s = manufacturer, + [USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC, + [USB_GADGET_SERIAL_IDX].s = "", { } /* end of list */ }; @@ -184,8 +181,8 @@ static int __init gncm_bind(struct usb_composite_dev *cdev) status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) goto fail; - device_desc.iManufacturer = strings_dev[STRING_MANUFACTURER_IDX].id; - device_desc.iProduct = strings_dev[STRING_PRODUCT_IDX].id; + device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; + device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; status = usb_add_config(cdev, &ncm_config_driver, ncm_do_config); diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index 5ed927b..34b97f1 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c @@ -56,17 +56,16 @@ USB_GADGET_COMPOSITE_OPTIONS(); /* string IDs are assigned dynamically */ -#define STRING_MANUFACTURER_IDX 0 -#define STRING_PRODUCT_IDX 1 -#define STRING_DESCRIPTION_IDX 2 +#define STRING_DESCRIPTION_IDX USB_GADGET_FIRST_AVAIL_IDX static char manufacturer_nokia[] = "Nokia"; static const char product_nokia[] = NOKIA_LONG_NAME; static const char description_nokia[] = "PC-Suite Configuration"; static struct usb_string strings_dev[] = { - [STRING_MANUFACTURER_IDX].s = manufacturer_nokia, - [STRING_PRODUCT_IDX].s = NOKIA_LONG_NAME, + [USB_GADGET_MANUFACTURER_IDX].s = manufacturer_nokia, + [USB_GADGET_PRODUCT_IDX].s = NOKIA_LONG_NAME, + [USB_GADGET_SERIAL_IDX].s = "", [STRING_DESCRIPTION_IDX].s = description_nokia, { } /* end of list */ }; @@ -168,8 +167,8 @@ static int __init nokia_bind(struct usb_composite_dev *cdev) status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) goto err_usb; - device_desc.iManufacturer = strings_dev[STRING_MANUFACTURER_IDX].id; - device_desc.iProduct = strings_dev[STRING_PRODUCT_IDX].id; + device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; + device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; status = strings_dev[STRING_DESCRIPTION_IDX].id; nokia_config_500ma_driver.iConfiguration = status; nokia_config_100ma_driver.iConfiguration = status; diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 3fa4d80..f02434a 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -139,10 +139,6 @@ module_param(qlen, uint, S_IRUGO|S_IWUSR); * descriptors are built on demand. */ -#define STRING_MANUFACTURER 0 -#define STRING_PRODUCT 1 -#define STRING_SERIALNUM 2 - /* holds our biggest descriptor */ #define USB_DESC_BUFSIZE 256 #define USB_BUFSIZE 8192 @@ -250,9 +246,9 @@ static char pnp_string [1024] = /* static strings, in UTF-8 */ static struct usb_string strings [] = { - [STRING_MANUFACTURER].s = manufacturer, - [STRING_PRODUCT].s = product_desc, - [STRING_SERIALNUM].s = serial_num, + [USB_GADGET_MANUFACTURER_IDX].s = manufacturer, + [USB_GADGET_PRODUCT_IDX].s = product_desc, + [USB_GADGET_SERIAL_IDX].s = serial_num, { } /* end of list */ }; @@ -1261,9 +1257,9 @@ static int __init printer_bind(struct usb_composite_dev *cdev) ret = usb_string_ids_tab(cdev, strings); if (ret < 0) return ret; - device_desc.iManufacturer = strings[STRING_MANUFACTURER].id; - device_desc.iProduct = strings[STRING_PRODUCT].id; - device_desc.iSerialNumber = strings[STRING_SERIALNUM].id; + device_desc.iManufacturer = strings[USB_GADGET_MANUFACTURER_IDX].id; + device_desc.iProduct = strings[USB_GADGET_PRODUCT_IDX].id; + device_desc.iSerialNumber = strings[USB_GADGET_SERIAL_IDX].id; ret = usb_add_config(cdev, &printer_cfg_driver, printer_bind_config); if (ret) diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 27b5ce9..768a38e 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -59,15 +59,14 @@ USB_GADGET_COMPOSITE_OPTIONS(); /* string IDs are assigned dynamically */ -#define STRING_MANUFACTURER_IDX 0 -#define STRING_PRODUCT_IDX 1 -#define STRING_DESCRIPTION_IDX 2 +#define STRING_DESCRIPTION_IDX USB_GADGET_FIRST_AVAIL_IDX static char manufacturer[50]; static struct usb_string strings_dev[] = { - [STRING_MANUFACTURER_IDX].s = manufacturer, - [STRING_PRODUCT_IDX].s = GS_VERSION_NAME, + [USB_GADGET_MANUFACTURER_IDX].s = manufacturer, + [USB_GADGET_PRODUCT_IDX].s = GS_VERSION_NAME, + [USB_GADGET_SERIAL_IDX].s = "", [STRING_DESCRIPTION_IDX].s = NULL /* updated; f(use_acm) */, { } /* end of list */ }; @@ -179,8 +178,8 @@ static int __init gs_bind(struct usb_composite_dev *cdev) status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) goto fail; - device_desc.iManufacturer = strings_dev[STRING_MANUFACTURER_IDX].id; - device_desc.iProduct = strings_dev[STRING_PRODUCT_IDX].id; + device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; + device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; status = strings_dev[STRING_DESCRIPTION_IDX].id; serial_config_driver.iConfiguration = status; diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c index fa3137e..b56d57d 100644 --- a/drivers/usb/gadget/tcm_usb_gadget.c +++ b/drivers/usb/gadget/tcm_usb_gadget.c @@ -2210,9 +2210,9 @@ static struct usb_device_descriptor usbg_device_desc = { }; static struct usb_string usbg_us_strings[] = { - [USB_G_STR_MANUFACTOR].s = "Target Manufactor", - [USB_G_STR_PRODUCT].s = "Target Product", - [USB_G_STR_SERIAL].s = "000000000001", + [USB_GADGET_MANUFACTURER_IDX].s = "Target Manufactor", + [USB_GADGET_PRODUCT_IDX].s = "Target Product", + [USB_GADGET_SERIAL_IDX].s = "000000000001", [USB_G_STR_CONFIG].s = "default config", [USB_G_STR_INT_UAS].s = "USB Attached SCSI", [USB_G_STR_INT_BBB].s = "Bulk Only Transport", @@ -2431,9 +2431,10 @@ static int usb_target_bind(struct usb_composite_dev *cdev) return ret; usbg_device_desc.iManufacturer = - usbg_us_strings[USB_G_STR_MANUFACTOR].id; - usbg_device_desc.iProduct = usbg_us_strings[USB_G_STR_PRODUCT].id; - usbg_device_desc.iSerialNumber = usbg_us_strings[USB_G_STR_SERIAL].id; + usbg_us_strings[USB_GADGET_MANUFACTURER_IDX].id; + usbg_device_desc.iProduct = usbg_us_strings[USB_GADGET_PRODUCT_IDX].id; + usbg_device_desc.iSerialNumber = + usbg_us_strings[USB_GADGET_SERIAL_IDX].id; usbg_config_driver.iConfiguration = usbg_us_strings[USB_G_STR_CONFIG].id; diff --git a/drivers/usb/gadget/tcm_usb_gadget.h b/drivers/usb/gadget/tcm_usb_gadget.h index 9d32ec3..8289219 100644 --- a/drivers/usb/gadget/tcm_usb_gadget.h +++ b/drivers/usb/gadget/tcm_usb_gadget.h @@ -17,10 +17,7 @@ #define UASP_SS_EP_COMP_NUM_STREAMS (1 << UASP_SS_EP_COMP_LOG_STREAMS) enum { - USB_G_STR_MANUFACTOR, - USB_G_STR_PRODUCT, - USB_G_STR_SERIAL, - USB_G_STR_CONFIG, + USB_G_STR_CONFIG = USB_GADGET_FIRST_AVAIL_IDX, USB_G_STR_INT_UAS, USB_G_STR_INT_BBB, }; diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c index 3060064..0359119 100644 --- a/drivers/usb/gadget/webcam.c +++ b/drivers/usb/gadget/webcam.c @@ -45,13 +45,12 @@ static char webcam_config_label[] = "Video"; /* string IDs are assigned dynamically */ -#define STRING_MANUFACTURER_IDX 0 -#define STRING_PRODUCT_IDX 1 -#define STRING_DESCRIPTION_IDX 2 +#define STRING_DESCRIPTION_IDX USB_GADGET_FIRST_AVAIL_IDX static struct usb_string webcam_strings[] = { - [STRING_MANUFACTURER_IDX].s = webcam_vendor_label, - [STRING_PRODUCT_IDX].s = webcam_product_label, + [USB_GADGET_MANUFACTURER_IDX].s = webcam_vendor_label, + [USB_GADGET_PRODUCT_IDX].s = webcam_product_label, + [USB_GADGET_SERIAL_IDX].s = "", [STRING_DESCRIPTION_IDX].s = webcam_config_label, { } }; @@ -360,9 +359,9 @@ webcam_bind(struct usb_composite_dev *cdev) if (ret < 0) goto error; webcam_device_descriptor.iManufacturer = - webcam_strings[STRING_MANUFACTURER_IDX].id; + webcam_strings[USB_GADGET_MANUFACTURER_IDX].id; webcam_device_descriptor.iProduct = - webcam_strings[STRING_PRODUCT_IDX].id; + webcam_strings[USB_GADGET_PRODUCT_IDX].id; webcam_config_driver.iConfiguration = webcam_strings[STRING_DESCRIPTION_IDX].id; diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 2b31a4a..ee769c4 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -139,20 +139,15 @@ const struct usb_descriptor_header *otg_desc[] = { #endif /* string IDs are assigned dynamically */ - -#define STRING_MANUFACTURER_IDX 0 -#define STRING_PRODUCT_IDX 1 -#define STRING_SERIAL_IDX 2 - static char manufacturer[50]; /* default serial number takes at least two packets */ static char serial[] = "0123456789.0123456789.0123456789"; static struct usb_string strings_dev[] = { - [STRING_MANUFACTURER_IDX].s = manufacturer, - [STRING_PRODUCT_IDX].s = longname, - [STRING_SERIAL_IDX].s = serial, + [USB_GADGET_MANUFACTURER_IDX].s = manufacturer, + [USB_GADGET_PRODUCT_IDX].s = longname, + [USB_GADGET_SERIAL_IDX].s = serial, { } /* end of list */ }; @@ -274,9 +269,9 @@ static int __init zero_bind(struct usb_composite_dev *cdev) if (status < 0) return status; - device_desc.iManufacturer = strings_dev[STRING_MANUFACTURER_IDX].id; - device_desc.iProduct = strings_dev[STRING_PRODUCT_IDX].id; - device_desc.iSerialNumber = strings_dev[STRING_SERIAL_IDX].id; + device_desc.iManufacturer = strings_dev[USB_GADGET_MANUFACTURER_IDX].id; + device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; + device_desc.iSerialNumber = strings_dev[USB_GADGET_SERIAL_IDX].id; setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev); diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 7651e5b..f821a3a 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -248,6 +248,14 @@ int usb_add_config(struct usb_composite_dev *, void usb_remove_config(struct usb_composite_dev *, struct usb_configuration *); +/* predefined index for usb_composite_driver */ +enum { + USB_GADGET_MANUFACTURER_IDX = 0, + USB_GADGET_PRODUCT_IDX, + USB_GADGET_SERIAL_IDX, + USB_GADGET_FIRST_AVAIL_IDX, +}; + /** * struct usb_composite_driver - groups configurations into a gadget * @name: For diagnostics, identifies the driver. @@ -261,7 +269,9 @@ void usb_remove_config(struct usb_composite_dev *, * @dev: Template descriptor for the device, including default device * identifiers. * @strings: tables of strings, keyed by identifiers assigned during @bind - * and language IDs provided in control requests + * and language IDs provided in control requests. Note: The first entries + * are predefined. The first entry that may be used is + * USB_GADGET_FIRST_AVAIL_IDX * @max_speed: Highest speed the driver supports. * @needs_serial: set to 1 if the gadget needs userspace to provide * a serial number. If one is not provided, warning will be printed. -- cgit v0.10.2 From 1cf0d264088907038be560ba2dd472d5e432a3dc Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 10 Sep 2012 15:01:54 +0200 Subject: usb: gadget: push iSerialNumber into gadgets This patch pushes the iSerialNumber module argument from composite into each gadget. Once the user uses the module paramter, the string is overwritten with the final value. Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 317a5ec..5642b21 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -40,10 +40,6 @@ static char *iProduct; module_param(iProduct, charp, S_IRUGO); MODULE_PARM_DESC(iProduct, "USB Product string"); -static char *iSerialNumber; -module_param(iSerialNumber, charp, S_IRUGO); -MODULE_PARM_DESC(iSerialNumber, "SerialNumber string"); - static char composite_manufacturer[50]; /*-------------------------------------------------------------------------*/ @@ -925,7 +921,7 @@ static int get_string(struct usb_composite_dev *cdev, else if (cdev->product_override == id) str = iProduct ?: composite->iProduct; else if (cdev->serial_override == id) - str = iSerialNumber ?: composite->iSerialNumber; + str = composite->iSerialNumber; else str = NULL; if (str) { @@ -1411,6 +1407,7 @@ static void update_unchanged_dev_desc(struct usb_device_descriptor *new, __le16 idVendor; __le16 idProduct; __le16 bcdDevice; + u8 iSerialNumber; /* * these variables may have been set in @@ -1419,6 +1416,7 @@ static void update_unchanged_dev_desc(struct usb_device_descriptor *new, idVendor = new->idVendor; idProduct = new->idProduct; bcdDevice = new->bcdDevice; + iSerialNumber = new->iSerialNumber; *new = *old; if (idVendor) @@ -1427,6 +1425,8 @@ static void update_unchanged_dev_desc(struct usb_device_descriptor *new, new->idProduct = idProduct; if (bcdDevice) new->bcdDevice = bcdDevice; + if (iSerialNumber) + new->iSerialNumber = iSerialNumber; } static struct usb_composite_driver *to_cdriver(struct usb_gadget_driver *gdrv) @@ -1505,8 +1505,7 @@ static int composite_bind(struct usb_gadget *gadget, cdev->product_override = override_id(cdev, &cdev->desc.iProduct); - if (iSerialNumber || - (!cdev->desc.iSerialNumber && composite->iSerialNumber)) + if (composite->iSerialNumber) cdev->serial_override = override_id(cdev, &cdev->desc.iSerialNumber); @@ -1691,6 +1690,8 @@ void usb_composite_overwrite_options(struct usb_composite_dev *cdev, struct usb_composite_overwrite *covr) { struct usb_device_descriptor *desc = &cdev->desc; + struct usb_gadget_strings *gstr = cdev->driver->strings[0]; + struct usb_string *dev_str = gstr->strings; if (covr->idVendor) desc->idVendor = cpu_to_le16(covr->idVendor); @@ -1700,4 +1701,9 @@ void usb_composite_overwrite_options(struct usb_composite_dev *cdev, if (covr->bcdDevice) desc->bcdDevice = cpu_to_le16(covr->bcdDevice); + + if (covr->serial_number) { + desc->iSerialNumber = dev_str[USB_GADGET_SERIAL_IDX].id; + dev_str[USB_GADGET_SERIAL_IDX].s = covr->serial_number; + } } diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c index 8ffbade..6f5a3b2 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c @@ -83,6 +83,22 @@ static const struct usb_descriptor_header *otg_desc[] = { NULL, }; +static struct usb_string strings_dev[] = { + [USB_GADGET_MANUFACTURER_IDX].s = "", + [USB_GADGET_PRODUCT_IDX].s = "", + [USB_GADGET_SERIAL_IDX].s = "", + { } /* end of list */ +}; + +static struct usb_gadget_strings stringtab_dev = { + .language = 0x0409, /* en-us */ + .strings = strings_dev, +}; + +static struct usb_gadget_strings *dev_strings[] = { + &stringtab_dev, + NULL, +}; /****************************** Configurations ******************************/ @@ -141,6 +157,10 @@ static int __init msg_bind(struct usb_composite_dev *cdev) { int status; + status = usb_string_ids_tab(cdev, strings_dev); + if (status < 0) + return status; + status = usb_add_config(cdev, &msg_config_driver, msg_do_config); if (status < 0) return status; @@ -160,6 +180,7 @@ static __refdata struct usb_composite_driver msg_driver = { .iProduct = DRIVER_DESC, .max_speed = USB_SPEED_SUPER, .needs_serial = 1, + .strings = dev_strings, .bind = msg_bind, }; diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index f02434a..3321a9d 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -118,8 +118,7 @@ static struct printer_dev usb_printer_gadget; * parameters are in UTF-8 (superset of ASCII's 7 bit characters). */ -static char *iSerialNum; -module_param(iSerialNum, charp, S_IRUGO); +module_param_named(iSerialNum, coverwrite.serial_number, charp, S_IRUGO); MODULE_PARM_DESC(iSerialNum, "1"); static char *iPNPstring; @@ -1170,9 +1169,6 @@ static int __init printer_bind_config(struct usb_configuration *c) init_utsname()->sysname, init_utsname()->release, gadget->name); - if (iSerialNum) - strlcpy(serial_num, iSerialNum, sizeof serial_num); - if (iPNPstring) strlcpy(&pnp_string[2], iPNPstring, (sizeof pnp_string)-2); diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index f821a3a..9d068a4 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -400,6 +400,7 @@ struct usb_composite_overwrite { u16 idVendor; u16 idProduct; u16 bcdDevice; + char *serial_number; }; #define USB_GADGET_COMPOSITE_OPTIONS() \ static struct usb_composite_overwrite coverwrite; \ @@ -411,7 +412,11 @@ struct usb_composite_overwrite { MODULE_PARM_DESC(idProduct, "USB Product ID"); \ \ module_param_named(bcdDevice, coverwrite.bcdDevice, ushort, S_IRUGO); \ - MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)") + MODULE_PARM_DESC(bcdDevice, "USB Device version (BCD)"); \ + \ + module_param_named(iSerialNumber, coverwrite.serial_number, charp, \ + S_IRUGO); \ + MODULE_PARM_DESC(iSerialNumber, "SerialNumber string") void usb_composite_overwrite_options(struct usb_composite_dev *cdev, struct usb_composite_overwrite *covr); -- cgit v0.10.2 From 03de9bf69c589b71c43aa52b838690cb477903c9 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 10 Sep 2012 15:01:55 +0200 Subject: usb: gadget: push iManufacturer into gadgets This patch pushes the iManufacturer module argument from composite into each gadget. Once the user uses the module paramter, the string is overwritten with the final value. Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 5642b21..482cf8c 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -32,10 +32,6 @@ * published in the device descriptor, either numbers or strings or both. * String parameters are in UTF-8 (superset of ASCII's 7 bit characters). */ -static char *iManufacturer; -module_param(iManufacturer, charp, S_IRUGO); -MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string"); - static char *iProduct; module_param(iProduct, charp, S_IRUGO); MODULE_PARM_DESC(iProduct, "USB Product string"); @@ -916,8 +912,7 @@ static int get_string(struct usb_composite_dev *cdev, * check if the string has not been overridden. */ if (cdev->manufacturer_override == id) - str = iManufacturer ?: composite->iManufacturer ?: - composite_manufacturer; + str = composite->iManufacturer ?: composite_manufacturer; else if (cdev->product_override == id) str = iProduct ?: composite->iProduct; else if (cdev->serial_override == id) @@ -1408,6 +1403,7 @@ static void update_unchanged_dev_desc(struct usb_device_descriptor *new, __le16 idProduct; __le16 bcdDevice; u8 iSerialNumber; + u8 iManufacturer; /* * these variables may have been set in @@ -1417,6 +1413,7 @@ static void update_unchanged_dev_desc(struct usb_device_descriptor *new, idProduct = new->idProduct; bcdDevice = new->bcdDevice; iSerialNumber = new->iSerialNumber; + iManufacturer = new->iManufacturer; *new = *old; if (idVendor) @@ -1427,6 +1424,8 @@ static void update_unchanged_dev_desc(struct usb_device_descriptor *new, new->bcdDevice = bcdDevice; if (iSerialNumber) new->iSerialNumber = iSerialNumber; + if (iManufacturer) + new->iManufacturer = iManufacturer; } static struct usb_composite_driver *to_cdriver(struct usb_gadget_driver *gdrv) @@ -1487,9 +1486,8 @@ static int composite_bind(struct usb_gadget *gadget, update_unchanged_dev_desc(&cdev->desc, composite->dev); /* string overrides */ - if (iManufacturer || !cdev->desc.iManufacturer) { - if (!iManufacturer && !composite->iManufacturer && - !*composite_manufacturer) + if (!cdev->desc.iManufacturer) { + if (!composite->iManufacturer) snprintf(composite_manufacturer, sizeof composite_manufacturer, "%s %s with %s", @@ -1706,4 +1704,8 @@ void usb_composite_overwrite_options(struct usb_composite_dev *cdev, desc->iSerialNumber = dev_str[USB_GADGET_SERIAL_IDX].id; dev_str[USB_GADGET_SERIAL_IDX].s = covr->serial_number; } + if (covr->manufacturer) { + desc->iManufacturer = dev_str[USB_GADGET_MANUFACTURER_IDX].id; + dev_str[USB_GADGET_MANUFACTURER_IDX].s = covr->manufacturer; + } } diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 9d068a4..86553c8 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -401,6 +401,7 @@ struct usb_composite_overwrite { u16 idProduct; u16 bcdDevice; char *serial_number; + char *manufacturer; }; #define USB_GADGET_COMPOSITE_OPTIONS() \ static struct usb_composite_overwrite coverwrite; \ @@ -416,7 +417,11 @@ struct usb_composite_overwrite { \ module_param_named(iSerialNumber, coverwrite.serial_number, charp, \ S_IRUGO); \ - MODULE_PARM_DESC(iSerialNumber, "SerialNumber string") + MODULE_PARM_DESC(iSerialNumber, "SerialNumber string"); \ + \ + module_param_named(iManufacturer, coverwrite.manufacturer, charp, \ + S_IRUGO); \ + MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string") void usb_composite_overwrite_options(struct usb_composite_dev *cdev, struct usb_composite_overwrite *covr); -- cgit v0.10.2 From 2d35ee47aaafac152bc4bc5020660ffa1753ab02 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 10 Sep 2012 15:01:56 +0200 Subject: usb: gadget: push iProduct into gadgets This patch pushes the iProduct module argument from composite into each gadget. Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 482cf8c..47b9130 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -28,14 +28,6 @@ * with the relevant device-wide data. */ -/* Some systems will need runtime overrides for the product identifiers - * published in the device descriptor, either numbers or strings or both. - * String parameters are in UTF-8 (superset of ASCII's 7 bit characters). - */ -static char *iProduct; -module_param(iProduct, charp, S_IRUGO); -MODULE_PARM_DESC(iProduct, "USB Product string"); - static char composite_manufacturer[50]; /*-------------------------------------------------------------------------*/ @@ -914,7 +906,7 @@ static int get_string(struct usb_composite_dev *cdev, if (cdev->manufacturer_override == id) str = composite->iManufacturer ?: composite_manufacturer; else if (cdev->product_override == id) - str = iProduct ?: composite->iProduct; + str = composite->iProduct; else if (cdev->serial_override == id) str = composite->iSerialNumber; else @@ -1404,6 +1396,7 @@ static void update_unchanged_dev_desc(struct usb_device_descriptor *new, __le16 bcdDevice; u8 iSerialNumber; u8 iManufacturer; + u8 iProduct; /* * these variables may have been set in @@ -1414,6 +1407,7 @@ static void update_unchanged_dev_desc(struct usb_device_descriptor *new, bcdDevice = new->bcdDevice; iSerialNumber = new->iSerialNumber; iManufacturer = new->iManufacturer; + iProduct = new->iProduct; *new = *old; if (idVendor) @@ -1426,6 +1420,8 @@ static void update_unchanged_dev_desc(struct usb_device_descriptor *new, new->iSerialNumber = iSerialNumber; if (iManufacturer) new->iManufacturer = iManufacturer; + if (iProduct) + new->iProduct = iProduct; } static struct usb_composite_driver *to_cdriver(struct usb_gadget_driver *gdrv) @@ -1499,7 +1495,7 @@ static int composite_bind(struct usb_gadget *gadget, override_id(cdev, &cdev->desc.iManufacturer); } - if (iProduct || (!cdev->desc.iProduct && composite->iProduct)) + if (!cdev->desc.iProduct && composite->iProduct) cdev->product_override = override_id(cdev, &cdev->desc.iProduct); @@ -1708,4 +1704,9 @@ void usb_composite_overwrite_options(struct usb_composite_dev *cdev, desc->iManufacturer = dev_str[USB_GADGET_MANUFACTURER_IDX].id; dev_str[USB_GADGET_MANUFACTURER_IDX].s = covr->manufacturer; } + + if (covr->product) { + desc->iProduct = dev_str[USB_GADGET_PRODUCT_IDX].id; + dev_str[USB_GADGET_PRODUCT_IDX].s = covr->product; + } } diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 86553c8..5cd110e 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -402,6 +402,7 @@ struct usb_composite_overwrite { u16 bcdDevice; char *serial_number; char *manufacturer; + char *product; }; #define USB_GADGET_COMPOSITE_OPTIONS() \ static struct usb_composite_overwrite coverwrite; \ @@ -421,7 +422,10 @@ struct usb_composite_overwrite { \ module_param_named(iManufacturer, coverwrite.manufacturer, charp, \ S_IRUGO); \ - MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string") + MODULE_PARM_DESC(iManufacturer, "USB Manufacturer string"); \ + \ + module_param_named(iProduct, coverwrite.product, charp, S_IRUGO); \ + MODULE_PARM_DESC(iProduct, "USB Product string") void usb_composite_overwrite_options(struct usb_composite_dev *cdev, struct usb_composite_overwrite *covr); -- cgit v0.10.2 From d33f74fce3756d51a0203cec3d0d278e3b48d827 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 10 Sep 2012 15:01:57 +0200 Subject: usb: gadget: remove string override from struct usb_composite_driver The struct usb_composite_driver members iProduct, iSerial and iManufacturer can be entered directly via the string array. There is no need for them to appear here. Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 47b9130..f3689e1 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -904,11 +904,7 @@ static int get_string(struct usb_composite_dev *cdev, * check if the string has not been overridden. */ if (cdev->manufacturer_override == id) - str = composite->iManufacturer ?: composite_manufacturer; - else if (cdev->product_override == id) - str = composite->iProduct; - else if (cdev->serial_override == id) - str = composite->iSerialNumber; + str = composite_manufacturer; else str = NULL; if (str) { @@ -1483,26 +1479,17 @@ static int composite_bind(struct usb_gadget *gadget, /* string overrides */ if (!cdev->desc.iManufacturer) { - if (!composite->iManufacturer) - snprintf(composite_manufacturer, - sizeof composite_manufacturer, - "%s %s with %s", - init_utsname()->sysname, - init_utsname()->release, - gadget->name); + snprintf(composite_manufacturer, + sizeof composite_manufacturer, + "%s %s with %s", + init_utsname()->sysname, + init_utsname()->release, + gadget->name); cdev->manufacturer_override = override_id(cdev, &cdev->desc.iManufacturer); } - if (!cdev->desc.iProduct && composite->iProduct) - cdev->product_override = - override_id(cdev, &cdev->desc.iProduct); - - if (composite->iSerialNumber) - cdev->serial_override = - override_id(cdev, &cdev->desc.iSerialNumber); - /* has userspace failed to provide a serial number? */ if (composite->needs_serial && !cdev->desc.iSerialNumber) WARNING(cdev, "userspace failed to provide iSerialNumber\n"); @@ -1619,8 +1606,6 @@ int usb_composite_probe(struct usb_composite_driver *driver) if (!driver->name) driver->name = "composite"; - if (!driver->iProduct) - driver->iProduct = driver->name; driver->gadget_driver = composite_driver_template; gadget_driver = &driver->gadget_driver; diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 16d1887..eaaed19 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -117,7 +117,7 @@ static const struct usb_descriptor_header *gfs_otg_desc[] = { /* String IDs are assigned dynamically */ static struct usb_string gfs_strings[] = { [USB_GADGET_MANUFACTURER_IDX].s = "", - [USB_GADGET_PRODUCT_IDX].s = "", + [USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC, [USB_GADGET_SERIAL_IDX].s = "", #ifdef CONFIG_USB_FUNCTIONFS_RNDIS { .s = "FunctionFS + RNDIS" }, @@ -172,7 +172,6 @@ static __refdata struct usb_composite_driver gfs_driver = { .max_speed = USB_SPEED_HIGH, .bind = gfs_bind, .unbind = gfs_unbind, - .iProduct = DRIVER_DESC, }; static DEFINE_MUTEX(gfs_lock); @@ -360,6 +359,7 @@ static int gfs_bind(struct usb_composite_dev *cdev) ret = usb_string_ids_tab(cdev, gfs_strings); if (unlikely(ret < 0)) goto error; + gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id; for (i = func_num; --i; ) { ret = functionfs_bind(ffs_tab[i].ffs_data, cdev); diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c index 6f5a3b2..50da3c8 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c @@ -85,7 +85,7 @@ static const struct usb_descriptor_header *otg_desc[] = { static struct usb_string strings_dev[] = { [USB_GADGET_MANUFACTURER_IDX].s = "", - [USB_GADGET_PRODUCT_IDX].s = "", + [USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC, [USB_GADGET_SERIAL_IDX].s = "", { } /* end of list */ }; @@ -160,6 +160,7 @@ static int __init msg_bind(struct usb_composite_dev *cdev) status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) return status; + msg_device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; status = usb_add_config(cdev, &msg_config_driver, msg_do_config); if (status < 0) @@ -177,7 +178,6 @@ static int __init msg_bind(struct usb_composite_dev *cdev) static __refdata struct usb_composite_driver msg_driver = { .name = "g_mass_storage", .dev = &msg_device_desc, - .iProduct = DRIVER_DESC, .max_speed = USB_SPEED_SUPER, .needs_serial = 1, .strings = dev_strings, diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index 94b35e5..c158706 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -115,7 +115,7 @@ enum { static struct usb_string strings_dev[] = { [USB_GADGET_MANUFACTURER_IDX].s = "", - [USB_GADGET_PRODUCT_IDX].s = "", + [USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC, [USB_GADGET_SERIAL_IDX].s = "", [MULTI_STRING_RNDIS_CONFIG_IDX].s = "Multifunction with RNDIS", [MULTI_STRING_CDC_CONFIG_IDX].s = "Multifunction with CDC ECM", @@ -293,6 +293,7 @@ static int __ref multi_bind(struct usb_composite_dev *cdev) status = usb_string_ids_tab(cdev, strings_dev); if (unlikely(status < 0)) goto fail2; + device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; /* register configurations */ status = rndis_config_register(cdev); @@ -338,7 +339,6 @@ static __refdata struct usb_composite_driver multi_driver = { .max_speed = USB_SPEED_HIGH, .bind = multi_bind, .unbind = __exit_p(multi_unbind), - .iProduct = DRIVER_DESC, .needs_serial = 1, }; diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 5cd110e..60f8815 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -259,13 +259,6 @@ enum { /** * struct usb_composite_driver - groups configurations into a gadget * @name: For diagnostics, identifies the driver. - * @iProduct: Used as iProduct override if @dev->iProduct is not set. - * If NULL value of @name is taken. - * @iManufacturer: Used as iManufacturer override if @dev->iManufacturer is - * not set. If NULL a default " with " value - * will be used. - * @iSerialNumber: Used as iSerialNumber override if @dev->iSerialNumber is - * not set. * @dev: Template descriptor for the device, including default device * identifiers. * @strings: tables of strings, keyed by identifiers assigned during @bind @@ -300,9 +293,6 @@ enum { */ struct usb_composite_driver { const char *name; - const char *iProduct; - const char *iManufacturer; - const char *iSerialNumber; const struct usb_device_descriptor *dev; struct usb_gadget_strings **strings; enum usb_device_speed max_speed; @@ -369,8 +359,6 @@ struct usb_composite_dev { struct usb_composite_driver *driver; u8 next_string_id; u8 manufacturer_override; - u8 product_override; - u8 serial_override; /* the gadget driver won't enable the data pullup * while the deactivation count is nonzero. -- cgit v0.10.2 From cc2683c318a5bf192b75cd5c343b51009db0cf6c Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 10 Sep 2012 15:01:58 +0200 Subject: usb: gadget: Provide a default implementation of default manufacturer string Some gadgets provide custom entry here. Some may override it with an etntry that is also created by composite if there was no value sumbitted at all. This patch removes all "custom manufacturer" strings which are the same as these which are created by composite. Then it moves the creation of the default manufacturer string to usb_composite_overwrite_options() in case no command line argument has been used and the entry is still an empty string. By doing this we get rid of the global variable "composite_manufacturer" in composite. Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/acm_ms.c b/drivers/usb/gadget/acm_ms.c index 35db6aa..d280f16 100644 --- a/drivers/usb/gadget/acm_ms.c +++ b/drivers/usb/gadget/acm_ms.c @@ -15,7 +15,6 @@ */ #include -#include #include "u_serial.h" @@ -87,13 +86,9 @@ static const struct usb_descriptor_header *otg_desc[] = { NULL, }; - /* string IDs are assigned dynamically */ - -static char manufacturer[50]; - static struct usb_string strings_dev[] = { - [USB_GADGET_MANUFACTURER_IDX].s = manufacturer, + [USB_GADGET_MANUFACTURER_IDX].s = "", [USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC, [USB_GADGET_SERIAL_IDX].s = "", { } /* end of list */ @@ -186,11 +181,6 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev) * Allocate string descriptor numbers ... note that string * contents can be overridden by the composite_dev glue. */ - - /* device descriptor strings: manufacturer, product */ - snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", - init_utsname()->sysname, init_utsname()->release, - gadget->name); status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) goto fail1; diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index 8857b6e..1f81e0f 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c @@ -12,7 +12,6 @@ /* #define VERBOSE_DEBUG */ #include -#include #include #include "gadget_chips.h" @@ -33,10 +32,8 @@ USB_GADGET_COMPOSITE_OPTIONS(); /* string IDs are assigned dynamically */ -static char manufacturer[50]; - static struct usb_string strings_dev[] = { - [USB_GADGET_MANUFACTURER_IDX].s = manufacturer, + [USB_GADGET_MANUFACTURER_IDX].s = "", [USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC, [USB_GADGET_SERIAL_IDX].s = "", { } /* end of list */ @@ -161,10 +158,6 @@ static int __init audio_bind(struct usb_composite_dev *cdev) __constant_cpu_to_le16(0x0300 | 0x0099); } - /* device descriptor strings: manufacturer, product */ - snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", - init_utsname()->sysname, init_utsname()->release, - cdev->gadget->name); status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) goto fail; diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index 8966bde..4e2060b 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c @@ -11,7 +11,6 @@ */ #include -#include #include #include "u_ether.h" @@ -90,10 +89,8 @@ static const struct usb_descriptor_header *otg_desc[] = { /* string IDs are assigned dynamically */ -static char manufacturer[50]; - static struct usb_string strings_dev[] = { - [USB_GADGET_MANUFACTURER_IDX].s = manufacturer, + [USB_GADGET_MANUFACTURER_IDX].s = "", [USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC, [USB_GADGET_SERIAL_IDX].s = "", { } /* end of list */ @@ -182,15 +179,10 @@ static int __init cdc_bind(struct usb_composite_dev *cdev) cpu_to_le16(0x0300 | 0x0099); } - /* Allocate string descriptor numbers ... note that string * contents can be overridden by the composite_dev glue. */ - /* device descriptor strings: manufacturer, product */ - snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", - init_utsname()->sysname, init_utsname()->release, - gadget->name); status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) goto fail1; diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index f3689e1..c7066cd 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -28,9 +28,6 @@ * with the relevant device-wide data. */ -static char composite_manufacturer[50]; - -/*-------------------------------------------------------------------------*/ /** * next_ep_desc() - advance to the next EP descriptor * @t: currect pointer within descriptor array @@ -860,7 +857,6 @@ static int get_string(struct usb_composite_dev *cdev, struct usb_configuration *c; struct usb_function *f; int len; - const char *str; /* Yes, not only is USB's I18N support probably more than most * folk will ever care about ... also, it's all supported here. @@ -900,21 +896,6 @@ static int get_string(struct usb_composite_dev *cdev, return s->bLength; } - /* Otherwise, look up and return a specified string. First - * check if the string has not been overridden. - */ - if (cdev->manufacturer_override == id) - str = composite_manufacturer; - else - str = NULL; - if (str) { - struct usb_gadget_strings strings = { - .language = language, - .strings = &(struct usb_string) { 0xff, str } - }; - return usb_gadget_get_string(&strings, 0xff, buf); - } - /* String IDs are device-scoped, so we look up each string * table we're told about. These lookups are infrequent; * simpler-is-better here. @@ -1367,23 +1348,11 @@ composite_unbind(struct usb_gadget *gadget) usb_ep_free_request(gadget->ep0, cdev->req); } device_remove_file(&gadget->dev, &dev_attr_suspended); + kfree(cdev->def_manufacturer); kfree(cdev); set_gadget_data(gadget, NULL); } -static u8 override_id(struct usb_composite_dev *cdev, u8 *desc) -{ - if (!*desc) { - int ret = usb_string_id(cdev); - if (unlikely(ret < 0)) - WARNING(cdev, "failed to override string ID\n"); - else - *desc = ret; - } - - return *desc; -} - static void update_unchanged_dev_desc(struct usb_device_descriptor *new, const struct usb_device_descriptor *old) { @@ -1477,19 +1446,6 @@ static int composite_bind(struct usb_gadget *gadget, update_unchanged_dev_desc(&cdev->desc, composite->dev); - /* string overrides */ - if (!cdev->desc.iManufacturer) { - snprintf(composite_manufacturer, - sizeof composite_manufacturer, - "%s %s with %s", - init_utsname()->sysname, - init_utsname()->release, - gadget->name); - - cdev->manufacturer_override = - override_id(cdev, &cdev->desc.iManufacturer); - } - /* has userspace failed to provide a serial number? */ if (composite->needs_serial && !cdev->desc.iSerialNumber) WARNING(cdev, "userspace failed to provide iSerialNumber\n"); @@ -1665,6 +1621,22 @@ void usb_composite_setup_continue(struct usb_composite_dev *cdev) spin_unlock_irqrestore(&cdev->lock, flags); } +static char *composite_default_mfr(struct usb_gadget *gadget) +{ + char *mfr; + int len; + + len = snprintf(NULL, 0, "%s %s with %s", init_utsname()->sysname, + init_utsname()->release, gadget->name); + len++; + mfr = kmalloc(len, GFP_KERNEL); + if (!mfr) + return NULL; + snprintf(mfr, len, "%s %s with %s", init_utsname()->sysname, + init_utsname()->release, gadget->name); + return mfr; +} + void usb_composite_overwrite_options(struct usb_composite_dev *cdev, struct usb_composite_overwrite *covr) { @@ -1688,6 +1660,11 @@ void usb_composite_overwrite_options(struct usb_composite_dev *cdev, if (covr->manufacturer) { desc->iManufacturer = dev_str[USB_GADGET_MANUFACTURER_IDX].id; dev_str[USB_GADGET_MANUFACTURER_IDX].s = covr->manufacturer; + + } else if (!strlen(dev_str[USB_GADGET_MANUFACTURER_IDX].s)) { + desc->iManufacturer = dev_str[USB_GADGET_MANUFACTURER_IDX].id; + cdev->def_manufacturer = composite_default_mfr(cdev->gadget); + dev_str[USB_GADGET_MANUFACTURER_IDX].s = cdev->def_manufacturer; } if (covr->product) { diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index dd5e00d..a5c2720 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -14,8 +14,6 @@ /* #define VERBOSE_DEBUG */ #include -#include - #if defined USB_ETH_RNDIS # undef USB_ETH_RNDIS @@ -193,11 +191,8 @@ static const struct usb_descriptor_header *otg_desc[] = { NULL, }; -/* string IDs are assigned dynamically */ -static char manufacturer[50]; - static struct usb_string strings_dev[] = { - [USB_GADGET_MANUFACTURER_IDX].s = manufacturer, + [USB_GADGET_MANUFACTURER_IDX].s = "", [USB_GADGET_PRODUCT_IDX].s = PREFIX DRIVER_DESC, [USB_GADGET_SERIAL_IDX].s = "", { } /* end of list */ @@ -333,15 +328,10 @@ static int __init eth_bind(struct usb_composite_dev *cdev) cpu_to_le16(0x0300 | 0x0099); } - /* Allocate string descriptor numbers ... note that string * contents can be overridden by the composite_dev glue. */ - /* device descriptor strings: manufacturer, product */ - snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", - init_utsname()->sysname, init_utsname()->release, - gadget->name); status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) goto fail; diff --git a/drivers/usb/gadget/f_hid.c b/drivers/usb/gadget/f_hid.c index 16a8b1c..77dbca0 100644 --- a/drivers/usb/gadget/f_hid.c +++ b/drivers/usb/gadget/f_hid.c @@ -10,7 +10,6 @@ */ #include -#include #include #include #include diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 4f1142e..1115096 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -213,7 +213,6 @@ #include #include #include -#include #include #include diff --git a/drivers/usb/gadget/f_midi.c b/drivers/usb/gadget/f_midi.c index 2f7e8f2..8ed1259 100644 --- a/drivers/usb/gadget/f_midi.c +++ b/drivers/usb/gadget/f_midi.c @@ -21,7 +21,6 @@ #include #include -#include #include #include diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index eaaed19..9e62c20 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -13,7 +13,6 @@ #define pr_fmt(fmt) "g_ffs: " fmt #include -#include /* * kbuild is not very cooperative with respect to linking separately diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 2ee3a74..59621ef 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -22,7 +22,6 @@ #include #include -#include #include #include diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c index 16caf50..0e2e357 100644 --- a/drivers/usb/gadget/hid.c +++ b/drivers/usb/gadget/hid.c @@ -91,10 +91,8 @@ static const struct usb_descriptor_header *otg_desc[] = { /* string IDs are assigned dynamically */ -static char manufacturer[50]; - static struct usb_string strings_dev[] = { - [USB_GADGET_MANUFACTURER_IDX].s = manufacturer, + [USB_GADGET_MANUFACTURER_IDX].s = "", [USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC, [USB_GADGET_SERIAL_IDX].s = "", { } /* end of list */ @@ -165,16 +163,10 @@ static int __init hid_bind(struct usb_composite_dev *cdev) else device_desc.bcdDevice = cpu_to_le16(0x0300 | 0x0099); - /* Allocate string descriptor numbers ... note that string * contents can be overridden by the composite_dev glue. */ - /* device descriptor strings: manufacturer, product */ - snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", - init_utsname()->sysname, init_utsname()->release, - gadget->name); - status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) return status; diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c index 50da3c8..9eb2be6 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c @@ -29,10 +29,8 @@ #include -#include #include - /*-------------------------------------------------------------------------*/ #define DRIVER_DESC "Mass Storage Gadget" diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index c158706..5bc5d96 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -14,10 +14,8 @@ #include -#include #include - #if defined USB_ETH_RNDIS # undef USB_ETH_RNDIS #endif diff --git a/drivers/usb/gadget/ncm.c b/drivers/usb/gadget/ncm.c index 1a26452..343f3d3 100644 --- a/drivers/usb/gadget/ncm.c +++ b/drivers/usb/gadget/ncm.c @@ -20,8 +20,6 @@ /* #define VERBOSE_DEBUG */ #include -#include - #include "u_ether.h" @@ -95,12 +93,9 @@ static const struct usb_descriptor_header *otg_desc[] = { NULL, }; - /* string IDs are assigned dynamically */ -static char manufacturer[50]; - static struct usb_string strings_dev[] = { - [USB_GADGET_MANUFACTURER_IDX].s = manufacturer, + [USB_GADGET_MANUFACTURER_IDX].s = "", [USB_GADGET_PRODUCT_IDX].s = DRIVER_DESC, [USB_GADGET_SERIAL_IDX].s = "", { } /* end of list */ @@ -169,15 +164,10 @@ static int __init gncm_bind(struct usb_composite_dev *cdev) cpu_to_le16(0x0300 | 0x0099); } - /* Allocate string descriptor numbers ... note that string * contents can be overridden by the composite_dev glue. */ - /* device descriptor strings: manufacturer, product */ - snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", - init_utsname()->sysname, init_utsname()->release, - gadget->name); status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) goto fail; diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index 34b97f1..465766e 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c @@ -16,7 +16,6 @@ */ #include -#include #include #include "u_serial.h" diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 3321a9d..9bd9942 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -237,7 +236,6 @@ static const struct usb_descriptor_header *otg_desc[] = { /* descriptors that are built on-demand */ -static char manufacturer [50]; static char product_desc [40] = DRIVER_DESC; static char serial_num [40] = "1"; static char pnp_string [1024] = @@ -245,7 +243,7 @@ static char pnp_string [1024] = /* static strings, in UTF-8 */ static struct usb_string strings [] = { - [USB_GADGET_MANUFACTURER_IDX].s = manufacturer, + [USB_GADGET_MANUFACTURER_IDX].s = "", [USB_GADGET_PRODUCT_IDX].s = product_desc, [USB_GADGET_SERIAL_IDX].s = serial_num, { } /* end of list */ @@ -1165,10 +1163,6 @@ static int __init printer_bind_config(struct usb_configuration *c) device_desc.bcdDevice = cpu_to_le16(0xFFFF); } - snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s", - init_utsname()->sysname, init_utsname()->release, - gadget->name); - if (iPNPstring) strlcpy(&pnp_string[2], iPNPstring, (sizeof pnp_string)-2); diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 768a38e..bf12d55 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -11,7 +11,6 @@ */ #include -#include #include #include #include @@ -61,10 +60,8 @@ USB_GADGET_COMPOSITE_OPTIONS(); #define STRING_DESCRIPTION_IDX USB_GADGET_FIRST_AVAIL_IDX -static char manufacturer[50]; - static struct usb_string strings_dev[] = { - [USB_GADGET_MANUFACTURER_IDX].s = manufacturer, + [USB_GADGET_MANUFACTURER_IDX].s = "", [USB_GADGET_PRODUCT_IDX].s = GS_VERSION_NAME, [USB_GADGET_SERIAL_IDX].s = "", [STRING_DESCRIPTION_IDX].s = NULL /* updated; f(use_acm) */, @@ -171,10 +168,6 @@ static int __init gs_bind(struct usb_composite_dev *cdev) * contents can be overridden by the composite_dev glue. */ - /* device description: manufacturer, product */ - snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", - init_utsname()->sysname, init_utsname()->release, - gadget->name); status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) goto fail; diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index ee769c4..a837f3a 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -42,7 +42,6 @@ #include #include -#include #include #include "g_zero.h" @@ -139,13 +138,11 @@ const struct usb_descriptor_header *otg_desc[] = { #endif /* string IDs are assigned dynamically */ -static char manufacturer[50]; - /* default serial number takes at least two packets */ static char serial[] = "0123456789.0123456789.0123456789"; static struct usb_string strings_dev[] = { - [USB_GADGET_MANUFACTURER_IDX].s = manufacturer, + [USB_GADGET_MANUFACTURER_IDX].s = "", [USB_GADGET_PRODUCT_IDX].s = longname, [USB_GADGET_SERIAL_IDX].s = serial, { } /* end of list */ @@ -305,10 +302,6 @@ static int __init zero_bind(struct usb_composite_dev *cdev) INFO(cdev, "%s, version: " DRIVER_VERSION "\n", longname); - snprintf(manufacturer, sizeof manufacturer, "%s %s with %s", - init_utsname()->sysname, init_utsname()->release, - gadget->name); - return 0; } diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 60f8815..65ae0a3 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -358,7 +358,7 @@ struct usb_composite_dev { struct list_head configs; struct usb_composite_driver *driver; u8 next_string_id; - u8 manufacturer_override; + char *def_manufacturer; /* the gadget driver won't enable the data pullup * while the deactivation count is nonzero. -- cgit v0.10.2 From 721e2e91945bc2520d57d795dfe1b502ecec567c Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 6 Sep 2012 20:11:27 +0200 Subject: usb: gadget: libcomposite: move composite.c into libcomposite This moves composite.c into libcomposite and updates all gadgets. Finally! Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 4fec0e8..5c4a133 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -5,7 +5,8 @@ ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG obj-$(CONFIG_USB_GADGET) += udc-core.o obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o -libcomposite-y := usbstring.o config.o epautoconf.o gadget_chips.o +libcomposite-y := usbstring.o config.o epautoconf.o +libcomposite-y += gadget_chips.o composite.o obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o obj-$(CONFIG_USB_NET2272) += net2272.o obj-$(CONFIG_USB_NET2280) += net2280.o diff --git a/drivers/usb/gadget/acm_ms.c b/drivers/usb/gadget/acm_ms.c index d280f16..b0abc25 100644 --- a/drivers/usb/gadget/acm_ms.c +++ b/drivers/usb/gadget/acm_ms.c @@ -15,6 +15,7 @@ */ #include +#include #include "u_serial.h" @@ -40,7 +41,6 @@ * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ -#include "composite.c" #include "u_serial.c" #include "f_acm.c" #include "f_mass_storage.c" diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index 1f81e0f..1b9dee9 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c @@ -12,22 +12,13 @@ /* #define VERBOSE_DEBUG */ #include +#include #include #include "gadget_chips.h" #define DRIVER_DESC "Linux USB Audio Gadget" #define DRIVER_VERSION "Feb 2, 2012" -/*-------------------------------------------------------------------------*/ - -/* - * Kbuild is not very cooperative with respect to linking separately - * compiled library objects into one module. So for now we won't use - * separate compilation ... ensuring init/exit sections work to shrink - * the runtime footprint, and giving us at least some parts of what - * a "gcc --combine ... part1.c part2.c part3.c ... " build would. - */ -#include "composite.c" USB_GADGET_COMPOSITE_OPTIONS(); /* string IDs are assigned dynamically */ diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index 4e2060b..ba38d2a 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c @@ -43,7 +43,6 @@ USB_GADGET_COMPOSITE_OPTIONS(); * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ -#include "composite.c" #include "u_serial.c" #include "f_acm.c" #include "f_ecm.c" diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index c7066cd..27ac366 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -154,6 +154,7 @@ ep_found: } return 0; } +EXPORT_SYMBOL_GPL(config_ep_by_speed); /** * usb_add_function() - add a function to a configuration @@ -212,6 +213,7 @@ done: function->name, function, value); return value; } +EXPORT_SYMBOL_GPL(usb_add_function); /** * usb_function_deactivate - prevent function and gadget enumeration @@ -248,6 +250,7 @@ int usb_function_deactivate(struct usb_function *function) spin_unlock_irqrestore(&cdev->lock, flags); return status; } +EXPORT_SYMBOL_GPL(usb_function_deactivate); /** * usb_function_activate - allow function and gadget enumeration @@ -278,6 +281,7 @@ int usb_function_activate(struct usb_function *function) spin_unlock_irqrestore(&cdev->lock, flags); return status; } +EXPORT_SYMBOL_GPL(usb_function_activate); /** * usb_interface_id() - allocate an unused interface ID @@ -314,6 +318,7 @@ int usb_interface_id(struct usb_configuration *config, } return -ENODEV; } +EXPORT_SYMBOL_GPL(usb_interface_id); static int config_buf(struct usb_configuration *config, enum usb_device_speed speed, void *buf, u8 type) @@ -754,6 +759,7 @@ done: config->bConfigurationValue, status); return status; } +EXPORT_SYMBOL_GPL(usb_add_config); static void remove_config(struct usb_composite_dev *cdev, struct usb_configuration *config) @@ -947,6 +953,7 @@ int usb_string_id(struct usb_composite_dev *cdev) } return -ENODEV; } +EXPORT_SYMBOL_GPL(usb_string_id); /** * usb_string_ids() - allocate unused string IDs in batch @@ -978,6 +985,7 @@ int usb_string_ids_tab(struct usb_composite_dev *cdev, struct usb_string *str) return 0; } +EXPORT_SYMBOL_GPL(usb_string_ids_tab); /** * usb_string_ids_n() - allocate unused string IDs in batch @@ -1006,7 +1014,7 @@ int usb_string_ids_n(struct usb_composite_dev *c, unsigned n) c->next_string_id += n; return next + 1; } - +EXPORT_SYMBOL_GPL(usb_string_ids_n); /*-------------------------------------------------------------------------*/ @@ -1572,6 +1580,7 @@ int usb_composite_probe(struct usb_composite_driver *driver) return usb_gadget_probe_driver(gadget_driver); } +EXPORT_SYMBOL_GPL(usb_composite_probe); /** * usb_composite_unregister() - unregister a composite driver @@ -1584,6 +1593,7 @@ void usb_composite_unregister(struct usb_composite_driver *driver) { usb_gadget_unregister_driver(&driver->gadget_driver); } +EXPORT_SYMBOL_GPL(usb_composite_unregister); /** * usb_composite_setup_continue() - Continue with the control transfer @@ -1620,6 +1630,7 @@ void usb_composite_setup_continue(struct usb_composite_dev *cdev) spin_unlock_irqrestore(&cdev->lock, flags); } +EXPORT_SYMBOL_GPL(usb_composite_setup_continue); static char *composite_default_mfr(struct usb_gadget *gadget) { @@ -1672,3 +1683,4 @@ void usb_composite_overwrite_options(struct usb_composite_dev *cdev, dev_str[USB_GADGET_PRODUCT_IDX].s = covr->product; } } +EXPORT_SYMBOL_GPL(usb_composite_overwrite_options); diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index a5c2720..d7ec87e 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -100,8 +100,6 @@ static inline bool has_rndis(void) * the runtime footprint, and giving us at least some parts of what * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ -#include "composite.c" - #include "f_ecm.c" #include "f_subset.c" #ifdef USB_ETH_RNDIS diff --git a/drivers/usb/gadget/f_hid.c b/drivers/usb/gadget/f_hid.c index 77dbca0..511e527 100644 --- a/drivers/usb/gadget/f_hid.c +++ b/drivers/usb/gadget/f_hid.c @@ -17,6 +17,7 @@ #include #include #include +#include #include static int major, minors; diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 9e62c20..3953dd4 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c @@ -21,9 +21,6 @@ * the runtime footprint, and giving us at least some parts of what * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ - -#include "composite.c" - #if defined CONFIG_USB_FUNCTIONFS_ETH || defined CONFIG_USB_FUNCTIONFS_RNDIS # if defined USB_ETH_RNDIS # undef USB_ETH_RNDIS diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 59621ef..4181524 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -30,13 +30,13 @@ #include #include +#include #include #include #include #include "gadget_chips.h" -#include "composite.c" #include "f_midi.c" /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c index 0e2e357..5fa1bfa 100644 --- a/drivers/usb/gadget/hid.c +++ b/drivers/usb/gadget/hid.c @@ -15,6 +15,8 @@ #include #include #include +#include +#include #include "gadget_chips.h" #define DRIVER_DESC "HID Gadget" @@ -34,9 +36,6 @@ * the runtime footprint, and giving us at least some parts of what * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ - -#include "composite.c" - #include "f_hid.c" diff --git a/drivers/usb/gadget/mass_storage.c b/drivers/usb/gadget/mass_storage.c index 9eb2be6..080e577 100644 --- a/drivers/usb/gadget/mass_storage.c +++ b/drivers/usb/gadget/mass_storage.c @@ -30,6 +30,7 @@ #include #include +#include /*-------------------------------------------------------------------------*/ @@ -45,8 +46,6 @@ * the runtime footprint, and giving us at least some parts of what * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ - -#include "composite.c" #include "f_mass_storage.c" /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index 5bc5d96..9d2e75c 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -40,9 +40,6 @@ MODULE_LICENSE("GPL"); * the runtime footprint, and giving us at least some parts of what * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ - -#include "composite.c" - #include "f_mass_storage.c" #include "u_serial.c" diff --git a/drivers/usb/gadget/ncm.c b/drivers/usb/gadget/ncm.c index 343f3d3..b21ec26 100644 --- a/drivers/usb/gadget/ncm.c +++ b/drivers/usb/gadget/ncm.c @@ -20,6 +20,8 @@ /* #define VERBOSE_DEBUG */ #include +#include +#include #include "u_ether.h" @@ -34,8 +36,6 @@ * the runtime footprint, and giving us at least some parts of what * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ -#include "composite.c" - #include "f_ncm.c" #include "u_ether.c" diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index 465766e..ad0cc34 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c @@ -37,8 +37,6 @@ * the runtime footprint, and giving us at least some parts of what * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ -#include "composite.c" - #include "u_serial.c" #include "f_acm.c" #include "f_ecm.c" diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 9bd9942..e394050 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -37,22 +37,12 @@ #include #include +#include #include #include #include "gadget_chips.h" - -/* - * Kbuild is not very cooperative with respect to linking separately - * compiled library objects into one module. So for now we won't use - * separate compilation ... ensuring init/exit sections work to shrink - * the runtime footprint, and giving us at least some parts of what - * a "gcc --combine ... part1.c part2.c part3.c ... " build would. - */ -#include "composite.c" - -/*-------------------------------------------------------------------------*/ USB_GADGET_COMPOSITE_OPTIONS(); #define DRIVER_DESC "Printer Gadget" diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index bf12d55..f17d462 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -36,8 +36,6 @@ * the runtime footprint, and giving us at least some parts of what * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ -#include "composite.c" - #include "f_acm.c" #include "f_obex.c" #include "f_serial.c" diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c index b56d57d..eaa1005 100644 --- a/drivers/usb/gadget/tcm_usb_gadget.c +++ b/drivers/usb/gadget/tcm_usb_gadget.c @@ -25,8 +25,6 @@ #include #include -#include "composite.c" - #include "tcm_usb_gadget.h" USB_GADGET_COMPOSITE_OPTIONS(); diff --git a/drivers/usb/gadget/webcam.c b/drivers/usb/gadget/webcam.c index 0359119..69cf5c2 100644 --- a/drivers/usb/gadget/webcam.c +++ b/drivers/usb/gadget/webcam.c @@ -23,8 +23,6 @@ * the runtime footprint, and giving us at least some parts of what * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ -#include "composite.c" - #include "uvc_queue.c" #include "uvc_video.c" #include "uvc_v4l2.c" diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index a837f3a..0dabffa 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -57,8 +57,6 @@ * the runtime footprint, and giving us at least some parts of what * a "gcc --combine ... part1.c part2.c part3.c ... " build would. */ -#include "composite.c" - #include "f_sourcesink.c" #include "f_loopback.c" -- cgit v0.10.2 From d80c304bcacaf340efa29364ed0107f5c30378c8 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Thu, 6 Sep 2012 20:11:28 +0200 Subject: usb: gadget: libcomposite: move MODULE_VERSION to composite.c MODULE_VERSION and AUTHOR looks better in composite.c than in usbstrings.c so I move it there. I put David Brownell as the module Author as I belive he wrote most of it. Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 27ac366..cacb273 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1684,3 +1684,6 @@ void usb_composite_overwrite_options(struct usb_composite_dev *cdev, } } EXPORT_SYMBOL_GPL(usb_composite_overwrite_options); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("David Brownell"); diff --git a/drivers/usb/gadget/usbstring.c b/drivers/usb/gadget/usbstring.c index 24e9bbd..1f49fce 100644 --- a/drivers/usb/gadget/usbstring.c +++ b/drivers/usb/gadget/usbstring.c @@ -70,4 +70,3 @@ usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf) return buf [0]; } EXPORT_SYMBOL_GPL(usb_gadget_get_string); -MODULE_LICENSE("GPL"); -- cgit v0.10.2 From 162ca3ca613e02e115ec9c5273f94bd22dad0af2 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 7 Sep 2012 14:54:25 +0800 Subject: usb: gadget: at91_udc: move the dereference below the NULL test The dereference should be moved below the NULL test. spatch with a semantic match is used to found this. (http://coccinelle.lip6.fr/) Signed-off-by: Wei Yongjun Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index c9e66df..d95f6b0 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -469,7 +469,7 @@ static int at91_ep_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) { struct at91_ep *ep = container_of(_ep, struct at91_ep, ep); - struct at91_udc *udc = ep->udc; + struct at91_udc *udc; u16 maxpacket; u32 tmp; unsigned long flags; @@ -484,6 +484,7 @@ static int at91_ep_enable(struct usb_ep *_ep, return -EINVAL; } + udc = ep->udc; if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) { DBG("bogus device state\n"); return -ESHUTDOWN; -- cgit v0.10.2 From 9c6d196d5aa35e07482f23c3e37755e7a82140e0 Mon Sep 17 00:00:00 2001 From: Fabio Porcedda Date: Fri, 7 Sep 2012 15:27:42 +0200 Subject: usb: gadget: at91_udc: fix dt support Don't fail the initialization check for the platform_data if there is avaiable an associated device tree node. Signed-off-by: Fabio Porcedda Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index d95f6b0..af93128 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c @@ -1704,7 +1704,7 @@ static int __devinit at91udc_probe(struct platform_device *pdev) int retval; struct resource *res; - if (!dev->platform_data) { + if (!dev->platform_data && !pdev->dev.of_node) { /* small (so we copy it) but critical! */ DBG("missing platform_data\n"); return -ENODEV; -- cgit v0.10.2 From ed9cbda63d45638b69ce62412e3a3c7b00644835 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 10 Sep 2012 09:16:07 +0200 Subject: usb: gadget: remove usb_gadget_controller_number() The bcdDevice field is defined as |Device release number in binary-coded decimal in the USB 2.0 specification. We use this field to distinguish the UDCs from each other. In theory this could be used on the host side to apply certain quirks if the "special" UDC in combination with this gadget is used. This hasn't been done as far as I am aware. In practice it would be better to fix the UDC driver before shipping since a later release might not need this quirk anymore. There are some driver in tree (on the host side) which use the bcdDevice field to figure out special workarounds for a given firmware revision. This seems to make sense. Therefore this patch converts all gadgets (except a few) to use the kernel version instead a random 2 or 3 plus the UDC number. The few that don't report kernel's version are: - webcam This one reports always a version 0x10 so allow it to do so in future. - nokia This one reports always 0x211. The comment says that this gadget works only if the UDC supports altsettings so I added a check for this. - serial This one reports 0x2400 + UDC number. Since the gadget version is 2.4 this could make sense. Therefore bcdDevice is 0x2400 here. I also remove various gadget_is_ macros which are unused. The remaining few macros should be moved to feature / bug bitfield. Acked-by: Michal Nazarewicz Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 5c4a133..307be5f 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile @@ -6,7 +6,7 @@ ccflags-$(CONFIG_USB_GADGET_DEBUG) := -DDEBUG obj-$(CONFIG_USB_GADGET) += udc-core.o obj-$(CONFIG_USB_LIBCOMPOSITE) += libcomposite.o libcomposite-y := usbstring.o config.o epautoconf.o -libcomposite-y += gadget_chips.o composite.o +libcomposite-y += composite.o obj-$(CONFIG_USB_DUMMY_HCD) += dummy_hcd.o obj-$(CONFIG_USB_NET2272) += net2272.o obj-$(CONFIG_USB_NET2280) += net2280.o diff --git a/drivers/usb/gadget/acm_ms.c b/drivers/usb/gadget/acm_ms.c index b0abc25..5a7f289 100644 --- a/drivers/usb/gadget/acm_ms.c +++ b/drivers/usb/gadget/acm_ms.c @@ -148,7 +148,6 @@ static struct usb_configuration acm_ms_config_driver = { static int __init acm_ms_bind(struct usb_composite_dev *cdev) { - int gcnum; struct usb_gadget *gadget = cdev->gadget; int status; void *retp; @@ -165,18 +164,6 @@ static int __init acm_ms_bind(struct usb_composite_dev *cdev) goto fail0; } - /* set bcdDevice */ - gcnum = usb_gadget_controller_number(gadget); - if (gcnum >= 0) { - device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum); - } else { - WARNING(cdev, "controller '%s' not recognized; trying %s\n", - gadget->name, - acm_ms_config_driver.label); - device_desc.bcdDevice = - cpu_to_le16(0x0300 | 0x0099); - } - /* * Allocate string descriptor numbers ... note that string * contents can be overridden by the composite_dev glue. diff --git a/drivers/usb/gadget/audio.c b/drivers/usb/gadget/audio.c index 1b9dee9..231b0ef 100644 --- a/drivers/usb/gadget/audio.c +++ b/drivers/usb/gadget/audio.c @@ -135,20 +135,8 @@ static struct usb_configuration audio_config_driver = { static int __init audio_bind(struct usb_composite_dev *cdev) { - int gcnum; int status; - gcnum = usb_gadget_controller_number(cdev->gadget); - if (gcnum >= 0) - device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum); - else { - ERROR(cdev, "controller '%s' not recognized; trying %s\n", - cdev->gadget->name, - audio_config_driver.label); - device_desc.bcdDevice = - __constant_cpu_to_le16(0x0300 | 0x0099); - } - status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) goto fail; diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index ba38d2a..1e4bb77 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c @@ -143,7 +143,6 @@ static struct usb_configuration cdc_config_driver = { static int __init cdc_bind(struct usb_composite_dev *cdev) { - int gcnum; struct usb_gadget *gadget = cdev->gadget; int status; @@ -163,21 +162,6 @@ static int __init cdc_bind(struct usb_composite_dev *cdev) if (status < 0) goto fail0; - gcnum = usb_gadget_controller_number(gadget); - if (gcnum >= 0) - device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum); - else { - /* We assume that can_support_ecm() tells the truth; - * but if the controller isn't recognized at all then - * that assumption is a bit more likely to be wrong. - */ - WARNING(cdev, "controller '%s' not recognized; trying %s\n", - gadget->name, - cdc_config_driver.label); - device_desc.bcdDevice = - cpu_to_le16(0x0300 | 0x0099); - } - /* Allocate string descriptor numbers ... note that string * contents can be overridden by the composite_dev glue. */ diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index cacb273..957f973 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1389,6 +1389,8 @@ static void update_unchanged_dev_desc(struct usb_device_descriptor *new, new->idProduct = idProduct; if (bcdDevice) new->bcdDevice = bcdDevice; + else + new->bcdDevice = cpu_to_le16(get_default_bcdDevice()); if (iSerialNumber) new->iSerialNumber = iSerialNumber; if (iManufacturer) diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index d7ec87e..18c3f42 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -275,7 +275,6 @@ static struct usb_configuration eth_config_driver = { static int __init eth_bind(struct usb_composite_dev *cdev) { - int gcnum; struct usb_gadget *gadget = cdev->gadget; int status; @@ -310,22 +309,6 @@ static int __init eth_bind(struct usb_composite_dev *cdev) device_desc.bNumConfigurations = 2; } - gcnum = usb_gadget_controller_number(gadget); - if (gcnum >= 0) - device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum); - else { - /* We assume that can_support_ecm() tells the truth; - * but if the controller isn't recognized at all then - * that assumption is a bit more likely to be wrong. - */ - dev_warn(&gadget->dev, - "controller '%s' not recognized; trying %s\n", - gadget->name, - eth_config_driver.label); - device_desc.bcdDevice = - cpu_to_le16(0x0300 | 0x0099); - } - /* Allocate string descriptor numbers ... note that string * contents can be overridden by the composite_dev glue. */ diff --git a/drivers/usb/gadget/f_mass_storage.c b/drivers/usb/gadget/f_mass_storage.c index 1115096..3a7668b 100644 --- a/drivers/usb/gadget/f_mass_storage.c +++ b/drivers/usb/gadget/f_mass_storage.c @@ -348,7 +348,6 @@ struct fsg_config { const char *vendor_name; /* 8 characters or less */ const char *product_name; /* 16 characters or less */ - u16 release; char can_stall; }; @@ -2772,18 +2771,7 @@ buffhds_first_it: bh->next = common->buffhds; /* Prepare inquiryString */ - if (cfg->release != 0xffff) { - i = cfg->release; - } else { - i = usb_gadget_controller_number(gadget); - if (i >= 0) { - i = 0x0300 + i; - } else { - WARNING(common, "controller '%s' not recognized\n", - gadget->name); - i = 0x0399; - } - } + i = get_default_bcdDevice(); snprintf(common->inquiry_string, sizeof common->inquiry_string, "%-8s%-16s%04x", cfg->vendor_name ?: "Linux", /* Assume product name dependent on the first LUN */ @@ -3109,7 +3097,6 @@ fsg_config_from_params(struct fsg_config *cfg, /* Let MSF use defaults */ cfg->vendor_name = 0; cfg->product_name = 0; - cfg->release = 0xffff; cfg->ops = NULL; cfg->private_data = NULL; diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index ce362f7..3f7d640 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -251,6 +251,7 @@ #include #include +#include #include #include @@ -3198,7 +3199,6 @@ static void /* __init_or_exit */ fsg_unbind(struct usb_gadget *gadget) static int __init check_parameters(struct fsg_dev *fsg) { int prot; - int gcnum; /* Store the default values */ mod_data.transport_type = USB_PR_BULK; @@ -3213,16 +3213,8 @@ static int __init check_parameters(struct fsg_dev *fsg) if (gadget_is_at91(fsg->gadget)) mod_data.can_stall = 0; - if (mod_data.release == 0xffff) { // Parameter wasn't set - gcnum = usb_gadget_controller_number(fsg->gadget); - if (gcnum >= 0) - mod_data.release = 0x0300 + gcnum; - else { - WARNING(fsg, "controller '%s' not recognized\n", - fsg->gadget->name); - mod_data.release = 0x0399; - } - } + if (mod_data.release == 0xffff) + mod_data.release = get_default_bcdDevice(); prot = simple_strtol(mod_data.protocol_parm, NULL, 0); diff --git a/drivers/usb/gadget/gadget_chips.c b/drivers/usb/gadget/gadget_chips.c deleted file mode 100644 index 6387d43..0000000 --- a/drivers/usb/gadget/gadget_chips.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * USB device controllers have lots of quirks. Use these macros in - * gadget drivers or other code that needs to deal with them, and which - * autoconfigures instead of using early binding to the hardware. - * - * This SHOULD eventually work like the ARM mach_is_*() stuff, driven by - * some config file that gets updated as new hardware is supported. - * (And avoiding all runtime comparisons in typical one-choice configs!) - * - * NOTE: some of these controller drivers may not be available yet. - * Some are available on 2.4 kernels; several are available, but not - * yet pushed in the 2.6 mainline tree. - */ - -#include -#include - -#include "gadget_chips.h" - -/** - * usb_gadget_controller_number - support bcdDevice id convention - * @gadget: the controller being driven - * - * Return a 2-digit BCD value associated with the peripheral controller, - * suitable for use as part of a bcdDevice value, or a negative error code. - * - * NOTE: this convention is purely optional, and has no meaning in terms of - * any USB specification. If you want to use a different convention in your - * gadget driver firmware -- maybe a more formal revision ID -- feel free. - * - * Hosts see these bcdDevice numbers, and are allowed (but not encouraged!) - * to change their behavior accordingly. For example it might help avoiding - * some chip bug. - */ -int usb_gadget_controller_number(struct usb_gadget *gadget) -{ - if (gadget_is_net2280(gadget)) - return 0x01; - else if (gadget_is_dummy(gadget)) - return 0x02; - else if (gadget_is_pxa(gadget)) - return 0x03; - else if (gadget_is_goku(gadget)) - return 0x06; - else if (gadget_is_omap(gadget)) - return 0x08; - else if (gadget_is_pxa27x(gadget)) - return 0x11; - else if (gadget_is_s3c2410(gadget)) - return 0x12; - else if (gadget_is_at91(gadget)) - return 0x13; - else if (gadget_is_imx(gadget)) - return 0x14; - else if (gadget_is_musbhdrc(gadget)) - return 0x16; - else if (gadget_is_atmel_usba(gadget)) - return 0x18; - else if (gadget_is_fsl_usb2(gadget)) - return 0x19; - else if (gadget_is_amd5536udc(gadget)) - return 0x20; - else if (gadget_is_m66592(gadget)) - return 0x21; - else if (gadget_is_fsl_qe(gadget)) - return 0x22; - else if (gadget_is_ci13xxx_pci(gadget)) - return 0x23; - else if (gadget_is_langwell(gadget)) - return 0x24; - else if (gadget_is_r8a66597(gadget)) - return 0x25; - else if (gadget_is_s3c_hsotg(gadget)) - return 0x26; - else if (gadget_is_pch(gadget)) - return 0x27; - else if (gadget_is_ci13xxx_msm(gadget)) - return 0x28; - else if (gadget_is_renesas_usbhs(gadget)) - return 0x29; - else if (gadget_is_s3c_hsudc(gadget)) - return 0x30; - else if (gadget_is_net2272(gadget)) - return 0x31; - else if (gadget_is_dwc3(gadget)) - return 0x32; - else if (gadget_is_lpc32xx(gadget)) - return 0x33; - else if (gadget_is_bcm63xx(gadget)) - return 0x34; - - return -ENOENT; -} -EXPORT_SYMBOL_GPL(usb_gadget_controller_number); diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h index c7055cd..bcd04bc 100644 --- a/drivers/usb/gadget/gadget_chips.h +++ b/drivers/usb/gadget/gadget_chips.h @@ -27,35 +27,12 @@ * If you have forgotten the alphabetical order let VIM/EMACS * do that for you. */ -#define gadget_is_amd5536udc(g) (!strcmp("amd5536udc", (g)->name)) #define gadget_is_at91(g) (!strcmp("at91_udc", (g)->name)) -#define gadget_is_atmel_usba(g) (!strcmp("atmel_usba_udc", (g)->name)) -#define gadget_is_bcm63xx(g) (!strcmp("bcm63xx_udc", (g)->name)) -#define gadget_is_ci13xxx_msm(g) (!strcmp("ci13xxx_msm", (g)->name)) -#define gadget_is_ci13xxx_pci(g) (!strcmp("ci13xxx_pci", (g)->name)) -#define gadget_is_dummy(g) (!strcmp("dummy_udc", (g)->name)) -#define gadget_is_dwc3(g) (!strcmp("dwc3-gadget", (g)->name)) -#define gadget_is_fsl_qe(g) (!strcmp("fsl_qe_udc", (g)->name)) -#define gadget_is_fsl_usb2(g) (!strcmp("fsl-usb2-udc", (g)->name)) #define gadget_is_goku(g) (!strcmp("goku_udc", (g)->name)) -#define gadget_is_imx(g) (!strcmp("imx_udc", (g)->name)) -#define gadget_is_langwell(g) (!strcmp("langwell_udc", (g)->name)) -#define gadget_is_lpc32xx(g) (!strcmp("lpc32xx_udc", (g)->name)) -#define gadget_is_m66592(g) (!strcmp("m66592_udc", (g)->name)) #define gadget_is_musbhdrc(g) (!strcmp("musb-hdrc", (g)->name)) -#define gadget_is_net2272(g) (!strcmp("net2272", (g)->name)) #define gadget_is_net2280(g) (!strcmp("net2280", (g)->name)) -#define gadget_is_omap(g) (!strcmp("omap_udc", (g)->name)) -#define gadget_is_pch(g) (!strcmp("pch_udc", (g)->name)) #define gadget_is_pxa(g) (!strcmp("pxa25x_udc", (g)->name)) #define gadget_is_pxa27x(g) (!strcmp("pxa27x_udc", (g)->name)) -#define gadget_is_r8a66597(g) (!strcmp("r8a66597_udc", (g)->name)) -#define gadget_is_renesas_usbhs(g) (!strcmp("renesas_usbhs_udc", (g)->name)) -#define gadget_is_s3c2410(g) (!strcmp("s3c2410_udc", (g)->name)) -#define gadget_is_s3c_hsotg(g) (!strcmp("s3c-hsotg", (g)->name)) -#define gadget_is_s3c_hsudc(g) (!strcmp("s3c-hsudc", (g)->name)) - -int usb_gadget_controller_number(struct usb_gadget *gadget); /** * gadget_supports_altsettings - return true if altsettings work diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 4181524..881aab8 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -137,8 +137,7 @@ static int __init midi_bind_config(struct usb_configuration *c) static int __init midi_bind(struct usb_composite_dev *cdev) { - struct usb_gadget *gadget = cdev->gadget; - int gcnum, status; + int status; status = usb_string_ids_tab(cdev, strings_dev); if (status < 0) @@ -147,19 +146,6 @@ static int __init midi_bind(struct usb_composite_dev *cdev) device_desc.iProduct = strings_dev[USB_GADGET_PRODUCT_IDX].id; midi_config.iConfiguration = strings_dev[STRING_DESCRIPTION_IDX].id; - gcnum = usb_gadget_controller_number(gadget); - if (gcnum < 0) { - /* gmidi is so simple (no altsettings) that - * it SHOULD NOT have problems with bulk-capable hardware. - * so warn about unrecognized controllers, don't panic. - */ - pr_warning("%s: controller '%s' not recognized\n", - __func__, gadget->name); - device_desc.bcdDevice = cpu_to_le16(0x9999); - } else { - device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum); - } - status = usb_add_config(cdev, &midi_config, midi_bind_config); if (status < 0) return status; diff --git a/drivers/usb/gadget/hid.c b/drivers/usb/gadget/hid.c index 5fa1bfa..74130f6 100644 --- a/drivers/usb/gadget/hid.c +++ b/drivers/usb/gadget/hid.c @@ -143,7 +143,7 @@ static int __init hid_bind(struct usb_composite_dev *cdev) { struct usb_gadget *gadget = cdev->gadget; struct list_head *tmp; - int status, gcnum, funcs = 0; + int status, funcs = 0; list_for_each(tmp, &hidg_func_list) funcs++; @@ -156,12 +156,6 @@ static int __init hid_bind(struct usb_composite_dev *cdev) if (status < 0) return status; - gcnum = usb_gadget_controller_number(gadget); - if (gcnum >= 0) - device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum); - else - device_desc.bcdDevice = cpu_to_le16(0x0300 | 0x0099); - /* Allocate string descriptor numbers ... note that string * contents can be overridden by the composite_dev glue. */ diff --git a/drivers/usb/gadget/multi.c b/drivers/usb/gadget/multi.c index 9d2e75c..88472bf 100644 --- a/drivers/usb/gadget/multi.c +++ b/drivers/usb/gadget/multi.c @@ -247,7 +247,7 @@ static int cdc_config_register(struct usb_composite_dev *cdev) static int __ref multi_bind(struct usb_composite_dev *cdev) { struct usb_gadget *gadget = cdev->gadget; - int status, gcnum; + int status; if (!can_support_ecm(cdev->gadget)) { dev_err(&gadget->dev, "controller '%s' not usable\n", @@ -275,15 +275,6 @@ static int __ref multi_bind(struct usb_composite_dev *cdev) } } - /* set bcdDevice */ - gcnum = usb_gadget_controller_number(gadget); - if (gcnum >= 0) { - device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum); - } else { - WARNING(cdev, "controller '%s' not recognized\n", gadget->name); - device_desc.bcdDevice = cpu_to_le16(0x0300 | 0x0099); - } - /* allocate string IDs */ status = usb_string_ids_tab(cdev, strings_dev); if (unlikely(status < 0)) diff --git a/drivers/usb/gadget/ncm.c b/drivers/usb/gadget/ncm.c index b21ec26..a22ad9a 100644 --- a/drivers/usb/gadget/ncm.c +++ b/drivers/usb/gadget/ncm.c @@ -139,7 +139,6 @@ static struct usb_configuration ncm_config_driver = { static int __init gncm_bind(struct usb_composite_dev *cdev) { - int gcnum; struct usb_gadget *gadget = cdev->gadget; int status; @@ -148,22 +147,6 @@ static int __init gncm_bind(struct usb_composite_dev *cdev) if (status < 0) return status; - gcnum = usb_gadget_controller_number(gadget); - if (gcnum >= 0) - device_desc.bcdDevice = cpu_to_le16(0x0300 | gcnum); - else { - /* We assume that can_support_ecm() tells the truth; - * but if the controller isn't recognized at all then - * that assumption is a bit more likely to be wrong. - */ - dev_warn(&gadget->dev, - "controller '%s' not recognized; trying %s\n", - gadget->name, - ncm_config_driver.label); - device_desc.bcdDevice = - cpu_to_le16(0x0300 | 0x0099); - } - /* Allocate string descriptor numbers ... note that string * contents can be overridden by the composite_dev glue. */ diff --git a/drivers/usb/gadget/nokia.c b/drivers/usb/gadget/nokia.c index ad0cc34..661600a 100644 --- a/drivers/usb/gadget/nokia.c +++ b/drivers/usb/gadget/nokia.c @@ -84,6 +84,7 @@ static struct usb_device_descriptor device_desc = { .bDeviceClass = USB_CLASS_COMM, .idVendor = __constant_cpu_to_le16(NOKIA_VENDOR_ID), .idProduct = __constant_cpu_to_le16(NOKIA_PRODUCT_ID), + .bcdDevice = cpu_to_le16(NOKIA_VERSION_NUM), /* .iManufacturer = DYNAMIC */ /* .iProduct = DYNAMIC */ .bNumConfigurations = 1, @@ -145,7 +146,6 @@ static struct usb_configuration nokia_config_100ma_driver = { static int __init nokia_bind(struct usb_composite_dev *cdev) { - int gcnum; struct usb_gadget *gadget = cdev->gadget; int status; @@ -170,18 +170,8 @@ static int __init nokia_bind(struct usb_composite_dev *cdev) nokia_config_500ma_driver.iConfiguration = status; nokia_config_100ma_driver.iConfiguration = status; - /* set up other descriptors */ - gcnum = usb_gadget_controller_number(gadget); - if (gcnum >= 0) - device_desc.bcdDevice = cpu_to_le16(NOKIA_VERSION_NUM); - else { - /* this should only work with hw that supports altsettings - * and several endpoints, anything else, panic. - */ - pr_err("nokia_bind: controller '%s' not recognized\n", - gadget->name); + if (!gadget_supports_altsettings(gadget)) goto err_usb; - } /* finally register the configuration */ status = usb_add_config(cdev, &nokia_config_500ma_driver, diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index e394050..e156e3f 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -1101,7 +1101,6 @@ static int __init printer_bind_config(struct usb_configuration *c) struct usb_gadget *gadget = c->cdev->gadget; struct printer_dev *dev; int status = -ENOMEM; - int gcnum; size_t len; u32 i; struct usb_request *req; @@ -1143,16 +1142,6 @@ static int __init printer_bind_config(struct usb_configuration *c) goto fail; } - gcnum = usb_gadget_controller_number(gadget); - if (gcnum >= 0) { - device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum); - } else { - dev_warn(&gadget->dev, "controller '%s' not recognized\n", - gadget->name); - /* unrecognized, but safe unless bulk is REALLY quirky */ - device_desc.bcdDevice = - cpu_to_le16(0xFFFF); - } if (iPNPstring) strlcpy(&pnp_string[2], iPNPstring, (sizeof pnp_string)-2); diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index f17d462..9420673 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -86,7 +86,7 @@ static struct usb_device_descriptor device_desc = { /* .bMaxPacketSize0 = f(hardware) */ .idVendor = cpu_to_le16(GS_VENDOR_ID), /* .idProduct = f(use_acm) */ - /* .bcdDevice = f(hardware) */ + .bcdDevice = cpu_to_le16(GS_VERSION_NUM << 16), /* .iManufacturer = DYNAMIC */ /* .iProduct = DYNAMIC */ .bNumConfigurations = 1, @@ -154,8 +154,6 @@ static struct usb_configuration serial_config_driver = { static int __init gs_bind(struct usb_composite_dev *cdev) { - int gcnum; - struct usb_gadget *gadget = cdev->gadget; int status; status = gserial_setup(cdev->gadget, n_ports); @@ -174,24 +172,6 @@ static int __init gs_bind(struct usb_composite_dev *cdev) status = strings_dev[STRING_DESCRIPTION_IDX].id; serial_config_driver.iConfiguration = status; - /* set up other descriptors */ - gcnum = usb_gadget_controller_number(gadget); - if (gcnum >= 0) - device_desc.bcdDevice = cpu_to_le16(GS_VERSION_NUM | gcnum); - else { - /* this is so simple (for now, no altsettings) that it - * SHOULD NOT have problems with bulk-capable hardware. - * so warn about unrcognized controllers -- don't panic. - * - * things like configuration and altsetting numbering - * can need hardware-specific attention though. - */ - pr_warning("gs_bind: controller '%s' not recognized\n", - gadget->name); - device_desc.bcdDevice = - cpu_to_le16(GS_VERSION_NUM | 0x0099); - } - if (gadget_is_otg(cdev->gadget)) { serial_config_driver.descriptors = otg_desc; serial_config_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 0dabffa..6bf4c06 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -253,8 +253,6 @@ static void zero_resume(struct usb_composite_dev *cdev) static int __init zero_bind(struct usb_composite_dev *cdev) { - int gcnum; - struct usb_gadget *gadget = cdev->gadget; int status; /* Allocate string descriptor numbers ... note that string @@ -281,21 +279,6 @@ static int __init zero_bind(struct usb_composite_dev *cdev) loopback_add(cdev, autoresume != 0); } - gcnum = usb_gadget_controller_number(gadget); - if (gcnum >= 0) - device_desc.bcdDevice = cpu_to_le16(0x0200 + gcnum); - else { - /* gadget zero is so simple (for now, no altsettings) that - * it SHOULD NOT have problems with bulk-capable hardware. - * so just warn about unrcognized controllers -- don't panic. - * - * things like configuration and altsetting numbering - * can need hardware-specific attention though. - */ - pr_warning("%s: controller '%s' not recognized\n", - longname, gadget->name); - device_desc.bcdDevice = cpu_to_le16(0x9999); - } usb_composite_overwrite_options(cdev, &coverwrite); INFO(cdev, "%s, version: " DRIVER_VERSION "\n", longname); diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h index 65ae0a3..f8dda06 100644 --- a/include/linux/usb/composite.h +++ b/include/linux/usb/composite.h @@ -34,6 +34,8 @@ * the composite model the host can use both functions at the same time. */ +#include +#include #include #include @@ -418,6 +420,15 @@ struct usb_composite_overwrite { void usb_composite_overwrite_options(struct usb_composite_dev *cdev, struct usb_composite_overwrite *covr); +static inline u16 get_default_bcdDevice(void) +{ + u16 bcdDevice; + + bcdDevice = bin2bcd((LINUX_VERSION_CODE >> 16 & 0xff)) << 8; + bcdDevice |= bin2bcd((LINUX_VERSION_CODE >> 8 & 0xff)); + return bcdDevice; +} + /* messaging utils */ #define DBG(d, fmt, args...) \ dev_dbg(&(d)->gadget->dev , fmt , ## args) -- cgit v0.10.2 From 9830317a3f97afc358949ffa87529ee9da49bb44 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 10 Sep 2012 16:30:50 +0200 Subject: usb: gadget: add module.h to u_ether.c Spotted by Fengguang Wu: |In file included from drivers/usb/gadget/ether.c:110:0: |drivers/usb/gadget/u_ether.c:87:21: error: expected ')' before 'uint' |drivers/usb/gadget/u_ether.c:88:25: error: expected ')' before string constant This is because u_ether.c relied on having module.h included somewhere. This isn't the case since composite.c is no longer included. Reported-by: Fengguang Wu Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/u_ether.c b/drivers/usb/gadget/u_ether.c index 1154a99..41b17d1 100644 --- a/drivers/usb/gadget/u_ether.c +++ b/drivers/usb/gadget/u_ether.c @@ -14,6 +14,7 @@ /* #define VERBOSE_DEBUG */ #include +#include #include #include #include -- cgit v0.10.2 From 58add6ca84c4815feef45008c41274b6df41ede8 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 10 Sep 2012 12:42:31 +0800 Subject: usb: otg: move the dereference below the NULL test The dereference should be moved below the NULL test. spatch with a semantic match is used to found this. (http://coccinelle.lip6.fr/) Signed-off-by: Wei Yongjun Signed-off-by: Felipe Balbi diff --git a/drivers/usb/otg/fsl_otg.c b/drivers/usb/otg/fsl_otg.c index 23c798c..c19d1d7 100644 --- a/drivers/usb/otg/fsl_otg.c +++ b/drivers/usb/otg/fsl_otg.c @@ -544,9 +544,13 @@ int fsl_otg_start_gadget(struct otg_fsm *fsm, int on) */ static int fsl_otg_set_host(struct usb_otg *otg, struct usb_bus *host) { - struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy); + struct fsl_otg *otg_dev; + + if (!otg) + return -ENODEV; - if (!otg || otg_dev != fsl_otg_dev) + otg_dev = container_of(otg->phy, struct fsl_otg, phy); + if (otg_dev != fsl_otg_dev) return -ENODEV; otg->host = host; @@ -590,12 +594,15 @@ static int fsl_otg_set_host(struct usb_otg *otg, struct usb_bus *host) static int fsl_otg_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) { - struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy); + struct fsl_otg *otg_dev; + if (!otg) + return -ENODEV; + + otg_dev = container_of(otg->phy, struct fsl_otg, phy); VDBG("otg_dev 0x%x\n", (int)otg_dev); VDBG("fsl_otg_dev 0x%x\n", (int)fsl_otg_dev); - - if (!otg || otg_dev != fsl_otg_dev) + if (otg_dev != fsl_otg_dev) return -ENODEV; if (!gadget) { @@ -660,10 +667,13 @@ static void fsl_otg_event(struct work_struct *work) /* B-device start SRP */ static int fsl_otg_start_srp(struct usb_otg *otg) { - struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy); + struct fsl_otg *otg_dev; + + if (!otg || otg->phy->state != OTG_STATE_B_IDLE) + return -ENODEV; - if (!otg || otg_dev != fsl_otg_dev - || otg->phy->state != OTG_STATE_B_IDLE) + otg_dev = container_of(otg->phy, struct fsl_otg, phy); + if (otg_dev != fsl_otg_dev) return -ENODEV; otg_dev->fsm.b_bus_req = 1; @@ -675,9 +685,13 @@ static int fsl_otg_start_srp(struct usb_otg *otg) /* A_host suspend will call this function to start hnp */ static int fsl_otg_start_hnp(struct usb_otg *otg) { - struct fsl_otg *otg_dev = container_of(otg->phy, struct fsl_otg, phy); + struct fsl_otg *otg_dev; + + if (!otg) + return -ENODEV; - if (!otg || otg_dev != fsl_otg_dev) + otg_dev = container_of(otg->phy, struct fsl_otg, phy); + if (otg_dev != fsl_otg_dev) return -ENODEV; DBG("start_hnp...n"); -- cgit v0.10.2 From e3ec3eb79481d23b7d371b6e9567e2b6972efc92 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 19 Jul 2012 13:50:44 +0300 Subject: usb: dwc3: pci: add nop transceiver support We will be adding support for transceivers on dwc3 driver but not all boards have controllable transceivers. For those which don't provide controllable transceivers we will register nop transceivers. Signed-off-by: Felipe Balbi diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index a9ca9ad..94f550e 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -42,6 +42,9 @@ #include #include +#include +#include + #include "core.h" /* FIXME define these in */ @@ -51,8 +54,64 @@ struct dwc3_pci { struct device *dev; struct platform_device *dwc3; + struct platform_device *usb2_phy; + struct platform_device *usb3_phy; }; +static int __devinit dwc3_pci_register_phys(struct dwc3_pci *glue) +{ + struct nop_usb_xceiv_platform_data pdata; + struct platform_device *pdev; + int ret; + + memset(&pdata, 0x00, sizeof(pdata)); + + pdev = platform_device_alloc("nop_usb_xceiv", 0); + if (!pdev) + return -ENOMEM; + + glue->usb2_phy = pdev; + pdata.type = USB_PHY_TYPE_USB2; + + ret = platform_device_add_data(glue->usb2_phy, &pdata, sizeof(pdata)); + if (ret) + goto err1; + + pdev = platform_device_alloc("nop_usb_xceiv", 1); + if (!pdev) { + ret = -ENOMEM; + goto err1; + } + + glue->usb3_phy = pdev; + pdata.type = USB_PHY_TYPE_USB3; + + ret = platform_device_add_data(glue->usb3_phy, &pdata, sizeof(pdata)); + if (ret) + goto err2; + + ret = platform_device_add(glue->usb2_phy); + if (ret) + goto err2; + + ret = platform_device_add(glue->usb3_phy); + if (ret) + goto err3; + + return 0; + +err3: + platform_device_del(glue->usb2_phy); + +err2: + platform_device_put(glue->usb3_phy); + +err1: + platform_device_put(glue->usb2_phy); + + return ret; +} + static int __devinit dwc3_pci_probe(struct pci_dev *pci, const struct pci_device_id *id) { @@ -80,6 +139,12 @@ static int __devinit dwc3_pci_probe(struct pci_dev *pci, pci_set_power_state(pci, PCI_D0); pci_set_master(pci); + ret = dwc3_pci_register_phys(glue); + if (ret) { + dev_err(dev, "couldn't register PHYs\n"); + return ret; + } + devid = dwc3_get_device_id(); if (devid < 0) { ret = -ENOMEM; @@ -144,6 +209,8 @@ static void __devexit dwc3_pci_remove(struct pci_dev *pci) { struct dwc3_pci *glue = pci_get_drvdata(pci); + platform_device_unregister(glue->usb2_phy); + platform_device_unregister(glue->usb3_phy); dwc3_put_device_id(glue->dwc3->id); platform_device_unregister(glue->dwc3); pci_set_drvdata(pci, NULL); -- cgit v0.10.2 From a418cc4ea552884e9f2aa875aaa0afa1f0ffe07d Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 19 Jul 2012 13:56:07 +0300 Subject: usb: dwc3: omap: add nop transceiver support We will be adding support for transceivers on dwc3 driver but not all boards have controllable transceivers. For those which don't provide controllable transceivers we will register nop transceivers. Note that once OMAP's transceiver drivers reach mainline, this glue layer will change accordingly. Signed-off-by: Felipe Balbi diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 479dc04..ee57a10 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c @@ -48,6 +48,9 @@ #include #include +#include +#include + #include "core.h" /* @@ -131,6 +134,8 @@ struct dwc3_omap { spinlock_t lock; struct platform_device *dwc3; + struct platform_device *usb2_phy; + struct platform_device *usb3_phy; struct device *dev; int irq; @@ -152,6 +157,59 @@ static inline void dwc3_omap_writel(void __iomem *base, u32 offset, u32 value) writel(value, base + offset); } +static int __devinit dwc3_omap_register_phys(struct dwc3_omap *omap) +{ + struct nop_usb_xceiv_platform_data pdata; + struct platform_device *pdev; + int ret; + + memset(&pdata, 0x00, sizeof(pdata)); + + pdev = platform_device_alloc("nop_usb_xceiv", 0); + if (!pdev) + return -ENOMEM; + + omap->usb2_phy = pdev; + pdata.type = USB_PHY_TYPE_USB2; + + ret = platform_device_add_data(omap->usb2_phy, &pdata, sizeof(pdata)); + if (ret) + goto err1; + + pdev = platform_device_alloc("nop_usb_xceiv", 1); + if (!pdev) { + ret = -ENOMEM; + goto err1; + } + + omap->usb3_phy = pdev; + pdata.type = USB_PHY_TYPE_USB3; + + ret = platform_device_add_data(omap->usb3_phy, &pdata, sizeof(pdata)); + if (ret) + goto err2; + + ret = platform_device_add(omap->usb2_phy); + if (ret) + goto err2; + + ret = platform_device_add(omap->usb3_phy); + if (ret) + goto err3; + + return 0; + +err3: + platform_device_del(omap->usb2_phy); + +err2: + platform_device_put(omap->usb3_phy); + +err1: + platform_device_put(omap->usb2_phy); + + return ret; +} static irqreturn_t dwc3_omap_interrupt(int irq, void *_omap) { @@ -251,6 +309,12 @@ static int __devinit dwc3_omap_probe(struct platform_device *pdev) return -ENOMEM; } + ret = dwc3_omap_register_phys(omap); + if (ret) { + dev_err(dev, "couldn't register PHYs\n"); + return ret; + } + devid = dwc3_get_device_id(); if (devid < 0) return -ENODEV; @@ -371,6 +435,8 @@ static int __devexit dwc3_omap_remove(struct platform_device *pdev) struct dwc3_omap *omap = platform_get_drvdata(pdev); platform_device_unregister(omap->dwc3); + platform_device_unregister(omap->usb2_phy); + platform_device_unregister(omap->usb3_phy); dwc3_put_device_id(omap->dwc3->id); -- cgit v0.10.2 From d720f057fda4bae91a5108a11587374b9e396c6a Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 19 Jul 2012 14:01:10 +0300 Subject: usb: dwc3: exynos: add nop transceiver support We will be adding support for transceivers on dwc3 driver but not all boards have controllable transceivers. For those which don't provide controllable transceivers we will register nop transceivers. Signed-off-by: Felipe Balbi diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c index b8f0038..ca65978 100644 --- a/drivers/usb/dwc3/dwc3-exynos.c +++ b/drivers/usb/dwc3/dwc3-exynos.c @@ -19,16 +19,74 @@ #include #include #include +#include +#include #include "core.h" struct dwc3_exynos { struct platform_device *dwc3; + struct platform_device *usb2_phy; + struct platform_device *usb3_phy; struct device *dev; struct clk *clk; }; +static int __devinit dwc3_exynos_register_phys(struct dwc3_exynos *exynos) +{ + struct nop_usb_xceiv_platform_data pdata; + struct platform_device *pdev; + int ret; + + memset(&pdata, 0x00, sizeof(pdata)); + + pdev = platform_device_alloc("nop_usb_xceiv", 0); + if (!pdev) + return -ENOMEM; + + exynos->usb2_phy = pdev; + pdata.type = USB_PHY_TYPE_USB2; + + ret = platform_device_add_data(exynos->usb2_phy, &pdata, sizeof(pdata)); + if (ret) + goto err1; + + pdev = platform_device_alloc("nop_usb_xceiv", 1); + if (!pdev) { + ret = -ENOMEM; + goto err1; + } + + exynos->usb3_phy = pdev; + pdata.type = USB_PHY_TYPE_USB3; + + ret = platform_device_add_data(exynos->usb3_phy, &pdata, sizeof(pdata)); + if (ret) + goto err2; + + ret = platform_device_add(exynos->usb2_phy); + if (ret) + goto err2; + + ret = platform_device_add(exynos->usb3_phy); + if (ret) + goto err3; + + return 0; + +err3: + platform_device_del(exynos->usb2_phy); + +err2: + platform_device_put(exynos->usb3_phy); + +err1: + platform_device_put(exynos->usb2_phy); + + return ret; +} + static int __devinit dwc3_exynos_probe(struct platform_device *pdev) { struct dwc3_exynos_data *pdata = pdev->dev.platform_data; @@ -51,6 +109,12 @@ static int __devinit dwc3_exynos_probe(struct platform_device *pdev) if (devid < 0) goto err1; + ret = dwc3_exynos_register_phys(exynos); + if (ret) { + dev_err(&pdev->dev, "couldn't register PHYs\n"); + goto err1; + } + dwc3 = platform_device_alloc("dwc3", devid); if (!dwc3) { dev_err(&pdev->dev, "couldn't allocate dwc3 device\n"); @@ -120,6 +184,8 @@ static int __devexit dwc3_exynos_remove(struct platform_device *pdev) struct dwc3_exynos_data *pdata = pdev->dev.platform_data; platform_device_unregister(exynos->dwc3); + platform_device_unregister(exynos->usb2_phy); + platform_device_unregister(exynos->usb3_phy); dwc3_put_device_id(exynos->dwc3->id); -- cgit v0.10.2 From 51e1e7bcef53e6a91cfffff0145ab315def61f61 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 19 Jul 2012 14:09:48 +0300 Subject: usb: dwc3: add basic PHY support this will let us control PHYs on platforms which need them. Signed-off-by: Felipe Balbi diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index c34452a..79a24fa 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c @@ -50,6 +50,7 @@ #include #include +#include #include #include @@ -136,6 +137,8 @@ static void dwc3_core_soft_reset(struct dwc3 *dwc) reg |= DWC3_GUSB2PHYCFG_PHYSOFTRST; dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg); + usb_phy_init(dwc->usb2_phy); + usb_phy_init(dwc->usb3_phy); mdelay(100); /* Clear USB3 PHY reset */ @@ -465,6 +468,18 @@ static int __devinit dwc3_probe(struct platform_device *pdev) return -ENOMEM; } + dwc->usb2_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB2); + if (IS_ERR_OR_NULL(dwc->usb2_phy)) { + dev_err(dev, "no usb2 phy configured\n"); + return -EPROBE_DEFER; + } + + dwc->usb3_phy = devm_usb_get_phy(dev, USB_PHY_TYPE_USB3); + if (IS_ERR_OR_NULL(dwc->usb3_phy)) { + dev_err(dev, "no usb3 phy configured\n"); + return -EPROBE_DEFER; + } + spin_lock_init(&dwc->lock); platform_set_drvdata(pdev, dwc); diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 151eca8..dbc5713 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -624,6 +624,8 @@ struct dwc3_scratchpad_array { * @maximum_speed: maximum speed requested (mainly for testing purposes) * @revision: revision register contents * @mode: mode of operation + * @usb2_phy: pointer to USB2 PHY + * @usb3_phy: pointer to USB3 PHY * @is_selfpowered: true when we are selfpowered * @three_stage_setup: set if we perform a three phase setup * @ep0_bounced: true when we used bounce buffer @@ -667,6 +669,9 @@ struct dwc3 { struct usb_gadget gadget; struct usb_gadget_driver *gadget_driver; + struct usb_phy *usb2_phy; + struct usb_phy *usb3_phy; + void __iomem *regs; size_t regs_size; -- cgit v0.10.2 From 363366cf61c544ea476f3d220f43a95cb03014f5 Mon Sep 17 00:00:00 2001 From: Mike Thompson Date: Thu, 30 Aug 2012 18:26:25 -0300 Subject: usb: otg: mxs-phy: Fix mx23 operation Currently mx23 fails to enumerate a USB device: [ 1.300000] hub 1-0:1.0: unable to enumerate USB device on port 1 [ 1.520000] hub 1-0:1.0: unable to enumerate USB device on port 1 [ 1.740000] hub 1-0:1.0: unable to enumerate USB device on port 1 [ 1.960000] hub 1-0:1.0: unable to enumerate USB device on port 1 [ 2.180000] hub 1-0:1.0: unable to enumerate USB device on port 1 Use a kernel workqueue to asynchronously delay the setting of ENHOSTDISCONDETECT bit until after higher level hub connect/reset processing is complete. Prematurely setting the bit prevents the connection processing from completing and not setting it prevents disconnect from being detected. No delay is needed for clearing of ENHOSTDISCONDETECT. Successfully tested on mx23-olinuxino (micro, mini and maxi variants) and mx28evk. Cc: stable@vger.kernel.org # v3.6 Signed-off-by: Mike Thompson Signed-off-by: Fabio Estevam Signed-off-by: Felipe Balbi diff --git a/drivers/usb/otg/mxs-phy.c b/drivers/usb/otg/mxs-phy.c index c1a67cb..88db976 100644 --- a/drivers/usb/otg/mxs-phy.c +++ b/drivers/usb/otg/mxs-phy.c @@ -20,6 +20,7 @@ #include #include #include +#include #define DRIVER_NAME "mxs_phy" @@ -34,9 +35,16 @@ #define BM_USBPHY_CTRL_ENUTMILEVEL2 BIT(14) #define BM_USBPHY_CTRL_ENHOSTDISCONDETECT BIT(1) +/* + * Amount of delay in miliseconds to safely enable ENHOSTDISCONDETECT bit + * so that connection and reset processing can be completed for the root hub. + */ +#define MXY_PHY_ENHOSTDISCONDETECT_DELAY 250 + struct mxs_phy { struct usb_phy phy; struct clk *clk; + struct delayed_work enhostdiscondetect_work; }; #define to_mxs_phy(p) container_of((p), struct mxs_phy, phy) @@ -62,6 +70,7 @@ static int mxs_phy_init(struct usb_phy *phy) clk_prepare_enable(mxs_phy->clk); mxs_phy_hw_init(mxs_phy); + INIT_DELAYED_WORK(&mxs_phy->enhostdiscondetect_work, NULL); return 0; } @@ -76,13 +85,34 @@ static void mxs_phy_shutdown(struct usb_phy *phy) clk_disable_unprepare(mxs_phy->clk); } +static void mxs_phy_enhostdiscondetect_delay(struct work_struct *ws) +{ + struct mxs_phy *mxs_phy = container_of(ws, struct mxs_phy, + enhostdiscondetect_work.work); + + /* Enable HOSTDISCONDETECT after delay. */ + dev_dbg(mxs_phy->phy.dev, "Setting ENHOSTDISCONDETECT\n"); + writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, + mxs_phy->phy.io_priv + HW_USBPHY_CTRL_SET); +} + static int mxs_phy_on_connect(struct usb_phy *phy, int port) { + struct mxs_phy *mxs_phy = to_mxs_phy(phy); + dev_dbg(phy->dev, "Connect on port %d\n", port); - mxs_phy_hw_init(to_mxs_phy(phy)); - writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, - phy->io_priv + HW_USBPHY_CTRL_SET); + mxs_phy_hw_init(mxs_phy); + + /* + * Delay enabling ENHOSTDISCONDETECT so that connection and + * reset processing can be completed for the root hub. + */ + dev_dbg(phy->dev, "Delaying setting ENHOSTDISCONDETECT\n"); + PREPARE_DELAYED_WORK(&mxs_phy->enhostdiscondetect_work, + mxs_phy_enhostdiscondetect_delay); + schedule_delayed_work(&mxs_phy->enhostdiscondetect_work, + msecs_to_jiffies(MXY_PHY_ENHOSTDISCONDETECT_DELAY)); return 0; } @@ -91,6 +121,8 @@ static int mxs_phy_on_disconnect(struct usb_phy *phy, int port) { dev_dbg(phy->dev, "Disconnect on port %d\n", port); + /* No need to delay before clearing ENHOSTDISCONDETECT. */ + dev_dbg(phy->dev, "Clearing ENHOSTDISCONDETECT\n"); writel_relaxed(BM_USBPHY_CTRL_ENHOSTDISCONDETECT, phy->io_priv + HW_USBPHY_CTRL_CLR); -- cgit v0.10.2 From 5c4d46eb89fe99011a02048533857345d9e8b506 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 10 Sep 2012 19:06:44 +0200 Subject: usb: gadget serial: don't shift bcd version left by 16 Fengguang Wu reported: |drivers/usb/gadget/serial.c:89:22: sparse: cast truncates bits from |constant value (24000000 becomes 0) I obviously let the version number shift away. Since the version is a 16bit number it can be applied as it. Cc: fengguang.wu@intel.com Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Felipe Balbi diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 9420673..44752f5 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -86,7 +86,7 @@ static struct usb_device_descriptor device_desc = { /* .bMaxPacketSize0 = f(hardware) */ .idVendor = cpu_to_le16(GS_VENDOR_ID), /* .idProduct = f(use_acm) */ - .bcdDevice = cpu_to_le16(GS_VERSION_NUM << 16), + .bcdDevice = cpu_to_le16(GS_VERSION_NUM), /* .iManufacturer = DYNAMIC */ /* .iProduct = DYNAMIC */ .bNumConfigurations = 1, -- cgit v0.10.2 From 0837e7e5270bd5547ba5763f11611dc43f677b3d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 8 Sep 2012 20:02:05 +0200 Subject: usbfs: Add a new disconnect-and-claim ioctl (v2) Apps which deal with devices which also have a kernel driver, need to do the following: 1) Check which driver is attached, so as to not detach the wrong driver (ie detaching usbfs while another instance of the app is using the device) 2) Detach the kernel driver 3) Claim the interface Where moving from one step to the next for both 1-2 and 2-3 consists of a (small) race window. So currently such apps are racy and people just live with it. This patch adds a new ioctl which makes it possible for apps to do this in a race free manner. For flexibility apps can choose to: 1) Specify the driver to disconnect 2) Specify to disconnect any driver except for the one named by the app 3) Disconnect any driver Note that if there is no driver attached, the ioctl will just act like the regular claim-interface ioctl, this is by design, as returning an error for this condition would open a new bag of race-conditions. Changes in v2: -Fix indentation of if blocks where the condition spans multiple lines Signed-off-by: Hans de Goede Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index ebb8a9d..e0356cb 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -1928,6 +1928,38 @@ static int proc_get_capabilities(struct dev_state *ps, void __user *arg) return 0; } +static int proc_disconnect_claim(struct dev_state *ps, void __user *arg) +{ + struct usbdevfs_disconnect_claim dc; + struct usb_interface *intf; + + if (copy_from_user(&dc, arg, sizeof(dc))) + return -EFAULT; + + intf = usb_ifnum_to_if(ps->dev, dc.interface); + if (!intf) + return -EINVAL; + + if (intf->dev.driver) { + struct usb_driver *driver = to_usb_driver(intf->dev.driver); + + if ((dc.flags & USBDEVFS_DISCONNECT_CLAIM_IF_DRIVER) && + strncmp(dc.driver, intf->dev.driver->name, + sizeof(dc.driver)) != 0) + return -EBUSY; + + if ((dc.flags & USBDEVFS_DISCONNECT_CLAIM_EXCEPT_DRIVER) && + strncmp(dc.driver, intf->dev.driver->name, + sizeof(dc.driver)) == 0) + return -EBUSY; + + dev_dbg(&intf->dev, "disconnect by usbfs\n"); + usb_driver_release_interface(driver, intf); + } + + return claimintf(ps, dc.interface); +} + /* * NOTE: All requests here that have interface numbers as parameters * are assuming that somehow the configuration has been prevented from @@ -2101,6 +2133,9 @@ static long usbdev_do_ioctl(struct file *file, unsigned int cmd, case USBDEVFS_GET_CAPABILITIES: ret = proc_get_capabilities(ps, p); break; + case USBDEVFS_DISCONNECT_CLAIM: + ret = proc_disconnect_claim(ps, p); + break; } usb_unlock_device(dev); if (ret >= 0) diff --git a/include/linux/usbdevice_fs.h b/include/linux/usbdevice_fs.h index 3b74666..4abe28e 100644 --- a/include/linux/usbdevice_fs.h +++ b/include/linux/usbdevice_fs.h @@ -131,6 +131,19 @@ struct usbdevfs_hub_portinfo { #define USBDEVFS_CAP_NO_PACKET_SIZE_LIM 0x04 #define USBDEVFS_CAP_BULK_SCATTER_GATHER 0x08 +/* USBDEVFS_DISCONNECT_CLAIM flags & struct */ + +/* disconnect-and-claim if the driver matches the driver field */ +#define USBDEVFS_DISCONNECT_CLAIM_IF_DRIVER 0x01 +/* disconnect-and-claim except when the driver matches the driver field */ +#define USBDEVFS_DISCONNECT_CLAIM_EXCEPT_DRIVER 0x02 + +struct usbdevfs_disconnect_claim { + unsigned int interface; + unsigned int flags; + char driver[USBDEVFS_MAXDRIVERNAME + 1]; +}; + #ifdef __KERNEL__ #ifdef CONFIG_COMPAT #include @@ -211,5 +224,6 @@ struct usbdevfs_ioctl32 { #define USBDEVFS_CLAIM_PORT _IOR('U', 24, unsigned int) #define USBDEVFS_RELEASE_PORT _IOR('U', 25, unsigned int) #define USBDEVFS_GET_CAPABILITIES _IOR('U', 26, __u32) +#define USBDEVFS_DISCONNECT_CLAIM _IOR('U', 27, struct usbdevfs_disconnect_claim) #endif /* _LINUX_USBDEVICE_FS_H */ -- cgit v0.10.2 From 8a424bf40d772fedacc91862ecc86f10541fabb3 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Mon, 10 Sep 2012 09:16:39 +0200 Subject: tools/usb: remove last USBFS user In commit fb28d58b ("USB: remove CONFIG_USB_DEVICEFS") USBFS got removed. Since it is gone we can stop using it in testusb and try udev nodes right away. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Greg Kroah-Hartman diff --git a/tools/usb/testusb.c b/tools/usb/testusb.c index b0adb27..68d0734 100644 --- a/tools/usb/testusb.c +++ b/tools/usb/testusb.c @@ -253,9 +253,6 @@ static int find_testdev(const char *name, const struct stat *sb, int flag) if (flag != FTW_F) return 0; - /* ignore /proc/bus/usb/{devices,drivers} */ - if (strrchr(name, '/')[1] == 'd') - return 0; fd = fopen(name, "rb"); if (!fd) { @@ -356,28 +353,8 @@ restart: static const char *usbfs_dir_find(void) { - static char usbfs_path_0[] = "/dev/usb/devices"; - static char usbfs_path_1[] = "/proc/bus/usb/devices"; static char udev_usb_path[] = "/dev/bus/usb"; - static char *const usbfs_paths[] = { - usbfs_path_0, usbfs_path_1 - }; - - static char *const * - end = usbfs_paths + sizeof usbfs_paths / sizeof *usbfs_paths; - - char *const *it = usbfs_paths; - do { - int fd = open(*it, O_RDONLY); - close(fd); - if (fd >= 0) { - strrchr(*it, '/')[0] = '\0'; - return *it; - } - } while (++it != end); - - /* real device-nodes managed by udev */ if (access(udev_usb_path, F_OK) == 0) return udev_usb_path; @@ -489,7 +466,7 @@ usage: goto usage; if (!all && !device) { fprintf (stderr, "must specify '-a' or '-D dev', " - "or DEVICE=/proc/bus/usb/BBB/DDD in env\n"); + "or DEVICE=/dev/bus/usb/BBB/DDD in env\n"); goto usage; } -- cgit v0.10.2 From b53d657d84f530e5d83f34ff1b81ceedad3faa31 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Fri, 7 Sep 2012 14:31:45 +0200 Subject: usb/core: use bin2bcd() for bcdDevice in RH The kernel's version number is used as decimal in the bcdDevice field of the RH descriptor. For kernel version v3.12 we would see 3.0c in lsusb. I am not sure how important it is to stick with bcd values since this is this way since we started git history and nobody complained (however back then we reported only 2.6). Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index bc84106..6e4fd28 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -22,6 +22,7 @@ * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include #include #include @@ -123,9 +124,8 @@ static inline int is_root_hub(struct usb_device *udev) */ /*-------------------------------------------------------------------------*/ - -#define KERNEL_REL ((LINUX_VERSION_CODE >> 16) & 0x0ff) -#define KERNEL_VER ((LINUX_VERSION_CODE >> 8) & 0x0ff) +#define KERNEL_REL bin2bcd(((LINUX_VERSION_CODE >> 16) & 0x0ff)) +#define KERNEL_VER bin2bcd(((LINUX_VERSION_CODE >> 8) & 0x0ff)) /* usb 3.0 root hub device descriptor */ static const u8 usb3_rh_dev_descriptor[18] = { diff --git a/include/linux/bcd.h b/include/linux/bcd.h index 22ea563..18fff11 100644 --- a/include/linux/bcd.h +++ b/include/linux/bcd.h @@ -3,7 +3,20 @@ #include -unsigned bcd2bin(unsigned char val) __attribute_const__; -unsigned char bin2bcd(unsigned val) __attribute_const__; +#define bcd2bin(x) \ + (__builtin_constant_p((u8 )(x)) ? \ + const_bcd2bin(x) : \ + _bcd2bin(x)) + +#define bin2bcd(x) \ + (__builtin_constant_p((u8 )(x)) ? \ + const_bin2bcd(x) : \ + _bin2bcd(x)) + +#define const_bcd2bin(x) (((x) & 0x0f) + ((x) >> 4) * 10) +#define const_bin2bcd(x) ((((x) / 10) << 4) + (x) % 10) + +unsigned _bcd2bin(unsigned char val) __attribute_const__; +unsigned char _bin2bcd(unsigned val) __attribute_const__; #endif /* _BCD_H */ diff --git a/lib/bcd.c b/lib/bcd.c index 55efaf7..40d304e 100644 --- a/lib/bcd.c +++ b/lib/bcd.c @@ -1,14 +1,14 @@ #include #include -unsigned bcd2bin(unsigned char val) +unsigned _bcd2bin(unsigned char val) { return (val & 0x0f) + (val >> 4) * 10; } -EXPORT_SYMBOL(bcd2bin); +EXPORT_SYMBOL(_bcd2bin); -unsigned char bin2bcd(unsigned val) +unsigned char _bin2bcd(unsigned val) { return ((val / 10) << 4) + val % 10; } -EXPORT_SYMBOL(bin2bcd); +EXPORT_SYMBOL(_bin2bcd); -- cgit v0.10.2 From 9c2089045b87130e8464ca7e21725959446d7f0c Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Mon, 10 Sep 2012 21:24:41 +0800 Subject: usb: redefine DeviceRemovable and wHubDelay as _le16 DeviceRemovalbe and wHubDelay for usb3.0 hub are little-endian and so define them as _le16. Signed-off-by: Lan Tianyu Signed-off-by: Greg Kroah-Hartman diff --git a/include/linux/usb/ch11.h b/include/linux/usb/ch11.h index b6c2863..7692dc6 100644 --- a/include/linux/usb/ch11.h +++ b/include/linux/usb/ch11.h @@ -236,8 +236,8 @@ struct usb_hub_descriptor { struct { __u8 bHubHdrDecLat; - __u16 wHubDelay; - __u16 DeviceRemovable; + __le16 wHubDelay; + __le16 DeviceRemovable; } __attribute__ ((packed)) ss; } u; } __attribute__ ((packed)); -- cgit v0.10.2 From fa2a9566257a3b62c328ea5d621ccf5952079dac Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Wed, 5 Sep 2012 13:44:31 +0800 Subject: usb: make usb port a real device This patch turns each USB port on a hub into a new struct device. This new device has the USB hub interface device as its parent. The port devices are stored in a new structure (usb_port), and an array of usb_ports are dynamically allocated once we know how many ports the USB hub has. Move the port_owner variable out of usb_hub and into this new structure. A new file will be created in the hub interface sysfs directory, so add documentation. Acked-by: Alan Stern Signed-off-by: Lan Tianyu Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb index 5f75f8f..b6fbe51 100644 --- a/Documentation/ABI/testing/sysfs-bus-usb +++ b/Documentation/ABI/testing/sysfs-bus-usb @@ -220,3 +220,10 @@ Description: If the device doesn't support LTM, the file will read "no". The file will be present for all speeds of USB devices, and will always read "no" for USB 1.1 and USB 2.0 devices. + +What: /sys/bus/usb/devices/.../(hub interface)/portX +Date: August 2012 +Contact: Lan Tianyu +Description: + The /sys/bus/usb/devices/.../(hub interface)/portX + is usb port device's sysfs directory. diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 128a804..87df22e 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -39,6 +39,11 @@ #endif #endif +struct usb_port { + struct device dev; + struct dev_state *port_owner; +}; + struct usb_hub { struct device *intfdev; /* the "interface" device */ struct usb_device *hdev; @@ -83,7 +88,7 @@ struct usb_hub { u8 indicator[USB_MAXCHILDREN]; struct delayed_work leds; struct delayed_work init_work; - struct dev_state **port_owners; + struct usb_port **ports; }; static inline int hub_is_superspeed(struct usb_device *hdev) @@ -156,6 +161,8 @@ EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem); #define HUB_DEBOUNCE_STEP 25 #define HUB_DEBOUNCE_STABLE 100 +#define to_usb_port(_dev) \ + container_of(_dev, struct usb_port, dev) static int usb_reset_and_verify_device(struct usb_device *udev); @@ -1222,6 +1229,52 @@ static int hub_post_reset(struct usb_interface *intf) return 0; } +static void usb_port_device_release(struct device *dev) +{ + struct usb_port *port_dev = to_usb_port(dev); + + kfree(port_dev); +} + +static void usb_hub_remove_port_device(struct usb_hub *hub, + int port1) +{ + device_unregister(&hub->ports[port1 - 1]->dev); +} + +struct device_type usb_port_device_type = { + .name = "usb_port", + .release = usb_port_device_release, +}; + +static int usb_hub_create_port_device(struct usb_hub *hub, + int port1) +{ + struct usb_port *port_dev = NULL; + int retval; + + port_dev = kzalloc(sizeof(*port_dev), GFP_KERNEL); + if (!port_dev) { + retval = -ENOMEM; + goto exit; + } + + hub->ports[port1 - 1] = port_dev; + port_dev->dev.parent = hub->intfdev; + port_dev->dev.type = &usb_port_device_type; + dev_set_name(&port_dev->dev, "port%d", port1); + + retval = device_register(&port_dev->dev); + if (retval) + goto error_register; + return 0; + +error_register: + put_device(&port_dev->dev); +exit: + return retval; +} + static int hub_configure(struct usb_hub *hub, struct usb_endpoint_descriptor *endpoint) { @@ -1231,7 +1284,7 @@ static int hub_configure(struct usb_hub *hub, u16 hubstatus, hubchange; u16 wHubCharacteristics; unsigned int pipe; - int maxp, ret; + int maxp, ret, i; char *message = "out of memory"; hub->buffer = kmalloc(sizeof(*hub->buffer), GFP_KERNEL); @@ -1273,9 +1326,9 @@ static int hub_configure(struct usb_hub *hub, hdev->children = kzalloc(hdev->maxchild * sizeof(struct usb_device *), GFP_KERNEL); - hub->port_owners = kzalloc(hdev->maxchild * sizeof(struct dev_state *), - GFP_KERNEL); - if (!hdev->children || !hub->port_owners) { + hub->ports = kzalloc(hdev->maxchild * sizeof(struct usb_port *), + GFP_KERNEL); + if (!hdev->children || !hub->ports) { ret = -ENOMEM; goto fail; } @@ -1484,6 +1537,11 @@ static int hub_configure(struct usb_hub *hub, if (hub->has_indicators && blinkenlights) hub->indicator [0] = INDICATOR_CYCLE; + for (i = 0; i < hdev->maxchild; i++) + if (usb_hub_create_port_device(hub, i + 1) < 0) + dev_err(hub->intfdev, + "couldn't create port%d device.\n", i + 1); + hub_activate(hub, HUB_INIT); return 0; @@ -1508,6 +1566,10 @@ static void hub_disconnect(struct usb_interface *intf) { struct usb_hub *hub = usb_get_intfdata(intf); struct usb_device *hdev = interface_to_usbdev(intf); + int i; + + for (i = 0; i < hdev->maxchild; i++) + usb_hub_remove_port_device(hub, i + 1); /* Take the hub off the event list and don't let it be added again */ spin_lock_irq(&hub_event_lock); @@ -1530,7 +1592,7 @@ static void hub_disconnect(struct usb_interface *intf) usb_free_urb(hub->urb); kfree(hdev->children); - kfree(hub->port_owners); + kfree(hub->ports); kfree(hub->descriptor); kfree(hub->status); kfree(hub->buffer); @@ -1662,7 +1724,7 @@ static int find_port_owner(struct usb_device *hdev, unsigned port1, /* This assumes that devices not managed by the hub driver * will always have maxchild equal to 0. */ - *ppowner = &(hdev_to_hub(hdev)->port_owners[port1 - 1]); + *ppowner = &(hdev_to_hub(hdev)->ports[port1 - 1]->port_owner); return 0; } @@ -1699,16 +1761,14 @@ int usb_hub_release_port(struct usb_device *hdev, unsigned port1, void usb_hub_release_all_ports(struct usb_device *hdev, struct dev_state *owner) { + struct usb_hub *hub = hdev_to_hub(hdev); int n; - struct dev_state **powner; - n = find_port_owner(hdev, 1, &powner); - if (n == 0) { - for (; n < hdev->maxchild; (++n, ++powner)) { - if (*powner == owner) - *powner = NULL; - } + for (n = 0; n < hdev->maxchild; n++) { + if (hub->ports[n]->port_owner == owner) + hub->ports[n]->port_owner = NULL; } + } /* The caller must hold udev's lock */ @@ -1719,10 +1779,9 @@ bool usb_device_is_owned(struct usb_device *udev) if (udev->state == USB_STATE_NOTATTACHED || !udev->parent) return false; hub = hdev_to_hub(udev->parent); - return !!hub->port_owners[udev->portnum - 1]; + return !!hub->ports[udev->portnum - 1]->port_owner; } - static void recursively_mark_NOTATTACHED(struct usb_device *udev) { int i; -- cgit v0.10.2 From ff823c79a5c33194c2e5594f7c4686ea3547910c Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Wed, 5 Sep 2012 13:44:32 +0800 Subject: usb: move children to struct usb_port The usb_device structure contains an array of usb_device "children". This array is only valid if the usb_device is a hub, so it makes no sense to store it there. Instead, store the usb_device child in its parent usb_port structure. Since usb_port is an internal USB core structure, add a new function to get the USB device child, usb_hub_find_child(). Add a new macro, usb_hub_get_each_child(), to iterate over all the children attached to a particular USB hub. Remove the printing the USB children array pointer from the usb-ip driver, since it's really not necessary. Acked-by: Alan Stern Signed-off-by: Lan Tianyu Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/usbip/usbip_common.c b/drivers/staging/usbip/usbip_common.c index 70f23026..95beb76 100644 --- a/drivers/staging/usbip/usbip_common.c +++ b/drivers/staging/usbip/usbip_common.c @@ -157,8 +157,7 @@ static void usbip_dump_usb_device(struct usb_device *udev) dev_dbg(dev, "have_langid %d, string_langid %d\n", udev->have_langid, udev->string_langid); - dev_dbg(dev, "maxchild %d, children %p\n", - udev->maxchild, udev->children); + dev_dbg(dev, "maxchild %d\n", udev->maxchild); } static void usbip_dump_request_type(__u8 rt) diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index d956965..f4ead12 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -496,6 +496,7 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, char *pages_start, *data_end, *speed; unsigned int length; ssize_t total_written = 0; + struct usb_device *childdev = NULL; /* don't bother with anything else if we're not writing any data */ if (*nbytes <= 0) @@ -589,14 +590,12 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, free_pages((unsigned long)pages_start, 1); /* Now look at all of this device's children. */ - for (chix = 0; chix < usbdev->maxchild; chix++) { - struct usb_device *childdev = usbdev->children[chix]; - + usb_hub_for_each_child(usbdev, chix, childdev) { if (childdev) { usb_lock_device(childdev); ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, childdev, bus, - level + 1, chix, ++cnt); + level + 1, chix - 1, ++cnt); usb_unlock_device(childdev); if (ret == -EFAULT) return total_written; diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 87df22e..cdbade1 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -40,6 +40,7 @@ #endif struct usb_port { + struct usb_device *child; struct device dev; struct dev_state *port_owner; }; @@ -181,7 +182,7 @@ static inline char *portspeed(struct usb_hub *hub, int portstatus) /* Note that hdev or one of its children must be locked! */ static struct usb_hub *hdev_to_hub(struct usb_device *hdev) { - if (!hdev || !hdev->actconfig) + if (!hdev || !hdev->actconfig || !hdev->maxchild) return NULL; return usb_get_intfdata(hdev->actconfig->interface[0]); } @@ -876,8 +877,8 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) struct usb_device *hdev = hub->hdev; int ret = 0; - if (hdev->children[port1-1] && set_state) - usb_set_device_state(hdev->children[port1-1], + if (hub->ports[port1 - 1]->child && set_state) + usb_set_device_state(hub->ports[port1 - 1]->child, USB_STATE_NOTATTACHED); if (!hub->error && !hub_is_superspeed(hub->hdev)) ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); @@ -1033,7 +1034,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) * which ports need attention. */ for (port1 = 1; port1 <= hdev->maxchild; ++port1) { - struct usb_device *udev = hdev->children[port1-1]; + struct usb_device *udev = hub->ports[port1 - 1]->child; u16 portstatus, portchange; portstatus = portchange = 0; @@ -1198,8 +1199,8 @@ static void hub_quiesce(struct usb_hub *hub, enum hub_quiescing_type type) if (type != HUB_SUSPEND) { /* Disconnect all the children */ for (i = 0; i < hdev->maxchild; ++i) { - if (hdev->children[i]) - usb_disconnect(&hdev->children[i]); + if (hub->ports[i]->child) + usb_disconnect(&hub->ports[i]->child); } } @@ -1324,11 +1325,9 @@ static int hub_configure(struct usb_hub *hub, dev_info (hub_dev, "%d port%s detected\n", hdev->maxchild, (hdev->maxchild == 1) ? "" : "s"); - hdev->children = kzalloc(hdev->maxchild * - sizeof(struct usb_device *), GFP_KERNEL); hub->ports = kzalloc(hdev->maxchild * sizeof(struct usb_port *), GFP_KERNEL); - if (!hdev->children || !hub->ports) { + if (!hub->ports) { ret = -ENOMEM; goto fail; } @@ -1591,7 +1590,6 @@ static void hub_disconnect(struct usb_interface *intf) highspeed_hubs--; usb_free_urb(hub->urb); - kfree(hdev->children); kfree(hub->ports); kfree(hub->descriptor); kfree(hub->status); @@ -1679,6 +1677,7 @@ static int hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) { struct usb_device *hdev = interface_to_usbdev (intf); + struct usb_hub *hub = hdev_to_hub(hdev); /* assert ifno == 0 (part of hub spec) */ switch (code) { @@ -1692,11 +1691,11 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) else { info->nports = hdev->maxchild; for (i = 0; i < info->nports; i++) { - if (hdev->children[i] == NULL) + if (hub->ports[i]->child == NULL) info->port[i] = 0; else info->port[i] = - hdev->children[i]->devnum; + hub->ports[i]->child->devnum; } } spin_unlock_irq(&device_state_lock); @@ -1784,11 +1783,12 @@ bool usb_device_is_owned(struct usb_device *udev) static void recursively_mark_NOTATTACHED(struct usb_device *udev) { + struct usb_hub *hub = hdev_to_hub(udev); int i; for (i = 0; i < udev->maxchild; ++i) { - if (udev->children[i]) - recursively_mark_NOTATTACHED(udev->children[i]); + if (hub->ports[i]->child) + recursively_mark_NOTATTACHED(hub->ports[i]->child); } if (udev->state == USB_STATE_SUSPENDED) udev->active_duration -= jiffies; @@ -1952,6 +1952,7 @@ static void hub_free_dev(struct usb_device *udev) void usb_disconnect(struct usb_device **pdev) { struct usb_device *udev = *pdev; + struct usb_hub *hub = hdev_to_hub(udev); int i; /* mark the device as inactive, so any further urb submissions for @@ -1966,8 +1967,8 @@ void usb_disconnect(struct usb_device **pdev) /* Free up all the children before we remove this device */ for (i = 0; i < udev->maxchild; i++) { - if (udev->children[i]) - usb_disconnect(&udev->children[i]); + if (hub->ports[i]->child) + usb_disconnect(&hub->ports[i]->child); } /* deallocate hcd/hardware state ... nuking all pending urbs and @@ -3131,7 +3132,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg) for (port1 = 1; port1 <= hdev->maxchild; port1++) { struct usb_device *udev; - udev = hdev->children [port1-1]; + udev = hub->ports[port1 - 1]->child; if (udev && udev->can_submit) { dev_warn(&intf->dev, "port %d nyet suspended\n", port1); if (PMSG_IS_AUTO(msg)) @@ -4058,7 +4059,7 @@ hub_power_remaining (struct usb_hub *hub) remaining = hdev->bus_mA - hub->descriptor->bHubContrCurrent; for (port1 = 1; port1 <= hdev->maxchild; ++port1) { - struct usb_device *udev = hdev->children[port1 - 1]; + struct usb_device *udev = hub->ports[port1 - 1]->child; int delta; if (!udev) @@ -4122,7 +4123,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, #endif /* Try to resuscitate an existing device */ - udev = hdev->children[port1-1]; + udev = hub->ports[port1 - 1]->child; if ((portstatus & USB_PORT_STAT_CONNECTION) && udev && udev->state != USB_STATE_NOTATTACHED) { usb_lock_device(udev); @@ -4151,7 +4152,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, /* Disconnect any existing devices under this port */ if (udev) - usb_disconnect(&hdev->children[port1-1]); + usb_disconnect(&hub->ports[port1 - 1]->child); clear_bit(port1, hub->change_bits); /* We can forget about a "removed" device when there's a physical @@ -4287,7 +4288,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, if (hdev->state == USB_STATE_NOTATTACHED) status = -ENOTCONN; else - hdev->children[port1-1] = udev; + hub->ports[port1 - 1]->child = udev; spin_unlock_irq(&device_state_lock); /* Run it through the hoops (find a driver, etc) */ @@ -4295,7 +4296,7 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, status = usb_new_device(udev); if (status) { spin_lock_irq(&device_state_lock); - hdev->children[port1-1] = NULL; + hub->ports[port1 - 1]->child = NULL; spin_unlock_irq(&device_state_lock); } } @@ -4341,7 +4342,7 @@ static int hub_handle_remote_wakeup(struct usb_hub *hub, unsigned int port, int ret; hdev = hub->hdev; - udev = hdev->children[port-1]; + udev = hub->ports[port - 1]->child; if (!hub_is_superspeed(hdev)) { if (!(portchange & USB_PORT_STAT_C_SUSPEND)) return 0; @@ -4495,7 +4496,7 @@ static void hub_events(void) */ if (!(portstatus & USB_PORT_STAT_ENABLE) && !connect_change - && hdev->children[i-1]) { + && hub->ports[i - 1]->child) { dev_err (hub_dev, "port %i " "disabled by hub (EMI?), " @@ -5052,3 +5053,27 @@ void usb_queue_reset_device(struct usb_interface *iface) schedule_work(&iface->reset_ws); } EXPORT_SYMBOL_GPL(usb_queue_reset_device); + +/** + * usb_hub_find_child - Get the pointer of child device + * attached to the port which is specified by @port1. + * @hdev: USB device belonging to the usb hub + * @port1: port num to indicate which port the child device + * is attached to. + * + * USB drivers call this function to get hub's child device + * pointer. + * + * Return NULL if input param is invalid and + * child's usb_device pointer if non-NULL. + */ +struct usb_device *usb_hub_find_child(struct usb_device *hdev, + int port1) +{ + struct usb_hub *hub = hdev_to_hub(hdev); + + if (port1 < 1 || port1 > hdev->maxchild) + return NULL; + return hub->ports[port1 - 1]->child; +} +EXPORT_SYMBOL_GPL(usb_hub_find_child); diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 4c634eb..fcc09e5 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -2029,15 +2029,14 @@ static int r8a66597_get_frame(struct usb_hcd *hcd) static void collect_usb_address_map(struct usb_device *udev, unsigned long *map) { int chix; + struct usb_device *childdev; if (udev->state == USB_STATE_CONFIGURED && udev->parent && udev->parent->devnum > 1 && udev->parent->descriptor.bDeviceClass == USB_CLASS_HUB) map[udev->devnum/32] |= (1 << (udev->devnum % 32)); - for (chix = 0; chix < udev->maxchild; chix++) { - struct usb_device *childdev = udev->children[chix]; - + usb_hub_for_each_child(udev, chix, childdev) { if (childdev) collect_usb_address_map(childdev, map); } diff --git a/include/linux/usb.h b/include/linux/usb.h index 30d1ae3..ff8ef2d 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -469,7 +469,6 @@ struct usb3_lpm_parameters { * access from userspace * @usbfs_dentry: usbfs dentry entry for the device * @maxchild: number of ports if hub - * @children: child devices - USB devices that are attached to this hub * @quirks: quirks of the whole device * @urbnum: number of URBs submitted for the whole device * @active_duration: total time device is not suspended @@ -543,7 +542,6 @@ struct usb_device { struct list_head filelist; int maxchild; - struct usb_device **children; u32 quirks; atomic_t urbnum; @@ -572,6 +570,19 @@ static inline struct usb_device *interface_to_usbdev(struct usb_interface *intf) extern struct usb_device *usb_get_dev(struct usb_device *dev); extern void usb_put_dev(struct usb_device *dev); +extern struct usb_device *usb_hub_find_child(struct usb_device *hdev, + int port1); + +/** + * usb_hub_for_each_child - iterate over all child devices on the hub + * @hdev: USB device belonging to the usb hub + * @port1: portnum associated with child device + * @child: child device pointer + */ +#define usb_hub_for_each_child(hdev, port1, child) \ + for (port1 = 1, child = usb_hub_find_child(hdev, port1); \ + port1 <= hdev->maxchild; \ + child = usb_hub_find_child(hdev, ++port1)) /* USB device locking */ #define usb_lock_device(udev) device_lock(&(udev)->dev) -- cgit v0.10.2 From d557542421da643358201664903e67fd01dfca1a Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Wed, 5 Sep 2012 13:44:33 +0800 Subject: usb/acpi: Bind ACPI node to USB port, not usb_device. In the ACPI DSDT table, only usb root hub and usb ports are ACPI device nodes. Originally, we bound the usb port's ACPI node to the usb device attached to the port. However, we want to access those ACPI port methods when the port is empty, and there's no usb_device associated with that port. Now that the usb port is a real device, we can bind the port's ACPI node to struct usb_port instead. Signed-off-by: Lan Tianyu Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index cdbade1..3341b55 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -5077,3 +5077,21 @@ struct usb_device *usb_hub_find_child(struct usb_device *hdev, return hub->ports[port1 - 1]->child; } EXPORT_SYMBOL_GPL(usb_hub_find_child); + +#ifdef CONFIG_ACPI +/** + * usb_get_hub_port_acpi_handle - Get the usb port's acpi handle + * @hdev: USB device belonging to the usb hub + * @port1: port num of the port + * + * Return port's acpi handle if successful, NULL if params are + * invaild. + */ +acpi_handle usb_get_hub_port_acpi_handle(struct usb_device *hdev, + int port1) +{ + struct usb_hub *hub = hdev_to_hub(hdev); + + return DEVICE_ACPI_HANDLE(&hub->ports[port1 - 1]->dev); +} +#endif diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index 8947b20..47197bf 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -70,22 +70,59 @@ static int usb_acpi_check_pld(struct usb_device *udev, acpi_handle handle) static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) { struct usb_device *udev; - struct device *parent; acpi_handle *parent_handle; + int port_num; - if (!is_usb_device(dev)) - return -ENODEV; - - udev = to_usb_device(dev); - parent = dev->parent; - parent_handle = DEVICE_ACPI_HANDLE(parent); - - if (!parent_handle) - return -ENODEV; - - *handle = acpi_get_child(parent_handle, udev->portnum); - - if (!*handle) + /* + * In the ACPI DSDT table, only usb root hub and usb ports are + * acpi device nodes. The hierarchy like following. + * Device (EHC1) + * Device (HUBN) + * Device (PR01) + * Device (PR11) + * Device (PR12) + * Device (PR13) + * ... + * So all binding process is divided into two parts. binding + * root hub and usb ports. + */ + if (is_usb_device(dev)) { + udev = to_usb_device(dev); + if (udev->parent) + return -ENODEV; + /* root hub's parent is the usb hcd. */ + parent_handle = DEVICE_ACPI_HANDLE(dev->parent); + *handle = acpi_get_child(parent_handle, udev->portnum); + if (!*handle) + return -ENODEV; + return 0; + } else if (is_usb_port(dev)) { + sscanf(dev_name(dev), "port%d", &port_num); + /* Get the struct usb_device point of port's hub */ + udev = to_usb_device(dev->parent->parent); + + /* + * The root hub ports' parent is the root hub. The non-root-hub + * ports' parent is the parent hub port which the hub is + * connected to. + */ + if (!udev->parent) { + *handle = acpi_get_child(DEVICE_ACPI_HANDLE(&udev->dev), + port_num); + if (!*handle) + return -ENODEV; + } else { + parent_handle = + usb_get_hub_port_acpi_handle(udev->parent, + udev->portnum); + if (!parent_handle) + return -ENODEV; + + *handle = acpi_get_child(parent_handle, port_num); + if (!*handle) + return -ENODEV; + } + } else return -ENODEV; /* @@ -102,7 +139,7 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) static struct acpi_bus_type usb_acpi_bus = { .bus = &usb_bus_type, - .find_bridge = NULL, + .find_bridge = usb_acpi_find_device, .find_device = usb_acpi_find_device, }; diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index acb103c..1633f6e 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -1,4 +1,5 @@ #include +#include struct dev_state; @@ -115,6 +116,7 @@ extern struct bus_type usb_bus_type; extern struct device_type usb_device_type; extern struct device_type usb_if_device_type; extern struct device_type usb_ep_device_type; +extern struct device_type usb_port_device_type; extern struct usb_device_driver usb_generic_driver; static inline int is_usb_device(const struct device *dev) @@ -132,6 +134,11 @@ static inline int is_usb_endpoint(const struct device *dev) return dev->type == &usb_ep_device_type; } +static inline int is_usb_port(const struct device *dev) +{ + return dev->type == &usb_port_device_type; +} + /* Do the same for device drivers and interface drivers. */ static inline int is_usb_device_driver(struct device_driver *drv) @@ -166,6 +173,8 @@ extern void usb_notify_remove_bus(struct usb_bus *ubus); #ifdef CONFIG_ACPI extern int usb_acpi_register(void); extern void usb_acpi_unregister(void); +extern acpi_handle usb_get_hub_port_acpi_handle(struct usb_device *hdev, + int port1); #else static inline int usb_acpi_register(void) { return 0; }; static inline void usb_acpi_unregister(void) { }; -- cgit v0.10.2 From 05f916894a692f0cc0973aef21521133623b21c0 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Wed, 5 Sep 2012 13:44:34 +0800 Subject: usb/acpi: Store info on device removability. In the upcoming USB port power off patches, we need to know whether a USB port can ever see a disconnect event. Often USB ports are internal to a system, and users can't disconnect USB devices from that port. Sometimes those ports will remain empty, because the OEM chose not to connect an internal USB device to that port. According to ACPI Spec 9.13, PLD indicates whether USB port is user visible and _UPC indicates whether a USB device can be connected to the USB port (we'll call this "connectible"). Here's a matrix of the possible combinations: Visible Connectible Name Example ------------------------------------------------------------------------- Yes No Unknown (Invalid state.) Yes Yes Hot-plug USB ports on the outside of a laptop. A user could freely connect and disconnect USB devices. No Yes Hard-wired A USB modem hard-wired to a port on the inside of a laptop. No No Not used The port is internal to the system and will remain empty. Represent each of these four states with an enum usb_port_connect_type. The four states are USB_PORT_CONNECT_TYPE_UNKNOWN, USB_PORT_CONNECT_TYPE_HOT_PLUG, USB_PORT_CONNECT_TYPE_HARD_WIRED, and USB_PORT_NOT_USED. When we get the USB port's acpi_handle, store the state in connect_type in struct usb_port. Signed-off-by: Lan Tianyu Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 3341b55..4ffe837 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -43,6 +43,7 @@ struct usb_port { struct usb_device *child; struct device dev; struct dev_state *port_owner; + enum usb_port_connect_type connect_type; }; struct usb_hub { @@ -5078,6 +5079,36 @@ struct usb_device *usb_hub_find_child(struct usb_device *hdev, } EXPORT_SYMBOL_GPL(usb_hub_find_child); +/** + * usb_set_hub_port_connect_type - set hub port connect type. + * @hdev: USB device belonging to the usb hub + * @port1: port num of the port + * @type: connect type of the port + */ +void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1, + enum usb_port_connect_type type) +{ + struct usb_hub *hub = hdev_to_hub(hdev); + + hub->ports[port1 - 1]->connect_type = type; +} + +/** + * usb_get_hub_port_connect_type - Get the port's connect type + * @hdev: USB device belonging to the usb hub + * @port1: port num of the port + * + * Return connect type of the port and if input params are + * invalid, return USB_PORT_CONNECT_TYPE_UNKNOWN. + */ +enum usb_port_connect_type +usb_get_hub_port_connect_type(struct usb_device *hdev, int port1) +{ + struct usb_hub *hub = hdev_to_hub(hdev); + + return hub->ports[port1 - 1]->connect_type; +} + #ifdef CONFIG_ACPI /** * usb_get_hub_port_acpi_handle - Get the usb port's acpi handle diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index 47197bf..404d86a 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -19,20 +19,29 @@ #include "usb.h" -static int usb_acpi_check_upc(struct usb_device *udev, acpi_handle handle) +static int usb_acpi_check_port_connect_type(struct usb_device *hdev, + acpi_handle handle, int port1) { acpi_status status; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; union acpi_object *upc; + struct acpi_pld pld; int ret = 0; - status = acpi_evaluate_object(handle, "_UPC", NULL, &buffer); - + /* + * Accoding to ACPI Spec 9.13. PLD indicates whether usb port is + * user visible and _UPC indicates whether it is connectable. If + * the port was visible and connectable, it could be freely connected + * and disconnected with USB devices. If no visible and connectable, + * a usb device is directly hard-wired to the port. If no visible and + * no connectable, the port would be not used. + */ + status = acpi_get_physical_device_location(handle, &pld); if (ACPI_FAILURE(status)) return -ENODEV; + status = acpi_evaluate_object(handle, "_UPC", NULL, &buffer); upc = buffer.pointer; - if (!upc || (upc->type != ACPI_TYPE_PACKAGE) || upc->package.count != 4) { ret = -EINVAL; @@ -40,33 +49,20 @@ static int usb_acpi_check_upc(struct usb_device *udev, acpi_handle handle) } if (upc->package.elements[0].integer.value) - udev->removable = USB_DEVICE_REMOVABLE; - else - udev->removable = USB_DEVICE_FIXED; + if (pld.user_visible) + usb_set_hub_port_connect_type(hdev, port1, + USB_PORT_CONNECT_TYPE_HOT_PLUG); + else + usb_set_hub_port_connect_type(hdev, port1, + USB_PORT_CONNECT_TYPE_HARD_WIRED); + else if (!pld.user_visible) + usb_set_hub_port_connect_type(hdev, port1, USB_PORT_NOT_USED); out: kfree(upc); return ret; } -static int usb_acpi_check_pld(struct usb_device *udev, acpi_handle handle) -{ - acpi_status status; - struct acpi_pld pld; - - status = acpi_get_physical_device_location(handle, &pld); - - if (ACPI_FAILURE(status)) - return -ENODEV; - - if (pld.user_visible) - udev->removable = USB_DEVICE_REMOVABLE; - else - udev->removable = USB_DEVICE_FIXED; - - return 0; -} - static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) { struct usb_device *udev; @@ -88,8 +84,30 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) */ if (is_usb_device(dev)) { udev = to_usb_device(dev); - if (udev->parent) + if (udev->parent) { + enum usb_port_connect_type type; + + /* + * According usb port's connect type to set usb device's + * removability. + */ + type = usb_get_hub_port_connect_type(udev->parent, + udev->portnum); + switch (type) { + case USB_PORT_CONNECT_TYPE_HOT_PLUG: + udev->removable = USB_DEVICE_REMOVABLE; + break; + case USB_PORT_CONNECT_TYPE_HARD_WIRED: + udev->removable = USB_DEVICE_FIXED; + break; + default: + udev->removable = USB_DEVICE_REMOVABLE_UNKNOWN; + break; + } + return -ENODEV; + } + /* root hub's parent is the usb hcd. */ parent_handle = DEVICE_ACPI_HANDLE(dev->parent); *handle = acpi_get_child(parent_handle, udev->portnum); @@ -122,18 +140,10 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) if (!*handle) return -ENODEV; } + usb_acpi_check_port_connect_type(udev, *handle, port_num); } else return -ENODEV; - /* - * PLD will tell us whether a port is removable to the user or - * not. If we don't get an answer from PLD (it's not present - * or it's malformed) then try to infer it from UPC. If a - * device isn't connectable then it's probably not removable. - */ - if (usb_acpi_check_pld(udev, *handle) != 0) - usb_acpi_check_upc(udev, *handle); - return 0; } diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index 1633f6e..1c528c1 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -169,6 +169,10 @@ extern void usb_notify_add_device(struct usb_device *udev); extern void usb_notify_remove_device(struct usb_device *udev); extern void usb_notify_add_bus(struct usb_bus *ubus); extern void usb_notify_remove_bus(struct usb_bus *ubus); +extern enum usb_port_connect_type + usb_get_hub_port_connect_type(struct usb_device *hdev, int port1); +extern void usb_set_hub_port_connect_type(struct usb_device *hdev, int port1, + enum usb_port_connect_type type); #ifdef CONFIG_ACPI extern int usb_acpi_register(void); diff --git a/include/linux/usb.h b/include/linux/usb.h index ff8ef2d..e0084a1 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -384,6 +384,13 @@ enum usb_device_removable { USB_DEVICE_FIXED, }; +enum usb_port_connect_type { + USB_PORT_CONNECT_TYPE_UNKNOWN = 0, + USB_PORT_CONNECT_TYPE_HOT_PLUG, + USB_PORT_CONNECT_TYPE_HARD_WIRED, + USB_PORT_NOT_USED, +}; + /* * USB 3.0 Link Power Management (LPM) parameters. * -- cgit v0.10.2 From 693d8eb853f62a1341cf59df151b12c053f34e8a Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Wed, 5 Sep 2012 13:44:35 +0800 Subject: xhci: Handle clear PORT_POWER feature. This patch makes the xHCI roothub code handle the clear PORT_POWER feature request. Setting port power is already handled. Signed-off-by: Lan Tianyu Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 74bfc86..03032b3 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -865,6 +865,10 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, xhci_disable_port(hcd, xhci, wIndex, port_array[wIndex], temp); break; + case USB_PORT_FEAT_POWER: + xhci_writel(xhci, temp & ~PORT_POWER, + port_array[wIndex]); + break; default: goto error; } -- cgit v0.10.2 From f7ac7787ad361e31a7972e2854ed8dc2eedfac3b Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Wed, 5 Sep 2012 13:44:36 +0800 Subject: usb/acpi: Use ACPI methods to power off ports. Upcoming Intel systems will have an ACPI method to control whether a USB port can be completely powered off. The implication of powering off a USB port is that the device and host sees a physical disconnect, and subsequent port connections and remote wakeups will be lost. Add a new function, usb_acpi_power_manageable(), that can be used to find whether the usb port has ACPI power resources that can be used to power on and off the port on these machines. Also add a new function called usb_acpi_set_power_state() that controls the port power via these ACPI methods. When the USB core calls into the xHCI hub driver to power off a port, check whether the port can be completely powered off via this new ACPI mechanism. If so, call into these new ACPI methods. Also use the ACPI methods when the USB core asks to power on a port. Signed-off-by: Lan Tianyu Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index 404d86a..0ef7d42 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c @@ -19,6 +19,68 @@ #include "usb.h" +/** + * usb_acpi_power_manageable - check whether usb port has + * acpi power resource. + * @hdev: USB device belonging to the usb hub + * @index: port index based zero + * + * Return true if the port has acpi power resource and false if no. + */ +bool usb_acpi_power_manageable(struct usb_device *hdev, int index) +{ + acpi_handle port_handle; + int port1 = index + 1; + + port_handle = usb_get_hub_port_acpi_handle(hdev, + port1); + if (port_handle) + return acpi_bus_power_manageable(port_handle); + else + return false; +} +EXPORT_SYMBOL_GPL(usb_acpi_power_manageable); + +/** + * usb_acpi_set_power_state - control usb port's power via acpi power + * resource + * @hdev: USB device belonging to the usb hub + * @index: port index based zero + * @enable: power state expected to be set + * + * Notice to use usb_acpi_power_manageable() to check whether the usb port + * has acpi power resource before invoking this function. + * + * Returns 0 on success, else negative errno. + */ +int usb_acpi_set_power_state(struct usb_device *hdev, int index, bool enable) +{ + acpi_handle port_handle; + unsigned char state; + int port1 = index + 1; + int error = -EINVAL; + + port_handle = (acpi_handle)usb_get_hub_port_acpi_handle(hdev, + port1); + if (!port_handle) + return error; + + if (enable) + state = ACPI_STATE_D0; + else + state = ACPI_STATE_D3_COLD; + + error = acpi_bus_set_power(port_handle, state); + if (!error) + dev_dbg(&hdev->dev, "The power of hub port %d was set to %d\n", + port1, enable); + else + dev_dbg(&hdev->dev, "The power of hub port failed to be set\n"); + + return error; +} +EXPORT_SYMBOL_GPL(usb_acpi_set_power_state); + static int usb_acpi_check_port_connect_type(struct usb_device *hdev, acpi_handle handle, int port1) { diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 03032b3..630e9e6 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -766,6 +766,12 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, temp = xhci_readl(xhci, port_array[wIndex]); xhci_dbg(xhci, "set port power, actual port %d status = 0x%x\n", wIndex, temp); + + temp = usb_acpi_power_manageable(hcd->self.root_hub, + wIndex); + if (temp) + usb_acpi_set_power_state(hcd->self.root_hub, + wIndex, true); break; case USB_PORT_FEAT_RESET: temp = (temp | PORT_RESET); @@ -868,6 +874,12 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, case USB_PORT_FEAT_POWER: xhci_writel(xhci, temp & ~PORT_POWER, port_array[wIndex]); + + temp = usb_acpi_power_manageable(hcd->self.root_hub, + wIndex); + if (temp) + usb_acpi_set_power_state(hcd->self.root_hub, + wIndex, false); break; default: goto error; diff --git a/include/linux/usb.h b/include/linux/usb.h index e0084a1..07915a3 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -602,6 +602,16 @@ extern int usb_lock_device_for_reset(struct usb_device *udev, extern int usb_reset_device(struct usb_device *dev); extern void usb_queue_reset_device(struct usb_interface *dev); +#ifdef CONFIG_ACPI +extern int usb_acpi_set_power_state(struct usb_device *hdev, int index, + bool enable); +extern bool usb_acpi_power_manageable(struct usb_device *hdev, int index); +#else +static inline int usb_acpi_set_power_state(struct usb_device *hdev, int index, + bool enable) { return 0; } +static inline bool usb_acpi_power_manageable(struct usb_device *hdev, int index) + { return true; } +#endif /* USB autosuspend and autoresume */ #ifdef CONFIG_USB_SUSPEND -- cgit v0.10.2 From 3a22b872e923954853cabd5a18f41da1846bccdb Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Wed, 5 Sep 2012 13:44:37 +0800 Subject: usb: Fail a get config when the port is powered off. Alan Stern pointed out that a USB port could potentially get powered off when the attached USB device is in the middle of enumerating, due to race conditions: http://marc.info/?l=linux-usb&m=134130616707548&w=2 If that happens, we need to ensure the enumeration fails. If a call to usb_get_descriptor() fails for a reason other than a Stall, return an error. That should handle the case where the port is powered off. Acked-by: Alan Stern Signed-off-by: Lan Tianyu Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c index f4bdd0c..7199adc 100644 --- a/drivers/usb/core/config.c +++ b/drivers/usb/core/config.c @@ -702,6 +702,8 @@ int usb_get_configuration(struct usb_device *dev) if (result < 0) { dev_err(ddev, "unable to read config index %d " "descriptor/%s: %d\n", cfgno, "start", result); + if (result != -EPIPE) + goto err; dev_err(ddev, "chopping to %d config(s)\n", cfgno); dev->descriptor.bNumConfigurations = cfgno; break; -- cgit v0.10.2 From ca9c9d0c922e4f1dac80699ebab1269d6dbaff85 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Wed, 5 Sep 2012 13:44:38 +0800 Subject: usb : Add sysfs files to control port power. This patch adds two sysfs files for each usb hub port to allow userspace to control the port power policy. For an upcoming Intel xHCI roothub, this will translate into ACPI calls to completely power off or power on the port. As a reminder, when these ports are completely powered off, the USB host and device will see a physical disconnect. All future USB device connections will be lost, and the device will not be able to signal a remote wakeup. The control sysfs file can be written to with two options: "on" - port power must be on. "off" - port must be off. The state sysfs file reports usb port's power state: "on" - powered on "off" - powered off "error" - can't get power state For now, let userspace dictate the port power off policy. Future patches may add an in-kernel policy. Acked-by: Alan Stern Signed-off-by: Lan Tianyu Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb index b6fbe51..13f3eee 100644 --- a/Documentation/ABI/testing/sysfs-bus-usb +++ b/Documentation/ABI/testing/sysfs-bus-usb @@ -227,3 +227,27 @@ Contact: Lan Tianyu Description: The /sys/bus/usb/devices/.../(hub interface)/portX is usb port device's sysfs directory. + +What: /sys/bus/usb/devices/.../(hub interface)/portX/control +Date: August 2012 +Contact: Lan Tianyu +Description: + The /sys/bus/usb/devices/.../(hub interface)/portX/control + attribute allows user space to control the power policy on + the usb port. + + All ports have one of the following two values for control + "on" - port power must be on. + "off" - port power must be off. + +What: /sys/bus/usb/devices/.../(hub interface)/portX/state +Date: August 2012 +Contact: Lan Tianyu +Description: + The /sys/bus/usb/devices/.../(hub interface)/portX/state + attribute allows user space to check hub port's power state. + + All ports have three following states + "on" - port power on + "off" - port power off + "error" - can't get the hub port's power state diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 4ffe837..3def91e 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -39,11 +39,17 @@ #endif #endif +enum port_power_policy { + USB_PORT_POWER_ON = 0, + USB_PORT_POWER_OFF, +}; + struct usb_port { struct usb_device *child; struct device dev; struct dev_state *port_owner; enum usb_port_connect_type connect_type; + enum port_power_policy port_power_policy; }; struct usb_hub { @@ -93,6 +99,10 @@ struct usb_hub { struct usb_port **ports; }; +static const char on_string[] = "on"; +static const char off_string[] = "off"; +static const struct attribute_group *port_dev_group[]; + static inline int hub_is_superspeed(struct usb_device *hdev) { return (hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS); @@ -845,7 +855,12 @@ static unsigned hub_power_on(struct usb_hub *hub, bool do_delay) dev_dbg(hub->intfdev, "trying to enable port power on " "non-switchable hub\n"); for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++) - set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER); + if (hub->ports[port1 - 1]->port_power_policy + == USB_PORT_POWER_ON) + set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER); + else + clear_port_feature(hub->hdev, port1, + USB_PORT_FEAT_POWER); /* Wait at least 100 msec for power to become stable */ delay = max(pgood_delay, (unsigned) 100); @@ -1263,6 +1278,7 @@ static int usb_hub_create_port_device(struct usb_hub *hub, hub->ports[port1 - 1] = port_dev; port_dev->dev.parent = hub->intfdev; + port_dev->dev.groups = port_dev_group; port_dev->dev.type = &usb_port_device_type; dev_set_name(&port_dev->dev, "port%d", port1); @@ -2627,6 +2643,25 @@ static int port_is_power_on(struct usb_hub *hub, unsigned portstatus) return ret; } +static int usb_get_hub_port_power_state(struct usb_device *hdev, int port1) +{ + struct usb_hub *hub = hdev_to_hub(hdev); + struct usb_port_status data; + u16 portstatus; + int ret; + + ret = get_port_status(hub->hdev, port1, &data); + if (ret < 4) { + dev_err(hub->intfdev, + "%s failed (err = %d)\n", __func__, ret); + if (ret >= 0) + ret = -EIO; + return ret; + } else + portstatus = le16_to_cpu(data.wPortStatus); + return port_is_power_on(hub, portstatus); +} + #ifdef CONFIG_PM /* Check if a port is suspended(USB2.0 port) or in U3 state(USB3.0 port) */ @@ -4633,6 +4668,102 @@ static int hub_thread(void *__unused) return 0; } +static ssize_t show_port_power_state(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_device *udev = to_usb_device(dev->parent->parent); + struct usb_interface *intf = to_usb_interface(dev->parent); + int port1, power_state; + const char *result; + + sscanf(dev_name(dev), "port%d", &port1); + usb_autopm_get_interface(intf); + power_state = usb_get_hub_port_power_state(udev, port1); + usb_autopm_put_interface(intf); + if (power_state == 1) + result = on_string; + else if (!power_state) + result = off_string; + else + result = "error"; + return sprintf(buf, "%s\n", result); +} +static DEVICE_ATTR(state, S_IRUGO, show_port_power_state, NULL); + +static ssize_t show_port_power_control(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct usb_port *hub_port = to_usb_port(dev); + const char *result; + + switch (hub_port->port_power_policy) { + case USB_PORT_POWER_ON: + result = on_string; + break; + case USB_PORT_POWER_OFF: + result = off_string; + break; + default: + return -EINVAL; + } + return sprintf(buf, "%s\n", result); +} + +static ssize_t store_port_power_control(struct device *dev, + struct device_attribute *attr, const char *buf, size_t count) +{ + struct usb_device *hdev = to_usb_device(dev->parent->parent); + struct usb_interface *intf = to_usb_interface(dev->parent); + struct usb_port *hub_port = to_usb_port(dev); + int port1, ret, len = count; + char *cp; + + sscanf(dev_name(dev), "port%d", &port1); + cp = memchr(buf, '\n', count); + if (cp) + len = cp - buf; + if (len == sizeof(on_string) - 1 + && strncmp(buf, on_string, len) == 0) { + hub_port->port_power_policy = USB_PORT_POWER_ON; + usb_autopm_get_interface(intf); + ret = set_port_feature(hdev, port1, USB_PORT_FEAT_POWER); + usb_autopm_put_interface(intf); + if (ret < 0) + return -EIO; + } else if (len == sizeof(off_string) - 1 + && strncmp(buf, off_string, len) == 0) { + struct usb_hub *hub = hdev_to_hub(hdev); + + hub_port->port_power_policy = USB_PORT_POWER_OFF; + usb_autopm_get_interface(intf); + hub_port_logical_disconnect(hub, port1); + ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_POWER); + usb_autopm_put_interface(intf); + if (ret < 0) + return -EIO; + } else + return -EINVAL; + + return count; +} +static DEVICE_ATTR(control, S_IWUSR | S_IRUGO, show_port_power_control, + store_port_power_control); + +static struct attribute *port_dev_attrs[] = { + &dev_attr_control.attr, + &dev_attr_state.attr, + NULL, +}; + +static struct attribute_group port_dev_attr_grp = { + .attrs = port_dev_attrs, +}; + +static const struct attribute_group *port_dev_group[] = { + &port_dev_attr_grp, + NULL, +}; + static const struct usb_device_id hub_id_table[] = { { .match_flags = USB_DEVICE_ID_MATCH_DEV_CLASS, .bDeviceClass = USB_CLASS_HUB}, -- cgit v0.10.2 From ca3c1539adfe9c1b86f16faf314b3bf54c3b5389 Mon Sep 17 00:00:00 2001 From: Lan Tianyu Date: Tue, 11 Sep 2012 04:22:36 +0800 Subject: usb: add little-endian transform for DeviceRemovable of usb3.0 hub Signed-off-by: Lan Tianyu Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 3def91e..aa45e43 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2190,7 +2190,8 @@ static void set_usb_port_removable(struct usb_device *udev) return; if (hub_is_superspeed(hdev)) { - if (hub->descriptor->u.ss.DeviceRemovable & (1 << port)) + if (le16_to_cpu(hub->descriptor->u.ss.DeviceRemovable) + & (1 << port)) removable = false; } else { if (hub->descriptor->u.hs.DeviceRemovable[port / 8] & (1 << (port % 8))) -- cgit v0.10.2 From 73d4066055e0e2830533041f4b91df8e6e5976ff Mon Sep 17 00:00:00 2001 From: Chuansheng Liu Date: Tue, 11 Sep 2012 16:00:30 +0800 Subject: USB/host: Cleanup unneccessary irq disable code Because the IRQF_DISABLED as the flag is now a NOOP and has been deprecated and in hardirq context the interrupt is disabled. so in usb/host code: Removing the usage of flag IRQF_DISABLED; Removing the calling local_irq save/restore actions in irq handler usb_hcd_irq(); Signed-off-by: liu chuansheng Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 6e4fd28..35b52f6 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -2153,15 +2153,8 @@ EXPORT_SYMBOL_GPL(usb_bus_start_enum); irqreturn_t usb_hcd_irq (int irq, void *__hcd) { struct usb_hcd *hcd = __hcd; - unsigned long flags; irqreturn_t rc; - /* IRQF_DISABLED doesn't work correctly with shared IRQs - * when the first handler doesn't use it. So let's just - * assume it's never used. - */ - local_irq_save(flags); - if (unlikely(HCD_DEAD(hcd) || !HCD_HW_ACCESSIBLE(hcd))) rc = IRQ_NONE; else if (hcd->driver->irq(hcd) == IRQ_NONE) @@ -2169,7 +2162,6 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd) else rc = IRQ_HANDLED; - local_irq_restore(flags); return rc; } EXPORT_SYMBOL_GPL(usb_hcd_irq); @@ -2357,14 +2349,6 @@ static int usb_hcd_request_irqs(struct usb_hcd *hcd, int retval; if (hcd->driver->irq) { - - /* IRQF_DISABLED doesn't work as advertised when used together - * with IRQF_SHARED. As usb_hcd_irq() will always disable - * interrupts we can remove it here. - */ - if (irqflags & IRQF_SHARED) - irqflags &= ~IRQF_DISABLED; - snprintf(hcd->irq_descr, sizeof(hcd->irq_descr), "%s:usb%d", hcd->driver->description, hcd->self.busnum); retval = request_irq(irqnum, &usb_hcd_irq, irqflags, diff --git a/drivers/usb/host/ehci-ls1x.c b/drivers/usb/host/ehci-ls1x.c index aa0f328..ca75965 100644 --- a/drivers/usb/host/ehci-ls1x.c +++ b/drivers/usb/host/ehci-ls1x.c @@ -113,7 +113,7 @@ static int ehci_hcd_ls1x_probe(struct platform_device *pdev) goto err_put_hcd; } - ret = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); + ret = usb_add_hcd(hcd, irq, IRQF_SHARED); if (ret) goto err_put_hcd; diff --git a/drivers/usb/host/ohci-xls.c b/drivers/usb/host/ohci-xls.c index 41e378f..84201cd 100644 --- a/drivers/usb/host/ohci-xls.c +++ b/drivers/usb/host/ohci-xls.c @@ -56,7 +56,7 @@ static int ohci_xls_probe_internal(const struct hc_driver *driver, goto err3; } - retval = usb_add_hcd(hcd, irq, IRQF_DISABLED | IRQF_SHARED); + retval = usb_add_hcd(hcd, irq, IRQF_SHARED); if (retval != 0) goto err4; return retval; -- cgit v0.10.2 From 94715d59453dd3aba588fd6b6881f4cb4fac5440 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Tue, 11 Sep 2012 14:39:38 +0530 Subject: arm: omap: hwmod: add a new addr space in otg for writing to control module The mailbox register for usb otg in omap is present in control module. On detection of any events VBUS or ID, this register should be written to send the notification to musb core. Till we have a separate control module driver to write to control module, omap2430 will handle the register writes to control module by itself. So a new address space to represent this control module register is added to usb_otg_hs. Acked-by: Benoit Cousson Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c index 242aee4..3c19120 100644 --- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c +++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c @@ -5890,6 +5890,12 @@ static struct omap_hwmod_addr_space omap44xx_usb_otg_hs_addrs[] = { .pa_end = 0x4a0ab003, .flags = ADDR_TYPE_RT }, + { + /* XXX: Remove this once control module driver is in place */ + .pa_start = 0x4a00233c, + .pa_end = 0x4a00233f, + .flags = ADDR_TYPE_RT + }, { } }; -- cgit v0.10.2 From 5ec40590765b8571ae6218f1bc421ec63d3e91c2 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Tue, 11 Sep 2012 14:39:39 +0530 Subject: usb: musb: omap: write directly to mailbox instead of using phy The glue layer should directly write to mailbox register (present in control module) instead of calling phy layer to write to mailbox register. Writing to mailbox register notifies the core of events like device connect/disconnect. Currently writing to control module register is taken care in this driver which will be removed once the control module driver is in place. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 02c39a7..f4d9503 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -45,6 +45,7 @@ struct omap2430_glue { struct platform_device *musb; enum omap_musb_vbus_id_status status; struct work_struct omap_musb_mailbox_work; + u32 __iomem *control_otghs; }; #define glue_to_musb(g) platform_get_drvdata(g->musb) @@ -52,6 +53,26 @@ struct omap2430_glue *_glue; static struct timer_list musb_idle_timer; +/** + * omap4_usb_phy_mailbox - write to usb otg mailbox + * @glue: struct omap2430_glue * + * @val: the value to be written to the mailbox + * + * On detection of a device (ID pin is grounded), this API should be called + * to set AVALID, VBUSVALID and ID pin is grounded. + * + * When OMAP is connected to a host (OMAP in device mode), this API + * is called to set AVALID, VBUSVALID and ID pin in high impedance. + * + * XXX: This function will be removed once we have a seperate driver for + * control module + */ +static void omap4_usb_phy_mailbox(struct omap2430_glue *glue, u32 val) +{ + if (glue->control_otghs) + writel(val, glue->control_otghs); +} + static void musb_do_idle(unsigned long _musb) { struct musb *musb = (void *)_musb; @@ -247,6 +268,7 @@ EXPORT_SYMBOL_GPL(omap_musb_mailbox); static void omap_musb_set_mailbox(struct omap2430_glue *glue) { + u32 val; struct musb *musb = glue_to_musb(glue); struct device *dev = musb->controller; struct musb_hdrc_platform_data *pdata = dev->platform_data; @@ -262,7 +284,8 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) musb->xceiv->last_event = USB_EVENT_ID; if (musb->gadget_driver) { pm_runtime_get_sync(dev); - usb_phy_init(musb->xceiv); + val = AVALID | VBUSVALID; + omap4_usb_phy_mailbox(glue, val); omap2430_musb_set_vbus(musb, 1); } break; @@ -275,7 +298,8 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) musb->xceiv->last_event = USB_EVENT_VBUS; if (musb->gadget_driver) pm_runtime_get_sync(dev); - usb_phy_init(musb->xceiv); + val = IDDIG | AVALID | VBUSVALID; + omap4_usb_phy_mailbox(glue, val); break; case OMAP_MUSB_ID_FLOAT: @@ -292,7 +316,8 @@ static void omap_musb_set_mailbox(struct omap2430_glue *glue) if (musb->xceiv->otg->set_vbus) otg_set_vbus(musb->xceiv->otg, 0); } - usb_phy_shutdown(musb->xceiv); + val = SESSEND | IDDIG; + omap4_usb_phy_mailbox(glue, val); break; default: dev_dbg(dev, "ID float\n"); @@ -367,6 +392,7 @@ err1: static void omap2430_musb_enable(struct musb *musb) { u8 devctl; + u32 val; unsigned long timeout = jiffies + msecs_to_jiffies(1000); struct device *dev = musb->controller; struct omap2430_glue *glue = dev_get_drvdata(dev->parent); @@ -376,7 +402,8 @@ static void omap2430_musb_enable(struct musb *musb) switch (glue->status) { case OMAP_MUSB_ID_GROUND: - usb_phy_init(musb->xceiv); + val = AVALID | VBUSVALID; + omap4_usb_phy_mailbox(glue, val); if (data->interface_type != MUSB_INTERFACE_UTMI) break; devctl = musb_readb(musb->mregs, MUSB_DEVCTL); @@ -395,7 +422,8 @@ static void omap2430_musb_enable(struct musb *musb) break; case OMAP_MUSB_VBUS_VALID: - usb_phy_init(musb->xceiv); + val = IDDIG | AVALID | VBUSVALID; + omap4_usb_phy_mailbox(glue, val); break; default: @@ -405,11 +433,14 @@ static void omap2430_musb_enable(struct musb *musb) static void omap2430_musb_disable(struct musb *musb) { + u32 val; struct device *dev = musb->controller; struct omap2430_glue *glue = dev_get_drvdata(dev->parent); - if (glue->status != OMAP_MUSB_UNKNOWN) - usb_phy_shutdown(musb->xceiv); + if (glue->status != OMAP_MUSB_UNKNOWN) { + val = SESSEND | IDDIG; + omap4_usb_phy_mailbox(glue, val); + } } static int omap2430_musb_exit(struct musb *musb) @@ -441,6 +472,7 @@ static int __devinit omap2430_probe(struct platform_device *pdev) struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; struct platform_device *musb; struct omap2430_glue *glue; + struct resource *res; int ret = -ENOMEM; glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL); @@ -463,6 +495,12 @@ static int __devinit omap2430_probe(struct platform_device *pdev) glue->musb = musb; glue->status = OMAP_MUSB_UNKNOWN; + res = platform_get_resource(pdev, IORESOURCE_MEM, 1); + + glue->control_otghs = devm_request_and_ioremap(&pdev->dev, res); + if (glue->control_otghs == NULL) + dev_dbg(&pdev->dev, "Failed to obtain control memory\n"); + pdata->platform_ops = &omap2430_ops; platform_set_drvdata(pdev, glue); diff --git a/drivers/usb/musb/omap2430.h b/drivers/usb/musb/omap2430.h index 40b3c02..b85f397 100644 --- a/drivers/usb/musb/omap2430.h +++ b/drivers/usb/musb/omap2430.h @@ -49,4 +49,13 @@ #define OTG_FORCESTDBY 0x414 # define ENABLEFORCE (1 << 0) +/* + * Control Module bit definitions + * XXX: Will be removed once we have a driver for control module. + */ +#define AVALID BIT(0) +#define BVALID BIT(1) +#define VBUSVALID BIT(2) +#define SESSEND BIT(3) +#define IDDIG BIT(4) #endif /* __MUSB_OMAP243X_H__ */ -- cgit v0.10.2 From 00a0b1d58af873d842580dcac55f3b156c3a4077 Mon Sep 17 00:00:00 2001 From: Kishon Vijay Abraham I Date: Tue, 11 Sep 2012 14:39:40 +0530 Subject: usb: musb: omap: Add device tree support for omap musb glue Added device tree support for omap musb driver and updated the Documentation with device tree binding information. Signed-off-by: Kishon Vijay Abraham I Signed-off-by: Felipe Balbi diff --git a/Documentation/devicetree/bindings/usb/omap-usb.txt b/Documentation/devicetree/bindings/usb/omap-usb.txt new file mode 100644 index 0000000..29a043e --- /dev/null +++ b/Documentation/devicetree/bindings/usb/omap-usb.txt @@ -0,0 +1,33 @@ +OMAP GLUE + +OMAP MUSB GLUE + - compatible : Should be "ti,omap4-musb" or "ti,omap3-musb" + - ti,hwmods : must be "usb_otg_hs" + - multipoint : Should be "1" indicating the musb controller supports + multipoint. This is a MUSB configuration-specific setting. + - num_eps : Specifies the number of endpoints. This is also a + MUSB configuration-specific setting. Should be set to "16" + - ram_bits : Specifies the ram address size. Should be set to "12" + - interface_type : This is a board specific setting to describe the type of + interface between the controller and the phy. It should be "0" or "1" + specifying ULPI and UTMI respectively. + - mode : Should be "3" to represent OTG. "1" signifies HOST and "2" + represents PERIPHERAL. + - power : Should be "50". This signifies the controller can supply upto + 100mA when operating in host mode. + +SOC specific device node entry +usb_otg_hs: usb_otg_hs@4a0ab000 { + compatible = "ti,omap4-musb"; + ti,hwmods = "usb_otg_hs"; + multipoint = <1>; + num_eps = <16>; + ram_bits = <12>; +}; + +Board specific device node entry +&usb_otg_hs { + interface_type = <1>; + mode = <3>; + power = <50>; +}; diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index f4d9503..d96873b 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -470,8 +471,11 @@ static u64 omap2430_dmamask = DMA_BIT_MASK(32); static int __devinit omap2430_probe(struct platform_device *pdev) { struct musb_hdrc_platform_data *pdata = pdev->dev.platform_data; + struct omap_musb_board_data *data; struct platform_device *musb; struct omap2430_glue *glue; + struct device_node *np = pdev->dev.of_node; + struct musb_hdrc_config *config; struct resource *res; int ret = -ENOMEM; @@ -501,6 +505,42 @@ static int __devinit omap2430_probe(struct platform_device *pdev) if (glue->control_otghs == NULL) dev_dbg(&pdev->dev, "Failed to obtain control memory\n"); + if (np) { + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + dev_err(&pdev->dev, + "failed to allocate musb platfrom data\n"); + ret = -ENOMEM; + goto err1; + } + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) { + dev_err(&pdev->dev, + "failed to allocate musb board data\n"); + ret = -ENOMEM; + goto err1; + } + + config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL); + if (!data) { + dev_err(&pdev->dev, + "failed to allocate musb hdrc config\n"); + goto err1; + } + + of_property_read_u32(np, "mode", (u32 *)&pdata->mode); + of_property_read_u32(np, "interface_type", + (u32 *)&data->interface_type); + of_property_read_u32(np, "num_eps", (u32 *)&config->num_eps); + of_property_read_u32(np, "ram_bits", (u32 *)&config->ram_bits); + of_property_read_u32(np, "power", (u32 *)&pdata->power); + config->multipoint = of_property_read_bool(np, "multipoint"); + + pdata->board_data = data; + pdata->config = config; + } + pdata->platform_ops = &omap2430_ops; platform_set_drvdata(pdev, glue); @@ -597,12 +637,26 @@ static struct dev_pm_ops omap2430_pm_ops = { #define DEV_PM_OPS NULL #endif +#ifdef CONFIG_OF +static const struct of_device_id omap2430_id_table[] = { + { + .compatible = "ti,omap4-musb" + }, + { + .compatible = "ti,omap3-musb" + }, + {}, +}; +MODULE_DEVICE_TABLE(of, omap2430_id_table); +#endif + static struct platform_driver omap2430_driver = { .probe = omap2430_probe, .remove = __devexit_p(omap2430_remove), .driver = { .name = "musb-omap2430", .pm = DEV_PM_OPS, + .of_match_table = of_match_ptr(omap2430_id_table), }, }; -- cgit v0.10.2 From 65b3d52d02a558fbfe08e43688e15390c5ab3067 Mon Sep 17 00:00:00 2001 From: "B, Ravi" Date: Fri, 31 Aug 2012 11:09:49 +0000 Subject: usb: musb: add musb_ida for multi instance support Added musb_ida in musb_core.c to manage the multi core ids. Signed-off-by: Ravi Babu Signed-off-by: Ajay Kumar Gupta Signed-off-by: Santhapuri, Damodar Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c index 9fbe736..de717b5 100644 --- a/drivers/usb/musb/am35x.c +++ b/drivers/usb/musb/am35x.c @@ -458,6 +458,7 @@ static int __devinit am35x_probe(struct platform_device *pdev) struct clk *clk; int ret = -ENOMEM; + int musbid; glue = kzalloc(sizeof(*glue), GFP_KERNEL); if (!glue) { @@ -465,38 +466,47 @@ static int __devinit am35x_probe(struct platform_device *pdev) goto err0; } - musb = platform_device_alloc("musb-hdrc", -1); + /* get the musb id */ + musbid = musb_get_id(&pdev->dev, GFP_KERNEL); + if (musbid < 0) { + dev_err(&pdev->dev, "failed to allocate musb id\n"); + ret = -ENOMEM; + goto err1; + } + + musb = platform_device_alloc("musb-hdrc", musbid); if (!musb) { dev_err(&pdev->dev, "failed to allocate musb device\n"); - goto err1; + goto err2; } phy_clk = clk_get(&pdev->dev, "fck"); if (IS_ERR(phy_clk)) { dev_err(&pdev->dev, "failed to get PHY clock\n"); ret = PTR_ERR(phy_clk); - goto err2; + goto err3; } clk = clk_get(&pdev->dev, "ick"); if (IS_ERR(clk)) { dev_err(&pdev->dev, "failed to get clock\n"); ret = PTR_ERR(clk); - goto err3; + goto err4; } ret = clk_enable(phy_clk); if (ret) { dev_err(&pdev->dev, "failed to enable PHY clock\n"); - goto err4; + goto err5; } ret = clk_enable(clk); if (ret) { dev_err(&pdev->dev, "failed to enable clock\n"); - goto err5; + goto err6; } + musb->id = musbid; musb->dev.parent = &pdev->dev; musb->dev.dma_mask = &am35x_dmamask; musb->dev.coherent_dma_mask = am35x_dmamask; @@ -514,38 +524,41 @@ static int __devinit am35x_probe(struct platform_device *pdev) pdev->num_resources); if (ret) { dev_err(&pdev->dev, "failed to add resources\n"); - goto err6; + goto err7; } ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); if (ret) { dev_err(&pdev->dev, "failed to add platform_data\n"); - goto err6; + goto err7; } ret = platform_device_add(musb); if (ret) { dev_err(&pdev->dev, "failed to register musb device\n"); - goto err6; + goto err7; } return 0; -err6: +err7: clk_disable(clk); -err5: +err6: clk_disable(phy_clk); -err4: +err5: clk_put(clk); -err3: +err4: clk_put(phy_clk); -err2: +err3: platform_device_put(musb); +err2: + musb_put_id(&pdev->dev, musbid); + err1: kfree(glue); @@ -557,6 +570,7 @@ static int __devexit am35x_remove(struct platform_device *pdev) { struct am35x_glue *glue = platform_get_drvdata(pdev); + musb_put_id(&pdev->dev, glue->musb->id); platform_device_del(glue->musb); platform_device_put(glue->musb); clk_disable(glue->clk); diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c index 54f1b98..26cc8b7 100644 --- a/drivers/usb/musb/blackfin.c +++ b/drivers/usb/musb/blackfin.c @@ -454,6 +454,7 @@ static int __devinit bfin_probe(struct platform_device *pdev) struct bfin_glue *glue; int ret = -ENOMEM; + int musbid; glue = kzalloc(sizeof(*glue), GFP_KERNEL); if (!glue) { @@ -461,12 +462,21 @@ static int __devinit bfin_probe(struct platform_device *pdev) goto err0; } - musb = platform_device_alloc("musb-hdrc", -1); + /* get the musb id */ + musbid = musb_get_id(&pdev->dev, GFP_KERNEL); + if (musbid < 0) { + dev_err(&pdev->dev, "failed to allocate musb id\n"); + ret = -ENOMEM; + goto err1; + } + + musb = platform_device_alloc("musb-hdrc", musbid); if (!musb) { dev_err(&pdev->dev, "failed to allocate musb device\n"); - goto err1; + goto err2; } + musb->id = musbid; musb->dev.parent = &pdev->dev; musb->dev.dma_mask = &bfin_dmamask; musb->dev.coherent_dma_mask = bfin_dmamask; @@ -482,26 +492,29 @@ static int __devinit bfin_probe(struct platform_device *pdev) pdev->num_resources); if (ret) { dev_err(&pdev->dev, "failed to add resources\n"); - goto err2; + goto err3; } ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); if (ret) { dev_err(&pdev->dev, "failed to add platform_data\n"); - goto err2; + goto err3; } ret = platform_device_add(musb); if (ret) { dev_err(&pdev->dev, "failed to register musb device\n"); - goto err2; + goto err3; } return 0; -err2: +err3: platform_device_put(musb); +err2: + musb_put_id(&pdev->dev, musbid); + err1: kfree(glue); @@ -513,6 +526,7 @@ static int __devexit bfin_remove(struct platform_device *pdev) { struct bfin_glue *glue = platform_get_drvdata(pdev); + musb_put_id(&pdev->dev, glue->musb->id); platform_device_del(glue->musb); platform_device_put(glue->musb); kfree(glue); diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c index 4e4df9d..ddb9c9c 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c @@ -479,6 +479,7 @@ static int __devinit da8xx_probe(struct platform_device *pdev) struct clk *clk; int ret = -ENOMEM; + int musbid; glue = kzalloc(sizeof(*glue), GFP_KERNEL); if (!glue) { @@ -486,25 +487,34 @@ static int __devinit da8xx_probe(struct platform_device *pdev) goto err0; } - musb = platform_device_alloc("musb-hdrc", -1); + /* get the musb id */ + musbid = musb_get_id(&pdev->dev, GFP_KERNEL); + if (musbid < 0) { + dev_err(&pdev->dev, "failed to allocate musb id\n"); + ret = -ENOMEM; + goto err1; + } + + musb = platform_device_alloc("musb-hdrc", musbid); if (!musb) { dev_err(&pdev->dev, "failed to allocate musb device\n"); - goto err1; + goto err2; } clk = clk_get(&pdev->dev, "usb20"); if (IS_ERR(clk)) { dev_err(&pdev->dev, "failed to get clock\n"); ret = PTR_ERR(clk); - goto err2; + goto err3; } ret = clk_enable(clk); if (ret) { dev_err(&pdev->dev, "failed to enable clock\n"); - goto err3; + goto err4; } + musb->id = musbid; musb->dev.parent = &pdev->dev; musb->dev.dma_mask = &da8xx_dmamask; musb->dev.coherent_dma_mask = da8xx_dmamask; @@ -521,32 +531,35 @@ static int __devinit da8xx_probe(struct platform_device *pdev) pdev->num_resources); if (ret) { dev_err(&pdev->dev, "failed to add resources\n"); - goto err4; + goto err5; } ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); if (ret) { dev_err(&pdev->dev, "failed to add platform_data\n"); - goto err4; + goto err5; } ret = platform_device_add(musb); if (ret) { dev_err(&pdev->dev, "failed to register musb device\n"); - goto err4; + goto err5; } return 0; -err4: +err5: clk_disable(clk); -err3: +err4: clk_put(clk); -err2: +err3: platform_device_put(musb); +err2: + musb_put_id(&pdev->dev, musbid); + err1: kfree(glue); @@ -558,6 +571,7 @@ static int __devexit da8xx_remove(struct platform_device *pdev) { struct da8xx_glue *glue = platform_get_drvdata(pdev); + musb_put_id(&pdev->dev, glue->musb->id); platform_device_del(glue->musb); platform_device_put(glue->musb); clk_disable(glue->clk); diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 8805f80..c269e61 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -511,6 +511,7 @@ static int __devinit davinci_probe(struct platform_device *pdev) struct clk *clk; int ret = -ENOMEM; + int musbid; glue = kzalloc(sizeof(*glue), GFP_KERNEL); if (!glue) { @@ -518,25 +519,34 @@ static int __devinit davinci_probe(struct platform_device *pdev) goto err0; } - musb = platform_device_alloc("musb-hdrc", -1); + /* get the musb id */ + musbid = musb_get_id(&pdev->dev, GFP_KERNEL); + if (musbid < 0) { + dev_err(&pdev->dev, "failed to allocate musb id\n"); + ret = -ENOMEM; + goto err1; + } + + musb = platform_device_alloc("musb-hdrc", musbid); if (!musb) { dev_err(&pdev->dev, "failed to allocate musb device\n"); - goto err1; + goto err2; } clk = clk_get(&pdev->dev, "usb"); if (IS_ERR(clk)) { dev_err(&pdev->dev, "failed to get clock\n"); ret = PTR_ERR(clk); - goto err2; + goto err3; } ret = clk_enable(clk); if (ret) { dev_err(&pdev->dev, "failed to enable clock\n"); - goto err3; + goto err4; } + musb->id = musbid; musb->dev.parent = &pdev->dev; musb->dev.dma_mask = &davinci_dmamask; musb->dev.coherent_dma_mask = davinci_dmamask; @@ -553,32 +563,35 @@ static int __devinit davinci_probe(struct platform_device *pdev) pdev->num_resources); if (ret) { dev_err(&pdev->dev, "failed to add resources\n"); - goto err4; + goto err5; } ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); if (ret) { dev_err(&pdev->dev, "failed to add platform_data\n"); - goto err4; + goto err5; } ret = platform_device_add(musb); if (ret) { dev_err(&pdev->dev, "failed to register musb device\n"); - goto err4; + goto err5; } return 0; -err4: +err5: clk_disable(clk); -err3: +err4: clk_put(clk); -err2: +err3: platform_device_put(musb); +err2: + musb_put_id(&pdev->dev, musbid); + err1: kfree(glue); @@ -590,6 +603,7 @@ static int __devexit davinci_remove(struct platform_device *pdev) { struct davinci_glue *glue = platform_get_drvdata(pdev); + musb_put_id(&pdev->dev, glue->musb->id); platform_device_del(glue->musb); platform_device_put(glue->musb); clk_disable(glue->clk); diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 5cacccb..61b64fc 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -99,6 +99,7 @@ #include #include #include +#include #include "musb_core.h" @@ -114,6 +115,7 @@ #define MUSB_DRIVER_NAME "musb-hdrc" const char musb_driver_name[] = MUSB_DRIVER_NAME; +static DEFINE_IDA(musb_ida); MODULE_DESCRIPTION(DRIVER_INFO); MODULE_AUTHOR(DRIVER_AUTHOR); @@ -130,6 +132,35 @@ static inline struct musb *dev_to_musb(struct device *dev) /*-------------------------------------------------------------------------*/ +int musb_get_id(struct device *dev, gfp_t gfp_mask) +{ + int ret; + int id; + + ret = ida_pre_get(&musb_ida, gfp_mask); + if (!ret) { + dev_err(dev, "failed to reserve resource for id\n"); + return -ENOMEM; + } + + ret = ida_get_new(&musb_ida, &id); + if (ret < 0) { + dev_err(dev, "failed to allocate a new id\n"); + return ret; + } + + return id; +} +EXPORT_SYMBOL_GPL(musb_get_id); + +void musb_put_id(struct device *dev, int id) +{ + + dev_dbg(dev, "removing id %d\n", id); + ida_remove(&musb_ida, id); +} +EXPORT_SYMBOL_GPL(musb_put_id); + #ifndef CONFIG_BLACKFIN static int musb_ulpi_read(struct usb_phy *phy, u32 offset) { diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index a1a32c6..a69ffd6 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -517,6 +517,8 @@ extern const char musb_driver_name[]; extern void musb_start(struct musb *musb); extern void musb_stop(struct musb *musb); +extern int musb_get_id(struct device *dev, gfp_t gfp_mask); +extern void musb_put_id(struct device *dev, int id); extern void musb_write_fifo(struct musb_hw_ep *ep, u16 len, const u8 *src); extern void musb_read_fifo(struct musb_hw_ep *ep, u16 len, u8 *dst); diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 51ff1bb..5351e96 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -448,7 +448,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) struct resource *res; struct resource resources[2]; char res_name[10]; - int ret; + int ret, musbid; /* get memory resource */ sprintf(res_name, "musb%d", id); @@ -473,14 +473,22 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) res->parent = NULL; resources[1] = *res; + /* get the musb id */ + musbid = musb_get_id(dev, GFP_KERNEL); + if (musbid < 0) { + dev_err(dev, "failed to allocate musb id\n"); + ret = -ENOMEM; + goto err0; + } /* allocate the child platform device */ - musb = platform_device_alloc("musb-hdrc", -1); + musb = platform_device_alloc("musb-hdrc", musbid); if (!musb) { dev_err(dev, "failed to allocate musb device\n"); ret = -ENOMEM; - goto err0; + goto err1; } + musb->id = musbid; musb->dev.parent = dev; musb->dev.dma_mask = &musb_dmamask; musb->dev.coherent_dma_mask = musb_dmamask; @@ -492,31 +500,34 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) ret = platform_device_add_resources(musb, resources, 2); if (ret) { dev_err(dev, "failed to add resources\n"); - goto err1; + goto err2; } ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); if (ret) { dev_err(dev, "failed to add platform_data\n"); - goto err1; + goto err2; } ret = platform_device_add(musb); if (ret) { dev_err(dev, "failed to register musb device\n"); - goto err1; + goto err2; } return 0; -err1: +err2: platform_device_put(musb); +err1: + musb_put_id(dev, musbid); err0: return ret; } static void __devexit dsps_delete_musb_pdev(struct dsps_glue *glue) { + musb_put_id(glue->dev, glue->musb->id); platform_device_del(glue->musb); platform_device_put(glue->musb); } diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index d96873b..a538fe1 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c @@ -478,6 +478,7 @@ static int __devinit omap2430_probe(struct platform_device *pdev) struct musb_hdrc_config *config; struct resource *res; int ret = -ENOMEM; + int musbid; glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL); if (!glue) { @@ -485,12 +486,21 @@ static int __devinit omap2430_probe(struct platform_device *pdev) goto err0; } - musb = platform_device_alloc("musb-hdrc", -1); + /* get the musb id */ + musbid = musb_get_id(&pdev->dev, GFP_KERNEL); + if (musbid < 0) { + dev_err(&pdev->dev, "failed to allocate musb id\n"); + ret = -ENOMEM; + goto err0; + } + + musb = platform_device_alloc("musb-hdrc", musbid); if (!musb) { dev_err(&pdev->dev, "failed to allocate musb device\n"); - goto err0; + goto err1; } + musb->id = musbid; musb->dev.parent = &pdev->dev; musb->dev.dma_mask = &omap2430_dmamask; musb->dev.coherent_dma_mask = omap2430_dmamask; @@ -557,13 +567,13 @@ static int __devinit omap2430_probe(struct platform_device *pdev) pdev->num_resources); if (ret) { dev_err(&pdev->dev, "failed to add resources\n"); - goto err1; + goto err2; } ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); if (ret) { dev_err(&pdev->dev, "failed to add platform_data\n"); - goto err1; + goto err2; } pm_runtime_enable(&pdev->dev); @@ -571,14 +581,17 @@ static int __devinit omap2430_probe(struct platform_device *pdev) ret = platform_device_add(musb); if (ret) { dev_err(&pdev->dev, "failed to register musb device\n"); - goto err1; + goto err2; } return 0; -err1: +err2: platform_device_put(musb); +err1: + musb_put_id(&pdev->dev, musbid); + err0: return ret; } @@ -588,6 +601,7 @@ static int __devexit omap2430_remove(struct platform_device *pdev) struct omap2430_glue *glue = platform_get_drvdata(pdev); cancel_work_sync(&glue->omap_musb_mailbox_work); + musb_put_id(&pdev->dev, glue->musb->id); platform_device_unregister(glue->musb); return 0; diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c index 1d0c090..878655f 100644 --- a/drivers/usb/musb/tusb6010.c +++ b/drivers/usb/musb/tusb6010.c @@ -1159,6 +1159,7 @@ static int __devinit tusb_probe(struct platform_device *pdev) struct tusb6010_glue *glue; int ret = -ENOMEM; + int musbid; glue = kzalloc(sizeof(*glue), GFP_KERNEL); if (!glue) { @@ -1166,12 +1167,21 @@ static int __devinit tusb_probe(struct platform_device *pdev) goto err0; } - musb = platform_device_alloc("musb-hdrc", -1); + /* get the musb id */ + musbid = musb_get_id(&pdev->dev, GFP_KERNEL); + if (musbid < 0) { + dev_err(&pdev->dev, "failed to allocate musb id\n"); + ret = -ENOMEM; + goto err1; + } + + musb = platform_device_alloc("musb-hdrc", musbid); if (!musb) { dev_err(&pdev->dev, "failed to allocate musb device\n"); - goto err1; + goto err2; } + musb->id = musbid; musb->dev.parent = &pdev->dev; musb->dev.dma_mask = &tusb_dmamask; musb->dev.coherent_dma_mask = tusb_dmamask; @@ -1187,26 +1197,29 @@ static int __devinit tusb_probe(struct platform_device *pdev) pdev->num_resources); if (ret) { dev_err(&pdev->dev, "failed to add resources\n"); - goto err2; + goto err3; } ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); if (ret) { dev_err(&pdev->dev, "failed to add platform_data\n"); - goto err2; + goto err3; } ret = platform_device_add(musb); if (ret) { dev_err(&pdev->dev, "failed to register musb device\n"); - goto err1; + goto err3; } return 0; -err2: +err3: platform_device_put(musb); +err2: + musb_put_id(&pdev->dev, musbid); + err1: kfree(glue); @@ -1218,6 +1231,7 @@ static int __devexit tusb_remove(struct platform_device *pdev) { struct tusb6010_glue *glue = platform_get_drvdata(pdev); + musb_put_id(&pdev->dev, glue->musb->id); platform_device_del(glue->musb); platform_device_put(glue->musb); kfree(glue); diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c index a8c0fad..d62a91f 100644 --- a/drivers/usb/musb/ux500.c +++ b/drivers/usb/musb/ux500.c @@ -74,25 +74,34 @@ static int __devinit ux500_probe(struct platform_device *pdev) goto err0; } - musb = platform_device_alloc("musb-hdrc", -1); + /* get the musb id */ + musbid = musb_get_id(&pdev->dev, GFP_KERNEL); + if (musbid < 0) { + dev_err(&pdev->dev, "failed to allocate musb id\n"); + ret = -ENOMEM; + goto err1; + } + + musb = platform_device_alloc("musb-hdrc", musbid); if (!musb) { dev_err(&pdev->dev, "failed to allocate musb device\n"); - goto err1; + goto err2; } clk = clk_get(&pdev->dev, "usb"); if (IS_ERR(clk)) { dev_err(&pdev->dev, "failed to get clock\n"); ret = PTR_ERR(clk); - goto err2; + goto err3; } ret = clk_enable(clk); if (ret) { dev_err(&pdev->dev, "failed to enable clock\n"); - goto err3; + goto err4; } + musb->id = musbid; musb->dev.parent = &pdev->dev; musb->dev.dma_mask = pdev->dev.dma_mask; musb->dev.coherent_dma_mask = pdev->dev.coherent_dma_mask; @@ -109,32 +118,35 @@ static int __devinit ux500_probe(struct platform_device *pdev) pdev->num_resources); if (ret) { dev_err(&pdev->dev, "failed to add resources\n"); - goto err4; + goto err5; } ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); if (ret) { dev_err(&pdev->dev, "failed to add platform_data\n"); - goto err4; + goto err5; } ret = platform_device_add(musb); if (ret) { dev_err(&pdev->dev, "failed to register musb device\n"); - goto err4; + goto err5; } return 0; -err4: +err5: clk_disable(clk); -err3: +err4: clk_put(clk); -err2: +err3: platform_device_put(musb); +err2: + musb_put_id(&pdev->dev, musbid); + err1: kfree(glue); @@ -146,6 +158,7 @@ static int __devexit ux500_remove(struct platform_device *pdev) { struct ux500_glue *glue = platform_get_drvdata(pdev); + musb_put_id(&pdev->dev, glue->musb->id); platform_device_del(glue->musb); platform_device_put(glue->musb); clk_disable(glue->clk); -- cgit v0.10.2 From 8d2421e68cb8a159963641eab72f8f8ba1c7f7b0 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Fri, 31 Aug 2012 11:09:50 +0000 Subject: usb: musb: kill global and static for multi instance Moved global variable "musb_debugfs_root" and static variable "old_state" to 'struct musb' to help support multi instance of musb controller as present on AM335x platform. Also removed the global variable "orig_dma_mask" and filled the dev->dma_mask with parent device's dma_mask. Signed-off-by: Ajay Kumar Gupta Signed-off-by: Santhapuri, Damodar Signed-off-by: Ravi Babu Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 61b64fc..bb56a0e 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -100,6 +100,7 @@ #include #include #include +#include #include "musb_core.h" @@ -1797,10 +1798,9 @@ static const struct attribute_group musb_attr_group = { static void musb_irq_work(struct work_struct *data) { struct musb *musb = container_of(data, struct musb, irq_work); - static int old_state; - if (musb->xceiv->state != old_state) { - old_state = musb->xceiv->state; + if (musb->xceiv->state != musb->xceiv_old_state) { + musb->xceiv_old_state = musb->xceiv->state; sysfs_notify(&musb->controller->kobj, NULL, "mode"); } } @@ -2060,11 +2060,6 @@ fail0: /* all implementations (PCI bridge to FPGA, VLYNQ, etc) should just * bridge to a platform device; this driver then suffices. */ - -#ifndef CONFIG_MUSB_PIO_ONLY -static u64 *orig_dma_mask; -#endif - static int __devinit musb_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; @@ -2083,10 +2078,6 @@ static int __devinit musb_probe(struct platform_device *pdev) return -ENOMEM; } -#ifndef CONFIG_MUSB_PIO_ONLY - /* clobbered by use_dma=n */ - orig_dma_mask = dev->dma_mask; -#endif status = musb_init_controller(dev, irq, base); if (status < 0) iounmap(base); @@ -2096,7 +2087,8 @@ static int __devinit musb_probe(struct platform_device *pdev) static int __devexit musb_remove(struct platform_device *pdev) { - struct musb *musb = dev_to_musb(&pdev->dev); + struct device *dev = &pdev->dev; + struct musb *musb = dev_to_musb(dev); void __iomem *ctrl_base = musb->ctrl_base; /* this gets called on rmmod. @@ -2109,9 +2101,9 @@ static int __devexit musb_remove(struct platform_device *pdev) musb_free(musb); iounmap(ctrl_base); - device_init_wakeup(&pdev->dev, 0); + device_init_wakeup(dev, 0); #ifndef CONFIG_MUSB_PIO_ONLY - pdev->dev.dma_mask = orig_dma_mask; + dma_set_mask(dev, *dev->parent->dma_mask); #endif return 0; } diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index a69ffd6..c158aac 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -437,6 +437,10 @@ struct musb { #ifdef MUSB_CONFIG_PROC_FS struct proc_dir_entry *proc_entry; #endif + int xceiv_old_state; +#ifdef CONFIG_DEBUG_FS + struct dentry *debugfs_root; +#endif }; static inline struct musb *gadget_to_musb(struct usb_gadget *g) diff --git a/drivers/usb/musb/musb_debugfs.c b/drivers/usb/musb/musb_debugfs.c index 40a37c9..1d6e8af 100644 --- a/drivers/usb/musb/musb_debugfs.c +++ b/drivers/usb/musb/musb_debugfs.c @@ -103,8 +103,6 @@ static const struct musb_register_map musb_regmap[] = { { } /* Terminating Entry */ }; -static struct dentry *musb_debugfs_root; - static int musb_regdump_show(struct seq_file *s, void *unused) { struct musb *musb = s->private; @@ -241,7 +239,7 @@ int __devinit musb_init_debugfs(struct musb *musb) struct dentry *file; int ret; - root = debugfs_create_dir("musb", NULL); + root = debugfs_create_dir(dev_name(musb->controller), NULL); if (!root) { ret = -ENOMEM; goto err0; @@ -261,7 +259,7 @@ int __devinit musb_init_debugfs(struct musb *musb) goto err1; } - musb_debugfs_root = root; + musb->debugfs_root = root; return 0; @@ -274,5 +272,5 @@ err0: void /* __init_or_exit */ musb_exit_debugfs(struct musb *musb) { - debugfs_remove_recursive(musb_debugfs_root); + debugfs_remove_recursive(musb->debugfs_root); } -- cgit v0.10.2 From db4a93202e086dbdb5789149666dbbff48f708bf Mon Sep 17 00:00:00 2001 From: "B, Ravi" Date: Fri, 31 Aug 2012 11:09:51 +0000 Subject: usb: musb: am335x: add support for dual instance AM335x and TI81xx platform has dual musb controller so updating the musb_dspc.c to support the same. Changes: - Moved otg_workaround timer to glue structure - Moved static local variable last_timer to glue structure - PHY on/off related cleanups Signed-off-by: Ravi Babu Signed-off-by: Ajay Kumar Gupta Signed-off-by: Santhapuri, Damodar [afzal@ti.com: remove control module related modifications] Signed-off-by: Afzal Mohammed Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 5351e96..796fc60 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -105,6 +105,8 @@ struct dsps_musb_wrapper { /* miscellaneous stuff */ u32 musb_core_offset; u8 poll_seconds; + /* number of musb instances */ + u8 instances; }; /** @@ -112,9 +114,10 @@ struct dsps_musb_wrapper { */ struct dsps_glue { struct device *dev; - struct platform_device *musb; /* child musb pdev */ + struct platform_device *musb[2]; /* child musb pdev */ const struct dsps_musb_wrapper *wrp; /* wrapper register offsets */ - struct timer_list timer; /* otg_workaround timer */ + struct timer_list timer[2]; /* otg_workaround timer */ + unsigned long last_timer[2]; /* last timer data for each instance */ }; /** @@ -164,8 +167,8 @@ static void otg_timer(unsigned long _musb) struct musb *musb = (void *)_musb; void __iomem *mregs = musb->mregs; struct device *dev = musb->controller; - struct platform_device *pdev = to_platform_device(dev->parent); - struct dsps_glue *glue = platform_get_drvdata(pdev); + struct platform_device *pdev = to_platform_device(dev); + struct dsps_glue *glue = dev_get_drvdata(dev->parent); const struct dsps_musb_wrapper *wrp = glue->wrp; u8 devctl; unsigned long flags; @@ -201,7 +204,7 @@ static void otg_timer(unsigned long _musb) case OTG_STATE_B_IDLE: devctl = dsps_readb(mregs, MUSB_DEVCTL); if (devctl & MUSB_DEVCTL_BDEVICE) - mod_timer(&glue->timer, + mod_timer(&glue->timer[pdev->id], jiffies + wrp->poll_seconds * HZ); else musb->xceiv->state = OTG_STATE_A_IDLE; @@ -215,9 +218,8 @@ static void otg_timer(unsigned long _musb) static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout) { struct device *dev = musb->controller; - struct platform_device *pdev = to_platform_device(dev->parent); - struct dsps_glue *glue = platform_get_drvdata(pdev); - static unsigned long last_timer; + struct platform_device *pdev = to_platform_device(dev); + struct dsps_glue *glue = dev_get_drvdata(dev->parent); if (timeout == 0) timeout = jiffies + msecs_to_jiffies(3); @@ -227,22 +229,23 @@ static void dsps_musb_try_idle(struct musb *musb, unsigned long timeout) musb->xceiv->state == OTG_STATE_A_WAIT_BCON)) { dev_dbg(musb->controller, "%s active, deleting timer\n", otg_state_string(musb->xceiv->state)); - del_timer(&glue->timer); - last_timer = jiffies; + del_timer(&glue->timer[pdev->id]); + glue->last_timer[pdev->id] = jiffies; return; } - if (time_after(last_timer, timeout) && timer_pending(&glue->timer)) { + if (time_after(glue->last_timer[pdev->id], timeout) && + timer_pending(&glue->timer[pdev->id])) { dev_dbg(musb->controller, "Longer idle timer already pending, ignoring...\n"); return; } - last_timer = timeout; + glue->last_timer[pdev->id] = timeout; dev_dbg(musb->controller, "%s inactive, starting idle timer for %u ms\n", otg_state_string(musb->xceiv->state), jiffies_to_msecs(timeout - jiffies)); - mod_timer(&glue->timer, timeout); + mod_timer(&glue->timer[pdev->id], timeout); } static irqreturn_t dsps_interrupt(int irq, void *hci) @@ -250,8 +253,8 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) struct musb *musb = hci; void __iomem *reg_base = musb->ctrl_base; struct device *dev = musb->controller; - struct platform_device *pdev = to_platform_device(dev->parent); - struct dsps_glue *glue = platform_get_drvdata(pdev); + struct platform_device *pdev = to_platform_device(dev); + struct dsps_glue *glue = dev_get_drvdata(dev->parent); const struct dsps_musb_wrapper *wrp = glue->wrp; unsigned long flags; irqreturn_t ret = IRQ_NONE; @@ -310,7 +313,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) */ musb->int_usb &= ~MUSB_INTR_VBUSERROR; musb->xceiv->state = OTG_STATE_A_WAIT_VFALL; - mod_timer(&glue->timer, + mod_timer(&glue->timer[pdev->id], jiffies + wrp->poll_seconds * HZ); WARNING("VBUS error workaround (delay coming)\n"); } else if (drvvbus) { @@ -318,7 +321,7 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) MUSB_HST_MODE(musb); musb->xceiv->otg->default_a = 1; musb->xceiv->state = OTG_STATE_A_WAIT_VRISE; - del_timer(&glue->timer); + del_timer(&glue->timer[pdev->id]); } else { musb->is_active = 0; MUSB_DEV_MODE(musb); @@ -345,7 +348,8 @@ static irqreturn_t dsps_interrupt(int irq, void *hci) /* Poll for ID change */ if (musb->xceiv->state == OTG_STATE_B_IDLE) - mod_timer(&glue->timer, jiffies + wrp->poll_seconds * HZ); + mod_timer(&glue->timer[pdev->id], + jiffies + wrp->poll_seconds * HZ); spin_unlock_irqrestore(&musb->lock, flags); @@ -356,8 +360,8 @@ static int dsps_musb_init(struct musb *musb) { struct device *dev = musb->controller; struct musb_hdrc_platform_data *plat = dev->platform_data; - struct platform_device *pdev = to_platform_device(dev->parent); - struct dsps_glue *glue = platform_get_drvdata(pdev); + struct platform_device *pdev = to_platform_device(dev); + struct dsps_glue *glue = dev_get_drvdata(dev->parent); const struct dsps_musb_wrapper *wrp = glue->wrp; struct omap_musb_board_data *data = plat->board_data; void __iomem *reg_base = musb->ctrl_base; @@ -380,7 +384,7 @@ static int dsps_musb_init(struct musb *musb) goto err0; } - setup_timer(&glue->timer, otg_timer, (unsigned long) musb); + setup_timer(&glue->timer[pdev->id], otg_timer, (unsigned long) musb); /* Reset the musb */ dsps_writel(reg_base, wrp->control, (1 << wrp->reset)); @@ -411,10 +415,10 @@ static int dsps_musb_exit(struct musb *musb) struct device *dev = musb->controller; struct musb_hdrc_platform_data *plat = dev->platform_data; struct omap_musb_board_data *data = plat->board_data; - struct platform_device *pdev = to_platform_device(dev->parent); - struct dsps_glue *glue = platform_get_drvdata(pdev); + struct platform_device *pdev = to_platform_device(dev); + struct dsps_glue *glue = dev_get_drvdata(dev->parent); - del_timer_sync(&glue->timer); + del_timer_sync(&glue->timer[pdev->id]); /* Shutdown the on-chip PHY and its PLL. */ if (data->set_phy_power) @@ -493,7 +497,7 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) musb->dev.dma_mask = &musb_dmamask; musb->dev.coherent_dma_mask = musb_dmamask; - glue->musb = musb; + glue->musb[id] = musb; pdata->platform_ops = &dsps_ops; @@ -525,11 +529,11 @@ err0: return ret; } -static void __devexit dsps_delete_musb_pdev(struct dsps_glue *glue) +static void dsps_delete_musb_pdev(struct dsps_glue *glue, u8 id) { - musb_put_id(glue->dev, glue->musb->id); - platform_device_del(glue->musb); - platform_device_put(glue->musb); + musb_put_id(glue->dev, glue->musb[id]->id); + platform_device_del(glue->musb[id]); + platform_device_put(glue->musb[id]); } static int __devinit dsps_probe(struct platform_device *pdev) @@ -539,7 +543,7 @@ static int __devinit dsps_probe(struct platform_device *pdev) (struct dsps_musb_wrapper *)id->driver_data; struct dsps_glue *glue; struct resource *iomem; - int ret; + int ret, i; /* allocate glue */ glue = kzalloc(sizeof(*glue), GFP_KERNEL); @@ -580,7 +584,16 @@ static int __devinit dsps_probe(struct platform_device *pdev) ret = pm_runtime_get_sync(&pdev->dev); if (ret < 0) { dev_err(&pdev->dev, "pm_runtime_get_sync FAILED"); - goto err3; + /* create the child platform device for all instances of musb */ + for (i = 0; i < wrp->instances ; i++) { + ret = dsps_create_musb_pdev(glue, i); + if (ret != 0) { + dev_err(&pdev->dev, "failed to create child pdev\n"); + /* release resources of previously created instances */ + for (i--; i >= 0 ; i--) + dsps_delete_musb_pdev(glue, i); + goto err3; + } } return 0; @@ -597,9 +610,12 @@ err0: static int __devexit dsps_remove(struct platform_device *pdev) { struct dsps_glue *glue = platform_get_drvdata(pdev); + const struct dsps_musb_wrapper *wrp = glue->wrp; + int i; /* delete the child platform device */ - dsps_delete_musb_pdev(glue); + for (i = 0; i < wrp->instances ; i++) + dsps_delete_musb_pdev(glue, i); /* disable usbss clocks */ pm_runtime_put(&pdev->dev); @@ -665,6 +681,7 @@ static const struct dsps_musb_wrapper ti81xx_driver_data __devinitconst = { .rxep_bitmap = (0xfffe << 16), .musb_core_offset = 0x400, .poll_seconds = 2, + .instances = 2, }; static const struct platform_device_id musb_dsps_id_table[] __devinitconst = { -- cgit v0.10.2 From 65145677a65c31a8fd2704e244801bdb11061f9a Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Fri, 31 Aug 2012 11:09:53 +0000 Subject: usb: musb: dsps: add dt support Added device tree support for dsps musb glue driver and updated the Documentation with device tree binding information. Signed-off-by: Ajay Kumar Gupta Signed-off-by: Santhapuri, Damodar Signed-off-by: Ravi Babu [afzal@ti.com: use '-' instead of '_' for dt properties] Signed-off-by: Afzal Mohammed Signed-off-by: Felipe Balbi diff --git a/Documentation/devicetree/bindings/usb/am33xx-usb.txt b/Documentation/devicetree/bindings/usb/am33xx-usb.txt new file mode 100644 index 0000000..ca8fa56 --- /dev/null +++ b/Documentation/devicetree/bindings/usb/am33xx-usb.txt @@ -0,0 +1,14 @@ +AM33XX MUSB GLUE + - compatible : Should be "ti,musb-am33xx" + - ti,hwmods : must be "usb_otg_hs" + - multipoint : Should be "1" indicating the musb controller supports + multipoint. This is a MUSB configuration-specific setting. + - num_eps : Specifies the number of endpoints. This is also a + MUSB configuration-specific setting. Should be set to "16" + - ram_bits : Specifies the ram address size. Should be set to "12" + - port0_mode : Should be "3" to represent OTG. "1" signifies HOST and "2" + represents PERIPHERAL. + - port1_mode : Should be "1" to represent HOST. "3" signifies OTG and "2" + represents PERIPHERAL. + - power : Should be "250". This signifies the controller can supply upto + 500mA when operating in host mode. diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index 796fc60..b8aecbb 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -45,6 +46,10 @@ #include "musb_core.h" +#ifdef CONFIG_OF +static const struct of_device_id musb_dsps_of_match[]; +#endif + /** * avoid using musb_readx()/musb_writex() as glue layer should not be * dependent on musb core layer symbols. @@ -448,6 +453,8 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) struct device *dev = glue->dev; struct platform_device *pdev = to_platform_device(dev); struct musb_hdrc_platform_data *pdata = dev->platform_data; + struct device_node *np = pdev->dev.of_node; + struct musb_hdrc_config *config; struct platform_device *musb; struct resource *res; struct resource resources[2]; @@ -499,14 +506,40 @@ static int __devinit dsps_create_musb_pdev(struct dsps_glue *glue, u8 id) glue->musb[id] = musb; - pdata->platform_ops = &dsps_ops; - ret = platform_device_add_resources(musb, resources, 2); if (ret) { dev_err(dev, "failed to add resources\n"); goto err2; } + if (np) { + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) { + dev_err(&pdev->dev, + "failed to allocate musb platfrom data\n"); + ret = -ENOMEM; + goto err2; + } + + config = devm_kzalloc(&pdev->dev, sizeof(*config), GFP_KERNEL); + if (!config) { + dev_err(&pdev->dev, + "failed to allocate musb hdrc config\n"); + goto err2; + } + + of_property_read_u32(np, "num-eps", (u32 *)&config->num_eps); + of_property_read_u32(np, "ram-bits", (u32 *)&config->ram_bits); + sprintf(res_name, "port%d-mode", id); + of_property_read_u32(np, res_name, (u32 *)&pdata->mode); + of_property_read_u32(np, "power", (u32 *)&pdata->power); + config->multipoint = of_property_read_bool(np, "multipoint"); + + pdata->config = config; + } + + pdata->platform_ops = &dsps_ops; + ret = platform_device_add_data(musb, pdata, sizeof(*pdata)); if (ret) { dev_err(dev, "failed to add platform_data\n"); @@ -538,13 +571,21 @@ static void dsps_delete_musb_pdev(struct dsps_glue *glue, u8 id) static int __devinit dsps_probe(struct platform_device *pdev) { - const struct platform_device_id *id = platform_get_device_id(pdev); - const struct dsps_musb_wrapper *wrp = - (struct dsps_musb_wrapper *)id->driver_data; + struct device_node *np = pdev->dev.of_node; + const struct of_device_id *match; + const struct dsps_musb_wrapper *wrp; struct dsps_glue *glue; struct resource *iomem; int ret, i; + match = of_match_node(musb_dsps_of_match, np); + if (!match) { + dev_err(&pdev->dev, "fail to get matching of_match struct\n"); + ret = -EINVAL; + goto err0; + } + wrp = match->data; + /* allocate glue */ glue = kzalloc(sizeof(*glue), GFP_KERNEL); if (!glue) { @@ -693,13 +734,14 @@ static const struct platform_device_id musb_dsps_id_table[] __devinitconst = { }; MODULE_DEVICE_TABLE(platform, musb_dsps_id_table); +#ifdef CONFIG_OF static const struct of_device_id musb_dsps_of_match[] __devinitconst = { - { .compatible = "musb-ti81xx", }, - { .compatible = "ti,ti81xx-musb", }, - { .compatible = "ti,am335x-musb", }, + { .compatible = "ti,musb-am33xx", + .data = (void *) &ti81xx_driver_data, }, { }, }; MODULE_DEVICE_TABLE(of, musb_dsps_of_match); +#endif static struct platform_driver dsps_usbss_driver = { .probe = dsps_probe, @@ -707,7 +749,7 @@ static struct platform_driver dsps_usbss_driver = { .driver = { .name = "musb-dsps", .pm = &dsps_pm_ops, - .of_match_table = musb_dsps_of_match, + .of_match_table = of_match_ptr(musb_dsps_of_match), }, .id_table = musb_dsps_id_table, }; -- cgit v0.10.2 From d8c3ef256f88b7c6ecd673d03073b5645be9c5e4 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Fri, 31 Aug 2012 11:09:56 +0000 Subject: usb: musb: dsps: remove explicit NOP device creation As NOP device node is now added in am33xx tree so remove the call which creates the NOP platform_device. Signed-off-by: Ajay Kumar Gupta Signed-off-by: Santhapuri, Damodar Signed-off-by: Ravi Babu Signed-off-by: Felipe Balbi diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index b8aecbb..2785e28 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c @@ -376,8 +376,7 @@ static int dsps_musb_init(struct musb *musb) /* mentor core register starts at offset of 0x400 from musb base */ musb->mregs += wrp->musb_core_offset; - /* NOP driver needs change if supporting dual instance */ - usb_nop_xceiv_register(); + /* Get the NOP PHY */ musb->xceiv = usb_get_phy(USB_PHY_TYPE_USB2); if (IS_ERR_OR_NULL(musb->xceiv)) return -ENODEV; -- cgit v0.10.2 From 58efc77c86af5cb81d7d7ea0c3c3e675e7d121dc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 10 Sep 2012 19:01:07 -0700 Subject: usb: renesas_usbhs: convert to devm_xxx() Signed-off-by: Kuninori Morimoto Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c index 681da06..072edc1 100644 --- a/drivers/usb/renesas_usbhs/common.c +++ b/drivers/usb/renesas_usbhs/common.c @@ -432,17 +432,16 @@ static int usbhs_probe(struct platform_device *pdev) } /* usb private data */ - priv = kzalloc(sizeof(*priv), GFP_KERNEL); + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) { dev_err(&pdev->dev, "Could not allocate priv\n"); return -ENOMEM; } - priv->base = ioremap_nocache(res->start, resource_size(res)); + priv->base = devm_request_and_ioremap(&pdev->dev, res); if (!priv->base) { dev_err(&pdev->dev, "ioremap error.\n"); - ret = -ENOMEM; - goto probe_end_kfree; + return -ENOMEM; } /* @@ -485,7 +484,7 @@ static int usbhs_probe(struct platform_device *pdev) /* call pipe and module init */ ret = usbhs_pipe_probe(priv); if (ret < 0) - goto probe_end_iounmap; + return ret; ret = usbhs_fifo_probe(priv); if (ret < 0) @@ -546,10 +545,6 @@ probe_end_fifo_exit: usbhs_fifo_remove(priv); probe_end_pipe_exit: usbhs_pipe_remove(priv); -probe_end_iounmap: - iounmap(priv->base); -probe_end_kfree: - kfree(priv); dev_info(&pdev->dev, "probe failed\n"); @@ -576,8 +571,6 @@ static int __devexit usbhs_remove(struct platform_device *pdev) usbhs_mod_remove(priv); usbhs_fifo_remove(priv); usbhs_pipe_remove(priv); - iounmap(priv->base); - kfree(priv); return 0; } -- cgit v0.10.2 From 1f2235b8e79bd276f19809f7f2a270f55909d695 Mon Sep 17 00:00:00 2001 From: Alexander Shishkin Date: Wed, 12 Sep 2012 14:48:31 +0300 Subject: usb: move children deallocation after quiescing the hub Commit ff823c79a5c33194c2e5594f7c4686ea3547910c ("usb: move children to struct usb_port") forgot to consider the hub_disconnect sequence, which releases ports before quiescing the hub, which will lead to a use-after-free, since hub_quiesce() will try to disconnect ports' children, which are already deallocated. Simple modprobe dummy_hcd && rmmod dummy_hcd will illustrate the problem. This patch moves deallocation of hub's ports after hub_quiesce() call in hub_disconnect(). Cc: Lan Tianyu Signed-off-by: Alexander Shishkin Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index aa45e43..6dc41c6 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1584,9 +1584,6 @@ static void hub_disconnect(struct usb_interface *intf) struct usb_device *hdev = interface_to_usbdev(intf); int i; - for (i = 0; i < hdev->maxchild; i++) - usb_hub_remove_port_device(hub, i + 1); - /* Take the hub off the event list and don't let it be added again */ spin_lock_irq(&hub_event_lock); if (!list_empty(&hub->event_list)) { @@ -1601,6 +1598,9 @@ static void hub_disconnect(struct usb_interface *intf) hub_quiesce(hub, HUB_DISCONNECT); usb_set_intfdata (intf, NULL); + + for (i = 0; i < hdev->maxchild; i++) + usb_hub_remove_port_device(hub, i + 1); hub->hdev->maxchild = 0; if (hub->hdev->speed == USB_SPEED_HIGH) -- cgit v0.10.2 From d142d6be231713330f9c0d7ee52f23e1b3f19ee4 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Wed, 12 Sep 2012 14:58:05 +0300 Subject: USB: chipidea: add imx usbmisc support i.MX usb controllers share non-core registers, which may include SoC specific controls. We turn it into a usbmisc device and usbmisc driver set operations needed by ci13xxx_imx driver. For example, Sabrelite board has bad over-current design, we can usbmisc to disable over-current detection. Acked-by: Sascha Hauer Signed-off-by: Richard Zhao Signed-off-by: Alexander Shishkin Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/devicetree/bindings/usb/ci13xxx-imx.txt b/Documentation/devicetree/bindings/usb/ci13xxx-imx.txt index 2c29041..5778b9c 100644 --- a/Documentation/devicetree/bindings/usb/ci13xxx-imx.txt +++ b/Documentation/devicetree/bindings/usb/ci13xxx-imx.txt @@ -7,7 +7,10 @@ Required properties: Optional properties: - fsl,usbphy: phandler of usb phy that connects to the only one port +- fsl,usbmisc: phandler of non-core register device, with one argument + that indicate usb controller index - vbus-supply: regulator for vbus +- disable-over-current: disable over current detect Examples: usb@02184000 { /* USB OTG */ @@ -15,4 +18,6 @@ usb@02184000 { /* USB OTG */ reg = <0x02184000 0x200>; interrupts = <0 43 0x04>; fsl,usbphy = <&usbphy1>; + fsl,usbmisc = <&usbmisc 0>; + disable-over-current; }; diff --git a/Documentation/devicetree/bindings/usb/usbmisc-imx.txt b/Documentation/devicetree/bindings/usb/usbmisc-imx.txt new file mode 100644 index 0000000..97ce94e --- /dev/null +++ b/Documentation/devicetree/bindings/usb/usbmisc-imx.txt @@ -0,0 +1,14 @@ +* Freescale i.MX non-core registers + +Required properties: +- #index-cells: Cells used to descibe usb controller index. Should be <1> +- compatible: Should be one of below: + "fsl,imx6q-usbmisc" for imx6q +- reg: Should contain registers location and length + +Examples: +usbmisc@02184800 { + #index-cells = <1>; + compatible = "fsl,imx6q-usbmisc"; + reg = <0x02184800 0x200>; +}; diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile index 5c66d9c..57e510f 100644 --- a/drivers/usb/chipidea/Makefile +++ b/drivers/usb/chipidea/Makefile @@ -15,5 +15,5 @@ ifneq ($(CONFIG_PCI),) endif ifneq ($(CONFIG_OF_DEVICE),) - obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_imx.o + obj-$(CONFIG_USB_CHIPIDEA) += ci13xxx_imx.o usbmisc_imx6q.o endif diff --git a/drivers/usb/chipidea/ci13xxx_imx.c b/drivers/usb/chipidea/ci13xxx_imx.c index ef60d06..96ac67b 100644 --- a/drivers/usb/chipidea/ci13xxx_imx.c +++ b/drivers/usb/chipidea/ci13xxx_imx.c @@ -22,6 +22,7 @@ #include #include "ci.h" +#include "ci13xxx_imx.h" #define pdev_to_phy(pdev) \ ((struct usb_phy *)platform_get_drvdata(pdev)) @@ -34,6 +35,55 @@ struct ci13xxx_imx_data { struct regulator *reg_vbus; }; +static const struct usbmisc_ops *usbmisc_ops; + +/* Common functions shared by usbmisc drivers */ + +int usbmisc_set_ops(const struct usbmisc_ops *ops) +{ + if (usbmisc_ops) + return -EBUSY; + + usbmisc_ops = ops; + + return 0; +} +EXPORT_SYMBOL_GPL(usbmisc_set_ops); + +void usbmisc_unset_ops(const struct usbmisc_ops *ops) +{ + usbmisc_ops = NULL; +} +EXPORT_SYMBOL_GPL(usbmisc_unset_ops); + +int usbmisc_get_init_data(struct device *dev, struct usbmisc_usb_device *usbdev) +{ + struct device_node *np = dev->of_node; + struct of_phandle_args args; + int ret; + + usbdev->dev = dev; + + ret = of_parse_phandle_with_args(np, "fsl,usbmisc", "#index-cells", + 0, &args); + if (ret) { + dev_err(dev, "Failed to parse property fsl,usbmisc, errno %d\n", + ret); + memset(usbdev, 0, sizeof(*usbdev)); + return ret; + } + usbdev->index = args.args[0]; + of_node_put(args.np); + + if (of_find_property(np, "disable-over-current", NULL)) + usbdev->disable_oc = 1; + + return 0; +} +EXPORT_SYMBOL_GPL(usbmisc_get_init_data); + +/* End of common functions shared by usbmisc drivers*/ + static struct ci13xxx_platform_data ci13xxx_imx_platdata __devinitdata = { .name = "ci13xxx_imx", .flags = CI13XXX_REQUIRE_TRANSCEIVER | @@ -51,6 +101,10 @@ static int __devinit ci13xxx_imx_probe(struct platform_device *pdev) struct regulator *reg_vbus; int ret; + if (of_find_property(pdev->dev.of_node, "fsl,usbmisc", NULL) + && !usbmisc_ops) + return -EPROBE_DEFER; + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); if (!data) { dev_err(&pdev->dev, "Failed to allocate CI13xxx-IMX data!\n"); @@ -120,6 +174,16 @@ static int __devinit ci13xxx_imx_probe(struct platform_device *pdev) *pdev->dev.dma_mask = DMA_BIT_MASK(32); dma_set_coherent_mask(&pdev->dev, *pdev->dev.dma_mask); } + + if (usbmisc_ops && usbmisc_ops->init) { + ret = usbmisc_ops->init(&pdev->dev); + if (ret) { + dev_err(&pdev->dev, + "usbmisc init failed, ret=%d\n", ret); + goto err; + } + } + plat_ci = ci13xxx_add_device(&pdev->dev, pdev->resource, pdev->num_resources, &ci13xxx_imx_platdata); diff --git a/drivers/usb/chipidea/ci13xxx_imx.h b/drivers/usb/chipidea/ci13xxx_imx.h new file mode 100644 index 0000000..2e88acc --- /dev/null +++ b/drivers/usb/chipidea/ci13xxx_imx.h @@ -0,0 +1,28 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +/* Used to set SoC specific callbacks */ +struct usbmisc_ops { + /* It's called once when probe a usb device */ + int (*init)(struct device *dev); +}; + +struct usbmisc_usb_device { + struct device *dev; /* usb controller device */ + int index; + + int disable_oc:1; /* over current detect disabled */ +}; + +int usbmisc_set_ops(const struct usbmisc_ops *ops); +void usbmisc_unset_ops(const struct usbmisc_ops *ops); +int +usbmisc_get_init_data(struct device *dev, struct usbmisc_usb_device *usbdev); diff --git a/drivers/usb/chipidea/usbmisc_imx6q.c b/drivers/usb/chipidea/usbmisc_imx6q.c new file mode 100644 index 0000000..416e3fc --- /dev/null +++ b/drivers/usb/chipidea/usbmisc_imx6q.c @@ -0,0 +1,162 @@ +/* + * Copyright 2012 Freescale Semiconductor, Inc. + * + * The code contained herein is licensed under the GNU General Public + * License. You may obtain a copy of the GNU General Public License + * Version 2 or later at the following locations: + * + * http://www.opensource.org/licenses/gpl-license.html + * http://www.gnu.org/copyleft/gpl.html + */ + +#include +#include +#include +#include +#include + +#include "ci13xxx_imx.h" + +#define USB_DEV_MAX 4 + +#define BM_OVER_CUR_DIS BIT(7) + +struct imx6q_usbmisc { + void __iomem *base; + spinlock_t lock; + struct clk *clk; + struct usbmisc_usb_device usbdev[USB_DEV_MAX]; +}; + +static struct imx6q_usbmisc *usbmisc; + +static struct usbmisc_usb_device *get_usbdev(struct device *dev) +{ + int i, ret; + + for (i = 0; i < USB_DEV_MAX; i++) { + if (usbmisc->usbdev[i].dev == dev) + return &usbmisc->usbdev[i]; + else if (!usbmisc->usbdev[i].dev) + break; + } + + if (i >= USB_DEV_MAX) + return ERR_PTR(-EBUSY); + + ret = usbmisc_get_init_data(dev, &usbmisc->usbdev[i]); + if (ret) + return ERR_PTR(ret); + + return &usbmisc->usbdev[i]; +} + +static int usbmisc_imx6q_init(struct device *dev) +{ + + struct usbmisc_usb_device *usbdev; + unsigned long flags; + u32 reg; + + usbdev = get_usbdev(dev); + if (IS_ERR(usbdev)) + return PTR_ERR(usbdev); + + if (usbdev->disable_oc) { + spin_lock_irqsave(&usbmisc->lock, flags); + reg = readl(usbmisc->base + usbdev->index * 4); + writel(reg | BM_OVER_CUR_DIS, + usbmisc->base + usbdev->index * 4); + spin_unlock_irqrestore(&usbmisc->lock, flags); + } + + return 0; +} + +static const struct usbmisc_ops imx6q_usbmisc_ops = { + .init = usbmisc_imx6q_init, +}; + +static const struct of_device_id usbmisc_imx6q_dt_ids[] = { + { .compatible = "fsl,imx6q-usbmisc"}, + { /* sentinel */ } +}; + +static int __devinit usbmisc_imx6q_probe(struct platform_device *pdev) +{ + struct resource *res; + struct imx6q_usbmisc *data; + int ret; + + if (usbmisc) + return -EBUSY; + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + spin_lock_init(&data->lock); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + data->base = devm_request_and_ioremap(&pdev->dev, res); + if (!data->base) + return -EADDRNOTAVAIL; + + data->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(data->clk)) { + dev_err(&pdev->dev, + "failed to get clock, err=%ld\n", PTR_ERR(data->clk)); + return PTR_ERR(data->clk); + } + + ret = clk_prepare_enable(data->clk); + if (ret) { + dev_err(&pdev->dev, + "clk_prepare_enable failed, err=%d\n", ret); + return ret; + } + + ret = usbmisc_set_ops(&imx6q_usbmisc_ops); + if (ret) { + clk_disable_unprepare(data->clk); + return ret; + } + + usbmisc = data; + + return 0; +} + +static int __devexit usbmisc_imx6q_remove(struct platform_device *pdev) +{ + usbmisc_unset_ops(&imx6q_usbmisc_ops); + clk_disable_unprepare(usbmisc->clk); + return 0; +} + +static struct platform_driver usbmisc_imx6q_driver = { + .probe = usbmisc_imx6q_probe, + .remove = __devexit_p(usbmisc_imx6q_remove), + .driver = { + .name = "usbmisc_imx6q", + .owner = THIS_MODULE, + .of_match_table = usbmisc_imx6q_dt_ids, + }, +}; + +int __init usbmisc_imx6q_drv_init(void) +{ + return platform_driver_register(&usbmisc_imx6q_driver); +} +subsys_initcall(usbmisc_imx6q_drv_init); + +void __exit usbmisc_imx6q_drv_exit(void) +{ + platform_driver_unregister(&usbmisc_imx6q_driver); +} +module_exit(usbmisc_imx6q_drv_exit); + +MODULE_ALIAS("platform:usbmisc-imx6q"); +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("driver for imx6q usb non-core registers"); +MODULE_AUTHOR("Richard Zhao "); -- cgit v0.10.2 From b4dbb258b67b12fff4c9df56983934e11813c404 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Wed, 12 Sep 2012 14:58:06 +0300 Subject: USB: chipidea: imx: add pinctrl support Some controllers may not need to setup pinctrl, so we don't fail the probe if pinctrl get/select failed. Tested-by: Michael Grzeschik Tested-by: Marc Kleine-Budde Signed-off-by: Richard Zhao Signed-off-by: Alexander Shishkin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/chipidea/ci13xxx_imx.c b/drivers/usb/chipidea/ci13xxx_imx.c index 96ac67b..0f5ca4b 100644 --- a/drivers/usb/chipidea/ci13xxx_imx.c +++ b/drivers/usb/chipidea/ci13xxx_imx.c @@ -20,6 +20,7 @@ #include #include #include +#include #include "ci.h" #include "ci13xxx_imx.h" @@ -99,6 +100,7 @@ static int __devinit ci13xxx_imx_probe(struct platform_device *pdev) struct device_node *phy_np; struct resource *res; struct regulator *reg_vbus; + struct pinctrl *pinctrl; int ret; if (of_find_property(pdev->dev.of_node, "fsl,usbmisc", NULL) @@ -117,6 +119,11 @@ static int __devinit ci13xxx_imx_probe(struct platform_device *pdev) return -ENOENT; } + pinctrl = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pinctrl)) + dev_warn(&pdev->dev, "pinctrl get/select failed, err=%ld\n", + PTR_ERR(pinctrl)); + data->clk = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(data->clk)) { dev_err(&pdev->dev, -- cgit v0.10.2 From 86ad01a907d7856edc07d8b49260c39520c0e932 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Wed, 12 Sep 2012 14:58:07 +0300 Subject: USB: chipidea: delay 2ms before read ID status at probe time The ID pin needs 1ms debounce time, even at probe time. We delay 2ms to be on the safe side. Tested-by: Michael Grzeschik Tested-by: Marc Kleine-Budde Signed-off-by: Richard Zhao Signed-off-by: Alexander Shishkin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 1083585..3c3ed77 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -462,6 +462,8 @@ static int __devinit ci_hdrc_probe(struct platform_device *pdev) if (ci->roles[CI_ROLE_HOST] && ci->roles[CI_ROLE_GADGET]) { ci->is_otg = true; + /* ID pin needs 1ms debouce time, we delay 2ms for safe */ + mdelay(2); ci->role = ci_otg_role(ci); } else { ci->role = ci->roles[CI_ROLE_HOST] -- cgit v0.10.2 From 984f753cf120db60d97271e34cf16c95761f0278 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Wed, 12 Sep 2012 14:58:08 +0300 Subject: USB: chipidea: acknowledge ID change interrupt in irq handler In order to avoid re-queueing of the role changing work, we need to clear the ID change interrupt bit right in the irq handler. Tested-by: Michael Grzeschik Tested-by: Marc Kleine-Budde Signed-off-by: Richard Zhao Signed-off-by: Alexander Shishkin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 3c3ed77..19ef324 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -273,8 +273,6 @@ static void ci_role_work(struct work_struct *work) struct ci13xxx *ci = container_of(work, struct ci13xxx, work); enum ci_role role = ci_otg_role(ci); - hw_write(ci, OP_OTGSC, OTGSC_IDIS, OTGSC_IDIS); - if (role != ci->role) { dev_dbg(ci->dev, "switching from %s to %s\n", ci_role(ci)->name, ci->roles[role]->name); @@ -325,6 +323,7 @@ static irqreturn_t ci_irq(int irq, void *data) u32 sts = hw_read(ci, OP_OTGSC, ~0); if (sts & OTGSC_IDIS) { + hw_write(ci, OP_OTGSC, OTGSC_IDIS, OTGSC_IDIS); queue_work(ci->wq, &ci->work); ret = IRQ_HANDLED; } -- cgit v0.10.2 From 8c4fc031954b4eb72daf13d3c907a985a3eee208 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Wed, 12 Sep 2012 14:58:09 +0300 Subject: USB: chipidea: add vbus detect for udc Using vbus valid interrupt to detect vbus. Tested-by: Michael Grzeschik Tested-by: Marc Kleine-Budde Signed-off-by: Richard Zhao Signed-off-by: Alexander Shishkin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h index d738603..e25d126 100644 --- a/drivers/usb/chipidea/ci.h +++ b/drivers/usb/chipidea/ci.h @@ -139,6 +139,7 @@ struct ci13xxx { enum ci_role role; bool is_otg; struct work_struct work; + struct work_struct vbus_work; struct workqueue_struct *wq; struct dma_pool *qh_pool; diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index d214448..2f45bba 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c @@ -305,6 +305,18 @@ static u32 hw_test_and_clear_intr_active(struct ci13xxx *ci) return reg; } +static void hw_enable_vbus_intr(struct ci13xxx *ci) +{ + hw_write(ci, OP_OTGSC, OTGSC_AVVIS, OTGSC_AVVIS); + hw_write(ci, OP_OTGSC, OTGSC_AVVIE, OTGSC_AVVIE); + queue_work(ci->wq, &ci->vbus_work); +} + +static void hw_disable_vbus_intr(struct ci13xxx *ci) +{ + hw_write(ci, OP_OTGSC, OTGSC_AVVIE, 0); +} + /** * hw_test_and_clear_setup_guard: test & clear setup guard (execute without * interruption) @@ -371,6 +383,16 @@ static int hw_usb_reset(struct ci13xxx *ci) return 0; } +static void vbus_work(struct work_struct *work) +{ + struct ci13xxx *ci = container_of(work, struct ci13xxx, vbus_work); + + if (hw_read(ci, OP_OTGSC, OTGSC_AVV)) + usb_gadget_vbus_connect(&ci->gadget); + else + usb_gadget_vbus_disconnect(&ci->gadget); +} + /****************************************************************************** * UTIL block *****************************************************************************/ @@ -1370,6 +1392,7 @@ static int ci13xxx_vbus_session(struct usb_gadget *_gadget, int is_active) if (is_active) { pm_runtime_get_sync(&_gadget->dev); hw_device_reset(ci, USBMODE_CM_DC); + hw_enable_vbus_intr(ci); hw_device_state(ci, ci->ep0out->qh.dma); } else { hw_device_state(ci, 0); @@ -1544,8 +1567,10 @@ static int ci13xxx_start(struct usb_gadget *gadget, pm_runtime_get_sync(&ci->gadget.dev); if (ci->platdata->flags & CI13XXX_PULLUP_ON_VBUS) { if (ci->vbus_active) { - if (ci->platdata->flags & CI13XXX_REGS_SHARED) + if (ci->platdata->flags & CI13XXX_REGS_SHARED) { hw_device_reset(ci, USBMODE_CM_DC); + hw_enable_vbus_intr(ci); + } } else { pm_runtime_put_sync(&ci->gadget.dev); goto done; @@ -1651,6 +1676,13 @@ static irqreturn_t udc_irq(struct ci13xxx *ci) } else { retval = IRQ_NONE; } + + intr = hw_read(ci, OP_OTGSC, ~0); + hw_write(ci, OP_OTGSC, ~0, intr); + + if (intr & (OTGSC_AVVIE & OTGSC_AVVIS)) + queue_work(ci->wq, &ci->vbus_work); + spin_unlock(&ci->lock); return retval; @@ -1726,6 +1758,7 @@ static int udc_start(struct ci13xxx *ci) retval = hw_device_reset(ci, USBMODE_CM_DC); if (retval) goto put_transceiver; + hw_enable_vbus_intr(ci); } retval = device_register(&ci->gadget.dev); @@ -1788,6 +1821,9 @@ static void udc_stop(struct ci13xxx *ci) if (ci == NULL) return; + hw_disable_vbus_intr(ci); + cancel_work_sync(&ci->vbus_work); + usb_del_gadget_udc(&ci->gadget); destroy_eps(ci); @@ -1828,6 +1864,7 @@ int ci_hdrc_gadget_init(struct ci13xxx *ci) rdrv->irq = udc_irq; rdrv->name = "gadget"; ci->roles[CI_ROLE_GADGET] = rdrv; + INIT_WORK(&ci->vbus_work, vbus_work); return 0; } -- cgit v0.10.2 From 388ed487234429652c1cdb797ad45cb0967b2343 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Wed, 12 Sep 2012 14:58:10 +0300 Subject: USB: chipidea: add -DDEBUG if debugging is enabled This patch turns on debugging output if CONFIG_USB_CHIPIDEA_DEBUG is enabled. Signed-off-by: Richard Zhao Tested-by: Michael Grzeschik Tested-by: Marc Kleine-Budde Signed-off-by: Alexander Shishkin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/chipidea/Makefile b/drivers/usb/chipidea/Makefile index 57e510f..d92ca32 100644 --- a/drivers/usb/chipidea/Makefile +++ b/drivers/usb/chipidea/Makefile @@ -1,3 +1,5 @@ +ccflags-$(CONFIG_USB_CHIPIDEA_DEBUG) := -DDEBUG + obj-$(CONFIG_USB_CHIPIDEA) += ci_hdrc.o ci_hdrc-y := core.o -- cgit v0.10.2 From b183c19f98f8afee799ee41e062810d6b1c7e123 Mon Sep 17 00:00:00 2001 From: Richard Zhao Date: Wed, 12 Sep 2012 14:58:11 +0300 Subject: USB: chipidea: re-order irq handling to avoid unhandled irqs - let role driver handle irq before ID change check; this gives the role driver a chance to handle disconnect; - disable irq during switch role; no role driver to handle irq in the period. Tested-by: Michael Grzeschik Tested-by: Marc Kleine-Budde Signed-off-by: Richard Zhao Signed-off-by: Alexander Shishkin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c index 19ef324..f69d029 100644 --- a/drivers/usb/chipidea/core.c +++ b/drivers/usb/chipidea/core.c @@ -279,6 +279,7 @@ static void ci_role_work(struct work_struct *work) ci_role_stop(ci); ci_role_start(ci, role); + enable_irq(ci->irq); } } @@ -318,18 +319,22 @@ static irqreturn_t ci_irq(int irq, void *data) { struct ci13xxx *ci = data; irqreturn_t ret = IRQ_NONE; + u32 otgsc = 0; - if (ci->is_otg) { - u32 sts = hw_read(ci, OP_OTGSC, ~0); + if (ci->is_otg) + otgsc = hw_read(ci, OP_OTGSC, ~0); + + if (ci->role != CI_ROLE_END) + ret = ci_role(ci)->irq(ci); - if (sts & OTGSC_IDIS) { - hw_write(ci, OP_OTGSC, OTGSC_IDIS, OTGSC_IDIS); - queue_work(ci->wq, &ci->work); - ret = IRQ_HANDLED; - } + if (ci->is_otg && (otgsc & OTGSC_IDIS)) { + hw_write(ci, OP_OTGSC, OTGSC_IDIS, OTGSC_IDIS); + disable_irq_nosync(ci->irq); + queue_work(ci->wq, &ci->work); + ret = IRQ_HANDLED; } - return ci->role == CI_ROLE_END ? ret : ci_role(ci)->irq(ci); + return ret; } static DEFINE_IDA(ci_ida); -- cgit v0.10.2 From 1db9e45c340213d3b19d456fbf678406c1334959 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 13 Sep 2012 09:19:05 -0700 Subject: USB: serial: move usb_serial_debug_data to use %*ph Now that we have a printk modifier for data streams, use it instead of rolling our own. Signed-off-by: Greg Kroah-Hartman diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 86c0b45..9e9a0a8 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -360,15 +360,9 @@ static inline void usb_serial_debug_data(int debug, const char *function, int size, const unsigned char *data) { - int i; - - if (debug) { - dev_printk(KERN_DEBUG, dev, "%s - length = %d, data = ", - function, size); - for (i = 0; i < size; ++i) - printk("%.2x ", data[i]); - printk("\n"); - } + if (debug) + dev_printk(KERN_DEBUG, dev, "%s - length = %d, data = %*ph\n", + function, size, size, data); } /* Use our own dbg macro */ -- cgit v0.10.2 From 799ee9243d892ad959c8e5f4549593ece59f1c80 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 17 Aug 2012 16:59:51 -0700 Subject: USB: serial: add zte_ev.c driver This adds a driver for the zte_ev set of usb to serial devices. It is based on a patch floating around the internet that modified the generic usb-serial driver to only work for this type of device. I've left comments in the code that I think show the data commands being sent to the device, which I'm guessing come from a usb analyzer. Maybe they can help others out as well. Many thanks to nirinA raseliarison for pointing the original patch out to me, and for testing that the driver works properly. Tested-by: nirinA raseliarison Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 325d291..f604f70 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -660,6 +660,14 @@ config USB_SERIAL_ZIO To compile this driver as a module, choose M here: the module will be called zio. +config USB_SERIAL_ZTE + tristate "ZTE USB serial driver" + help + Say Y here if you want to use a ZTE USB to serial device. + + To compile this driver as a module, choose M here: the + module will be called zte. + config USB_SERIAL_SSU100 tristate "USB Quatech SSU-100 Single Port Serial Driver" help diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 1dc483a..45871f9 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -63,3 +63,4 @@ obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o obj-$(CONFIG_USB_SERIAL_XIRCOM) += keyspan_pda.o obj-$(CONFIG_USB_SERIAL_VIVOPAY_SERIAL) += vivopay-serial.o obj-$(CONFIG_USB_SERIAL_ZIO) += zio.o +obj-$(CONFIG_USB_SERIAL_ZTE) += zte_ev.o diff --git a/drivers/usb/serial/zte_ev.c b/drivers/usb/serial/zte_ev.c new file mode 100644 index 0000000..39ee737 --- /dev/null +++ b/drivers/usb/serial/zte_ev.c @@ -0,0 +1,307 @@ +/* + * ZTE_EV USB serial driver + * + * Copyright (C) 2012 Greg Kroah-Hartman + * Copyright (C) 2012 Linux Foundation + * + * 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. + * + * This driver is based on code found in a ZTE_ENV patch that modified + * the usb-serial generic driver. Comments were left in that I think + * show the commands used to talk to the device, but I am not sure. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_SETUP_DATA_SIZE 32 + +static void debug_data(struct device *dev, const char *function, int len, + const unsigned char *data, int result) +{ + dev_dbg(dev, "result = %d\n", result); + if (result == len) + dev_dbg(dev, "%s - length = %d, data = %*ph\n", function, + len, len, data); +} + +static int zte_ev_usb_serial_open(struct tty_struct *tty, + struct usb_serial_port *port) +{ + struct usb_device *udev = port->serial->dev; + struct device *dev = &port->dev; + int result = 0; + int len; + unsigned char *buf; + + if (port->number != 0) + return -ENODEV; + + buf = kmalloc(MAX_SETUP_DATA_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + /* send 1st ctl cmd(CTL 21 22 01 00 00 00 00 00) */ + len = 0; + result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x22, 0x21, + 0x0001, 0x0000, NULL, len, + HZ * USB_CTRL_GET_TIMEOUT); + dev_dbg(dev, "result = %d\n", result); + + /* send 2st cmd and recieve data */ + /* + * 16.0 CTL a1 21 00 00 00 00 07 00 CLASS 25.1.0(5) + * 16.0 DI 00 96 00 00 00 00 08 + */ + len = 0x0007; + result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + 0x21, 0xa1, + 0x0000, 0x0000, buf, len, + HZ * USB_CTRL_GET_TIMEOUT); + debug_data(dev, __func__, len, buf, result); + + /* send 3 cmd */ + /* + * 16.0 CTL 21 20 00 00 00 00 07 00 CLASS 30.1.0 + * 16.0 DO 80 25 00 00 00 00 08 .%..... 30.2.0 + */ + len = 0x0007; + buf[0] = 0x80; + buf[1] = 0x25; + buf[2] = 0x00; + buf[3] = 0x00; + buf[4] = 0x00; + buf[5] = 0x00; + buf[6] = 0x08; + result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x20, 0x21, + 0x0000, 0x0000, buf, len, + HZ * USB_CTRL_GET_TIMEOUT); + debug_data(dev, __func__, len, buf, result); + + /* send 4 cmd */ + /* + * 16.0 CTL 21 22 03 00 00 00 00 00 + */ + len = 0; + result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x22, 0x21, + 0x0003, 0x0000, NULL, len, + HZ * USB_CTRL_GET_TIMEOUT); + dev_dbg(dev, "result = %d\n", result); + + /* send 5 cmd */ + /* + * 16.0 CTL a1 21 00 00 00 00 07 00 CLASS 33.1.0 + * 16.0 DI 80 25 00 00 00 00 08 + */ + len = 0x0007; + result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + 0x21, 0xa1, + 0x0000, 0x0000, buf, len, + HZ * USB_CTRL_GET_TIMEOUT); + debug_data(dev, __func__, len, buf, result); + + /* send 6 cmd */ + /* + * 16.0 CTL 21 20 00 00 00 00 07 00 CLASS 34.1.0 + * 16.0 DO 80 25 00 00 00 00 08 + */ + len = 0x0007; + buf[0] = 0x80; + buf[1] = 0x25; + buf[2] = 0x00; + buf[3] = 0x00; + buf[4] = 0x00; + buf[5] = 0x00; + buf[6] = 0x08; + result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x20, 0x21, + 0x0000, 0x0000, buf, len, + HZ * USB_CTRL_GET_TIMEOUT); + debug_data(dev, __func__, len, buf, result); + kfree(buf); + + return usb_serial_generic_open(tty, port); +} + +/* + * CTL 21 22 02 00 00 00 00 00 CLASS 338.1.0 + * + * 16.1 DI a1 20 00 00 00 00 02 00 02 00 . ........ 340.1.0 + * 16.0 CTL 21 22 03 00 00 00 00 00 CLASS 341.1.0 + * + * 16.0 CTL a1 21 00 00 00 00 07 00 CLASS 346.1.0(3) + * 16.0 DI 00 08 07 00 00 00 08 ....... 346.2.0 + * + * 16.0 CTL 21 20 00 00 00 00 07 00 CLASS 349.1.0 + * 16.0 DO 00 c2 01 00 00 00 08 ....... 349.2.0 + * + * 16.0 CTL 21 22 03 00 00 00 00 00 CLASS 350.1.0(2) + * + * 16.0 CTL a1 21 00 00 00 00 07 00 CLASS 352.1.0 + * 16.0 DI 00 c2 01 00 00 00 08 ....... 352.2.0 + * + * 16.1 DI a1 20 00 00 00 00 02 00 02 00 . ........ 353.1.0 + * + * 16.0 CTL 21 20 00 00 00 00 07 00 CLASS 354.1.0 + * 16.0 DO 00 c2 01 00 00 00 08 ....... 354.2.0 + * + * 16.0 CTL 21 22 03 00 00 00 00 00 +*/ + +static void zte_ev_usb_serial_close(struct usb_serial_port *port) +{ + struct usb_device *udev = port->serial->dev; + struct device *dev = &port->dev; + int result = 0; + int len; + unsigned char *buf; + + if (port->number != 0) + return; + + buf = kmalloc(MAX_SETUP_DATA_SIZE, GFP_KERNEL); + if (!buf) + return; + + /* send 1st ctl cmd(CTL 21 22 02 00 00 00 00 00) */ + len = 0; + result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x22, 0x21, + 0x0002, 0x0000, NULL, len, + HZ * USB_CTRL_GET_TIMEOUT); + dev_dbg(dev, "result = %d\n", result); + + /* send 2st ctl cmd(CTL 21 22 03 00 00 00 00 00 ) */ + len = 0; + result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x22, 0x21, + 0x0003, 0x0000, NULL, len, + HZ * USB_CTRL_GET_TIMEOUT); + dev_dbg(dev, "result = %d\n", result); + + /* send 3st cmd and recieve data */ + /* + * 16.0 CTL a1 21 00 00 00 00 07 00 CLASS 25.1.0(5) + * 16.0 DI 00 08 07 00 00 00 08 + */ + len = 0x0007; + result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + 0x21, 0xa1, + 0x0000, 0x0000, buf, len, + HZ * USB_CTRL_GET_TIMEOUT); + debug_data(dev, __func__, len, buf, result); + + /* send 4 cmd */ + /* + * 16.0 CTL 21 20 00 00 00 00 07 00 CLASS 30.1.0 + * 16.0 DO 00 c2 01 00 00 00 08 .%..... 30.2.0 + */ + len = 0x0007; + buf[0] = 0x00; + buf[1] = 0xc2; + buf[2] = 0x01; + buf[3] = 0x00; + buf[4] = 0x00; + buf[5] = 0x00; + buf[6] = 0x08; + result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x20, 0x21, + 0x0000, 0x0000, buf, len, + HZ * USB_CTRL_GET_TIMEOUT); + debug_data(dev, __func__, len, buf, result); + + /* send 5 cmd */ + /* + * 16.0 CTL 21 22 03 00 00 00 00 00 + */ + len = 0; + result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x22, 0x21, + 0x0003, 0x0000, NULL, len, + HZ * USB_CTRL_GET_TIMEOUT); + dev_dbg(dev, "result = %d\n", result); + + /* send 6 cmd */ + /* + * 16.0 CTL a1 21 00 00 00 00 07 00 CLASS 33.1.0 + * 16.0 DI 00 c2 01 00 00 00 08 + */ + len = 0x0007; + result = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), + 0x21, 0xa1, + 0x0000, 0x0000, buf, len, + HZ * USB_CTRL_GET_TIMEOUT); + debug_data(dev, __func__, len, buf, result); + + /* send 7 cmd */ + /* + * 16.0 CTL 21 20 00 00 00 00 07 00 CLASS 354.1.0 + * 16.0 DO 00 c2 01 00 00 00 08 ....... 354.2.0 + */ + len = 0x0007; + buf[0] = 0x00; + buf[1] = 0xc2; + buf[2] = 0x01; + buf[3] = 0x00; + buf[4] = 0x00; + buf[5] = 0x00; + buf[6] = 0x08; + result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x20, 0x21, + 0x0000, 0x0000, buf, len, + HZ * USB_CTRL_GET_TIMEOUT); + debug_data(dev, __func__, len, buf, result); + + /* send 8 cmd */ + /* + * 16.0 CTL 21 22 03 00 00 00 00 00 + */ + len = 0; + result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), + 0x22, 0x21, + 0x0003, 0x0000, NULL, len, + HZ * USB_CTRL_GET_TIMEOUT); + dev_dbg(dev, "result = %d\n", result); + + kfree(buf); + + usb_serial_generic_close(port); +} + +static const struct usb_device_id id_table[] = { + { USB_DEVICE(0x19d2, 0xffff) }, /* AC8700 */ + { USB_DEVICE(0x19d2, 0xfffe) }, + { USB_DEVICE(0x19d2, 0xfffd) }, /* MG880 */ + { USB_DEVICE(0x05C6, 0x3197) }, + { USB_DEVICE(0x05C6, 0x6000) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table); + +static struct usb_serial_driver zio_device = { + .driver = { + .owner = THIS_MODULE, + .name = "zte_ev", + }, + .id_table = id_table, + .num_ports = 1, + .open = zte_ev_usb_serial_open, + .close = zte_ev_usb_serial_close, +}; + +static struct usb_serial_driver * const serial_drivers[] = { + &zio_device, NULL +}; + +module_usb_serial_driver(serial_drivers, id_table); +MODULE_LICENSE("GPL v2"); -- cgit v0.10.2 From 34ad569fec46937b48cda329b037c1ff7fac9ab6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 13 Sep 2012 11:21:12 -0700 Subject: USB: atm: usbatm: fix up debug printing code If VERBOSE_DEBUG was enabled, lots of build errors happend (obviously no one uses this mode.) So fix that up, and get rid of the dbg() call, and use dev_dbg() like the rest of the driver does. Cc: Duncan Sands Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c index ee62b35..35f10bf 100644 --- a/drivers/usb/atm/usbatm.c +++ b/drivers/usb/atm/usbatm.c @@ -84,7 +84,7 @@ #include #ifdef VERBOSE_DEBUG -static int usbatm_print_packet(const unsigned char *data, int len); +static int usbatm_print_packet(struct usbatm_data *instance, const unsigned char *data, int len); #define PACKETDEBUG(arg...) usbatm_print_packet(arg) #define vdbg(arg...) dev_dbg(arg) #else @@ -230,8 +230,8 @@ static int usbatm_submit_urb(struct urb *urb) struct usbatm_channel *channel = urb->context; int ret; - vdbg("%s: submitting urb 0x%p, size %u", - __func__, urb, urb->transfer_buffer_length); + /* vdbg("%s: submitting urb 0x%p, size %u", + __func__, urb, urb->transfer_buffer_length); */ ret = usb_submit_urb(urb, GFP_ATOMIC); if (ret) { @@ -261,8 +261,8 @@ static void usbatm_complete(struct urb *urb) unsigned long flags; int status = urb->status; - vdbg("%s: urb 0x%p, status %d, actual_length %d", - __func__, urb, status, urb->actual_length); + /* vdbg("%s: urb 0x%p, status %d, actual_length %d", + __func__, urb, status, urb->actual_length); */ /* usually in_interrupt(), but not always */ spin_lock_irqsave(&channel->lock, flags); @@ -311,7 +311,7 @@ static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char int vci = ((source[1] & 0x0f) << 12) | (source[2] << 4) | (source[3] >> 4); u8 pti = ((source[3] & 0xe) >> 1); - vdbg("%s: vpi %hd, vci %d, pti %d", __func__, vpi, vci, pti); + vdbg(&instance->usb_intf->dev, "%s: vpi %hd, vci %d, pti %d", __func__, vpi, vci, pti); if ((vci != instance->cached_vci) || (vpi != instance->cached_vpi)) { instance->cached_vpi = vpi; @@ -381,7 +381,9 @@ static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char goto out; } - vdbg("%s: got packet (length: %u, pdu_length: %u, vcc: 0x%p)", __func__, length, pdu_length, vcc); + vdbg(&instance->usb_intf->dev, + "%s: got packet (length: %u, pdu_length: %u, vcc: 0x%p)", + __func__, length, pdu_length, vcc); if (!(skb = dev_alloc_skb(length))) { if (printk_ratelimit()) @@ -391,7 +393,9 @@ static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char goto out; } - vdbg("%s: allocated new sk_buff (skb: 0x%p, skb->truesize: %u)", __func__, skb, skb->truesize); + vdbg(&instance->usb_intf->dev, + "%s: allocated new sk_buff (skb: 0x%p, skb->truesize: %u)", + __func__, skb, skb->truesize); if (!atm_charge(vcc, skb->truesize)) { atm_rldbg(instance, "%s: failed atm_charge (skb->truesize: %u)!\n", @@ -405,10 +409,11 @@ static void usbatm_extract_one_cell(struct usbatm_data *instance, unsigned char length); __skb_put(skb, length); - vdbg("%s: sending skb 0x%p, skb->len %u, skb->truesize %u", + vdbg(&instance->usb_intf->dev, + "%s: sending skb 0x%p, skb->len %u, skb->truesize %u", __func__, skb, skb->len, skb->truesize); - PACKETDEBUG(skb->data, skb->len); + PACKETDEBUG(instance, skb->data, skb->len); vcc->push(vcc, skb); @@ -474,7 +479,8 @@ static unsigned int usbatm_write_cells(struct usbatm_data *instance, unsigned int bytes_written; unsigned int stride = instance->tx_channel.stride; - vdbg("%s: skb->len=%d, avail_space=%u", __func__, skb->len, avail_space); + vdbg(&instance->usb_intf->dev, "%s: skb->len=%d, avail_space=%u", + __func__, skb->len, avail_space); UDSL_ASSERT(instance, !(avail_space % stride)); for (bytes_written = 0; bytes_written < avail_space && ctrl->len; @@ -534,7 +540,8 @@ static void usbatm_rx_process(unsigned long data) struct urb *urb; while ((urb = usbatm_pop_urb(&instance->rx_channel))) { - vdbg("%s: processing urb 0x%p", __func__, urb); + vdbg(&instance->usb_intf->dev, + "%s: processing urb 0x%p", __func__, urb); if (usb_pipeisoc(urb->pipe)) { unsigned char *merge_start = NULL; @@ -608,7 +615,8 @@ static void usbatm_tx_process(unsigned long data) buffer + bytes_written, buf_size - bytes_written); - vdbg("%s: wrote %u bytes from skb 0x%p to urb 0x%p", + vdbg(&instance->usb_intf->dev, + "%s: wrote %u bytes from skb 0x%p to urb 0x%p", __func__, bytes_written, skb, urb); if (!UDSL_SKB(skb)->len) { @@ -664,7 +672,8 @@ static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) struct usbatm_control *ctrl = UDSL_SKB(skb); int err; - vdbg("%s called (skb 0x%p, len %u)", __func__, skb, skb->len); + vdbg(&instance->usb_intf->dev, "%s called (skb 0x%p, len %u)", __func__, + skb, skb->len); /* racy disconnection check - fine */ if (!instance || instance->disconnected) { @@ -688,7 +697,7 @@ static int usbatm_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) goto fail; } - PACKETDEBUG(skb->data, skb->len); + PACKETDEBUG(instance, skb->data, skb->len); /* initialize the control block */ ctrl->atm.vcc = vcc; @@ -1202,7 +1211,7 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id, if (i >= num_rcv_urbs) list_add_tail(&urb->urb_list, &channel->list); - vdbg("%s: alloced buffer 0x%p buf size %u urb 0x%p", + vdbg(&intf->dev, "%s: alloced buffer 0x%p buf size %u urb 0x%p", __func__, urb->transfer_buffer, urb->transfer_buffer_length, urb); } @@ -1359,7 +1368,8 @@ MODULE_VERSION(DRIVER_VERSION); ************/ #ifdef VERBOSE_DEBUG -static int usbatm_print_packet(const unsigned char *data, int len) +static int usbatm_print_packet(struct usbatm_data *instance, + const unsigned char *data, int len) { unsigned char buffer[256]; int i = 0, j = 0; @@ -1369,7 +1379,7 @@ static int usbatm_print_packet(const unsigned char *data, int len) sprintf(buffer, "%.3d :", i); for (j = 0; (j < 16) && (i < len); j++, i++) sprintf(buffer, "%s %2.2x", buffer, data[i]); - dbg("%s", buffer); + dev_dbg(&instance->usb_intf->dev, "%s", buffer); } return i; } -- cgit v0.10.2 From c2d57aec81f3d479642523fd4d3537006168c240 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 13 Sep 2012 11:23:03 -0700 Subject: USB: core: remove unused dbg() call in message.c It's not needed, and commented out, so just remove it. Cc: Sarah Sharp Cc: Alan Stern Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 0ab7da2..1ed5afd 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -146,8 +146,6 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, __u8 request, dr->wIndex = cpu_to_le16(index); dr->wLength = cpu_to_le16(size); - /* dbg("usb_control_msg"); */ - ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout); kfree(dr); -- cgit v0.10.2 From fee84a54e707d93282f1854a9f712534b6543a5e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 13 Sep 2012 15:39:01 -0700 Subject: USB: serial: core: remove some trace debugging calls These dbg() calls were no more than just a function trace, so remove them. If you want to see the functions being called, use the in-kernel function trace code instead, it's much nicer. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index b9cca6d..4a9b601 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -68,8 +68,6 @@ static int usb_console_setup(struct console *co, char *options) struct tty_struct *tty = NULL; struct ktermios dummy; - dbg("%s", __func__); - if (options) { baud = simple_strtoul(options, NULL, 10); s = options; diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 27483f9..5dd48f3 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -123,8 +123,6 @@ static void return_serial(struct usb_serial *serial) { int i; - dbg("%s", __func__); - mutex_lock(&table_lock); for (i = 0; i < serial->num_ports; ++i) serial_table[serial->minor + i] = NULL; @@ -191,8 +189,6 @@ static int serial_install(struct tty_driver *driver, struct tty_struct *tty) struct usb_serial_port *port; int retval = -ENODEV; - dbg("%s", __func__); - serial = usb_serial_get_by_index(idx); if (!serial) return retval; @@ -445,7 +441,6 @@ static int serial_proc_show(struct seq_file *m, void *v) int i; char tmp[40]; - dbg("%s", __func__); seq_puts(m, "usbserinfo:1.0 driver:2.0\n"); for (i = 0; i < SERIAL_TTY_MINORS; ++i) { serial = usb_serial_get_by_index(i); @@ -1100,7 +1095,6 @@ static void usb_serial_disconnect(struct usb_interface *interface) struct usb_serial_port *port; usb_serial_console_disconnect(serial); - dbg("%s", __func__); mutex_lock(&serial->disc_mutex); /* must set a flag, to signal subdrivers */ -- cgit v0.10.2 From c181bc5b5d5c79b71203cd10cef97f802fb6f9c1 Mon Sep 17 00:00:00 2001 From: Elric Fu Date: Wed, 27 Jun 2012 16:30:57 +0800 Subject: xHCI: add cmd_ring_state Adding cmd_ring_state for command ring. It helps to verify the current command ring state for controlling the command ring operations. This patch should be backported to kernels as old as 3.0. The commit 7ed603ecf8b68ab81f4c83097d3063d43ec73bb8 "xhci: Add an assertion to check for virt_dev=0 bug." papers over the NULL pointer dereference that I now believe is related to a timed out Set Address command. This (and the four patches that follow it) contain the real fix that also allows VIA USB 3.0 hubs to consistently re-enumerate during the plug/unplug stress tests. Signed-off-by: Elric Fu Signed-off-by: Sarah Sharp Tested-by: Miroslav Sabljic Cc: stable@vger.kernel.org diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 643c2f3..75c857e 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -280,6 +280,9 @@ static inline int room_on_ring(struct xhci_hcd *xhci, struct xhci_ring *ring, /* Ring the host controller doorbell after placing a command on the ring */ void xhci_ring_cmd_db(struct xhci_hcd *xhci) { + if (!(xhci->cmd_ring_state & CMD_RING_STATE_RUNNING)) + return; + xhci_dbg(xhci, "// Ding dong!\n"); xhci_writel(xhci, DB_VALUE_HOST, &xhci->dba->doorbell[0]); /* Flush PCI posted writes */ diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index c59d5b5..f425356 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -104,9 +104,10 @@ int xhci_halt(struct xhci_hcd *xhci) ret = handshake(xhci, &xhci->op_regs->status, STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC); - if (!ret) + if (!ret) { xhci->xhc_state |= XHCI_STATE_HALTED; - else + xhci->cmd_ring_state = CMD_RING_STATE_STOPPED; + } else xhci_warn(xhci, "Host not halted after %u microseconds.\n", XHCI_MAX_HALT_USEC); return ret; @@ -485,6 +486,7 @@ static int xhci_run_finished(struct xhci_hcd *xhci) return -ENODEV; } xhci->shared_hcd->state = HC_STATE_RUNNING; + xhci->cmd_ring_state = CMD_RING_STATE_RUNNING; if (xhci->quirks & XHCI_NEC_HOST) xhci_ring_cmd_db(xhci); diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index c713256..33f24e9 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1421,6 +1421,10 @@ struct xhci_hcd { /* data structures */ struct xhci_device_context_array *dcbaa; struct xhci_ring *cmd_ring; + unsigned int cmd_ring_state; +#define CMD_RING_STATE_RUNNING (1 << 0) +#define CMD_RING_STATE_ABORTED (1 << 1) +#define CMD_RING_STATE_STOPPED (1 << 2) unsigned int cmd_ring_reserved_trbs; struct xhci_ring *event_ring; struct xhci_erst erst; -- cgit v0.10.2 From b92cc66c047ff7cf587b318fe377061a353c120f Mon Sep 17 00:00:00 2001 From: Elric Fu Date: Wed, 27 Jun 2012 16:31:12 +0800 Subject: xHCI: add aborting command ring function Software have to abort command ring and cancel command when a command is failed or hang. Otherwise, the command ring will hang up and can't handle the others. An example of a command that may hang is the Address Device Command, because waiting for a SET_ADDRESS request to be acknowledged by a USB device is outside of the xHC's ability to control. To cancel a command, software will initialize a command descriptor for the cancel command, and add it into a cancel_cmd_list of xhci. Sarah: Fixed missing newline on "Have the command ring been stopped?" debugging statement. This patch should be backported to kernels as old as 3.0, that contain the commit 7ed603ecf8b68ab81f4c83097d3063d43ec73bb8 "xhci: Add an assertion to check for virt_dev=0 bug." That commit papers over a NULL pointer dereference, and this patch fixes the underlying issue that caused the NULL pointer dereference. Signed-off-by: Elric Fu Signed-off-by: Sarah Sharp Tested-by: Miroslav Sabljic Cc: stable@vger.kernel.org diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 77689bd..487bc08 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c @@ -1772,6 +1772,7 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) { struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); struct dev_info *dev_info, *next; + struct xhci_cd *cur_cd, *next_cd; unsigned long flags; int size; int i, j, num_ports; @@ -1795,6 +1796,11 @@ void xhci_mem_cleanup(struct xhci_hcd *xhci) xhci_ring_free(xhci, xhci->cmd_ring); xhci->cmd_ring = NULL; xhci_dbg(xhci, "Freed command ring\n"); + list_for_each_entry_safe(cur_cd, next_cd, + &xhci->cancel_cmd_list, cancel_cmd_list) { + list_del(&cur_cd->cancel_cmd_list); + kfree(cur_cd); + } for (i = 1; i < MAX_HC_SLOTS; ++i) xhci_free_virt_device(xhci, i); @@ -2340,6 +2346,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags) xhci->cmd_ring = xhci_ring_alloc(xhci, 1, 1, TYPE_COMMAND, flags); if (!xhci->cmd_ring) goto fail; + INIT_LIST_HEAD(&xhci->cancel_cmd_list); xhci_dbg(xhci, "Allocated command ring at %p\n", xhci->cmd_ring); xhci_dbg(xhci, "First segment DMA is 0x%llx\n", (unsigned long long)xhci->cmd_ring->first_seg->dma); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 75c857e..0b0e720 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -289,6 +289,114 @@ void xhci_ring_cmd_db(struct xhci_hcd *xhci) xhci_readl(xhci, &xhci->dba->doorbell[0]); } +static int xhci_abort_cmd_ring(struct xhci_hcd *xhci) +{ + u64 temp_64; + int ret; + + xhci_dbg(xhci, "Abort command ring\n"); + + if (!(xhci->cmd_ring_state & CMD_RING_STATE_RUNNING)) { + xhci_dbg(xhci, "The command ring isn't running, " + "Have the command ring been stopped?\n"); + return 0; + } + + temp_64 = xhci_read_64(xhci, &xhci->op_regs->cmd_ring); + if (!(temp_64 & CMD_RING_RUNNING)) { + xhci_dbg(xhci, "Command ring had been stopped\n"); + return 0; + } + xhci->cmd_ring_state = CMD_RING_STATE_ABORTED; + xhci_write_64(xhci, temp_64 | CMD_RING_ABORT, + &xhci->op_regs->cmd_ring); + + /* Section 4.6.1.2 of xHCI 1.0 spec says software should + * time the completion od all xHCI commands, including + * the Command Abort operation. If software doesn't see + * CRR negated in a timely manner (e.g. longer than 5 + * seconds), then it should assume that the there are + * larger problems with the xHC and assert HCRST. + */ + ret = handshake(xhci, &xhci->op_regs->cmd_ring, + CMD_RING_RUNNING, 0, 5 * 1000 * 1000); + if (ret < 0) { + xhci_err(xhci, "Stopped the command ring failed, " + "maybe the host is dead\n"); + xhci->xhc_state |= XHCI_STATE_DYING; + xhci_quiesce(xhci); + xhci_halt(xhci); + return -ESHUTDOWN; + } + + return 0; +} + +static int xhci_queue_cd(struct xhci_hcd *xhci, + struct xhci_command *command, + union xhci_trb *cmd_trb) +{ + struct xhci_cd *cd; + cd = kzalloc(sizeof(struct xhci_cd), GFP_ATOMIC); + if (!cd) + return -ENOMEM; + INIT_LIST_HEAD(&cd->cancel_cmd_list); + + cd->command = command; + cd->cmd_trb = cmd_trb; + list_add_tail(&cd->cancel_cmd_list, &xhci->cancel_cmd_list); + + return 0; +} + +/* + * Cancel the command which has issue. + * + * Some commands may hang due to waiting for acknowledgement from + * usb device. It is outside of the xHC's ability to control and + * will cause the command ring is blocked. When it occurs software + * should intervene to recover the command ring. + * See Section 4.6.1.1 and 4.6.1.2 + */ +int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command, + union xhci_trb *cmd_trb) +{ + int retval = 0; + unsigned long flags; + + spin_lock_irqsave(&xhci->lock, flags); + + if (xhci->xhc_state & XHCI_STATE_DYING) { + xhci_warn(xhci, "Abort the command ring," + " but the xHCI is dead.\n"); + retval = -ESHUTDOWN; + goto fail; + } + + /* queue the cmd desriptor to cancel_cmd_list */ + retval = xhci_queue_cd(xhci, command, cmd_trb); + if (retval) { + xhci_warn(xhci, "Queuing command descriptor failed.\n"); + goto fail; + } + + /* abort command ring */ + retval = xhci_abort_cmd_ring(xhci); + if (retval) { + xhci_err(xhci, "Abort command ring failed\n"); + if (unlikely(retval == -ESHUTDOWN)) { + spin_unlock_irqrestore(&xhci->lock, flags); + usb_hc_died(xhci_to_hcd(xhci)->primary_hcd); + xhci_dbg(xhci, "xHCI host controller is dead.\n"); + return retval; + } + } + +fail: + spin_unlock_irqrestore(&xhci->lock, flags); + return retval; +} + void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index f425356..3f0763d 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -51,7 +51,7 @@ MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB"); * handshake done). There are two failure modes: "usec" have passed (major * hardware flakeout), or the register reads as all-ones (hardware removed). */ -static int handshake(struct xhci_hcd *xhci, void __iomem *ptr, +int handshake(struct xhci_hcd *xhci, void __iomem *ptr, u32 mask, u32 done, int usec) { u32 result; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index 33f24e9..fdfcebf 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1256,6 +1256,13 @@ struct xhci_td { union xhci_trb *last_trb; }; +/* command descriptor */ +struct xhci_cd { + struct list_head cancel_cmd_list; + struct xhci_command *command; + union xhci_trb *cmd_trb; +}; + struct xhci_dequeue_state { struct xhci_segment *new_deq_seg; union xhci_trb *new_deq_ptr; @@ -1425,6 +1432,7 @@ struct xhci_hcd { #define CMD_RING_STATE_RUNNING (1 << 0) #define CMD_RING_STATE_ABORTED (1 << 1) #define CMD_RING_STATE_STOPPED (1 << 2) + struct list_head cancel_cmd_list; unsigned int cmd_ring_reserved_trbs; struct xhci_ring *event_ring; struct xhci_erst erst; @@ -1702,6 +1710,8 @@ static inline void xhci_unregister_plat(void) /* xHCI host controller glue */ typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *); +int handshake(struct xhci_hcd *xhci, void __iomem *ptr, + u32 mask, u32 done, int usec); void xhci_quiesce(struct xhci_hcd *xhci); int xhci_halt(struct xhci_hcd *xhci); int xhci_reset(struct xhci_hcd *xhci); @@ -1792,6 +1802,8 @@ void xhci_queue_config_ep_quirk(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, struct xhci_dequeue_state *deq_state); void xhci_stop_endpoint_command_watchdog(unsigned long arg); +int xhci_cancel_cmd(struct xhci_hcd *xhci, struct xhci_command *command, + union xhci_trb *cmd_trb); void xhci_ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, unsigned int stream_id); -- cgit v0.10.2 From 6e4468b9a0793dfb53eb80d9fe52c739b13b27fd Mon Sep 17 00:00:00 2001 From: Elric Fu Date: Wed, 27 Jun 2012 16:31:52 +0800 Subject: xHCI: cancel command after command timeout The patch is used to cancel command when the command isn't acknowledged and a timeout occurs. This patch should be backported to kernels as old as 3.0, that contain the commit 7ed603ecf8b68ab81f4c83097d3063d43ec73bb8 "xhci: Add an assertion to check for virt_dev=0 bug." That commit papers over a NULL pointer dereference, and this patch fixes the underlying issue that caused the NULL pointer dereference. Signed-off-by: Elric Fu Signed-off-by: Sarah Sharp Tested-by: Miroslav Sabljic Cc: stable@vger.kernel.org diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 3f0763d..b95e3e8 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -2402,6 +2402,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, struct completion *cmd_completion; u32 *cmd_status; struct xhci_virt_device *virt_dev; + union xhci_trb *cmd_trb; spin_lock_irqsave(&xhci->lock, flags); virt_dev = xhci->devs[udev->slot_id]; @@ -2447,6 +2448,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, } init_completion(cmd_completion); + cmd_trb = xhci->cmd_ring->dequeue; if (!ctx_change) ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma, udev->slot_id, must_succeed); @@ -2468,14 +2470,17 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci, /* Wait for the configure endpoint command to complete */ timeleft = wait_for_completion_interruptible_timeout( cmd_completion, - USB_CTRL_SET_TIMEOUT); + XHCI_CMD_DEFAULT_TIMEOUT); if (timeleft <= 0) { xhci_warn(xhci, "%s while waiting for %s command\n", timeleft == 0 ? "Timeout" : "Signal", ctx_change == 0 ? "configure endpoint" : "evaluate context"); - /* FIXME cancel the configure endpoint command */ + /* cancel the configure endpoint command */ + ret = xhci_cancel_cmd(xhci, command, cmd_trb); + if (ret < 0) + return ret; return -ETIME; } @@ -3424,8 +3429,10 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) unsigned long flags; int timeleft; int ret; + union xhci_trb *cmd_trb; spin_lock_irqsave(&xhci->lock, flags); + cmd_trb = xhci->cmd_ring->dequeue; ret = xhci_queue_slot_control(xhci, TRB_ENABLE_SLOT, 0); if (ret) { spin_unlock_irqrestore(&xhci->lock, flags); @@ -3437,12 +3444,12 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev) /* XXX: how much time for xHC slot assignment? */ timeleft = wait_for_completion_interruptible_timeout(&xhci->addr_dev, - USB_CTRL_SET_TIMEOUT); + XHCI_CMD_DEFAULT_TIMEOUT); if (timeleft <= 0) { xhci_warn(xhci, "%s while waiting for a slot\n", timeleft == 0 ? "Timeout" : "Signal"); - /* FIXME cancel the enable slot request */ - return 0; + /* cancel the enable slot request */ + return xhci_cancel_cmd(xhci, NULL, cmd_trb); } if (!xhci->slot_id) { @@ -3503,6 +3510,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) struct xhci_slot_ctx *slot_ctx; struct xhci_input_control_ctx *ctrl_ctx; u64 temp_64; + union xhci_trb *cmd_trb; if (!udev->slot_id) { xhci_dbg(xhci, "Bad Slot ID %d\n", udev->slot_id); @@ -3541,6 +3549,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) xhci_dbg_ctx(xhci, virt_dev->in_ctx, 2); spin_lock_irqsave(&xhci->lock, flags); + cmd_trb = xhci->cmd_ring->dequeue; ret = xhci_queue_address_device(xhci, virt_dev->in_ctx->dma, udev->slot_id); if (ret) { @@ -3553,7 +3562,7 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) /* ctrl tx can take up to 5 sec; XXX: need more time for xHC? */ timeleft = wait_for_completion_interruptible_timeout(&xhci->addr_dev, - USB_CTRL_SET_TIMEOUT); + XHCI_CMD_DEFAULT_TIMEOUT); /* FIXME: From section 4.3.4: "Software shall be responsible for timing * the SetAddress() "recovery interval" required by USB and aborting the * command on a timeout. @@ -3561,7 +3570,10 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) if (timeleft <= 0) { xhci_warn(xhci, "%s while waiting for address device command\n", timeleft == 0 ? "Timeout" : "Signal"); - /* FIXME cancel the address device command */ + /* cancel the address device command */ + ret = xhci_cancel_cmd(xhci, NULL, cmd_trb); + if (ret < 0) + return ret; return -ETIME; } diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index fdfcebf..e81ccfa 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1256,6 +1256,9 @@ struct xhci_td { union xhci_trb *last_trb; }; +/* xHCI command default timeout value */ +#define XHCI_CMD_DEFAULT_TIMEOUT (5 * HZ) + /* command descriptor */ struct xhci_cd { struct list_head cancel_cmd_list; -- cgit v0.10.2 From b63f4053cc8aa22a98e3f9a97845afe6c15d0a0d Mon Sep 17 00:00:00 2001 From: Elric Fu Date: Wed, 27 Jun 2012 16:55:43 +0800 Subject: xHCI: handle command after aborting the command ring According to xHCI spec section 4.6.1.1 and section 4.6.1.2, after aborting a command on the command ring, xHC will generate a command completion event with its completion code set to Command Ring Stopped at least. If a command is currently executing at the time of aborting a command, xHC also generate a command completion event with its completion code set to Command Abort. When the command ring is stopped, software may remove, add, or rearrage Command Descriptors. To cancel a command, software will initialize a command descriptor for the cancel command, and add it into a cancel_cmd_list of xhci. When the command ring is stopped, software will find the command trbs described by command descriptors in cancel_cmd_list and modify it to No Op command. If software can't find the matched trbs, we can think it had been finished. This patch should be backported to kernels as old as 3.0, that contain the commit 7ed603ecf8b68ab81f4c83097d3063d43ec73bb8 "xhci: Add an assertion to check for virt_dev=0 bug." That commit papers over a NULL pointer dereference, and this patch fixes the underlying issue that caused the NULL pointer dereference. Signed-off-by: Elric Fu Signed-off-by: Sarah Sharp Tested-by: Miroslav Sabljic Cc: stable@vger.kernel.org diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 0b0e720..700709c 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -1170,6 +1170,20 @@ static void handle_reset_ep_completion(struct xhci_hcd *xhci, } } +/* Complete the command and detele it from the devcie's command queue. + */ +static void xhci_complete_cmd_in_cmd_wait_list(struct xhci_hcd *xhci, + struct xhci_command *command, u32 status) +{ + command->status = status; + list_del(&command->cmd_list); + if (command->completion) + complete(command->completion); + else + xhci_free_command(xhci, command); +} + + /* Check to see if a command in the device's command queue matches this one. * Signal the completion or free the command, and return 1. Return 0 if the * completed command isn't at the head of the command list. @@ -1188,15 +1202,144 @@ static int handle_cmd_in_cmd_wait_list(struct xhci_hcd *xhci, if (xhci->cmd_ring->dequeue != command->command_trb) return 0; - command->status = GET_COMP_CODE(le32_to_cpu(event->status)); - list_del(&command->cmd_list); - if (command->completion) - complete(command->completion); - else - xhci_free_command(xhci, command); + xhci_complete_cmd_in_cmd_wait_list(xhci, command, + GET_COMP_CODE(le32_to_cpu(event->status))); return 1; } +/* + * Finding the command trb need to be cancelled and modifying it to + * NO OP command. And if the command is in device's command wait + * list, finishing and freeing it. + * + * If we can't find the command trb, we think it had already been + * executed. + */ +static void xhci_cmd_to_noop(struct xhci_hcd *xhci, struct xhci_cd *cur_cd) +{ + struct xhci_segment *cur_seg; + union xhci_trb *cmd_trb; + u32 cycle_state; + + if (xhci->cmd_ring->dequeue == xhci->cmd_ring->enqueue) + return; + + /* find the current segment of command ring */ + cur_seg = find_trb_seg(xhci->cmd_ring->first_seg, + xhci->cmd_ring->dequeue, &cycle_state); + + /* find the command trb matched by cd from command ring */ + for (cmd_trb = xhci->cmd_ring->dequeue; + cmd_trb != xhci->cmd_ring->enqueue; + next_trb(xhci, xhci->cmd_ring, &cur_seg, &cmd_trb)) { + /* If the trb is link trb, continue */ + if (TRB_TYPE_LINK_LE32(cmd_trb->generic.field[3])) + continue; + + if (cur_cd->cmd_trb == cmd_trb) { + + /* If the command in device's command list, we should + * finish it and free the command structure. + */ + if (cur_cd->command) + xhci_complete_cmd_in_cmd_wait_list(xhci, + cur_cd->command, COMP_CMD_STOP); + + /* get cycle state from the origin command trb */ + cycle_state = le32_to_cpu(cmd_trb->generic.field[3]) + & TRB_CYCLE; + + /* modify the command trb to NO OP command */ + cmd_trb->generic.field[0] = 0; + cmd_trb->generic.field[1] = 0; + cmd_trb->generic.field[2] = 0; + cmd_trb->generic.field[3] = cpu_to_le32( + TRB_TYPE(TRB_CMD_NOOP) | cycle_state); + break; + } + } +} + +static void xhci_cancel_cmd_in_cd_list(struct xhci_hcd *xhci) +{ + struct xhci_cd *cur_cd, *next_cd; + + if (list_empty(&xhci->cancel_cmd_list)) + return; + + list_for_each_entry_safe(cur_cd, next_cd, + &xhci->cancel_cmd_list, cancel_cmd_list) { + xhci_cmd_to_noop(xhci, cur_cd); + list_del(&cur_cd->cancel_cmd_list); + kfree(cur_cd); + } +} + +/* + * traversing the cancel_cmd_list. If the command descriptor according + * to cmd_trb is found, the function free it and return 1, otherwise + * return 0. + */ +static int xhci_search_cmd_trb_in_cd_list(struct xhci_hcd *xhci, + union xhci_trb *cmd_trb) +{ + struct xhci_cd *cur_cd, *next_cd; + + if (list_empty(&xhci->cancel_cmd_list)) + return 0; + + list_for_each_entry_safe(cur_cd, next_cd, + &xhci->cancel_cmd_list, cancel_cmd_list) { + if (cur_cd->cmd_trb == cmd_trb) { + if (cur_cd->command) + xhci_complete_cmd_in_cmd_wait_list(xhci, + cur_cd->command, COMP_CMD_STOP); + list_del(&cur_cd->cancel_cmd_list); + kfree(cur_cd); + return 1; + } + } + + return 0; +} + +/* + * If the cmd_trb_comp_code is COMP_CMD_ABORT, we just check whether the + * trb pointed by the command ring dequeue pointer is the trb we want to + * cancel or not. And if the cmd_trb_comp_code is COMP_CMD_STOP, we will + * traverse the cancel_cmd_list to trun the all of the commands according + * to command descriptor to NO-OP trb. + */ +static int handle_stopped_cmd_ring(struct xhci_hcd *xhci, + int cmd_trb_comp_code) +{ + int cur_trb_is_good = 0; + + /* Searching the cmd trb pointed by the command ring dequeue + * pointer in command descriptor list. If it is found, free it. + */ + cur_trb_is_good = xhci_search_cmd_trb_in_cd_list(xhci, + xhci->cmd_ring->dequeue); + + if (cmd_trb_comp_code == COMP_CMD_ABORT) + xhci->cmd_ring_state = CMD_RING_STATE_STOPPED; + else if (cmd_trb_comp_code == COMP_CMD_STOP) { + /* traversing the cancel_cmd_list and canceling + * the command according to command descriptor + */ + xhci_cancel_cmd_in_cd_list(xhci); + + xhci->cmd_ring_state = CMD_RING_STATE_RUNNING; + /* + * ring command ring doorbell again to restart the + * command ring + */ + if (xhci->cmd_ring->dequeue != xhci->cmd_ring->enqueue) + xhci_ring_cmd_db(xhci); + } + return cur_trb_is_good; +} + static void handle_cmd_completion(struct xhci_hcd *xhci, struct xhci_event_cmd *event) { @@ -1222,6 +1365,22 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, xhci->error_bitmask |= 1 << 5; return; } + + if ((GET_COMP_CODE(le32_to_cpu(event->status)) == COMP_CMD_ABORT) || + (GET_COMP_CODE(le32_to_cpu(event->status)) == COMP_CMD_STOP)) { + /* If the return value is 0, we think the trb pointed by + * command ring dequeue pointer is a good trb. The good + * trb means we don't want to cancel the trb, but it have + * been stopped by host. So we should handle it normally. + * Otherwise, driver should invoke inc_deq() and return. + */ + if (handle_stopped_cmd_ring(xhci, + GET_COMP_CODE(le32_to_cpu(event->status)))) { + inc_deq(xhci, xhci->cmd_ring); + return; + } + } + switch (le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3]) & TRB_TYPE_BITMASK) { case TRB_TYPE(TRB_ENABLE_SLOT): -- cgit v0.10.2 From ed384bd3a8faab3b3e09fd2cab8a7dc95851d771 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Tue, 7 Aug 2012 14:10:03 +0300 Subject: usb: host: xhci: sparse fixes drivers/usb/host/xhci.c:1826:14: warning: symbol 'xhci_get_block_size' was not declared. Should it be static? drivers/usb/host/xhci.c:1844:14: warning: symbol 'xhci_get_largest_overhead' was not declared. Should it be static? drivers/usb/host/xhci-ring.c:2304:36: warning: context imbalance in 'handle_tx_event' - unexpected unlock drivers/usb/host/xhci-hub.c:425:6: warning: symbol 'xhci_set_remote_wake_mask' was not declared. Should it be static? Signed-off-by: Felipe Balbi Signed-off-by: Sarah Sharp diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index 630e9e6..eb640d0 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -422,7 +422,7 @@ void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array, xhci_writel(xhci, temp, port_array[port_id]); } -void xhci_set_remote_wake_mask(struct xhci_hcd *xhci, +static void xhci_set_remote_wake_mask(struct xhci_hcd *xhci, __le32 __iomem **port_array, int port_id, u16 wake_mask) { u32 temp; diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 700709c..37e23ed 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2273,6 +2273,8 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, */ static int handle_tx_event(struct xhci_hcd *xhci, struct xhci_transfer_event *event) + __releases(&xhci->lock) + __acquires(&xhci->lock) { struct xhci_virt_device *xdev; struct xhci_virt_ep *ep; diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index b95e3e8..66bc5c3 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1829,7 +1829,7 @@ static void xhci_finish_resource_reservation(struct xhci_hcd *xhci, xhci->num_active_eps); } -unsigned int xhci_get_block_size(struct usb_device *udev) +static unsigned int xhci_get_block_size(struct usb_device *udev) { switch (udev->speed) { case USB_SPEED_LOW: @@ -1847,7 +1847,8 @@ unsigned int xhci_get_block_size(struct usb_device *udev) } } -unsigned int xhci_get_largest_overhead(struct xhci_interval_bw *interval_bw) +static unsigned int +xhci_get_largest_overhead(struct xhci_interval_bw *interval_bw) { if (interval_bw->overhead[LS_OVERHEAD_TYPE]) return LS_OVERHEAD; -- cgit v0.10.2 From 3415fc94bba86b397f1fefec3c904bfc57de7038 Mon Sep 17 00:00:00 2001 From: Sebastian Andrzej Siewior Date: Wed, 22 Aug 2012 15:12:06 +0200 Subject: usb/xhci: update a comment regarding the BOS descriptor to reflect the code The comment is a quote of Alan Stern and reflects the data structure better than the the initial comment. Signed-off-by: Sebastian Andrzej Siewior Signed-off-by: Sarah Sharp diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index eb640d0..5896f05 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c @@ -29,7 +29,7 @@ #define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \ PORT_RC | PORT_PLC | PORT_PE) -/* usb 1.1 root hub device descriptor */ +/* USB 3.0 BOS descriptor and a capability descriptor, combined */ static u8 usb_bos_descriptor [] = { USB_DT_BOS_SIZE, /* __u8 bLength, 5 bytes */ USB_DT_BOS, /* __u8 bDescriptorType */ -- cgit v0.10.2 From 261fa12be074f2731f727bfca372c9f727060196 Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Wed, 12 Sep 2012 19:03:17 +0200 Subject: drivers/usb/host/xhci-ring.c: removes unnecessary semicolon removes unnecessary semicolon Found by Coccinelle: http://coccinelle.lip6.fr/ Signed-off-by: Peter Senna Tschudin Signed-off-by: Sarah Sharp diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 37e23ed..f270e70 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2852,7 +2852,7 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring, xhci_err(xhci, "Ring expansion failed\n"); return -ENOMEM; } - }; + } if (enqueue_is_link_trb(ep_ring)) { struct xhci_ring *ring = ep_ring; -- cgit v0.10.2 From 92931d243b5cafa23de2d693342966bb9133cdbc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 13 Sep 2012 16:30:31 -0700 Subject: USB: serial: core: clean up dbg and printk usage. This cleans up the usb-serial module to remove all old usages of dbg() and "raw" printk() calls for error reporting (there are some info messages left for now.) Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 4a9b601..335f98d 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -11,6 +11,8 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -111,8 +113,7 @@ static int usb_console_setup(struct console *co, char *options) serial = usb_serial_get_by_index(co->index); if (serial == NULL) { /* no device is connected yet, sorry :( */ - printk(KERN_ERR "No USB device connected to ttyUSB%i\n", - co->index); + pr_err("No USB device connected to ttyUSB%i\n", co->index); return -ENODEV; } @@ -211,10 +212,10 @@ static void usb_console_write(struct console *co, if (count == 0) return; - dbg("%s - port %d, %d byte(s)", __func__, port->number, count); + pr_debug("%s - port %d, %d byte(s)\n", __func__, port->number, count); if (!port->port.console) { - dbg("%s - port not opened", __func__); + pr_debug("%s - port not opened\n", __func__); return; } @@ -235,7 +236,7 @@ static void usb_console_write(struct console *co, retval = serial->type->write(NULL, port, buf, i); else retval = usb_serial_generic_write(NULL, port, buf, i); - dbg("%s - return value : %d", __func__, retval); + pr_debug("%s - return value : %d\n", __func__, retval); if (lf) { /* append CR after LF */ unsigned char cr = 13; @@ -245,7 +246,7 @@ static void usb_console_write(struct console *co, else retval = usb_serial_generic_write(NULL, port, &cr, 1); - dbg("%s - return value : %d", __func__, retval); + pr_debug("%s - return value : %d\n", __func__, retval); } buf += i; count -= i; @@ -300,7 +301,7 @@ void usb_serial_console_init(int serial_debug, int minor) * register_console). console_write() is called immediately * from register_console iff CON_PRINTBUFFER is set in flags. */ - dbg("registering the USB serial console."); + pr_debug("registering the USB serial console.\n"); register_console(&usbcons); } } diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 5dd48f3..8a9352b 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -17,6 +17,8 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include #include #include @@ -87,7 +89,7 @@ static struct usb_serial *get_free_serial(struct usb_serial *serial, unsigned int i, j; int good_spot; - dbg("%s %d", __func__, num_ports); + dev_dbg(&serial->interface->dev, "%s %d\n", __func__, num_ports); *minor = 0; mutex_lock(&table_lock); @@ -107,7 +109,7 @@ static struct usb_serial *get_free_serial(struct usb_serial *serial, *minor = i; j = 0; - dbg("%s - minor base = %d", __func__, *minor); + dev_dbg(&serial->interface->dev, "%s - minor base = %d\n", __func__, *minor); for (i = *minor; (i < (*minor + num_ports)) && (i < SERIAL_TTY_MINORS); ++i) { serial_table[i] = serial; serial->port[j++]->number = i; @@ -137,8 +139,6 @@ static void destroy_serial(struct kref *kref) serial = to_usb_serial(kref); - dbg("%s - %s", __func__, serial->type->description); - /* return the minor range that this device had */ if (serial->minor != SERIAL_TTY_NO_MINOR) return_serial(serial); @@ -252,7 +252,7 @@ static int serial_open(struct tty_struct *tty, struct file *filp) { struct usb_serial_port *port = tty->driver_data; - dbg("%s - port %d", __func__, port->number); + dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); return tty_port_open(&port->port, tty, filp); } @@ -283,14 +283,16 @@ static void serial_down(struct tty_port *tport) static void serial_hangup(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - dbg("%s - port %d", __func__, port->number); + + dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); tty_port_hangup(&port->port); } static void serial_close(struct tty_struct *tty, struct file *filp) { struct usb_serial_port *port = tty->driver_data; - dbg("%s - port %d", __func__, port->number); + + dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); tty_port_close(&port->port, tty, filp); } @@ -316,7 +318,7 @@ static void serial_cleanup(struct tty_struct *tty) if (port->port.console) return; - dbg("%s - port %d", __func__, port->number); + dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); tty->driver_data = NULL; @@ -341,7 +343,8 @@ static int serial_write(struct tty_struct *tty, const unsigned char *buf, if (port->serial->dev->state == USB_STATE_NOTATTACHED) goto exit; - dbg("%s - port %d, %d byte(s)", __func__, port->number, count); + dev_dbg(tty->dev, "%s - port %d, %d byte(s)\n", __func__, + port->number, count); /* pass on to the driver specific version of this function */ retval = port->serial->type->write(tty, port, buf, count); @@ -354,7 +357,8 @@ exit: static int serial_write_room(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - dbg("%s - port %d", __func__, port->number); + + dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); /* pass on to the driver specific version of this function */ return port->serial->type->write_room(tty); } @@ -362,7 +366,8 @@ static int serial_write_room(struct tty_struct *tty) static int serial_chars_in_buffer(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - dbg("%s - port %d", __func__, port->number); + + dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); /* if the device was unplugged then any remaining characters fell out of the connector ;) */ @@ -375,7 +380,8 @@ static int serial_chars_in_buffer(struct tty_struct *tty) static void serial_throttle(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - dbg("%s - port %d", __func__, port->number); + + dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); /* pass on to the driver specific version of this function */ if (port->serial->type->throttle) @@ -385,7 +391,8 @@ static void serial_throttle(struct tty_struct *tty) static void serial_unthrottle(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - dbg("%s - port %d", __func__, port->number); + + dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); /* pass on to the driver specific version of this function */ if (port->serial->type->unthrottle) @@ -398,7 +405,8 @@ static int serial_ioctl(struct tty_struct *tty, struct usb_serial_port *port = tty->driver_data; int retval = -ENODEV; - dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd); + dev_dbg(tty->dev, "%s - port %d, cmd 0x%.4x\n", __func__, + port->number, cmd); /* pass on to the driver specific version of this function if it is available */ @@ -412,7 +420,8 @@ static int serial_ioctl(struct tty_struct *tty, static void serial_set_termios(struct tty_struct *tty, struct ktermios *old) { struct usb_serial_port *port = tty->driver_data; - dbg("%s - port %d", __func__, port->number); + + dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); /* pass on to the driver specific version of this function if it is available */ @@ -426,7 +435,7 @@ static int serial_break(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; - dbg("%s - port %d", __func__, port->number); + dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); /* pass on to the driver specific version of this function if it is available */ @@ -485,7 +494,7 @@ static int serial_tiocmget(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; - dbg("%s - port %d", __func__, port->number); + dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); if (port->serial->type->tiocmget) return port->serial->type->tiocmget(tty); @@ -497,7 +506,7 @@ static int serial_tiocmset(struct tty_struct *tty, { struct usb_serial_port *port = tty->driver_data; - dbg("%s - port %d", __func__, port->number); + dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); if (port->serial->type->tiocmset) return port->serial->type->tiocmset(tty, set, clear); @@ -509,7 +518,7 @@ static int serial_get_icount(struct tty_struct *tty, { struct usb_serial_port *port = tty->driver_data; - dbg("%s - port %d", __func__, port->number); + dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); if (port->serial->type->get_icount) return port->serial->type->get_icount(tty, icount); @@ -533,12 +542,12 @@ static void usb_serial_port_work(struct work_struct *work) container_of(work, struct usb_serial_port, work); struct tty_struct *tty; - dbg("%s - port %d", __func__, port->number); - tty = tty_port_tty_get(&port->port); if (!tty) return; + dev_dbg(tty->dev, "%s - port %d\n", __func__, port->number); + tty_wakeup(tty); tty_kref_put(tty); } @@ -571,7 +580,7 @@ static void port_release(struct device *dev) struct usb_serial_port *port = to_usb_serial_port(dev); int i; - dbg ("%s - %s", __func__, dev_name(dev)); + dev_dbg(dev, "%s\n", __func__); /* * Stop all the traffic before cancelling the work, so that @@ -640,12 +649,12 @@ static const struct usb_device_id *get_iface_id(struct usb_serial_driver *drv, id = usb_match_id(intf, drv->id_table); if (id) { - dbg("static descriptor matches"); + dev_dbg(&intf->dev, "static descriptor matches\n"); goto exit; } id = match_dynamic_id(intf, drv); if (id) - dbg("dynamic descriptor matches"); + dev_dbg(&intf->dev, "dynamic descriptor matches\n"); exit: return id; } @@ -699,6 +708,7 @@ static const struct tty_port_operations serial_port_ops = { static int usb_serial_probe(struct usb_interface *interface, const struct usb_device_id *id) { + struct device *ddev = &interface->dev; struct usb_device *dev = interface_to_usbdev(interface); struct usb_serial *serial = NULL; struct usb_serial_port *port; @@ -725,13 +735,13 @@ static int usb_serial_probe(struct usb_interface *interface, type = search_serial_device(interface); if (!type) { mutex_unlock(&table_lock); - dbg("none matched"); + dev_dbg(ddev, "none matched\n"); return -ENODEV; } if (!try_module_get(type->driver.owner)) { mutex_unlock(&table_lock); - dev_err(&interface->dev, "module get failed, exiting\n"); + dev_err(ddev, "module get failed, exiting\n"); return -EIO; } mutex_unlock(&table_lock); @@ -739,7 +749,7 @@ static int usb_serial_probe(struct usb_interface *interface, serial = create_serial(dev, interface, type); if (!serial) { module_put(type->driver.owner); - dev_err(&interface->dev, "%s - out of memory\n", __func__); + dev_err(ddev, "%s - out of memory\n", __func__); return -ENOMEM; } @@ -751,7 +761,7 @@ static int usb_serial_probe(struct usb_interface *interface, retval = type->probe(serial, id); if (retval) { - dbg("sub driver rejected device"); + dev_dbg(ddev, "sub driver rejected device\n"); usb_serial_put(serial); module_put(type->driver.owner); return retval; @@ -766,28 +776,28 @@ static int usb_serial_probe(struct usb_interface *interface, if (usb_endpoint_is_bulk_in(endpoint)) { /* we found a bulk in endpoint */ - dbg("found bulk in on endpoint %d", i); + dev_dbg(ddev, "found bulk in on endpoint %d\n", i); bulk_in_endpoint[num_bulk_in] = endpoint; ++num_bulk_in; } if (usb_endpoint_is_bulk_out(endpoint)) { /* we found a bulk out endpoint */ - dbg("found bulk out on endpoint %d", i); + dev_dbg(ddev, "found bulk out on endpoint %d\n", i); bulk_out_endpoint[num_bulk_out] = endpoint; ++num_bulk_out; } if (usb_endpoint_is_int_in(endpoint)) { /* we found a interrupt in endpoint */ - dbg("found interrupt in on endpoint %d", i); + dev_dbg(ddev, "found interrupt in on endpoint %d\n", i); interrupt_in_endpoint[num_interrupt_in] = endpoint; ++num_interrupt_in; } if (usb_endpoint_is_int_out(endpoint)) { /* we found an interrupt out endpoint */ - dbg("found interrupt out on endpoint %d", i); + dev_dbg(ddev, "found interrupt out on endpoint %d\n", i); interrupt_out_endpoint[num_interrupt_out] = endpoint; ++num_interrupt_out; } @@ -811,7 +821,7 @@ static int usb_serial_probe(struct usb_interface *interface, endpoint = &iface_desc->endpoint[i].desc; if (usb_endpoint_is_int_in(endpoint)) { /* we found a interrupt in endpoint */ - dbg("found interrupt in for Prolific device on separate interface"); + dev_dbg(ddev, "found interrupt in for Prolific device on separate interface\n"); interrupt_in_endpoint[num_interrupt_in] = endpoint; ++num_interrupt_in; } @@ -823,7 +833,7 @@ static int usb_serial_probe(struct usb_interface *interface, * properly during a later invocation of usb_serial_probe */ if (num_bulk_in == 0 || num_bulk_out == 0) { - dev_info(&interface->dev, "PL-2303 hack: descriptors matched but endpoints did not\n"); + dev_info(ddev, "PL-2303 hack: descriptors matched but endpoints did not\n"); usb_serial_put(serial); module_put(type->driver.owner); return -ENODEV; @@ -836,14 +846,13 @@ static int usb_serial_probe(struct usb_interface *interface, if (type == &usb_serial_generic_device) { num_ports = num_bulk_out; if (num_ports == 0) { - dev_err(&interface->dev, - "Generic device with no bulk out, not allowed.\n"); + dev_err(ddev, "Generic device with no bulk out, not allowed.\n"); usb_serial_put(serial); module_put(type->driver.owner); return -EIO; } - dev_info(&interface->dev, "The \"generic\" usb-serial driver is only for testing and one-off prototypes.\n"); - dev_info(&interface->dev, "Tell linux-usb@vger.kernel.org to add your device to a proper driver.\n"); + dev_info(ddev, "The \"generic\" usb-serial driver is only for testing and one-off prototypes.\n"); + dev_info(ddev, "Tell linux-usb@vger.kernel.org to add your device to a proper driver.\n"); } #endif if (!num_ports) { @@ -861,8 +870,7 @@ static int usb_serial_probe(struct usb_interface *interface, serial->num_interrupt_out = num_interrupt_out; /* found all that we need */ - dev_info(&interface->dev, "%s converter detected\n", - type->description); + dev_info(ddev, "%s converter detected\n", type->description); /* create our ports, we need as many as the max endpoints */ /* we don't use num_ports here because some devices have more @@ -873,8 +881,7 @@ static int usb_serial_probe(struct usb_interface *interface, max_endpoints = max(max_endpoints, (int)serial->num_ports); serial->num_port_pointers = max_endpoints; - dbg("%s - setting up %d port structures for this device", - __func__, max_endpoints); + dev_dbg(ddev, "setting up %d port structures for this device", max_endpoints); for (i = 0; i < max_endpoints; ++i) { port = kzalloc(sizeof(struct usb_serial_port), GFP_KERNEL); if (!port) @@ -907,15 +914,13 @@ static int usb_serial_probe(struct usb_interface *interface, set_bit(j, &port->read_urbs_free); port->read_urbs[j] = usb_alloc_urb(0, GFP_KERNEL); if (!port->read_urbs[j]) { - dev_err(&interface->dev, - "No free urbs available\n"); + dev_err(ddev, "No free urbs available\n"); goto probe_error; } port->bulk_in_buffers[j] = kmalloc(buffer_size, GFP_KERNEL); if (!port->bulk_in_buffers[j]) { - dev_err(&interface->dev, - "Couldn't allocate bulk_in_buffer\n"); + dev_err(ddev, "Couldn't allocate bulk_in_buffer\n"); goto probe_error; } usb_fill_bulk_urb(port->read_urbs[j], dev, @@ -945,15 +950,13 @@ static int usb_serial_probe(struct usb_interface *interface, set_bit(j, &port->write_urbs_free); port->write_urbs[j] = usb_alloc_urb(0, GFP_KERNEL); if (!port->write_urbs[j]) { - dev_err(&interface->dev, - "No free urbs available\n"); + dev_err(ddev, "No free urbs available\n"); goto probe_error; } port->bulk_out_buffers[j] = kmalloc(buffer_size, GFP_KERNEL); if (!port->bulk_out_buffers[j]) { - dev_err(&interface->dev, - "Couldn't allocate bulk_out_buffer\n"); + dev_err(ddev, "Couldn't allocate bulk_out_buffer\n"); goto probe_error; } usb_fill_bulk_urb(port->write_urbs[j], dev, @@ -974,8 +977,7 @@ static int usb_serial_probe(struct usb_interface *interface, port = serial->port[i]; port->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL); if (!port->interrupt_in_urb) { - dev_err(&interface->dev, - "No free urbs available\n"); + dev_err(ddev, "No free urbs available\n"); goto probe_error; } buffer_size = usb_endpoint_maxp(endpoint); @@ -984,8 +986,7 @@ static int usb_serial_probe(struct usb_interface *interface, port->interrupt_in_buffer = kmalloc(buffer_size, GFP_KERNEL); if (!port->interrupt_in_buffer) { - dev_err(&interface->dev, - "Couldn't allocate interrupt_in_buffer\n"); + dev_err(ddev, "Couldn't allocate interrupt_in_buffer\n"); goto probe_error; } usb_fill_int_urb(port->interrupt_in_urb, dev, @@ -996,7 +997,7 @@ static int usb_serial_probe(struct usb_interface *interface, endpoint->bInterval); } } else if (num_interrupt_in) { - dbg("the device claims to support interrupt in transfers, but read_int_callback is not defined"); + dev_dbg(ddev, "The device claims to support interrupt in transfers, but read_int_callback is not defined\n"); } if (serial->type->write_int_callback) { @@ -1005,8 +1006,7 @@ static int usb_serial_probe(struct usb_interface *interface, port = serial->port[i]; port->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL); if (!port->interrupt_out_urb) { - dev_err(&interface->dev, - "No free urbs available\n"); + dev_err(ddev, "No free urbs available\n"); goto probe_error; } buffer_size = usb_endpoint_maxp(endpoint); @@ -1016,8 +1016,7 @@ static int usb_serial_probe(struct usb_interface *interface, port->interrupt_out_buffer = kmalloc(buffer_size, GFP_KERNEL); if (!port->interrupt_out_buffer) { - dev_err(&interface->dev, - "Couldn't allocate interrupt_out_buffer\n"); + dev_err(ddev, "Couldn't allocate interrupt_out_buffer\n"); goto probe_error; } usb_fill_int_urb(port->interrupt_out_urb, dev, @@ -1028,7 +1027,7 @@ static int usb_serial_probe(struct usb_interface *interface, endpoint->bInterval); } } else if (num_interrupt_out) { - dbg("the device claims to support interrupt out transfers, but write_int_callback is not defined"); + dev_dbg(ddev, "The device claims to support interrupt out transfers, but write_int_callback is not defined\n"); } usb_set_intfdata(interface, serial); @@ -1056,7 +1055,7 @@ static int usb_serial_probe(struct usb_interface *interface, serial->disconnected = 1; if (get_free_serial(serial, num_ports, &minor) == NULL) { - dev_err(&interface->dev, "No more free serial devices\n"); + dev_err(ddev, "No more free serial devices\n"); goto probe_error; } serial->minor = minor; @@ -1065,13 +1064,12 @@ static int usb_serial_probe(struct usb_interface *interface, for (i = 0; i < num_ports; ++i) { port = serial->port[i]; dev_set_name(&port->dev, "ttyUSB%d", port->number); - dbg ("%s - registering %s", __func__, dev_name(&port->dev)); + dev_dbg(ddev, "registering %s", dev_name(&port->dev)); device_enable_async_suspend(&port->dev); retval = device_add(&port->dev); if (retval) - dev_err(&port->dev, "Error registering port device, " - "continuing\n"); + dev_err(ddev, "Error registering port device, continuing\n"); } serial->disconnected = 0; @@ -1229,8 +1227,7 @@ static int __init usb_serial_init(void) result = bus_register(&usb_serial_bus_type); if (result) { - printk(KERN_ERR "usb-serial: %s - registering bus driver " - "failed\n", __func__); + pr_err("%s - registering bus driver failed\n", __func__); goto exit_bus; } @@ -1250,24 +1247,21 @@ static int __init usb_serial_init(void) tty_set_operations(usb_serial_tty_driver, &serial_ops); result = tty_register_driver(usb_serial_tty_driver); if (result) { - printk(KERN_ERR "usb-serial: %s - tty_register_driver failed\n", - __func__); + pr_err("%s - tty_register_driver failed\n", __func__); goto exit_reg_driver; } /* register the USB driver */ result = usb_register(&usb_serial_driver); if (result < 0) { - printk(KERN_ERR "usb-serial: %s - usb_register failed\n", - __func__); + pr_err("%s - usb_register failed\n", __func__); goto exit_tty; } /* register the generic driver, if we should */ result = usb_serial_generic_register(debug); if (result < 0) { - printk(KERN_ERR "usb-serial: %s - registering generic " - "driver failed\n", __func__); + pr_err("%s - registering generic driver failed\n", __func__); goto exit_generic; } @@ -1285,8 +1279,7 @@ exit_reg_driver: bus_unregister(&usb_serial_bus_type); exit_bus: - printk(KERN_ERR "usb-serial: %s - returning with error %d\n", - __func__, result); + pr_err("%s - returning with error %d\n", __func__, result); put_tty_driver(usb_serial_tty_driver); return result; } @@ -1312,7 +1305,7 @@ module_exit(usb_serial_exit); do { \ if (!type->function) { \ type->function = usb_serial_generic_##function; \ - dbg("Had to override the " #function \ + pr_debug("Had to override the " #function \ " usb serial operation with the generic one.");\ } \ } while (0) @@ -1355,8 +1348,7 @@ static int usb_serial_register(struct usb_serial_driver *driver) retval = usb_serial_bus_register(driver); if (retval) { - printk(KERN_ERR "usb-serial: problem %d when registering " - "driver %s\n", retval, driver->description); + pr_err("problem %d when registering driver %s\n", retval, driver->description); list_del(&driver->driver_list); } else printk(KERN_INFO "USB Serial support registered for %s\n", -- cgit v0.10.2 From 79cbeeaf26b3f8c3e3043e05a8e14ca7e7a49b89 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 13 Sep 2012 17:18:10 -0700 Subject: USB: serial: ch341.c: remove dbg() usage dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. CC: Johan Hovold CC: Alan Stern CC: Rusty Russell CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index cabd1b1..9aae210 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -93,8 +93,9 @@ static int ch341_control_out(struct usb_device *dev, u8 request, u16 value, u16 index) { int r; - dbg("ch341_control_out(%02x,%02x,%04x,%04x)", USB_DIR_OUT|0x40, - (int)request, (int)value, (int)index); + + dev_dbg(&dev->dev, "ch341_control_out(%02x,%02x,%04x,%04x)\n", + USB_DIR_OUT|0x40, (int)request, (int)value, (int)index); r = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, @@ -108,8 +109,10 @@ static int ch341_control_in(struct usb_device *dev, char *buf, unsigned bufsize) { int r; - dbg("ch341_control_in(%02x,%02x,%04x,%04x,%p,%u)", USB_DIR_IN|0x40, - (int)request, (int)value, (int)index, buf, (int)bufsize); + + dev_dbg(&dev->dev, "ch341_control_in(%02x,%02x,%04x,%04x,%p,%u)\n", + USB_DIR_IN|0x40, (int)request, (int)value, (int)index, buf, + (int)bufsize); r = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), request, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, @@ -320,7 +323,7 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port) if (r) goto out; - dbg("%s - submitting interrupt urb", __func__); + dev_dbg(&port->dev, "%s - submitting interrupt urb", __func__); r = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (r) { dev_err(&port->dev, "%s - failed submitting interrupt urb," @@ -390,19 +393,19 @@ static void ch341_break_ctl(struct tty_struct *tty, int break_state) __func__, r); goto out; } - dbg("%s - initial ch341 break register contents - reg1: %x, reg2: %x", - __func__, break_reg[0], break_reg[1]); + dev_dbg(&port->dev, "%s - initial ch341 break register contents - reg1: %x, reg2: %x\n", + __func__, break_reg[0], break_reg[1]); if (break_state != 0) { - dbg("%s - Enter break state requested", __func__); + dev_dbg(&port->dev, "%s - Enter break state requested\n", __func__); break_reg[0] &= ~CH341_NBREAK_BITS_REG1; break_reg[1] &= ~CH341_NBREAK_BITS_REG2; } else { - dbg("%s - Leave break state requested", __func__); + dev_dbg(&port->dev, "%s - Leave break state requested\n", __func__); break_reg[0] |= CH341_NBREAK_BITS_REG1; break_reg[1] |= CH341_NBREAK_BITS_REG2; } - dbg("%s - New ch341 break register contents - reg1: %x, reg2: %x", - __func__, break_reg[0], break_reg[1]); + dev_dbg(&port->dev, "%s - New ch341 break register contents - reg1: %x, reg2: %x\n", + __func__, break_reg[0], break_reg[1]); reg_contents = get_unaligned_le16(break_reg); r = ch341_control_out(port->serial->dev, CH341_REQ_WRITE_REG, ch341_break_reg, reg_contents); @@ -451,12 +454,12 @@ static void ch341_read_int_callback(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __func__, - urb->status); + dev_dbg(&urb->dev->dev, "%s - urb shutting down with status: %d\n", + __func__, urb->status); return; default: - dbg("%s - nonzero urb status received: %d", __func__, - urb->status); + dev_dbg(&urb->dev->dev, "%s - nonzero urb status received: %d\n", + __func__, urb->status); goto exit; } @@ -536,15 +539,16 @@ static int ch341_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { struct usb_serial_port *port = tty->driver_data; - dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd); + + dev_dbg(&port->dev, "%s (%d) cmd = 0x%04x\n", __func__, port->number, cmd); switch (cmd) { case TIOCMIWAIT: - dbg("%s (%d) TIOCMIWAIT", __func__, port->number); + dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__, port->number); return wait_modem_info(port, arg); default: - dbg("%s not supported = 0x%04x", __func__, cmd); + dev_dbg(&port->dev, "%s not supported = 0x%04x\n", __func__, cmd); break; } @@ -572,7 +576,7 @@ static int ch341_tiocmget(struct tty_struct *tty) | ((status & CH341_BIT_RI) ? TIOCM_RI : 0) | ((status & CH341_BIT_DCD) ? TIOCM_CD : 0); - dbg("%s - result = %x", __func__, result); + dev_dbg(&port->dev, "%s - result = %x\n", __func__, result); return result; } -- cgit v0.10.2 From 660f3b1410d327e8cd29adb5b834caa66ebbd7d4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 13 Sep 2012 17:18:13 -0700 Subject: USB: serial: cp210x.c: remove dbg() usage dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. CC: Johan Hovold CC: Preston Fick Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 3f86cf3..9cf6985 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -304,9 +304,8 @@ static int cp210x_get_config(struct usb_serial_port *port, u8 request, kfree(buf); if (result != size) { - dbg("%s - Unable to send config request, " - "request=0x%x size=%d result=%d", - __func__, request, size, result); + dev_dbg(&port->dev, "%s - Unable to send config request, request=0x%x size=%d result=%d\n", + __func__, request, size, result); if (result > 0) result = -EPROTO; @@ -361,9 +360,8 @@ static int cp210x_set_config(struct usb_serial_port *port, u8 request, kfree(buf); if ((size > 2 && result != size) || result < 0) { - dbg("%s - Unable to send request, " - "request=0x%x size=%d result=%d", - __func__, request, size, result); + dev_dbg(&port->dev, "%s - Unable to send request, request=0x%x size=%d result=%d\n", + __func__, request, size, result); if (result > 0) result = -EPROTO; @@ -487,13 +485,14 @@ static void cp210x_get_termios(struct tty_struct *tty, static void cp210x_get_termios_port(struct usb_serial_port *port, unsigned int *cflagp, unsigned int *baudp) { + struct device *dev = &port->dev; unsigned int cflag, modem_ctl[4]; unsigned int baud; unsigned int bits; cp210x_get_config(port, CP210X_GET_BAUDRATE, &baud, 4); - dbg("%s - baud rate = %d", __func__, baud); + dev_dbg(dev, "%s - baud rate = %d\n", __func__, baud); *baudp = baud; cflag = *cflagp; @@ -502,31 +501,30 @@ static void cp210x_get_termios_port(struct usb_serial_port *port, cflag &= ~CSIZE; switch (bits & BITS_DATA_MASK) { case BITS_DATA_5: - dbg("%s - data bits = 5", __func__); + dev_dbg(dev, "%s - data bits = 5\n", __func__); cflag |= CS5; break; case BITS_DATA_6: - dbg("%s - data bits = 6", __func__); + dev_dbg(dev, "%s - data bits = 6\n", __func__); cflag |= CS6; break; case BITS_DATA_7: - dbg("%s - data bits = 7", __func__); + dev_dbg(dev, "%s - data bits = 7\n", __func__); cflag |= CS7; break; case BITS_DATA_8: - dbg("%s - data bits = 8", __func__); + dev_dbg(dev, "%s - data bits = 8\n", __func__); cflag |= CS8; break; case BITS_DATA_9: - dbg("%s - data bits = 9 (not supported, using 8 data bits)", - __func__); + dev_dbg(dev, "%s - data bits = 9 (not supported, using 8 data bits)\n", __func__); cflag |= CS8; bits &= ~BITS_DATA_MASK; bits |= BITS_DATA_8; cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2); break; default: - dbg("%s - Unknown number of data bits, using 8", __func__); + dev_dbg(dev, "%s - Unknown number of data bits, using 8\n", __func__); cflag |= CS8; bits &= ~BITS_DATA_MASK; bits |= BITS_DATA_8; @@ -536,29 +534,29 @@ static void cp210x_get_termios_port(struct usb_serial_port *port, switch (bits & BITS_PARITY_MASK) { case BITS_PARITY_NONE: - dbg("%s - parity = NONE", __func__); + dev_dbg(dev, "%s - parity = NONE\n", __func__); cflag &= ~PARENB; break; case BITS_PARITY_ODD: - dbg("%s - parity = ODD", __func__); + dev_dbg(dev, "%s - parity = ODD\n", __func__); cflag |= (PARENB|PARODD); break; case BITS_PARITY_EVEN: - dbg("%s - parity = EVEN", __func__); + dev_dbg(dev, "%s - parity = EVEN\n", __func__); cflag &= ~PARODD; cflag |= PARENB; break; case BITS_PARITY_MARK: - dbg("%s - parity = MARK", __func__); + dev_dbg(dev, "%s - parity = MARK\n", __func__); cflag |= (PARENB|PARODD|CMSPAR); break; case BITS_PARITY_SPACE: - dbg("%s - parity = SPACE", __func__); + dev_dbg(dev, "%s - parity = SPACE\n", __func__); cflag &= ~PARODD; cflag |= (PARENB|CMSPAR); break; default: - dbg("%s - Unknown parity mode, disabling parity", __func__); + dev_dbg(dev, "%s - Unknown parity mode, disabling parity\n", __func__); cflag &= ~PARENB; bits &= ~BITS_PARITY_MASK; cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2); @@ -568,21 +566,19 @@ static void cp210x_get_termios_port(struct usb_serial_port *port, cflag &= ~CSTOPB; switch (bits & BITS_STOP_MASK) { case BITS_STOP_1: - dbg("%s - stop bits = 1", __func__); + dev_dbg(dev, "%s - stop bits = 1\n", __func__); break; case BITS_STOP_1_5: - dbg("%s - stop bits = 1.5 (not supported, using 1 stop bit)", - __func__); + dev_dbg(dev, "%s - stop bits = 1.5 (not supported, using 1 stop bit)\n", __func__); bits &= ~BITS_STOP_MASK; cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2); break; case BITS_STOP_2: - dbg("%s - stop bits = 2", __func__); + dev_dbg(dev, "%s - stop bits = 2\n", __func__); cflag |= CSTOPB; break; default: - dbg("%s - Unknown number of stop bits, using 1 stop bit", - __func__); + dev_dbg(dev, "%s - Unknown number of stop bits, using 1 stop bit\n", __func__); bits &= ~BITS_STOP_MASK; cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2); break; @@ -590,10 +586,10 @@ static void cp210x_get_termios_port(struct usb_serial_port *port, cp210x_get_config(port, CP210X_GET_FLOW, modem_ctl, 16); if (modem_ctl[0] & 0x0008) { - dbg("%s - flow control = CRTSCTS", __func__); + dev_dbg(dev, "%s - flow control = CRTSCTS\n", __func__); cflag |= CRTSCTS; } else { - dbg("%s - flow control = NONE", __func__); + dev_dbg(dev, "%s - flow control = NONE\n", __func__); cflag &= ~CRTSCTS; } @@ -640,7 +636,7 @@ static void cp210x_change_speed(struct tty_struct *tty, */ baud = cp210x_quantise_baudrate(baud); - dbg("%s - setting baud rate to %u", __func__, baud); + dev_dbg(&port->dev, "%s - setting baud rate to %u\n", __func__, baud); if (cp210x_set_config(port, CP210X_SET_BAUDRATE, &baud, sizeof(baud))) { dev_warn(&port->dev, "failed to set baud rate to %u\n", baud); @@ -656,11 +652,12 @@ static void cp210x_change_speed(struct tty_struct *tty, static void cp210x_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { + struct device *dev = &port->dev; unsigned int cflag, old_cflag; unsigned int bits; unsigned int modem_ctl[4]; - dbg("%s - port %d", __func__, port->number); + dev_dbg(dev, "%s - port %d\n", __func__, port->number); if (!tty) return; @@ -678,34 +675,31 @@ static void cp210x_set_termios(struct tty_struct *tty, switch (cflag & CSIZE) { case CS5: bits |= BITS_DATA_5; - dbg("%s - data bits = 5", __func__); + dev_dbg(dev, "%s - data bits = 5\n", __func__); break; case CS6: bits |= BITS_DATA_6; - dbg("%s - data bits = 6", __func__); + dev_dbg(dev, "%s - data bits = 6\n", __func__); break; case CS7: bits |= BITS_DATA_7; - dbg("%s - data bits = 7", __func__); + dev_dbg(dev, "%s - data bits = 7\n", __func__); break; case CS8: bits |= BITS_DATA_8; - dbg("%s - data bits = 8", __func__); + dev_dbg(dev, "%s - data bits = 8\n", __func__); break; /*case CS9: bits |= BITS_DATA_9; - dbg("%s - data bits = 9", __func__); + dev_dbg(dev, "%s - data bits = 9\n", __func__); break;*/ default: - dbg("cp210x driver does not " - "support the number of bits requested," - " using 8 bit mode"); + dev_dbg(dev, "cp210x driver does not support the number of bits requested, using 8 bit mode\n"); bits |= BITS_DATA_8; break; } if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2)) - dbg("Number of data bits requested " - "not supported by device"); + dev_dbg(dev, "Number of data bits requested not supported by device\n"); } if ((cflag & (PARENB|PARODD|CMSPAR)) != @@ -714,25 +708,25 @@ static void cp210x_set_termios(struct tty_struct *tty, bits &= ~BITS_PARITY_MASK; if (cflag & PARENB) { if (cflag & CMSPAR) { - if (cflag & PARODD) { - bits |= BITS_PARITY_MARK; - dbg("%s - parity = MARK", __func__); - } else { - bits |= BITS_PARITY_SPACE; - dbg("%s - parity = SPACE", __func__); - } + if (cflag & PARODD) { + bits |= BITS_PARITY_MARK; + dev_dbg(dev, "%s - parity = MARK\n", __func__); + } else { + bits |= BITS_PARITY_SPACE; + dev_dbg(dev, "%s - parity = SPACE\n", __func__); + } } else { - if (cflag & PARODD) { - bits |= BITS_PARITY_ODD; - dbg("%s - parity = ODD", __func__); - } else { - bits |= BITS_PARITY_EVEN; - dbg("%s - parity = EVEN", __func__); - } + if (cflag & PARODD) { + bits |= BITS_PARITY_ODD; + dev_dbg(dev, "%s - parity = ODD\n", __func__); + } else { + bits |= BITS_PARITY_EVEN; + dev_dbg(dev, "%s - parity = EVEN\n", __func__); + } } } if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2)) - dbg("Parity mode not supported by device"); + dev_dbg(dev, "Parity mode not supported by device\n"); } if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) { @@ -740,37 +734,36 @@ static void cp210x_set_termios(struct tty_struct *tty, bits &= ~BITS_STOP_MASK; if (cflag & CSTOPB) { bits |= BITS_STOP_2; - dbg("%s - stop bits = 2", __func__); + dev_dbg(dev, "%s - stop bits = 2\n", __func__); } else { bits |= BITS_STOP_1; - dbg("%s - stop bits = 1", __func__); + dev_dbg(dev, "%s - stop bits = 1\n", __func__); } if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2)) - dbg("Number of stop bits requested " - "not supported by device"); + dev_dbg(dev, "Number of stop bits requested not supported by device\n"); } if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) { cp210x_get_config(port, CP210X_GET_FLOW, modem_ctl, 16); - dbg("%s - read modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x", - __func__, modem_ctl[0], modem_ctl[1], - modem_ctl[2], modem_ctl[3]); + dev_dbg(dev, "%s - read modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x\n", + __func__, 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", __func__); + dev_dbg(dev, "%s - flow control = CRTSCTS\n", __func__); } else { modem_ctl[0] &= ~0x7B; modem_ctl[0] |= 0x01; modem_ctl[1] |= 0x40; - dbg("%s - flow control = NONE", __func__); + dev_dbg(dev, "%s - flow control = NONE\n", __func__); } - dbg("%s - write modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x", - __func__, modem_ctl[0], modem_ctl[1], - modem_ctl[2], modem_ctl[3]); + dev_dbg(dev, "%s - write modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x\n", + __func__, modem_ctl[0], modem_ctl[1], + modem_ctl[2], modem_ctl[3]); cp210x_set_config(port, CP210X_SET_FLOW, modem_ctl, 16); } @@ -805,7 +798,7 @@ static int cp210x_tiocmset_port(struct usb_serial_port *port, control |= CONTROL_WRITE_DTR; } - dbg("%s - control = 0x%.4x", __func__, control); + dev_dbg(&port->dev, "%s - control = 0x%.4x\n", __func__, control); return cp210x_set_config(port, CP210X_SET_MHS, &control, 2); } @@ -833,7 +826,7 @@ static int cp210x_tiocmget (struct tty_struct *tty) |((control & CONTROL_RING)? TIOCM_RI : 0) |((control & CONTROL_DCD) ? TIOCM_CD : 0); - dbg("%s - control = 0x%.2x", __func__, control); + dev_dbg(&port->dev, "%s - control = 0x%.2x\n", __func__, control); return result; } @@ -847,8 +840,8 @@ static void cp210x_break_ctl (struct tty_struct *tty, int break_state) state = BREAK_OFF; else state = BREAK_ON; - dbg("%s - turning break %s", __func__, - state == BREAK_OFF ? "off" : "on"); + dev_dbg(&port->dev, "%s - turning break %s\n", __func__, + state == BREAK_OFF ? "off" : "on"); cp210x_set_config(port, CP210X_SET_BREAK, &state, 2); } -- cgit v0.10.2 From 96fc8e8d8551f4d67b54982175b412c4e1b8d395 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 13 Sep 2012 17:18:14 -0700 Subject: USB: serial: cyberjack.c: remove dbg() usage dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. CC: Matthias Bruestle and Harald Welte Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 3aa0b53..9c90575 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -136,7 +136,8 @@ static int cyberjack_startup(struct usb_serial *serial) if (result) dev_err(&serial->dev->dev, "usb_submit_urb(read int) failed\n"); - dbg("%s - usb_submit_urb(int urb)", __func__); + dev_dbg(&serial->dev->dev, "%s - usb_submit_urb(int urb)\n", + __func__); } return 0; @@ -167,7 +168,7 @@ static int cyberjack_open(struct tty_struct *tty, unsigned long flags; int result = 0; - dbg("%s - usb_clear_halt", __func__); + dev_dbg(&port->dev, "%s - usb_clear_halt\n", __func__); usb_clear_halt(port->serial->dev, port->write_urb->pipe); priv = usb_get_serial_port_data(port); @@ -192,18 +193,19 @@ static void cyberjack_close(struct usb_serial_port *port) static int cyberjack_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count) { + struct device *dev = &port->dev; struct cyberjack_private *priv = usb_get_serial_port_data(port); unsigned long flags; int result; int wrexpected; if (count == 0) { - dbg("%s - write request of 0 bytes", __func__); + dev_dbg(dev, "%s - write request of 0 bytes\n", __func__); return 0; } if (!test_and_clear_bit(0, &port->write_urbs_free)) { - dbg("%s - already writing", __func__); + dev_dbg(dev, "%s - already writing\n", __func__); return 0; } @@ -220,13 +222,13 @@ static int cyberjack_write(struct tty_struct *tty, /* Copy data */ memcpy(priv->wrbuf + priv->wrfilled, buf, count); - usb_serial_debug_data(debug, &port->dev, __func__, count, + usb_serial_debug_data(debug, dev, __func__, count, priv->wrbuf + priv->wrfilled); priv->wrfilled += count; if (priv->wrfilled >= 3) { wrexpected = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3; - dbg("%s - expected data: %d", __func__, wrexpected); + dev_dbg(dev, "%s - expected data: %d\n", __func__, wrexpected); } else wrexpected = sizeof(priv->wrbuf); @@ -234,7 +236,7 @@ static int cyberjack_write(struct tty_struct *tty, /* We have enough data to begin transmission */ int length; - dbg("%s - transmitting data (frame 1)", __func__); + dev_dbg(dev, "%s - transmitting data (frame 1)\n", __func__); length = (wrexpected > port->bulk_out_size) ? port->bulk_out_size : wrexpected; @@ -258,11 +260,11 @@ static int cyberjack_write(struct tty_struct *tty, return 0; } - dbg("%s - priv->wrsent=%d", __func__, priv->wrsent); - dbg("%s - priv->wrfilled=%d", __func__, priv->wrfilled); + dev_dbg(dev, "%s - priv->wrsent=%d\n", __func__, priv->wrsent); + dev_dbg(dev, "%s - priv->wrfilled=%d\n", __func__, priv->wrfilled); if (priv->wrsent >= priv->wrfilled) { - dbg("%s - buffer cleaned", __func__); + dev_dbg(dev, "%s - buffer cleaned\n", __func__); memset(priv->wrbuf, 0, sizeof(priv->wrbuf)); priv->wrfilled = 0; priv->wrsent = 0; @@ -284,6 +286,7 @@ static void cyberjack_read_int_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct cyberjack_private *priv = usb_get_serial_port_data(port); + struct device *dev = &port->dev; unsigned char *data = urb->transfer_buffer; int status = urb->status; int result; @@ -292,8 +295,7 @@ static void cyberjack_read_int_callback(struct urb *urb) if (status) return; - usb_serial_debug_data(debug, &port->dev, __func__, - urb->actual_length, data); + usb_serial_debug_data(debug, dev, __func__, urb->actual_length, data); /* React only to interrupts signaling a bulk_in transfer */ if (urb->actual_length == 4 && data[0] == 0x01) { @@ -307,7 +309,7 @@ static void cyberjack_read_int_callback(struct urb *urb) old_rdtodo = priv->rdtodo; if (old_rdtodo + size < old_rdtodo) { - dbg("To many bulk_in urbs to do."); + dev_dbg(dev, "To many bulk_in urbs to do.\n"); spin_unlock(&priv->lock); goto resubmit; } @@ -315,17 +317,16 @@ static void cyberjack_read_int_callback(struct urb *urb) /* "+=" is probably more fault tollerant than "=" */ priv->rdtodo += size; - dbg("%s - rdtodo: %d", __func__, priv->rdtodo); + dev_dbg(dev, "%s - rdtodo: %d\n", __func__, priv->rdtodo); spin_unlock(&priv->lock); if (!old_rdtodo) { result = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (result) - dev_err(&port->dev, "%s - failed resubmitting " - "read urb, error %d\n", + dev_err(dev, "%s - failed resubmitting read urb, error %d\n", __func__, result); - dbg("%s - usb_submit_urb(read urb)", __func__); + dev_dbg(dev, "%s - usb_submit_urb(read urb)\n", __func__); } } @@ -333,13 +334,14 @@ resubmit: result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); if (result) dev_err(&port->dev, "usb_submit_urb(read int) failed\n"); - dbg("%s - usb_submit_urb(int urb)", __func__); + dev_dbg(dev, "%s - usb_submit_urb(int urb)\n", __func__); } static void cyberjack_read_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct cyberjack_private *priv = usb_get_serial_port_data(port); + struct device *dev = &port->dev; struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; short todo; @@ -349,14 +351,14 @@ static void cyberjack_read_bulk_callback(struct urb *urb) usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); if (status) { - dbg("%s - nonzero read bulk status received: %d", - __func__, status); + dev_dbg(dev, "%s - nonzero read bulk status received: %d\n", + __func__, status); return; } tty = tty_port_tty_get(&port->port); if (!tty) { - dbg("%s - ignoring since device not open", __func__); + dev_dbg(dev, "%s - ignoring since device not open\n", __func__); return; } if (urb->actual_length) { @@ -376,15 +378,15 @@ static void cyberjack_read_bulk_callback(struct urb *urb) spin_unlock(&priv->lock); - dbg("%s - rdtodo: %d", __func__, todo); + dev_dbg(dev, "%s - rdtodo: %d\n", __func__, todo); /* Continue to read if we have still urbs to do. */ if (todo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/) { result = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (result) - dev_err(&port->dev, "%s - failed resubmitting read " - "urb, error %d\n", __func__, result); - dbg("%s - usb_submit_urb(read urb)", __func__); + dev_err(dev, "%s - failed resubmitting read urb, error %d\n", + __func__, result); + dev_dbg(dev, "%s - usb_submit_urb(read urb)\n", __func__); } } @@ -392,12 +394,13 @@ static void cyberjack_write_bulk_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct cyberjack_private *priv = usb_get_serial_port_data(port); + struct device *dev = &port->dev; int status = urb->status; set_bit(0, &port->write_urbs_free); if (status) { - dbg("%s - nonzero write bulk status received: %d", - __func__, status); + dev_dbg(dev, "%s - nonzero write bulk status received: %d\n", + __func__, status); return; } @@ -407,7 +410,7 @@ static void cyberjack_write_bulk_callback(struct urb *urb) if (priv->wrfilled) { int length, blksize, result; - dbg("%s - transmitting data (frame n)", __func__); + dev_dbg(dev, "%s - transmitting data (frame n)\n", __func__); length = ((priv->wrfilled - priv->wrsent) > port->bulk_out_size) ? port->bulk_out_size : (priv->wrfilled - priv->wrsent); @@ -422,8 +425,7 @@ static void cyberjack_write_bulk_callback(struct urb *urb) /* send the data out the bulk port */ result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) { - dev_err(&port->dev, - "%s - failed submitting write urb, error %d\n", + dev_err(dev, "%s - failed submitting write urb, error %d\n", __func__, result); /* Throw away data. No better idea what to do with it. */ priv->wrfilled = 0; @@ -431,14 +433,14 @@ static void cyberjack_write_bulk_callback(struct urb *urb) goto exit; } - dbg("%s - priv->wrsent=%d", __func__, priv->wrsent); - dbg("%s - priv->wrfilled=%d", __func__, priv->wrfilled); + dev_dbg(dev, "%s - priv->wrsent=%d\n", __func__, priv->wrsent); + dev_dbg(dev, "%s - priv->wrfilled=%d\n", __func__, priv->wrfilled); blksize = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3; if (priv->wrsent >= priv->wrfilled || priv->wrsent >= blksize) { - dbg("%s - buffer cleaned", __func__); + dev_dbg(dev, "%s - buffer cleaned\n", __func__); memset(priv->wrbuf, 0, sizeof(priv->wrbuf)); priv->wrfilled = 0; priv->wrsent = 0; -- cgit v0.10.2 From 592ba39fab1072d6d37f4118f4b0efa15377ced5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 13 Sep 2012 17:18:16 -0700 Subject: USB: serial: ipw.c: remove dbg() usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab CC: "Bjørn Mork" Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index 2cb30c5..fbd54a1 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -142,7 +142,8 @@ static bool debug; static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port) { - struct usb_device *dev = port->serial->dev; + struct usb_device *udev = port->serial->dev; + struct device *dev = &port->dev; u8 buf_flow_static[16] = IPW_BYTES_FLOWINIT; u8 *buf_flow_init; int result; @@ -154,8 +155,8 @@ static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port) /* --1: Tell the modem to initialize (we think) From sniffs this is * always the first thing that gets sent to the modem during * opening of the device */ - dbg("%s: Sending SIO_INIT (we guess)", __func__); - result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + dev_dbg(dev, "%s: Sending SIO_INIT (we guess)\n", __func__); + result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), IPW_SIO_INIT, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, 0, @@ -164,22 +165,19 @@ static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port) 0, 100000); if (result < 0) - dev_err(&port->dev, - "Init of modem failed (error = %d)\n", result); + dev_err(dev, "Init of modem failed (error = %d)\n", result); /* reset the bulk pipes */ - usb_clear_halt(dev, - usb_rcvbulkpipe(dev, port->bulk_in_endpointAddress)); - usb_clear_halt(dev, - usb_sndbulkpipe(dev, port->bulk_out_endpointAddress)); + usb_clear_halt(udev, usb_rcvbulkpipe(udev, port->bulk_in_endpointAddress)); + usb_clear_halt(udev, usb_sndbulkpipe(udev, port->bulk_out_endpointAddress)); /*--2: Start reading from the device */ - dbg("%s: setting up bulk read callback", __func__); + dev_dbg(dev, "%s: setting up bulk read callback\n", __func__); usb_wwan_open(tty, port); /*--3: Tell the modem to open the floodgates on the rx bulk channel */ - dbg("%s:asking modem for RxRead (RXBULK_ON)", __func__); - result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + dev_dbg(dev, "%s:asking modem for RxRead (RXBULK_ON)\n", __func__); + result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), IPW_SIO_RXCTL, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, IPW_RXBULK_ON, @@ -188,12 +186,11 @@ static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port) 0, 100000); if (result < 0) - dev_err(&port->dev, - "Enabling bulk RxRead failed (error = %d)\n", result); + dev_err(dev, "Enabling bulk RxRead failed (error = %d)\n", result); /*--4: setup the initial flowcontrol */ - dbg("%s:setting init flowcontrol (%s)", __func__, buf_flow_init); - result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + dev_dbg(dev, "%s:setting init flowcontrol (%s)\n", __func__, buf_flow_init); + result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), IPW_SIO_HANDFLOW, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, 0, @@ -202,8 +199,7 @@ static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port) 0x10, 200000); if (result < 0) - dev_err(&port->dev, - "initial flowcontrol failed (error = %d)\n", result); + dev_err(dev, "initial flowcontrol failed (error = %d)\n", result); kfree(buf_flow_init); return 0; @@ -233,12 +229,13 @@ static void ipw_release(struct usb_serial *serial) static void ipw_dtr_rts(struct usb_serial_port *port, int on) { - struct usb_device *dev = port->serial->dev; + struct usb_device *udev = port->serial->dev; + struct device *dev = &port->dev; int result; - dbg("%s: on = %d", __func__, on); + dev_dbg(dev, "%s: on = %d\n", __func__, on); - result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), IPW_SIO_SET_PIN, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, on ? IPW_PIN_SETDTR : IPW_PIN_CLRDTR, @@ -247,10 +244,9 @@ static void ipw_dtr_rts(struct usb_serial_port *port, int on) 0, 200000); if (result < 0) - dev_err(&port->dev, "setting dtr failed (error = %d)\n", - result); + dev_err(dev, "setting dtr failed (error = %d)\n", result); - result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), IPW_SIO_SET_PIN, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, on ? IPW_PIN_SETRTS : IPW_PIN_CLRRTS, @@ -259,18 +255,18 @@ static void ipw_dtr_rts(struct usb_serial_port *port, int on) 0, 200000); if (result < 0) - dev_err(&port->dev, "setting rts failed (error = %d)\n", - result); + dev_err(dev, "setting rts failed (error = %d)\n", result); } static void ipw_close(struct usb_serial_port *port) { - struct usb_device *dev = port->serial->dev; + struct usb_device *udev = port->serial->dev; + struct device *dev = &port->dev; int result; /*--3: purge */ - dbg("%s:sending purge", __func__); - result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + dev_dbg(dev, "%s:sending purge\n", __func__); + result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), IPW_SIO_PURGE, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, 0x03, @@ -279,12 +275,12 @@ static void ipw_close(struct usb_serial_port *port) 0, 200000); if (result < 0) - dev_err(&port->dev, "purge failed (error = %d)\n", result); + dev_err(dev, "purge failed (error = %d)\n", result); /* send RXBULK_off (tell modem to stop transmitting bulk data on rx chan) */ - result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + result = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), IPW_SIO_RXCTL, USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, IPW_RXBULK_OFF, @@ -294,8 +290,7 @@ static void ipw_close(struct usb_serial_port *port) 100000); if (result < 0) - dev_err(&port->dev, - "Disabling bulk RxRead failed (error = %d)\n", result); + dev_err(dev, "Disabling bulk RxRead failed (error = %d)\n", result); usb_wwan_close(port); } -- cgit v0.10.2 From d44d9ab79212d56eea6b26f1e4925284861c347e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 13 Sep 2012 17:18:19 -0700 Subject: USB: serial: opticon.c: remove dbg() usage dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. CC: Johan Hovold CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 02cb1b7..6f05d64 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -78,12 +78,12 @@ static void opticon_read_bulk_callback(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", - __func__, status); + dev_dbg(&priv->udev->dev, "%s - urb shutting down with status: %d\n", + __func__, status); return; default: - dbg("%s - nonzero urb status received: %d", - __func__, status); + dev_dbg(&priv->udev->dev, "%s - nonzero urb status received: %d\n", + __func__, status); goto exit; } @@ -229,8 +229,8 @@ static void opticon_write_control_callback(struct urb *urb) kfree(urb->setup_packet); if (status) - dbg("%s - nonzero write bulk status received: %d", - __func__, status); + dev_dbg(&priv->udev->dev, "%s - nonzero write bulk status received: %d\n", + __func__, status); spin_lock_irqsave(&priv->lock, flags); --priv->outstanding_urbs; @@ -253,7 +253,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, spin_lock_irqsave(&priv->lock, flags); if (priv->outstanding_urbs > URB_UPPER_LIMIT) { spin_unlock_irqrestore(&priv->lock, flags); - dbg("%s - write limit hit", __func__); + dev_dbg(&port->dev, "%s - write limit hit\n", __func__); return 0; } priv->outstanding_urbs++; @@ -338,7 +338,7 @@ static int opticon_write_room(struct tty_struct *tty) spin_lock_irqsave(&priv->lock, flags); if (priv->outstanding_urbs > URB_UPPER_LIMIT * 2 / 3) { spin_unlock_irqrestore(&priv->lock, flags); - dbg("%s - write limit hit", __func__); + dev_dbg(&port->dev, "%s - write limit hit\n", __func__); return 0; } spin_unlock_irqrestore(&priv->lock, flags); @@ -394,7 +394,7 @@ static int opticon_tiocmget(struct tty_struct *tty) result |= TIOCM_CTS; spin_unlock_irqrestore(&priv->lock, flags); - dbg("%s - %x", __func__, result); + dev_dbg(&port->dev, "%s - %x\n", __func__, result); return result; } @@ -466,7 +466,7 @@ static int opticon_ioctl(struct tty_struct *tty, struct usb_serial_port *port = tty->driver_data; struct opticon_private *priv = usb_get_serial_data(port->serial); - dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); + dev_dbg(&port->dev, "%s - port %d, cmd = 0x%x\n", __func__, port->number, cmd); switch (cmd) { case TIOCGSERIAL: -- cgit v0.10.2 From 0e00609d857962ebecfba7deab834a52087b2454 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 13 Sep 2012 17:18:19 -0700 Subject: USB: serial: option.c: remove dbg() usage dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. CC: Matthias Urlichs Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index cc40f47..3891c0f 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1367,18 +1367,19 @@ static void option_instat_callback(struct urb *urb) { int err; int status = urb->status; - struct usb_serial_port *port = urb->context; + struct usb_serial_port *port = urb->context; + struct device *dev = &port->dev; struct usb_wwan_port_private *portdata = usb_get_serial_port_data(port); - dbg("%s: urb %p port %p has data %p", __func__, urb, port, portdata); + dev_dbg(dev, "%s: urb %p port %p has data %p\n", __func__, urb, port, portdata); if (status == 0) { struct usb_ctrlrequest *req_pkt = (struct usb_ctrlrequest *)urb->transfer_buffer; if (!req_pkt) { - dbg("%s: NULL req_pkt", __func__); + dev_dbg(dev, "%s: NULL req_pkt\n", __func__); return; } if ((req_pkt->bRequestType == 0xA1) && @@ -1388,7 +1389,7 @@ static void option_instat_callback(struct urb *urb) urb->transfer_buffer + sizeof(struct usb_ctrlrequest)); - dbg("%s: signal x%x", __func__, signals); + dev_dbg(dev, "%s: signal x%x\n", __func__, signals); old_dcd_state = portdata->dcd_state; portdata->cts_state = 1; @@ -1404,17 +1405,17 @@ static void option_instat_callback(struct urb *urb) tty_kref_put(tty); } } else { - dbg("%s: type %x req %x", __func__, + dev_dbg(dev, "%s: type %x req %x\n", __func__, req_pkt->bRequestType, req_pkt->bRequest); } } else - dev_err(&port->dev, "%s: error %d\n", __func__, status); + dev_err(dev, "%s: error %d\n", __func__, status); /* Resubmit urb so we continue receiving IRQ data */ if (status != -ESHUTDOWN && status != -ENOENT) { err = usb_submit_urb(urb, GFP_ATOMIC); if (err) - dbg("%s: resubmit intr urb failed. (%d)", + dev_dbg(dev, "%s: resubmit intr urb failed. (%d)\n", __func__, err); } } -- cgit v0.10.2 From 7b5ba275dfa8858e66aad8641874cf88c1ed0651 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 13 Sep 2012 17:41:48 -0700 Subject: USB: serial: omninet.c: remove dbg() usage dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. CC: Johan Hovold CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 6f3d705..d31f661 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -167,8 +167,8 @@ static void omninet_read_bulk_callback(struct urb *urb) int i; if (status) { - dbg("%s - nonzero read bulk status received: %d", - __func__, status); + dev_dbg(&port->dev, "%s - nonzero read bulk status received: %d\n", + __func__, status); return; } @@ -212,12 +212,12 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, int result; if (count == 0) { - dbg("%s - write request of 0 bytes", __func__); + dev_dbg(&port->dev, "%s - write request of 0 bytes\n", __func__); return 0; } if (!test_and_clear_bit(0, &port->write_urbs_free)) { - dbg("%s - already writing", __func__); + dev_dbg(&port->dev, "%s - already writing\n", __func__); return 0; } @@ -261,7 +261,7 @@ static int omninet_write_room(struct tty_struct *tty) if (test_bit(0, &wport->write_urbs_free)) room = wport->bulk_out_size - OMNINET_HEADERLEN; - dbg("%s - returns %d", __func__, room); + dev_dbg(&port->dev, "%s - returns %d\n", __func__, room); return room; } @@ -275,8 +275,8 @@ static void omninet_write_bulk_callback(struct urb *urb) set_bit(0, &port->write_urbs_free); if (status) { - dbg("%s - nonzero write bulk status received: %d", - __func__, status); + dev_dbg(&port->dev, "%s - nonzero write bulk status received: %d\n", + __func__, status); return; } -- cgit v0.10.2 From a80be97d0a37c1f93efc233f78722b03faedb2ed Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 13 Sep 2012 17:41:50 -0700 Subject: USB: serial: usb_wwan.c: remove dbg() usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. CC: "Bjørn Mork" CC: Rusty Russell CC: Mauro Carvalho Chehab CC: Dan Carpenter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 6855d5e..3520eff 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -178,7 +178,7 @@ int usb_wwan_ioctl(struct tty_struct *tty, { struct usb_serial_port *port = tty->driver_data; - dbg("%s cmd 0x%04x", __func__, cmd); + dev_dbg(&port->dev, "%s cmd 0x%04x\n", __func__, cmd); switch (cmd) { case TIOCGSERIAL: @@ -191,7 +191,7 @@ int usb_wwan_ioctl(struct tty_struct *tty, break; } - dbg("%s arg not supported", __func__); + dev_dbg(&port->dev, "%s arg not supported\n", __func__); return -ENOIOCTLCMD; } @@ -212,7 +212,7 @@ int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port, portdata = usb_get_serial_port_data(port); intfdata = port->serial->private; - dbg("%s: write (%d chars)", __func__, count); + dev_dbg(&port->dev, "%s: write (%d chars)\n", __func__, count); i = 0; left = count; @@ -229,8 +229,8 @@ int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port, usb_unlink_urb(this_urb); continue; } - dbg("%s: endpoint %d buf %d", __func__, - usb_pipeendpoint(this_urb->pipe), i); + dev_dbg(&port->dev, "%s: endpoint %d buf %d\n", __func__, + usb_pipeendpoint(this_urb->pipe), i); err = usb_autopm_get_interface_async(port->serial->interface); if (err < 0) @@ -249,8 +249,9 @@ int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port, spin_unlock_irqrestore(&intfdata->susp_lock, flags); err = usb_submit_urb(this_urb, GFP_ATOMIC); if (err) { - dbg("usb_submit_urb %p (write bulk) failed " - "(%d)", this_urb, err); + dev_dbg(&port->dev, + "usb_submit_urb %p (write bulk) failed (%d)\n", + this_urb, err); clear_bit(i, &portdata->out_busy); spin_lock_irqsave(&intfdata->susp_lock, flags); intfdata->in_flight--; @@ -267,7 +268,7 @@ int usb_wwan_write(struct tty_struct *tty, struct usb_serial_port *port, } count -= left; - dbg("%s: wrote (did %d)", __func__, count); + dev_dbg(&port->dev, "%s: wrote (did %d)\n", __func__, count); return count; } EXPORT_SYMBOL(usb_wwan_write); @@ -278,15 +279,17 @@ static void usb_wwan_indat_callback(struct urb *urb) int endpoint; struct usb_serial_port *port; struct tty_struct *tty; + struct device *dev; unsigned char *data = urb->transfer_buffer; int status = urb->status; endpoint = usb_pipeendpoint(urb->pipe); port = urb->context; + dev = &port->dev; if (status) { - dbg("%s: nonzero status: %d on endpoint %02x.", - __func__, status, endpoint); + dev_dbg(dev, "%s: nonzero status: %d on endpoint %02x.\n", + __func__, status, endpoint); } else { tty = tty_port_tty_get(&port->port); if (tty) { @@ -295,7 +298,7 @@ static void usb_wwan_indat_callback(struct urb *urb) urb->actual_length); tty_flip_buffer_push(tty); } else - dbg("%s: empty read urb received", __func__); + dev_dbg(dev, "%s: empty read urb received\n", __func__); tty_kref_put(tty); } @@ -303,8 +306,7 @@ static void usb_wwan_indat_callback(struct urb *urb) err = usb_submit_urb(urb, GFP_ATOMIC); if (err) { if (err != -EPERM) { - printk(KERN_ERR "%s: resubmit read urb failed. " - "(%d)", __func__, err); + dev_err(dev, "%s: resubmit read urb failed. (%d)\n", __func__, err); /* busy also in error unless we are killed */ usb_mark_last_busy(port->serial->dev); } @@ -356,7 +358,7 @@ int usb_wwan_write_room(struct tty_struct *tty) data_len += OUT_BUFLEN; } - dbg("%s: %d", __func__, data_len); + dev_dbg(&port->dev, "%s: %d\n", __func__, data_len); return data_len; } EXPORT_SYMBOL(usb_wwan_write_room); @@ -378,7 +380,7 @@ int usb_wwan_chars_in_buffer(struct tty_struct *tty) if (this_urb && test_bit(i, &portdata->out_busy)) data_len += this_urb->transfer_buffer_length; } - dbg("%s: %d", __func__, data_len); + dev_dbg(&port->dev, "%s: %d\n", __func__, data_len); return data_len; } EXPORT_SYMBOL(usb_wwan_chars_in_buffer); @@ -401,8 +403,8 @@ int usb_wwan_open(struct tty_struct *tty, struct usb_serial_port *port) continue; err = usb_submit_urb(urb, GFP_KERNEL); if (err) { - dbg("%s: submit urb %d failed (%d) %d", - __func__, i, err, urb->transfer_buffer_length); + dev_dbg(&port->dev, "%s: submit urb %d failed (%d) %d\n", + __func__, i, err, urb->transfer_buffer_length); } } @@ -458,7 +460,9 @@ static struct urb *usb_wwan_setup_urb(struct usb_serial *serial, int endpoint, urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */ if (urb == NULL) { - dbg("%s: alloc for endpoint %d failed.", __func__, endpoint); + dev_dbg(&serial->interface->dev, + "%s: alloc for endpoint %d failed.\n", __func__, + endpoint); return NULL; } @@ -522,8 +526,8 @@ int usb_wwan_startup(struct usb_serial *serial) port = serial->port[i]; portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); if (!portdata) { - dbg("%s: kmalloc for usb_wwan_port_private (%d) failed!.", - __func__, i); + dev_dbg(&port->dev, "%s: kmalloc for usb_wwan_port_private (%d) failed!.\n", + __func__, i); return 1; } init_usb_anchor(&portdata->delayed); @@ -548,7 +552,8 @@ int usb_wwan_startup(struct usb_serial *serial) continue; err = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (err) - dbg("%s: submit irq_in urb failed %d", __func__, err); + dev_dbg(&port->dev, "%s: submit irq_in urb failed %d\n", + __func__, err); } usb_wwan_setup_urbs(serial); return 0; @@ -683,11 +688,11 @@ int usb_wwan_resume(struct usb_serial *serial) for (i = 0; i < serial->num_ports; i++) { port = serial->port[i]; if (!port->interrupt_in_urb) { - dbg("%s: No interrupt URB for port %d", __func__, i); + dev_dbg(&port->dev, "%s: No interrupt URB for port\n", __func__); continue; } err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO); - dbg("Submitted interrupt URB for port %d (result %d)", i, err); + dev_dbg(&port->dev, "Submitted interrupt URB for port (result %d)\n", err); if (err < 0) { dev_err(&port->dev, "%s: Error %d for interrupt URB\n", __func__, err); -- cgit v0.10.2 From 2edd968638038375f43b5b5e591064b5a87424c0 Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Wed, 12 Sep 2012 19:03:22 +0200 Subject: drivers/usb/host/sl811-hcd.c: removes unnecessary semicolon removes unnecessary semicolon Found by Coccinelle: http://coccinelle.lip6.fr/ Signed-off-by: Peter Senna Tschudin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index 91ce1c0..619b05f 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -156,7 +156,7 @@ static void setup_packet( writeb(SL_SETUP /* | ep->epnum */, data_reg); writeb(usb_pipedevice(urb->pipe), data_reg); - /* always OUT/data0 */ ; + /* always OUT/data0 */ sl811_write(sl811, bank + SL11H_HOSTCTLREG, control | SL11H_HCTLMASK_OUT); ep->length = 0; -- cgit v0.10.2 From 17e6791082e3dc34d0b43fd50ff8655fdfcc3a99 Mon Sep 17 00:00:00 2001 From: Peter Senna Tschudin Date: Wed, 12 Sep 2012 19:03:20 +0200 Subject: drivers/usb/misc/rio500.c: removes unnecessary semicolon removes unnecessary semicolon Found by Coccinelle: http://coccinelle.lip6.fr/ Signed-off-by: Peter Senna Tschudin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/misc/rio500.c b/drivers/usb/misc/rio500.c index 1084124..b9b356a 100644 --- a/drivers/usb/misc/rio500.c +++ b/drivers/usb/misc/rio500.c @@ -338,7 +338,7 @@ write_rio(struct file *file, const char __user *buffer, thistime -= partial; } else break; - }; + } if (result) { dev_err(&rio->rio_dev->dev, "Write Whoops - %x\n", result); -- cgit v0.10.2 From 8321652ae22f38830af5b553f3a316d68948ddce Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Thu, 13 Sep 2012 22:56:55 +0400 Subject: USB: omninet: fix potential tty NULL dereference Add check for return value of tty_port_tty_get, since it can return NULL after port hangup that may happen anytime. Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index d31f661..f524cd9 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -185,10 +185,12 @@ static void omninet_read_bulk_callback(struct urb *urb) if (urb->actual_length && header->oh_len) { struct tty_struct *tty = tty_port_tty_get(&port->port); - tty_insert_flip_string(tty, data + OMNINET_DATAOFFSET, + if (tty) { + tty_insert_flip_string(tty, data + OMNINET_DATAOFFSET, header->oh_len); - tty_flip_buffer_push(tty); - tty_kref_put(tty); + tty_flip_buffer_push(tty); + tty_kref_put(tty); + } } /* Continue trying to always read */ -- cgit v0.10.2 From 99495c7061892f0312c0119725b550bb221634ce Mon Sep 17 00:00:00 2001 From: Rene Buergel Date: Thu, 13 Sep 2012 22:14:38 +0200 Subject: USB: ezusb: remove dependancy on usb_serial MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch removes the dependency on the usb_serial interface and names some magic constants Signed-off-by: René Bürgel -- Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c index 800e8eb..3048b52d 100644 --- a/drivers/usb/serial/ezusb.c +++ b/drivers/usb/serial/ezusb.c @@ -9,24 +9,24 @@ */ #include -#include #include #include -#include #include #include -#include /* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */ #define CPUCS_REG 0x7F92 -int ezusb_writememory(struct usb_serial *serial, int address, +/* Command for writing to internal memory */ +#define WRITE_INT_RAM 0xA0 + +int ezusb_writememory(struct usb_device *dev, int address, unsigned char *data, int length, __u8 request) { int result; unsigned char *transfer_buffer; - if (!serial->dev) { + if (!dev) { printk(KERN_ERR "ezusb: %s - no physical device present, " "failing.\n", __func__); return -ENODEV; @@ -34,25 +34,25 @@ int ezusb_writememory(struct usb_serial *serial, int address, transfer_buffer = kmemdup(data, length, GFP_KERNEL); if (!transfer_buffer) { - dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", + dev_err(&dev->dev, "%s - kmalloc(%d) failed.\n", __func__, length); return -ENOMEM; } - result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), - request, 0x40, address, 0, transfer_buffer, length, 3000); + result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + address, 0, transfer_buffer, length, 3000); + kfree(transfer_buffer); return result; } EXPORT_SYMBOL_GPL(ezusb_writememory); -int ezusb_set_reset(struct usb_serial *serial, unsigned char reset_bit) +int ezusb_set_reset(struct usb_device *dev, unsigned char reset_bit) { - int response; - - response = ezusb_writememory(serial, CPUCS_REG, &reset_bit, 1, 0xa0); + int response = ezusb_writememory(dev, CPUCS_REG, &reset_bit, 1, WRITE_INT_RAM); if (response < 0) - dev_err(&serial->dev->dev, "%s- %d failed\n", - __func__, reset_bit); + dev_err(&dev->dev, "%s-%d failed: %d\n", + __func__, reset_bit, response); return response; } EXPORT_SYMBOL_GPL(ezusb_set_reset); diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index af0b70e..f0d4f3f 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -1241,12 +1241,12 @@ static int keyspan_fake_startup(struct usb_serial *serial) dbg("Uploading Keyspan %s firmware.", fw_name); /* download the firmware image */ - response = ezusb_set_reset(serial, 1); + response = ezusb_set_reset(serial->dev, 1); record = (const struct ihex_binrec *)fw->data; while (record) { - response = ezusb_writememory(serial, be32_to_cpu(record->addr), + response = ezusb_writememory(serial->dev, be32_to_cpu(record->addr), (unsigned char *)record->data, be16_to_cpu(record->len), 0xa0); if (response < 0) { @@ -1260,7 +1260,7 @@ static int keyspan_fake_startup(struct usb_serial *serial) release_firmware(fw); /* bring device out of reset. Renumeration will occur in a moment and the new device will bind to the real driver */ - response = ezusb_set_reset(serial, 0); + response = ezusb_set_reset(serial->dev, 0); /* we don't want this device to have a driver assigned to it. */ return 1; diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index a4ac3cf..1290b6f 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -682,7 +682,7 @@ static int keyspan_pda_fake_startup(struct usb_serial *serial) const struct firmware *fw; /* download the firmware here ... */ - response = ezusb_set_reset(serial, 1); + response = ezusb_set_reset(serial->dev, 1); if (0) { ; } #ifdef KEYSPAN @@ -707,7 +707,7 @@ static int keyspan_pda_fake_startup(struct usb_serial *serial) record = (const struct ihex_binrec *)fw->data; while (record) { - response = ezusb_writememory(serial, be32_to_cpu(record->addr), + response = ezusb_writememory(serial->dev, be32_to_cpu(record->addr), (unsigned char *)record->data, be16_to_cpu(record->len), 0xa0); if (response < 0) { @@ -722,7 +722,7 @@ static int keyspan_pda_fake_startup(struct usb_serial *serial) release_firmware(fw); /* bring device out of reset. Renumeration will occur in a moment and the new device will bind to the real driver */ - response = ezusb_set_reset(serial, 0); + response = ezusb_set_reset(serial->dev, 0); /* we want this device to fail to have a driver assigned to it. */ return 1; diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 473635e..fc72591 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -213,13 +213,13 @@ static int whiteheat_firmware_download(struct usb_serial *serial, goto out; } ret = 0; - response = ezusb_set_reset (serial, 1); + response = ezusb_set_reset(serial->dev, 1); record = (const struct ihex_binrec *)loader_fw->data; while (record) { - response = ezusb_writememory (serial, be32_to_cpu(record->addr), - (unsigned char *)record->data, - be16_to_cpu(record->len), 0xa0); + response = ezusb_writememory(serial->dev, be32_to_cpu(record->addr), + (unsigned char *)record->data, + be16_to_cpu(record->len), 0xa0); if (response < 0) { dev_err(&serial->dev->dev, "%s - ezusb_writememory " "failed for loader (%d %04X %p %d)\n", @@ -230,15 +230,15 @@ static int whiteheat_firmware_download(struct usb_serial *serial, record = ihex_next_binrec(record); } - response = ezusb_set_reset(serial, 0); + response = ezusb_set_reset(serial->dev, 0); record = (const struct ihex_binrec *)firmware_fw->data; while (record && be32_to_cpu(record->addr) < 0x1b40) record = ihex_next_binrec(record); while (record) { - response = ezusb_writememory (serial, be32_to_cpu(record->addr), - (unsigned char *)record->data, - be16_to_cpu(record->len), 0xa3); + response = ezusb_writememory(serial->dev, be32_to_cpu(record->addr), + (unsigned char *)record->data, + be16_to_cpu(record->len), 0xa3); if (response < 0) { dev_err(&serial->dev->dev, "%s - ezusb_writememory " "failed for first firmware step " @@ -250,13 +250,13 @@ static int whiteheat_firmware_download(struct usb_serial *serial, ++record; } - response = ezusb_set_reset(serial, 1); + response = ezusb_set_reset(serial->dev, 1); record = (const struct ihex_binrec *)firmware_fw->data; while (record && be32_to_cpu(record->addr) < 0x1b40) { - response = ezusb_writememory (serial, be32_to_cpu(record->addr), - (unsigned char *)record->data, - be16_to_cpu(record->len), 0xa0); + response = ezusb_writememory(serial->dev, be32_to_cpu(record->addr), + (unsigned char *)record->data, + be16_to_cpu(record->len), 0xa0); if (response < 0) { dev_err(&serial->dev->dev, "%s - ezusb_writememory " "failed for second firmware step " @@ -268,7 +268,7 @@ static int whiteheat_firmware_download(struct usb_serial *serial, ++record; } ret = 0; - response = ezusb_set_reset (serial, 0); + response = ezusb_set_reset(serial->dev, 0); out: release_firmware(loader_fw); release_firmware(firmware_fw); diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 9e9a0a8..6bed6db 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -301,9 +301,9 @@ extern void usb_serial_port_softint(struct usb_serial_port *port); extern int usb_serial_suspend(struct usb_interface *intf, pm_message_t message); extern int usb_serial_resume(struct usb_interface *intf); -extern int ezusb_writememory(struct usb_serial *serial, int address, +extern int ezusb_writememory(struct usb_device *dev, int address, unsigned char *data, int length, __u8 bRequest); -extern int ezusb_set_reset(struct usb_serial *serial, unsigned char reset_bit); +extern int ezusb_set_reset(struct usb_device *dev, unsigned char reset_bit); /* USB Serial console functions */ #ifdef CONFIG_USB_SERIAL_CONSOLE -- cgit v0.10.2 From dfa1c31564404284d4faa694c157192cd64cf6a4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 09:47:38 -0700 Subject: USB: serial: cypress_m8.c: remove dbg() usage dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. CC: Lonnie Mendez Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index b78c34e..872a45d 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -263,8 +263,9 @@ static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate) * safest speed for a part like that. */ if (new_rate > 4800) { - dbg("%s - failed setting baud rate, device incapable " - "speed %d", __func__, new_rate); + dev_dbg(&port->dev, + "%s - failed setting baud rate, device incapable speed %d\n", + __func__, new_rate); return -1; } } @@ -274,8 +275,9 @@ static int analyze_baud_rate(struct usb_serial_port *port, speed_t new_rate) /* 300 and 600 baud rates are supported under * the generic firmware, but are not used with * NMEA and SiRF protocols */ - dbg("%s - failed setting baud rate, unsupported speed " - "of %d on Earthmate GPS", __func__, new_rate); + dev_dbg(&port->dev, + "%s - failed setting baud rate, unsupported speed of %d on Earthmate GPS", + __func__, new_rate); return -1; } break; @@ -294,6 +296,7 @@ static int cypress_serial_control(struct tty_struct *tty, { int new_baudrate = 0, retval = 0, tries = 0; struct cypress_private *priv; + struct device *dev = &port->dev; u8 *feature_buffer; const unsigned int feature_len = 5; unsigned long flags; @@ -312,16 +315,16 @@ static int cypress_serial_control(struct tty_struct *tty, /* 0 means 'Hang up' so doesn't change the true bit rate */ new_baudrate = priv->baud_rate; if (baud_rate && baud_rate != priv->baud_rate) { - dbg("%s - baud rate is changing", __func__); + dev_dbg(dev, "%s - baud rate is changing\n", __func__); retval = analyze_baud_rate(port, baud_rate); if (retval >= 0) { new_baudrate = retval; - dbg("%s - New baud rate set to %d", - __func__, new_baudrate); + dev_dbg(dev, "%s - New baud rate set to %d\n", + __func__, new_baudrate); } } - dbg("%s - baud rate is being sent as %d", - __func__, new_baudrate); + dev_dbg(dev, "%s - baud rate is being sent as %d\n", __func__, + new_baudrate); /* fill the feature_buffer with new configuration */ put_unaligned_le32(new_baudrate, feature_buffer); @@ -333,9 +336,8 @@ static int cypress_serial_control(struct tty_struct *tty, /* 1 bit gap */ feature_buffer[4] |= (reset << 7); /* assign reset at end of byte, 1 bit space */ - dbg("%s - device is being sent this feature report:", - __func__); - dbg("%s - %02X - %02X - %02X - %02X - %02X", __func__, + dev_dbg(dev, "%s - device is being sent this feature report:\n", __func__); + dev_dbg(dev, "%s - %02X - %02X - %02X - %02X - %02X\n", __func__, feature_buffer[0], feature_buffer[1], feature_buffer[2], feature_buffer[3], feature_buffer[4]); @@ -355,8 +357,8 @@ static int cypress_serial_control(struct tty_struct *tty, retval != -ENODEV); if (retval != feature_len) { - dev_err(&port->dev, "%s - failed sending serial " - "line settings - %d\n", __func__, retval); + dev_err(dev, "%s - failed sending serial line settings - %d\n", + __func__, retval); cypress_set_dead(port); } else { spin_lock_irqsave(&priv->lock, flags); @@ -377,7 +379,7 @@ static int cypress_serial_control(struct tty_struct *tty, retval = -ENOTTY; goto out; } - dbg("%s - retreiving serial line settings", __func__); + dev_dbg(dev, "%s - retreiving serial line settings\n", __func__); do { retval = usb_control_msg(port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0), @@ -392,8 +394,8 @@ static int cypress_serial_control(struct tty_struct *tty, && retval != -ENODEV); if (retval != feature_len) { - dev_err(&port->dev, "%s - failed to retrieve serial " - "line settings - %d\n", __func__, retval); + dev_err(dev, "%s - failed to retrieve serial line settings - %d\n", + __func__, retval); cypress_set_dead(port); goto out; } else { @@ -474,14 +476,14 @@ static int generic_startup(struct usb_serial *serial) if (interval > 0) { priv->write_urb_interval = interval; priv->read_urb_interval = interval; - dbg("%s - port %d read & write intervals forced to %d", - __func__, port->number, interval); + dev_dbg(&port->dev, "%s - read & write intervals forced to %d\n", + __func__, interval); } else { priv->write_urb_interval = port->interrupt_out_urb->interval; priv->read_urb_interval = port->interrupt_in_urb->interval; - dbg("%s - port %d intervals: read=%d write=%d", - __func__, port->number, - priv->read_urb_interval, priv->write_urb_interval); + dev_dbg(&port->dev, "%s - intervals: read=%d write=%d\n", + __func__, priv->read_urb_interval, + priv->write_urb_interval); } usb_set_serial_port_data(port, priv); @@ -495,8 +497,7 @@ static int cypress_earthmate_startup(struct usb_serial *serial) struct usb_serial_port *port = serial->port[0]; if (generic_startup(serial)) { - dbg("%s - Failed setting up port %d", __func__, - port->number); + dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__); return 1; } @@ -511,8 +512,9 @@ static int cypress_earthmate_startup(struct usb_serial *serial) handle GET_CONFIG requests; everything they've produced since that time crashes if this command is attempted :-( */ - dbg("%s - Marking this device as unsafe for GET_CONFIG " - "commands", __func__); + dev_dbg(&port->dev, + "%s - Marking this device as unsafe for GET_CONFIG commands\n", + __func__); priv->get_cfg_unsafe = !0; } @@ -523,14 +525,14 @@ static int cypress_earthmate_startup(struct usb_serial *serial) static int cypress_hidcom_startup(struct usb_serial *serial) { struct cypress_private *priv; + struct usb_serial_port *port = serial->port[0]; if (generic_startup(serial)) { - dbg("%s - Failed setting up port %d", __func__, - serial->port[0]->number); + dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__); return 1; } - priv = usb_get_serial_port_data(serial->port[0]); + priv = usb_get_serial_port_data(port); priv->chiptype = CT_CYPHIDCOM; return 0; @@ -540,14 +542,14 @@ static int cypress_hidcom_startup(struct usb_serial *serial) static int cypress_ca42v2_startup(struct usb_serial *serial) { struct cypress_private *priv; + struct usb_serial_port *port = serial->port[0]; if (generic_startup(serial)) { - dbg("%s - Failed setting up port %d", __func__, - serial->port[0]->number); + dev_dbg(&port->dev, "%s - Failed setting up port\n", __func__); return 1; } - priv = usb_get_serial_port_data(serial->port[0]); + priv = usb_get_serial_port_data(port); priv->chiptype = CT_CA42V2; return 0; @@ -649,7 +651,7 @@ static void cypress_close(struct usb_serial_port *port) kfifo_reset_out(&priv->write_fifo); spin_unlock_irqrestore(&priv->lock, flags); - dbg("%s - stopping urbs", __func__); + dev_dbg(&port->dev, "%s - stopping urbs\n", __func__); usb_kill_urb(port->interrupt_in_urb); usb_kill_urb(port->interrupt_out_urb); @@ -665,7 +667,7 @@ static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port, { struct cypress_private *priv = usb_get_serial_port_data(port); - dbg("%s - port %d, %d bytes", __func__, port->number, count); + dev_dbg(&port->dev, "%s - port %d, %d bytes\n", __func__, port->number, count); /* line control commands, which need to be executed immediately, are not put into the buffer for obvious reasons. @@ -691,17 +693,18 @@ static void cypress_send(struct usb_serial_port *port) { int count = 0, result, offset, actual_size; struct cypress_private *priv = usb_get_serial_port_data(port); + struct device *dev = &port->dev; unsigned long flags; if (!priv->comm_is_ok) return; - dbg("%s - interrupt out size is %d", __func__, - port->interrupt_out_size); + dev_dbg(dev, "%s - interrupt out size is %d\n", __func__, + port->interrupt_out_size); spin_lock_irqsave(&priv->lock, flags); if (priv->write_urb_in_use) { - dbg("%s - can't write, urb in use", __func__); + dev_dbg(dev, "%s - can't write, urb in use\n", __func__); spin_unlock_irqrestore(&priv->lock, flags); return; } @@ -731,7 +734,7 @@ static void cypress_send(struct usb_serial_port *port) if (priv->cmd_ctrl) { priv->cmd_count++; - dbg("%s - line control command being issued", __func__); + dev_dbg(dev, "%s - line control command being issued\n", __func__); spin_unlock_irqrestore(&priv->lock, flags); goto send; } else @@ -753,7 +756,7 @@ static void cypress_send(struct usb_serial_port *port) port->interrupt_out_buffer[0] |= count; } - dbg("%s - count is %d", __func__, count); + dev_dbg(dev, "%s - count is %d\n", __func__, count); send: spin_lock_irqsave(&priv->lock, flags); @@ -807,7 +810,7 @@ static int cypress_write_room(struct tty_struct *tty) room = kfifo_avail(&priv->write_fifo); spin_unlock_irqrestore(&priv->lock, flags); - dbg("%s - returns %d", __func__, room); + dev_dbg(&port->dev, "%s - returns %d\n", __func__, room); return room; } @@ -832,7 +835,7 @@ static int cypress_tiocmget(struct tty_struct *tty) | ((status & UART_RI) ? TIOCM_RI : 0) | ((status & UART_CD) ? TIOCM_CD : 0); - dbg("%s - result = %x", __func__, result); + dev_dbg(&port->dev, "%s - result = %x\n", __func__, result); return result; } @@ -867,7 +870,7 @@ static int cypress_ioctl(struct tty_struct *tty, struct usb_serial_port *port = tty->driver_data; struct cypress_private *priv = usb_get_serial_port_data(port); - dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd); + dev_dbg(&port->dev, "%s - port %d, cmd 0x%.4x\n", __func__, port->number, cmd); switch (cmd) { /* This code comes from drivers/char/serial.c and ftdi_sio.c */ @@ -902,7 +905,7 @@ static int cypress_ioctl(struct tty_struct *tty, default: break; } - dbg("%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h", __func__, cmd); + dev_dbg(&port->dev, "%s - arg not supported - it was 0x%04x - check include/asm/ioctls.h\n", __func__, cmd); return -ENOIOCTLCMD; } /* cypress_ioctl */ @@ -911,6 +914,7 @@ static void cypress_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { struct cypress_private *priv = usb_get_serial_port_data(port); + struct device *dev = &port->dev; int data_bits, stop_bits, parity_type, parity_enable; unsigned cflag, iflag; unsigned long flags; @@ -984,23 +988,21 @@ static void cypress_set_termios(struct tty_struct *tty, data_bits = 3; break; default: - dev_err(&port->dev, "%s - CSIZE was set, but not CS5-CS8\n", - __func__); + dev_err(dev, "%s - CSIZE was set, but not CS5-CS8\n", __func__); data_bits = 3; } spin_lock_irqsave(&priv->lock, flags); oldlines = priv->line_control; if ((cflag & CBAUD) == B0) { /* drop dtr and rts */ - dbg("%s - dropping the lines, baud rate 0bps", __func__); + dev_dbg(dev, "%s - dropping the lines, baud rate 0bps\n", __func__); priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); } else priv->line_control = (CONTROL_DTR | CONTROL_RTS); spin_unlock_irqrestore(&priv->lock, flags); - dbg("%s - sending %d stop_bits, %d parity_enable, %d parity_type, " - "%d data_bits (+5)", __func__, stop_bits, - parity_enable, parity_type, data_bits); + dev_dbg(dev, "%s - sending %d stop_bits, %d parity_enable, %d parity_type, %d data_bits (+5)\n", + __func__, stop_bits, parity_enable, parity_type, data_bits); cypress_serial_control(tty, port, tty_get_baud_rate(tty), data_bits, stop_bits, @@ -1017,8 +1019,7 @@ static void cypress_set_termios(struct tty_struct *tty, spin_lock_irqsave(&priv->lock, flags); if (priv->chiptype == CT_EARTHMATE && priv->baud_rate == 4800) { - dbg("Using custom termios settings for a baud rate of " - "4800bps."); + dev_dbg(dev, "Using custom termios settings for a baud rate of 4800bps.\n"); /* define custom termios settings for NMEA protocol */ tty->termios->c_iflag /* input modes - */ @@ -1067,7 +1068,7 @@ static int cypress_chars_in_buffer(struct tty_struct *tty) chars = kfifo_len(&priv->write_fifo); spin_unlock_irqrestore(&priv->lock, flags); - dbg("%s - returns %d", __func__, chars); + dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars); return chars; } @@ -1112,6 +1113,7 @@ static void cypress_read_int_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct cypress_private *priv = usb_get_serial_port_data(port); + struct device *dev = &urb->dev->dev; struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; unsigned long flags; @@ -1135,16 +1137,15 @@ static void cypress_read_int_callback(struct urb *urb) /* FALLS THROUGH */ default: /* something ugly is going on... */ - dev_err(&urb->dev->dev, - "%s - unexpected nonzero read status received: %d\n", - __func__, status); + dev_err(dev, "%s - unexpected nonzero read status received: %d\n", + __func__, status); cypress_set_dead(port); return; } spin_lock_irqsave(&priv->lock, flags); if (priv->rx_flags & THROTTLED) { - dbg("%s - now throttling", __func__); + dev_dbg(dev, "%s - now throttling\n", __func__); priv->rx_flags |= ACTUALLY_THROTTLED; spin_unlock_irqrestore(&priv->lock, flags); return; @@ -1153,7 +1154,7 @@ static void cypress_read_int_callback(struct urb *urb) tty = tty_port_tty_get(&port->port); if (!tty) { - dbg("%s - bad tty pointer - exiting", __func__); + dev_dbg(dev, "%s - bad tty pointer - exiting\n", __func__); return; } @@ -1180,8 +1181,9 @@ static void cypress_read_int_callback(struct urb *urb) } spin_unlock_irqrestore(&priv->lock, flags); if (result < bytes) { - dbg("%s - wrong packet size - received %d bytes but packet " - "said %d bytes", __func__, result, bytes); + dev_dbg(dev, + "%s - wrong packet size - received %d bytes but packet said %d bytes\n", + __func__, result, bytes); goto continue_read; } @@ -1202,7 +1204,7 @@ static void cypress_read_int_callback(struct urb *urb) * though */ if (tty && !(tty->termios->c_cflag & CLOCAL) && !(priv->current_status & UART_CD)) { - dbg("%s - calling hangup", __func__); + dev_dbg(dev, "%s - calling hangup\n", __func__); tty_hangup(tty); goto continue_read; } @@ -1215,7 +1217,7 @@ static void cypress_read_int_callback(struct urb *urb) if (priv->current_status & CYP_ERROR) { spin_unlock_irqrestore(&priv->lock, flags); tty_flag = TTY_PARITY; - dbg("%s - Parity Error detected", __func__); + dev_dbg(dev, "%s - Parity Error detected\n", __func__); } else spin_unlock_irqrestore(&priv->lock, flags); @@ -1246,9 +1248,8 @@ continue_read: priv->read_urb_interval); result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); if (result && result != -EPERM) { - dev_err(&urb->dev->dev, "%s - failed resubmitting " - "read urb, error %d\n", __func__, - result); + dev_err(dev, "%s - failed resubmitting read urb, error %d\n", + __func__, result); cypress_set_dead(port); } } @@ -1259,6 +1260,7 @@ static void cypress_write_int_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct cypress_private *priv = usb_get_serial_port_data(port); + struct device *dev = &urb->dev->dev; int result; int status = urb->status; @@ -1270,8 +1272,8 @@ static void cypress_write_int_callback(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", - __func__, status); + dev_dbg(dev, "%s - urb shutting down with status: %d\n", + __func__, status); priv->write_urb_in_use = 0; return; case -EPIPE: /* no break needed; clear halt and resubmit */ @@ -1279,21 +1281,19 @@ static void cypress_write_int_callback(struct urb *urb) break; usb_clear_halt(port->serial->dev, 0x02); /* error in the urb, so we have to resubmit it */ - dbg("%s - nonzero write bulk status received: %d", + dev_dbg(dev, "%s - nonzero write bulk status received: %d\n", __func__, status); port->interrupt_out_urb->transfer_buffer_length = 1; result = usb_submit_urb(port->interrupt_out_urb, GFP_ATOMIC); if (!result) return; - dev_err(&urb->dev->dev, - "%s - failed resubmitting write urb, error %d\n", - __func__, result); + dev_err(dev, "%s - failed resubmitting write urb, error %d\n", + __func__, result); cypress_set_dead(port); break; default: - dev_err(&urb->dev->dev, - "%s - unexpected nonzero write status received: %d\n", - __func__, status); + dev_err(dev, "%s - unexpected nonzero write status received: %d\n", + __func__, status); cypress_set_dead(port); break; } -- cgit v0.10.2 From f9dfbebb8b39b692474a30e9430073577dd88d7c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 09:47:39 -0700 Subject: USB: serial: digi_acceleport.c: remove dbg() usage dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. CC: Peter Berger CC: Al Borchers Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index b5cd838..df60a33 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -404,14 +404,15 @@ static void digi_wakeup_write(struct usb_serial_port *port) static int digi_write_oob_command(struct usb_serial_port *port, unsigned char *buf, int count, int interruptible) { - int ret = 0; int len; struct usb_serial_port *oob_port = (struct usb_serial_port *)((struct digi_serial *)(usb_get_serial_data(port->serial)))->ds_oob_port; struct digi_port *oob_priv = usb_get_serial_port_data(oob_port); unsigned long flags = 0; - dbg("digi_write_oob_command: TOP: port=%d, count=%d", oob_priv->dp_port_num, count); + dev_dbg(&port->dev, + "digi_write_oob_command: TOP: port=%d, count=%d\n", + oob_priv->dp_port_num, count); spin_lock_irqsave(&oob_priv->dp_port_lock, flags); while (count > 0) { @@ -467,7 +468,7 @@ static int digi_write_inb_command(struct usb_serial_port *port, unsigned char *data = port->write_urb->transfer_buffer; unsigned long flags = 0; - dbg("digi_write_inb_command: TOP: port=%d, count=%d", + dev_dbg(&port->dev, "digi_write_inb_command: TOP: port=%d, count=%d\n", priv->dp_port_num, count); if (timeout) @@ -549,7 +550,8 @@ static int digi_set_modem_signals(struct usb_serial_port *port, unsigned long flags = 0; - dbg("digi_set_modem_signals: TOP: port=%d, modem_signals=0x%x", + dev_dbg(&port->dev, + "digi_set_modem_signals: TOP: port=%d, modem_signals=0x%x\n", port_priv->dp_port_num, modem_signals); spin_lock_irqsave(&oob_priv->dp_port_lock, flags); @@ -687,6 +689,7 @@ static void digi_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { struct digi_port *priv = usb_get_serial_port_data(port); + struct device *dev = &port->dev; unsigned int iflag = tty->termios->c_iflag; unsigned int cflag = tty->termios->c_cflag; unsigned int old_iflag = old_termios->c_iflag; @@ -697,7 +700,9 @@ static void digi_set_termios(struct tty_struct *tty, int i = 0; speed_t baud; - dbg("digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, old_cflag=0x%x", priv->dp_port_num, iflag, old_iflag, cflag, old_cflag); + dev_dbg(dev, + "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, old_cflag=0x%x\n", + priv->dp_port_num, iflag, old_iflag, cflag, old_cflag); /* set baud rate */ baud = tty_get_baud_rate(tty); @@ -773,7 +778,8 @@ static void digi_set_termios(struct tty_struct *tty, case CS7: arg = DIGI_WORD_SIZE_7; break; case CS8: arg = DIGI_WORD_SIZE_8; break; default: - dbg("digi_set_termios: can't handle word size %d", + dev_dbg(dev, + "digi_set_termios: can't handle word size %d\n", (cflag&CSIZE)); break; } @@ -866,7 +872,7 @@ static void digi_set_termios(struct tty_struct *tty, } ret = digi_write_oob_command(port, buf, i, 1); if (ret != 0) - dbg("digi_set_termios: write oob failed, ret=%d", ret); + dev_dbg(dev, "digi_set_termios: write oob failed, ret=%d\n", ret); tty_encode_baud_rate(tty, baud, baud); } @@ -922,7 +928,8 @@ static int digi_write(struct tty_struct *tty, struct usb_serial_port *port, unsigned char *data = port->write_urb->transfer_buffer; unsigned long flags = 0; - dbg("digi_write: TOP: port=%d, count=%d, in_interrupt=%ld", + dev_dbg(&port->dev, + "digi_write: TOP: port=%d, count=%d, in_interrupt=%ld\n", priv->dp_port_num, count, in_interrupt()); /* copy user data (which can sleep) before getting spin lock */ @@ -981,7 +988,7 @@ static int digi_write(struct tty_struct *tty, struct usb_serial_port *port, dev_err_console(port, "%s: usb_submit_urb failed, ret=%d, port=%d\n", __func__, ret, priv->dp_port_num); - dbg("digi_write: returning %d", ret); + dev_dbg(&port->dev, "digi_write: returning %d\n", ret); return ret; } @@ -1012,7 +1019,7 @@ static void digi_write_bulk_callback(struct urb *urb) /* handle oob callback */ if (priv->dp_port_num == serial_priv->ds_oob_port_num) { - dbg("digi_write_bulk_callback: oob callback"); + dev_dbg(&port->dev, "digi_write_bulk_callback: oob callback\n"); spin_lock(&priv->dp_port_lock); priv->dp_write_urb_in_use = 0; wake_up_interruptible(&port->write_wait); @@ -1066,7 +1073,7 @@ static int digi_write_room(struct tty_struct *tty) room = port->bulk_out_size - 2 - priv->dp_out_buf_len; spin_unlock_irqrestore(&priv->dp_port_lock, flags); - dbg("digi_write_room: port=%d, room=%d", priv->dp_port_num, room); + dev_dbg(&port->dev, "digi_write_room: port=%d, room=%d\n", priv->dp_port_num, room); return room; } @@ -1077,12 +1084,12 @@ static int digi_chars_in_buffer(struct tty_struct *tty) struct digi_port *priv = usb_get_serial_port_data(port); if (priv->dp_write_urb_in_use) { - dbg("digi_chars_in_buffer: port=%d, chars=%d", + dev_dbg(&port->dev, "digi_chars_in_buffer: port=%d, chars=%d\n", priv->dp_port_num, port->bulk_out_size - 2); /* return(port->bulk_out_size - 2); */ return 256; } else { - dbg("digi_chars_in_buffer: port=%d, chars=%d", + dev_dbg(&port->dev, "digi_chars_in_buffer: port=%d, chars=%d\n", priv->dp_port_num, priv->dp_out_buf_len); return priv->dp_out_buf_len; } @@ -1120,7 +1127,7 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port) ret = digi_write_oob_command(port, buf, 8, 1); if (ret != 0) - dbg("digi_open: write oob failed, ret=%d", ret); + dev_dbg(&port->dev, "digi_open: write oob failed, ret=%d\n", ret); /* set termios settings */ if (tty) { @@ -1180,7 +1187,7 @@ static void digi_close(struct usb_serial_port *port) ret = digi_write_oob_command(port, buf, 20, 0); if (ret != 0) - dbg("digi_close: write oob failed, ret=%d", ret); + dev_dbg(&port->dev, "digi_close: write oob failed, ret=%d\n", ret); /* wait for final commands on oob port to complete */ prepare_to_wait(&priv->dp_flush_wait, &wait, @@ -1448,9 +1455,9 @@ static int digi_read_inb_callback(struct urb *urb) tty_kref_put(tty); if (opcode == DIGI_CMD_RECEIVE_DISABLE) - dbg("%s: got RECEIVE_DISABLE", __func__); + dev_dbg(&port->dev, "%s: got RECEIVE_DISABLE\n", __func__); else if (opcode != DIGI_CMD_RECEIVE_DATA) - dbg("%s: unknown opcode: %d", __func__, opcode); + dev_dbg(&port->dev, "%s: unknown opcode: %d\n", __func__, opcode); return throttled ? 1 : 0; @@ -1484,7 +1491,7 @@ static int digi_read_oob_callback(struct urb *urb) status = ((unsigned char *)urb->transfer_buffer)[i++]; val = ((unsigned char *)urb->transfer_buffer)[i++]; - dbg("digi_read_oob_callback: opcode=%d, line=%d, status=%d, val=%d", + dev_dbg(&port->dev, "digi_read_oob_callback: opcode=%d, line=%d, status=%d, val=%d\n", opcode, line, status, val); if (status != 0 || line >= serial->type->num_ports) -- cgit v0.10.2 From bfc51614b389f5c7a05181accfef38ccdd66661e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 09:47:42 -0700 Subject: USB: serial: ftdi_sio.c: remove dbg() usage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. CC: Uwe Bonnes CC: Simon Arlott CC: Andrew Worsley CC: "Michał Wróbel" Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 29b81ad..5f8f172 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1043,11 +1043,12 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, unsigned int clear) { struct ftdi_private *priv = usb_get_serial_port_data(port); + struct device *dev = &port->dev; unsigned urb_value; int rv; if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) { - dbg("%s - DTR|RTS not being set|cleared", __func__); + dev_dbg(dev, "%s - DTR|RTS not being set|cleared\n", __func__); return 0; /* no change */ } @@ -1068,18 +1069,14 @@ static int update_mctrl(struct usb_serial_port *port, unsigned int set, urb_value, priv->interface, NULL, 0, WDR_TIMEOUT); if (rv < 0) { - dbg("%s Error from MODEM_CTRL urb: DTR %s, RTS %s", - __func__, - (set & TIOCM_DTR) ? "HIGH" : - (clear & TIOCM_DTR) ? "LOW" : "unchanged", - (set & TIOCM_RTS) ? "HIGH" : - (clear & TIOCM_RTS) ? "LOW" : "unchanged"); + dev_dbg(dev, "%s Error from MODEM_CTRL urb: DTR %s, RTS %s\n", + __func__, + (set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged", + (set & TIOCM_RTS) ? "HIGH" : (clear & TIOCM_RTS) ? "LOW" : "unchanged"); } else { - dbg("%s - DTR %s, RTS %s", __func__, - (set & TIOCM_DTR) ? "HIGH" : - (clear & TIOCM_DTR) ? "LOW" : "unchanged", - (set & TIOCM_RTS) ? "HIGH" : - (clear & TIOCM_RTS) ? "LOW" : "unchanged"); + dev_dbg(dev, "%s - DTR %s, RTS %s\n", __func__, + (set & TIOCM_DTR) ? "HIGH" : (clear & TIOCM_DTR) ? "LOW" : "unchanged", + (set & TIOCM_RTS) ? "HIGH" : (clear & TIOCM_RTS) ? "LOW" : "unchanged"); /* FIXME: locking on last_dtr_rts */ priv->last_dtr_rts = (priv->last_dtr_rts & ~clear) | set; } @@ -1091,6 +1088,7 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty, struct usb_serial_port *port) { struct ftdi_private *priv = usb_get_serial_port_data(port); + struct device *dev = &port->dev; __u32 div_value = 0; int div_okay = 1; int baud; @@ -1126,7 +1124,7 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty, alt_speed hack */ baud = tty_get_baud_rate(tty); - dbg("%s - tty_get_baud_rate reports speed %d", __func__, baud); + dev_dbg(dev, "%s - tty_get_baud_rate reports speed %d\n", __func__, baud); /* 2. Observe async-compatible custom_divisor hack, update baudrate if needed */ @@ -1135,8 +1133,8 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty, ((priv->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST) && (priv->custom_divisor)) { baud = priv->baud_base / priv->custom_divisor; - dbg("%s - custom divisor %d sets baud rate to %d", - __func__, priv->custom_divisor, baud); + dev_dbg(dev, "%s - custom divisor %d sets baud rate to %d\n", + __func__, priv->custom_divisor, baud); } /* 3. Convert baudrate to device-specific divisor */ @@ -1158,8 +1156,8 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty, case 115200: div_value = ftdi_sio_b115200; break; } /* baud */ if (div_value == 0) { - dbg("%s - Baudrate (%d) requested is not supported", - __func__, baud); + dev_dbg(dev, "%s - Baudrate (%d) requested is not supported\n", + __func__, baud); div_value = ftdi_sio_b9600; baud = 9600; div_okay = 0; @@ -1169,7 +1167,7 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty, if (baud <= 3000000) { div_value = ftdi_232am_baud_to_divisor(baud); } else { - dbg("%s - Baud rate too high!", __func__); + dev_dbg(dev, "%s - Baud rate too high!\n", __func__); baud = 9600; div_value = ftdi_232am_baud_to_divisor(9600); div_okay = 0; @@ -1192,7 +1190,7 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty, } div_value = ftdi_232bm_baud_to_divisor(baud); } else { - dbg("%s - Baud rate too high!", __func__); + dev_dbg(dev, "%s - Baud rate too high!\n", __func__); div_value = ftdi_232bm_baud_to_divisor(9600); div_okay = 0; baud = 9600; @@ -1206,7 +1204,7 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty, } else if (baud < 1200) { div_value = ftdi_232bm_baud_to_divisor(baud); } else { - dbg("%s - Baud rate too high!", __func__); + dev_dbg(dev, "%s - Baud rate too high!\n", __func__); div_value = ftdi_232bm_baud_to_divisor(9600); div_okay = 0; baud = 9600; @@ -1215,7 +1213,7 @@ static __u32 get_ftdi_divisor(struct tty_struct *tty, } /* priv->chip_type */ if (div_okay) { - dbg("%s - Baud rate set to %d (divisor 0x%lX) on chip %s", + dev_dbg(dev, "%s - Baud rate set to %d (divisor 0x%lX) on chip %s\n", __func__, baud, (unsigned long)div_value, ftdi_chip_name[priv->chip_type]); } @@ -1261,7 +1259,7 @@ static int write_latency_timer(struct usb_serial_port *port) if (priv->flags & ASYNC_LOW_LATENCY) l = 1; - dbg("%s: setting latency timer = %i", __func__, l); + dev_dbg(&port->dev, "%s: setting latency timer = %i\n", __func__, l); rv = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), @@ -1416,8 +1414,8 @@ static void ftdi_determine_type(struct usb_serial_port *port) version = le16_to_cpu(udev->descriptor.bcdDevice); interfaces = udev->actconfig->desc.bNumInterfaces; - dbg("%s: bcdDevice = 0x%x, bNumInterfaces = %u", __func__, - version, interfaces); + dev_dbg(&port->dev, "%s: bcdDevice = 0x%x, bNumInterfaces = %u\n", __func__, + version, interfaces); if (interfaces > 1) { int inter; @@ -1447,8 +1445,9 @@ static void ftdi_determine_type(struct usb_serial_port *port) /* BM-type devices have a bug where bcdDevice gets set * to 0x200 when iSerialNumber is 0. */ if (version < 0x500) { - dbg("%s: something fishy - bcdDevice too low for multi-interface device", - __func__); + dev_dbg(&port->dev, + "%s: something fishy - bcdDevice too low for multi-interface device\n", + __func__); } } else if (version < 0x200) { /* Old device. Assume it's the original SIO. */ @@ -1562,7 +1561,7 @@ static ssize_t store_event_char(struct device *dev, int v = simple_strtoul(valbuf, NULL, 10); int rv; - dbg("%s: setting event char = %i", __func__, v); + dev_dbg(&port->dev, "%s: setting event char = %i\n", __func__, v); rv = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), @@ -1571,7 +1570,7 @@ static ssize_t store_event_char(struct device *dev, v, priv->interface, NULL, 0, WDR_TIMEOUT); if (rv < 0) { - dbg("Unable to write event character: %i", rv); + dev_dbg(&port->dev, "Unable to write event character: %i\n", rv); return -EIO; } @@ -1590,7 +1589,7 @@ static int create_sysfs_attrs(struct usb_serial_port *port) /* XXX I've no idea if the original SIO supports the event_char * sysfs parameter, so I'm playing it safe. */ if (priv->chip_type != SIO) { - dbg("sysfs attributes for %s", ftdi_chip_name[priv->chip_type]); + dev_dbg(&port->dev, "sysfs attributes for %s\n", ftdi_chip_name[priv->chip_type]); retval = device_create_file(&port->dev, &dev_attr_event_char); if ((!retval) && (priv->chip_type == FT232BM || @@ -1730,8 +1729,8 @@ static int ftdi_NDI_device_setup(struct usb_serial *serial) if (latency > 99) latency = 99; - dbg("%s setting NDI device latency to %d", __func__, latency); - dev_info(&udev->dev, "NDI device with a latency value of %d", latency); + dev_dbg(&udev->dev, "%s setting NDI device latency to %d\n", __func__, latency); + dev_info(&udev->dev, "NDI device with a latency value of %d\n", latency); /* FIXME: errors are not returned */ usb_control_msg(udev, usb_sndctrlpipe(udev, 0), @@ -1949,7 +1948,7 @@ static int ftdi_process_packet(struct tty_struct *tty, char *ch; if (len < 2) { - dbg("malformed packet"); + dev_dbg(&port->dev, "malformed packet\n"); return 0; } @@ -2064,12 +2063,12 @@ static void ftdi_break_ctl(struct tty_struct *tty, int break_state) FTDI_SIO_SET_DATA_REQUEST_TYPE, urb_value , priv->interface, NULL, 0, WDR_TIMEOUT) < 0) { - dev_err(&port->dev, "%s FAILED to enable/disable break state " - "(state was %d)\n", __func__, break_state); + dev_err(&port->dev, "%s FAILED to enable/disable break state (state was %d)\n", + __func__, break_state); } - dbg("%s break state is %d - urb is %d", __func__, - break_state, urb_value); + dev_dbg(&port->dev, "%s break state is %d - urb is %d\n", __func__, + break_state, urb_value); } @@ -2081,6 +2080,7 @@ static void ftdi_set_termios(struct tty_struct *tty, struct usb_serial_port *port, struct ktermios *old_termios) { struct usb_device *dev = port->serial->dev; + struct device *ddev = &port->dev; struct ftdi_private *priv = usb_get_serial_port_data(port); struct ktermios *termios = tty->termios; unsigned int cflag = termios->c_cflag; @@ -2094,14 +2094,14 @@ static void ftdi_set_termios(struct tty_struct *tty, /* Force baud rate if this device requires it, unless it is set to B0. */ if (priv->force_baud && ((termios->c_cflag & CBAUD) != B0)) { - dbg("%s: forcing baud rate for this device", __func__); + dev_dbg(ddev, "%s: forcing baud rate for this device\n", __func__); tty_encode_baud_rate(tty, priv->force_baud, priv->force_baud); } /* Force RTS-CTS if this device requires it. */ if (priv->force_rtscts) { - dbg("%s: forcing rtscts for this device", __func__); + dev_dbg(ddev, "%s: forcing rtscts for this device\n", __func__); termios->c_cflag |= CRTSCTS; } @@ -2143,10 +2143,16 @@ no_skip: } if (cflag & CSIZE) { switch (cflag & CSIZE) { - case CS7: urb_value |= 7; dbg("Setting CS7"); break; - case CS8: urb_value |= 8; dbg("Setting CS8"); break; + case CS7: + urb_value |= 7; + dev_dbg(ddev, "Setting CS7\n"); + break; + case CS8: + urb_value |= 8; + dev_dbg(ddev, "Setting CS8\n"); + break; default: - dev_err(&port->dev, "CSIZE was set but not CS7-CS8\n"); + dev_err(ddev, "CSIZE was set but not CS7-CS8\n"); } } @@ -2159,8 +2165,8 @@ no_skip: FTDI_SIO_SET_DATA_REQUEST_TYPE, urb_value , priv->interface, NULL, 0, WDR_SHORT_TIMEOUT) < 0) { - dev_err(&port->dev, "%s FAILED to set " - "databits/stopbits/parity\n", __func__); + dev_err(ddev, "%s FAILED to set databits/stopbits/parity\n", + __func__); } /* Now do the baudrate */ @@ -2172,8 +2178,7 @@ no_data_parity_stop_changes: FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 0, priv->interface, NULL, 0, WDR_TIMEOUT) < 0) { - dev_err(&port->dev, - "%s error from disable flowcontrol urb\n", + dev_err(ddev, "%s error from disable flowcontrol urb\n", __func__); } /* Drop RTS and DTR */ @@ -2182,8 +2187,7 @@ no_data_parity_stop_changes: /* set the baudrate determined before */ mutex_lock(&priv->cfg_lock); if (change_speed(tty, port)) - dev_err(&port->dev, "%s urb failed to set baudrate\n", - __func__); + dev_err(ddev, "%s urb failed to set baudrate\n", __func__); mutex_unlock(&priv->cfg_lock); /* Ensure RTS and DTR are raised when baudrate changed from 0 */ if (!old_termios || (old_termios->c_cflag & CBAUD) == B0) @@ -2194,17 +2198,15 @@ no_data_parity_stop_changes: /* Note device also supports DTR/CD (ugh) and Xon/Xoff in hardware */ no_c_cflag_changes: if (cflag & CRTSCTS) { - dbg("%s Setting to CRTSCTS flow control", __func__); + dev_dbg(ddev, "%s Setting to CRTSCTS flow control\n", __func__); if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 0 , (FTDI_SIO_RTS_CTS_HS | priv->interface), NULL, 0, WDR_TIMEOUT) < 0) { - dev_err(&port->dev, - "urb failed to set to rts/cts flow control\n"); + dev_err(ddev, "urb failed to set to rts/cts flow control\n"); } - } else { /* * Xon/Xoff code @@ -2214,8 +2216,8 @@ no_c_cflag_changes: * code is executed. */ if (iflag & IXOFF) { - dbg("%s request to enable xonxoff iflag=%04x", - __func__, iflag); + dev_dbg(ddev, "%s request to enable xonxoff iflag=%04x\n", + __func__, iflag); /* Try to enable the XON/XOFF on the ftdi_sio * Set the vstart and vstop -- could have been done up * above where a lot of other dereferencing is done but @@ -2240,18 +2242,16 @@ no_c_cflag_changes: /* else clause to only run if cflag ! CRTSCTS and iflag * ! XOFF. CHECKME Assuming XON/XOFF handled by tty * stack - not by device */ - dbg("%s Turning off hardware flow control", __func__); + dev_dbg(ddev, "%s Turning off hardware flow control\n", __func__); if (usb_control_msg(dev, usb_sndctrlpipe(dev, 0), FTDI_SIO_SET_FLOW_CTRL_REQUEST, FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, 0, priv->interface, NULL, 0, WDR_TIMEOUT) < 0) { - dev_err(&port->dev, - "urb failed to clear flow control\n"); + dev_err(ddev, "urb failed to clear flow control\n"); } } - } } @@ -2345,7 +2345,7 @@ static int ftdi_ioctl(struct tty_struct *tty, struct async_icount cnow; struct async_icount cprev; - dbg("%s cmd 0x%04x", __func__, cmd); + dev_dbg(&port->dev, "%s cmd 0x%04x\n", __func__, cmd); /* Based on code from acm.c and others */ switch (cmd) { @@ -2393,7 +2393,8 @@ static int ftdi_ioctl(struct tty_struct *tty, /* This is not necessarily an error - turns out the higher layers * will do some ioctls themselves (see comment above) */ - dbg("%s arg not supported - it was 0x%04x - check /usr/include/asm/ioctls.h", __func__, cmd); + dev_dbg(&port->dev, "%s arg not supported - it was 0x%04x - check /usr/include/asm/ioctls.h\n", + __func__, cmd); return -ENOIOCTLCMD; } -- cgit v0.10.2 From 1ad7604f69ae3c735e7537971f62b26e3807c18a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 09:47:43 -0700 Subject: USB: serial: kl5kusb105.c: remove dbg() usage dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. CC: Oliver Neukum Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 5bed59c..73e0a23 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -239,7 +239,9 @@ static int klsi_105_startup(struct usb_serial *serial) priv = kmalloc(sizeof(struct klsi_105_private), GFP_KERNEL); if (!priv) { - dbg("%skmalloc for klsi_105_private failed.", __func__); + dev_dbg(&serial->interface->dev, + "%s - kmalloc for klsi_105_private failed.\n", + __func__); i--; goto err_cleanup; } @@ -344,14 +346,14 @@ static int klsi_105_open(struct tty_struct *tty, struct usb_serial_port *port) dev_err(&port->dev, "Enabling read failed (error = %d)\n", rc); retval = rc; } else - dbg("%s - enabled reading", __func__); + dev_dbg(&port->dev, "%s - enabled reading\n", __func__); rc = klsi_105_get_line_state(port, &line_state); if (rc >= 0) { spin_lock_irqsave(&priv->lock, flags); priv->line_state = line_state; spin_unlock_irqrestore(&priv->lock, flags); - dbg("%s - read line state 0x%lx", __func__, line_state); + dev_dbg(&port->dev, "%s - read line state 0x%lx\n", __func__, line_state); retval = 0; } else retval = rc; @@ -421,7 +423,7 @@ static void klsi_105_process_read_urb(struct urb *urb) return; if (urb->actual_length <= KLSI_HDR_LEN) { - dbg("%s - malformed packet", __func__); + dev_dbg(&port->dev, "%s - malformed packet\n", __func__); return; } @@ -431,7 +433,7 @@ static void klsi_105_process_read_urb(struct urb *urb) len = get_unaligned_le16(data); if (len > urb->actual_length - KLSI_HDR_LEN) { - dbg("%s - packet length mismatch", __func__); + dev_dbg(&port->dev, "%s - packet length mismatch\n", __func__); len = urb->actual_length - KLSI_HDR_LEN; } @@ -445,6 +447,7 @@ static void klsi_105_set_termios(struct tty_struct *tty, struct ktermios *old_termios) { struct klsi_105_private *priv = usb_get_serial_port_data(port); + struct device *dev = &port->dev; unsigned int iflag = tty->termios->c_iflag; unsigned int old_iflag = old_termios->c_iflag; unsigned int cflag = tty->termios->c_cflag; @@ -455,8 +458,7 @@ static void klsi_105_set_termios(struct tty_struct *tty, cfg = kmalloc(sizeof(*cfg), GFP_KERNEL); if (!cfg) { - dev_err(&port->dev, "%s - out of memory for config buffer.\n", - __func__); + dev_err(dev, "%s - out of memory for config buffer.\n", __func__); return; } @@ -471,7 +473,7 @@ static void klsi_105_set_termios(struct tty_struct *tty, if ((cflag & CBAUD) != (old_cflag & CBAUD)) { /* reassert DTR and (maybe) RTS on transition from B0 */ if ((old_cflag & CBAUD) == B0) { - dbg("%s: baud was B0", __func__); + dev_dbg(dev, "%s: baud was B0\n", __func__); #if 0 priv->control_state |= TIOCM_DTR; /* don't set RTS if using hardware flow control */ @@ -509,14 +511,13 @@ static void klsi_105_set_termios(struct tty_struct *tty, priv->cfg.baudrate = kl5kusb105a_sio_b115200; break; default: - dbg("KLSI USB->Serial converter:" - " unsupported baudrate request, using default of 9600"); - priv->cfg.baudrate = kl5kusb105a_sio_b9600; + dev_dbg(dev, "KLSI USB->Serial converter: unsupported baudrate request, using default of 9600"); + priv->cfg.baudrate = kl5kusb105a_sio_b9600; baud = 9600; break; } if ((cflag & CBAUD) == B0) { - dbg("%s: baud is B0", __func__); + dev_dbg(dev, "%s: baud is B0\n", __func__); /* Drop RTS and DTR */ /* maybe this should be simulated by sending read * disable and read enable messages? @@ -533,11 +534,11 @@ static void klsi_105_set_termios(struct tty_struct *tty, /* set the number of data bits */ switch (cflag & CSIZE) { case CS5: - dbg("%s - 5 bits/byte not supported", __func__); + dev_dbg(dev, "%s - 5 bits/byte not supported\n", __func__); spin_unlock_irqrestore(&priv->lock, flags); goto err; case CS6: - dbg("%s - 6 bits/byte not supported", __func__); + dev_dbg(dev, "%s - 6 bits/byte not supported\n", __func__); spin_unlock_irqrestore(&priv->lock, flags); goto err; case CS7: @@ -547,8 +548,7 @@ static void klsi_105_set_termios(struct tty_struct *tty, priv->cfg.databits = kl5kusb105a_dtb_8; break; default: - dev_err(&port->dev, - "CSIZE was not CS5-CS8, using default of 8\n"); + dev_err(dev, "CSIZE was not CS5-CS8, using default of 8\n"); priv->cfg.databits = kl5kusb105a_dtb_8; break; } @@ -616,7 +616,7 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state) (struct mct_u232_private *)port->private; unsigned char lcr = priv->last_lcr; - dbg("%sstate=%d", __func__, break_state); + dev_dbg(&port->dev, "%s - state=%d\n", __func__, break_state); /* LOCKING */ if (break_state) @@ -645,7 +645,7 @@ static int klsi_105_tiocmget(struct tty_struct *tty) spin_lock_irqsave(&priv->lock, flags); priv->line_state = line_state; spin_unlock_irqrestore(&priv->lock, flags); - dbg("%s - read line state 0x%lx", __func__, line_state); + dev_dbg(&port->dev, "%s - read line state 0x%lx\n", __func__, line_state); return (int)line_state; } -- cgit v0.10.2 From 7065e8267bfaac4fb43caaa81a4e2b5660f7c1f0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 11:50:30 -0700 Subject: USB: serial: garmin_gps.c: remove dbg() usage dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. CC: Johan Hovold CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 346c15a..11029df 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -303,8 +303,9 @@ static int pkt_add(struct garmin_data *garmin_data_p, state = garmin_data_p->state; spin_unlock_irqrestore(&garmin_data_p->lock, flags); - dbg("%s - added: pkt: %d - %d bytes", - __func__, pkt->seq, data_length); + dev_dbg(&garmin_data_p->port->dev, + "%s - added: pkt: %d - %d bytes\n", __func__, + pkt->seq, data_length); /* in serial mode, if someone is waiting for data from the device, convert and send the next packet to tty. */ @@ -359,7 +360,8 @@ static int gsp_send_ack(struct garmin_data *garmin_data_p, __u8 pkt_id) __u8 *ptr = pkt; unsigned l = 0; - dbg("%s - pkt-id: 0x%X.", __func__, 0xFF & pkt_id); + dev_dbg(&garmin_data_p->port->dev, "%s - pkt-id: 0x%X.\n", __func__, + 0xFF & pkt_id); *ptr++ = DLE; *ptr++ = ACK; @@ -399,10 +401,10 @@ static int gsp_send_ack(struct garmin_data *garmin_data_p, __u8 pkt_id) */ static int gsp_rec_packet(struct garmin_data *garmin_data_p, int count) { + struct device *dev = &garmin_data_p->port->dev; unsigned long flags; const __u8 *recpkt = garmin_data_p->inbuffer+GSP_INITIAL_OFFSET; __le32 *usbdata = (__le32 *) garmin_data_p->inbuffer; - int cksum = 0; int n = 0; int pktid = recpkt[0]; @@ -412,7 +414,7 @@ static int gsp_rec_packet(struct garmin_data *garmin_data_p, int count) __func__, count-GSP_INITIAL_OFFSET, recpkt); if (size != (count-GSP_INITIAL_OFFSET-3)) { - dbg("%s - invalid size, expected %d bytes, got %d", + dev_dbg(dev, "%s - invalid size, expected %d bytes, got %d\n", __func__, size, (count-GSP_INITIAL_OFFSET-3)); return -EINVPKT; } @@ -422,8 +424,8 @@ static int gsp_rec_packet(struct garmin_data *garmin_data_p, int count) /* sanity check, remove after test ... */ if ((__u8 *)&(usbdata[3]) != recpkt) { - dbg("%s - ptr mismatch %p - %p", - __func__, &(usbdata[4]), recpkt); + dev_dbg(dev, "%s - ptr mismatch %p - %p\n", __func__, + &(usbdata[4]), recpkt); return -EINVPKT; } @@ -433,7 +435,7 @@ static int gsp_rec_packet(struct garmin_data *garmin_data_p, int count) } if ((0xff & (cksum + *recpkt)) != 0) { - dbg("%s - invalid checksum, expected %02x, got %02x", + dev_dbg(dev, "%s - invalid checksum, expected %02x, got %02x\n", __func__, 0xff & -cksum, 0xff & *recpkt); return -EINVPKT; } @@ -480,6 +482,7 @@ static int gsp_rec_packet(struct garmin_data *garmin_data_p, int count) static int gsp_receive(struct garmin_data *garmin_data_p, const unsigned char *buf, int count) { + struct device *dev = &garmin_data_p->port->dev; unsigned long flags; int offs = 0; int ack_or_nak_seen = 0; @@ -500,7 +503,7 @@ static int gsp_receive(struct garmin_data *garmin_data_p, skip = garmin_data_p->flags & FLAGS_GSP_SKIP; spin_unlock_irqrestore(&garmin_data_p->lock, flags); - /* dbg("%s - dle=%d skip=%d size=%d count=%d", + /* dev_dbg(dev, "%s - dle=%d skip=%d size=%d count=%d\n", __func__, dleSeen, skip, size, count); */ if (size == 0) @@ -530,12 +533,12 @@ static int gsp_receive(struct garmin_data *garmin_data_p, if (data == ACK) { ack_or_nak_seen = ACK; - dbg("ACK packet complete."); + dev_dbg(dev, "ACK packet complete.\n"); } else if (data == NAK) { ack_or_nak_seen = NAK; - dbg("NAK packet complete."); + dev_dbg(dev, "NAK packet complete.\n"); } else { - dbg("packet complete - id=0x%X.", + dev_dbg(dev, "packet complete - id=0x%X.\n", 0xFF & data); gsp_rec_packet(garmin_data_p, size); } @@ -557,7 +560,7 @@ static int gsp_receive(struct garmin_data *garmin_data_p, } if (size >= GPS_IN_BUFSIZ) { - dbg("%s - packet too large.", __func__); + dev_dbg(dev, "%s - packet too large.\n", __func__); skip = 1; size = GSP_INITIAL_OFFSET; dleSeen = 0; @@ -602,6 +605,7 @@ static int gsp_receive(struct garmin_data *garmin_data_p, static int gsp_send(struct garmin_data *garmin_data_p, const unsigned char *buf, int count) { + struct device *dev = &garmin_data_p->port->dev; const unsigned char *src; unsigned char *dst; int pktid = 0; @@ -610,12 +614,12 @@ static int gsp_send(struct garmin_data *garmin_data_p, int i = 0; int k; - dbg("%s - state %d - %d bytes.", __func__, - garmin_data_p->state, count); + dev_dbg(dev, "%s - state %d - %d bytes.\n", __func__, + garmin_data_p->state, count); k = garmin_data_p->outsize; if ((k+count) > GPS_OUT_BUFSIZ) { - dbg("packet too large"); + dev_dbg(dev, "packet too large\n"); garmin_data_p->outsize = 0; return -4; } @@ -634,7 +638,7 @@ static int gsp_send(struct garmin_data *garmin_data_p, return 0; } - dbg("%s - %d bytes in buffer, %d bytes in pkt.", __func__, k, i); + dev_dbg(dev, "%s - %d bytes in buffer, %d bytes in pkt.\n", __func__, k, i); /* garmin_data_p->outbuffer now contains a complete packet */ @@ -644,18 +648,18 @@ static int gsp_send(struct garmin_data *garmin_data_p, garmin_data_p->outsize = 0; if (GARMIN_LAYERID_APPL != getLayerId(garmin_data_p->outbuffer)) { - dbg("not an application packet (%d)", + dev_dbg(dev, "not an application packet (%d)\n", getLayerId(garmin_data_p->outbuffer)); return -1; } if (pktid > 255) { - dbg("packet-id %d too large", pktid); + dev_dbg(dev, "packet-id %d too large\n", pktid); return -2; } if (datalen > 255) { - dbg("packet-size %d too large", datalen); + dev_dbg(dev, "packet-size %d too large\n", datalen); return -3; } @@ -722,7 +726,7 @@ static int gsp_next_packet(struct garmin_data *garmin_data_p) struct garmin_packet *pkt = NULL; while ((pkt = pkt_pop(garmin_data_p)) != NULL) { - dbg("%s - next pkt: %d", __func__, pkt->seq); + dev_dbg(&garmin_data_p->port->dev, "%s - next pkt: %d\n", __func__, pkt->seq); result = gsp_send(garmin_data_p, pkt->data, pkt->size); if (result > 0) { kfree(pkt); @@ -768,7 +772,9 @@ static int nat_receive(struct garmin_data *garmin_data_p, if (len >= GPS_IN_BUFSIZ) { /* seems to be an invalid packet, ignore rest of input */ - dbg("%s - packet size too large: %d", __func__, len); + dev_dbg(&garmin_data_p->port->dev, + "%s - packet size too large: %d\n", + __func__, len); garmin_data_p->insize = 0; count = 0; result = -EINVPKT; @@ -849,10 +855,10 @@ static int process_resetdev_request(struct usb_serial_port *port) spin_unlock_irqrestore(&garmin_data_p->lock, flags); usb_kill_urb(port->interrupt_in_urb); - dbg("%s - usb_reset_device", __func__); + dev_dbg(&port->dev, "%s - usb_reset_device\n", __func__); status = usb_reset_device(port->serial->dev); if (status) - dbg("%s - usb_reset_device failed: %d", + dev_dbg(&port->dev, "%s - usb_reset_device failed: %d\n", __func__, status); return status; } @@ -889,7 +895,7 @@ static int garmin_init_session(struct usb_serial_port *port) if (status == 0) { usb_kill_urb(port->interrupt_in_urb); - dbg("%s - adding interrupt input", __func__); + dev_dbg(&serial->dev->dev, "%s - adding interrupt input\n", __func__); status = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (status) dev_err(&serial->dev->dev, @@ -902,7 +908,7 @@ static int garmin_init_session(struct usb_serial_port *port) * gpsbabel/jeeps/gpslibusb.c gusb_reset_toggles() */ if (status == 0) { - dbg("%s - starting session ...", __func__); + dev_dbg(&serial->dev->dev, "%s - starting session ...\n", __func__); garmin_data_p->state = STATE_ACTIVE; for (i = 0; i < 3; i++) { @@ -952,8 +958,8 @@ static void garmin_close(struct usb_serial_port *port) struct usb_serial *serial = port->serial; struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); - dbg("%s - port %d - mode=%d state=%d flags=0x%X", __func__, - port->number, garmin_data_p->mode, + dev_dbg(&port->dev, "%s - port %d - mode=%d state=%d flags=0x%X\n", + __func__, port->number, garmin_data_p->mode, garmin_data_p->state, garmin_data_p->flags); if (!serial) @@ -1073,11 +1079,12 @@ static int garmin_write_bulk(struct usb_serial_port *port, static int garmin_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count) { + struct device *dev = &port->dev; int pktid, pktsiz, len; struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); __le32 *privpkt = (__le32 *)garmin_data_p->privpkt; - usb_serial_debug_data(debug, &port->dev, __func__, count, buf); + usb_serial_debug_data(debug, dev, __func__, count, buf); if (garmin_data_p->state == STATE_RESET) return -EIO; @@ -1097,7 +1104,7 @@ static int garmin_write(struct tty_struct *tty, struct usb_serial_port *port, && GARMIN_LAYERID_PRIVATE == getLayerId(garmin_data_p->privpkt)) { - dbg("%s - processing private request %d", + dev_dbg(dev, "%s - processing private request %d\n", __func__, pktid); /* drop all unfinished transfers */ @@ -1109,7 +1116,7 @@ static int garmin_write(struct tty_struct *tty, struct usb_serial_port *port, if (pktsiz != 4) return -EINVPKT; debug = __le32_to_cpu(privpkt[3]); - dbg("%s - debug level set to 0x%X", + dev_dbg(dev, "%s - debug level set to 0x%X\n", __func__, debug); break; @@ -1117,7 +1124,7 @@ static int garmin_write(struct tty_struct *tty, struct usb_serial_port *port, if (pktsiz != 4) return -EINVPKT; garmin_data_p->mode = __le32_to_cpu(privpkt[3]); - dbg("%s - mode set to %d", + dev_dbg(dev, "%s - mode set to %d\n", __func__, garmin_data_p->mode); break; @@ -1133,7 +1140,7 @@ static int garmin_write(struct tty_struct *tty, struct usb_serial_port *port, if (pktsiz != 4) return -EINVPKT; initial_mode = __le32_to_cpu(privpkt[3]); - dbg("%s - initial_mode set to %d", + dev_dbg(dev, "%s - initial_mode set to %d\n", __func__, garmin_data_p->mode); break; @@ -1169,7 +1176,7 @@ static void garmin_read_process(struct garmin_data *garmin_data_p, if (garmin_data_p->flags & FLAGS_DROP_DATA) { /* abort-transfer cmd is actice */ - dbg("%s - pkt dropped", __func__); + dev_dbg(&garmin_data_p->port->dev, "%s - pkt dropped\n", __func__); } else if (garmin_data_p->state != STATE_DISCONNECTED && garmin_data_p->state != STATE_RESET) { @@ -1178,7 +1185,7 @@ static void garmin_read_process(struct garmin_data *garmin_data_p, send it directly to the tty port */ if (garmin_data_p->flags & FLAGS_QUEUING) { pkt_add(garmin_data_p, data, data_length); - } else if (bulk_data || + } else if (bulk_data || getLayerId(data) == GARMIN_LAYERID_APPL) { spin_lock_irqsave(&garmin_data_p->lock, flags); @@ -1208,12 +1215,12 @@ static void garmin_read_bulk_callback(struct urb *urb) int retval; if (!serial) { - dbg("%s - bad serial pointer, exiting", __func__); + dev_dbg(&urb->dev->dev, "%s - bad serial pointer, exiting\n", __func__); return; } if (status) { - dbg("%s - nonzero read bulk status received: %d", + dev_dbg(&urb->dev->dev, "%s - nonzero read bulk status received: %d\n", __func__, status); return; } @@ -1239,11 +1246,11 @@ static void garmin_read_bulk_callback(struct urb *urb) retval = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (retval) dev_err(&port->dev, - "%s - failed resubmitting read urb, " - "error %d\n", __func__, retval); + "%s - failed resubmitting read urb, error %d\n", + __func__, retval); } } else { - dbg("%s - end of bulk data", __func__); + dev_dbg(&port->dev, "%s - end of bulk data\n", __func__); spin_lock_irqsave(&garmin_data_p->lock, flags); garmin_data_p->flags &= ~FLAGS_BULK_IN_ACTIVE; spin_unlock_irqrestore(&garmin_data_p->lock, flags); @@ -1268,11 +1275,11 @@ static void garmin_read_int_callback(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", + dev_dbg(&urb->dev->dev, "%s - urb shutting down with status: %d\n", __func__, status); return; default: - dbg("%s - nonzero urb status received: %d", + dev_dbg(&urb->dev->dev, "%s - nonzero urb status received: %d\n", __func__, status); return; } @@ -1284,7 +1291,7 @@ static void garmin_read_int_callback(struct urb *urb) 0 == memcmp(data, GARMIN_BULK_IN_AVAIL_REPLY, sizeof(GARMIN_BULK_IN_AVAIL_REPLY))) { - dbg("%s - bulk data available.", __func__); + dev_dbg(&port->dev, "%s - bulk data available.\n", __func__); if (0 == (garmin_data_p->flags & FLAGS_BULK_IN_ACTIVE)) { @@ -1319,7 +1326,7 @@ static void garmin_read_int_callback(struct urb *urb) garmin_data_p->serial_num = __le32_to_cpup( (__le32 *)(data+GARMIN_PKTHDR_LENGTH)); - dbg("%s - start-of-session reply seen - serial %u.", + dev_dbg(&port->dev, "%s - start-of-session reply seen - serial %u.\n", __func__, garmin_data_p->serial_num); } -- cgit v0.10.2 From 8c8e87bc23acb4e9ed42c3d1b1d9fbf42f368ea2 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 11:50:32 -0700 Subject: USB: serial: oti6858.c: remove dbg() usage dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. CC: Johan Hovold CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index 5976b65..e91a774 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -256,11 +256,11 @@ static void setup_line(struct work_struct *work) priv->setup_done = 1; spin_unlock_irqrestore(&priv->lock, flags); - dbg("%s(): submitting interrupt urb", __func__); + dev_dbg(&port->dev, "%s(): submitting interrupt urb\n", __func__); result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (result != 0) { - dev_err(&port->dev, "%s(): usb_submit_urb() failed" - " with error %d\n", __func__, result); + dev_err(&port->dev, "%s(): usb_submit_urb() failed with error %d\n", + __func__, result); } } @@ -310,11 +310,11 @@ static void send_data(struct work_struct *work) if (count == 0) { priv->flags.write_urb_in_use = 0; - dbg("%s(): submitting interrupt urb", __func__); + dev_dbg(&port->dev, "%s(): submitting interrupt urb\n", __func__); result = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO); if (result != 0) { - dev_err(&port->dev, "%s(): usb_submit_urb() failed" - " with error %d\n", __func__, result); + dev_err(&port->dev, "%s(): usb_submit_urb() failed with error %d\n", + __func__, result); } return; } @@ -325,8 +325,8 @@ static void send_data(struct work_struct *work) port->write_urb->transfer_buffer_length = count; result = usb_submit_urb(port->write_urb, GFP_NOIO); if (result != 0) { - dev_err_console(port, "%s(): usb_submit_urb() failed" - " with error %d\n", __func__, result); + dev_err_console(port, "%s(): usb_submit_urb() failed with error %d\n", + __func__, result); priv->flags.write_urb_in_use = 0; } @@ -420,10 +420,8 @@ static void oti6858_set_termios(struct tty_struct *tty, __le16 divisor; int br; - if (!tty) { - dbg("%s(): no tty structures", __func__); + if (!tty) return; - } cflag = tty->termios->c_cflag; @@ -560,11 +558,11 @@ static int oti6858_open(struct tty_struct *tty, struct usb_serial_port *port) spin_unlock_irqrestore(&priv->lock, flags); kfree(buf); - dbg("%s(): submitting interrupt urb", __func__); + dev_dbg(&port->dev, "%s(): submitting interrupt urb\n", __func__); result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (result != 0) { - dev_err(&port->dev, "%s(): usb_submit_urb() failed" - " with error %d\n", __func__, result); + dev_err(&port->dev, "%s(): usb_submit_urb() failed with error %d\n", + __func__, result); oti6858_close(port); return result; } @@ -586,14 +584,14 @@ static void oti6858_close(struct usb_serial_port *port) kfifo_reset_out(&port->write_fifo); spin_unlock_irqrestore(&port->lock, flags); - dbg("%s(): after buf_clear()", __func__); + dev_dbg(&port->dev, "%s(): after buf_clear()\n", __func__); /* cancel scheduled setup */ cancel_delayed_work_sync(&priv->delayed_setup_work); cancel_delayed_work_sync(&priv->delayed_write_work); /* shutdown our urbs */ - dbg("%s(): shutting down urbs", __func__); + dev_dbg(&port->dev, "%s(): shutting down urbs\n", __func__); usb_kill_urb(port->write_urb); usb_kill_urb(port->read_urb); usb_kill_urb(port->interrupt_in_urb); @@ -607,8 +605,8 @@ static int oti6858_tiocmset(struct tty_struct *tty, unsigned long flags; u8 control; - dbg("%s(port = %d, set = 0x%08x, clear = 0x%08x)", - __func__, port->number, set, clear); + dev_dbg(&port->dev, "%s(set = 0x%08x, clear = 0x%08x)\n", + __func__, set, clear); /* FIXME: check if this is correct (active high/low) */ spin_lock_irqsave(&priv->lock, flags); @@ -655,7 +653,7 @@ static int oti6858_tiocmget(struct tty_struct *tty) if ((pin_state & PIN_DCD) != 0) result |= TIOCM_CD; - dbg("%s() = 0x%08x", __func__, result); + dev_dbg(&port->dev, "%s() = 0x%08x\n", __func__, result); return result; } @@ -700,15 +698,14 @@ static int oti6858_ioctl(struct tty_struct *tty, { struct usb_serial_port *port = tty->driver_data; - dbg("%s(port = %d, cmd = 0x%04x, arg = 0x%08lx)", - __func__, port->number, cmd, arg); + dev_dbg(&port->dev, "%s(cmd = 0x%04x, arg = 0x%08lx)\n", __func__, cmd, arg); switch (cmd) { case TIOCMIWAIT: - dbg("%s(): TIOCMIWAIT", __func__); + dev_dbg(&port->dev, "%s(): TIOCMIWAIT\n", __func__); return wait_modem_info(port, arg); default: - dbg("%s(): 0x%04x not supported", __func__, cmd); + dev_dbg(&port->dev, "%s(): 0x%04x not supported\n", __func__, cmd); break; } return -ENOIOCTLCMD; @@ -738,12 +735,12 @@ static void oti6858_read_int_callback(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s(): urb shutting down with status: %d", - __func__, status); + dev_dbg(&urb->dev->dev, "%s(): urb shutting down with status: %d\n", + __func__, status); return; default: - dbg("%s(): nonzero urb status received: %d", - __func__, status); + dev_dbg(&urb->dev->dev, "%s(): nonzero urb status received: %d\n", + __func__, status); break; } @@ -759,8 +756,7 @@ static void oti6858_read_int_callback(struct urb *urb) priv->transient = 4; priv->setup_done = 0; resubmit = 0; - dbg("%s(): scheduling setup_line()", - __func__); + dev_dbg(&port->dev, "%s(): scheduling setup_line()\n", __func__); schedule_delayed_work(&priv->delayed_setup_work, 0); } } @@ -774,8 +770,7 @@ static void oti6858_read_int_callback(struct urb *urb) priv->transient = 4; priv->setup_done = 0; resubmit = 0; - dbg("%s(): scheduling setup_line()", - __func__); + dev_dbg(&port->dev, "%s(): scheduling setup_line()\n", __func__); schedule_delayed_work(&priv->delayed_setup_work, 0); } } @@ -826,7 +821,7 @@ static void oti6858_read_int_callback(struct urb *urb) if (resubmit) { int result; -/* dbg("%s(): submitting interrupt urb", __func__); */ +/* dev_dbg(&urb->dev->dev, "%s(): submitting interrupt urb\n", __func__); */ result = usb_submit_urb(urb, GFP_ATOMIC); if (result != 0) { dev_err(&urb->dev->dev, @@ -851,7 +846,7 @@ static void oti6858_read_bulk_callback(struct urb *urb) spin_unlock_irqrestore(&priv->lock, flags); if (status != 0) { - dbg("%s(): unable to handle the error, exiting", __func__); + dev_dbg(&urb->dev->dev, "%s(): unable to handle the error, exiting\n", __func__); return; } @@ -885,15 +880,13 @@ static void oti6858_write_bulk_callback(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s(): urb shutting down with status: %d", - __func__, status); + dev_dbg(&urb->dev->dev, "%s(): urb shutting down with status: %d\n", __func__, status); priv->flags.write_urb_in_use = 0; return; default: /* error in the urb, so we have to resubmit it */ - dbg("%s(): nonzero write bulk status received: %d", - __func__, status); - dbg("%s(): overflow in write", __func__); + dev_dbg(&urb->dev->dev, "%s(): nonzero write bulk status received: %d\n", __func__, status); + dev_dbg(&urb->dev->dev, "%s(): overflow in write\n", __func__); port->write_urb->transfer_buffer_length = 1; result = usb_submit_urb(port->write_urb, GFP_ATOMIC); @@ -908,7 +901,7 @@ static void oti6858_write_bulk_callback(struct urb *urb) priv->flags.write_urb_in_use = 0; /* schedule the interrupt urb if we are still open */ - dbg("%s(): submitting interrupt urb", __func__); + dev_dbg(&port->dev, "%s(): submitting interrupt urb\n", __func__); result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); if (result != 0) { dev_err(&port->dev, "%s(): failed submitting int urb," -- cgit v0.10.2 From 4f0c64120041fc92a35cd1fe84562b7abcd7aeb7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 11:50:35 -0700 Subject: USB: serial: ssu100.c: remove dbg() usage dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. CC: Alan Stern CC: Rusty Russell CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index 3fee23b..e719661 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -135,7 +135,7 @@ static inline int update_mctrl(struct usb_device *dev, unsigned int set, int result; if (((set | clear) & (TIOCM_DTR | TIOCM_RTS)) == 0) { - dbg("%s - DTR|RTS not being set|cleared", __func__); + dev_dbg(&dev->dev, "%s - DTR|RTS not being set|cleared\n", __func__); return 0; /* no change */ } @@ -148,7 +148,7 @@ static inline int update_mctrl(struct usb_device *dev, unsigned int set, result = ssu100_setregister(dev, 0, UART_MCR, urb_value); if (result < 0) - dbg("%s Error from MODEM_CTRL urb", __func__); + dev_dbg(&dev->dev, "%s Error from MODEM_CTRL urb\n", __func__); return result; } @@ -164,7 +164,7 @@ static int ssu100_initdevice(struct usb_device *dev) result = ssu100_getdevice(dev, data); if (result < 0) { - dbg("%s - get_device failed %i", __func__, result); + dev_dbg(&dev->dev, "%s - get_device failed %i\n", __func__, result); goto out; } @@ -172,25 +172,25 @@ static int ssu100_initdevice(struct usb_device *dev) result = ssu100_setdevice(dev, data); if (result < 0) { - dbg("%s - setdevice failed %i", __func__, result); + dev_dbg(&dev->dev, "%s - setdevice failed %i\n", __func__, result); goto out; } result = ssu100_control_msg(dev, QT_GET_SET_PREBUF_TRIG_LVL, 128, 0); if (result < 0) { - dbg("%s - set prebuffer level failed %i", __func__, result); + dev_dbg(&dev->dev, "%s - set prebuffer level failed %i\n", __func__, result); goto out; } result = ssu100_control_msg(dev, QT_SET_ATF, ATC_DISABLED, 0); if (result < 0) { - dbg("%s - set ATFprebuffer level failed %i", __func__, result); + dev_dbg(&dev->dev, "%s - set ATFprebuffer level failed %i\n", __func__, result); goto out; } result = ssu100_getdevice(dev, data); if (result < 0) { - dbg("%s - get_device failed %i", __func__, result); + dev_dbg(&dev->dev, "%s - get_device failed %i\n", __func__, result); goto out; } @@ -201,7 +201,7 @@ static int ssu100_initdevice(struct usb_device *dev) result = ssu100_setdevice(dev, data); if (result < 0) { - dbg("%s - setdevice failed %i", __func__, result); + dev_dbg(&dev->dev, "%s - setdevice failed %i\n", __func__, result); goto out; } @@ -249,7 +249,7 @@ static void ssu100_set_termios(struct tty_struct *tty, if (!baud) baud = 9600; - dbg("%s - got baud = %d\n", __func__, baud); + dev_dbg(&port->dev, "%s - got baud = %d\n", __func__, baud); divisor = MAX_BAUD_RATE / baud; @@ -261,7 +261,7 @@ static void ssu100_set_termios(struct tty_struct *tty, result = ssu100_control_msg(dev, QT_GET_SET_UART, divisor, urb_value); if (result < 0) - dbg("%s - set uart failed", __func__); + dev_dbg(&port->dev, "%s - set uart failed\n", __func__); if (cflag & CRTSCTS) result = ssu100_control_msg(dev, QT_HW_FLOW_CONTROL_MASK, @@ -270,7 +270,7 @@ static void ssu100_set_termios(struct tty_struct *tty, result = ssu100_control_msg(dev, QT_HW_FLOW_CONTROL_MASK, 0, 0); if (result < 0) - dbg("%s - set HW flow control failed", __func__); + dev_dbg(&port->dev, "%s - set HW flow control failed\n", __func__); if (I_IXOFF(tty) || I_IXON(tty)) { u16 x = ((u16)(START_CHAR(tty) << 8) | (u16)(STOP_CHAR(tty))); @@ -282,7 +282,7 @@ static void ssu100_set_termios(struct tty_struct *tty, 0, 0); if (result < 0) - dbg("%s - set SW flow control failed", __func__); + dev_dbg(&port->dev, "%s - set SW flow control failed\n", __func__); } @@ -304,7 +304,7 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port) QT_TRANSFER_IN, 0x01, 0, data, 2, 300); if (result < 0) { - dbg("%s - open failed %i", __func__, result); + dev_dbg(&port->dev, "%s - open failed %i\n", __func__, result); kfree(data); return result; } @@ -319,7 +319,7 @@ static int ssu100_open(struct tty_struct *tty, struct usb_serial_port *port) /* set to 9600 */ result = ssu100_control_msg(dev, QT_GET_SET_UART, 0x30, 0x0300); if (result < 0) - dbg("%s - set uart failed", __func__); + dev_dbg(&port->dev, "%s - set uart failed\n", __func__); if (tty) ssu100_set_termios(tty, port, tty->termios); @@ -423,7 +423,7 @@ static int ssu100_ioctl(struct tty_struct *tty, { struct usb_serial_port *port = tty->driver_data; - dbg("%s cmd 0x%04x", __func__, cmd); + dev_dbg(&port->dev, "%s cmd 0x%04x\n", __func__, cmd); switch (cmd) { case TIOCGSERIAL: @@ -437,7 +437,7 @@ static int ssu100_ioctl(struct tty_struct *tty, break; } - dbg("%s arg not supported", __func__); + dev_dbg(&port->dev, "%s arg not supported\n", __func__); return -ENOIOCTLCMD; } -- cgit v0.10.2 From 255b703a341d3eaf3ec74f567c00f085225fc3db Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 11:50:35 -0700 Subject: USB: serial: whiteheat.c: remove dbg() usage dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. CC: Support Department Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index fc72591..d9456b4 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -533,7 +533,7 @@ static int whiteheat_ioctl(struct tty_struct *tty, struct serial_struct serstruct; void __user *user_arg = (void __user *)arg; - dbg("%s - port %d, cmd 0x%.4x", __func__, port->number, cmd); + dev_dbg(&port->dev, "%s - cmd 0x%.4x\n", __func__, cmd); switch (cmd) { case TIOCGSERIAL: @@ -580,7 +580,7 @@ static void command_port_write_callback(struct urb *urb) int status = urb->status; if (status) { - dbg("nonzero urb status: %d", status); + dev_dbg(&urb->dev->dev, "nonzero urb status: %d\n", status); return; } } @@ -596,11 +596,11 @@ static void command_port_read_callback(struct urb *urb) command_info = usb_get_serial_port_data(command_port); if (!command_info) { - dbg("%s - command_info is NULL, exiting.", __func__); + dev_dbg(&urb->dev->dev, "%s - command_info is NULL, exiting.\n", __func__); return; } if (status) { - dbg("%s - nonzero urb status: %d", __func__, status); + dev_dbg(&urb->dev->dev, "%s - nonzero urb status: %d\n", __func__, status); if (status != -ENOENT) command_info->command_finished = WHITEHEAT_CMD_FAILURE; wake_up(&command_info->wait_command); @@ -619,19 +619,19 @@ static void command_port_read_callback(struct urb *urb) } else if (data[0] == WHITEHEAT_EVENT) { /* These are unsolicited reports from the firmware, hence no waiting command to wakeup */ - dbg("%s - event received", __func__); + dev_dbg(&urb->dev->dev, "%s - event received\n", __func__); } else if (data[0] == WHITEHEAT_GET_DTR_RTS) { memcpy(command_info->result_buffer, &data[1], urb->actual_length - 1); command_info->command_finished = WHITEHEAT_CMD_COMPLETE; wake_up(&command_info->wait_command); } else - dbg("%s - bad reply from firmware", __func__); + dev_dbg(&urb->dev->dev, "%s - bad reply from firmware\n", __func__); /* Continue trying to always read */ result = usb_submit_urb(command_port->read_urb, GFP_ATOMIC); if (result) - dbg("%s - failed resubmitting read urb, error %d", + dev_dbg(&urb->dev->dev, "%s - failed resubmitting read urb, error %d\n", __func__, result); } @@ -645,11 +645,12 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command, struct usb_serial_port *command_port; struct whiteheat_command_private *command_info; struct whiteheat_private *info; + struct device *dev = &port->dev; __u8 *transfer_buffer; int retval = 0; int t; - dbg("%s - command %d", __func__, command); + dev_dbg(dev, "%s - command %d\n", __func__, command); command_port = port->serial->port[COMMAND_PORT]; command_info = usb_get_serial_port_data(command_port); @@ -662,7 +663,7 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command, command_port->write_urb->transfer_buffer_length = datasize + 1; retval = usb_submit_urb(command_port->write_urb, GFP_NOIO); if (retval) { - dbg("%s - submit urb failed", __func__); + dev_dbg(dev, "%s - submit urb failed\n", __func__); goto exit; } @@ -673,19 +674,19 @@ static int firm_send_command(struct usb_serial_port *port, __u8 command, usb_kill_urb(command_port->write_urb); if (command_info->command_finished == false) { - dbg("%s - command timed out.", __func__); + dev_dbg(dev, "%s - command timed out.\n", __func__); retval = -ETIMEDOUT; goto exit; } if (command_info->command_finished == WHITEHEAT_CMD_FAILURE) { - dbg("%s - command failed.", __func__); + dev_dbg(dev, "%s - command failed.\n", __func__); retval = -EIO; goto exit; } if (command_info->command_finished == WHITEHEAT_CMD_COMPLETE) { - dbg("%s - command completed.", __func__); + dev_dbg(dev, "%s - command completed.\n", __func__); switch (command) { case WHITEHEAT_GET_DTR_RTS: info = usb_get_serial_port_data(port); @@ -723,6 +724,7 @@ static int firm_close(struct usb_serial_port *port) static void firm_setup_port(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; + struct device *dev = &port->dev; struct whiteheat_port_settings port_settings; unsigned int cflag = tty->termios->c_cflag; @@ -736,7 +738,7 @@ static void firm_setup_port(struct tty_struct *tty) default: case CS8: port_settings.bits = 8; break; } - dbg("%s - data bits = %d", __func__, port_settings.bits); + dev_dbg(dev, "%s - data bits = %d\n", __func__, port_settings.bits); /* determine the parity */ if (cflag & PARENB) @@ -752,14 +754,14 @@ static void firm_setup_port(struct tty_struct *tty) port_settings.parity = WHITEHEAT_PAR_EVEN; else port_settings.parity = WHITEHEAT_PAR_NONE; - dbg("%s - parity = %c", __func__, port_settings.parity); + dev_dbg(dev, "%s - parity = %c\n", __func__, port_settings.parity); /* figure out the stop bits requested */ if (cflag & CSTOPB) port_settings.stop = 2; else port_settings.stop = 1; - dbg("%s - stop bits = %d", __func__, port_settings.stop); + dev_dbg(dev, "%s - stop bits = %d\n", __func__, port_settings.stop); /* figure out the flow control settings */ if (cflag & CRTSCTS) @@ -767,7 +769,7 @@ static void firm_setup_port(struct tty_struct *tty) WHITEHEAT_HFLOW_RTS); else port_settings.hflow = WHITEHEAT_HFLOW_NONE; - dbg("%s - hardware flow control = %s %s %s %s", __func__, + dev_dbg(dev, "%s - hardware flow control = %s %s %s %s\n", __func__, (port_settings.hflow & WHITEHEAT_HFLOW_CTS) ? "CTS" : "", (port_settings.hflow & WHITEHEAT_HFLOW_RTS) ? "RTS" : "", (port_settings.hflow & WHITEHEAT_HFLOW_DSR) ? "DSR" : "", @@ -778,16 +780,15 @@ static void firm_setup_port(struct tty_struct *tty) port_settings.sflow = WHITEHEAT_SFLOW_RXTX; else port_settings.sflow = WHITEHEAT_SFLOW_NONE; - dbg("%s - software flow control = %c", __func__, port_settings.sflow); + dev_dbg(dev, "%s - software flow control = %c\n", __func__, port_settings.sflow); port_settings.xon = START_CHAR(tty); port_settings.xoff = STOP_CHAR(tty); - dbg("%s - XON = %2x, XOFF = %2x", - __func__, port_settings.xon, port_settings.xoff); + dev_dbg(dev, "%s - XON = %2x, XOFF = %2x\n", __func__, port_settings.xon, port_settings.xoff); /* get the baud rate wanted */ port_settings.baud = tty_get_baud_rate(tty); - dbg("%s - baud rate = %d", __func__, port_settings.baud); + dev_dbg(dev, "%s - baud rate = %d\n", __func__, port_settings.baud); /* fixme: should set validated settings */ tty_encode_baud_rate(tty, port_settings.baud, port_settings.baud); -- cgit v0.10.2 From 826575fc958649ebaddfbf89cdca5ed0bd23e6c9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 12:06:52 -0700 Subject: USB: serial: keyspan_pda.c: remove dbg() usage dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 1290b6f..940a0d5 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -137,8 +137,8 @@ static void keyspan_pda_request_unthrottle(struct work_struct *work) 0, 2000); if (result < 0) - dbg("%s - error %d from usb_control_msg", - __func__, result); + dev_dbg(&serial->dev->dev, "%s - error %d from usb_control_msg\n", + __func__, result); } @@ -160,12 +160,10 @@ static void keyspan_pda_rx_interrupt(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", - __func__, status); + dev_dbg(&urb->dev->dev, "%s - urb shutting down with status: %d\n", __func__, status); return; default: - dbg("%s - nonzero urb status received: %d", - __func__, status); + dev_dbg(&urb->dev->dev, "%s - nonzero urb status received: %d\n", __func__, status); goto exit; } @@ -183,7 +181,7 @@ static void keyspan_pda_rx_interrupt(struct urb *urb) break; case 1: /* status interrupt */ - dbg(" rx int, d1=%d, d2=%d", data[1], data[2]); + dev_dbg(&port->dev, "rx int, d1=%d, d2=%d\n", data[1], data[2]); switch (data[1]) { case 1: /* modemline change */ break; @@ -229,7 +227,7 @@ static void keyspan_pda_rx_unthrottle(struct tty_struct *tty) /* just restart the receive interrupt URB */ if (usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL)) - dbg(" usb_submit_urb(read urb) failed"); + dev_dbg(&port->dev, "usb_submit_urb(read urb) failed\n"); } @@ -308,8 +306,8 @@ static void keyspan_pda_break_ctl(struct tty_struct *tty, int break_state) USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, value, 0, NULL, 0, 2000); if (result < 0) - dbg("%s - error %d from usb_control_msg", - __func__, result); + dev_dbg(&port->dev, "%s - error %d from usb_control_msg\n", + __func__, result); /* there is something funky about this.. the TCSBRK that 'cu' performs ought to translate into a break_ctl(-1),break_ctl(0) pair HZ/4 seconds apart, but it feels like the break sent isn't as long as it @@ -347,7 +345,7 @@ static void keyspan_pda_set_termios(struct tty_struct *tty, speed = keyspan_pda_setbaud(serial, speed); if (speed == 0) { - dbg("can't handle requested baud rate"); + dev_dbg(&port->dev, "can't handle requested baud rate\n"); /* It hasn't changed so.. */ speed = tty_termios_baud_rate(old_termios); } @@ -459,7 +457,7 @@ static int keyspan_pda_write(struct tty_struct *tty, Block if we can't write anything at all, otherwise write as much as we can. */ if (count == 0) { - dbg(" write request of 0 bytes"); + dev_dbg(&port->dev, "write request of 0 bytes\n"); return 0; } @@ -505,16 +503,16 @@ static int keyspan_pda_write(struct tty_struct *tty, 1, 2000); if (rc > 0) { - dbg(" roomquery says %d", *room); + dev_dbg(&port->dev, "roomquery says %d\n", *room); priv->tx_room = *room; } kfree(room); if (rc < 0) { - dbg(" roomquery failed"); + dev_dbg(&port->dev, "roomquery failed\n"); goto exit; } if (rc == 0) { - dbg(" roomquery returned 0 bytes"); + dev_dbg(&port->dev, "roomquery returned 0 bytes\n"); rc = -EIO; /* device didn't return any data */ goto exit; } @@ -536,7 +534,7 @@ static int keyspan_pda_write(struct tty_struct *tty, rc = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (rc) { - dbg(" usb_submit_urb(write bulk) failed"); + dev_dbg(&port->dev, "usb_submit_urb(write bulk) failed\n"); goto exit; } } else { @@ -639,11 +637,11 @@ static int keyspan_pda_open(struct tty_struct *tty, 1, 2000); if (rc < 0) { - dbg("%s - roomquery failed", __func__); + dev_dbg(&port->dev, "%s - roomquery failed\n", __func__); goto error; } if (rc == 0) { - dbg("%s - roomquery returned 0 bytes", __func__); + dev_dbg(&port->dev, "%s - roomquery returned 0 bytes\n", __func__); rc = -EIO; goto error; } @@ -654,7 +652,7 @@ static int keyspan_pda_open(struct tty_struct *tty, /*Start reading from the device*/ rc = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); if (rc) { - dbg("%s - usb_submit_urb(read int) failed", __func__); + dev_dbg(&port->dev, "%s - usb_submit_urb(read int) failed\n", __func__); goto error; } error: -- cgit v0.10.2 From b12f7a1cb957e534646afa46fd11cf38a1885d87 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 12:06:55 -0700 Subject: USB: serial: kobil_sct.c: remove dbg() usage dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. CC: Johan Hovold CC: Alan Stern CC: Felipe Balbi Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index fafeabb..a2f7230 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -164,13 +164,15 @@ static int kobil_startup(struct usb_serial *serial) for (i = 0; i < altsetting->desc.bNumEndpoints; i++) { endpoint = &altsetting->endpoint[i]; if (usb_endpoint_is_int_out(&endpoint->desc)) { - dbg("%s Found interrupt out endpoint. Address: %d", + dev_dbg(&serial->dev->dev, + "%s Found interrupt out endpoint. Address: %d\n", __func__, endpoint->desc.bEndpointAddress); priv->write_int_endpoint_address = endpoint->desc.bEndpointAddress; } if (usb_endpoint_is_int_in(&endpoint->desc)) { - dbg("%s Found interrupt in endpoint. Address: %d", + dev_dbg(&serial->dev->dev, + "%s Found interrupt in endpoint. Address: %d\n", __func__, endpoint->desc.bEndpointAddress); priv->read_int_endpoint_address = endpoint->desc.bEndpointAddress; @@ -200,6 +202,7 @@ static void kobil_init_termios(struct tty_struct *tty) static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port) { + struct device *dev = &port->dev; int result = 0; struct kobil_private *priv; unsigned char *transfer_buffer; @@ -215,12 +218,10 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port) /* allocate write_urb */ if (!port->write_urb) { - dbg("%s - port %d Allocating port->write_urb", - __func__, port->number); + dev_dbg(dev, "%s - Allocating port->write_urb\n", __func__); port->write_urb = usb_alloc_urb(0, GFP_KERNEL); if (!port->write_urb) { - dbg("%s - port %d usb_alloc_urb failed", - __func__, port->number); + dev_dbg(dev, "%s - usb_alloc_urb failed\n", __func__); kfree(transfer_buffer); return -ENOMEM; } @@ -247,10 +248,9 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port) transfer_buffer_length, KOBIL_TIMEOUT ); - dbg("%s - port %d Send get_HW_version URB returns: %i", - __func__, port->number, result); - dbg("Harware version: %i.%i.%i", - transfer_buffer[0], transfer_buffer[1], transfer_buffer[2]); + dev_dbg(dev, "%s - Send get_HW_version URB returns: %i\n", __func__, result); + dev_dbg(dev, "Harware version: %i.%i.%i\n", transfer_buffer[0], + transfer_buffer[1], transfer_buffer[2]); /* get firmware version */ result = usb_control_msg(port->serial->dev, @@ -263,10 +263,9 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port) transfer_buffer_length, KOBIL_TIMEOUT ); - dbg("%s - port %d Send get_FW_version URB returns: %i", - __func__, port->number, result); - dbg("Firmware version: %i.%i.%i", - transfer_buffer[0], transfer_buffer[1], transfer_buffer[2]); + dev_dbg(dev, "%s - Send get_FW_version URB returns: %i\n", __func__, result); + dev_dbg(dev, "Firmware version: %i.%i.%i\n", transfer_buffer[0], + transfer_buffer[1], transfer_buffer[2]); if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) { @@ -282,8 +281,7 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port) 0, KOBIL_TIMEOUT ); - dbg("%s - port %d Send set_baudrate URB returns: %i", - __func__, port->number, result); + dev_dbg(dev, "%s - Send set_baudrate URB returns: %i\n", __func__, result); /* reset all queues */ result = usb_control_msg(port->serial->dev, @@ -296,16 +294,14 @@ static int kobil_open(struct tty_struct *tty, struct usb_serial_port *port) 0, KOBIL_TIMEOUT ); - dbg("%s - port %d Send reset_all_queues URB returns: %i", - __func__, port->number, result); + dev_dbg(dev, "%s - Send reset_all_queues URB returns: %i\n", __func__, result); } if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) { /* start reading (Adapter B 'cause PNP string) */ result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); - dbg("%s - port %d Send read URB returns: %i", - __func__, port->number, result); + dev_dbg(dev, "%s - Send read URB returns: %i\n", __func__, result); } kfree(transfer_buffer); @@ -333,11 +329,9 @@ static void kobil_read_int_callback(struct urb *urb) struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; int status = urb->status; -/* char *dbg_data; */ if (status) { - dbg("%s - port %d Read int status not zero: %d", - __func__, port->number, status); + dev_dbg(&port->dev, "%s - Read int status not zero: %d\n", __func__, status); return; } @@ -346,6 +340,8 @@ static void kobil_read_int_callback(struct urb *urb) /* BEGIN DEBUG */ /* + char *dbg_data; + dbg_data = kzalloc((3 * purb->actual_length + 10) * sizeof(char), GFP_KERNEL); if (! dbg_data) { @@ -354,7 +350,7 @@ static void kobil_read_int_callback(struct urb *urb) for (i = 0; i < purb->actual_length; i++) { sprintf(dbg_data +3*i, "%02X ", data[i]); } - dbg(" <-- %s", dbg_data); + dev_dbg(&port->dev, " <-- %s\n", dbg_data); kfree(dbg_data); */ /* END DEBUG */ @@ -365,8 +361,7 @@ static void kobil_read_int_callback(struct urb *urb) tty_kref_put(tty); result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); - dbg("%s - port %d Send read URB returns: %i", - __func__, port->number, result); + dev_dbg(&port->dev, "%s - Send read URB returns: %i\n", __func__, result); } @@ -384,15 +379,14 @@ static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, struct kobil_private *priv; if (count == 0) { - dbg("%s - port %d write request of 0 bytes", - __func__, port->number); + dev_dbg(&port->dev, "%s - write request of 0 bytes\n", __func__); return 0; } priv = usb_get_serial_port_data(port); if (count > (KOBIL_BUF_LENGTH - priv->filled)) { - dbg("%s - port %d Error: write request bigger than buffer size", __func__, port->number); + dev_dbg(&port->dev, "%s - Error: write request bigger than buffer size\n", __func__); return -ENOMEM; } @@ -432,8 +426,7 @@ static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, priv->cur_pos = priv->cur_pos + length; result = usb_submit_urb(port->write_urb, GFP_NOIO); - dbg("%s - port %d Send write URB returns: %i", - __func__, port->number, result); + dev_dbg(&port->dev, "%s - Send write URB returns: %i\n", __func__, result); todo = priv->filled - priv->cur_pos; if (todo > 0) @@ -448,8 +441,7 @@ static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) { result = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO); - dbg("%s - port %d Send read URB returns: %i", - __func__, port->number, result); + dev_dbg(&port->dev, "%s - Send read URB returns: %i\n", __func__, result); } } return count; @@ -493,8 +485,8 @@ static int kobil_tiocmget(struct tty_struct *tty) transfer_buffer_length, KOBIL_TIMEOUT); - dbg("%s - port %d Send get_status_line_state URB returns: %i. Statusline: %02x", - __func__, port->number, result, transfer_buffer[0]); + dev_dbg(&port->dev, "%s - Send get_status_line_state URB returns: %i. Statusline: %02x\n", + __func__, result, transfer_buffer[0]); result = 0; if ((transfer_buffer[0] & SUSBCR_GSL_DSR) != 0) @@ -507,6 +499,7 @@ static int kobil_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; + struct device *dev = &port->dev; struct kobil_private *priv; int result; int dtr = 0; @@ -538,11 +531,9 @@ static int kobil_tiocmset(struct tty_struct *tty, if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) { if (dtr != 0) - dbg("%s - port %d Setting DTR", - __func__, port->number); + dev_dbg(dev, "%s - Setting DTR\n", __func__); else - dbg("%s - port %d Clearing DTR", - __func__, port->number); + dev_dbg(dev, "%s - Clearing DTR\n", __func__); result = usb_control_msg(port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0), SUSBCRequest_SetStatusLinesOrQueues, @@ -554,11 +545,9 @@ static int kobil_tiocmset(struct tty_struct *tty, KOBIL_TIMEOUT); } else { if (rts != 0) - dbg("%s - port %d Setting RTS", - __func__, port->number); + dev_dbg(dev, "%s - Setting RTS\n", __func__); else - dbg("%s - port %d Clearing RTS", - __func__, port->number); + dev_dbg(dev, "%s - Clearing RTS\n", __func__); result = usb_control_msg(port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0), SUSBCRequest_SetStatusLinesOrQueues, @@ -569,8 +558,7 @@ static int kobil_tiocmset(struct tty_struct *tty, 0, KOBIL_TIMEOUT); } - dbg("%s - port %d Send set_status_line URB returns: %i", - __func__, port->number, result); + dev_dbg(dev, "%s - Send set_status_line URB returns: %i\n", __func__, result); kfree(transfer_buffer); return (result < 0) ? result : 0; } @@ -658,7 +646,8 @@ static int kobil_ioctl(struct tty_struct *tty, KOBIL_TIMEOUT ); - dbg("%s - port %d Send reset_all_queues (FLUSH) URB returns: %i", __func__, port->number, result); + dev_dbg(&port->dev, + "%s - Send reset_all_queues (FLUSH) URB returns: %i", __func__, result); kfree(transfer_buffer); return (result < 0) ? -EIO: 0; default: -- cgit v0.10.2 From c34518dce9e66ee17b9de85fe0b3a9ea018405f9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 12:31:18 -0700 Subject: USB: serial: aircable.c: remove debug module parameter Now that the dbg() macro is no longer being used in the driver, the debug module parameter doesn't do anything at all. So remove it so as to not confuse people. CC: Paul Gortmaker CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/aircable.c b/drivers/usb/serial/aircable.c index d634e66..54e1bb6 100644 --- a/drivers/usb/serial/aircable.c +++ b/drivers/usb/serial/aircable.c @@ -52,8 +52,6 @@ #include #include -static bool debug; - /* Vendor and Product ID */ #define AIRCABLE_VID 0x16CA #define AIRCABLE_USB_PID 0x1502 @@ -196,6 +194,3 @@ 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 enabled or not"); -- cgit v0.10.2 From 19e988cfb9f28d2f2fc12b3b368fed4822dc48e4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 12:31:21 -0700 Subject: USB: serial: cp210x.c: remove debug module parameter Now that the dbg() macro is no longer being used in the driver, the debug module parameter doesn't do anything at all. So remove it so as to not confuse people. CC: Johan Hovold CC: Preston Fick Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 9cf6985..697c7d9 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -52,8 +52,6 @@ static int cp210x_startup(struct usb_serial *); static void cp210x_release(struct usb_serial *); static void cp210x_dtr_rts(struct usb_serial_port *p, int on); -static bool debug; - static const struct usb_device_id id_table[] = { { USB_DEVICE(0x045B, 0x0053) }, /* Renesas RX610 RX-Stick */ { USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */ @@ -884,6 +882,3 @@ module_usb_serial_driver(serial_drivers, id_table); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Enable verbose debugging messages"); -- cgit v0.10.2 From a2f98a203b02617107086ac72996a1ab3c4d5ea4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 12:31:21 -0700 Subject: USB: serial: digi_acceleport.c: remove debug module parameter Now that the dbg() macro is no longer being used in the driver, the debug module parameter doesn't do anything at all. So remove it so as to not confuse people. CC: Peter Berger CC: Al Borchers Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index df60a33..d3a8941 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c @@ -249,10 +249,6 @@ static int digi_read_inb_callback(struct urb *urb); static int digi_read_oob_callback(struct urb *urb); -/* Statics */ - -static bool debug; - static const struct usb_device_id id_table_combined[] = { { USB_DEVICE(DIGI_VENDOR_ID, DIGI_2_ID) }, { USB_DEVICE(DIGI_VENDOR_ID, DIGI_4_ID) }, @@ -1559,6 +1555,3 @@ module_usb_serial_driver(serial_drivers, id_table_combined); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v0.10.2 From a9b57be074688cdfd9b10b1db58988bb31da20ef Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 12:31:22 -0700 Subject: USB: serial: empeg.c: remove debug module parameter Now that the dbg() macro is no longer being used in the driver, the debug module parameter doesn't do anything at all. So remove it so as to not confuse people. CC: Gary Brubaker Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index cdf61dd..4d9935f 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c @@ -28,8 +28,6 @@ #include #include -static bool debug; - /* * Version Information */ @@ -134,6 +132,3 @@ module_usb_serial_driver(serial_drivers, id_table); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v0.10.2 From e6e367b26ec1881cf44e68346a40a9b7b3352055 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 12:31:24 -0700 Subject: USB: serial: ftdi_sio.c: remove debug module parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the dbg() macro is no longer being used in the driver, the debug module parameter doesn't do anything at all. So remove it so as to not confuse people. CC: Uwe Bonnes CC: Simon Arlott CC: Andrew Worsley CC: "Michał Wróbel" Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 5f8f172..6d77d2c 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -55,7 +55,6 @@ #define DRIVER_AUTHOR "Greg Kroah-Hartman , Bill Ryder , Kuba Ober , Andreas Mohr, Johan Hovold " #define DRIVER_DESC "USB FTDI Serial Converters Driver" -static bool debug; static __u16 vendor = FTDI_VID; static __u16 product; @@ -2431,8 +2430,6 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); module_param(vendor, ushort, 0); MODULE_PARM_DESC(vendor, "User specified vendor ID (default=" __MODULE_STRING(FTDI_VID)")"); -- cgit v0.10.2 From 347708d9293ecad63aa3825637f754bd6edb235b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 12:31:27 -0700 Subject: USB: serial: funsoft.c: remove debug module parameter Now that the dbg() macro is no longer being used in the driver, the debug module parameter doesn't do anything at all. So remove it so as to not confuse people. CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/funsoft.c b/drivers/usb/serial/funsoft.c index 2357079..9362f8f 100644 --- a/drivers/usb/serial/funsoft.c +++ b/drivers/usb/serial/funsoft.c @@ -16,8 +16,6 @@ #include #include -static bool debug; - static const struct usb_device_id id_table[] = { { USB_DEVICE(0x1404, 0xcddc) }, { }, @@ -40,6 +38,3 @@ static struct usb_serial_driver * const serial_drivers[] = { module_usb_serial_driver(serial_drivers, id_table); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v0.10.2 From 06e454c40e67df631e2020571ab4e089d9fe0026 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 12:31:30 -0700 Subject: USB: serial: ipaq.c: remove debug module parameter Now that the dbg() macro is no longer being used in the driver, the debug module parameter doesn't do anything at all. So remove it so as to not confuse people. CC: Rusty Russell CC: Johan Hovold CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index c85a7eb..1068bf2 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c @@ -33,7 +33,6 @@ #define DRIVER_AUTHOR "Ganesh Varadarajan " #define DRIVER_DESC "USB PocketPC PDA driver" -static bool debug; static int connect_retries = KP_RETRIES; static int initial_wait; @@ -616,9 +615,6 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); - module_param(connect_retries, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(connect_retries, "Maximum number of connect retries (one second each)"); -- cgit v0.10.2 From f3004d54027d1c440f1e45ec3aa7caba6cca6f1a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 12:31:32 -0700 Subject: USB: serial: ipw.c: remove debug module parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the dbg() macro is no longer being used in the driver, the debug module parameter doesn't do anything at all. So remove it so as to not confuse people. CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab CC: "Bjørn Mork" Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index fbd54a1..20a132e 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c @@ -138,8 +138,6 @@ static const struct usb_device_id id_table[] = { }; MODULE_DEVICE_TABLE(usb, id_table); -static bool debug; - static int ipw_open(struct tty_struct *tty, struct usb_serial_port *port) { struct usb_device *udev = port->serial->dev; @@ -323,6 +321,3 @@ module_usb_serial_driver(serial_drivers, id_table); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v0.10.2 From 7beb3c31a5ab7594e9a339b9a69f523dd6ab7f1c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 12:31:35 -0700 Subject: USB: serial: ir-usb.c: remove debug module parameter Now that the dbg() macro is no longer being used in the driver, the debug module parameter doesn't do anything at all. So remove it so as to not confuse people. CC: Rusty Russell CC: Johan Hovold CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index fc09414..7b7319d 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -45,8 +45,6 @@ #define DRIVER_AUTHOR "Greg Kroah-Hartman , Johan Hovold " #define DRIVER_DESC "USB IR Dongle driver" -static bool debug; - /* if overridden by the user, then use their value for the size of the read and * write urbs */ static int buffer_size; @@ -457,8 +455,6 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); module_param(xbof, int, 0); MODULE_PARM_DESC(xbof, "Force specific number of XBOFs"); module_param(buffer_size, int, 0); -- cgit v0.10.2 From 8c46939be412ba98bc2d552deba1eabb6112053d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 12:31:35 -0700 Subject: USB: serial: keyspan_pda.c: remove debug module parameter Now that the dbg() macro is no longer being used in the driver, the debug module parameter doesn't do anything at all. So remove it so as to not confuse people. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 940a0d5..124d4e5 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -31,8 +31,6 @@ #include #include -static bool debug; - /* make a simple define to handle if we are compiling keyspan_pda or xircom support */ #if defined(CONFIG_USB_SERIAL_KEYSPAN_PDA) || defined(CONFIG_USB_SERIAL_KEYSPAN_PDA_MODULE) #define KEYSPAN @@ -826,6 +824,3 @@ module_usb_serial_driver(serial_drivers, id_table_combined); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v0.10.2 From 63f10ddadb666ed852f972950ed4fa217172b457 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 12:31:36 -0700 Subject: USB: serial: kl5kusb105.c: remove debug module parameter Now that the dbg() macro is no longer being used in the driver, the debug module parameter doesn't do anything at all. So remove it so as to not confuse people. CC: Oliver Neukum Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index 73e0a23..e4aa6c0 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c @@ -49,8 +49,6 @@ #include #include "kl5kusb105.h" -static bool debug; - /* * Version Information */ @@ -681,6 +679,3 @@ module_usb_serial_driver(serial_drivers, id_table); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "enable extensive debugging messages"); -- cgit v0.10.2 From e4fd70c5e2befa29f962d640c1f78feefb7b3c25 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 12:31:42 -0700 Subject: USB: serial: metro-usb.c: remove debug module parameter Now that the dbg() macro is no longer being used in the driver, the debug module parameter doesn't do anything at all. So remove it so as to not confuse people. CC: Aleksey Babahin Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/metro-usb.c b/drivers/usb/serial/metro-usb.c index d47eb06..ed61b53 100644 --- a/drivers/usb/serial/metro-usb.c +++ b/drivers/usb/serial/metro-usb.c @@ -52,9 +52,6 @@ static struct usb_device_id id_table[] = { }; MODULE_DEVICE_TABLE(usb, id_table); -/* Input parameter constants. */ -static bool debug; - /* UNI-Directional mode commands for device configure */ #define UNI_CMD_OPEN 0x80 #define UNI_CMD_CLOSE 0xFF @@ -442,7 +439,3 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Philip Nicastro"); MODULE_AUTHOR("Aleksey Babahin "); MODULE_DESCRIPTION(DRIVER_DESC); - -/* Module input parameters */ -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Print debug info (bool 1=on, 0=off)"); -- cgit v0.10.2 From 6ae06571da628cae889606dae1250ae7e355b899 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 12:31:42 -0700 Subject: USB: serial: option.c: remove debug module parameter Now that the dbg() macro is no longer being used in the driver, the debug module parameter doesn't do anything at all. So remove it so as to not confuse people. CC: Matthias Urlichs Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 3891c0f..3229368 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -1255,8 +1255,6 @@ static struct usb_serial_driver * const serial_drivers[] = { &option_1port_device, NULL }; -static bool debug; - struct option_private { u8 bInterfaceNumber; }; @@ -1449,6 +1447,3 @@ 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"); -- cgit v0.10.2 From ec035e4b832d690c1e82e6e4cacd055b5b3cc2d5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 12:31:45 -0700 Subject: USB: serial: oti6858.c: remove debug module parameter Now that the dbg() macro is no longer being used in the driver, the debug module parameter doesn't do anything at all. So remove it so as to not confuse people. CC: Johan Hovold CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index e91a774..1498b3d 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c @@ -66,8 +66,6 @@ static const struct usb_device_id id_table[] = { MODULE_DEVICE_TABLE(usb, id_table); -static bool debug; - /* requests */ #define OTI6858_REQ_GET_STATUS (USB_DIR_IN | USB_TYPE_VENDOR | 0x00) #define OTI6858_REQ_T_GET_STATUS 0x01 @@ -915,7 +913,3 @@ MODULE_DESCRIPTION(OTI6858_DESCRIPTION); MODULE_AUTHOR(OTI6858_AUTHOR); MODULE_VERSION(OTI6858_VERSION); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "enable debug output"); - -- cgit v0.10.2 From 3da3bf76cb6ccd1fbb9205bfa9e8a13dce6e3238 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 12:31:47 -0700 Subject: USB: serial: qcserial.c: remove debug module parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the dbg() macro is no longer being used in the driver, the debug module parameter doesn't do anything at all. So remove it so as to not confuse people. CC: "Bjørn Mork" CC: Dan Williams CC: Thomas Tuttle CC: Alan Stern Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index bfd5077..c3ddb65 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -22,8 +22,6 @@ #define DRIVER_AUTHOR "Qualcomm Inc" #define DRIVER_DESC "Qualcomm USB Serial driver" -static bool debug; - #define DEVICE_G1K(v, p) \ USB_DEVICE(v, p), .driver_info = 1 @@ -305,6 +303,3 @@ module_usb_serial_driver(serial_drivers, id_table); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL v2"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v0.10.2 From 620a4616b26c05b3a3301d2bd0767c4647652372 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 12:31:52 -0700 Subject: USB: serial: quatech2.c: remove debug module parameter Now that the dbg() macro is no longer being used in the driver, the debug module parameter doesn't do anything at all. So remove it so as to not confuse people. CC: Bill Pemberton Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 151670b..e60f27b 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -27,8 +27,6 @@ #include #include -static bool debug; - /* default urb timeout for usb operations */ #define QT2_USB_TIMEOUT USB_CTRL_SET_TIMEOUT @@ -1146,6 +1144,3 @@ module_usb_serial_driver(serial_drivers, id_table); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v0.10.2 From 40c9616bdd4abf319860195361abd7387710b3aa Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 12:31:55 -0700 Subject: USB: serial: safe_serial.c: remove debug module parameter Now that the dbg() macro is no longer being used in the driver, the debug module parameter doesn't do anything at all. So remove it so as to not confuse people. CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c index 36e9d9f..e3457e2 100644 --- a/drivers/usb/serial/safe_serial.c +++ b/drivers/usb/serial/safe_serial.c @@ -81,7 +81,6 @@ #define CONFIG_USB_SERIAL_SAFE_PADDED 0 #endif -static bool debug; static bool safe = 1; static bool padded = CONFIG_USB_SERIAL_SAFE_PADDED; @@ -100,9 +99,6 @@ MODULE_PARM_DESC(vendor, "User specified USB idVendor (required)"); module_param(product, ushort, 0); MODULE_PARM_DESC(product, "User specified USB idProduct (required)"); -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); - module_param(safe, bool, 0); MODULE_PARM_DESC(safe, "Turn Safe Encapsulation On/Off"); -- cgit v0.10.2 From 1a6635f7299aa01c7f11c7eed731f2956cd5bde8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 12:31:58 -0700 Subject: USB: serial: spcp8x5.c: remove debug module parameter Now that the dbg() macro is no longer being used in the driver, the debug module parameter doesn't do anything at all. So remove it so as to not confuse people. CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index cad6089..1ca86e6 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c @@ -33,8 +33,6 @@ #define DRIVER_VERSION "v0.10" #define DRIVER_DESC "SPCP8x5 USB to serial adaptor driver" -static bool debug; - #define SPCP8x5_007_VID 0x04FC #define SPCP8x5_007_PID 0x0201 #define SPCP8x5_008_VID 0x04fc @@ -665,6 +663,3 @@ module_usb_serial_driver(serial_drivers, id_table); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v0.10.2 From 186f3812f5005d3d5435f69f672971afdae3e732 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 12:32:00 -0700 Subject: USB: serial: ssu100.c: remove debug module parameter Now that the dbg() macro is no longer being used in the driver, the debug module parameter doesn't do anything at all. So remove it so as to not confuse people. CC: Alan Stern CC: Rusty Russell CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index e719661..6635743 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c @@ -46,8 +46,6 @@ #define FULLPWRBIT 0x00000080 #define NEXT_BOARD_POWER_BIT 0x00000004 -static bool debug; - /* Version Information */ #define DRIVER_VERSION "v0.1" #define DRIVER_DESC "Quatech SSU-100 USB to Serial Driver" @@ -668,6 +666,3 @@ module_usb_serial_driver(serial_drivers, id_table); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v0.10.2 From 061b2a22bc9a22c2571e603d9f66dce2d4e156a5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 12:32:03 -0700 Subject: USB: serial: usb_wwan.c: remove debug module parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the dbg() macro is no longer being used in the driver, the debug module parameter doesn't do anything at all. So remove it so as to not confuse people. CC: "Bjørn Mork" CC: Rusty Russell CC: Mauro Carvalho Chehab CC: Dan Carpenter Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/usb_wwan.c b/drivers/usb/serial/usb_wwan.c index 3520eff..bc58d4a 100644 --- a/drivers/usb/serial/usb_wwan.c +++ b/drivers/usb/serial/usb_wwan.c @@ -37,8 +37,6 @@ #include #include "usb-wwan.h" -static bool debug; - void usb_wwan_dtr_rts(struct usb_serial_port *port, int on) { struct usb_serial *serial = port->serial; @@ -738,6 +736,3 @@ 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"); -- cgit v0.10.2 From 2621cee19a33a713d539fea9870e5fd56aa1fcd5 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 15:08:28 -0700 Subject: USB: serial: iuu_phoenix.c: remove dbg() usage dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. CC: Rusty Russell CC: Johan Hovold CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 22b1eb5..f9832b7 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -72,7 +72,6 @@ struct iuu_private { u8 *writebuf; /* buffer for writing to device */ int writelen; /* num of byte to write to device */ u8 *buf; /* used for initialize speed */ - u8 *dbgbuf; /* debug buffer */ u8 len; int vcc; /* vcc (either 3 or 5 V) */ u32 baud; @@ -84,32 +83,31 @@ struct iuu_private { static void iuu_free_buf(struct iuu_private *priv) { kfree(priv->buf); - kfree(priv->dbgbuf); kfree(priv->writebuf); } -static int iuu_alloc_buf(struct iuu_private *priv) +static int iuu_alloc_buf(struct usb_serial *serial, struct iuu_private *priv) { priv->buf = kzalloc(256, GFP_KERNEL); - priv->dbgbuf = kzalloc(256, GFP_KERNEL); priv->writebuf = kzalloc(256, GFP_KERNEL); - if (!priv->buf || !priv->dbgbuf || !priv->writebuf) { + if (!priv->buf || !priv->writebuf) { iuu_free_buf(priv); - dbg("%s problem allocation buffer", __func__); + dev_dbg(&serial->dev->dev, "%s problem allocation buffer\n", __func__); return -ENOMEM; } - dbg("%s - Privates buffers allocation success", __func__); + dev_dbg(&serial->dev->dev, "%s - Privates buffers allocation success\n", __func__); return 0; } static int iuu_startup(struct usb_serial *serial) { struct iuu_private *priv; + priv = kzalloc(sizeof(struct iuu_private), GFP_KERNEL); - dbg("%s- priv allocation success", __func__); + dev_dbg(&serial->dev->dev, "%s- priv allocation success\n", __func__); if (!priv) return -ENOMEM; - if (iuu_alloc_buf(priv)) { + if (iuu_alloc_buf(serial, priv)) { kfree(priv); return -ENOMEM; } @@ -130,13 +128,13 @@ static void iuu_release(struct usb_serial *serial) if (priv) { iuu_free_buf(priv); - dbg("%s - I will free all", __func__); + dev_dbg(&port->dev, "%s - I will free all\n", __func__); usb_set_serial_port_data(port, NULL); - dbg("%s - priv is not anymore in port structure", __func__); + dev_dbg(&port->dev, "%s - priv is not anymore in port structure\n", __func__); kfree(priv); - dbg("%s priv is now kfree", __func__); + dev_dbg(&port->dev, "%s priv is now kfree\n", __func__); } } @@ -148,13 +146,13 @@ static int iuu_tiocmset(struct tty_struct *tty, unsigned long flags; /* FIXME: locking on tiomstatus */ - dbg("%s (%d) msg : SET = 0x%04x, CLEAR = 0x%04x ", __func__, - port->number, set, clear); + dev_dbg(&port->dev, "%s msg : SET = 0x%04x, CLEAR = 0x%04x\n", + __func__, set, clear); spin_lock_irqsave(&priv->lock, flags); if ((set & TIOCM_RTS) && !(priv->tiostatus == TIOCM_RTS)) { - dbg("%s TIOCMSET RESET called !!!", __func__); + dev_dbg(&port->dev, "%s TIOCMSET RESET called !!!\n", __func__); priv->reset = 1; } if (set & TIOCM_RTS) @@ -190,7 +188,7 @@ static void iuu_rxcmd(struct urb *urb) int status = urb->status; if (status) { - dbg("%s - status = %d", __func__, status); + dev_dbg(&port->dev, "%s - status = %d\n", __func__, status); /* error stop all */ return; } @@ -244,13 +242,13 @@ static void iuu_update_status_callback(struct urb *urb) int status = urb->status; if (status) { - dbg("%s - status = %d", __func__, status); + dev_dbg(&port->dev, "%s - status = %d\n", __func__, status); /* error stop all */ return; } st = urb->transfer_buffer; - dbg("%s - enter", __func__); + dev_dbg(&port->dev, "%s - enter\n", __func__); if (urb->actual_length == 1) { switch (st[0]) { case 0x1: @@ -272,7 +270,7 @@ static void iuu_status_callback(struct urb *urb) int result; int status = urb->status; - dbg("%s - status = %d", __func__, status); + dev_dbg(&port->dev, "%s - status = %d\n", __func__, status); usb_fill_bulk_urb(port->read_urb, port->serial->dev, usb_rcvbulkpipe(port->serial->dev, port->bulk_in_endpointAddress), @@ -311,9 +309,9 @@ static int bulk_immediate(struct usb_serial_port *port, u8 *buf, u8 count) count, &actual, HZ * 1); if (status != IUU_OPERATION_OK) - dbg("%s - error = %2x", __func__, status); + dev_dbg(&port->dev, "%s - error = %2x\n", __func__, status); else - dbg("%s - write OK !", __func__); + dev_dbg(&port->dev, "%s - write OK !\n", __func__); return status; } @@ -331,9 +329,9 @@ static int read_immediate(struct usb_serial_port *port, u8 *buf, u8 count) count, &actual, HZ * 1); if (status != IUU_OPERATION_OK) - dbg("%s - error = %2x", __func__, status); + dev_dbg(&port->dev, "%s - error = %2x\n", __func__, status); else - dbg("%s - read OK !", __func__); + dev_dbg(&port->dev, "%s - read OK !\n", __func__); return status; } @@ -357,9 +355,9 @@ static int iuu_led(struct usb_serial_port *port, unsigned int R, status = bulk_immediate(port, buf, 8); kfree(buf); if (status != IUU_OPERATION_OK) - dbg("%s - led error status = %2x", __func__, status); + dev_dbg(&port->dev, "%s - led error status = %2x\n", __func__, status); else - dbg("%s - led OK !", __func__); + dev_dbg(&port->dev, "%s - led OK !\n", __func__); return IUU_OPERATION_OK; } @@ -445,7 +443,7 @@ static int iuu_clk(struct usb_serial_port *port, int dwFrq) status = bulk_immediate(port, (u8 *) priv->buf, Count); if (status != 0) { - dbg("%s - write error ", __func__); + dev_dbg(&port->dev, "%s - write error\n", __func__); return status; } } else if (frq == 3579000) { @@ -554,12 +552,13 @@ static int iuu_clk(struct usb_serial_port *port, int dwFrq) status = bulk_immediate(port, (u8 *) priv->buf, Count); if (status != IUU_OPERATION_OK) - dbg("%s - write error ", __func__); + dev_dbg(&port->dev, "%s - write error\n", __func__); return status; } static int iuu_uart_flush(struct usb_serial_port *port) { + struct device *dev = &port->dev; int i; int status; u8 rxcmd = IUU_UART_RX; @@ -571,27 +570,26 @@ static int iuu_uart_flush(struct usb_serial_port *port) for (i = 0; i < 2; i++) { status = bulk_immediate(port, &rxcmd, 1); if (status != IUU_OPERATION_OK) { - dbg("%s - uart_flush_write error", __func__); + dev_dbg(dev, "%s - uart_flush_write error\n", __func__); return status; } status = read_immediate(port, &priv->len, 1); if (status != IUU_OPERATION_OK) { - dbg("%s - uart_flush_read error", __func__); + dev_dbg(dev, "%s - uart_flush_read error\n", __func__); return status; } if (priv->len > 0) { - dbg("%s - uart_flush datalen is : %i ", __func__, - priv->len); + dev_dbg(dev, "%s - uart_flush datalen is : %i\n", __func__, priv->len); status = read_immediate(port, priv->buf, priv->len); if (status != IUU_OPERATION_OK) { - dbg("%s - uart_flush_read error", __func__); + dev_dbg(dev, "%s - uart_flush_read error\n", __func__); return status; } } } - dbg("%s - uart_flush_read OK!", __func__); + dev_dbg(dev, "%s - uart_flush_read OK!\n", __func__); iuu_led(port, 0, 0xF000, 0, 0xFF); return status; } @@ -610,10 +608,10 @@ static void read_buf_callback(struct urb *urb) return; } - dbg("%s - %i chars to write", __func__, urb->actual_length); + dev_dbg(&port->dev, "%s - %i chars to write\n", __func__, urb->actual_length); tty = tty_port_tty_get(&port->port); if (data == NULL) - dbg("%s - data is NULL !!!", __func__); + dev_dbg(&port->dev, "%s - data is NULL !!!\n", __func__); if (tty && urb->actual_length && data) { tty_insert_flip_string(tty, data, urb->actual_length); tty_flip_buffer_push(tty); @@ -627,7 +625,6 @@ static int iuu_bulk_write(struct usb_serial_port *port) struct iuu_private *priv = usb_get_serial_port_data(port); unsigned long flags; int result; - int i; int buf_len; char *buf_ptr = port->write_urb->transfer_buffer; @@ -640,14 +637,8 @@ static int iuu_bulk_write(struct usb_serial_port *port) buf_len = priv->writelen; priv->writelen = 0; spin_unlock_irqrestore(&priv->lock, flags); - if (debug == 1) { - for (i = 0; i < buf_len; i++) - sprintf(priv->dbgbuf + i*2 , - "%02X", priv->writebuf[i]); - priv->dbgbuf[buf_len+i*2] = 0; - dbg("%s - writing %i chars : %s", __func__, - buf_len, priv->dbgbuf); - } + dev_dbg(&port->dev, "%s - writing %i chars : %*ph\n", __func__, + buf_len, buf_len, buf_ptr); usb_fill_bulk_urb(port->write_urb, port->serial->dev, usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress), @@ -683,18 +674,18 @@ static void iuu_uart_read_callback(struct urb *urb) priv->poll++; if (status) { - dbg("%s - status = %d", __func__, status); + dev_dbg(&port->dev, "%s - status = %d\n", __func__, status); /* error stop all */ return; } if (data == NULL) - dbg("%s - data is NULL !!!", __func__); + dev_dbg(&port->dev, "%s - data is NULL !!!\n", __func__); if (urb->actual_length == 1 && data != NULL) len = (int) data[0]; if (urb->actual_length > 1) { - dbg("%s - urb->actual_length = %i", __func__, + dev_dbg(&port->dev, "%s - urb->actual_length = %i\n", __func__, urb->actual_length); error = 1; return; @@ -702,7 +693,7 @@ static void iuu_uart_read_callback(struct urb *urb) /* if len > 0 call readbuf */ if (len > 0 && error == 0) { - dbg("%s - call read buf - len to read is %i ", + dev_dbg(&port->dev, "%s - call read buf - len to read is %i\n", __func__, len); status = iuu_read_buf(port, len); return; @@ -729,7 +720,7 @@ static void iuu_uart_read_callback(struct urb *urb) } spin_unlock_irqrestore(&priv->lock, flags); /* if nothing to write call again rxcmd */ - dbg("%s - rxcmd recall", __func__); + dev_dbg(&port->dev, "%s - rxcmd recall\n", __func__); iuu_led_activity_off(urb); } @@ -769,7 +760,7 @@ static void read_rxcmd_callback(struct urb *urb) port->read_urb->transfer_buffer, 256, iuu_uart_read_callback, port); result = usb_submit_urb(port->read_urb, GFP_ATOMIC); - dbg("%s - submit result = %d", __func__, result); + dev_dbg(&port->dev, "%s - submit result = %d\n", __func__, result); } static int iuu_uart_on(struct usb_serial_port *port) @@ -789,13 +780,13 @@ static int iuu_uart_on(struct usb_serial_port *port) status = bulk_immediate(port, buf, 4); if (status != IUU_OPERATION_OK) { - dbg("%s - uart_on error", __func__); + dev_dbg(&port->dev, "%s - uart_on error\n", __func__); goto uart_enable_failed; } /* iuu_reset() the card after iuu_uart_on() */ status = iuu_uart_flush(port); if (status != IUU_OPERATION_OK) - dbg("%s - uart_flush error", __func__); + dev_dbg(&port->dev, "%s - uart_flush error\n", __func__); uart_enable_failed: kfree(buf); return status; @@ -813,7 +804,7 @@ static int iuu_uart_off(struct usb_serial_port *port) status = bulk_immediate(port, buf, 1); if (status != IUU_OPERATION_OK) - dbg("%s - uart_off error", __func__); + dev_dbg(&port->dev, "%s - uart_off error\n", __func__); kfree(buf); return status; @@ -830,7 +821,7 @@ static int iuu_uart_baud(struct usb_serial_port *port, u32 baud_base, u8 T1reload = 0; unsigned int T1FrekvensHZ = 0; - dbg("%s - enter baud_base=%d", __func__, baud_base); + dev_dbg(&port->dev, "%s - enter baud_base=%d\n", __func__, baud_base); dataout = kmalloc(sizeof(u8) * 5, GFP_KERNEL); if (!dataout) @@ -911,7 +902,7 @@ static int iuu_uart_baud(struct usb_serial_port *port, u32 baud_base, status = bulk_immediate(port, dataout, DataCount); if (status != IUU_OPERATION_OK) - dbg("%s - uart_off error", __func__); + dev_dbg(&port->dev, "%s - uart_off error\n", __func__); kfree(dataout); return status; } @@ -932,7 +923,7 @@ static void iuu_set_termios(struct tty_struct *tty, /* Just use the ospeed. ispeed should be the same. */ baud = tty->termios->c_ospeed; - dbg("%s - enter c_ospeed or baud=%d", __func__, baud); + dev_dbg(&port->dev, "%s - enter c_ospeed or baud=%d\n", __func__, baud); /* compute the parity parameter */ parity = 0; @@ -983,7 +974,7 @@ static void iuu_close(struct usb_serial_port *port) if (serial->dev) { /* free writebuf */ /* shutdown our urbs */ - dbg("%s - shutting down urbs", __func__); + dev_dbg(&port->dev, "%s - shutting down urbs\n", __func__); usb_kill_urb(port->write_urb); usb_kill_urb(port->read_urb); usb_kill_urb(port->interrupt_in_urb); @@ -1006,6 +997,7 @@ static void iuu_init_termios(struct tty_struct *tty) static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port) { struct usb_serial *serial = port->serial; + struct device *dev = &port->dev; u8 *buf; int result; int baud; @@ -1017,7 +1009,7 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port) /* Re-encode speed */ tty_encode_baud_rate(tty, baud, baud); - dbg("%s - port %d, baud %d", __func__, port->number, baud); + dev_dbg(dev, "%s - baud %d\n", __func__, baud); usb_clear_halt(serial->dev, port->write_urb->pipe); usb_clear_halt(serial->dev, port->read_urb->pipe); @@ -1032,14 +1024,14 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port) result = usb_control_msg(port->serial->dev, \ usb_rcvctrlpipe(port->serial->dev, 0), \ b, a, c, d, buf, 1, 1000); \ - dbg("0x%x:0x%x:0x%x:0x%x %d - %x", a, b, c, d, result, \ + dev_dbg(dev, "0x%x:0x%x:0x%x:0x%x %d - %x\n", a, b, c, d, result, \ buf[0]); } while (0); #define SOUP(a, b, c, d) do { \ result = usb_control_msg(port->serial->dev, \ usb_sndctrlpipe(port->serial->dev, 0), \ b, a, c, d, NULL, 0, 1000); \ - dbg("0x%x:0x%x:0x%x:0x%x %d", a, b, c, d, result); } while (0) + dev_dbg(dev, "0x%x:0x%x:0x%x:0x%x %d\n", a, b, c, d, result); } while (0) /* This is not UART related but IUU USB driver related or something */ /* like that. Basically no IUU will accept any commands from the USB */ @@ -1119,7 +1111,7 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port) iuu_uart_flush(port); - dbg("%s - initialization done", __func__); + dev_dbg(dev, "%s - initialization done\n", __func__); memset(port->write_urb->transfer_buffer, IUU_UART_RX, 1); usb_fill_bulk_urb(port->write_urb, port->serial->dev, @@ -1129,11 +1121,10 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port) read_rxcmd_callback, port); result = usb_submit_urb(port->write_urb, GFP_KERNEL); if (result) { - dev_err(&port->dev, "%s - failed submitting read urb," - " error %d\n", __func__, result); + dev_err(dev, "%s - failed submitting read urb, error %d\n", __func__, result); iuu_close(port); } else { - dbg("%s - rxcmd OK", __func__); + dev_dbg(dev, "%s - rxcmd OK\n", __func__); } return result; @@ -1159,9 +1150,9 @@ static int iuu_vcc_set(struct usb_serial_port *port, unsigned int vcc) kfree(buf); if (status != IUU_OPERATION_OK) - dbg("%s - vcc error status = %2x", __func__, status); + dev_dbg(&port->dev, "%s - vcc error status = %2x\n", __func__, status); else - dbg("%s - vcc OK !", __func__); + dev_dbg(&port->dev, "%s - vcc OK !\n", __func__); return status; } @@ -1192,7 +1183,7 @@ static ssize_t store_vcc_mode(struct device *dev, goto fail_store_vcc_mode; } - dbg("%s: setting vcc_mode = %ld", __func__, v); + dev_dbg(dev, "%s: setting vcc_mode = %ld", __func__, v); if ((v != 3) && (v != 5)) { dev_err(dev, "%s - vcc_mode %ld is invalid\n", __func__, v); -- cgit v0.10.2 From 4a770ccaae1fd2ecad9dcc3f7942d3b163ecf362 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 15:08:30 -0700 Subject: USB: serial: mct_u232.c: remove dbg() usage dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. CC: Johan Hovold CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index a71fa0a..ab8f9ff 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -214,7 +214,7 @@ static int mct_u232_set_baud_rate(struct tty_struct *tty, value, rc); else tty_encode_baud_rate(tty, speed, speed); - dbg("set_baud_rate: value: 0x%x, divisor: 0x%x", value, divisor); + dev_dbg(&port->dev, "set_baud_rate: value: 0x%x, divisor: 0x%x\n", value, divisor); /* Mimic the MCT-supplied Windows driver (version 1.21P.0104), which always sends two extra USB 'device request' messages after the @@ -247,8 +247,8 @@ static int mct_u232_set_baud_rate(struct tty_struct *tty, if (port && C_CRTSCTS(tty)) cts_enable_byte = 1; - dbg("set_baud_rate: send second control message, data = %02X", - cts_enable_byte); + dev_dbg(&port->dev, "set_baud_rate: send second control message, data = %02X\n", + cts_enable_byte); buf[0] = cts_enable_byte; rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), MCT_U232_SET_CTS_REQUEST, @@ -263,7 +263,8 @@ static int mct_u232_set_baud_rate(struct tty_struct *tty, return rc; } /* mct_u232_set_baud_rate */ -static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr) +static int mct_u232_set_line_ctrl(struct usb_serial_port *port, + unsigned char lcr) { int rc; unsigned char *buf; @@ -273,20 +274,19 @@ static int mct_u232_set_line_ctrl(struct usb_serial *serial, unsigned char lcr) return -ENOMEM; buf[0] = lcr; - rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + rc = usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0), MCT_U232_SET_LINE_CTRL_REQUEST, MCT_U232_SET_REQUEST_TYPE, 0, 0, buf, MCT_U232_SET_LINE_CTRL_SIZE, WDR_TIMEOUT); if (rc < 0) - dev_err(&serial->dev->dev, - "Set LINE CTRL 0x%x failed (error = %d)\n", lcr, rc); - dbg("set_line_ctrl: 0x%x", lcr); + dev_err(&port->dev, "Set LINE CTRL 0x%x failed (error = %d)\n", lcr, rc); + dev_dbg(&port->dev, "set_line_ctrl: 0x%x\n", lcr); kfree(buf); return rc; } /* mct_u232_set_line_ctrl */ -static int mct_u232_set_modem_ctrl(struct usb_serial *serial, +static int mct_u232_set_modem_ctrl(struct usb_serial_port *port, unsigned int control_state) { int rc; @@ -304,25 +304,24 @@ static int mct_u232_set_modem_ctrl(struct usb_serial *serial, mcr |= MCT_U232_MCR_RTS; buf[0] = mcr; - rc = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), + rc = usb_control_msg(port->serial->dev, usb_sndctrlpipe(port->serial->dev, 0), MCT_U232_SET_MODEM_CTRL_REQUEST, MCT_U232_SET_REQUEST_TYPE, 0, 0, buf, MCT_U232_SET_MODEM_CTRL_SIZE, WDR_TIMEOUT); kfree(buf); - dbg("set_modem_ctrl: state=0x%x ==> mcr=0x%x", control_state, mcr); + dev_dbg(&port->dev, "set_modem_ctrl: state=0x%x ==> mcr=0x%x\n", control_state, mcr); if (rc < 0) { - dev_err(&serial->dev->dev, - "Set MODEM CTRL 0x%x failed (error = %d)\n", mcr, rc); + dev_err(&port->dev, "Set MODEM CTRL 0x%x failed (error = %d)\n", mcr, rc); return rc; } return 0; } /* mct_u232_set_modem_ctrl */ -static int mct_u232_get_modem_stat(struct usb_serial *serial, - unsigned char *msr) +static int mct_u232_get_modem_stat(struct usb_serial_port *port, + unsigned char *msr) { int rc; unsigned char *buf; @@ -332,19 +331,18 @@ static int mct_u232_get_modem_stat(struct usb_serial *serial, *msr = 0; return -ENOMEM; } - rc = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + rc = usb_control_msg(port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0), MCT_U232_GET_MODEM_STAT_REQUEST, MCT_U232_GET_REQUEST_TYPE, 0, 0, buf, MCT_U232_GET_MODEM_STAT_SIZE, WDR_TIMEOUT); if (rc < 0) { - dev_err(&serial->dev->dev, - "Get MODEM STATus failed (error = %d)\n", rc); + dev_err(&port->dev, "Get MODEM STATus failed (error = %d)\n", rc); *msr = 0; } else { *msr = buf[0]; } - dbg("get_modem_stat: 0x%x", *msr); + dev_dbg(&port->dev, "get_modem_stat: 0x%x\n", *msr); kfree(buf); return rc; } /* mct_u232_get_modem_stat */ @@ -363,8 +361,8 @@ static void mct_u232_msr_to_icount(struct async_icount *icount, icount->dcd++; } /* mct_u232_msr_to_icount */ -static void mct_u232_msr_to_state(unsigned int *control_state, - unsigned char msr) +static void mct_u232_msr_to_state(struct usb_serial_port *port, + unsigned int *control_state, unsigned char msr) { /* Translate Control Line states */ if (msr & MCT_U232_MSR_DSR) @@ -383,7 +381,7 @@ static void mct_u232_msr_to_state(unsigned int *control_state, *control_state |= TIOCM_CD; else *control_state &= ~TIOCM_CD; - dbg("msr_to_state: msr=0x%x ==> state=0x%x", msr, *control_state); + dev_dbg(&port->dev, "msr_to_state: msr=0x%x ==> state=0x%x\n", msr, *control_state); } /* mct_u232_msr_to_state */ /* @@ -465,14 +463,14 @@ static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port) control_state = priv->control_state; last_lcr = priv->last_lcr; spin_unlock_irqrestore(&priv->lock, flags); - mct_u232_set_modem_ctrl(serial, control_state); - mct_u232_set_line_ctrl(serial, last_lcr); + mct_u232_set_modem_ctrl(port, control_state); + mct_u232_set_line_ctrl(port, last_lcr); /* Read modem status and update control state */ - mct_u232_get_modem_stat(serial, &last_msr); + mct_u232_get_modem_stat(port, &last_msr); spin_lock_irqsave(&priv->lock, flags); priv->last_msr = last_msr; - mct_u232_msr_to_state(&priv->control_state, priv->last_msr); + mct_u232_msr_to_state(port, &priv->control_state, priv->last_msr); spin_unlock_irqrestore(&priv->lock, flags); retval = usb_submit_urb(port->read_urb, GFP_KERNEL); @@ -512,7 +510,7 @@ static void mct_u232_dtr_rts(struct usb_serial_port *port, int on) priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); control_state = priv->control_state; spin_unlock_irq(&priv->lock); - mct_u232_set_modem_ctrl(port->serial, control_state); + mct_u232_set_modem_ctrl(port, control_state); } mutex_unlock(&port->serial->disc_mutex); } @@ -532,7 +530,6 @@ static void mct_u232_read_int_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct mct_u232_private *priv = usb_get_serial_port_data(port); - struct usb_serial *serial = port->serial; struct tty_struct *tty; unsigned char *data = urb->transfer_buffer; int retval; @@ -547,20 +544,15 @@ static void mct_u232_read_int_callback(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", - __func__, status); + dev_dbg(&port->dev, "%s - urb shutting down with status: %d\n", + __func__, status); return; default: - dbg("%s - nonzero urb status received: %d", - __func__, status); + dev_dbg(&port->dev, "%s - nonzero urb status received: %d\n", + __func__, status); goto exit; } - if (!serial) { - dbg("%s - bad serial pointer, exiting", __func__); - return; - } - usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); @@ -588,7 +580,7 @@ static void mct_u232_read_int_callback(struct urb *urb) priv->last_msr = data[MCT_U232_MSR_INDEX]; /* Record Control Line states */ - mct_u232_msr_to_state(&priv->control_state, priv->last_msr); + mct_u232_msr_to_state(port, &priv->control_state, priv->last_msr); mct_u232_msr_to_icount(&priv->icount, priv->last_msr); @@ -656,18 +648,18 @@ static void mct_u232_set_termios(struct tty_struct *tty, /* reassert DTR and RTS on transition from B0 */ if ((old_cflag & CBAUD) == B0) { - dbg("%s: baud was B0", __func__); + dev_dbg(&port->dev, "%s: baud was B0\n", __func__); control_state |= TIOCM_DTR | TIOCM_RTS; - mct_u232_set_modem_ctrl(serial, control_state); + mct_u232_set_modem_ctrl(port, control_state); } mct_u232_set_baud_rate(tty, serial, port, tty_get_baud_rate(tty)); if ((cflag & CBAUD) == B0) { - dbg("%s: baud is B0", __func__); + dev_dbg(&port->dev, "%s: baud is B0\n", __func__); /* Drop RTS and DTR */ control_state &= ~(TIOCM_DTR | TIOCM_RTS); - mct_u232_set_modem_ctrl(serial, control_state); + mct_u232_set_modem_ctrl(port, control_state); } /* @@ -704,7 +696,7 @@ static void mct_u232_set_termios(struct tty_struct *tty, last_lcr |= (cflag & CSTOPB) ? MCT_U232_STOP_BITS_2 : MCT_U232_STOP_BITS_1; - mct_u232_set_line_ctrl(serial, last_lcr); + mct_u232_set_line_ctrl(port, last_lcr); /* save off the modified port settings */ spin_lock_irqsave(&priv->lock, flags); @@ -716,7 +708,6 @@ static void mct_u232_set_termios(struct tty_struct *tty, static void mct_u232_break_ctl(struct tty_struct *tty, int break_state) { struct usb_serial_port *port = tty->driver_data; - struct usb_serial *serial = port->serial; struct mct_u232_private *priv = usb_get_serial_port_data(port); unsigned char lcr; unsigned long flags; @@ -728,7 +719,7 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state) lcr |= MCT_U232_SET_BREAK; spin_unlock_irqrestore(&priv->lock, flags); - mct_u232_set_line_ctrl(serial, lcr); + mct_u232_set_line_ctrl(port, lcr); } /* mct_u232_break_ctl */ @@ -750,7 +741,6 @@ static int mct_u232_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; - struct usb_serial *serial = port->serial; struct mct_u232_private *priv = usb_get_serial_port_data(port); unsigned int control_state; unsigned long flags; @@ -769,7 +759,7 @@ static int mct_u232_tiocmset(struct tty_struct *tty, priv->control_state = control_state; spin_unlock_irqrestore(&priv->lock, flags); - return mct_u232_set_modem_ctrl(serial, control_state); + return mct_u232_set_modem_ctrl(port, control_state); } static void mct_u232_throttle(struct tty_struct *tty) @@ -784,7 +774,7 @@ static void mct_u232_throttle(struct tty_struct *tty) priv->control_state &= ~TIOCM_RTS; control_state = priv->control_state; spin_unlock_irq(&priv->lock); - (void) mct_u232_set_modem_ctrl(port->serial, control_state); + mct_u232_set_modem_ctrl(port, control_state); } else { spin_unlock_irq(&priv->lock); } @@ -802,7 +792,7 @@ static void mct_u232_unthrottle(struct tty_struct *tty) priv->control_state |= TIOCM_RTS; control_state = priv->control_state; spin_unlock_irq(&priv->lock); - (void) mct_u232_set_modem_ctrl(port->serial, control_state); + mct_u232_set_modem_ctrl(port, control_state); } else { spin_unlock_irq(&priv->lock); } @@ -817,13 +807,13 @@ static int mct_u232_ioctl(struct tty_struct *tty, struct async_icount cnow, cprev; unsigned long flags; - dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); + dev_dbg(&port->dev, "%s - cmd = 0x%x\n", __func__, cmd); switch (cmd) { case TIOCMIWAIT: - dbg("%s (%d) TIOCMIWAIT", __func__, port->number); + dev_dbg(&port->dev, "%s TIOCMIWAIT", __func__); spin_lock_irqsave(&mct_u232_port->lock, flags); cprev = mct_u232_port->icount; @@ -879,8 +869,8 @@ static int mct_u232_get_icount(struct tty_struct *tty, spin_unlock_irqrestore(&mct_u232_port->lock, flags); - dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", - __func__, port->number, icount->rx, icount->tx); + dev_dbg(&port->dev, "%s TIOCGICOUNT RX=%d, TX=%d\n", + __func__, icount->rx, icount->tx); return 0; } -- cgit v0.10.2 From 9eecf8085473c9bbe77d35ee84928696185cceed Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 15:08:33 -0700 Subject: USB: serial: mos7720.c: remove dbg() usage dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. CC: Johan Hovold CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 9817d9d..192191c 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -283,14 +283,17 @@ static void send_deferred_urbs(unsigned long _mos_parport) struct mos7715_parport *mos_parport = (void *)_mos_parport; struct urbtracker *urbtrack, *tmp; struct list_head *cursor, *next; + struct device *dev; /* if release function ran, game over */ if (unlikely(mos_parport->serial == NULL)) return; + dev = &mos_parport->serial->dev->dev; + /* try again to get the mutex */ if (!mutex_trylock(&mos_parport->serial->disc_mutex)) { - dbg("%s: rescheduling tasklet", __func__); + dev_dbg(dev, "%s: rescheduling tasklet\n", __func__); tasklet_schedule(&mos_parport->urb_tasklet); return; } @@ -305,7 +308,7 @@ static void send_deferred_urbs(unsigned long _mos_parport) if (list_empty(&mos_parport->deferred_urbs)) { spin_unlock_irqrestore(&mos_parport->listlock, flags); mutex_unlock(&mos_parport->serial->disc_mutex); - dbg("%s: deferred_urbs list empty", __func__); + dev_dbg(dev, "%s: deferred_urbs list empty\n", __func__); return; } @@ -315,10 +318,9 @@ static void send_deferred_urbs(unsigned long _mos_parport) list_for_each_entry_safe(urbtrack, tmp, &mos_parport->active_urbs, urblist_entry) { ret_val = usb_submit_urb(urbtrack->urb, GFP_ATOMIC); - dbg("%s: urb submitted", __func__); + dev_dbg(dev, "%s: urb submitted\n", __func__); if (ret_val) { - dev_err(&mos_parport->serial->dev->dev, - "usb_submit_urb() failed: %d", ret_val); + dev_err(dev, "usb_submit_urb() failed: %d\n", ret_val); list_del(&urbtrack->urblist_entry); kref_put(&urbtrack->ref_count, destroy_urbtracker); } @@ -334,7 +336,7 @@ static void async_complete(struct urb *urb) int status = urb->status; if (unlikely(status)) - dbg("%s - nonzero urb status received: %d", __func__, status); + dev_dbg(&urb->dev->dev, "%s - nonzero urb status received: %d\n", __func__, status); /* remove the urbtracker from the active_urbs list */ spin_lock(&urbtrack->mos_parport->listlock); @@ -389,7 +391,7 @@ static int write_parport_reg_nonblock(struct mos7715_parport *mos_parport, &mos_parport->deferred_urbs); spin_unlock_irqrestore(&mos_parport->listlock, flags); tasklet_schedule(&mos_parport->urb_tasklet); - dbg("tasklet scheduled"); + dev_dbg(&usbdev->dev, "tasklet scheduled"); return 0; } @@ -690,7 +692,7 @@ static int mos7715_parport_init(struct usb_serial *serial) /* allocate and initialize parallel port control struct */ mos_parport = kzalloc(sizeof(struct mos7715_parport), GFP_KERNEL); if (mos_parport == NULL) { - dbg("mos7715_parport_init: kzalloc failed"); + dev_dbg(&serial->dev->dev, "%s: kzalloc failed\n", __func__); return -ENOMEM; } mos_parport->msg_pending = false; @@ -743,6 +745,7 @@ static void mos7720_interrupt_callback(struct urb *urb) int result; int length; int status = urb->status; + struct device *dev = &urb->dev->dev; __u8 *data; __u8 sp1; __u8 sp2; @@ -755,12 +758,10 @@ static void mos7720_interrupt_callback(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __func__, - status); + dev_dbg(dev, "%s - urb shutting down with status: %d\n", __func__, status); return; default: - dbg("%s - nonzero urb status received: %d", __func__, - status); + dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status); goto exit; } @@ -777,7 +778,7 @@ static void mos7720_interrupt_callback(struct urb *urb) * oneukum 2007-03-14 */ if (unlikely(length != 4)) { - dbg("Wrong data !!!"); + dev_dbg(dev, "Wrong data !!!\n"); return; } @@ -786,31 +787,29 @@ static void mos7720_interrupt_callback(struct urb *urb) if ((sp1 | sp2) & 0x01) { /* No Interrupt Pending in both the ports */ - dbg("No Interrupt !!!"); + dev_dbg(dev, "No Interrupt !!!\n"); } else { switch (sp1 & 0x0f) { case SERIAL_IIR_RLS: - dbg("Serial Port 1: Receiver status error or address " - "bit detected in 9-bit mode\n"); + dev_dbg(dev, "Serial Port 1: Receiver status error or address bit detected in 9-bit mode\n"); break; case SERIAL_IIR_CTI: - dbg("Serial Port 1: Receiver time out"); + dev_dbg(dev, "Serial Port 1: Receiver time out\n"); break; case SERIAL_IIR_MS: - /* dbg("Serial Port 1: Modem status change"); */ + /* dev_dbg(dev, "Serial Port 1: Modem status change\n"); */ break; } switch (sp2 & 0x0f) { case SERIAL_IIR_RLS: - dbg("Serial Port 2: Receiver status error or address " - "bit detected in 9-bit mode"); + dev_dbg(dev, "Serial Port 2: Receiver status error or address bit detected in 9-bit mode\n"); break; case SERIAL_IIR_CTI: - dbg("Serial Port 2: Receiver time out"); + dev_dbg(dev, "Serial Port 2: Receiver time out\n"); break; case SERIAL_IIR_MS: - /* dbg("Serial Port 2: Modem status change"); */ + /* dev_dbg(dev, "Serial Port 2: Modem status change\n"); */ break; } } @@ -818,9 +817,7 @@ static void mos7720_interrupt_callback(struct urb *urb) exit: result = usb_submit_urb(urb, GFP_ATOMIC); if (result) - dev_err(&urb->dev->dev, - "%s - Error %d submitting control urb\n", - __func__, result); + dev_err(dev, "%s - Error %d submitting control urb\n", __func__, result); } /* @@ -833,6 +830,7 @@ static void mos7715_interrupt_callback(struct urb *urb) int result; int length; int status = urb->status; + struct device *dev = &urb->dev->dev; __u8 *data; __u8 iir; @@ -845,12 +843,10 @@ static void mos7715_interrupt_callback(struct urb *urb) case -ESHUTDOWN: case -ENODEV: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __func__, - status); + dev_dbg(dev, "%s - urb shutting down with status: %d\n", __func__, status); return; default: - dbg("%s - nonzero urb status received: %d", __func__, - status); + dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status); goto exit; } @@ -864,7 +860,7 @@ static void mos7715_interrupt_callback(struct urb *urb) * Byte 4: FIFO status for both */ if (unlikely(length != 4)) { - dbg("Wrong data !!!"); + dev_dbg(dev, "Wrong data !!!\n"); return; } @@ -872,14 +868,13 @@ static void mos7715_interrupt_callback(struct urb *urb) if (!(iir & 0x01)) { /* serial port interrupt pending */ switch (iir & 0x0f) { case SERIAL_IIR_RLS: - dbg("Serial Port: Receiver status error or address " - "bit detected in 9-bit mode\n"); + dev_dbg(dev, "Serial Port: Receiver status error or address bit detected in 9-bit mode\n\n"); break; case SERIAL_IIR_CTI: - dbg("Serial Port: Receiver time out"); + dev_dbg(dev, "Serial Port: Receiver time out\n"); break; case SERIAL_IIR_MS: - /* dbg("Serial Port: Modem status change"); */ + /* dev_dbg(dev, "Serial Port: Modem status change\n"); */ break; } } @@ -897,9 +892,7 @@ static void mos7715_interrupt_callback(struct urb *urb) exit: result = usb_submit_urb(urb, GFP_ATOMIC); if (result) - dev_err(&urb->dev->dev, - "%s - Error %d submitting control urb\n", - __func__, result); + dev_err(dev, "%s - Error %d submitting control urb\n", __func__, result); } /* @@ -916,13 +909,13 @@ static void mos7720_bulk_in_callback(struct urb *urb) int status = urb->status; if (status) { - dbg("nonzero read bulk status received: %d", status); + dev_dbg(&urb->dev->dev, "nonzero read bulk status received: %d\n", status); return; } port = urb->context; - dbg("Entering...%s", __func__); + dev_dbg(&port->dev, "Entering...%s\n", __func__); data = urb->transfer_buffer; @@ -936,8 +929,7 @@ static void mos7720_bulk_in_callback(struct urb *urb) if (port->read_urb->status != -EINPROGRESS) { retval = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (retval) - dbg("usb_submit_urb(read bulk) failed, retval = %d", - retval); + dev_dbg(&port->dev, "usb_submit_urb(read bulk) failed, retval = %d\n", retval); } } @@ -953,13 +945,13 @@ static void mos7720_bulk_out_data_callback(struct urb *urb) int status = urb->status; if (status) { - dbg("nonzero write bulk status received:%d", status); + dev_dbg(&urb->dev->dev, "nonzero write bulk status received:%d\n", status); return; } mos7720_port = urb->context; if (!mos7720_port) { - dbg("NULL mos7720_port pointer"); + dev_dbg(&urb->dev->dev, "NULL mos7720_port pointer\n"); return ; } @@ -1061,9 +1053,7 @@ static int mos7720_open(struct tty_struct *tty, struct usb_serial_port *port) port_number = port->number - port->serial->minor; read_mos_reg(serial, port_number, LSR, &data); - dbg("SS::%p LSR:%x", mos7720_port, data); - - dbg("Check:Sending Command .........."); + dev_dbg(&port->dev, "SS::%p LSR:%x\n", mos7720_port, data); write_mos_reg(serial, dummy, SP1_REG, 0x02); write_mos_reg(serial, dummy, SP2_REG, 0x02); @@ -1122,20 +1112,16 @@ static int mos7720_chars_in_buffer(struct tty_struct *tty) int chars = 0; struct moschip_port *mos7720_port; - dbg("%s:entering ...........", __func__); - mos7720_port = usb_get_serial_port_data(port); - if (mos7720_port == NULL) { - dbg("%s:leaving ...........", __func__); + if (mos7720_port == NULL) return 0; - } for (i = 0; i < NUM_URBS; ++i) { if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status == -EINPROGRESS) chars += URB_TRANSFER_BUFFER_SIZE; } - dbg("%s - returns %d", __func__, chars); + dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars); return chars; } @@ -1145,8 +1131,6 @@ static void mos7720_close(struct usb_serial_port *port) struct moschip_port *mos7720_port; int j; - dbg("mos7720_close:entering..."); - serial = port->serial; mos7720_port = usb_get_serial_port_data(port); @@ -1166,9 +1150,7 @@ static void mos7720_close(struct usb_serial_port *port) /* While closing port, shutdown all bulk read, write * * and interrupt read if they exists, otherwise nop */ - dbg("Shutdown bulk write"); usb_kill_urb(port->write_urb); - dbg("Shutdown bulk read"); usb_kill_urb(port->read_urb); mutex_lock(&serial->disc_mutex); @@ -1182,8 +1164,6 @@ static void mos7720_close(struct usb_serial_port *port) } mutex_unlock(&serial->disc_mutex); mos7720_port->open = 0; - - dbg("Leaving %s", __func__); } static void mos7720_break(struct tty_struct *tty, int break_state) @@ -1193,8 +1173,6 @@ static void mos7720_break(struct tty_struct *tty, int break_state) struct usb_serial *serial; struct moschip_port *mos7720_port; - dbg("Entering %s", __func__); - serial = port->serial; mos7720_port = usb_get_serial_port_data(port); @@ -1225,13 +1203,9 @@ static int mos7720_write_room(struct tty_struct *tty) int room = 0; int i; - dbg("%s:entering ...........", __func__); - mos7720_port = usb_get_serial_port_data(port); - if (mos7720_port == NULL) { - dbg("%s:leaving ...........", __func__); + if (mos7720_port == NULL) return -ENODEV; - } /* FIXME: Locking */ for (i = 0; i < NUM_URBS; ++i) { @@ -1240,7 +1214,7 @@ static int mos7720_write_room(struct tty_struct *tty) room += URB_TRANSFER_BUFFER_SIZE; } - dbg("%s - returns %d", __func__, room); + dev_dbg(&port->dev, "%s - returns %d\n", __func__, room); return room; } @@ -1257,15 +1231,11 @@ static int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port, struct urb *urb; const unsigned char *current_position = data; - dbg("%s:entering ...........", __func__); - serial = port->serial; mos7720_port = usb_get_serial_port_data(port); - if (mos7720_port == NULL) { - dbg("mos7720_port is NULL"); + if (mos7720_port == NULL) return -ENODEV; - } /* try to find a free urb in the list */ urb = NULL; @@ -1274,13 +1244,13 @@ static int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port, if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status != -EINPROGRESS) { urb = mos7720_port->write_urb_pool[i]; - dbg("URB:%d", i); + dev_dbg(&port->dev, "URB:%d\n", i); break; } } if (urb == NULL) { - dbg("%s - no more free urbs", __func__); + dev_dbg(&port->dev, "%s - no more free urbs\n", __func__); goto exit; } @@ -1326,20 +1296,16 @@ static void mos7720_throttle(struct tty_struct *tty) struct moschip_port *mos7720_port; int status; - dbg("%s- port %d", __func__, port->number); - mos7720_port = usb_get_serial_port_data(port); if (mos7720_port == NULL) return; if (!mos7720_port->open) { - dbg("port not opened"); + dev_dbg(&port->dev, "%s - port not opened\n", __func__); return; } - dbg("%s: Entering ..........", __func__); - /* if we are implementing XON/XOFF, send the stop character */ if (I_IXOFF(tty)) { unsigned char stop_char = STOP_CHAR(tty); @@ -1368,12 +1334,10 @@ static void mos7720_unthrottle(struct tty_struct *tty) return; if (!mos7720_port->open) { - dbg("%s - port not opened", __func__); + dev_dbg(&port->dev, "%s - port not opened\n", __func__); return; } - dbg("%s: Entering ..........", __func__); - /* if we are implementing XON/XOFF, send the start character */ if (I_IXOFF(tty)) { unsigned char start_char = START_CHAR(tty); @@ -1409,7 +1373,7 @@ static int set_higher_rates(struct moschip_port *mos7720_port, /*********************************************** * Init Sequence for higher rates ***********************************************/ - dbg("Sending Setting Commands .........."); + dev_dbg(&port->dev, "Sending Setting Commands ..........\n"); port_number = port->number - port->serial->minor; write_mos_reg(serial, port_number, IER, 0x00); @@ -1478,7 +1442,7 @@ static struct divisor_table_entry divisor_table[] = { * this function calculates the proper baud rate divisor for the specified * baud rate. *****************************************************************************/ -static int calc_baud_rate_divisor(int baudrate, int *divisor) +static int calc_baud_rate_divisor(struct usb_serial_port *port, int baudrate, int *divisor) { int i; __u16 custom; @@ -1486,7 +1450,7 @@ static int calc_baud_rate_divisor(int baudrate, int *divisor) __u16 round; - dbg("%s - %d", __func__, baudrate); + dev_dbg(&port->dev, "%s - %d\n", __func__, baudrate); for (i = 0; i < ARRAY_SIZE(divisor_table); i++) { if (divisor_table[i].baudrate == baudrate) { @@ -1508,11 +1472,11 @@ static int calc_baud_rate_divisor(int baudrate, int *divisor) custom++; *divisor = custom; - dbg("Baud %d = %d", baudrate, custom); + dev_dbg(&port->dev, "Baud %d = %d\n", baudrate, custom); return 0; } - dbg("Baud calculation Failed..."); + dev_dbg(&port->dev, "Baud calculation Failed...\n"); return -EINVAL; } @@ -1536,13 +1500,11 @@ static int send_cmd_write_baud_rate(struct moschip_port *mos7720_port, port = mos7720_port->port; serial = port->serial; - dbg("%s: Entering ..........", __func__); - number = port->number - port->serial->minor; - dbg("%s - port = %d, baud = %d", __func__, port->number, baudrate); + dev_dbg(&port->dev, "%s - baud = %d\n", __func__, baudrate); /* Calculate the Divisor */ - status = calc_baud_rate_divisor(baudrate, &divisor); + status = calc_baud_rate_divisor(port, baudrate, &divisor); if (status) { dev_err(&port->dev, "%s - bad baud rate\n", __func__); return status; @@ -1591,15 +1553,11 @@ static void change_port_settings(struct tty_struct *tty, serial = port->serial; port_number = port->number - port->serial->minor; - dbg("%s - port %d", __func__, port->number); - if (!mos7720_port->open) { - dbg("%s - port not opened", __func__); + dev_dbg(&port->dev, "%s - port not opened\n", __func__); return; } - dbg("%s: Entering ..........", __func__); - lData = UART_LCR_WLEN8; lStop = 0x00; /* 1 stop bit */ lParity = 0x00; /* No parity */ @@ -1633,14 +1591,14 @@ static void change_port_settings(struct tty_struct *tty, if (cflag & PARENB) { if (cflag & PARODD) { lParity = UART_LCR_PARITY; - dbg("%s - parity = odd", __func__); + dev_dbg(&port->dev, "%s - parity = odd\n", __func__); } else { lParity = (UART_LCR_EPAR | UART_LCR_PARITY); - dbg("%s - parity = even", __func__); + dev_dbg(&port->dev, "%s - parity = even\n", __func__); } } else { - dbg("%s - parity = none", __func__); + dev_dbg(&port->dev, "%s - parity = none\n", __func__); } if (cflag & CMSPAR) @@ -1649,10 +1607,10 @@ static void change_port_settings(struct tty_struct *tty, /* Change the Stop bit */ if (cflag & CSTOPB) { lStop = UART_LCR_STOP; - dbg("%s - stop bits = 2", __func__); + dev_dbg(&port->dev, "%s - stop bits = 2\n", __func__); } else { lStop = 0x00; - dbg("%s - stop bits = 1", __func__); + dev_dbg(&port->dev, "%s - stop bits = 1\n", __func__); } #define LCR_BITS_MASK 0x03 /* Mask for bits/char field */ @@ -1698,7 +1656,7 @@ static void change_port_settings(struct tty_struct *tty, baud = tty_get_baud_rate(tty); if (!baud) { /* pick a default, any default... */ - dbg("Picked default baud..."); + dev_dbg(&port->dev, "Picked default baud...\n"); baud = 9600; } @@ -1709,7 +1667,7 @@ static void change_port_settings(struct tty_struct *tty, return; } - dbg("%s - baud rate = %d", __func__, baud); + dev_dbg(&port->dev, "%s - baud rate = %d\n", __func__, baud); status = send_cmd_write_baud_rate(mos7720_port, baud); /* FIXME: needs to write actual resulting baud back not just blindly do so */ @@ -1721,8 +1679,7 @@ static void change_port_settings(struct tty_struct *tty, if (port->read_urb->status != -EINPROGRESS) { status = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (status) - dbg("usb_submit_urb(read bulk) failed, status = %d", - status); + dev_dbg(&port->dev, "usb_submit_urb(read bulk) failed, status = %d\n", status); } } @@ -1747,23 +1704,19 @@ static void mos7720_set_termios(struct tty_struct *tty, return; if (!mos7720_port->open) { - dbg("%s - port not opened", __func__); + dev_dbg(&port->dev, "%s - port not opened\n", __func__); return; } - dbg("%s\n", "setting termios - ASPIRE"); + dev_dbg(&port->dev, "setting termios - ASPIRE\n"); cflag = tty->termios->c_cflag; - dbg("%s - cflag %08x iflag %08x", __func__, - tty->termios->c_cflag, - RELEVANT_IFLAG(tty->termios->c_iflag)); + dev_dbg(&port->dev, "%s - cflag %08x iflag %08x\n", __func__, + tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag)); - dbg("%s - old cflag %08x old iflag %08x", __func__, - old_termios->c_cflag, - RELEVANT_IFLAG(old_termios->c_iflag)); - - dbg("%s - port %d", __func__, port->number); + dev_dbg(&port->dev, "%s - old cflag %08x old iflag %08x\n", __func__, + old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag)); /* change the port settings to the new ones specified */ change_port_settings(tty, mos7720_port, old_termios); @@ -1771,8 +1724,7 @@ static void mos7720_set_termios(struct tty_struct *tty, if (port->read_urb->status != -EINPROGRESS) { status = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (status) - dbg("usb_submit_urb(read bulk) failed, status = %d", - status); + dev_dbg(&port->dev, "usb_submit_urb(read bulk) failed, status = %d\n", status); } } @@ -1800,7 +1752,7 @@ static int get_lsr_info(struct tty_struct *tty, read_mos_reg(port->serial, port_number, LSR, &data); if ((data & (UART_LSR_TEMT | UART_LSR_THRE)) == (UART_LSR_TEMT | UART_LSR_THRE)) { - dbg("%s -- Empty", __func__); + dev_dbg(&port->dev, "%s -- Empty\n", __func__); result = TIOCSER_TEMT; } } @@ -1817,8 +1769,6 @@ static int mos7720_tiocmget(struct tty_struct *tty) unsigned int mcr ; unsigned int msr ; - dbg("%s - port %d", __func__, port->number); - mcr = mos7720_port->shadowMCR; msr = mos7720_port->shadowMSR; @@ -1829,8 +1779,6 @@ static int mos7720_tiocmget(struct tty_struct *tty) | ((msr & UART_MSR_RI) ? TIOCM_RI : 0) /* 0x080 */ | ((msr & UART_MSR_DSR) ? TIOCM_DSR : 0); /* 0x100 */ - dbg("%s -- %x", __func__, result); - return result; } @@ -1840,8 +1788,6 @@ static int mos7720_tiocmset(struct tty_struct *tty, struct usb_serial_port *port = tty->driver_data; struct moschip_port *mos7720_port = usb_get_serial_port_data(port); unsigned int mcr ; - dbg("%s - port %d", __func__, port->number); - dbg("he was at tiocmset"); mcr = mos7720_port->shadowMCR; @@ -1888,8 +1834,8 @@ static int mos7720_get_icount(struct tty_struct *tty, icount->brk = cnow.brk; icount->buf_overrun = cnow.buf_overrun; - dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, - port->number, icount->rx, icount->tx); + dev_dbg(&port->dev, "%s TIOCGICOUNT RX=%d, TX=%d\n", __func__, + icount->rx, icount->tx); return 0; } @@ -1975,29 +1921,28 @@ static int mos7720_ioctl(struct tty_struct *tty, if (mos7720_port == NULL) return -ENODEV; - dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); + dev_dbg(&port->dev, "%s - cmd = 0x%x", __func__, cmd); switch (cmd) { case TIOCSERGETLSR: - dbg("%s (%d) TIOCSERGETLSR", __func__, port->number); + dev_dbg(&port->dev, "%s TIOCSERGETLSR\n", __func__); return get_lsr_info(tty, mos7720_port, (unsigned int __user *)arg); /* FIXME: These should be using the mode methods */ case TIOCMBIS: case TIOCMBIC: - dbg("%s (%d) TIOCMSET/TIOCMBIC/TIOCMSET", - __func__, port->number); + dev_dbg(&port->dev, "%s TIOCMSET/TIOCMBIC/TIOCMSET\n", __func__); return set_modem_info(mos7720_port, cmd, (unsigned int __user *)arg); case TIOCGSERIAL: - dbg("%s (%d) TIOCGSERIAL", __func__, port->number); + dev_dbg(&port->dev, "%s TIOCGSERIAL\n", __func__); return get_serial_info(mos7720_port, (struct serial_struct __user *)arg); case TIOCMIWAIT: - dbg("%s (%d) TIOCMIWAIT", __func__, port->number); + dev_dbg(&port->dev, "%s TIOCMIWAIT\n", __func__); cprev = mos7720_port->icount; while (1) { if (signal_pending(current)) @@ -2030,13 +1975,6 @@ static int mos7720_startup(struct usb_serial *serial) u16 product; int ret_val; - dbg("%s: Entering ..........", __func__); - - if (!serial) { - dbg("Invalid Handler"); - return -ENODEV; - } - product = le16_to_cpu(serial->dev->descriptor.idProduct); dev = serial->dev; @@ -2081,8 +2019,8 @@ static int mos7720_startup(struct usb_serial *serial) mos7720_port->port = serial->port[i]; usb_set_serial_port_data(serial->port[i], mos7720_port); - dbg("port number is %d", serial->port[i]->number); - dbg("serial number is %d", serial->minor); + dev_dbg(&dev->dev, "port number is %d\n", serial->port[i]->number); + dev_dbg(&dev->dev, "serial number is %d\n", serial->minor); } @@ -2106,7 +2044,7 @@ static int mos7720_startup(struct usb_serial *serial) #endif /* LSR For Port 1 */ read_mos_reg(serial, 0, LSR, &data); - dbg("LSR:%x", data); + dev_dbg(&dev->dev, "LSR:%x\n", data); return 0; } -- cgit v0.10.2 From d53839cf446c93dddea92d83e9a0c8afc1a8dbba Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 15:08:36 -0700 Subject: USB: serial: ti_usb_3410_5052.c: remove dbg() usage dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. CC: Johan Hovold CC: Rusty Russell CC: Adhir Ramjiawan CC: Andrew Lunn Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index a4404f5..0b113fa 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -141,8 +141,8 @@ static int ti_command_out_sync(struct ti_device *tdev, __u8 command, static int ti_command_in_sync(struct ti_device *tdev, __u8 command, __u16 moduleid, __u16 value, __u8 *data, int size); -static int ti_write_byte(struct ti_device *tdev, unsigned long addr, - __u8 mask, __u8 byte); +static int ti_write_byte(struct usb_serial_port *port, struct ti_device *tdev, + unsigned long addr, __u8 mask, __u8 byte); static int ti_download_firmware(struct ti_device *tdev); @@ -364,10 +364,11 @@ static int ti_startup(struct usb_serial *serial) int i; - dbg("%s - product 0x%4X, num configurations %d, configuration value %d", - __func__, le16_to_cpu(dev->descriptor.idProduct), - dev->descriptor.bNumConfigurations, - dev->actconfig->desc.bConfigurationValue); + dev_dbg(&dev->dev, + "%s - product 0x%4X, num configurations %d, configuration value %d", + __func__, le16_to_cpu(dev->descriptor.idProduct), + dev->descriptor.bNumConfigurations, + dev->actconfig->desc.bConfigurationValue); /* create device structure */ tdev = kzalloc(sizeof(struct ti_device), GFP_KERNEL); @@ -382,8 +383,8 @@ static int ti_startup(struct usb_serial *serial) /* determine device type */ if (usb_match_id(serial->interface, ti_id_table_3410)) tdev->td_is_3410 = 1; - dbg("%s - device type is %s", __func__, - tdev->td_is_3410 ? "3410" : "5052"); + dev_dbg(&dev->dev, "%s - device type is %s\n", __func__, + tdev->td_is_3410 ? "3410" : "5052"); /* if we have only 1 configuration, download firmware */ if (dev->descriptor.bNumConfigurations == 1) { @@ -501,20 +502,17 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port) /* start interrupt urb the first time a port is opened on this device */ if (tdev->td_open_port_count == 0) { - dbg("%s - start interrupt in urb", __func__); + dev_dbg(&port->dev, "%s - start interrupt in urb\n", __func__); urb = tdev->td_serial->port[0]->interrupt_in_urb; if (!urb) { - dev_err(&port->dev, "%s - no interrupt urb\n", - __func__); + dev_err(&port->dev, "%s - no interrupt urb\n", __func__); status = -EINVAL; goto release_lock; } urb->context = tdev; status = usb_submit_urb(urb, GFP_KERNEL); if (status) { - dev_err(&port->dev, - "%s - submit interrupt urb failed, %d\n", - __func__, status); + dev_err(&port->dev, "%s - submit interrupt urb failed, %d\n", __func__, status); goto release_lock; } } @@ -522,16 +520,16 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port) if (tty) ti_set_termios(tty, port, tty->termios); - dbg("%s - sending TI_OPEN_PORT", __func__); + dev_dbg(&port->dev, "%s - sending TI_OPEN_PORT\n", __func__); status = ti_command_out_sync(tdev, TI_OPEN_PORT, (__u8)(TI_UART1_PORT + port_number), open_settings, NULL, 0); if (status) { dev_err(&port->dev, "%s - cannot send open command, %d\n", - __func__, status); + __func__, status); goto unlink_int_urb; } - dbg("%s - sending TI_START_PORT", __func__); + dev_dbg(&port->dev, "%s - sending TI_START_PORT\n", __func__); status = ti_command_out_sync(tdev, TI_START_PORT, (__u8)(TI_UART1_PORT + port_number), 0, NULL, 0); if (status) { @@ -540,7 +538,7 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port) goto unlink_int_urb; } - dbg("%s - sending TI_PURGE_PORT", __func__); + dev_dbg(&port->dev, "%s - sending TI_PURGE_PORT\n", __func__); status = ti_command_out_sync(tdev, TI_PURGE_PORT, (__u8)(TI_UART1_PORT + port_number), TI_PURGE_INPUT, NULL, 0); if (status) { @@ -564,7 +562,7 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port) if (tty) ti_set_termios(tty, port, tty->termios); - dbg("%s - sending TI_OPEN_PORT (2)", __func__); + dev_dbg(&port->dev, "%s - sending TI_OPEN_PORT (2)\n", __func__); status = ti_command_out_sync(tdev, TI_OPEN_PORT, (__u8)(TI_UART1_PORT + port_number), open_settings, NULL, 0); if (status) { @@ -573,7 +571,7 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port) goto unlink_int_urb; } - dbg("%s - sending TI_START_PORT (2)", __func__); + dev_dbg(&port->dev, "%s - sending TI_START_PORT (2)\n", __func__); status = ti_command_out_sync(tdev, TI_START_PORT, (__u8)(TI_UART1_PORT + port_number), 0, NULL, 0); if (status) { @@ -583,7 +581,7 @@ static int ti_open(struct tty_struct *tty, struct usb_serial_port *port) } /* start read urb */ - dbg("%s - start read urb", __func__); + dev_dbg(&port->dev, "%s - start read urb\n", __func__); urb = port->read_urb; if (!urb) { dev_err(&port->dev, "%s - no read urb\n", __func__); @@ -609,7 +607,7 @@ unlink_int_urb: usb_kill_urb(port->serial->port[0]->interrupt_in_urb); release_lock: mutex_unlock(&tdev->td_open_close_lock); - dbg("%s - exit %d", __func__, status); + dev_dbg(&port->dev, "%s - exit %d\n", __func__, status); return status; } @@ -637,7 +635,7 @@ static void ti_close(struct usb_serial_port *port) port_number = port->number - port->serial->minor; - dbg("%s - sending TI_CLOSE_PORT", __func__); + dev_dbg(&port->dev, "%s - sending TI_CLOSE_PORT\n", __func__); status = ti_command_out_sync(tdev, TI_CLOSE_PORT, (__u8)(TI_UART1_PORT + port_number), 0, NULL, 0); if (status) @@ -664,7 +662,7 @@ static int ti_write(struct tty_struct *tty, struct usb_serial_port *port, struct ti_port *tport = usb_get_serial_port_data(port); if (count == 0) { - dbg("%s - write request of 0 bytes", __func__); + dev_dbg(&port->dev, "%s - write request of 0 bytes\n", __func__); return 0; } @@ -693,7 +691,7 @@ static int ti_write_room(struct tty_struct *tty) room = kfifo_avail(&tport->write_fifo); spin_unlock_irqrestore(&tport->tp_lock, flags); - dbg("%s - returns %d", __func__, room); + dev_dbg(&port->dev, "%s - returns %d\n", __func__, room); return room; } @@ -712,7 +710,7 @@ static int ti_chars_in_buffer(struct tty_struct *tty) chars = kfifo_len(&tport->write_fifo); spin_unlock_irqrestore(&tport->tp_lock, flags); - dbg("%s - returns %d", __func__, chars); + dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars); return chars; } @@ -755,8 +753,7 @@ static int ti_get_icount(struct tty_struct *tty, struct ti_port *tport = usb_get_serial_port_data(port); struct async_icount cnow = tport->tp_icount; - dbg("%s - (%d) TIOCGICOUNT RX=%d, TX=%d", - __func__, port->number, + dev_dbg(&port->dev, "%s - TIOCGICOUNT RX=%d, TX=%d\n", __func__, cnow.rx, cnow.tx); icount->cts = cnow.cts; @@ -782,22 +779,22 @@ static int ti_ioctl(struct tty_struct *tty, struct async_icount cnow; struct async_icount cprev; - dbg("%s - port %d, cmd = 0x%04X", __func__, port->number, cmd); + dev_dbg(&port->dev, "%s - cmd = 0x%04X\n", __func__, cmd); if (tport == NULL) return -ENODEV; switch (cmd) { case TIOCGSERIAL: - dbg("%s - (%d) TIOCGSERIAL", __func__, port->number); + dev_dbg(&port->dev, "%s - TIOCGSERIAL\n", __func__); return ti_get_serial_info(tport, (struct serial_struct __user *)arg); case TIOCSSERIAL: - dbg("%s - (%d) TIOCSSERIAL", __func__, port->number); + dev_dbg(&port->dev, "%s - TIOCSSERIAL\n", __func__); return ti_set_serial_info(tty, tport, (struct serial_struct __user *)arg); case TIOCMIWAIT: - dbg("%s - (%d) TIOCMIWAIT", __func__, port->number); + dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__); cprev = tport->tp_icount; while (1) { interruptible_sleep_on(&tport->tp_msr_wait); @@ -834,9 +831,9 @@ static void ti_set_termios(struct tty_struct *tty, cflag = tty->termios->c_cflag; iflag = tty->termios->c_iflag; - dbg("%s - cflag %08x, iflag %08x", __func__, cflag, iflag); - dbg("%s - old clfag %08x, old iflag %08x", __func__, - old_termios->c_cflag, old_termios->c_iflag); + dev_dbg(&port->dev, "%s - cflag %08x, iflag %08x\n", __func__, cflag, iflag); + dev_dbg(&port->dev, "%s - old clfag %08x, old iflag %08x\n", __func__, + old_termios->c_cflag, old_termios->c_iflag); if (tport == NULL) return; @@ -926,8 +923,11 @@ static void ti_set_termios(struct tty_struct *tty, if ((cflag & CBAUD) != B0) tty_encode_baud_rate(tty, baud, baud); - dbg("%s - BaudRate=%d, wBaudRate=%d, wFlags=0x%04X, bDataBits=%d, bParity=%d, bStopBits=%d, cXon=%d, cXoff=%d, bUartMode=%d", - __func__, baud, config->wBaudRate, config->wFlags, config->bDataBits, config->bParity, config->bStopBits, config->cXon, config->cXoff, config->bUartMode); + dev_dbg(&port->dev, + "%s - BaudRate=%d, wBaudRate=%d, wFlags=0x%04X, bDataBits=%d, bParity=%d, bStopBits=%d, cXon=%d, cXoff=%d, bUartMode=%d", + __func__, baud, config->wBaudRate, config->wFlags, + config->bDataBits, config->bParity, config->bStopBits, + config->cXon, config->cXoff, config->bUartMode); cpu_to_be16s(&config->wBaudRate); cpu_to_be16s(&config->wFlags); @@ -979,7 +979,7 @@ static int ti_tiocmget(struct tty_struct *tty) | ((msr & TI_MSR_RI) ? TIOCM_RI : 0) | ((msr & TI_MSR_DSR) ? TIOCM_DSR : 0); - dbg("%s - 0x%04X", __func__, result); + dev_dbg(&port->dev, "%s - 0x%04X\n", __func__, result); return result; } @@ -1024,19 +1024,19 @@ static void ti_break(struct tty_struct *tty, int break_state) struct ti_port *tport = usb_get_serial_port_data(port); int status; - dbg("%s - state = %d", __func__, break_state); + dev_dbg(&port->dev, "%s - state = %d\n", __func__, break_state); if (tport == NULL) return; ti_drain(tport, (tport->tp_closing_wait*HZ)/100, 0); - status = ti_write_byte(tport->tp_tdev, + status = ti_write_byte(port, tport->tp_tdev, tport->tp_uart_base_addr + TI_UART_OFFSET_LCR, TI_LCR_BREAK, break_state == -1 ? TI_LCR_BREAK : 0); if (status) - dbg("%s - error setting break, %d", __func__, status); + dev_dbg(&port->dev, "%s - error setting break, %d\n", __func__, status); } @@ -1061,18 +1061,17 @@ static void ti_interrupt_callback(struct urb *urb) case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: - dbg("%s - urb shutting down, %d", __func__, status); + dev_dbg(dev, "%s - urb shutting down, %d\n", __func__, status); tdev->td_urb_error = 1; return; default: - dev_err(dev, "%s - nonzero urb status, %d\n", - __func__, status); + dev_err(dev, "%s - nonzero urb status, %d\n", __func__, status); tdev->td_urb_error = 1; goto exit; } if (length != 2) { - dbg("%s - bad packet size, %d", __func__, length); + dev_dbg(dev, "%s - bad packet size, %d\n", __func__, length); goto exit; } @@ -1084,8 +1083,8 @@ static void ti_interrupt_callback(struct urb *urb) port_number = TI_GET_PORT_FROM_CODE(data[0]); function = TI_GET_FUNC_FROM_CODE(data[0]); - dbg("%s - port_number %d, function %d, data 0x%02X", - __func__, port_number, function, data[1]); + dev_dbg(dev, "%s - port_number %d, function %d, data 0x%02X\n", + __func__, port_number, function, data[1]); if (port_number >= serial->num_ports) { dev_err(dev, "%s - bad port number, %d\n", @@ -1102,12 +1101,12 @@ static void ti_interrupt_callback(struct urb *urb) switch (function) { case TI_CODE_DATA_ERROR: dev_err(dev, "%s - DATA ERROR, port %d, data 0x%02X\n", - __func__, port_number, data[1]); + __func__, port_number, data[1]); break; case TI_CODE_MODEM_STATUS: msr = data[1]; - dbg("%s - port %d, msr 0x%02X", __func__, port_number, msr); + dev_dbg(dev, "%s - port %d, msr 0x%02X\n", __func__, port_number, msr); ti_handle_new_msr(tport, msr); break; @@ -1140,7 +1139,7 @@ static void ti_bulk_in_callback(struct urb *urb) case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: - dbg("%s - urb shutting down, %d", __func__, status); + dev_dbg(dev, "%s - urb shutting down, %d\n", __func__, status); tport->tp_tdev->td_urb_error = 1; wake_up_interruptible(&tport->tp_write_wait); return; @@ -1166,7 +1165,7 @@ static void ti_bulk_in_callback(struct urb *urb) urb->actual_length, urb->transfer_buffer); if (!tport->tp_is_open) - dbg("%s - port closed, dropping data", + dev_dbg(dev, "%s - port closed, dropping data\n", __func__); else ti_recv(&urb->dev->dev, tty, @@ -1208,7 +1207,7 @@ static void ti_bulk_out_callback(struct urb *urb) case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: - dbg("%s - urb shutting down, %d", __func__, status); + dev_dbg(&port->dev, "%s - urb shutting down, %d\n", __func__, status); tport->tp_tdev->td_urb_error = 1; wake_up_interruptible(&tport->tp_write_wait); return; @@ -1307,7 +1306,7 @@ static int ti_set_mcr(struct ti_port *tport, unsigned int mcr) unsigned long flags; int status; - status = ti_write_byte(tport->tp_tdev, + status = ti_write_byte(tport->tp_port, tport->tp_tdev, tport->tp_uart_base_addr + TI_UART_OFFSET_MCR, TI_MCR_RTS | TI_MCR_DTR | TI_MCR_LOOP, mcr); @@ -1344,7 +1343,7 @@ static int ti_get_lsr(struct ti_port *tport) goto free_data; } - dbg("%s - lsr 0x%02X", __func__, data->bLSR); + dev_dbg(&port->dev, "%s - lsr 0x%02X\n", __func__, data->bLSR); tport->tp_lsr = data->bLSR; @@ -1401,7 +1400,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr) struct tty_struct *tty; unsigned long flags; - dbg("%s - msr 0x%02X", __func__, msr); + dev_dbg(&tport->tp_port->dev, "%s - msr 0x%02X\n", __func__, msr); if (msr & TI_MSR_DELTA_MASK) { spin_lock_irqsave(&tport->tp_lock, flags); @@ -1560,21 +1559,21 @@ static int ti_command_in_sync(struct ti_device *tdev, __u8 command, } -static int ti_write_byte(struct ti_device *tdev, unsigned long addr, - __u8 mask, __u8 byte) +static int ti_write_byte(struct usb_serial_port *port, + struct ti_device *tdev, unsigned long addr, + __u8 mask, __u8 byte) { int status; unsigned int size; struct ti_write_data_bytes *data; - struct device *dev = &tdev->td_serial->dev->dev; - dbg("%s - addr 0x%08lX, mask 0x%02X, byte 0x%02X", - __func__, addr, mask, byte); + dev_dbg(&port->dev, "%s - addr 0x%08lX, mask 0x%02X, byte 0x%02X\n", __func__, + addr, mask, byte); size = sizeof(struct ti_write_data_bytes) + 2; data = kmalloc(size, GFP_KERNEL); if (!data) { - dev_err(dev, "%s - out of memory\n", __func__); + dev_err(&port->dev, "%s - out of memory\n", __func__); return -ENOMEM; } @@ -1590,7 +1589,7 @@ static int ti_write_byte(struct ti_device *tdev, unsigned long addr, (__u8 *)data, size); if (status < 0) - dev_err(dev, "%s - failed, %d\n", __func__, status); + dev_err(&port->dev, "%s - failed, %d\n", __func__, status); kfree(data); @@ -1615,7 +1614,7 @@ static int ti_do_download(struct usb_device *dev, int pipe, - sizeof(struct ti_firmware_header))); header->bCheckSum = cs; - dbg("%s - downloading firmware", __func__); + dev_dbg(&dev->dev, "%s - downloading firmware\n", __func__); for (pos = 0; pos < size; pos += done) { len = min(size - pos, TI_DOWNLOAD_MAX_PACKET_SIZE); status = usb_bulk_msg(dev, pipe, buffer + pos, len, @@ -1691,7 +1690,7 @@ static int ti_download_firmware(struct ti_device *tdev) status = ti_do_download(dev, pipe, buffer, fw_p->size); kfree(buffer); } else { - dbg("%s ENOMEM\n", __func__); + dev_dbg(&dev->dev, "%s ENOMEM\n", __func__); status = -ENOMEM; } release_firmware(fw_p); @@ -1701,7 +1700,7 @@ static int ti_download_firmware(struct ti_device *tdev) return status; } - dbg("%s - download successful", __func__); + dev_dbg(&dev->dev, "%s - download successful\n", __func__); return 0; } -- cgit v0.10.2 From 9c134a14f2da1631d583090a898a8b9d40930472 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 16:06:04 -0700 Subject: USB: serial: mos7840.c: remove dbg() usage dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. CC: Johan Hovold CC: Mark Ferrell CC: Donald Lee CC: Tony Zelenoff Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 2f6da1e..ffbe4ee 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -265,7 +265,7 @@ static int mos7840_set_reg_sync(struct usb_serial_port *port, __u16 reg, { struct usb_device *dev = port->serial->dev; val = val & 0x00ff; - dbg("mos7840_set_reg_sync offset is %x, value %x", reg, val); + dev_dbg(&port->dev, "mos7840_set_reg_sync offset is %x, value %x\n", reg, val); return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ, MCS_WR_RTYPE, val, reg, NULL, 0, @@ -293,7 +293,7 @@ static int mos7840_get_reg_sync(struct usb_serial_port *port, __u16 reg, MCS_RD_RTYPE, 0, reg, buf, VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT); *val = buf[0]; - dbg("mos7840_get_reg_sync offset is %x, return val %x", reg, *val); + dev_dbg(&port->dev, "%s offset is %x, return val %x\n", __func__, reg, *val); kfree(buf); return ret; @@ -316,21 +316,16 @@ static int mos7840_set_uart_reg(struct usb_serial_port *port, __u16 reg, if (port->serial->num_ports == 4) { val |= (((__u16) port->number - (__u16) (port->serial->minor)) + 1) << 8; - dbg("mos7840_set_uart_reg application number is %x", val); } else { if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) { val |= (((__u16) port->number - (__u16) (port->serial->minor)) + 1) << 8; - dbg("mos7840_set_uart_reg application number is %x", - val); } else { - val |= - (((__u16) port->number - + val |= (((__u16) port->number - (__u16) (port->serial->minor)) + 2) << 8; - dbg("mos7840_set_uart_reg application number is %x", - val); } } + dev_dbg(&port->dev, "%s application number is %x\n", __func__, val); return usb_control_msg(dev, usb_sndctrlpipe(dev, 0), MCS_WRREQ, MCS_WR_RTYPE, val, reg, NULL, 0, MOS_WDR_TIMEOUT); @@ -354,27 +349,21 @@ static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg, if (!buf) return -ENOMEM; - /* dbg("application number is %4x", - (((__u16)port->number - (__u16)(port->serial->minor))+1)<<8); */ /* Wval is same as application number */ if (port->serial->num_ports == 4) { Wval = (((__u16) port->number - (__u16) (port->serial->minor)) + 1) << 8; - dbg("mos7840_get_uart_reg application number is %x", Wval); } else { if (((__u16) port->number - (__u16) (port->serial->minor)) == 0) { Wval = (((__u16) port->number - (__u16) (port->serial->minor)) + 1) << 8; - dbg("mos7840_get_uart_reg application number is %x", - Wval); } else { Wval = (((__u16) port->number - (__u16) (port->serial->minor)) + 2) << 8; - dbg("mos7840_get_uart_reg application number is %x", - Wval); } } + dev_dbg(&port->dev, "%s application number is %x\n", __func__, Wval); ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), MCS_RDREQ, MCS_RD_RTYPE, Wval, reg, buf, VENDOR_READ_LENGTH, MOS_WDR_TIMEOUT); @@ -384,14 +373,13 @@ static int mos7840_get_uart_reg(struct usb_serial_port *port, __u16 reg, return ret; } -static void mos7840_dump_serial_port(struct moschip_port *mos7840_port) +static void mos7840_dump_serial_port(struct usb_serial_port *port, + struct moschip_port *mos7840_port) { - dbg("***************************************"); - dbg("SpRegOffset is %2x", mos7840_port->SpRegOffset); - dbg("ControlRegOffset is %2x", mos7840_port->ControlRegOffset); - dbg("DCRRegOffset is %2x", mos7840_port->DcrRegOffset); - dbg("***************************************"); + dev_dbg(&port->dev, "SpRegOffset is %2x\n", mos7840_port->SpRegOffset); + dev_dbg(&port->dev, "ControlRegOffset is %2x\n", mos7840_port->ControlRegOffset); + dev_dbg(&port->dev, "DCRRegOffset is %2x\n", mos7840_port->DcrRegOffset); } @@ -450,8 +438,6 @@ static void mos7840_handle_new_lsr(struct moschip_port *port, __u8 new_lsr) { struct async_icount *icount; - dbg("%s - %02x", __func__, new_lsr); - if (new_lsr & SERIAL_LSR_BI) { /* * Parity and Framing errors only count if they @@ -492,6 +478,7 @@ static void mos7840_control_callback(struct urb *urb) { unsigned char *data; struct moschip_port *mos7840_port; + struct device *dev = &urb->dev->dev; __u8 regval = 0x0; int result = 0; int status = urb->status; @@ -506,21 +493,19 @@ static void mos7840_control_callback(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __func__, - status); + dev_dbg(dev, "%s - urb shutting down with status: %d\n", __func__, status); return; default: - dbg("%s - nonzero urb status received: %d", __func__, - status); + dev_dbg(dev, "%s - nonzero urb status received: %d\n", __func__, status); goto exit; } - dbg("%s urb buffer size is %d", __func__, urb->actual_length); - dbg("%s mos7840_port->MsrLsr is %d port %d", __func__, - mos7840_port->MsrLsr, mos7840_port->port_num); + dev_dbg(dev, "%s urb buffer size is %d\n", __func__, urb->actual_length); + dev_dbg(dev, "%s mos7840_port->MsrLsr is %d port %d\n", __func__, + mos7840_port->MsrLsr, mos7840_port->port_num); data = urb->transfer_buffer; regval = (__u8) data[0]; - dbg("%s data is %x", __func__, regval); + dev_dbg(dev, "%s data is %x\n", __func__, regval); if (mos7840_port->MsrLsr == 0) mos7840_handle_new_msr(mos7840_port, regval); else if (mos7840_port->MsrLsr == 1) @@ -532,8 +517,7 @@ exit: result = usb_submit_urb(mos7840_port->int_urb, GFP_ATOMIC); spin_unlock(&mos7840_port->pool_lock); if (result) { - dev_err(&urb->dev->dev, - "%s - Error %d submitting interrupt urb\n", + dev_err(dev, "%s - Error %d submitting interrupt urb\n", __func__, result); } } @@ -570,12 +554,12 @@ static void mos7840_set_led_callback(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* This urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __func__, - urb->status); + dev_dbg(&urb->dev->dev, "%s - urb shutting down with status: %d", + __func__, urb->status); break; default: - dbg("%s - nonzero urb status received: %d", __func__, - urb->status); + dev_dbg(&urb->dev->dev, "%s - nonzero urb status received: %d", + __func__, urb->status); } } @@ -650,12 +634,12 @@ static void mos7840_interrupt_callback(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __func__, - status); + dev_dbg(&urb->dev->dev, "%s - urb shutting down with status: %d\n", + __func__, status); return; default: - dbg("%s - nonzero urb status received: %d", __func__, - status); + dev_dbg(&urb->dev->dev, "%s - nonzero urb status received: %d\n", + __func__, status); goto exit; } @@ -672,7 +656,7 @@ static void mos7840_interrupt_callback(struct urb *urb) * Byte 5 FIFO status for both */ if (length && length > 5) { - dbg("%s", "Wrong data !!!"); + dev_dbg(&urb->dev->dev, "%s", "Wrong data !!!\n"); return; } @@ -689,17 +673,17 @@ static void mos7840_interrupt_callback(struct urb *urb) (__u16) (serial->minor)) + 1) << 8; if (mos7840_port->open) { if (sp[i] & 0x01) { - dbg("SP%d No Interrupt !!!", i); + dev_dbg(&urb->dev->dev, "SP%d No Interrupt !!!\n", i); } else { switch (sp[i] & 0x0f) { case SERIAL_IIR_RLS: - dbg("Serial Port %d: Receiver status error or ", i); - dbg("address bit detected in 9-bit mode"); + dev_dbg(&urb->dev->dev, "Serial Port %d: Receiver status error or \n", i); + dev_dbg(&urb->dev->dev, "address bit detected in 9-bit mode\n"); mos7840_port->MsrLsr = 1; wreg = LINE_STATUS_REGISTER; break; case SERIAL_IIR_MS: - dbg("Serial Port %d: Modem status change", i); + dev_dbg(&urb->dev->dev, "Serial Port %d: Modem status change\n", i); mos7840_port->MsrLsr = 0; wreg = MODEM_STATUS_REGISTER; break; @@ -731,11 +715,11 @@ static int mos7840_port_paranoia_check(struct usb_serial_port *port, const char *function) { if (!port) { - dbg("%s - port == NULL", function); + pr_debug("%s - port == NULL\n", function); return -1; } if (!port->serial) { - dbg("%s - port->serial == NULL", function); + pr_debug("%s - port->serial == NULL\n", function); return -1; } @@ -747,11 +731,11 @@ static int mos7840_serial_paranoia_check(struct usb_serial *serial, const char *function) { if (!serial) { - dbg("%s - serial == NULL", function); + pr_debug("%s - serial == NULL\n", function); return -1; } if (!serial->type) { - dbg("%s - serial->type == NULL!", function); + pr_debug("%s - serial->type == NULL!\n", function); return -1; } @@ -790,49 +774,44 @@ static void mos7840_bulk_in_callback(struct urb *urb) int status = urb->status; mos7840_port = urb->context; - if (!mos7840_port) { - dbg("%s", "NULL mos7840_port pointer"); + if (!mos7840_port) return; - } if (status) { - dbg("nonzero read bulk status received: %d", status); + dev_dbg(&urb->dev->dev, "nonzero read bulk status received: %d\n", status); mos7840_port->read_urb_busy = false; return; } - port = (struct usb_serial_port *)mos7840_port->port; + port = mos7840_port->port; if (mos7840_port_paranoia_check(port, __func__)) { - dbg("%s", "Port Paranoia failed"); mos7840_port->read_urb_busy = false; return; } serial = mos7840_get_usb_serial(port, __func__); if (!serial) { - dbg("%s", "Bad serial pointer"); mos7840_port->read_urb_busy = false; return; } data = urb->transfer_buffer; + usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); if (urb->actual_length) { tty = tty_port_tty_get(&mos7840_port->port->port); if (tty) { tty_insert_flip_string(tty, data, urb->actual_length); - dbg(" %s ", data); tty_flip_buffer_push(tty); tty_kref_put(tty); } mos7840_port->icount.rx += urb->actual_length; smp_wmb(); - dbg("mos7840_port->icount.rx is %d:", - mos7840_port->icount.rx); + dev_dbg(&port->dev, "mos7840_port->icount.rx is %d:\n", mos7840_port->icount.rx); } if (!mos7840_port->read_urb) { - dbg("%s", "URB KILLED !!!"); + dev_dbg(&port->dev, "%s", "URB KILLED !!!\n"); mos7840_port->read_urb_busy = false; return; } @@ -850,7 +829,7 @@ static void mos7840_bulk_in_callback(struct urb *urb) retval = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); if (retval) { - dbg("usb_submit_urb(read bulk) failed, retval = %d", retval); + dev_dbg(&port->dev, "usb_submit_urb(read bulk) failed, retval = %d\n", retval); mos7840_port->read_urb_busy = false; } } @@ -864,11 +843,13 @@ static void mos7840_bulk_in_callback(struct urb *urb) static void mos7840_bulk_out_data_callback(struct urb *urb) { struct moschip_port *mos7840_port; + struct usb_serial_port *port; struct tty_struct *tty; int status = urb->status; int i; mos7840_port = urb->context; + port = mos7840_port->port; spin_lock(&mos7840_port->pool_lock); for (i = 0; i < NUM_URBS; i++) { if (urb == mos7840_port->write_urb_pool[i]) { @@ -879,16 +860,14 @@ static void mos7840_bulk_out_data_callback(struct urb *urb) spin_unlock(&mos7840_port->pool_lock); if (status) { - dbg("nonzero write bulk status received:%d", status); + dev_dbg(&port->dev, "nonzero write bulk status received:%d\n", status); return; } - if (mos7840_port_paranoia_check(mos7840_port->port, __func__)) { - dbg("%s", "Port Paranoia failed"); + if (mos7840_port_paranoia_check(port, __func__)) return; - } - tty = tty_port_tty_get(&mos7840_port->port->port); + tty = tty_port_tty_get(&port->port); if (tty && mos7840_port->open) tty_wakeup(tty); tty_kref_put(tty); @@ -929,17 +908,13 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port) struct moschip_port *mos7840_port; struct moschip_port *port0; - if (mos7840_port_paranoia_check(port, __func__)) { - dbg("%s", "Port Paranoia failed"); + if (mos7840_port_paranoia_check(port, __func__)) return -ENODEV; - } serial = port->serial; - if (mos7840_serial_paranoia_check(serial, __func__)) { - dbg("%s", "Serial Paranoia failed"); + if (mos7840_serial_paranoia_check(serial, __func__)) return -ENODEV; - } mos7840_port = mos7840_get_port_private(port); port0 = mos7840_get_port_private(serial->port[0]); @@ -990,20 +965,20 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port) Data = 0x0; status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data); if (status < 0) { - dbg("Reading Spreg failed"); + dev_dbg(&port->dev, "Reading Spreg failed\n"); return -1; } Data |= 0x80; status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data); if (status < 0) { - dbg("writing Spreg failed"); + dev_dbg(&port->dev, "writing Spreg failed\n"); return -1; } Data &= ~0x80; status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data); if (status < 0) { - dbg("writing Spreg failed"); + dev_dbg(&port->dev, "writing Spreg failed\n"); return -1; } /* End of block to be checked */ @@ -1012,7 +987,7 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port) status = mos7840_get_reg_sync(port, mos7840_port->ControlRegOffset, &Data); if (status < 0) { - dbg("Reading Controlreg failed"); + dev_dbg(&port->dev, "Reading Controlreg failed\n"); return -1; } Data |= 0x08; /* Driver done bit */ @@ -1020,7 +995,7 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port) status = mos7840_set_reg_sync(port, mos7840_port->ControlRegOffset, Data); if (status < 0) { - dbg("writing Controlreg failed"); + dev_dbg(&port->dev, "writing Controlreg failed\n"); return -1; } /* do register settings here */ @@ -1031,21 +1006,21 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port) Data = 0x00; status = mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); if (status < 0) { - dbg("disabling interrupts failed"); + dev_dbg(&port->dev, "disabling interrupts failed\n"); return -1; } /* Set FIFO_CONTROL_REGISTER to the default value */ Data = 0x00; status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); if (status < 0) { - dbg("Writing FIFO_CONTROL_REGISTER failed"); + dev_dbg(&port->dev, "Writing FIFO_CONTROL_REGISTER failed\n"); return -1; } Data = 0xcf; status = mos7840_set_uart_reg(port, FIFO_CONTROL_REGISTER, Data); if (status < 0) { - dbg("Writing FIFO_CONTROL_REGISTER failed"); + dev_dbg(&port->dev, "Writing FIFO_CONTROL_REGISTER failed\n"); return -1; } @@ -1142,12 +1117,12 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port) * (can't set it up in mos7840_startup as the * * structures were not set up at that time.) */ - dbg("port number is %d", port->number); - dbg("serial number is %d", port->serial->minor); - dbg("Bulkin endpoint is %d", port->bulk_in_endpointAddress); - dbg("BulkOut endpoint is %d", port->bulk_out_endpointAddress); - dbg("Interrupt endpoint is %d", port->interrupt_in_endpointAddress); - dbg("port's number in the device is %d", mos7840_port->port_num); + dev_dbg(&port->dev, "port number is %d\n", port->number); + dev_dbg(&port->dev, "serial number is %d\n", port->serial->minor); + dev_dbg(&port->dev, "Bulkin endpoint is %d\n", port->bulk_in_endpointAddress); + dev_dbg(&port->dev, "BulkOut endpoint is %d\n", port->bulk_out_endpointAddress); + dev_dbg(&port->dev, "Interrupt endpoint is %d\n", port->interrupt_in_endpointAddress); + dev_dbg(&port->dev, "port's number in the device is %d\n", mos7840_port->port_num); mos7840_port->read_urb = port->read_urb; /* set up our bulk in urb */ @@ -1171,8 +1146,7 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port) mos7840_bulk_in_callback, mos7840_port); } - dbg("mos7840_open: bulkin endpoint is %d", - port->bulk_in_endpointAddress); + dev_dbg(&port->dev, "%s: bulkin endpoint is %d\n", __func__, port->bulk_in_endpointAddress); mos7840_port->read_urb_busy = true; response = usb_submit_urb(mos7840_port->read_urb, GFP_KERNEL); if (response) { @@ -1197,9 +1171,6 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port) mos7840_port->icount.tx = 0; mos7840_port->icount.rx = 0; - dbg("usb_serial serial:%p mos7840_port:%p\n usb_serial_port port:%p", - serial, mos7840_port, port); - return 0; } @@ -1221,10 +1192,8 @@ static int mos7840_chars_in_buffer(struct tty_struct *tty) unsigned long flags; struct moschip_port *mos7840_port; - if (mos7840_port_paranoia_check(port, __func__)) { - dbg("%s", "Invalid port"); + if (mos7840_port_paranoia_check(port, __func__)) return 0; - } mos7840_port = mos7840_get_port_private(port); if (mos7840_port == NULL) @@ -1238,7 +1207,7 @@ static int mos7840_chars_in_buffer(struct tty_struct *tty) } } spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); - dbg("%s - returns %d", __func__, chars); + dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars); return chars; } @@ -1256,16 +1225,12 @@ static void mos7840_close(struct usb_serial_port *port) int j; __u16 Data; - if (mos7840_port_paranoia_check(port, __func__)) { - dbg("%s", "Port Paranoia failed"); + if (mos7840_port_paranoia_check(port, __func__)) return; - } serial = mos7840_get_usb_serial(port, __func__); - if (!serial) { - dbg("%s", "Serial Paranoia failed"); + if (!serial) return; - } mos7840_port = mos7840_get_port_private(port); port0 = mos7840_get_port_private(serial->port[0]); @@ -1291,27 +1256,26 @@ static void mos7840_close(struct usb_serial_port *port) * and interrupt read if they exists */ if (serial->dev) { if (mos7840_port->write_urb) { - dbg("%s", "Shutdown bulk write"); + dev_dbg(&port->dev, "%s", "Shutdown bulk write\n"); usb_kill_urb(mos7840_port->write_urb); } if (mos7840_port->read_urb) { - dbg("%s", "Shutdown bulk read"); + dev_dbg(&port->dev, "%s", "Shutdown bulk read\n"); usb_kill_urb(mos7840_port->read_urb); mos7840_port->read_urb_busy = false; } if ((&mos7840_port->control_urb)) { - dbg("%s", "Shutdown control read"); + dev_dbg(&port->dev, "%s", "Shutdown control read\n"); /*/ usb_kill_urb (mos7840_port->control_urb); */ } } /* if(mos7840_port->ctrl_buf != NULL) */ /* kfree(mos7840_port->ctrl_buf); */ port0->open_ports--; - dbg("mos7840_num_open_ports in close%d:in port%d", - port0->open_ports, port->number); + dev_dbg(&port->dev, "%s in close%d:in port%d\n", __func__, port0->open_ports, port->number); if (port0->open_ports == 0) { if (serial->port[0]->interrupt_in_urb) { - dbg("%s", "Shutdown interrupt_in_urb"); + dev_dbg(&port->dev, "Shutdown interrupt_in_urb\n"); usb_kill_urb(serial->port[0]->interrupt_in_urb); } } @@ -1363,7 +1327,7 @@ static void mos7840_block_until_chase_response(struct tty_struct *tty, /* No activity.. count down section */ wait--; if (wait == 0) { - dbg("%s - TIMEOUT", __func__); + dev_dbg(&mos7840_port->port->dev, "%s - TIMEOUT\n", __func__); return; } else { /* Reset timeout value back to seconds */ @@ -1384,16 +1348,12 @@ static void mos7840_break(struct tty_struct *tty, int break_state) struct usb_serial *serial; struct moschip_port *mos7840_port; - if (mos7840_port_paranoia_check(port, __func__)) { - dbg("%s", "Port Paranoia failed"); + if (mos7840_port_paranoia_check(port, __func__)) return; - } serial = mos7840_get_usb_serial(port, __func__); - if (!serial) { - dbg("%s", "Serial Paranoia failed"); + if (!serial) return; - } mos7840_port = mos7840_get_port_private(port); @@ -1411,8 +1371,7 @@ static void mos7840_break(struct tty_struct *tty, int break_state) /* FIXME: no locking on shadowLCR anywhere in driver */ mos7840_port->shadowLCR = data; - dbg("mcs7840_break mos7840_port->shadowLCR is %x", - mos7840_port->shadowLCR); + dev_dbg(&port->dev, "%s mos7840_port->shadowLCR is %x\n", __func__, mos7840_port->shadowLCR); mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, mos7840_port->shadowLCR); } @@ -1433,17 +1392,12 @@ static int mos7840_write_room(struct tty_struct *tty) unsigned long flags; struct moschip_port *mos7840_port; - if (mos7840_port_paranoia_check(port, __func__)) { - dbg("%s", "Invalid port"); - dbg("%s", " mos7840_write_room:leaving ..........."); + if (mos7840_port_paranoia_check(port, __func__)) return -1; - } mos7840_port = mos7840_get_port_private(port); - if (mos7840_port == NULL) { - dbg("%s", "mos7840_break:leaving ..........."); + if (mos7840_port == NULL) return -1; - } spin_lock_irqsave(&mos7840_port->pool_lock, flags); for (i = 0; i < NUM_URBS; ++i) { @@ -1453,7 +1407,7 @@ static int mos7840_write_room(struct tty_struct *tty) spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); room = (room == 0) ? 0 : room - URB_TRANSFER_BUFFER_SIZE + 1; - dbg("%s - returns %d", __func__, room); + dev_dbg(&mos7840_port->port->dev, "%s - returns %d\n", __func__, room); return room; } @@ -1486,9 +1440,8 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, Data = 0x00; status = mos7840_get_uart_reg(port, LINE_CONTROL_REGISTER, &Data); mos7840_port->shadowLCR = Data; - dbg("mos7840_write: LINE_CONTROL_REGISTER is %x", Data); - dbg("mos7840_write: mos7840_port->shadowLCR is %x", - mos7840_port->shadowLCR); + dev_dbg(&port->dev, "%s: LINE_CONTROL_REGISTER is %x\n", __func__, Data); + dev_dbg(&port->dev, "%s: mos7840_port->shadowLCR is %x\n", __func__, mos7840_port->shadowLCR); /* Data = 0x03; */ /* status = mos7840_set_uart_reg(port,LINE_CONTROL_REGISTER,Data); */ @@ -1501,34 +1454,27 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, /* status = mos7840_set_uart_reg(port,DIVISOR_LATCH_LSB,Data); */ Data = 0x00; status = mos7840_get_uart_reg(port, DIVISOR_LATCH_LSB, &Data); - dbg("mos7840_write:DLL value is %x", Data); + dev_dbg(&port->dev, "%s: DLL value is %x\n", __func__, Data); Data = 0x0; status = mos7840_get_uart_reg(port, DIVISOR_LATCH_MSB, &Data); - dbg("mos7840_write:DLM value is %x", Data); + dev_dbg(&port->dev, "%s: DLM value is %x\n", __func__, Data); Data = Data & ~SERIAL_LCR_DLAB; - dbg("mos7840_write: mos7840_port->shadowLCR is %x", - mos7840_port->shadowLCR); + dev_dbg(&port->dev, "%s: mos7840_port->shadowLCR is %x\n", __func__, mos7840_port->shadowLCR); status = mos7840_set_uart_reg(port, LINE_CONTROL_REGISTER, Data); #endif - if (mos7840_port_paranoia_check(port, __func__)) { - dbg("%s", "Port Paranoia failed"); + if (mos7840_port_paranoia_check(port, __func__)) return -1; - } serial = port->serial; - if (mos7840_serial_paranoia_check(serial, __func__)) { - dbg("%s", "Serial Paranoia failed"); + if (mos7840_serial_paranoia_check(serial, __func__)) return -1; - } mos7840_port = mos7840_get_port_private(port); - if (mos7840_port == NULL) { - dbg("%s", "mos7840_port is NULL"); + if (mos7840_port == NULL) return -1; - } /* try to find a free urb in the list */ urb = NULL; @@ -1538,14 +1484,14 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, if (!mos7840_port->busy[i]) { mos7840_port->busy[i] = 1; urb = mos7840_port->write_urb_pool[i]; - dbg("URB:%d", i); + dev_dbg(&port->dev, "URB:%d\n", i); break; } } spin_unlock_irqrestore(&mos7840_port->pool_lock, flags); if (urb == NULL) { - dbg("%s - no more free urbs", __func__); + dev_dbg(&port->dev, "%s - no more free urbs\n", __func__); goto exit; } @@ -1585,7 +1531,7 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, } data1 = urb->transfer_buffer; - dbg("bulkout endpoint is %d", port->bulk_out_endpointAddress); + dev_dbg(&port->dev, "bulkout endpoint is %d\n", port->bulk_out_endpointAddress); /* Turn on LED */ if (mos7840_port->has_led && !mos7840_port->led_flag) { @@ -1608,7 +1554,7 @@ static int mos7840_write(struct tty_struct *tty, struct usb_serial_port *port, bytes_sent = transfer_size; mos7840_port->icount.tx += transfer_size; smp_wmb(); - dbg("mos7840_port->icount.tx is %d:", mos7840_port->icount.tx); + dev_dbg(&port->dev, "mos7840_port->icount.tx is %d:\n", mos7840_port->icount.tx); exit: return bytes_sent; @@ -1626,12 +1572,8 @@ static void mos7840_throttle(struct tty_struct *tty) struct moschip_port *mos7840_port; int status; - if (mos7840_port_paranoia_check(port, __func__)) { - dbg("%s", "Invalid port"); + if (mos7840_port_paranoia_check(port, __func__)) return; - } - - dbg("- port %d", port->number); mos7840_port = mos7840_get_port_private(port); @@ -1639,7 +1581,7 @@ static void mos7840_throttle(struct tty_struct *tty) return; if (!mos7840_port->open) { - dbg("%s", "port not opened"); + dev_dbg(&port->dev, "%s", "port not opened\n"); return; } @@ -1672,16 +1614,14 @@ static void mos7840_unthrottle(struct tty_struct *tty) int status; struct moschip_port *mos7840_port = mos7840_get_port_private(port); - if (mos7840_port_paranoia_check(port, __func__)) { - dbg("%s", "Invalid port"); + if (mos7840_port_paranoia_check(port, __func__)) return; - } if (mos7840_port == NULL) return; if (!mos7840_port->open) { - dbg("%s - port not opened", __func__); + dev_dbg(&port->dev, "%s - port not opened\n", __func__); return; } @@ -1726,7 +1666,7 @@ static int mos7840_tiocmget(struct tty_struct *tty) | ((msr & MOS7840_MSR_RI) ? TIOCM_RI : 0) | ((msr & MOS7840_MSR_DSR) ? TIOCM_DSR : 0); - dbg("%s - 0x%04X", __func__, result); + dev_dbg(&port->dev, "%s - 0x%04X\n", __func__, result); return result; } @@ -1764,7 +1704,7 @@ static int mos7840_tiocmset(struct tty_struct *tty, status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, mcr); if (status < 0) { - dbg("setting MODEM_CONTROL_REGISTER Failed"); + dev_dbg(&port->dev, "setting MODEM_CONTROL_REGISTER Failed\n"); return status; } @@ -1776,10 +1716,11 @@ static int mos7840_tiocmset(struct tty_struct *tty, * this function calculates the proper baud rate divisor for the specified * baud rate. *****************************************************************************/ -static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor, +static int mos7840_calc_baud_rate_divisor(struct usb_serial_port *port, + int baudRate, int *divisor, __u16 *clk_sel_val) { - dbg("%s - %d", __func__, baudRate); + dev_dbg(&port->dev, "%s - %d\n", __func__, baudRate); if (baudRate <= 115200) { *divisor = 115200 / baudRate; @@ -1832,11 +1773,11 @@ static int mos7840_calc_baud_rate_divisor(int baudRate, int *divisor, custom++; *divisor = custom; - dbg(" Baud %d = %d", baudrate, custom); + dev_dbg(&port->dev, " Baud %d = %d\n", baudrate, custom); return 0; } - dbg("%s", " Baud calculation Failed..."); + dev_dbg(&port->dev, "%s", " Baud calculation Failed...\n"); return -1; #endif } @@ -1860,21 +1801,17 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port, if (mos7840_port == NULL) return -1; - port = (struct usb_serial_port *)mos7840_port->port; - if (mos7840_port_paranoia_check(port, __func__)) { - dbg("%s", "Invalid port"); + port = mos7840_port->port; + if (mos7840_port_paranoia_check(port, __func__)) return -1; - } - if (mos7840_serial_paranoia_check(port->serial, __func__)) { - dbg("%s", "Invalid Serial"); + if (mos7840_serial_paranoia_check(port->serial, __func__)) return -1; - } number = mos7840_port->port->number - mos7840_port->port->serial->minor; - dbg("%s - port = %d, baud = %d", __func__, - mos7840_port->port->number, baudRate); + dev_dbg(&port->dev, "%s - port = %d, baud = %d\n", __func__, + mos7840_port->port->number, baudRate); /* reset clk_uart_sel in spregOffset */ if (baudRate > 115200) { #ifdef HW_flow_control @@ -1885,7 +1822,7 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port, status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); if (status < 0) { - dbg("Writing spreg failed in set_serial_baud"); + dev_dbg(&port->dev, "Writing spreg failed in set_serial_baud\n"); return -1; } #endif @@ -1898,7 +1835,7 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port, status = mos7840_set_uart_reg(port, MODEM_CONTROL_REGISTER, Data); if (status < 0) { - dbg("Writing spreg failed in set_serial_baud"); + dev_dbg(&port->dev, "Writing spreg failed in set_serial_baud\n"); return -1; } #endif @@ -1908,19 +1845,19 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port, if (1) { /* baudRate <= 115200) */ clk_sel_val = 0x0; Data = 0x0; - status = mos7840_calc_baud_rate_divisor(baudRate, &divisor, + status = mos7840_calc_baud_rate_divisor(port, baudRate, &divisor, &clk_sel_val); status = mos7840_get_reg_sync(port, mos7840_port->SpRegOffset, &Data); if (status < 0) { - dbg("reading spreg failed in set_serial_baud"); + dev_dbg(&port->dev, "reading spreg failed in set_serial_baud\n"); return -1; } Data = (Data & 0x8f) | clk_sel_val; status = mos7840_set_reg_sync(port, mos7840_port->SpRegOffset, Data); if (status < 0) { - dbg("Writing spreg failed in set_serial_baud"); + dev_dbg(&port->dev, "Writing spreg failed in set_serial_baud\n"); return -1; } /* Calculate the Divisor */ @@ -1936,11 +1873,11 @@ static int mos7840_send_cmd_write_baud_rate(struct moschip_port *mos7840_port, /* Write the divisor */ Data = (unsigned char)(divisor & 0xff); - dbg("set_serial_baud Value to write DLL is %x", Data); + dev_dbg(&port->dev, "set_serial_baud Value to write DLL is %x\n", Data); mos7840_set_uart_reg(port, DIVISOR_LATCH_LSB, Data); Data = (unsigned char)((divisor & 0xff00) >> 8); - dbg("set_serial_baud Value to write DLM is %x", Data); + dev_dbg(&port->dev, "set_serial_baud Value to write DLM is %x\n", Data); mos7840_set_uart_reg(port, DIVISOR_LATCH_MSB, Data); /* Disable access to divisor latch */ @@ -1975,24 +1912,18 @@ static void mos7840_change_port_settings(struct tty_struct *tty, if (mos7840_port == NULL) return; - port = (struct usb_serial_port *)mos7840_port->port; + port = mos7840_port->port; - if (mos7840_port_paranoia_check(port, __func__)) { - dbg("%s", "Invalid port"); + if (mos7840_port_paranoia_check(port, __func__)) return; - } - if (mos7840_serial_paranoia_check(port->serial, __func__)) { - dbg("%s", "Invalid Serial"); + if (mos7840_serial_paranoia_check(port->serial, __func__)) return; - } serial = port->serial; - dbg("%s - port %d", __func__, mos7840_port->port->number); - if (!mos7840_port->open) { - dbg("%s - port not opened", __func__); + dev_dbg(&port->dev, "%s - port not opened\n", __func__); return; } @@ -2027,14 +1958,14 @@ static void mos7840_change_port_settings(struct tty_struct *tty, if (cflag & PARENB) { if (cflag & PARODD) { lParity = LCR_PAR_ODD; - dbg("%s - parity = odd", __func__); + dev_dbg(&port->dev, "%s - parity = odd\n", __func__); } else { lParity = LCR_PAR_EVEN; - dbg("%s - parity = even", __func__); + dev_dbg(&port->dev, "%s - parity = even\n", __func__); } } else { - dbg("%s - parity = none", __func__); + dev_dbg(&port->dev, "%s - parity = none\n", __func__); } if (cflag & CMSPAR) @@ -2043,10 +1974,10 @@ static void mos7840_change_port_settings(struct tty_struct *tty, /* Change the Stop bit */ if (cflag & CSTOPB) { lStop = LCR_STOP_2; - dbg("%s - stop bits = 2", __func__); + dev_dbg(&port->dev, "%s - stop bits = 2\n", __func__); } else { lStop = LCR_STOP_1; - dbg("%s - stop bits = 1", __func__); + dev_dbg(&port->dev, "%s - stop bits = 1\n", __func__); } /* Update the LCR with the correct value */ @@ -2054,8 +1985,8 @@ static void mos7840_change_port_settings(struct tty_struct *tty, ~(LCR_BITS_MASK | LCR_STOP_MASK | LCR_PAR_MASK); mos7840_port->shadowLCR |= (lData | lParity | lStop); - dbg("mos7840_change_port_settings mos7840_port->shadowLCR is %x", - mos7840_port->shadowLCR); + dev_dbg(&port->dev, "%s - mos7840_port->shadowLCR is %x\n", __func__, + mos7840_port->shadowLCR); /* Disable Interrupts */ Data = 0x00; mos7840_set_uart_reg(port, INTERRUPT_ENABLE_REGISTER, Data); @@ -2096,11 +2027,11 @@ static void mos7840_change_port_settings(struct tty_struct *tty, if (!baud) { /* pick a default, any default... */ - dbg("%s", "Picked default baud..."); + dev_dbg(&port->dev, "%s", "Picked default baud...\n"); baud = 9600; } - dbg("%s - baud rate = %d", __func__, baud); + dev_dbg(&port->dev, "%s - baud rate = %d\n", __func__, baud); status = mos7840_send_cmd_write_baud_rate(mos7840_port, baud); /* Enable Interrupts */ @@ -2111,15 +2042,15 @@ static void mos7840_change_port_settings(struct tty_struct *tty, mos7840_port->read_urb_busy = true; status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); if (status) { - dbg("usb_submit_urb(read bulk) failed, status = %d", + dev_dbg(&port->dev, "usb_submit_urb(read bulk) failed, status = %d\n", status); mos7840_port->read_urb_busy = false; } } wake_up(&mos7840_port->delta_msr_wait); mos7840_port->delta_msr_cond = 1; - dbg("mos7840_change_port_settings mos7840_port->shadowLCR is End %x", - mos7840_port->shadowLCR); + dev_dbg(&port->dev, "%s - mos7840_port->shadowLCR is End %x\n", __func__, + mos7840_port->shadowLCR); } /***************************************************************************** @@ -2137,17 +2068,13 @@ static void mos7840_set_termios(struct tty_struct *tty, struct usb_serial *serial; struct moschip_port *mos7840_port; - if (mos7840_port_paranoia_check(port, __func__)) { - dbg("%s", "Invalid port"); + if (mos7840_port_paranoia_check(port, __func__)) return; - } serial = port->serial; - if (mos7840_serial_paranoia_check(serial, __func__)) { - dbg("%s", "Invalid Serial"); + if (mos7840_serial_paranoia_check(serial, __func__)) return; - } mos7840_port = mos7840_get_port_private(port); @@ -2155,26 +2082,26 @@ static void mos7840_set_termios(struct tty_struct *tty, return; if (!mos7840_port->open) { - dbg("%s - port not opened", __func__); + dev_dbg(&port->dev, "%s - port not opened\n", __func__); return; } - dbg("%s", "setting termios - "); + dev_dbg(&port->dev, "%s", "setting termios - \n"); cflag = tty->termios->c_cflag; - dbg("%s - clfag %08x iflag %08x", __func__, - tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag)); - dbg("%s - old clfag %08x old iflag %08x", __func__, - old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag)); - dbg("%s - port %d", __func__, port->number); + dev_dbg(&port->dev, "%s - clfag %08x iflag %08x\n", __func__, + tty->termios->c_cflag, RELEVANT_IFLAG(tty->termios->c_iflag)); + dev_dbg(&port->dev, "%s - old clfag %08x old iflag %08x\n", __func__, + old_termios->c_cflag, RELEVANT_IFLAG(old_termios->c_iflag)); + dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number); /* change the port settings to the new ones specified */ mos7840_change_port_settings(tty, mos7840_port, old_termios); if (!mos7840_port->read_urb) { - dbg("%s", "URB KILLED !!!!!"); + dev_dbg(&port->dev, "%s", "URB KILLED !!!!!\n"); return; } @@ -2182,7 +2109,7 @@ static void mos7840_set_termios(struct tty_struct *tty, mos7840_port->read_urb_busy = true; status = usb_submit_urb(mos7840_port->read_urb, GFP_ATOMIC); if (status) { - dbg("usb_submit_urb(read bulk) failed, status = %d", + dev_dbg(&port->dev, "usb_submit_urb(read bulk) failed, status = %d\n", status); mos7840_port->read_urb_busy = false; } @@ -2207,10 +2134,8 @@ static int mos7840_get_lsr_info(struct tty_struct *tty, unsigned int result = 0; count = mos7840_chars_in_buffer(tty); - if (count == 0) { - dbg("%s -- Empty", __func__); + if (count == 0) result = TIOCSER_TEMT; - } if (copy_to_user(value, &result, sizeof(int))) return -EFAULT; @@ -2273,8 +2198,8 @@ static int mos7840_get_icount(struct tty_struct *tty, icount->brk = cnow.brk; icount->buf_overrun = cnow.buf_overrun; - dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", __func__, - port->number, icount->rx, icount->tx); + dev_dbg(&port->dev, "%s TIOCGICOUNT RX=%d, TX=%d\n", __func__, + icount->rx, icount->tx); return 0; } @@ -2293,35 +2218,33 @@ static int mos7840_ioctl(struct tty_struct *tty, struct async_icount cnow; struct async_icount cprev; - if (mos7840_port_paranoia_check(port, __func__)) { - dbg("%s", "Invalid port"); + if (mos7840_port_paranoia_check(port, __func__)) return -1; - } mos7840_port = mos7840_get_port_private(port); if (mos7840_port == NULL) return -1; - dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); + dev_dbg(&port->dev, "%s - cmd = 0x%x\n", __func__, cmd); switch (cmd) { /* return number of bytes available */ case TIOCSERGETLSR: - dbg("%s (%d) TIOCSERGETLSR", __func__, port->number); + dev_dbg(&port->dev, "%s TIOCSERGETLSR\n", __func__); return mos7840_get_lsr_info(tty, argp); case TIOCGSERIAL: - dbg("%s (%d) TIOCGSERIAL", __func__, port->number); + dev_dbg(&port->dev, "%s TIOCGSERIAL\n", __func__); return mos7840_get_serial_info(mos7840_port, argp); case TIOCSSERIAL: - dbg("%s (%d) TIOCSSERIAL", __func__, port->number); + dev_dbg(&port->dev, "%s TIOCSSERIAL\n", __func__); break; case TIOCMIWAIT: - dbg("%s (%d) TIOCMIWAIT", __func__, port->number); + dev_dbg(&port->dev, "%s TIOCMIWAIT\n", __func__); cprev = mos7840_port->icount; while (1) { /* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */ @@ -2437,11 +2360,6 @@ static int mos7840_startup(struct usb_serial *serial) int i, status; __u16 Data; - if (!serial) { - dbg("%s", "Invalid Handler"); - return -1; - } - dev = serial->dev; /* we set up the pointers to the endpoints in the mos7840_open * @@ -2449,7 +2367,7 @@ static int mos7840_startup(struct usb_serial *serial) /* set up port private structures */ for (i = 0; i < serial->num_ports; ++i) { - dbg ("mos7840_startup: configuring port %d............", i); + dev_dbg(&dev->dev, "mos7840_startup: configuring port %d............\n", i); mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL); if (mos7840_port == NULL) { dev_err(&dev->dev, "%s - Out of memory\n", __func__); @@ -2470,10 +2388,10 @@ static int mos7840_startup(struct usb_serial *serial) * usb-serial.c:get_free_serial() and cannot therefore be used * to index device instances */ mos7840_port->port_num = i + 1; - dbg ("serial->port[i]->number = %d", serial->port[i]->number); - dbg ("serial->port[i]->serial->minor = %d", serial->port[i]->serial->minor); - dbg ("mos7840_port->port_num = %d", mos7840_port->port_num); - dbg ("serial->minor = %d", serial->minor); + dev_dbg(&dev->dev, "serial->port[i]->number = %d\n", serial->port[i]->number); + dev_dbg(&dev->dev, "serial->port[i]->serial->minor = %d\n", serial->port[i]->serial->minor); + dev_dbg(&dev->dev, "mos7840_port->port_num = %d\n", mos7840_port->port_num); + dev_dbg(&dev->dev, "serial->minor = %d\n", serial->minor); if (mos7840_port->port_num == 1) { mos7840_port->SpRegOffset = 0x0; @@ -2500,18 +2418,17 @@ static int mos7840_startup(struct usb_serial *serial) mos7840_port->ControlRegOffset = 0xd; mos7840_port->DcrRegOffset = 0x1c; } - mos7840_dump_serial_port(mos7840_port); + mos7840_dump_serial_port(serial->port[i], mos7840_port); mos7840_set_port_private(serial->port[i], mos7840_port); /* enable rx_disable bit in control register */ status = mos7840_get_reg_sync(serial->port[i], mos7840_port->ControlRegOffset, &Data); if (status < 0) { - dbg("Reading ControlReg failed status-0x%x", status); + dev_dbg(&dev->dev, "Reading ControlReg failed status-0x%x\n", status); break; } else - dbg("ControlReg Reading success val is %x, status%d", - Data, status); + dev_dbg(&dev->dev, "ControlReg Reading success val is %x, status%d\n", Data, status); Data |= 0x08; /* setting driver done bit */ Data |= 0x04; /* sp1_bit to have cts change reflect in modem status reg */ @@ -2520,11 +2437,10 @@ static int mos7840_startup(struct usb_serial *serial) status = mos7840_set_reg_sync(serial->port[i], mos7840_port->ControlRegOffset, Data); if (status < 0) { - dbg("Writing ControlReg failed(rx_disable) status-0x%x", status); + dev_dbg(&dev->dev, "Writing ControlReg failed(rx_disable) status-0x%x\n", status); break; } else - dbg("ControlReg Writing success(rx_disable) status%d", - status); + dev_dbg(&dev->dev, "ControlReg Writing success(rx_disable) status%d\n", status); /* Write default values in DCR (i.e 0x01 in DCR0, 0x05 in DCR2 and 0x24 in DCR3 */ @@ -2532,61 +2448,57 @@ static int mos7840_startup(struct usb_serial *serial) status = mos7840_set_reg_sync(serial->port[i], (__u16) (mos7840_port->DcrRegOffset + 0), Data); if (status < 0) { - dbg("Writing DCR0 failed status-0x%x", status); + dev_dbg(&dev->dev, "Writing DCR0 failed status-0x%x\n", status); break; } else - dbg("DCR0 Writing success status%d", status); + dev_dbg(&dev->dev, "DCR0 Writing success status%d\n", status); Data = 0x05; status = mos7840_set_reg_sync(serial->port[i], (__u16) (mos7840_port->DcrRegOffset + 1), Data); if (status < 0) { - dbg("Writing DCR1 failed status-0x%x", status); + dev_dbg(&dev->dev, "Writing DCR1 failed status-0x%x\n", status); break; } else - dbg("DCR1 Writing success status%d", status); + dev_dbg(&dev->dev, "DCR1 Writing success status%d\n", status); Data = 0x24; status = mos7840_set_reg_sync(serial->port[i], (__u16) (mos7840_port->DcrRegOffset + 2), Data); if (status < 0) { - dbg("Writing DCR2 failed status-0x%x", status); + dev_dbg(&dev->dev, "Writing DCR2 failed status-0x%x\n", status); break; } else - dbg("DCR2 Writing success status%d", status); + dev_dbg(&dev->dev, "DCR2 Writing success status%d\n", status); /* write values in clkstart0x0 and clkmulti 0x20 */ Data = 0x0; status = mos7840_set_reg_sync(serial->port[i], CLK_START_VALUE_REGISTER, Data); if (status < 0) { - dbg("Writing CLK_START_VALUE_REGISTER failed status-0x%x", status); + dev_dbg(&dev->dev, "Writing CLK_START_VALUE_REGISTER failed status-0x%x\n", status); break; } else - dbg("CLK_START_VALUE_REGISTER Writing success status%d", status); + dev_dbg(&dev->dev, "CLK_START_VALUE_REGISTER Writing success status%d\n", status); Data = 0x20; status = mos7840_set_reg_sync(serial->port[i], CLK_MULTI_REGISTER, Data); if (status < 0) { - dbg("Writing CLK_MULTI_REGISTER failed status-0x%x", - status); + dev_dbg(&dev->dev, "Writing CLK_MULTI_REGISTER failed status-0x%x\n", status); goto error; } else - dbg("CLK_MULTI_REGISTER Writing success status%d", - status); + dev_dbg(&dev->dev, "CLK_MULTI_REGISTER Writing success status%d\n", status); /* write value 0x0 to scratchpad register */ Data = 0x00; status = mos7840_set_uart_reg(serial->port[i], SCRATCH_PAD_REGISTER, Data); if (status < 0) { - dbg("Writing SCRATCH_PAD_REGISTER failed status-0x%x", - status); + dev_dbg(&dev->dev, "Writing SCRATCH_PAD_REGISTER failed status-0x%x\n", status); break; } else - dbg("SCRATCH_PAD_REGISTER Writing success status%d", - status); + dev_dbg(&dev->dev, "SCRATCH_PAD_REGISTER Writing success status%d\n", status); /* Zero Length flag register */ if ((mos7840_port->port_num != 1) @@ -2596,31 +2508,25 @@ static int mos7840_startup(struct usb_serial *serial) status = mos7840_set_reg_sync(serial->port[i], (__u16) (ZLP_REG1 + ((__u16)mos7840_port->port_num)), Data); - dbg("ZLIP offset %x", - (__u16) (ZLP_REG1 + - ((__u16) mos7840_port->port_num))); + dev_dbg(&dev->dev, "ZLIP offset %x\n", + (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num))); if (status < 0) { - dbg("Writing ZLP_REG%d failed status-0x%x", - i + 2, status); + dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 2, status); break; } else - dbg("ZLP_REG%d Writing success status%d", - i + 2, status); + dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 2, status); } else { Data = 0xff; status = mos7840_set_reg_sync(serial->port[i], (__u16) (ZLP_REG1 + ((__u16)mos7840_port->port_num) - 0x1), Data); - dbg("ZLIP offset %x", - (__u16) (ZLP_REG1 + - ((__u16) mos7840_port->port_num) - 0x1)); + dev_dbg(&dev->dev, "ZLIP offset %x\n", + (__u16)(ZLP_REG1 + ((__u16) mos7840_port->port_num) - 0x1)); if (status < 0) { - dbg("Writing ZLP_REG%d failed status-0x%x", - i + 1, status); + dev_dbg(&dev->dev, "Writing ZLP_REG%d failed status-0x%x\n", i + 1, status); break; } else - dbg("ZLP_REG%d Writing success status%d", - i + 1, status); + dev_dbg(&dev->dev, "ZLP_REG%d Writing success status%d\n", i + 1, status); } mos7840_port->control_urb = usb_alloc_urb(0, GFP_KERNEL); @@ -2661,16 +2567,15 @@ static int mos7840_startup(struct usb_serial *serial) MODEM_CONTROL_REGISTER, 0x0300); } } - dbg ("mos7840_startup: all ports configured..........."); /* Zero Length flag enable */ Data = 0x0f; status = mos7840_set_reg_sync(serial->port[0], ZLP_REG5, Data); if (status < 0) { - dbg("Writing ZLP_REG5 failed status-0x%x", status); + dev_dbg(&dev->dev, "Writing ZLP_REG5 failed status-0x%x\n", status); goto error; } else - dbg("ZLP_REG5 Writing success status%d", status); + dev_dbg(&dev->dev, "ZLP_REG5 Writing success status%d\n", status); /* setting configuration feature to one */ usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), @@ -2700,11 +2605,6 @@ static void mos7840_disconnect(struct usb_serial *serial) unsigned long flags; struct moschip_port *mos7840_port; - if (!serial) { - dbg("%s", "Invalid Handler"); - return; - } - /* check for the ports to be closed,close the ports and disconnect */ /* free private structure allocated for serial port * @@ -2712,7 +2612,6 @@ static void mos7840_disconnect(struct usb_serial *serial) for (i = 0; i < serial->num_ports; ++i) { mos7840_port = mos7840_get_port_private(serial->port[i]); - dbg ("mos7840_port %d = %p", i, mos7840_port); if (mos7840_port) { spin_lock_irqsave(&mos7840_port->pool_lock, flags); mos7840_port->zombie = 1; @@ -2732,11 +2631,6 @@ static void mos7840_release(struct usb_serial *serial) int i; struct moschip_port *mos7840_port; - if (!serial) { - dbg("%s", "Invalid Handler"); - return; - } - /* check for the ports to be closed,close the ports and disconnect */ /* free private structure allocated for serial port * @@ -2744,7 +2638,6 @@ static void mos7840_release(struct usb_serial *serial) for (i = 0; i < serial->num_ports; ++i) { mos7840_port = mos7840_get_port_private(serial->port[i]); - dbg("mos7840_port %d = %p", i, mos7840_port); if (mos7840_port) { if (mos7840_port->has_led) { /* Turn off LED */ -- cgit v0.10.2 From 049c6b4e8f85d9ef5f26c8a974e5e9fb084f8ce0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 16:30:23 -0700 Subject: USB: serial: keyspan: remove dbg() usage dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the keyspan driver and uses dev_dbg() instead. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index f0d4f3f..0d37581 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -165,7 +165,7 @@ static void keyspan_set_termios(struct tty_struct *tty, so other rates can be generated if desired. */ baud_rate = tty_get_baud_rate(tty); /* If no match or invalid, don't change */ - if (d_details->calculate_baud_rate(baud_rate, d_details->baudclk, + if (d_details->calculate_baud_rate(port, baud_rate, d_details->baudclk, NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) { /* FIXME - more to do here to ensure rate changes cleanly */ /* FIXME - calcuate exact rate from divisor ? */ @@ -241,8 +241,8 @@ static int keyspan_write(struct tty_struct *tty, dataOffset = 1; } - dbg("%s - for port %d (%d chars), flip=%d", - __func__, port->number, count, p_priv->out_flip); + dev_dbg(&port->dev, "%s - for port %d (%d chars), flip=%d\n", + __func__, port->number, count, p_priv->out_flip); for (left = count; left > 0; left -= todo) { todo = left; @@ -255,11 +255,11 @@ static int keyspan_write(struct tty_struct *tty, this_urb = p_priv->out_urbs[flip]; if (this_urb == NULL) { /* no bulk out, so return 0 bytes written */ - dbg("%s - no output urb :(", __func__); + dev_dbg(&port->dev, "%s - no output urb :(\n", __func__); return count; } - dbg("%s - endpoint %d flip %d", + dev_dbg(&port->dev, "%s - endpoint %d flip %d\n", __func__, usb_pipeendpoint(this_urb->pipe), flip); if (this_urb->status == -EINPROGRESS) { @@ -282,7 +282,7 @@ static int keyspan_write(struct tty_struct *tty, err = usb_submit_urb(this_urb, GFP_ATOMIC); if (err != 0) - dbg("usb_submit_urb(write bulk) failed (%d)", err); + dev_dbg(&port->dev, "usb_submit_urb(write bulk) failed (%d)\n", err); p_priv->tx_start_time[flip] = jiffies; /* Flip for next time if usa26 or usa28 interface @@ -305,8 +305,8 @@ static void usa26_indat_callback(struct urb *urb) endpoint = usb_pipeendpoint(urb->pipe); if (status) { - dbg("%s - nonzero status: %x on endpoint %d.", - __func__, status, endpoint); + dev_dbg(&urb->dev->dev,"%s - nonzero status: %x on endpoint %d.\n", + __func__, status, endpoint); return; } @@ -325,7 +325,7 @@ static void usa26_indat_callback(struct urb *urb) tty_insert_flip_char(tty, data[i], err); } else { /* some bytes had errors, every byte has status */ - dbg("%s - RX error!!!!", __func__); + dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__); for (i = 0; i + 1 < urb->actual_length; i += 2) { int stat = data[i], flag = 0; if (stat & RXERROR_OVERRUN) @@ -345,7 +345,7 @@ static void usa26_indat_callback(struct urb *urb) /* Resubmit urb so we continue receiving */ err = usb_submit_urb(urb, GFP_ATOMIC); if (err != 0) - dbg("%s - resubmit read urb failed. (%d)", __func__, err); + dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err); } /* Outdat handling is common for all devices */ @@ -356,7 +356,7 @@ static void usa2x_outdat_callback(struct urb *urb) port = urb->context; p_priv = usb_get_serial_port_data(port); - dbg("%s - urb %d", __func__, urb == p_priv->out_urbs[1]); + dev_dbg(&port->dev, "%s - urb %d\n", __func__, urb == p_priv->out_urbs[1]); usb_serial_port_softint(port); } @@ -374,7 +374,7 @@ static void usa26_outcont_callback(struct urb *urb) p_priv = usb_get_serial_port_data(port); if (p_priv->resend_cont) { - dbg("%s - sending setup", __func__); + dev_dbg(&port->dev, "%s - sending setup\n", __func__); keyspan_usa26_send_setup(port->serial, port, p_priv->resend_cont - 1); } @@ -394,20 +394,22 @@ static void usa26_instat_callback(struct urb *urb) serial = urb->context; if (status) { - dbg("%s - nonzero status: %x", __func__, status); + dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status); return; } if (urb->actual_length != 9) { - dbg("%s - %d byte report??", __func__, urb->actual_length); + dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length); goto exit; } msg = (struct keyspan_usa26_portStatusMessage *)data; #if 0 - dbg("%s - port status: port %d cts %d dcd %d dsr %d ri %d toff %d txoff %d rxen %d cr %d", - __func__, msg->port, msg->hskia_cts, msg->gpia_dcd, msg->dsr, msg->ri, msg->_txOff, - msg->_txXoff, msg->rxEnabled, msg->controlResponse); + dev_dbg(&urb->dev->dev, + "%s - port status: port %d cts %d dcd %d dsr %d ri %d toff %d txoff %d rxen %d cr %d", + __func__, msg->port, msg->hskia_cts, msg->gpia_dcd, msg->dsr, + msg->ri, msg->_txOff, msg->_txXoff, msg->rxEnabled, + msg->controlResponse); #endif /* Now do something useful with the data */ @@ -415,7 +417,7 @@ static void usa26_instat_callback(struct urb *urb) /* Check port number from message and retrieve private data */ if (msg->port >= serial->num_ports) { - dbg("%s - Unexpected port number %d", __func__, msg->port); + dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port); goto exit; } port = serial->port[msg->port]; @@ -438,7 +440,7 @@ static void usa26_instat_callback(struct urb *urb) /* Resubmit urb so we continue receiving */ err = usb_submit_urb(urb, GFP_ATOMIC); if (err != 0) - dbg("%s - resubmit read urb failed. (%d)", __func__, err); + dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err); exit: ; } @@ -465,8 +467,8 @@ static void usa28_indat_callback(struct urb *urb) do { if (status) { - dbg("%s - nonzero status: %x on endpoint %d.", - __func__, status, usb_pipeendpoint(urb->pipe)); + dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n", + __func__, status, usb_pipeendpoint(urb->pipe)); return; } @@ -484,7 +486,7 @@ static void usa28_indat_callback(struct urb *urb) /* Resubmit urb so we continue receiving */ err = usb_submit_urb(urb, GFP_ATOMIC); if (err != 0) - dbg("%s - resubmit read urb failed. (%d)", + dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err); p_priv->in_flip ^= 1; @@ -505,7 +507,7 @@ static void usa28_outcont_callback(struct urb *urb) p_priv = usb_get_serial_port_data(port); if (p_priv->resend_cont) { - dbg("%s - sending setup", __func__); + dev_dbg(&port->dev, "%s - sending setup\n", __func__); keyspan_usa28_send_setup(port->serial, port, p_priv->resend_cont - 1); } @@ -526,25 +528,28 @@ static void usa28_instat_callback(struct urb *urb) serial = urb->context; if (status) { - dbg("%s - nonzero status: %x", __func__, status); + dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status); return; } if (urb->actual_length != sizeof(struct keyspan_usa28_portStatusMessage)) { - dbg("%s - bad length %d", __func__, urb->actual_length); + dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length); goto exit; } - /*dbg("%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__ - data[0], data[1], data[2], data[3], data[4], data[5], - data[6], data[7], data[8], data[9], data[10], data[11]);*/ + /* + dev_dbg(&urb->dev->dev, + "%s %x %x %x %x %x %x %x %x %x %x %x %x", __func__, + data[0], data[1], data[2], data[3], data[4], data[5], + data[6], data[7], data[8], data[9], data[10], data[11]); + */ /* Now do something useful with the data */ msg = (struct keyspan_usa28_portStatusMessage *)data; /* Check port number from message and retrieve private data */ if (msg->port >= serial->num_ports) { - dbg("%s - Unexpected port number %d", __func__, msg->port); + dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port); goto exit; } port = serial->port[msg->port]; @@ -567,7 +572,7 @@ static void usa28_instat_callback(struct urb *urb) /* Resubmit urb so we continue receiving */ err = usb_submit_urb(urb, GFP_ATOMIC); if (err != 0) - dbg("%s - resubmit read urb failed. (%d)", __func__, err); + dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err); exit: ; } @@ -589,7 +594,7 @@ static void usa49_glocont_callback(struct urb *urb) p_priv = usb_get_serial_port_data(port); if (p_priv->resend_cont) { - dbg("%s - sending setup", __func__); + dev_dbg(&port->dev, "%s - sending setup\n", __func__); keyspan_usa49_send_setup(serial, port, p_priv->resend_cont - 1); break; @@ -613,27 +618,29 @@ static void usa49_instat_callback(struct urb *urb) serial = urb->context; if (status) { - dbg("%s - nonzero status: %x", __func__, status); + dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status); return; } if (urb->actual_length != sizeof(struct keyspan_usa49_portStatusMessage)) { - dbg("%s - bad length %d", __func__, urb->actual_length); + dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length); goto exit; } - /*dbg(" %x %x %x %x %x %x %x %x %x %x %x", __func__, - data[0], data[1], data[2], data[3], data[4], data[5], - data[6], data[7], data[8], data[9], data[10]);*/ + /* + dev_dbg(&urb->dev->dev, "%s: %x %x %x %x %x %x %x %x %x %x %x", + __func__, data[0], data[1], data[2], data[3], data[4], + data[5], data[6], data[7], data[8], data[9], data[10]); + */ /* Now do something useful with the data */ msg = (struct keyspan_usa49_portStatusMessage *)data; /* Check port number from message and retrieve private data */ if (msg->portNumber >= serial->num_ports) { - dbg("%s - Unexpected port number %d", - __func__, msg->portNumber); + dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", + __func__, msg->portNumber); goto exit; } port = serial->port[msg->portNumber]; @@ -656,7 +663,7 @@ static void usa49_instat_callback(struct urb *urb) /* Resubmit urb so we continue receiving */ err = usb_submit_urb(urb, GFP_ATOMIC); if (err != 0) - dbg("%s - resubmit read urb failed. (%d)", __func__, err); + dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err); exit: ; } @@ -676,8 +683,8 @@ static void usa49_indat_callback(struct urb *urb) endpoint = usb_pipeendpoint(urb->pipe); if (status) { - dbg("%s - nonzero status: %x on endpoint %d.", __func__, - status, endpoint); + dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n", + __func__, status, endpoint); return; } @@ -710,7 +717,7 @@ static void usa49_indat_callback(struct urb *urb) /* Resubmit urb so we continue receiving */ err = usb_submit_urb(urb, GFP_ATOMIC); if (err != 0) - dbg("%s - resubmit read urb failed. (%d)", __func__, err); + dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err); } static void usa49wg_indat_callback(struct urb *urb) @@ -725,7 +732,7 @@ static void usa49wg_indat_callback(struct urb *urb) serial = urb->context; if (status) { - dbg("%s - nonzero status: %x", __func__, status); + dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status); return; } @@ -738,7 +745,7 @@ static void usa49wg_indat_callback(struct urb *urb) /* Check port number from message*/ if (data[i] >= serial->num_ports) { - dbg("%s - Unexpected port number %d", + dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, data[i]); return; } @@ -778,7 +785,7 @@ static void usa49wg_indat_callback(struct urb *urb) /* Resubmit urb so we continue receiving */ err = usb_submit_urb(urb, GFP_ATOMIC); if (err != 0) - dbg("%s - resubmit read urb failed. (%d)", __func__, err); + dev_dbg(&urb->dev->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err); } /* not used, usa-49 doesn't have per-port control endpoints */ @@ -799,7 +806,7 @@ static void usa90_indat_callback(struct urb *urb) endpoint = usb_pipeendpoint(urb->pipe); if (status) { - dbg("%s - nonzero status: %x on endpoint %d.", + dev_dbg(&urb->dev->dev, "%s - nonzero status: %x on endpoint %d.\n", __func__, status, endpoint); return; } @@ -828,7 +835,7 @@ static void usa90_indat_callback(struct urb *urb) err); } else { /* some bytes had errors, every byte has status */ - dbg("%s - RX error!!!!", __func__); + dev_dbg(&port->dev, "%s - RX error!!!!\n", __func__); for (i = 0; i + 1 < urb->actual_length; i += 2) { int stat = data[i], flag = 0; if (stat & RXERROR_OVERRUN) @@ -850,7 +857,7 @@ static void usa90_indat_callback(struct urb *urb) /* Resubmit urb so we continue receiving */ err = usb_submit_urb(urb, GFP_ATOMIC); if (err != 0) - dbg("%s - resubmit read urb failed. (%d)", __func__, err); + dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err); } @@ -868,11 +875,11 @@ static void usa90_instat_callback(struct urb *urb) serial = urb->context; if (status) { - dbg("%s - nonzero status: %x", __func__, status); + dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status); return; } if (urb->actual_length < 14) { - dbg("%s - %d byte report??", __func__, urb->actual_length); + dev_dbg(&urb->dev->dev, "%s - %d byte report??\n", __func__, urb->actual_length); goto exit; } @@ -900,7 +907,7 @@ static void usa90_instat_callback(struct urb *urb) /* Resubmit urb so we continue receiving */ err = usb_submit_urb(urb, GFP_ATOMIC); if (err != 0) - dbg("%s - resubmit read urb failed. (%d)", __func__, err); + dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err); exit: ; } @@ -914,7 +921,7 @@ static void usa90_outcont_callback(struct urb *urb) p_priv = usb_get_serial_port_data(port); if (p_priv->resend_cont) { - dbg("%s - sending setup", __func__); + dev_dbg(&urb->dev->dev, "%s - sending setup\n", __func__); keyspan_usa90_send_setup(port->serial, port, p_priv->resend_cont - 1); } @@ -935,13 +942,13 @@ static void usa67_instat_callback(struct urb *urb) serial = urb->context; if (status) { - dbg("%s - nonzero status: %x", __func__, status); + dev_dbg(&urb->dev->dev, "%s - nonzero status: %x\n", __func__, status); return; } if (urb->actual_length != sizeof(struct keyspan_usa67_portStatusMessage)) { - dbg("%s - bad length %d", __func__, urb->actual_length); + dev_dbg(&urb->dev->dev, "%s - bad length %d\n", __func__, urb->actual_length); return; } @@ -951,7 +958,7 @@ static void usa67_instat_callback(struct urb *urb) /* Check port number from message and retrieve private data */ if (msg->port >= serial->num_ports) { - dbg("%s - Unexpected port number %d", __func__, msg->port); + dev_dbg(&urb->dev->dev, "%s - Unexpected port number %d\n", __func__, msg->port); return; } @@ -973,7 +980,7 @@ static void usa67_instat_callback(struct urb *urb) /* Resubmit urb so we continue receiving */ err = usb_submit_urb(urb, GFP_ATOMIC); if (err != 0) - dbg("%s - resubmit read urb failed. (%d)", __func__, err); + dev_dbg(&port->dev, "%s - resubmit read urb failed. (%d)\n", __func__, err); } static void usa67_glocont_callback(struct urb *urb) @@ -989,7 +996,7 @@ static void usa67_glocont_callback(struct urb *urb) p_priv = usb_get_serial_port_data(port); if (p_priv->resend_cont) { - dbg("%s - sending setup", __func__); + dev_dbg(&port->dev, "%s - sending setup\n", __func__); keyspan_usa67_send_setup(serial, port, p_priv->resend_cont - 1); break; @@ -1068,8 +1075,7 @@ static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port) usb_clear_halt(urb->dev, urb->pipe); err = usb_submit_urb(urb, GFP_KERNEL); if (err != 0) - dbg("%s - submit urb %d failed (%d)", - __func__, i, err); + dev_dbg(&port->dev, "%s - submit urb %d failed (%d)\n", __func__, i, err); } /* Reset low level data toggle on out endpoints */ @@ -1092,7 +1098,7 @@ static int keyspan_open(struct tty_struct *tty, struct usb_serial_port *port) baud_rate = tty_get_baud_rate(tty); /* If no match or invalid, leave as default */ if (baud_rate >= 0 - && d_details->calculate_baud_rate(baud_rate, d_details->baudclk, + && d_details->calculate_baud_rate(port, baud_rate, d_details->baudclk, NULL, NULL, NULL, device_port) == KEYSPAN_BAUD_RATE_OK) { p_priv->baud = baud_rate; } @@ -1142,7 +1148,7 @@ static void keyspan_close(struct usb_serial_port *port) } /*while (p_priv->outcont_urb->status == -EINPROGRESS) { - dbg("%s - urb in progress", __func__); + dev_dbg(&port->dev, "%s - urb in progress\n", __func__); }*/ p_priv->out_flip = 0; @@ -1167,13 +1173,13 @@ static int keyspan_fake_startup(struct usb_serial *serial) char *fw_name; const struct firmware *fw; - dbg("Keyspan startup version %04x product %04x", - le16_to_cpu(serial->dev->descriptor.bcdDevice), - le16_to_cpu(serial->dev->descriptor.idProduct)); + dev_dbg(&serial->dev->dev, "Keyspan startup version %04x product %04x\n", + le16_to_cpu(serial->dev->descriptor.bcdDevice), + le16_to_cpu(serial->dev->descriptor.idProduct)); if ((le16_to_cpu(serial->dev->descriptor.bcdDevice) & 0x8000) != 0x8000) { - dbg("Firmware already loaded. Quitting."); + dev_dbg(&serial->dev->dev, "Firmware already loaded. Quitting.\n"); return 1; } @@ -1238,7 +1244,7 @@ static int keyspan_fake_startup(struct usb_serial *serial) return 1; } - dbg("Uploading Keyspan %s firmware.", fw_name); + dev_dbg(&serial->dev->dev, "Uploading Keyspan %s firmware.\n", fw_name); /* download the firmware image */ response = ezusb_set_reset(serial->dev, 1); @@ -1296,10 +1302,10 @@ static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint, if (endpoint == -1) return NULL; /* endpoint not needed */ - dbg("%s - alloc for endpoint %d.", __func__, endpoint); + dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %d.\n", __func__, endpoint); urb = usb_alloc_urb(0, GFP_KERNEL); /* No ISO */ if (urb == NULL) { - dbg("%s - alloc for endpoint %d failed.", __func__, endpoint); + dev_dbg(&serial->interface->dev, "%s - alloc for endpoint %d failed.\n", __func__, endpoint); return NULL; } @@ -1332,7 +1338,7 @@ static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint, return NULL; } - dbg("%s - using urb %p for %s endpoint %x", + dev_dbg(&serial->interface->dev, "%s - using urb %p for %s endpoint %x\n", __func__, urb, ep_type_name, endpoint); return urb; } @@ -1464,14 +1470,15 @@ static void keyspan_setup_urbs(struct usb_serial *serial) } /* usa19 function doesn't require prescaler */ -static int keyspan_usa19_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi, +static int keyspan_usa19_calc_baud(struct usb_serial_port *port, + u32 baud_rate, u32 baudclk, u8 *rate_hi, u8 *rate_low, u8 *prescaler, int portnum) { u32 b16, /* baud rate times 16 (actual rate used internally) */ div, /* divisor */ cnt; /* inverse of divisor (programmed into 8051) */ - dbg("%s - %d.", __func__, baud_rate); + dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate); /* prevent divide by zero... */ b16 = baud_rate * 16L; @@ -1498,19 +1505,20 @@ static int keyspan_usa19_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi, if (rate_hi) *rate_hi = (u8) ((cnt >> 8) & 0xff); if (rate_low && rate_hi) - dbg("%s - %d %02x %02x.", + dev_dbg(&port->dev, "%s - %d %02x %02x.\n", __func__, baud_rate, *rate_hi, *rate_low); return KEYSPAN_BAUD_RATE_OK; } /* usa19hs function doesn't require prescaler */ -static int keyspan_usa19hs_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi, - u8 *rate_low, u8 *prescaler, int portnum) +static int keyspan_usa19hs_calc_baud(struct usb_serial_port *port, + u32 baud_rate, u32 baudclk, u8 *rate_hi, + u8 *rate_low, u8 *prescaler, int portnum) { u32 b16, /* baud rate times 16 (actual rate used internally) */ div; /* divisor */ - dbg("%s - %d.", __func__, baud_rate); + dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate); /* prevent divide by zero... */ b16 = baud_rate * 16L; @@ -1533,13 +1541,14 @@ static int keyspan_usa19hs_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi, *rate_hi = (u8) ((div >> 8) & 0xff); if (rate_low && rate_hi) - dbg("%s - %d %02x %02x.", + dev_dbg(&port->dev, "%s - %d %02x %02x.\n", __func__, baud_rate, *rate_hi, *rate_low); return KEYSPAN_BAUD_RATE_OK; } -static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi, +static int keyspan_usa19w_calc_baud(struct usb_serial_port *port, + u32 baud_rate, u32 baudclk, u8 *rate_hi, u8 *rate_low, u8 *prescaler, int portnum) { u32 b16, /* baud rate times 16 (actual rate used internally) */ @@ -1551,7 +1560,7 @@ static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi, u8 best_prescaler; int i; - dbg("%s - %d.", __func__, baud_rate); + dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate); /* prevent divide by zero */ b16 = baud_rate * 16L; @@ -1596,20 +1605,21 @@ static int keyspan_usa19w_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi, *rate_hi = (u8) ((div >> 8) & 0xff); if (prescaler) { *prescaler = best_prescaler; - /* dbg("%s - %d %d", __func__, *prescaler, div); */ + /* dev_dbg(&port->dev, "%s - %d %d\n", __func__, *prescaler, div); */ } return KEYSPAN_BAUD_RATE_OK; } /* USA-28 supports different maximum baud rates on each port */ -static int keyspan_usa28_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi, - u8 *rate_low, u8 *prescaler, int portnum) +static int keyspan_usa28_calc_baud(struct usb_serial_port *port, + u32 baud_rate, u32 baudclk, u8 *rate_hi, + u8 *rate_low, u8 *prescaler, int portnum) { u32 b16, /* baud rate times 16 (actual rate used internally) */ div, /* divisor */ cnt; /* inverse of divisor (programmed into 8051) */ - dbg("%s - %d.", __func__, baud_rate); + dev_dbg(&port->dev, "%s - %d.\n", __func__, baud_rate); /* prevent divide by zero */ b16 = baud_rate * 16L; @@ -1642,7 +1652,7 @@ static int keyspan_usa28_calc_baud(u32 baud_rate, u32 baudclk, u8 *rate_hi, *rate_low = (u8) (cnt & 0xff); if (rate_hi) *rate_hi = (u8) ((cnt >> 8) & 0xff); - dbg("%s - %d OK.", __func__, baud_rate); + dev_dbg(&port->dev, "%s - %d OK.\n", __func__, baud_rate); return KEYSPAN_BAUD_RATE_OK; } @@ -1658,7 +1668,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial, struct urb *this_urb; int device_port, err; - dbg("%s reset=%d", __func__, reset_port); + dev_dbg(&port->dev, "%s reset=%d\n", __func__, reset_port); s_priv = usb_get_serial_data(serial); p_priv = usb_get_serial_port_data(port); @@ -1668,11 +1678,11 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial, outcont_urb = d_details->outcont_endpoints[port->number]; this_urb = p_priv->outcont_urb; - dbg("%s - endpoint %d", __func__, usb_pipeendpoint(this_urb->pipe)); + dev_dbg(&port->dev, "%s - endpoint %d\n", __func__, usb_pipeendpoint(this_urb->pipe)); /* Make sure we have an urb then send the message */ if (this_urb == NULL) { - dbg("%s - oops no urb.", __func__); + dev_dbg(&port->dev, "%s - oops no urb.\n", __func__); return -1; } @@ -1681,7 +1691,7 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial, if ((reset_port + 1) > p_priv->resend_cont) p_priv->resend_cont = reset_port + 1; if (this_urb->status == -EINPROGRESS) { - /* dbg("%s - already writing", __func__); */ + /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */ mdelay(5); return -1; } @@ -1692,11 +1702,11 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial, if (p_priv->old_baud != p_priv->baud) { p_priv->old_baud = p_priv->baud; msg.setClocking = 0xff; - if (d_details->calculate_baud_rate - (p_priv->baud, d_details->baudclk, &msg.baudHi, - &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) { - dbg("%s - Invalid baud rate %d requested, using 9600.", - __func__, p_priv->baud); + if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk, + &msg.baudHi, &msg.baudLo, &msg.prescaler, + device_port) == KEYSPAN_INVALID_BAUD_RATE) { + dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n", + __func__, p_priv->baud); msg.baudLo = 0; msg.baudHi = 125; /* Values for 9600 baud */ msg.prescaler = 10; @@ -1790,12 +1800,12 @@ static int keyspan_usa26_send_setup(struct usb_serial *serial, err = usb_submit_urb(this_urb, GFP_ATOMIC); if (err != 0) - dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err); + dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err); #if 0 else { - dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__ - outcont_urb, this_urb->transfer_buffer_length, - usb_pipeendpoint(this_urb->pipe)); + dev_dbg(&port->dev, "%s - usb_submit_urb(%d) OK %d bytes (end %d)\n", __func__ + outcont_urb, this_urb->transfer_buffer_length, + usb_pipeendpoint(this_urb->pipe)); } #endif @@ -1821,7 +1831,7 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial, /* only do something if we have a bulk out endpoint */ this_urb = p_priv->outcont_urb; if (this_urb == NULL) { - dbg("%s - oops no urb.", __func__); + dev_dbg(&port->dev, "%s - oops no urb.\n", __func__); return -1; } @@ -1830,7 +1840,7 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial, if ((reset_port + 1) > p_priv->resend_cont) p_priv->resend_cont = reset_port + 1; if (this_urb->status == -EINPROGRESS) { - dbg("%s already writing", __func__); + dev_dbg(&port->dev, "%s already writing\n", __func__); mdelay(5); return -1; } @@ -1838,9 +1848,10 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial, memset(&msg, 0, sizeof(struct keyspan_usa28_portControlMessage)); msg.setBaudRate = 1; - if (d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk, - &msg.baudHi, &msg.baudLo, NULL, device_port) == KEYSPAN_INVALID_BAUD_RATE) { - dbg("%s - Invalid baud rate requested %d.", + if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk, + &msg.baudHi, &msg.baudLo, NULL, + device_port) == KEYSPAN_INVALID_BAUD_RATE) { + dev_dbg(&port->dev, "%s - Invalid baud rate requested %d.\n", __func__, p_priv->baud); msg.baudLo = 0xff; msg.baudHi = 0xb2; /* Values for 9600 baud */ @@ -1915,10 +1926,10 @@ static int keyspan_usa28_send_setup(struct usb_serial *serial, err = usb_submit_urb(this_urb, GFP_ATOMIC); if (err != 0) - dbg("%s - usb_submit_urb(setup) failed", __func__); + dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed\n", __func__); #if 0 else { - dbg("%s - usb_submit_urb(setup) OK %d bytes", __func__, + dev_dbg(&port->dev, "%s - usb_submit_urb(setup) OK %d bytes\n", __func__, this_urb->transfer_buffer_length); } #endif @@ -1949,13 +1960,13 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, /* Make sure we have an urb then send the message */ if (this_urb == NULL) { - dbg("%s - oops no urb for port %d.", __func__, port->number); + dev_dbg(&port->dev, "%s - oops no urb for port %d.\n", __func__, port->number); return -1; } - dbg("%s - endpoint %d port %d (%d)", - __func__, usb_pipeendpoint(this_urb->pipe), - port->number, device_port); + dev_dbg(&port->dev, "%s - endpoint %d port %d (%d)\n", + __func__, usb_pipeendpoint(this_urb->pipe), + port->number, device_port); /* Save reset port val for resend. Don't overwrite resend for open/close condition. */ @@ -1963,7 +1974,7 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, p_priv->resend_cont = reset_port + 1; if (this_urb->status == -EINPROGRESS) { - /* dbg("%s - already writing", __func__); */ + /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */ mdelay(5); return -1; } @@ -1977,11 +1988,11 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, if (p_priv->old_baud != p_priv->baud) { p_priv->old_baud = p_priv->baud; msg.setClocking = 0xff; - if (d_details->calculate_baud_rate - (p_priv->baud, d_details->baudclk, &msg.baudHi, - &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) { - dbg("%s - Invalid baud rate %d requested, using 9600.", - __func__, p_priv->baud); + if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk, + &msg.baudHi, &msg.baudLo, &msg.prescaler, + device_port) == KEYSPAN_INVALID_BAUD_RATE) { + dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n", + __func__, p_priv->baud); msg.baudLo = 0; msg.baudHi = 125; /* Values for 9600 baud */ msg.prescaler = 10; @@ -2100,12 +2111,12 @@ static int keyspan_usa49_send_setup(struct usb_serial *serial, } err = usb_submit_urb(this_urb, GFP_ATOMIC); if (err != 0) - dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err); + dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err); #if 0 else { - dbg("%s - usb_submit_urb(%d) OK %d bytes (end %d)", __func__, - outcont_urb, this_urb->transfer_buffer_length, - usb_pipeendpoint(this_urb->pipe)); + dev_dbg(&port->dev, "%s - usb_submit_urb(%d) OK %d bytes (end %d)\n", __func__, + outcont_urb, this_urb->transfer_buffer_length, + usb_pipeendpoint(this_urb->pipe)); } #endif @@ -2131,7 +2142,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial, /* only do something if we have a bulk out endpoint */ this_urb = p_priv->outcont_urb; if (this_urb == NULL) { - dbg("%s - oops no urb.", __func__); + dev_dbg(&port->dev, "%s - oops no urb.\n", __func__); return -1; } @@ -2140,7 +2151,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial, if ((reset_port + 1) > p_priv->resend_cont) p_priv->resend_cont = reset_port + 1; if (this_urb->status == -EINPROGRESS) { - dbg("%s already writing", __func__); + dev_dbg(&port->dev, "%s already writing\n", __func__); mdelay(5); return -1; } @@ -2151,13 +2162,12 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial, if (p_priv->old_baud != p_priv->baud) { p_priv->old_baud = p_priv->baud; msg.setClocking = 0x01; - if (d_details->calculate_baud_rate - (p_priv->baud, d_details->baudclk, &msg.baudHi, - &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) { - dbg("%s - Invalid baud rate %d requested, using 9600.", - __func__, p_priv->baud); + if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk, + &msg.baudHi, &msg.baudLo, &prescaler, 0) == KEYSPAN_INVALID_BAUD_RATE) { + dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n", + __func__, p_priv->baud); p_priv->baud = 9600; - d_details->calculate_baud_rate(p_priv->baud, d_details->baudclk, + d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk, &msg.baudHi, &msg.baudLo, &prescaler, 0); } msg.setRxMode = 1; @@ -2239,7 +2249,7 @@ static int keyspan_usa90_send_setup(struct usb_serial *serial, err = usb_submit_urb(this_urb, GFP_ATOMIC); if (err != 0) - dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err); + dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err); return 0; } @@ -2265,7 +2275,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial, /* Make sure we have an urb then send the message */ if (this_urb == NULL) { - dbg("%s - oops no urb for port %d.", __func__, + dev_dbg(&port->dev, "%s - oops no urb for port %d.\n", __func__, port->number); return -1; } @@ -2275,7 +2285,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial, if ((reset_port + 1) > p_priv->resend_cont) p_priv->resend_cont = reset_port + 1; if (this_urb->status == -EINPROGRESS) { - /* dbg("%s - already writing", __func__); */ + /* dev_dbg(&port->dev, "%s - already writing\n", __func__); */ mdelay(5); return -1; } @@ -2288,11 +2298,11 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial, if (p_priv->old_baud != p_priv->baud) { p_priv->old_baud = p_priv->baud; msg.setClocking = 0xff; - if (d_details->calculate_baud_rate - (p_priv->baud, d_details->baudclk, &msg.baudHi, - &msg.baudLo, &msg.prescaler, device_port) == KEYSPAN_INVALID_BAUD_RATE) { - dbg("%s - Invalid baud rate %d requested, using 9600.", - __func__, p_priv->baud); + if (d_details->calculate_baud_rate(port, p_priv->baud, d_details->baudclk, + &msg.baudHi, &msg.baudLo, &msg.prescaler, + device_port) == KEYSPAN_INVALID_BAUD_RATE) { + dev_dbg(&port->dev, "%s - Invalid baud rate %d requested, using 9600.\n", + __func__, p_priv->baud); msg.baudLo = 0; msg.baudHi = 125; /* Values for 9600 baud */ msg.prescaler = 10; @@ -2383,8 +2393,7 @@ static int keyspan_usa67_send_setup(struct usb_serial *serial, err = usb_submit_urb(this_urb, GFP_ATOMIC); if (err != 0) - dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, - err); + dev_dbg(&port->dev, "%s - usb_submit_urb(setup) failed (%d)\n", __func__, err); return 0; } @@ -2440,8 +2449,7 @@ static int keyspan_startup(struct usb_serial *serial) /* Setup private data for serial driver */ s_priv = kzalloc(sizeof(struct keyspan_serial_private), GFP_KERNEL); if (!s_priv) { - dbg("%s - kmalloc for keyspan_serial_private failed.", - __func__); + dev_dbg(&serial->dev->dev, "%s - kmalloc for keyspan_serial_private failed.\n", __func__); return -ENOMEM; } @@ -2454,7 +2462,7 @@ static int keyspan_startup(struct usb_serial *serial) p_priv = kzalloc(sizeof(struct keyspan_port_private), GFP_KERNEL); if (!p_priv) { - dbg("%s - kmalloc for keyspan_port_private (%d) failed!.", __func__, i); + dev_dbg(&port->dev, "%s - kmalloc for keyspan_port_private (%d) failed!.\n", __func__, i); return 1; } p_priv->device_details = d_details; @@ -2466,13 +2474,13 @@ static int keyspan_startup(struct usb_serial *serial) if (s_priv->instat_urb != NULL) { err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL); if (err != 0) - dbg("%s - submit instat urb failed %d", __func__, + dev_dbg(&port->dev, "%s - submit instat urb failed %d\n", __func__, err); } if (s_priv->indat_urb != NULL) { err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL); if (err != 0) - dbg("%s - submit indat urb failed %d", __func__, + dev_dbg(&port->dev, "%s - submit indat urb failed %d\n", __func__, err); } @@ -2527,10 +2535,8 @@ static void keyspan_release(struct usb_serial *serial) s_priv = usb_get_serial_data(serial); - /* dbg("Freeing serial->private."); */ kfree(s_priv); - /* dbg("Freeing port->private."); */ /* Now free per port private data */ for (i = 0; i < serial->num_ports; i++) { port = serial->port[i]; diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h index fe1c5d9..0a8a40b 100644 --- a/drivers/usb/serial/keyspan.h +++ b/drivers/usb/serial/keyspan.h @@ -64,19 +64,23 @@ static int keyspan_tiocmset (struct tty_struct *tty, unsigned int clear); static int keyspan_fake_startup (struct usb_serial *serial); -static int keyspan_usa19_calc_baud (u32 baud_rate, u32 baudclk, +static int keyspan_usa19_calc_baud (struct usb_serial_port *port, + u32 baud_rate, u32 baudclk, u8 *rate_hi, u8 *rate_low, u8 *prescaler, int portnum); -static int keyspan_usa19w_calc_baud (u32 baud_rate, u32 baudclk, +static int keyspan_usa19w_calc_baud (struct usb_serial_port *port, + u32 baud_rate, u32 baudclk, u8 *rate_hi, u8 *rate_low, u8 *prescaler, int portnum); -static int keyspan_usa28_calc_baud (u32 baud_rate, u32 baudclk, +static int keyspan_usa28_calc_baud (struct usb_serial_port *port, + u32 baud_rate, u32 baudclk, u8 *rate_hi, u8 *rate_low, u8 *prescaler, int portnum); -static int keyspan_usa19hs_calc_baud (u32 baud_rate, u32 baudclk, +static int keyspan_usa19hs_calc_baud (struct usb_serial_port *port, + u32 baud_rate, u32 baudclk, u8 *rate_hi, u8 *rate_low, u8 *prescaler, int portnum); @@ -188,8 +192,9 @@ struct keyspan_device_details { /* Endpoint used for global control functions */ int glocont_endpoint; - int (*calculate_baud_rate) (u32 baud_rate, u32 baudclk, - u8 *rate_hi, u8 *rate_low, u8 *prescaler, int portnum); + int (*calculate_baud_rate) (struct usb_serial_port *port, + u32 baud_rate, u32 baudclk, + u8 *rate_hi, u8 *rate_low, u8 *prescaler, int portnum); u32 baudclk; }; -- cgit v0.10.2 From 7ebcb334433fa73c74b0c397fab831cdc2000418 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 16:34:21 -0700 Subject: USB: serial: keyspan: fix up some compiler warnings I accidentally caused some compiler warnings, that were correct in pointing out problems, so fix them up now. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 0d37581..1635f506 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -2474,14 +2474,12 @@ static int keyspan_startup(struct usb_serial *serial) if (s_priv->instat_urb != NULL) { err = usb_submit_urb(s_priv->instat_urb, GFP_KERNEL); if (err != 0) - dev_dbg(&port->dev, "%s - submit instat urb failed %d\n", __func__, - err); + dev_dbg(&serial->dev->dev, "%s - submit instat urb failed %d\n", __func__, err); } if (s_priv->indat_urb != NULL) { err = usb_submit_urb(s_priv->indat_urb, GFP_KERNEL); if (err != 0) - dev_dbg(&port->dev, "%s - submit indat urb failed %d\n", __func__, - err); + dev_dbg(&serial->dev->dev, "%s - submit indat urb failed %d\n", __func__, err); } return 0; -- cgit v0.10.2 From 67e6da702753dac8f0540209dded80a0c4e60d81 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 16:58:58 -0700 Subject: USB: serial: io_ti.c: remove dbg() usage dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. CC: Johan Hovold CC: "Eric W. Biederman" CC: Rusty Russell CC: Alan Stern Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 3936904..54916d7 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -233,8 +233,8 @@ static int ti_vread_sync(struct usb_device *dev, __u8 request, if (status < 0) return status; if (status != size) { - dbg("%s - wanted to write %d, but only wrote %d", - __func__, size, status); + dev_dbg(&dev->dev, "%s - wanted to write %d, but only wrote %d\n", + __func__, size, status); return -ECOMM; } return 0; @@ -251,8 +251,8 @@ static int ti_vsend_sync(struct usb_device *dev, __u8 request, if (status < 0) return status; if (status != size) { - dbg("%s - wanted to write %d, but only wrote %d", - __func__, size, status); + dev_dbg(&dev->dev, "%s - wanted to write %d, but only wrote %d\n", + __func__, size, status); return -ECOMM; } return 0; @@ -270,7 +270,7 @@ static int purge_port(struct usb_serial_port *port, __u16 mask) { int port_number = port->number - port->serial->minor; - dbg("%s - port %d, mask %x", __func__, port_number, mask); + dev_dbg(&port->dev, "%s - port %d, mask %x\n", __func__, port_number, mask); return send_cmd(port->serial->dev, UMPC_PURGE_PORT, @@ -295,7 +295,7 @@ static int read_download_mem(struct usb_device *dev, int start_address, __u8 read_length; __be16 be_start_address; - dbg("%s - @ %x for %d", __func__, start_address, length); + dev_dbg(&dev->dev, "%s - @ %x for %d\n", __func__, start_address, length); /* Read in blocks of 64 bytes * (TI firmware can't handle more than 64 byte reads) @@ -307,8 +307,7 @@ static int read_download_mem(struct usb_device *dev, int start_address, read_length = (__u8)length; if (read_length > 1) { - dbg("%s - @ %x for %d", __func__, - start_address, read_length); + dev_dbg(&dev->dev, "%s - @ %x for %d\n", __func__, start_address, read_length); } be_start_address = cpu_to_be16(start_address); status = ti_vread_sync(dev, UMPC_MEMORY_READ, @@ -317,7 +316,7 @@ static int read_download_mem(struct usb_device *dev, int start_address, buffer, read_length); if (status) { - dbg("%s - ERROR %x", __func__, status); + dev_dbg(&dev->dev, "%s - ERROR %x\n", __func__, status); return status; } @@ -353,13 +352,13 @@ static int read_boot_mem(struct edgeport_serial *serial, UMPC_MEMORY_READ, serial->TI_I2C_Type, (__u16)(start_address+i), &buffer[i], 0x01); if (status) { - dbg("%s - ERROR %x", __func__, status); + dev_dbg(&serial->serial->dev->dev, "%s - ERROR %x\n", __func__, status); return status; } } - dbg("%s - start_address = %x, length = %d", - __func__, start_address, length); + dev_dbg(&serial->serial->dev->dev, "%s - start_address = %x, length = %d\n", + __func__, start_address, length); usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, length, buffer); @@ -398,8 +397,7 @@ static int write_boot_mem(struct edgeport_serial *serial, return status; } - dbg("%s - start_sddr = %x, length = %d", - __func__, start_address, length); + dev_dbg(&serial->serial->dev->dev, "%s - start_sddr = %x, length = %d\n", __func__, start_address, length); usb_serial_debug_data(debug, &serial->serial->dev->dev, __func__, length, buffer); @@ -411,6 +409,7 @@ static int write_boot_mem(struct edgeport_serial *serial, static int write_i2c_mem(struct edgeport_serial *serial, int start_address, int length, __u8 address_type, __u8 *buffer) { + struct device *dev = &serial->serial->dev->dev; int status = 0; int write_length; __be16 be_start_address; @@ -424,10 +423,9 @@ static int write_i2c_mem(struct edgeport_serial *serial, if (write_length > length) write_length = length; - dbg("%s - BytesInFirstPage Addr = %x, length = %d", - __func__, start_address, write_length); - usb_serial_debug_data(debug, &serial->serial->dev->dev, - __func__, write_length, buffer); + dev_dbg(dev, "%s - BytesInFirstPage Addr = %x, length = %d\n", + __func__, start_address, write_length); + usb_serial_debug_data(debug, dev, __func__, write_length, buffer); /* Write first page */ be_start_address = cpu_to_be16(start_address); @@ -436,7 +434,7 @@ static int write_i2c_mem(struct edgeport_serial *serial, (__force __u16)be_start_address, buffer, write_length); if (status) { - dbg("%s - ERROR %d", __func__, status); + dev_dbg(dev, "%s - ERROR %d\n", __func__, status); return status; } @@ -452,10 +450,9 @@ static int write_i2c_mem(struct edgeport_serial *serial, else write_length = length; - dbg("%s - Page Write Addr = %x, length = %d", - __func__, start_address, write_length); - usb_serial_debug_data(debug, &serial->serial->dev->dev, - __func__, write_length, buffer); + dev_dbg(dev, "%s - Page Write Addr = %x, length = %d\n", + __func__, start_address, write_length); + usb_serial_debug_data(debug, dev, __func__, write_length, buffer); /* Write next page */ be_start_address = cpu_to_be16(start_address); @@ -464,8 +461,7 @@ static int write_i2c_mem(struct edgeport_serial *serial, (__force __u16)be_start_address, buffer, write_length); if (status) { - dev_err(&serial->serial->dev->dev, "%s - ERROR %d\n", - __func__, status); + dev_err(dev, "%s - ERROR %d\n", __func__, status); return status; } @@ -508,7 +504,7 @@ static int tx_active(struct edgeport_port *port) if (status) goto exit_is_tx_active; - dbg("%s - XByteCount 0x%X", __func__, oedb->XByteCount); + dev_dbg(&port->port->dev, "%s - XByteCount 0x%X\n", __func__, oedb->XByteCount); /* and the LSR */ status = read_ram(port->port->serial->dev, @@ -516,7 +512,7 @@ static int tx_active(struct edgeport_port *port) if (status) goto exit_is_tx_active; - dbg("%s - LSR = 0x%X", __func__, *lsr); + dev_dbg(&port->port->dev, "%s - LSR = 0x%X\n", __func__, *lsr); /* If either buffer has data or we are transmitting then return TRUE */ if ((oedb->XByteCount & 0x80) != 0) @@ -527,7 +523,7 @@ static int tx_active(struct edgeport_port *port) /* We return Not Active if we get any kind of error */ exit_is_tx_active: - dbg("%s - return %d", __func__, bytes_left); + dev_dbg(&port->port->dev, "%s - return %d\n", __func__, bytes_left); kfree(lsr); kfree(oedb); @@ -599,14 +595,13 @@ static int choose_config(struct usb_device *dev) * configuration # 1, which is Config Descriptor 0. */ - dbg("%s - Number of Interfaces = %d", - __func__, dev->config->desc.bNumInterfaces); - dbg("%s - MAX Power = %d", - __func__, dev->config->desc.bMaxPower * 2); + dev_dbg(&dev->dev, "%s - Number of Interfaces = %d\n", + __func__, dev->config->desc.bNumInterfaces); + dev_dbg(&dev->dev, "%s - MAX Power = %d\n", + __func__, dev->config->desc.bMaxPower * 2); if (dev->config->desc.bNumInterfaces != 1) { - dev_err(&dev->dev, "%s - bNumInterfaces is not 1, ERROR!\n", - __func__); + dev_err(&dev->dev, "%s - bNumInterfaces is not 1, ERROR!\n", __func__); return -ENODEV; } @@ -684,7 +679,7 @@ static int valid_csum(struct ti_i2c_desc *rom_desc, __u8 *buffer) cs = (__u8)(cs + buffer[i]); if (cs != rom_desc->CheckSum) { - dbg("%s - Mismatch %x - %x", __func__, rom_desc->CheckSum, cs); + pr_debug("%s - Mismatch %x - %x", __func__, rom_desc->CheckSum, cs); return -EINVAL; } return 0; @@ -736,11 +731,11 @@ static int check_i2c_image(struct edgeport_serial *serial) if ((start_address + sizeof(struct ti_i2c_desc) + rom_desc->Size) > TI_MAX_I2C_SIZE) { status = -ENODEV; - dbg("%s - structure too big, erroring out.", __func__); + dev_dbg(dev, "%s - structure too big, erroring out.\n", __func__); break; } - dbg("%s Type = 0x%x", __func__, rom_desc->Type); + dev_dbg(dev, "%s Type = 0x%x\n", __func__, rom_desc->Type); /* Skip type 2 record */ ttype = rom_desc->Type & 0x0f; @@ -779,18 +774,18 @@ static int get_manuf_info(struct edgeport_serial *serial, __u8 *buffer) int start_address; struct ti_i2c_desc *rom_desc; struct edge_ti_manuf_descriptor *desc; + struct device *dev = &serial->serial->dev->dev; rom_desc = kmalloc(sizeof(*rom_desc), GFP_KERNEL); if (!rom_desc) { - dev_err(&serial->serial->dev->dev, "%s - out of memory\n", - __func__); + dev_err(dev, "%s - out of memory\n", __func__); return -ENOMEM; } start_address = get_descriptor_addr(serial, I2C_DESC_TYPE_ION, rom_desc); if (!start_address) { - dbg("%s - Edge Descriptor not found in I2C", __func__); + dev_dbg(dev, "%s - Edge Descriptor not found in I2C\n", __func__); status = -ENODEV; goto exit; } @@ -804,12 +799,12 @@ static int get_manuf_info(struct edgeport_serial *serial, __u8 *buffer) status = valid_csum(rom_desc, buffer); desc = (struct edge_ti_manuf_descriptor *)buffer; - dbg("%s - IonConfig 0x%x", __func__, desc->IonConfig); - dbg("%s - Version %d", __func__, desc->Version); - dbg("%s - Cpu/Board 0x%x", __func__, desc->CpuRev_BoardRev); - dbg("%s - NumPorts %d", __func__, desc->NumPorts); - dbg("%s - NumVirtualPorts %d", __func__, desc->NumVirtualPorts); - dbg("%s - TotalPorts %d", __func__, desc->TotalPorts); + dev_dbg(dev, "%s - IonConfig 0x%x\n", __func__, desc->IonConfig); + dev_dbg(dev, "%s - Version %d\n", __func__, desc->Version); + dev_dbg(dev, "%s - Cpu/Board 0x%x\n", __func__, desc->CpuRev_BoardRev); + dev_dbg(dev, "%s - NumPorts %d\n", __func__, desc->NumPorts); + dev_dbg(dev, "%s - NumVirtualPorts %d\n", __func__, desc->NumVirtualPorts); + dev_dbg(dev, "%s - TotalPorts %d\n", __func__, desc->TotalPorts); exit: kfree(rom_desc); @@ -903,13 +898,13 @@ static int build_i2c_fw_hdr(__u8 *header, struct device *dev) /* Try to figure out what type of I2c we have */ static int i2c_type_bootmode(struct edgeport_serial *serial) { + struct device *dev = &serial->serial->dev->dev; int status; u8 *data; data = kmalloc(1, GFP_KERNEL); if (!data) { - dev_err(&serial->serial->dev->dev, - "%s - out of memory\n", __func__); + dev_err(dev, "%s - out of memory\n", __func__); return -ENOMEM; } @@ -917,11 +912,11 @@ static int i2c_type_bootmode(struct edgeport_serial *serial) status = ti_vread_sync(serial->serial->dev, UMPC_MEMORY_READ, DTK_ADDR_SPACE_I2C_TYPE_II, 0, data, 0x01); if (status) - dbg("%s - read 2 status error = %d", __func__, status); + dev_dbg(dev, "%s - read 2 status error = %d\n", __func__, status); else - dbg("%s - read 2 data = 0x%x", __func__, *data); + dev_dbg(dev, "%s - read 2 data = 0x%x\n", __func__, *data); if ((!status) && (*data == UMP5152 || *data == UMP3410)) { - dbg("%s - ROM_TYPE_II", __func__); + dev_dbg(dev, "%s - ROM_TYPE_II\n", __func__); serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II; goto out; } @@ -930,16 +925,16 @@ static int i2c_type_bootmode(struct edgeport_serial *serial) status = ti_vread_sync(serial->serial->dev, UMPC_MEMORY_READ, DTK_ADDR_SPACE_I2C_TYPE_III, 0, data, 0x01); if (status) - dbg("%s - read 3 status error = %d", __func__, status); + dev_dbg(dev, "%s - read 3 status error = %d\n", __func__, status); else - dbg("%s - read 2 data = 0x%x", __func__, *data); + dev_dbg(dev, "%s - read 2 data = 0x%x\n", __func__, *data); if ((!status) && (*data == UMP5152 || *data == UMP3410)) { - dbg("%s - ROM_TYPE_III", __func__); + dev_dbg(dev, "%s - ROM_TYPE_III\n", __func__); serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_III; goto out; } - dbg("%s - Unknown", __func__); + dev_dbg(dev, "%s - Unknown\n", __func__); serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II; status = -ENODEV; out: @@ -1050,11 +1045,11 @@ static int download_fw(struct edgeport_serial *serial) if (serial->product_info.TiMode == TI_MODE_DOWNLOAD) { struct ti_i2c_desc *rom_desc; - dbg("%s - RUNNING IN DOWNLOAD MODE", __func__); + dev_dbg(dev, "%s - RUNNING IN DOWNLOAD MODE\n", __func__); status = check_i2c_image(serial); if (status) { - dbg("%s - DOWNLOAD MODE -- BAD I2C", __func__); + dev_dbg(dev, "%s - DOWNLOAD MODE -- BAD I2C\n", __func__); return status; } @@ -1074,7 +1069,7 @@ static int download_fw(struct edgeport_serial *serial) /* Check version number of ION descriptor */ if (!ignore_cpu_rev && ti_cpu_rev(ti_manuf_desc) < 2) { - dbg("%s - Wrong CPU Rev %d (Must be 2)", + dev_dbg(dev, "%s - Wrong CPU Rev %d (Must be 2)\n", __func__, ti_cpu_rev(ti_manuf_desc)); kfree(ti_manuf_desc); return -EINVAL; @@ -1094,8 +1089,7 @@ static int download_fw(struct edgeport_serial *serial) struct ti_i2c_firmware_rec *firmware_version; u8 *record; - dbg("%s - Found Type FIRMWARE (Type 2) record", - __func__); + dev_dbg(dev, "%s - Found Type FIRMWARE (Type 2) record\n", __func__); firmware_version = kmalloc(sizeof(*firmware_version), GFP_KERNEL); @@ -1127,22 +1121,21 @@ static int download_fw(struct edgeport_serial *serial) download_new_ver = (OperationalMajorVersion << 8) + (OperationalMinorVersion); - dbg("%s - >> FW Versions Device %d.%d Driver %d.%d", - __func__, - firmware_version->Ver_Major, - firmware_version->Ver_Minor, - OperationalMajorVersion, - OperationalMinorVersion); + dev_dbg(dev, "%s - >> FW Versions Device %d.%d Driver %d.%d\n", + __func__, firmware_version->Ver_Major, + firmware_version->Ver_Minor, + OperationalMajorVersion, + OperationalMinorVersion); /* Check if we have an old version in the I2C and update if necessary */ if (download_cur_ver < download_new_ver) { - dbg("%s - Update I2C dld from %d.%d to %d.%d", - __func__, - firmware_version->Ver_Major, - firmware_version->Ver_Minor, - OperationalMajorVersion, - OperationalMinorVersion); + dev_dbg(dev, "%s - Update I2C dld from %d.%d to %d.%d\n", + __func__, + firmware_version->Ver_Major, + firmware_version->Ver_Minor, + OperationalMajorVersion, + OperationalMinorVersion); record = kmalloc(1, GFP_KERNEL); if (!record) { @@ -1196,9 +1189,7 @@ static int download_fw(struct edgeport_serial *serial) } if (*record != I2C_DESC_TYPE_FIRMWARE_BLANK) { - dev_err(dev, - "%s - error resetting device\n", - __func__); + dev_err(dev, "%s - error resetting device\n", __func__); kfree(record); kfree(firmware_version); kfree(rom_desc); @@ -1206,15 +1197,14 @@ static int download_fw(struct edgeport_serial *serial) return -ENODEV; } - dbg("%s - HARDWARE RESET", __func__); + dev_dbg(dev, "%s - HARDWARE RESET\n", __func__); /* Reset UMP -- Back to BOOT MODE */ status = ti_vsend_sync(serial->serial->dev, UMPC_HARDWARE_RESET, 0, 0, NULL, 0); - dbg("%s - HARDWARE RESET return %d", - __func__, status); + dev_dbg(dev, "%s - HARDWARE RESET return %d\n", __func__, status); /* return an error on purpose. */ kfree(record); @@ -1249,8 +1239,7 @@ static int download_fw(struct edgeport_serial *serial) return -ENOMEM; } - dbg("%s - Found Type BLANK FIRMWARE (Type F2) record", - __func__); + dev_dbg(dev, "%s - Found Type BLANK FIRMWARE (Type F2) record\n", __func__); /* * In order to update the I2C firmware we must change @@ -1292,7 +1281,7 @@ static int download_fw(struct edgeport_serial *serial) HEADER_SIZE, vheader); if (status) { - dbg("%s - can't read header back", __func__); + dev_dbg(dev, "%s - can't read header back\n", __func__); kfree(vheader); kfree(header); kfree(rom_desc); @@ -1300,8 +1289,7 @@ static int download_fw(struct edgeport_serial *serial) return status; } if (memcmp(vheader, header, HEADER_SIZE)) { - dbg("%s - write download record failed", - __func__); + dev_dbg(dev, "%s - write download record failed\n", __func__); kfree(vheader); kfree(header); kfree(rom_desc); @@ -1312,13 +1300,13 @@ static int download_fw(struct edgeport_serial *serial) kfree(vheader); kfree(header); - dbg("%s - Start firmware update", __func__); + dev_dbg(dev, "%s - Start firmware update\n", __func__); /* Tell firmware to copy download image into I2C */ status = ti_vsend_sync(serial->serial->dev, UMPC_COPY_DNLD_TO_I2C, 0, 0, NULL, 0); - dbg("%s - Update complete 0x%x", __func__, status); + dev_dbg(dev, "%s - Update complete 0x%x\n", __func__, status); if (status) { dev_err(dev, "%s - UMPC_COPY_DNLD_TO_I2C failed\n", @@ -1338,7 +1326,7 @@ static int download_fw(struct edgeport_serial *serial) /********************************************************************/ /* Boot Mode */ /********************************************************************/ - dbg("%s - RUNNING IN BOOT MODE", __func__); + dev_dbg(dev, "%s - RUNNING IN BOOT MODE\n", __func__); /* Configure the TI device so we can use the BULK pipes for download */ status = config_boot_dev(serial->serial->dev); @@ -1347,8 +1335,8 @@ static int download_fw(struct edgeport_serial *serial) if (le16_to_cpu(serial->serial->dev->descriptor.idVendor) != USB_VENDOR_ID_ION) { - dbg("%s - VID = 0x%x", __func__, - le16_to_cpu(serial->serial->dev->descriptor.idVendor)); + dev_dbg(dev, "%s - VID = 0x%x\n", __func__, + le16_to_cpu(serial->serial->dev->descriptor.idVendor)); serial->TI_I2C_Type = DTK_ADDR_SPACE_I2C_TYPE_II; goto stayinbootmode; } @@ -1385,8 +1373,8 @@ static int download_fw(struct edgeport_serial *serial) /* Check for version 2 */ if (!ignore_cpu_rev && ti_cpu_rev(ti_manuf_desc) < 2) { - dbg("%s - Wrong CPU Rev %d (Must be 2)", - __func__, ti_cpu_rev(ti_manuf_desc)); + dev_dbg(dev, "%s - Wrong CPU Rev %d (Must be 2)\n", + __func__, ti_cpu_rev(ti_manuf_desc)); kfree(ti_manuf_desc); goto stayinbootmode; } @@ -1442,23 +1430,20 @@ static int download_fw(struct edgeport_serial *serial) header->CheckSum = cs; /* Download the operational code */ - dbg("%s - Downloading operational code image (TI UMP)", - __func__); + dev_dbg(dev, "%s - Downloading operational code image (TI UMP)\n", __func__); status = download_code(serial, buffer, buffer_size); kfree(buffer); if (status) { - dbg("%s - Error downloading operational code image", - __func__); + dev_dbg(dev, "%s - Error downloading operational code image\n", __func__); return status; } /* Device will reboot */ serial->product_info.TiMode = TI_MODE_TRANSITIONING; - dbg("%s - Download successful -- Device rebooting...", - __func__); + dev_dbg(dev, "%s - Download successful -- Device rebooting...\n", __func__); /* return an error on purpose */ return -ENODEV; @@ -1466,7 +1451,7 @@ static int download_fw(struct edgeport_serial *serial) stayinbootmode: /* Eprom is invalid or blank stay in boot mode */ - dbg("%s - STAYING IN BOOT MODE", __func__); + dev_dbg(dev, "%s - STAYING IN BOOT MODE\n", __func__); serial->product_info.TiMode = TI_MODE_BOOT; return 0; @@ -1487,7 +1472,7 @@ static int restore_mcr(struct edgeport_port *port, __u8 mcr) { int status = 0; - dbg("%s - %x", __func__, mcr); + dev_dbg(&port->port->dev, "%s - %x\n", __func__, mcr); status = ti_do_config(port, UMPC_SET_CLR_DTR, mcr & MCR_DTR); if (status) @@ -1524,7 +1509,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr) struct async_icount *icount; struct tty_struct *tty; - dbg("%s - %02x", __func__, msr); + dev_dbg(&edge_port->port->dev, "%s - %02x\n", __func__, msr); if (msr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) { @@ -1566,7 +1551,7 @@ static void handle_new_lsr(struct edgeport_port *edge_port, int lsr_data, LSR_FRM_ERR | LSR_BREAK)); struct tty_struct *tty; - dbg("%s - %02x", __func__, new_lsr); + dev_dbg(&edge_port->port->dev, "%s - %02x\n", __func__, new_lsr); edge_port->shadow_lsr = lsr; @@ -1604,6 +1589,7 @@ static void edge_interrupt_callback(struct urb *urb) struct edgeport_serial *edge_serial = urb->context; struct usb_serial_port *port; struct edgeport_port *edge_port; + struct device *dev; unsigned char *data = urb->transfer_buffer; int length = urb->actual_length; int port_number; @@ -1613,8 +1599,6 @@ static void edge_interrupt_callback(struct urb *urb) __u8 msr; int status = urb->status; - dbg("%s", __func__); - switch (status) { case 0: /* success */ @@ -1623,7 +1607,7 @@ static void edge_interrupt_callback(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", + dev_dbg(&urb->dev->dev, "%s - urb shutting down with status: %d\n", __func__, status); return; default: @@ -1633,27 +1617,26 @@ static void edge_interrupt_callback(struct urb *urb) } if (!length) { - dbg("%s - no data in urb", __func__); + dev_dbg(&urb->dev->dev, "%s - no data in urb\n", __func__); goto exit; } - usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, - __func__, length, data); + dev = &edge_serial->serial->dev->dev; + usb_serial_debug_data(debug, dev, __func__, length, data); if (length != 2) { - dbg("%s - expecting packet of size 2, got %d", - __func__, length); + dev_dbg(dev, "%s - expecting packet of size 2, got %d\n", __func__, length); goto exit; } port_number = TIUMP_GET_PORT_FROM_CODE(data[0]); function = TIUMP_GET_FUNC_FROM_CODE(data[0]); - dbg("%s - port_number %d, function %d, info 0x%x", - __func__, port_number, function, data[1]); + dev_dbg(dev, "%s - port_number %d, function %d, info 0x%x\n", __func__, + port_number, function, data[1]); port = edge_serial->serial->port[port_number]; edge_port = usb_get_serial_port_data(port); if (!edge_port) { - dbg("%s - edge_port not found", __func__); + dev_dbg(dev, "%s - edge_port not found\n", __func__); return; } switch (function) { @@ -1662,13 +1645,13 @@ static void edge_interrupt_callback(struct urb *urb) if (lsr & UMP_UART_LSR_DATA_MASK) { /* Save the LSR event for bulk read completion routine */ - dbg("%s - LSR Event Port %u LSR Status = %02x", - __func__, port_number, lsr); + dev_dbg(dev, "%s - LSR Event Port %u LSR Status = %02x\n", + __func__, port_number, lsr); edge_port->lsr_event = 1; edge_port->lsr_mask = lsr; } else { - dbg("%s - ===== Port %d LSR Status = %02x ======", - __func__, port_number, lsr); + dev_dbg(dev, "%s - ===== Port %d LSR Status = %02x ======\n", + __func__, port_number, lsr); handle_new_lsr(edge_port, 0, lsr, 0); } break; @@ -1676,8 +1659,8 @@ static void edge_interrupt_callback(struct urb *urb) case TIUMP_INTERRUPT_CODE_MSR: /* MSR */ /* Copy MSR from UMP */ msr = data[1]; - dbg("%s - ===== Port %u MSR Status = %02x ======", - __func__, port_number, msr); + dev_dbg(dev, "%s - ===== Port %u MSR Status = %02x ======\n", + __func__, port_number, msr); handle_new_msr(edge_port, msr); break; @@ -1700,14 +1683,13 @@ exit: static void edge_bulk_in_callback(struct urb *urb) { struct edgeport_port *edge_port = urb->context; + struct device *dev = &edge_port->port->dev; unsigned char *data = urb->transfer_buffer; struct tty_struct *tty; int retval = 0; int port_number; int status = urb->status; - dbg("%s", __func__); - switch (status) { case 0: /* success */ @@ -1716,13 +1698,10 @@ static void edge_bulk_in_callback(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", - __func__, status); + dev_dbg(&urb->dev->dev, "%s - urb shutting down with status: %d\n", __func__, status); return; default: - dev_err(&urb->dev->dev, - "%s - nonzero read bulk status received: %d\n", - __func__, status); + dev_err(&urb->dev->dev, "%s - nonzero read bulk status received: %d\n", __func__, status); } if (status == -EPIPE) @@ -1737,8 +1716,8 @@ static void edge_bulk_in_callback(struct urb *urb) if (edge_port->lsr_event) { edge_port->lsr_event = 0; - dbg("%s ===== Port %u LSR Status = %02x, Data = %02x ======", - __func__, port_number, edge_port->lsr_mask, *data); + dev_dbg(dev, "%s ===== Port %u LSR Status = %02x, Data = %02x ======\n", + __func__, port_number, edge_port->lsr_mask, *data); handle_new_lsr(edge_port, 1, edge_port->lsr_mask, *data); /* Adjust buffer length/pointer */ --urb->actual_length; @@ -1747,14 +1726,12 @@ static void edge_bulk_in_callback(struct urb *urb) tty = tty_port_tty_get(&edge_port->port->port); if (tty && urb->actual_length) { - usb_serial_debug_data(debug, &edge_port->port->dev, - __func__, urb->actual_length, data); + usb_serial_debug_data(debug, dev, __func__, urb->actual_length, data); if (edge_port->close_pending) - dbg("%s - close pending, dropping data on the floor", + dev_dbg(dev, "%s - close pending, dropping data on the floor\n", __func__); else - edge_tty_recv(&edge_port->port->dev, tty, data, - urb->actual_length); + edge_tty_recv(dev, tty, data, urb->actual_length); edge_port->icount.rx += urb->actual_length; } tty_kref_put(tty); @@ -1769,9 +1746,7 @@ exit: spin_unlock(&edge_port->ep_lock); if (retval) - dev_err(&urb->dev->dev, - "%s - usb_submit_urb failed with result %d\n", - __func__, retval); + dev_err(dev, "%s - usb_submit_urb failed with result %d\n", __func__, retval); } static void edge_tty_recv(struct device *dev, struct tty_struct *tty, @@ -1793,8 +1768,6 @@ static void edge_bulk_out_callback(struct urb *urb) int status = urb->status; struct tty_struct *tty; - dbg("%s - port %d", __func__, port->number); - edge_port->ep_write_urb_in_use = 0; switch (status) { @@ -1805,7 +1778,7 @@ static void edge_bulk_out_callback(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", + dev_dbg(&urb->dev->dev, "%s - urb shutting down with status: %d\n", __func__, status); return; default: @@ -1830,8 +1803,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) u16 open_settings; u8 transaction_timeout; - dbg("%s - port %d", __func__, port->number); - if (edge_port == NULL) return -ENODEV; @@ -1850,9 +1821,8 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) return -ENODEV; } - dbg("%s - port_number = %d, uart_base = %04x, dma_address = %04x", - __func__, port_number, edge_port->uart_base, - edge_port->dma_address); + dev_dbg(&port->dev, "%s - port_number = %d, uart_base = %04x, dma_address = %04x\n", + __func__, port_number, edge_port->uart_base, edge_port->dma_address); dev = port->serial->dev; @@ -1885,7 +1855,7 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) UMP_PIPE_TRANS_TIMEOUT_ENA | (transaction_timeout << 2)); - dbg("%s - Sending UMPC_OPEN_PORT", __func__); + dev_dbg(&port->dev, "%s - Sending UMPC_OPEN_PORT\n", __func__); /* Tell TI to open and start the port */ status = send_cmd(dev, UMPC_OPEN_PORT, @@ -1924,11 +1894,11 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) return status; } - dbg("ShadowMSR 0x%X", edge_port->shadow_msr); + dev_dbg(&port->dev, "ShadowMSR 0x%X\n", edge_port->shadow_msr); /* Set Initial MCR */ edge_port->shadow_mcr = MCR_RTS | MCR_DTR; - dbg("ShadowMCR 0x%X", edge_port->shadow_mcr); + dev_dbg(&port->dev, "ShadowMCR 0x%X\n", edge_port->shadow_mcr); edge_serial = edge_port->edge_serial; if (mutex_lock_interruptible(&edge_serial->es_lock)) @@ -1980,8 +1950,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) ++edge_serial->num_ports_open; - dbg("%s - exited", __func__); - goto release_es_lock; unlink_int_urb: @@ -1999,8 +1967,6 @@ static void edge_close(struct usb_serial_port *port) struct usb_serial *serial = port->serial; int port_number; - dbg("%s - port %d", __func__, port->number); - edge_serial = usb_get_serial_data(port->serial); edge_port = usb_get_serial_port_data(port); if (edge_serial == NULL || edge_port == NULL) @@ -2019,7 +1985,7 @@ static void edge_close(struct usb_serial_port *port) /* assuming we can still talk to the device, * send a close port command to it */ - dbg("%s - send umpc_close_port", __func__); + dev_dbg(&port->dev, "%s - send umpc_close_port\n", __func__); port_number = port->number - port->serial->minor; mutex_lock(&serial->disc_mutex); @@ -2042,8 +2008,6 @@ static void edge_close(struct usb_serial_port *port) } mutex_unlock(&edge_serial->es_lock); edge_port->close_pending = 0; - - dbg("%s - exited", __func__); } static int edge_write(struct tty_struct *tty, struct usb_serial_port *port, @@ -2051,10 +2015,8 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port, { struct edgeport_port *edge_port = usb_get_serial_port_data(port); - dbg("%s - port %d", __func__, port->number); - if (count == 0) { - dbg("%s - write request of 0 bytes", __func__); + dev_dbg(&port->dev, "%s - write request of 0 bytes\n", __func__); return 0; } @@ -2077,9 +2039,6 @@ static void edge_send(struct tty_struct *tty) struct edgeport_port *edge_port = usb_get_serial_port_data(port); unsigned long flags; - - dbg("%s - port %d", __func__, port->number); - spin_lock_irqsave(&edge_port->ep_lock, flags); if (edge_port->ep_write_urb_in_use) { @@ -2130,8 +2089,6 @@ static int edge_write_room(struct tty_struct *tty) int room = 0; unsigned long flags; - dbg("%s - port %d", __func__, port->number); - if (edge_port == NULL) return 0; if (edge_port->close_pending == 1) @@ -2141,7 +2098,7 @@ static int edge_write_room(struct tty_struct *tty) room = kfifo_avail(&edge_port->write_fifo); spin_unlock_irqrestore(&edge_port->ep_lock, flags); - dbg("%s - returns %d", __func__, room); + dev_dbg(&port->dev, "%s - returns %d\n", __func__, room); return room; } @@ -2152,8 +2109,6 @@ static int edge_chars_in_buffer(struct tty_struct *tty) int chars = 0; unsigned long flags; - dbg("%s - port %d", __func__, port->number); - if (edge_port == NULL) return 0; if (edge_port->close_pending == 1) @@ -2163,7 +2118,7 @@ static int edge_chars_in_buffer(struct tty_struct *tty) chars = kfifo_len(&edge_port->write_fifo); spin_unlock_irqrestore(&edge_port->ep_lock, flags); - dbg("%s - returns %d", __func__, chars); + dev_dbg(&port->dev, "%s - returns %d\n", __func__, chars); return chars; } @@ -2173,8 +2128,6 @@ static void edge_throttle(struct tty_struct *tty) struct edgeport_port *edge_port = usb_get_serial_port_data(port); int status; - dbg("%s - port %d", __func__, port->number); - if (edge_port == NULL) return; @@ -2200,8 +2153,6 @@ static void edge_unthrottle(struct tty_struct *tty) struct edgeport_port *edge_port = usb_get_serial_port_data(port); int status; - dbg("%s - port %d", __func__, port->number); - if (edge_port == NULL) return; @@ -2261,6 +2212,7 @@ static int restart_read(struct edgeport_port *edge_port) static void change_port_settings(struct tty_struct *tty, struct edgeport_port *edge_port, struct ktermios *old_termios) { + struct device *dev = &edge_port->port->dev; struct ump_uart_config *config; int baud; unsigned cflag; @@ -2268,13 +2220,12 @@ static void change_port_settings(struct tty_struct *tty, int port_number = edge_port->port->number - edge_port->port->serial->minor; - dbg("%s - port %d", __func__, edge_port->port->number); + dev_dbg(dev, "%s - port %d\n", __func__, edge_port->port->number); config = kmalloc (sizeof (*config), GFP_KERNEL); if (!config) { *tty->termios = *old_termios; - dev_err(&edge_port->port->dev, "%s - out of memory\n", - __func__); + dev_err(dev, "%s - out of memory\n", __func__); return; } @@ -2290,20 +2241,20 @@ static void change_port_settings(struct tty_struct *tty, switch (cflag & CSIZE) { case CS5: config->bDataBits = UMP_UART_CHAR5BITS; - dbg("%s - data bits = 5", __func__); + dev_dbg(dev, "%s - data bits = 5\n", __func__); break; case CS6: config->bDataBits = UMP_UART_CHAR6BITS; - dbg("%s - data bits = 6", __func__); + dev_dbg(dev, "%s - data bits = 6\n", __func__); break; case CS7: config->bDataBits = UMP_UART_CHAR7BITS; - dbg("%s - data bits = 7", __func__); + dev_dbg(dev, "%s - data bits = 7\n", __func__); break; default: case CS8: config->bDataBits = UMP_UART_CHAR8BITS; - dbg("%s - data bits = 8", __func__); + dev_dbg(dev, "%s - data bits = 8\n", __func__); break; } @@ -2311,32 +2262,32 @@ static void change_port_settings(struct tty_struct *tty, if (cflag & PARODD) { config->wFlags |= UMP_MASK_UART_FLAGS_PARITY; config->bParity = UMP_UART_ODDPARITY; - dbg("%s - parity = odd", __func__); + dev_dbg(dev, "%s - parity = odd\n", __func__); } else { config->wFlags |= UMP_MASK_UART_FLAGS_PARITY; config->bParity = UMP_UART_EVENPARITY; - dbg("%s - parity = even", __func__); + dev_dbg(dev, "%s - parity = even\n", __func__); } } else { config->bParity = UMP_UART_NOPARITY; - dbg("%s - parity = none", __func__); + dev_dbg(dev, "%s - parity = none\n", __func__); } if (cflag & CSTOPB) { config->bStopBits = UMP_UART_STOPBIT2; - dbg("%s - stop bits = 2", __func__); + dev_dbg(dev, "%s - stop bits = 2\n", __func__); } else { config->bStopBits = UMP_UART_STOPBIT1; - dbg("%s - stop bits = 1", __func__); + dev_dbg(dev, "%s - stop bits = 1\n", __func__); } /* figure out the flow control settings */ if (cflag & CRTSCTS) { config->wFlags |= UMP_MASK_UART_FLAGS_OUT_X_CTS_FLOW; config->wFlags |= UMP_MASK_UART_FLAGS_RTS_FLOW; - dbg("%s - RTS/CTS is enabled", __func__); + dev_dbg(dev, "%s - RTS/CTS is enabled\n", __func__); } else { - dbg("%s - RTS/CTS is disabled", __func__); + dev_dbg(dev, "%s - RTS/CTS is disabled\n", __func__); tty->hw_stopped = 0; restart_read(edge_port); } @@ -2349,18 +2300,18 @@ static void change_port_settings(struct tty_struct *tty, /* if we are implementing INBOUND XON/XOFF */ if (I_IXOFF(tty)) { config->wFlags |= UMP_MASK_UART_FLAGS_IN_X; - dbg("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", - __func__, config->cXon, config->cXoff); + dev_dbg(dev, "%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x\n", + __func__, config->cXon, config->cXoff); } else - dbg("%s - INBOUND XON/XOFF is disabled", __func__); + dev_dbg(dev, "%s - INBOUND XON/XOFF is disabled\n", __func__); /* if we are implementing OUTBOUND XON/XOFF */ if (I_IXON(tty)) { config->wFlags |= UMP_MASK_UART_FLAGS_OUT_X; - dbg("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", - __func__, config->cXon, config->cXoff); + dev_dbg(dev, "%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x\n", + __func__, config->cXon, config->cXoff); } else - dbg("%s - OUTBOUND XON/XOFF is disabled", __func__); + dev_dbg(dev, "%s - OUTBOUND XON/XOFF is disabled\n", __func__); tty->termios->c_cflag &= ~CMSPAR; @@ -2377,17 +2328,16 @@ static void change_port_settings(struct tty_struct *tty, /* FIXME: Recompute actual baud from divisor here */ - dbg("%s - baud rate = %d, wBaudRate = %d", __func__, baud, - config->wBaudRate); + dev_dbg(dev, "%s - baud rate = %d, wBaudRate = %d\n", __func__, baud, config->wBaudRate); - dbg("wBaudRate: %d", (int)(461550L / config->wBaudRate)); - dbg("wFlags: 0x%x", config->wFlags); - dbg("bDataBits: %d", config->bDataBits); - dbg("bParity: %d", config->bParity); - dbg("bStopBits: %d", config->bStopBits); - dbg("cXon: %d", config->cXon); - dbg("cXoff: %d", config->cXoff); - dbg("bUartMode: %d", config->bUartMode); + dev_dbg(dev, "wBaudRate: %d\n", (int)(461550L / config->wBaudRate)); + dev_dbg(dev, "wFlags: 0x%x\n", config->wFlags); + dev_dbg(dev, "bDataBits: %d\n", config->bDataBits); + dev_dbg(dev, "bParity: %d\n", config->bParity); + dev_dbg(dev, "bStopBits: %d\n", config->bStopBits); + dev_dbg(dev, "cXon: %d\n", config->cXon); + dev_dbg(dev, "cXoff: %d\n", config->cXoff); + dev_dbg(dev, "bUartMode: %d\n", config->bUartMode); /* move the word values into big endian mode */ cpu_to_be16s(&config->wFlags); @@ -2397,8 +2347,8 @@ static void change_port_settings(struct tty_struct *tty, (__u8)(UMPM_UART1_PORT + port_number), 0, (__u8 *)config, sizeof(*config)); if (status) - dbg("%s - error %d when trying to write config to device", - __func__, status); + dev_dbg(dev, "%s - error %d when trying to write config to device\n", + __func__, status); kfree(config); } @@ -2410,11 +2360,11 @@ static void edge_set_termios(struct tty_struct *tty, cflag = tty->termios->c_cflag; - dbg("%s - clfag %08x iflag %08x", __func__, - tty->termios->c_cflag, tty->termios->c_iflag); - dbg("%s - old clfag %08x old iflag %08x", __func__, - old_termios->c_cflag, old_termios->c_iflag); - dbg("%s - port %d", __func__, port->number); + dev_dbg(&port->dev, "%s - clfag %08x iflag %08x\n", __func__, + tty->termios->c_cflag, tty->termios->c_iflag); + dev_dbg(&port->dev, "%s - old clfag %08x old iflag %08x\n", __func__, + old_termios->c_cflag, old_termios->c_iflag); + dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number); if (edge_port == NULL) return; @@ -2430,8 +2380,6 @@ static int edge_tiocmset(struct tty_struct *tty, unsigned int mcr; unsigned long flags; - dbg("%s - port %d", __func__, port->number); - spin_lock_irqsave(&edge_port->ep_lock, flags); mcr = edge_port->shadow_mcr; if (set & TIOCM_RTS) @@ -2464,8 +2412,6 @@ static int edge_tiocmget(struct tty_struct *tty) unsigned int mcr; unsigned long flags; - dbg("%s - port %d", __func__, port->number); - spin_lock_irqsave(&edge_port->ep_lock, flags); msr = edge_port->shadow_msr; @@ -2478,7 +2424,7 @@ static int edge_tiocmget(struct tty_struct *tty) | ((msr & EDGEPORT_MSR_DSR) ? TIOCM_DSR: 0); /* 0x100 */ - dbg("%s -- %x", __func__, result); + dev_dbg(&port->dev, "%s -- %x\n", __func__, result); spin_unlock_irqrestore(&edge_port->ep_lock, flags); return result; @@ -2538,15 +2484,15 @@ static int edge_ioctl(struct tty_struct *tty, struct async_icount cnow; struct async_icount cprev; - dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); + dev_dbg(&port->dev, "%s - port %d, cmd = 0x%x\n", __func__, port->number, cmd); switch (cmd) { case TIOCGSERIAL: - dbg("%s - (%d) TIOCGSERIAL", __func__, port->number); + dev_dbg(&port->dev, "%s - TIOCGSERIAL\n", __func__); return get_serial_info(edge_port, (struct serial_struct __user *) arg); case TIOCMIWAIT: - dbg("%s - (%d) TIOCMIWAIT", __func__, port->number); + dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__); cprev = edge_port->icount; while (1) { interruptible_sleep_on(&edge_port->delta_msr_wait); @@ -2578,8 +2524,6 @@ static void edge_break(struct tty_struct *tty, int break_state) int status; int bv = 0; /* Off */ - dbg("%s - state = %d", __func__, break_state); - /* chase the port close */ chase_port(edge_port, 0, 0); @@ -2587,8 +2531,8 @@ static void edge_break(struct tty_struct *tty, int break_state) bv = 1; /* On */ status = ti_do_config(edge_port, UMPC_SET_CLR_BREAK, bv); if (status) - dbg("%s - error %d sending break set/clear command.", - __func__, status); + dev_dbg(&port->dev, "%s - error %d sending break set/clear command.\n", + __func__, status); } static int edge_startup(struct usb_serial *serial) @@ -2655,7 +2599,6 @@ cleanup: static void edge_disconnect(struct usb_serial *serial) { - dbg("%s", __func__); } static void edge_release(struct usb_serial *serial) @@ -2663,8 +2606,6 @@ static void edge_release(struct usb_serial *serial) int i; struct edgeport_port *edge_port; - dbg("%s", __func__); - for (i = 0; i < serial->num_ports; ++i) { edge_port = usb_get_serial_port_data(serial->port[i]); kfifo_free(&edge_port->write_fifo); @@ -2692,7 +2633,7 @@ static ssize_t store_uart_mode(struct device *dev, struct edgeport_port *edge_port = usb_get_serial_port_data(port); unsigned int v = simple_strtoul(valbuf, NULL, 0); - dbg("%s: setting uart_mode = %d", __func__, v); + dev_dbg(dev, "%s: setting uart_mode = %d\n", __func__, v); if (v < 256) edge_port->bUartMode = v; -- cgit v0.10.2 From ac08de32d2e2b2b56bfe85720ec9e0b06e75350a Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Mon, 17 Sep 2012 11:55:23 +0100 Subject: usb: remove junk from store_remove_id retval is 0, and carefully assigned - and tested as non zero. This is not useful. While we are at it remove some other bogus initialisation in the function Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 445455a..ddd820d 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -125,10 +125,9 @@ store_remove_id(struct device_driver *driver, const char *buf, size_t count) { struct usb_dynid *dynid, *n; struct usb_driver *usb_driver = to_usb_driver(driver); - u32 idVendor = 0; - u32 idProduct = 0; - int fields = 0; - int retval = 0; + u32 idVendor; + u32 idProduct; + int fields; fields = sscanf(buf, "%x %x", &idVendor, &idProduct); if (fields < 2) @@ -141,14 +140,10 @@ store_remove_id(struct device_driver *driver, const char *buf, size_t count) (id->idProduct == idProduct)) { list_del(&dynid->node); kfree(dynid); - retval = 0; break; } } spin_unlock(&usb_driver->dynids.lock); - - if (retval) - return retval; return count; } static DRIVER_ATTR(remove_id, S_IRUGO | S_IWUSR, show_dynids, store_remove_id); -- cgit v0.10.2 From c05fecb1d57e7f4dd3244c7bfaf4374b02728238 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 17 Sep 2012 22:53:32 -0700 Subject: USB: serial: add vizzini driver Here's a driver for the Vizzini USB to serial device. It looks to be copied from cdc-acm, and probably can be cleaned up a lot more. Also, there's some odd "try to grab another interface" that is probably wrong. And, if this really is a cdc-acm device, it probably should just be a quirk of the cdc-acm device, but I can't figure that out, and people have been using this driver for a long time now. So merge it to let people use their hardware and clean it up over time. Driver written by Rob Duncan but cleaned up and forward ported to the latest kernel tree by me. Cc: Rob Duncan Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index f604f70..a5c1446 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -182,6 +182,14 @@ config USB_SERIAL_VISOR To compile this driver as a module, choose M here: the module will be called visor. +config USB_SERIAL_VIZZINI + tristate "USB Vizzini Serial Converter Driver" + help + Say Y here if you have a Vizzini USB to serial device. + + To compile this driver as a module, choose M here: the + module will be called vizzini. + config USB_SERIAL_IPAQ tristate "USB PocketPC PDA Driver" help diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 45871f9..5fd21a0 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -59,6 +59,7 @@ obj-$(CONFIG_USB_SERIAL_SYMBOL) += symbolserial.o obj-$(CONFIG_USB_SERIAL_WWAN) += usb_wwan.o obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o +obj-$(CONFIG_USB_SERIAL_VIZZINI) += vizzini.o obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o obj-$(CONFIG_USB_SERIAL_XIRCOM) += keyspan_pda.o obj-$(CONFIG_USB_SERIAL_VIVOPAY_SERIAL) += vivopay-serial.o diff --git a/drivers/usb/serial/vizzini.c b/drivers/usb/serial/vizzini.c new file mode 100644 index 0000000..2ac48fe --- /dev/null +++ b/drivers/usb/serial/vizzini.c @@ -0,0 +1,1363 @@ +/* + * vizzini.c + * + * Copyright (c) 2011 Exar Corporation, Inc. + * + * ChangeLog: + * v0.76- Support for 3.0.0 (Ubuntu 11.10) (Removed all Kernel source + * compiler conditions and now the base is Kernel 3.0. Ravi Reddy) + * v0.75- Support for 2.6.38.8 (Ubuntu 11.04) - Added + * .usb_driver = &vizzini_driver. + * v0.74- Support for 2.6.35.22 (Ubuntu 10.10) - Added + * #include to fix kmalloc/kfree error. + * v0.73- Fixed VZIOC_SET_REG (by Ravi Reddy). + * v0.72- Support for 2.6.32.21 (by Ravi Reddy, for Ubuntu 10.04). + * v0.71- Support for 2.6.31. + * v0.5 - Tentative support for compiling with the CentOS 5.1 + * kernel (2.6.18-53). + * v0.4 - First version. Lots of stuff lifted from + * cdc-acm.c (credits due to Armin Fuerst, Pavel Machek, + * Johannes Erdfelt, Vojtech Pavlik, David Kubicek) and + * and sierra.c (credit due to Kevin Lloyd). + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* This version of the Linux driver source contains a number of + abominable conditional compilation sections to manage the API + changes between kernel versions 2.6.18, 2.6.25, and the latest + (currently 2.6.27). At some point we'll hand a version of this + driver off to the mainline Linux source tree, and we'll strip all + these sections out. For now it makes it much easier to keep it all + in sync while the driver is being developed. */ + + +#define DRIVER_VERSION "v.0.76" +#define DRIVER_AUTHOR "Rob Duncan " +#define DRIVER_DESC "USB Driver for Vizzini USB serial port" + +#undef VIZZINI_IWA + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#ifndef CDC_DATA_INTERFACE_TYPE +#define CDC_DATA_INTERFACE_TYPE 0x0a +#endif +#ifndef USB_RT_ACM +#define USB_RT_ACM (USB_TYPE_CLASS | USB_RECIP_INTERFACE) +#define ACM_CTRL_DTR 0x01 +#define ACM_CTRL_RTS 0x02 +#define ACM_CTRL_DCD 0x01 +#define ACM_CTRL_DSR 0x02 +#define ACM_CTRL_BRK 0x04 +#define ACM_CTRL_RI 0x08 +#define ACM_CTRL_FRAMING 0x10 +#define ACM_CTRL_PARITY 0x20 +#define ACM_CTRL_OVERRUN 0x40 +#endif + +#define XR_SET_REG 0 +#define XR_GETN_REG 1 + +#define UART_0_REG_BLOCK 0 +#define UART_1_REG_BLOCK 1 +#define UART_2_REG_BLOCK 2 +#define UART_3_REG_BLOCK 3 +#define URM_REG_BLOCK 4 +#define PRM_REG_BLOCK 5 +#define EPMERR_REG_BLOCK 6 +#define RAMCTL_REG_BLOCK 0x64 +#define TWI_ROM_REG_BLOCK 0x65 +#define EPLOCALS_REG_BLOCK 0x66 + +#define MEM_SHADOW_REG_SIZE_S 5 +#define MEM_SHADOW_REG_SIZE (1 << MEM_SHADOW_REG_SIZE_S) + +#define MEM_EP_LOCALS_SIZE_S 3 +#define MEM_EP_LOCALS_SIZE (1 << MEM_EP_LOCALS_SIZE_S) + +#define EP_WIDE_MODE 0x03 + + +#define UART_GPIO_MODE 0x01a + +#define UART_GPIO_MODE_SEL_M 0x7 +#define UART_GPIO_MODE_SEL_S 0 +#define UART_GPIO_MODE_SEL 0x007 + +#define UART_GPIO_MODE_SEL_GPIO (0x0 << UART_GPIO_MODE_SEL_S) +#define UART_GPIO_MODE_SEL_RTS_CTS (0x1 << UART_GPIO_MODE_SEL_S) +#define UART_GPIO_MODE_SEL_DTR_DSR (0x2 << UART_GPIO_MODE_SEL_S) +#define UART_GPIO_MODE_SEL_XCVR_EN_ACT (0x3 << UART_GPIO_MODE_SEL_S) +#define UART_GPIO_MODE_SEL_XCVR_EN_FLOW (0x4 << UART_GPIO_MODE_SEL_S) + +#define UART_GPIO_MODE_XCVR_EN_POL_M 0x1 +#define UART_GPIO_MODE_XCVR_EN_POL_S 3 +#define UART_GPIO_MODE_XCVR_EN_POL 0x008 + +#define UART_ENABLE 0x003 +#define UART_ENABLE_TX_M 0x1 +#define UART_ENABLE_TX_S 0 +#define UART_ENABLE_TX 0x001 +#define UART_ENABLE_RX_M 0x1 +#define UART_ENABLE_RX_S 1 +#define UART_ENABLE_RX 0x002 + +#define UART_CLOCK_DIVISOR_0 0x004 +#define UART_CLOCK_DIVISOR_1 0x005 +#define UART_CLOCK_DIVISOR_2 0x006 + +#define UART_CLOCK_DIVISOR_2_MSB_M 0x7 +#define UART_CLOCK_DIVISOR_2_MSB_S 0 +#define UART_CLOCK_DIVISOR_2_MSB 0x007 +#define UART_CLOCK_DIVISOR_2_DIAGMODE_M 0x1 +#define UART_CLOCK_DIVISOR_2_DIAGMODE_S 3 +#define UART_CLOCK_DIVISOR_2_DIAGMODE 0x008 + +#define UART_TX_CLOCK_MASK_0 0x007 +#define UART_TX_CLOCK_MASK_1 0x008 + +#define UART_RX_CLOCK_MASK_0 0x009 +#define UART_RX_CLOCK_MASK_1 0x00a + +#define UART_FORMAT 0x00b + +#define UART_FORMAT_SIZE_M 0xf +#define UART_FORMAT_SIZE_S 0 +#define UART_FORMAT_SIZE 0x00f + +#define UART_FORMAT_SIZE_7 (0x7 << UART_FORMAT_SIZE_S) +#define UART_FORMAT_SIZE_8 (0x8 << UART_FORMAT_SIZE_S) +#define UART_FORMAT_SIZE_9 (0x9 << UART_FORMAT_SIZE_S) + +#define UART_FORMAT_PARITY_M 0x7 +#define UART_FORMAT_PARITY_S 4 +#define UART_FORMAT_PARITY 0x070 + +#define UART_FORMAT_PARITY_NONE (0x0 << UART_FORMAT_PARITY_S) +#define UART_FORMAT_PARITY_ODD (0x1 << UART_FORMAT_PARITY_S) +#define UART_FORMAT_PARITY_EVEN (0x2 << UART_FORMAT_PARITY_S) +#define UART_FORMAT_PARITY_1 (0x3 << UART_FORMAT_PARITY_S) +#define UART_FORMAT_PARITY_0 (0x4 << UART_FORMAT_PARITY_S) + +#define UART_FORMAT_STOP_M 0x1 +#define UART_FORMAT_STOP_S 7 +#define UART_FORMAT_STOP 0x080 + +#define UART_FORMAT_STOP_1 (0x0 << UART_FORMAT_STOP_S) +#define UART_FORMAT_STOP_2 (0x1 << UART_FORMAT_STOP_S) + +#define UART_FORMAT_MODE_7N1 0 +#define UART_FORMAT_MODE_RES1 1 +#define UART_FORMAT_MODE_RES2 2 +#define UART_FORMAT_MODE_RES3 3 +#define UART_FORMAT_MODE_7N2 4 +#define UART_FORMAT_MODE_7P1 5 +#define UART_FORMAT_MODE_8N1 6 +#define UART_FORMAT_MODE_RES7 7 +#define UART_FORMAT_MODE_7P2 8 +#define UART_FORMAT_MODE_8N2 9 +#define UART_FORMAT_MODE_8P1 10 +#define UART_FORMAT_MODE_9N1 11 +#define UART_FORMAT_MODE_8P2 12 +#define UART_FORMAT_MODE_RESD 13 +#define UART_FORMAT_MODE_RESE 14 +#define UART_FORMAT_MODE_9N2 15 + +#define UART_FLOW 0x00c + +#define UART_FLOW_MODE_M 0x7 +#define UART_FLOW_MODE_S 0 +#define UART_FLOW_MODE 0x007 + +#define UART_FLOW_MODE_NONE (0x0 << UART_FLOW_MODE_S) +#define UART_FLOW_MODE_HW (0x1 << UART_FLOW_MODE_S) +#define UART_FLOW_MODE_SW (0x2 << UART_FLOW_MODE_S) +#define UART_FLOW_MODE_ADDR_MATCH (0x3 << UART_FLOW_MODE_S) +#define UART_FLOW_MODE_ADDR_MATCH_TX (0x4 << UART_FLOW_MODE_S) + +#define UART_FLOW_HALF_DUPLEX_M 0x1 +#define UART_FLOW_HALF_DUPLEX_S 3 +#define UART_FLOW_HALF_DUPLEX 0x008 + +#define UART_LOOPBACK_CTL 0x012 +#define UART_LOOPBACK_CTL_ENABLE_M 0x1 +#define UART_LOOPBACK_CTL_ENABLE_S 2 +#define UART_LOOPBACK_CTL_ENABLE 0x004 +#define UART_LOOPBACK_CTL_RX_SOURCE_M 0x3 +#define UART_LOOPBACK_CTL_RX_SOURCE_S 0 +#define UART_LOOPBACK_CTL_RX_SOURCE 0x003 +#define UART_LOOPBACK_CTL_RX_UART0 (0x0 << UART_LOOPBACK_CTL_RX_SOURCE_S) +#define UART_LOOPBACK_CTL_RX_UART1 (0x1 << UART_LOOPBACK_CTL_RX_SOURCE_S) +#define UART_LOOPBACK_CTL_RX_UART2 (0x2 << UART_LOOPBACK_CTL_RX_SOURCE_S) +#define UART_LOOPBACK_CTL_RX_UART3 (0x3 << UART_LOOPBACK_CTL_RX_SOURCE_S) + +#define UART_CHANNEL_NUM 0x00d + +#define UART_XON_CHAR 0x010 +#define UART_XOFF_CHAR 0x011 + +#define UART_GPIO_SET 0x01d +#define UART_GPIO_CLR 0x01e +#define UART_GPIO_STATUS 0x01f + +#define URM_ENABLE_BASE 0x010 +#define URM_ENABLE_0 0x010 +#define URM_ENABLE_0_TX_M 0x1 +#define URM_ENABLE_0_TX_S 0 +#define URM_ENABLE_0_TX 0x001 +#define URM_ENABLE_0_RX_M 0x1 +#define URM_ENABLE_0_RX_S 1 +#define URM_ENABLE_0_RX 0x002 + +#define URM_RX_FIFO_RESET_0 0x018 +#define URM_RX_FIFO_RESET_1 0x019 +#define URM_RX_FIFO_RESET_2 0x01a +#define URM_RX_FIFO_RESET_3 0x01b +#define URM_TX_FIFO_RESET_0 0x01c +#define URM_TX_FIFO_RESET_1 0x01d +#define URM_TX_FIFO_RESET_2 0x01e +#define URM_TX_FIFO_RESET_3 0x01f + + +#define RAMCTL_REGS_TXFIFO_0_LEVEL 0x000 +#define RAMCTL_REGS_TXFIFO_1_LEVEL 0x001 +#define RAMCTL_REGS_TXFIFO_2_LEVEL 0x002 +#define RAMCTL_REGS_TXFIFO_3_LEVEL 0x003 +#define RAMCTL_REGS_RXFIFO_0_LEVEL 0x004 + +#define RAMCTL_REGS_RXFIFO_0_LEVEL_LEVEL_M 0x7ff +#define RAMCTL_REGS_RXFIFO_0_LEVEL_LEVEL_S 0 +#define RAMCTL_REGS_RXFIFO_0_LEVEL_LEVEL 0x7ff +#define RAMCTL_REGS_RXFIFO_0_LEVEL_STALE_M 0x1 +#define RAMCTL_REGS_RXFIFO_0_LEVEL_STALE_S 11 +#define RAMCTL_REGS_RXFIFO_0_LEVEL_STALE 0x800 + +#define RAMCTL_REGS_RXFIFO_1_LEVEL 0x005 +#define RAMCTL_REGS_RXFIFO_2_LEVEL 0x006 +#define RAMCTL_REGS_RXFIFO_3_LEVEL 0x007 + +#define RAMCTL_BUFFER_PARITY 0x1 +#define RAMCTL_BUFFER_BREAK 0x2 +#define RAMCTL_BUFFER_FRAME 0x4 +#define RAMCTL_BUFFER_OVERRUN 0x8 + +#define N_IN_URB 4 +#define N_OUT_URB 4 +#define IN_BUFLEN 4096 + +static struct usb_device_id id_table[] = { + { USB_DEVICE(0x04e2, 0x1410) }, + { USB_DEVICE(0x04e2, 0x1412) }, + { USB_DEVICE(0x04e2, 0x1414) }, + { } +}; +MODULE_DEVICE_TABLE(usb, id_table); + +struct vizzini_serial_private { + struct usb_interface *data_interface; +}; + +struct vizzini_port_private { + spinlock_t lock; + int outstanding_urbs; + + struct urb *in_urbs[N_IN_URB]; + char *in_buffer[N_IN_URB]; + + int ctrlin; + int ctrlout; + int clocal; + + int block; + int preciseflags; /* USB: wide mode, TTY: flags per character */ + int trans9; /* USB: wide mode, serial 9N1 */ + unsigned int baud_base; /* setserial: used to hack in non-standard baud rates */ + int have_extra_byte; + int extra_byte; + + int bcd_device; + +#ifdef VIZZINI_IWA + int iwa; +#endif +}; + + +static int vizzini_rev_a(struct usb_serial_port *port) +{ + struct vizzini_port_private *portdata = usb_get_serial_port_data(port); + return portdata->bcd_device == 0; +} + +static int acm_ctrl_msg(struct usb_serial_port *port, int request, + int value, void *buf, int len) +{ + struct usb_serial *serial = port->serial; + int retval = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + request, + USB_RT_ACM, + value, + serial->interface->cur_altsetting->desc.bInterfaceNumber, + buf, + len, + 5000); + dev_dbg(&port->dev, "acm_control_msg: rq: 0x%02x val: %#x len: %#x result: %d\n", request, value, len, retval); + return retval < 0 ? retval : 0; +} + +#define acm_set_control(port, control) \ + acm_ctrl_msg(port, USB_CDC_REQ_SET_CONTROL_LINE_STATE, control, NULL, 0) +#define acm_set_line(port, line) \ + acm_ctrl_msg(port, USB_CDC_REQ_SET_LINE_CODING, 0, line, sizeof *(line)) +#define acm_send_break(port, ms) \ + acm_ctrl_msg(port, USB_CDC_REQ_SEND_BREAK, ms, NULL, 0) + +static int vizzini_set_reg(struct usb_serial_port *port, int block, int regnum, int value) +{ + struct usb_serial *serial = port->serial; + int result; + + result = usb_control_msg(serial->dev, /* usb device */ + usb_sndctrlpipe(serial->dev, 0), /* endpoint pipe */ + XR_SET_REG, /* request */ + USB_DIR_OUT | USB_TYPE_VENDOR, /* request_type */ + value, /* request value */ + regnum | (block << 8), /* index */ + NULL, /* data */ + 0, /* size */ + 5000); /* timeout */ + + return result; +} + +static void vizzini_disable(struct usb_serial_port *port) +{ + struct vizzini_port_private *portdata = usb_get_serial_port_data(port); + int block = portdata->block; + + vizzini_set_reg(port, block, UART_ENABLE, 0); + vizzini_set_reg(port, URM_REG_BLOCK, URM_ENABLE_BASE + block, 0); +} + +static void vizzini_enable(struct usb_serial_port *port) +{ + struct vizzini_port_private *portdata = usb_get_serial_port_data(port); + int block = portdata->block; + + vizzini_set_reg(port, URM_REG_BLOCK, URM_ENABLE_BASE + block, URM_ENABLE_0_TX); + vizzini_set_reg(port, block, UART_ENABLE, UART_ENABLE_TX | UART_ENABLE_RX); + vizzini_set_reg(port, URM_REG_BLOCK, URM_ENABLE_BASE + block, URM_ENABLE_0_TX | URM_ENABLE_0_RX); +} + +struct vizzini_baud_rate { + unsigned int tx; + unsigned int rx0; + unsigned int rx1; +}; + +static struct vizzini_baud_rate vizzini_baud_rates[] = { + { 0x000, 0x000, 0x000 }, + { 0x000, 0x000, 0x000 }, + { 0x100, 0x000, 0x100 }, + { 0x020, 0x400, 0x020 }, + { 0x010, 0x100, 0x010 }, + { 0x208, 0x040, 0x208 }, + { 0x104, 0x820, 0x108 }, + { 0x844, 0x210, 0x884 }, + { 0x444, 0x110, 0x444 }, + { 0x122, 0x888, 0x224 }, + { 0x912, 0x448, 0x924 }, + { 0x492, 0x248, 0x492 }, + { 0x252, 0x928, 0x292 }, + { 0X94A, 0X4A4, 0XA52 }, + { 0X52A, 0XAA4, 0X54A }, + { 0XAAA, 0x954, 0X4AA }, + { 0XAAA, 0x554, 0XAAA }, + { 0x555, 0XAD4, 0X5AA }, + { 0XB55, 0XAB4, 0X55A }, + { 0X6B5, 0X5AC, 0XB56 }, + { 0X5B5, 0XD6C, 0X6D6 }, + { 0XB6D, 0XB6A, 0XDB6 }, + { 0X76D, 0X6DA, 0XBB6 }, + { 0XEDD, 0XDDA, 0X76E }, + { 0XDDD, 0XBBA, 0XEEE }, + { 0X7BB, 0XF7A, 0XDDE }, + { 0XF7B, 0XEF6, 0X7DE }, + { 0XDF7, 0XBF6, 0XF7E }, + { 0X7F7, 0XFEE, 0XEFE }, + { 0XFDF, 0XFBE, 0X7FE }, + { 0XF7F, 0XEFE, 0XFFE }, + { 0XFFF, 0XFFE, 0XFFD }, +}; + +static int vizzini_set_baud_rate(struct usb_serial_port *port, unsigned int rate) +{ + struct vizzini_port_private *portdata = usb_get_serial_port_data(port); + int block = portdata->block; + unsigned int divisor = 48000000 / rate; + unsigned int i = ((32 * 48000000) / rate) & 0x1f; + unsigned int tx_mask = vizzini_baud_rates[i].tx; + unsigned int rx_mask = (divisor & 1) ? vizzini_baud_rates[i].rx1 : vizzini_baud_rates[i].rx0; + + dev_dbg(&port->dev, "Setting baud rate to %d: i=%u div=%u tx=%03x rx=%03x\n", rate, i, divisor, tx_mask, rx_mask); + + vizzini_set_reg(port, block, UART_CLOCK_DIVISOR_0, (divisor >> 0) & 0xff); + vizzini_set_reg(port, block, UART_CLOCK_DIVISOR_1, (divisor >> 8) & 0xff); + vizzini_set_reg(port, block, UART_CLOCK_DIVISOR_2, (divisor >> 16) & 0xff); + vizzini_set_reg(port, block, UART_TX_CLOCK_MASK_0, (tx_mask >> 0) & 0xff); + vizzini_set_reg(port, block, UART_TX_CLOCK_MASK_1, (tx_mask >> 8) & 0xff); + vizzini_set_reg(port, block, UART_RX_CLOCK_MASK_0, (rx_mask >> 0) & 0xff); + vizzini_set_reg(port, block, UART_RX_CLOCK_MASK_1, (rx_mask >> 8) & 0xff); + + return -EINVAL; +} + +static void vizzini_set_termios(struct tty_struct *tty_param, + struct usb_serial_port *port, + struct ktermios *old_termios) +{ + struct vizzini_port_private *portdata = usb_get_serial_port_data(port); + unsigned int cflag, block; + speed_t rate; + unsigned int format_size, format_parity, format_stop, flow, gpio_mode; + struct tty_struct *tty = port->port.tty; + + cflag = tty->termios->c_cflag; + + portdata->clocal = ((cflag & CLOCAL) != 0); + + block = portdata->block; + + vizzini_disable(port); + + if ((cflag & CSIZE) == CS7) { + format_size = UART_FORMAT_SIZE_7; + } else if ((cflag & CSIZE) == CS5) { + /* Enabling 5-bit mode is really 9-bit mode! */ + format_size = UART_FORMAT_SIZE_9; + } else { + format_size = UART_FORMAT_SIZE_8; + } + portdata->trans9 = (format_size == UART_FORMAT_SIZE_9); + + if (cflag & PARENB) { + if (cflag & PARODD) { + if (cflag & CMSPAR) + format_parity = UART_FORMAT_PARITY_1; + else + format_parity = UART_FORMAT_PARITY_ODD; + } else { + if (cflag & CMSPAR) + format_parity = UART_FORMAT_PARITY_0; + else + format_parity = UART_FORMAT_PARITY_EVEN; + } + } else { + format_parity = UART_FORMAT_PARITY_NONE; + } + + if (cflag & CSTOPB) + format_stop = UART_FORMAT_STOP_2; + else + format_stop = UART_FORMAT_STOP_1; + +#ifdef VIZZINI_IWA + if (format_size == UART_FORMAT_SIZE_8) { + portdata->iwa = format_parity; + if (portdata->iwa != UART_FORMAT_PARITY_NONE) { + format_size = UART_FORMAT_SIZE_9; + format_parity = UART_FORMAT_PARITY_NONE; + } + } else { + portdata->iwa = UART_FORMAT_PARITY_NONE; + } +#endif + vizzini_set_reg(port, block, UART_FORMAT, format_size | format_parity | format_stop); + + if (cflag & CRTSCTS) { + flow = UART_FLOW_MODE_HW; + gpio_mode = UART_GPIO_MODE_SEL_RTS_CTS; + } else if (I_IXOFF(tty) || I_IXON(tty)) { + unsigned char start_char = START_CHAR(tty); + unsigned char stop_char = STOP_CHAR(tty); + + flow = UART_FLOW_MODE_SW; + gpio_mode = UART_GPIO_MODE_SEL_GPIO; + + vizzini_set_reg(port, block, UART_XON_CHAR, start_char); + vizzini_set_reg(port, block, UART_XOFF_CHAR, stop_char); + } else { + flow = UART_FLOW_MODE_NONE; + gpio_mode = UART_GPIO_MODE_SEL_GPIO; + } + + vizzini_set_reg(port, block, UART_FLOW, flow); + vizzini_set_reg(port, block, UART_GPIO_MODE, gpio_mode); + + if (portdata->trans9) { + /* Turn on wide mode if we're 9-bit transparent. */ + vizzini_set_reg(port, EPLOCALS_REG_BLOCK, (block * MEM_EP_LOCALS_SIZE) + EP_WIDE_MODE, 1); +#ifdef VIZZINI_IWA + } else if (portdata->iwa != UART_FORMAT_PARITY_NONE) { + vizzini_set_reg(port, EPLOCALS_REG_BLOCK, (block * MEM_EP_LOCALS_SIZE) + EP_WIDE_MODE, 1); +#endif + } else if (!portdata->preciseflags) { + /* Turn off wide mode unless we have precise flags. */ + vizzini_set_reg(port, EPLOCALS_REG_BLOCK, (block * MEM_EP_LOCALS_SIZE) + EP_WIDE_MODE, 0); + } + + rate = tty_get_baud_rate(tty); + if (rate) + vizzini_set_baud_rate(port, rate); + + vizzini_enable(port); +} + +static void vizzini_break_ctl(struct tty_struct *tty, int break_state) +{ + struct usb_serial_port *port = tty->driver_data; + + dev_dbg(&port->dev, "BREAK %d\n", break_state); + if (break_state) + acm_send_break(port, 0x10); + else + acm_send_break(port, 0x000); +} + +static int vizzini_tiocmget(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + struct vizzini_port_private *portdata = usb_get_serial_port_data(port); + + return (portdata->ctrlout & ACM_CTRL_DTR ? TIOCM_DTR : 0) | + (portdata->ctrlout & ACM_CTRL_RTS ? TIOCM_RTS : 0) | + (portdata->ctrlin & ACM_CTRL_DSR ? TIOCM_DSR : 0) | + (portdata->ctrlin & ACM_CTRL_RI ? TIOCM_RI : 0) | + (portdata->ctrlin & ACM_CTRL_DCD ? TIOCM_CD : 0) | + TIOCM_CTS; +} + +static int vizzini_tiocmset(struct tty_struct *tty, + unsigned int set, unsigned int clear) +{ + struct usb_serial_port *port = tty->driver_data; + struct vizzini_port_private *portdata = usb_get_serial_port_data(port); + unsigned int newctrl; + + newctrl = portdata->ctrlout; + set = (set & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (set & TIOCM_RTS ? ACM_CTRL_RTS : 0); + clear = (clear & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (clear & TIOCM_RTS ? ACM_CTRL_RTS : 0); + + newctrl = (newctrl & ~clear) | set; + + if (portdata->ctrlout == newctrl) + return 0; + return acm_set_control(port, portdata->ctrlout = newctrl); +} + +static int vizzini_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) +{ + struct usb_serial_port *port = tty->driver_data; + struct vizzini_port_private *portdata = usb_get_serial_port_data(port); + struct serial_struct ss; + + dev_dbg(&port->dev, "%s %08x\n", __func__, cmd); + + switch (cmd) { + case TIOCGSERIAL: + if (!arg) + return -EFAULT; + memset(&ss, 0, sizeof(ss)); + ss.baud_base = portdata->baud_base; + if (copy_to_user((void __user *)arg, &ss, sizeof(ss))) + return -EFAULT; + break; + + case TIOCSSERIAL: + if (!arg) + return -EFAULT; + if (copy_from_user(&ss, (void __user *)arg, sizeof(ss))) + return -EFAULT; + portdata->baud_base = ss.baud_base; + dev_dbg(&port->dev, "baud_base=%d\n", portdata->baud_base); + + vizzini_disable(port); + if (portdata->baud_base) + vizzini_set_baud_rate(port, portdata->baud_base); + vizzini_enable(port); + break; + + default: + return -ENOIOCTLCMD; + } + + return 0; +} + +#ifdef VIZZINI_IWA +static const int vizzini_parity[] = { + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, + 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 +}; +#endif + +static void vizzini_out_callback(struct urb *urb) +{ + struct usb_serial_port *port = urb->context; + struct vizzini_port_private *portdata = usb_get_serial_port_data(port); + int status = urb->status; + unsigned long flags; + + dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number); + + /* free up the transfer buffer, as usb_free_urb() does not do this */ + kfree(urb->transfer_buffer); + + if (status) + dev_dbg(&port->dev, "%s - nonzero write bulk status received: %d\n", __func__, status); + + spin_lock_irqsave(&portdata->lock, flags); + --portdata->outstanding_urbs; + spin_unlock_irqrestore(&portdata->lock, flags); + + usb_serial_port_softint(port); +} + +static int vizzini_write_room(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + struct vizzini_port_private *portdata = usb_get_serial_port_data(port); + unsigned long flags; + + dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number); + + /* try to give a good number back based on if we have any free urbs at + * this point in time */ + spin_lock_irqsave(&portdata->lock, flags); + if (portdata->outstanding_urbs > N_OUT_URB * 2 / 3) { + spin_unlock_irqrestore(&portdata->lock, flags); + dev_dbg(&port->dev, "%s - write limit hit\n", __func__); + return 0; + } + spin_unlock_irqrestore(&portdata->lock, flags); + + return 2048; +} + +static int vizzini_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count) +{ + struct vizzini_port_private *portdata = usb_get_serial_port_data(port); + struct usb_serial *serial = port->serial; + int bufsize = count; + unsigned long flags; + unsigned char *buffer; + struct urb *urb; + int status; + + portdata = usb_get_serial_port_data(port); + + dev_dbg(&port->dev, "%s: write (%d chars)\n", __func__, count); + + spin_lock_irqsave(&portdata->lock, flags); + if (portdata->outstanding_urbs > N_OUT_URB) { + spin_unlock_irqrestore(&portdata->lock, flags); + dev_dbg(&port->dev, "%s - write limit hit\n", __func__); + return 0; + } + portdata->outstanding_urbs++; + spin_unlock_irqrestore(&portdata->lock, flags); + +#ifdef VIZZINI_IWA + if (portdata->iwa != UART_FORMAT_PARITY_NONE) + bufsize = count * 2; +#endif + buffer = kmalloc(bufsize, GFP_ATOMIC); + + if (!buffer) { + dev_err(&port->dev, "out of memory\n"); + count = -ENOMEM; + goto error_no_buffer; + } + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) { + dev_err(&port->dev, "no more free urbs\n"); + count = -ENOMEM; + goto error_no_urb; + } + +#ifdef VIZZINI_IWA + if (portdata->iwa != UART_FORMAT_PARITY_NONE) { + int i; + char *b = buffer; + for (i = 0; i < count; ++i) { + int c, p = 0; + c = buf[i]; + switch (portdata->iwa) { + case UART_FORMAT_PARITY_ODD: + p = !vizzini_parity[c]; + break; + case UART_FORMAT_PARITY_EVEN: + p = vizzini_parity[c]; + break; + case UART_FORMAT_PARITY_1: + p = 1; + break; + case UART_FORMAT_PARITY_0: + p = 0; + break; + } + *b++ = c; + *b++ = p; + } + } else +#endif + memcpy(buffer, buf, count); + + usb_fill_bulk_urb(urb, serial->dev, + usb_sndbulkpipe(serial->dev, + port->bulk_out_endpointAddress), + buffer, bufsize, vizzini_out_callback, port); + + /* send it down the pipe */ + status = usb_submit_urb(urb, GFP_ATOMIC); + if (status) { + dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n", __func__, status); + count = status; + goto error; + } + + /* we are done with this urb, so let the host driver + * really free it when it is finished with it */ + usb_free_urb(urb); + + return count; +error: + usb_free_urb(urb); +error_no_urb: + kfree(buffer); +error_no_buffer: + spin_lock_irqsave(&portdata->lock, flags); + --portdata->outstanding_urbs; + spin_unlock_irqrestore(&portdata->lock, flags); + return count; +} + +static void vizzini_in_callback(struct urb *urb) +{ + int endpoint = usb_pipeendpoint(urb->pipe); + struct usb_serial_port *port = urb->context; + struct vizzini_port_private *portdata = usb_get_serial_port_data(port); + struct tty_struct *tty = port->port.tty; + int preciseflags = portdata->preciseflags; + char *transfer_buffer = urb->transfer_buffer; + int length, room, have_extra_byte; + int err; + + if (urb->status) { + dev_dbg(&port->dev, "%s: nonzero status: %d on endpoint %02x.\n", __func__, urb->status, endpoint); + return; + } + +#ifdef VIZZINI_IWA + if (portdata->iwa != UART_FORMAT_PARITY_NONE) + preciseflags = true; +#endif + + length = urb->actual_length; + if (length == 0) { + dev_dbg(&port->dev, "%s: empty read urb received\n", __func__); + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err) + dev_err(&port->dev, "resubmit read urb failed. (%d)\n", err); + return; + } + + length = length + (portdata->have_extra_byte ? 1 : 0); + have_extra_byte = (preciseflags && (length & 1)); + length = (preciseflags) ? (length / 2) : length; + + room = tty_buffer_request_room(tty, length); + if (room != length) + dev_dbg(&port->dev, "Not enough room in TTY buf, dropped %d chars.\n", length - room); + + if (room) { + if (preciseflags) { + char *dp = transfer_buffer; + int i, ch, ch_flags; + + for (i = 0; i < room; ++i) { + char tty_flag; + + if (i == 0) { + if (portdata->have_extra_byte) + ch = portdata->extra_byte; + else + ch = *dp++; + } else { + ch = *dp++; + } + ch_flags = *dp++; + +#ifdef VIZZINI_IWA + { + int p; + switch (portdata->iwa) { + case UART_FORMAT_PARITY_ODD: + p = !vizzini_parity[ch]; + break; + case UART_FORMAT_PARITY_EVEN: + p = vizzini_parity[ch]; + break; + case UART_FORMAT_PARITY_1: + p = 1; + break; + case UART_FORMAT_PARITY_0: + p = 0; + break; + default: + p = 0; + break; + } + ch_flags ^= p; + } +#endif + if (ch_flags & RAMCTL_BUFFER_PARITY) + tty_flag = TTY_PARITY; + else if (ch_flags & RAMCTL_BUFFER_BREAK) + tty_flag = TTY_BREAK; + else if (ch_flags & RAMCTL_BUFFER_FRAME) + tty_flag = TTY_FRAME; + else if (ch_flags & RAMCTL_BUFFER_OVERRUN) + tty_flag = TTY_OVERRUN; + else + tty_flag = TTY_NORMAL; + + tty_insert_flip_char(tty, ch, tty_flag); + } + } else { + tty_insert_flip_string(tty, transfer_buffer, room); + } + + tty_flip_buffer_push(tty); + } + + portdata->have_extra_byte = have_extra_byte; + if (have_extra_byte) + portdata->extra_byte = transfer_buffer[urb->actual_length - 1]; + + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err) + dev_err(&port->dev, "resubmit read urb failed. (%d)\n", err); +} + +static void vizzini_int_callback(struct urb *urb) +{ + struct usb_serial_port *port = urb->context; + struct vizzini_port_private *portdata = usb_get_serial_port_data(port); + struct tty_struct *tty = port->port.tty; + + struct usb_cdc_notification *dr = urb->transfer_buffer; + unsigned char *data; + int newctrl; + int status; + + switch (urb->status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dev_dbg(&port->dev, "urb shutting down with status: %d\n", urb->status); + return; + default: + dev_dbg(&port->dev, "nonzero urb status received: %d\n", urb->status); + goto exit; + } + + data = (unsigned char *)(dr + 1); + switch (dr->bNotificationType) { + + case USB_CDC_NOTIFY_NETWORK_CONNECTION: + dev_dbg(&port->dev, "%s network\n", dr->wValue ? "connected to" : "disconnected from"); + break; + + case USB_CDC_NOTIFY_SERIAL_STATE: + newctrl = le16_to_cpu(get_unaligned((__le16 *)data)); + + if (!portdata->clocal && (portdata->ctrlin & ~newctrl & ACM_CTRL_DCD)) { + dev_dbg(&port->dev, "calling hangup\n"); + tty_hangup(tty); + } + + portdata->ctrlin = newctrl; + + dev_dbg(&port->dev, "input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c\n", + portdata->ctrlin & ACM_CTRL_DCD ? '+' : '-', + portdata->ctrlin & ACM_CTRL_DSR ? '+' : '-', + portdata->ctrlin & ACM_CTRL_BRK ? '+' : '-', + portdata->ctrlin & ACM_CTRL_RI ? '+' : '-', + portdata->ctrlin & ACM_CTRL_FRAMING ? '+' : '-', + portdata->ctrlin & ACM_CTRL_PARITY ? '+' : '-', + portdata->ctrlin & ACM_CTRL_OVERRUN ? '+' : '-'); + break; + + default: + dev_dbg(&port->dev, "unknown notification %d received: index %d len %d data0 %d data1 %d\n", + dr->bNotificationType, dr->wIndex, + dr->wLength, data[0], data[1]); + break; + } +exit: + dev_dbg(&port->dev, "Resubmitting interrupt IN urb %p\n", urb); + status = usb_submit_urb(urb, GFP_ATOMIC); + if (status) + dev_err(&port->dev, "usb_submit_urb failed with result %d", status); +} + +static int vizzini_open(struct tty_struct *tty_param, struct usb_serial_port *port) +{ + struct vizzini_port_private *portdata; + struct usb_serial *serial = port->serial; + struct tty_struct *tty = port->port.tty; + int i; + struct urb *urb; + int result; + + portdata = usb_get_serial_port_data(port); + + acm_set_control(port, portdata->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS); + + /* Reset low level data toggle and start reading from endpoints */ + for (i = 0; i < N_IN_URB; i++) { + dev_dbg(&port->dev, "%s urb %d\n", __func__, i); + + urb = portdata->in_urbs[i]; + if (!urb) + continue; + if (urb->dev != serial->dev) { + dev_dbg(&port->dev, "%s: dev %p != %p\n", __func__, + urb->dev, serial->dev); + continue; + } + + /* + * make sure endpoint data toggle is synchronized with the + * device + */ + /* dev_dbg(&port->dev, "%s clearing halt on %x\n", __func__, urb->pipe); */ + /* usb_clear_halt(urb->dev, urb->pipe); */ + + dev_dbg(&port->dev, "%s submitting urb %p\n", __func__, urb); + result = usb_submit_urb(urb, GFP_KERNEL); + if (result) { + dev_err(&port->dev, "submit urb %d failed (%d) %d\n", + i, result, urb->transfer_buffer_length); + } + } + + tty->low_latency = 1; + + /* start up the interrupt endpoint if we have one */ + if (port->interrupt_in_urb) { + result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); + if (result) + dev_err(&port->dev, "submit irq_in urb failed %d\n", + result); + } + return 0; +} + +static void vizzini_close(struct usb_serial_port *port) +{ + int i; + struct usb_serial *serial = port->serial; + struct vizzini_port_private *portdata; + struct tty_struct *tty = port->port.tty; + + portdata = usb_get_serial_port_data(port); + + acm_set_control(port, portdata->ctrlout = 0); + + if (serial->dev) { + /* Stop reading/writing urbs */ + for (i = 0; i < N_IN_URB; i++) + usb_kill_urb(portdata->in_urbs[i]); + } + + usb_kill_urb(port->interrupt_in_urb); + + tty = NULL; /* FIXME */ +} + +static int vizzini_attach(struct usb_serial *serial) +{ + struct vizzini_serial_private *serial_priv = usb_get_serial_data(serial); + struct usb_interface *interface = serial_priv->data_interface; + struct usb_host_interface *iface_desc; + struct usb_endpoint_descriptor *endpoint; + struct usb_endpoint_descriptor *bulk_in_endpoint = NULL; + struct usb_endpoint_descriptor *bulk_out_endpoint = NULL; + + struct usb_serial_port *port; + struct vizzini_port_private *portdata; + struct urb *urb; + int i, j; + + /* Assume that there's exactly one serial port. */ + port = serial->port[0]; + + /* The usb_serial is now fully set up, but we want to make a + * couple of modifications. Namely, it was configured based + * upon the control interface and not the data interface, so + * it has no notion of the bulk in and out endpoints. So we + * essentially do some of the same allocations and + * configurations that the usb-serial core would have done if + * it had not made any faulty assumptions about the + * endpoints. */ + + iface_desc = interface->cur_altsetting; + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { + endpoint = &iface_desc->endpoint[i].desc; + + if (usb_endpoint_is_bulk_in(endpoint)) + bulk_in_endpoint = endpoint; + + if (usb_endpoint_is_bulk_out(endpoint)) + bulk_out_endpoint = endpoint; + } + + if (!bulk_out_endpoint || !bulk_in_endpoint) { + dev_dbg(&port->dev, "Missing endpoint!\n"); + return -EINVAL; + } + + port->bulk_out_endpointAddress = bulk_out_endpoint->bEndpointAddress; + port->bulk_in_endpointAddress = bulk_in_endpoint->bEndpointAddress; + + portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); + if (!portdata) { + dev_dbg(&port->dev, "%s: kmalloc for vizzini_port_private (%d) failed!.\n", + __func__, i); + return -ENOMEM; + } + spin_lock_init(&portdata->lock); + for (j = 0; j < N_IN_URB; j++) { + portdata->in_buffer[j] = kmalloc(IN_BUFLEN, GFP_KERNEL); + if (!portdata->in_buffer[j]) { + for (--j; j >= 0; j--) + kfree(portdata->in_buffer[j]); + kfree(portdata); + return -ENOMEM; + } + } + + /* Bulk OUT endpoints 0x1..0x4 map to register blocks 0..3 */ + portdata->block = port->bulk_out_endpointAddress - 1; + + usb_set_serial_port_data(port, portdata); + + portdata->bcd_device = le16_to_cpu(serial->dev->descriptor.bcdDevice); + if (vizzini_rev_a(port)) + dev_info(&port->dev, "Adapting to revA silicon\n"); + + /* initialize the in urbs */ + for (j = 0; j < N_IN_URB; ++j) { + urb = usb_alloc_urb(0, GFP_KERNEL); + if (urb == NULL) { + dev_dbg(&port->dev, "%s: alloc for in port failed.\n", __func__); + continue; + } + /* Fill URB using supplied data. */ + dev_dbg(&port->dev, "Filling URB %p, EP=%d buf=%p len=%d\n", urb, port->bulk_in_endpointAddress, portdata->in_buffer[j], IN_BUFLEN); + usb_fill_bulk_urb(urb, serial->dev, + usb_rcvbulkpipe(serial->dev, + port->bulk_in_endpointAddress), + portdata->in_buffer[j], IN_BUFLEN, + vizzini_in_callback, port); + portdata->in_urbs[j] = urb; + } + + return 0; +} + +static void vizzini_serial_disconnect(struct usb_serial *serial) +{ + struct usb_serial_port *port; + struct vizzini_port_private *portdata; + int i, j; + + dev_dbg(&serial->dev->dev, "%s %p\n", __func__, serial); + + for (i = 0; i < serial->num_ports; ++i) { + port = serial->port[i]; + if (!port) + continue; + portdata = usb_get_serial_port_data(port); + if (!portdata) + continue; + + for (j = 0; j < N_IN_URB; j++) { + usb_kill_urb(portdata->in_urbs[j]); + usb_free_urb(portdata->in_urbs[j]); + } + } +} + +static void vizzini_serial_release(struct usb_serial *serial) +{ + struct usb_serial_port *port; + struct vizzini_port_private *portdata; + int i, j; + + dev_dbg(&serial->dev->dev, "%s %p\n", __func__, serial); + + for (i = 0; i < serial->num_ports; ++i) { + port = serial->port[i]; + if (!port) + continue; + portdata = usb_get_serial_port_data(port); + if (!portdata) + continue; + + for (j = 0; j < N_IN_URB; j++) + kfree(portdata->in_buffer[j]); + + kfree(portdata); + usb_set_serial_port_data(port, NULL); + } +} + +static int vizzini_calc_num_ports(struct usb_serial *serial) +{ + return 1; +} + +static int vizzini_probe(struct usb_serial *serial, + const struct usb_device_id *id) +{ + struct usb_interface *intf = serial->interface; + unsigned char *buffer = intf->altsetting->extra; + int buflen = intf->altsetting->extralen; + struct usb_device *usb_dev = interface_to_usbdev(intf); + struct usb_cdc_union_desc *union_header = NULL; + struct usb_cdc_country_functional_desc *cfd = NULL; + int call_interface_num = -1; + int data_interface_num; + struct usb_interface *control_interface; + struct usb_interface *data_interface; + struct usb_endpoint_descriptor *epctrl; + struct usb_endpoint_descriptor *epread; + struct usb_endpoint_descriptor *epwrite; + struct vizzini_serial_private *serial_priv; + + if (!buffer) { + dev_err(&intf->dev, "Weird descriptor references\n"); + return -EINVAL; + } + + if (!buflen) { + if (intf->cur_altsetting->endpoint->extralen && intf->cur_altsetting->endpoint->extra) { + dev_dbg(&intf->dev, "Seeking extra descriptors on endpoint\n"); + buflen = intf->cur_altsetting->endpoint->extralen; + buffer = intf->cur_altsetting->endpoint->extra; + } else { + dev_err(&intf->dev, "Zero length descriptor references\n"); + return -EINVAL; + } + } + + while (buflen > 0) { + if (buffer[1] != USB_DT_CS_INTERFACE) { + dev_err(&intf->dev, "skipping garbage\n"); + goto next_desc; + } + + switch (buffer[2]) { + case USB_CDC_UNION_TYPE: /* we've found it */ + if (union_header) { + dev_err(&intf->dev, "More than one union descriptor, skipping ...\n"); + goto next_desc; + } + union_header = (struct usb_cdc_union_desc *)buffer; + break; + case USB_CDC_COUNTRY_TYPE: /* export through sysfs */ + cfd = (struct usb_cdc_country_functional_desc *)buffer; + break; + case USB_CDC_HEADER_TYPE: /* maybe check version */ + break; /* for now we ignore it */ + case USB_CDC_CALL_MANAGEMENT_TYPE: + call_interface_num = buffer[4]; + break; + default: + /* there are LOTS more CDC descriptors that + * could legitimately be found here. + */ + dev_dbg(&intf->dev, "Ignoring descriptor: type %02x, length %d\n", buffer[2], buffer[0]); + break; + } +next_desc: + buflen -= buffer[0]; + buffer += buffer[0]; + } + + if (!union_header) { + if (call_interface_num > 0) { + dev_dbg(&intf->dev, "No union descriptor, using call management descriptor\n"); + data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num)); + control_interface = intf; + } else { + dev_dbg(&intf->dev, "No union descriptor, giving up\n"); + return -ENODEV; + } + } else { + control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0); + data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0)); + if (!control_interface || !data_interface) { + dev_dbg(&intf->dev, "no interfaces\n"); + return -ENODEV; + } + } + + if (data_interface_num != call_interface_num) + dev_dbg(&intf->dev, "Separate call control interface. That is not fully supported.\n"); + + /* workaround for switched interfaces */ + if (data_interface->cur_altsetting->desc.bInterfaceClass != CDC_DATA_INTERFACE_TYPE) { + if (control_interface->cur_altsetting->desc.bInterfaceClass == CDC_DATA_INTERFACE_TYPE) { + struct usb_interface *t; + + t = control_interface; + control_interface = data_interface; + data_interface = t; + } else { + return -EINVAL; + } + } + + /* Accept probe requests only for the control interface */ + if (intf != control_interface) + return -ENODEV; + + if (usb_interface_claimed(data_interface)) { /* valid in this context */ + dev_dbg(&intf->dev, "The data interface isn't available\n"); + return -EBUSY; + } + + if (data_interface->cur_altsetting->desc.bNumEndpoints < 2) + return -EINVAL; + + epctrl = &control_interface->cur_altsetting->endpoint[0].desc; + epread = &data_interface->cur_altsetting->endpoint[0].desc; + epwrite = &data_interface->cur_altsetting->endpoint[1].desc; + if (!usb_endpoint_dir_in(epread)) { + struct usb_endpoint_descriptor *t; + t = epread; + epread = epwrite; + epwrite = t; + } + + /* The documentation suggests that we allocate private storage + * with the attach() entry point, but we can't allow the data + * interface to remain unclaimed until then; so we need + * somewhere to save the claimed interface now. */ + serial_priv = kzalloc(sizeof(struct vizzini_serial_private), + GFP_KERNEL); + if (!serial_priv) + goto alloc_fail; + usb_set_serial_data(serial, serial_priv); + + //usb_driver_claim_interface(&vizzini_driver, data_interface, NULL); + + /* Don't set the data interface private data. When we + * disconnect we test this field against NULL to discover + * whether we're dealing with the control or data + * interface. */ + serial_priv->data_interface = data_interface; + + return 0; + +alloc_fail: + return -ENOMEM; +} + +static struct usb_serial_driver vizzini_device = { + .driver = { + .owner = THIS_MODULE, + .name = "vizzini", + }, + .description = "Vizzini USB serial port", + .id_table = id_table, + .calc_num_ports = vizzini_calc_num_ports, + .probe = vizzini_probe, + .open = vizzini_open, + .close = vizzini_close, + .write = vizzini_write, + .write_room = vizzini_write_room, + .ioctl = vizzini_ioctl, + .set_termios = vizzini_set_termios, + .break_ctl = vizzini_break_ctl, + .tiocmget = vizzini_tiocmget, + .tiocmset = vizzini_tiocmset, + .attach = vizzini_attach, + .disconnect = vizzini_serial_disconnect, + .release = vizzini_serial_release, + .read_int_callback = vizzini_int_callback, +}; + +static struct usb_serial_driver * const serial_drivers[] = { + &vizzini_device, NULL +}; + +module_usb_serial_driver(serial_drivers, id_table); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_VERSION(DRIVER_VERSION); +MODULE_LICENSE("GPL"); -- cgit v0.10.2 From eb83be985510ab07f05be9541adfe3d5125deb18 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 14 Sep 2012 21:15:50 -0700 Subject: USB: remove CONFIG_EXPERIMENTAL dependancies As discussed at the kernel summit this year, CONFIG_EXPERIMENTAL means nothing, so let's get rid of it. Acked-by: Felipe Balbi Cc: Kees Cook Cc: David Herrmann Cc: Hauke Mehrtens Cc: Alan Stern Cc: Neil Zhang Cc: Randy Dunlap Cc: Fabio Estevam Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index 9981984..f70c1a1 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig @@ -56,7 +56,7 @@ config USB_SUSPEND config USB_OTG bool "OTG support" - depends on USB && EXPERIMENTAL + depends on USB depends on USB_SUSPEND default n help diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index a53be32..dfb51a4 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -557,7 +557,7 @@ config USB_ZERO_HNPTEST one serve as the USB host instead (in the "B-Host" role). config USB_AUDIO - tristate "Audio Gadget (EXPERIMENTAL)" + tristate "Audio Gadget" depends on SND select USB_LIBCOMPOSITE select SND_PCM @@ -672,8 +672,7 @@ config USB_G_NCM dynamically linked module called "g_ncm". config USB_GADGETFS - tristate "Gadget Filesystem (EXPERIMENTAL)" - depends on EXPERIMENTAL + tristate "Gadget Filesystem" help This driver provides a filesystem based API that lets user mode programs implement a single-configuration USB device, including @@ -681,15 +680,11 @@ config USB_GADGETFS All endpoints, transfer speeds, and transfer types supported by the hardware are available, through read() and write() calls. - Currently, this option is still labelled as EXPERIMENTAL because - of existing race conditions in the underlying in-kernel AIO core. - Say "y" to link the driver statically, or "m" to build a dynamically linked module called "gadgetfs". config USB_FUNCTIONFS - tristate "Function Filesystem (EXPERIMENTAL)" - depends on EXPERIMENTAL + tristate "Function Filesystem" select USB_LIBCOMPOSITE select USB_FUNCTIONFS_GENERIC if !(USB_FUNCTIONFS_ETH || USB_FUNCTIONFS_RNDIS) help @@ -799,8 +794,8 @@ config USB_G_SERIAL make MS-Windows work with CDC ACM. config USB_MIDI_GADGET - tristate "MIDI Gadget (EXPERIMENTAL)" - depends on SND && EXPERIMENTAL + tristate "MIDI Gadget" + depends on SND select USB_LIBCOMPOSITE select SND_RAWMIDI help @@ -867,7 +862,7 @@ config USB_G_ACM_MS dynamically linked module called "g_acm_ms". config USB_G_MULTI - tristate "Multifunction Composite Gadget (EXPERIMENTAL)" + tristate "Multifunction Composite Gadget" depends on BLOCK && NET select USB_G_MULTI_CDC if !USB_G_MULTI_RNDIS select USB_LIBCOMPOSITE diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 13cd6d5..b1deb0f 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -18,8 +18,8 @@ config USB_C67X00_HCD module will be called c67x00. config USB_XHCI_HCD - tristate "xHCI HCD (USB 3.0) support (EXPERIMENTAL)" - depends on USB && USB_ARCH_HAS_XHCI && EXPERIMENTAL + tristate "xHCI HCD (USB 3.0) support" + depends on USB && USB_ARCH_HAS_XHCI ---help--- The eXtensible Host Controller Interface (xHCI) is standard for USB 3.0 "SuperSpeed" host controller hardware. @@ -262,7 +262,7 @@ config USB_ISP116X_HCD config USB_ISP1760_HCD tristate "ISP 1760 HCD support" - depends on USB && EXPERIMENTAL + depends on USB ---help--- The ISP1760 chip is a USB 2.0 host controller. @@ -376,7 +376,7 @@ config USB_OHCI_HCD_PCI config USB_OHCI_HCD_SSB bool "OHCI support for Broadcom SSB OHCI core (DEPRECATED)" - depends on USB_OHCI_HCD && (SSB = y || SSB = USB_OHCI_HCD) && EXPERIMENTAL + depends on USB_OHCI_HCD && (SSB = y || SSB = USB_OHCI_HCD) select USB_HCD_SSB select USB_OHCI_HCD_PLATFORM default n @@ -414,7 +414,7 @@ config USB_CNS3XXX_OHCI config USB_OHCI_HCD_PLATFORM bool "Generic OHCI driver for a platform device" - depends on USB_OHCI_HCD && EXPERIMENTAL + depends on USB_OHCI_HCD default n ---help--- Adds an OHCI host driver for a generic platform device, which @@ -424,7 +424,7 @@ config USB_OHCI_HCD_PLATFORM config USB_EHCI_HCD_PLATFORM bool "Generic EHCI driver for a platform device" - depends on USB_EHCI_HCD && EXPERIMENTAL + depends on USB_EHCI_HCD default n ---help--- Adds an EHCI host driver for a generic platform device, which @@ -591,8 +591,7 @@ config USB_RENESAS_USBHS_HCD module will be called renesas-usbhs. config USB_WHCI_HCD - tristate "Wireless USB Host Controller Interface (WHCI) driver (EXPERIMENTAL)" - depends on EXPERIMENTAL + tristate "Wireless USB Host Controller Interface (WHCI) driver" depends on PCI && USB && UWB select USB_WUSB select UWB_WHCI @@ -604,8 +603,7 @@ config USB_WHCI_HCD will be called "whci-hcd". config USB_HWA_HCD - tristate "Host Wire Adapter (HWA) driver (EXPERIMENTAL)" - depends on EXPERIMENTAL + tristate "Host Wire Adapter (HWA) driver" depends on USB && UWB select USB_WUSB select UWB_HWA @@ -656,7 +654,7 @@ config USB_OCTEON2_COMMON config USB_HCD_BCMA tristate "BCMA usb host driver" - depends on BCMA && EXPERIMENTAL + depends on BCMA select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD help @@ -668,7 +666,7 @@ config USB_HCD_BCMA config USB_HCD_SSB tristate "SSB usb host driver" - depends on SSB && EXPERIMENTAL + depends on SSB select USB_OHCI_HCD_PLATFORM if USB_OHCI_HCD select USB_EHCI_HCD_PLATFORM if USB_EHCI_HCD help diff --git a/drivers/usb/wusbcore/Kconfig b/drivers/usb/wusbcore/Kconfig index f29fdd7..8bf1976 100644 --- a/drivers/usb/wusbcore/Kconfig +++ b/drivers/usb/wusbcore/Kconfig @@ -2,8 +2,7 @@ # Wireless USB Core configuration # config USB_WUSB - tristate "Enable Wireless USB extensions (EXPERIMENTAL)" - depends on EXPERIMENTAL + tristate "Enable Wireless USB extensions" depends on USB depends on PCI depends on UWB -- cgit v0.10.2 From 984f68683298ba53af32f909de1f9452fbb37ccb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 01:33:23 -0700 Subject: USB: serial: io_edgeport.c: remove dbg() usage dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. Cc: Johan Hovold Cc: Alan Stern Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index e1f5ccd..1a82697 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -244,7 +244,7 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, __u8 lsr, __u8 data); static int send_iosp_ext_cmd(struct edgeport_port *edge_port, __u8 command, __u8 param); -static int calc_baud_rate_divisor(int baud_rate, int *divisor); +static int calc_baud_rate_divisor(struct device *dev, int baud_rate, int *divisor); static int send_cmd_write_baud_rate(struct edgeport_port *edge_port, int baudRate); static void change_port_settings(struct tty_struct *tty, @@ -286,6 +286,7 @@ static void unicode_to_ascii(char *string, int buflen, ************************************************************************/ static void update_edgeport_E2PROM(struct edgeport_serial *edge_serial) { + struct device *dev = &edge_serial->serial->dev->dev; __u32 BootCurVer; __u32 BootNewVer; __u8 BootMajorVersion; @@ -311,7 +312,7 @@ static void update_edgeport_E2PROM(struct edgeport_serial *edge_serial) response = request_ihex_firmware(&fw, fw_name, &edge_serial->serial->dev->dev); if (response) { - printk(KERN_ERR "Failed to load image \"%s\" err %d\n", + dev_err(dev, "Failed to load image \"%s\" err %d\n", fw_name, response); return; } @@ -330,20 +331,20 @@ static void update_edgeport_E2PROM(struct edgeport_serial *edge_serial) (BootMinorVersion << 16) + BootBuildNumber; - dbg("Current Boot Image version %d.%d.%d", + dev_dbg(dev, "Current Boot Image version %d.%d.%d\n", edge_serial->boot_descriptor.MajorVersion, edge_serial->boot_descriptor.MinorVersion, le16_to_cpu(edge_serial->boot_descriptor.BuildNumber)); if (BootNewVer > BootCurVer) { - dbg("**Update Boot Image from %d.%d.%d to %d.%d.%d", + dev_dbg(dev, "**Update Boot Image from %d.%d.%d to %d.%d.%d\n", edge_serial->boot_descriptor.MajorVersion, edge_serial->boot_descriptor.MinorVersion, le16_to_cpu(edge_serial->boot_descriptor.BuildNumber), BootMajorVersion, BootMinorVersion, BootBuildNumber); - dbg("Downloading new Boot Image"); + dev_dbg(dev, "Downloading new Boot Image\n"); for (rec = ihex_next_binrec(rec); rec; rec = ihex_next_binrec(rec)) { @@ -362,7 +363,7 @@ static void update_edgeport_E2PROM(struct edgeport_serial *edge_serial) } } } else { - dbg("Boot Image -- already up to date"); + dev_dbg(dev, "Boot Image -- already up to date\n"); } release_firmware(fw); } @@ -379,7 +380,7 @@ static int get_string_desc(struct usb_device *dev, int Id, struct usb_string_descriptor StringDesc; struct usb_string_descriptor *pStringDesc; - dbg("%s - USB String ID = %d", __func__, Id); + dev_dbg(&dev->dev, "%s - USB String ID = %d\n", __func__, Id); if (!usb_get_descriptor(dev, USB_DT_STRING, Id, &StringDesc, sizeof(StringDesc))) @@ -400,34 +401,39 @@ static int get_string_desc(struct usb_device *dev, int Id, } #endif -static void dump_product_info(struct edgeport_product_info *product_info) +static void dump_product_info(struct edgeport_serial *edge_serial, + struct edgeport_product_info *product_info) { + struct device *dev = &edge_serial->serial->dev->dev; + /* Dump Product Info structure */ - dbg("**Product Information:"); - dbg(" ProductId %x", product_info->ProductId); - dbg(" NumPorts %d", product_info->NumPorts); - dbg(" ProdInfoVer %d", product_info->ProdInfoVer); - dbg(" IsServer %d", product_info->IsServer); - dbg(" IsRS232 %d", product_info->IsRS232); - dbg(" IsRS422 %d", product_info->IsRS422); - dbg(" IsRS485 %d", product_info->IsRS485); - dbg(" RomSize %d", product_info->RomSize); - dbg(" RamSize %d", product_info->RamSize); - dbg(" CpuRev %x", product_info->CpuRev); - dbg(" BoardRev %x", product_info->BoardRev); - dbg(" BootMajorVersion %d.%d.%d", product_info->BootMajorVersion, - product_info->BootMinorVersion, - le16_to_cpu(product_info->BootBuildNumber)); - dbg(" FirmwareMajorVersion %d.%d.%d", - product_info->FirmwareMajorVersion, - product_info->FirmwareMinorVersion, - le16_to_cpu(product_info->FirmwareBuildNumber)); - dbg(" ManufactureDescDate %d/%d/%d", - product_info->ManufactureDescDate[0], - product_info->ManufactureDescDate[1], - product_info->ManufactureDescDate[2]+1900); - dbg(" iDownloadFile 0x%x", product_info->iDownloadFile); - dbg(" EpicVer %d", product_info->EpicVer); + dev_dbg(dev, "**Product Information:\n"); + dev_dbg(dev, " ProductId %x\n", product_info->ProductId); + dev_dbg(dev, " NumPorts %d\n", product_info->NumPorts); + dev_dbg(dev, " ProdInfoVer %d\n", product_info->ProdInfoVer); + dev_dbg(dev, " IsServer %d\n", product_info->IsServer); + dev_dbg(dev, " IsRS232 %d\n", product_info->IsRS232); + dev_dbg(dev, " IsRS422 %d\n", product_info->IsRS422); + dev_dbg(dev, " IsRS485 %d\n", product_info->IsRS485); + dev_dbg(dev, " RomSize %d\n", product_info->RomSize); + dev_dbg(dev, " RamSize %d\n", product_info->RamSize); + dev_dbg(dev, " CpuRev %x\n", product_info->CpuRev); + dev_dbg(dev, " BoardRev %x\n", product_info->BoardRev); + dev_dbg(dev, " BootMajorVersion %d.%d.%d\n", + product_info->BootMajorVersion, + product_info->BootMinorVersion, + le16_to_cpu(product_info->BootBuildNumber)); + dev_dbg(dev, " FirmwareMajorVersion %d.%d.%d\n", + product_info->FirmwareMajorVersion, + product_info->FirmwareMinorVersion, + le16_to_cpu(product_info->FirmwareBuildNumber)); + dev_dbg(dev, " ManufactureDescDate %d/%d/%d\n", + product_info->ManufactureDescDate[0], + product_info->ManufactureDescDate[1], + product_info->ManufactureDescDate[2]+1900); + dev_dbg(dev, " iDownloadFile 0x%x\n", + product_info->iDownloadFile); + dev_dbg(dev, " EpicVer %d\n", product_info->EpicVer); } static void get_product_info(struct edgeport_serial *edge_serial) @@ -462,7 +468,7 @@ static void get_product_info(struct edgeport_serial *edge_serial) product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_80251; else product_info->iDownloadFile = EDGE_DOWNLOAD_FILE_I930; - + /* Determine Product type and set appropriate flags */ switch (DEVICE_ID_FROM_USB_PRODUCT_ID(product_info->ProductId)) { case ION_DEVICE_ID_EDGEPORT_COMPATIBLE: @@ -490,7 +496,7 @@ static void get_product_info(struct edgeport_serial *edge_serial) break; } - dump_product_info(product_info); + dump_product_info(edge_serial, product_info); } static int get_epic_descriptor(struct edgeport_serial *ep) @@ -500,6 +506,7 @@ static int get_epic_descriptor(struct edgeport_serial *ep) struct edgeport_product_info *product_info = &ep->product_info; struct edge_compatibility_descriptor *epic = &ep->epic_descriptor; struct edge_compatibility_bits *bits; + struct device *dev = &serial->dev->dev; ep->is_epic = 0; result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), @@ -509,8 +516,6 @@ static int get_epic_descriptor(struct edgeport_serial *ep) sizeof(struct edge_compatibility_descriptor), 300); - dbg("%s result = %d", __func__, result); - if (result > 0) { ep->is_epic = 1; memset(product_info, 0, sizeof(struct edgeport_product_info)); @@ -524,23 +529,23 @@ static int get_epic_descriptor(struct edgeport_serial *ep) product_info->EpicVer = epic->EpicVer; product_info->Epic = epic->Supports; product_info->ProductId = ION_DEVICE_ID_EDGEPORT_COMPATIBLE; - dump_product_info(product_info); + dump_product_info(ep, product_info); bits = &ep->epic_descriptor.Supports; - dbg("**EPIC descriptor:"); - dbg(" VendEnableSuspend: %s", bits->VendEnableSuspend ? "TRUE": "FALSE"); - dbg(" IOSPOpen : %s", bits->IOSPOpen ? "TRUE": "FALSE"); - dbg(" IOSPClose : %s", bits->IOSPClose ? "TRUE": "FALSE"); - dbg(" IOSPChase : %s", bits->IOSPChase ? "TRUE": "FALSE"); - dbg(" IOSPSetRxFlow : %s", bits->IOSPSetRxFlow ? "TRUE": "FALSE"); - dbg(" IOSPSetTxFlow : %s", bits->IOSPSetTxFlow ? "TRUE": "FALSE"); - dbg(" IOSPSetXChar : %s", bits->IOSPSetXChar ? "TRUE": "FALSE"); - dbg(" IOSPRxCheck : %s", bits->IOSPRxCheck ? "TRUE": "FALSE"); - dbg(" IOSPSetClrBreak : %s", bits->IOSPSetClrBreak ? "TRUE": "FALSE"); - dbg(" IOSPWriteMCR : %s", bits->IOSPWriteMCR ? "TRUE": "FALSE"); - dbg(" IOSPWriteLCR : %s", bits->IOSPWriteLCR ? "TRUE": "FALSE"); - dbg(" IOSPSetBaudRate : %s", bits->IOSPSetBaudRate ? "TRUE": "FALSE"); - dbg(" TrueEdgeport : %s", bits->TrueEdgeport ? "TRUE": "FALSE"); + dev_dbg(dev, "**EPIC descriptor:\n"); + dev_dbg(dev, " VendEnableSuspend: %s\n", bits->VendEnableSuspend ? "TRUE": "FALSE"); + dev_dbg(dev, " IOSPOpen : %s\n", bits->IOSPOpen ? "TRUE": "FALSE"); + dev_dbg(dev, " IOSPClose : %s\n", bits->IOSPClose ? "TRUE": "FALSE"); + dev_dbg(dev, " IOSPChase : %s\n", bits->IOSPChase ? "TRUE": "FALSE"); + dev_dbg(dev, " IOSPSetRxFlow : %s\n", bits->IOSPSetRxFlow ? "TRUE": "FALSE"); + dev_dbg(dev, " IOSPSetTxFlow : %s\n", bits->IOSPSetTxFlow ? "TRUE": "FALSE"); + dev_dbg(dev, " IOSPSetXChar : %s\n", bits->IOSPSetXChar ? "TRUE": "FALSE"); + dev_dbg(dev, " IOSPRxCheck : %s\n", bits->IOSPRxCheck ? "TRUE": "FALSE"); + dev_dbg(dev, " IOSPSetClrBreak : %s\n", bits->IOSPSetClrBreak ? "TRUE": "FALSE"); + dev_dbg(dev, " IOSPWriteMCR : %s\n", bits->IOSPWriteMCR ? "TRUE": "FALSE"); + dev_dbg(dev, " IOSPWriteLCR : %s\n", bits->IOSPWriteLCR ? "TRUE": "FALSE"); + dev_dbg(dev, " IOSPSetBaudRate : %s\n", bits->IOSPSetBaudRate ? "TRUE": "FALSE"); + dev_dbg(dev, " TrueEdgeport : %s\n", bits->TrueEdgeport ? "TRUE": "FALSE"); } return result; @@ -561,7 +566,8 @@ static int get_epic_descriptor(struct edgeport_serial *ep) *****************************************************************************/ static void edge_interrupt_callback(struct urb *urb) { - struct edgeport_serial *edge_serial = urb->context; + struct edgeport_serial *edge_serial = urb->context; + struct device *dev; struct edgeport_port *edge_port; struct usb_serial_port *port; struct tty_struct *tty; @@ -574,8 +580,6 @@ static void edge_interrupt_callback(struct urb *urb) int result; int status = urb->status; - dbg("%s", __func__); - switch (status) { case 0: /* success */ @@ -584,36 +588,42 @@ static void edge_interrupt_callback(struct urb *urb) case -ENOENT: case -ESHUTDOWN: /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", - __func__, status); + dev_dbg(&urb->dev->dev, "%s - urb shutting down with status: %d\n", __func__, status); return; default: - dbg("%s - nonzero urb status received: %d", __func__, status); + dev_dbg(&urb->dev->dev, "%s - nonzero urb status received: %d\n", __func__, status); goto exit; } + dev = &edge_serial->serial->dev->dev; + /* process this interrupt-read even if there are no ports open */ if (length) { - usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, - __func__, length, data); + usb_serial_debug_data(debug, dev, __func__, length, data); if (length > 1) { bytes_avail = data[0] | (data[1] << 8); if (bytes_avail) { spin_lock(&edge_serial->es_lock); edge_serial->rxBytesAvail += bytes_avail; - dbg("%s - bytes_avail=%d, rxBytesAvail=%d, read_in_progress=%d", __func__, bytes_avail, edge_serial->rxBytesAvail, edge_serial->read_in_progress); + dev_dbg(dev, + "%s - bytes_avail=%d, rxBytesAvail=%d, read_in_progress=%d\n", + __func__, bytes_avail, + edge_serial->rxBytesAvail, + edge_serial->read_in_progress); if (edge_serial->rxBytesAvail > 0 && !edge_serial->read_in_progress) { - dbg("%s - posting a read", __func__); + dev_dbg(dev, "%s - posting a read\n", __func__); edge_serial->read_in_progress = true; /* we have pending bytes on the bulk in pipe, send a request */ result = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC); if (result) { - dev_err(&edge_serial->serial->dev->dev, "%s - usb_submit_urb(read bulk) failed with result = %d\n", __func__, result); + dev_err(dev, + "%s - usb_submit_urb(read bulk) failed with result = %d\n", + __func__, result); edge_serial->read_in_progress = false; } } @@ -633,9 +643,9 @@ static void edge_interrupt_callback(struct urb *urb) spin_lock(&edge_port->ep_lock); edge_port->txCredits += txCredits; spin_unlock(&edge_port->ep_lock); - dbg("%s - txcredits for port%d = %d", - __func__, portNumber, - edge_port->txCredits); + dev_dbg(dev, "%s - txcredits for port%d = %d\n", + __func__, portNumber, + edge_port->txCredits); /* tell the tty driver that something has changed */ @@ -673,49 +683,48 @@ exit: static void edge_bulk_in_callback(struct urb *urb) { struct edgeport_serial *edge_serial = urb->context; + struct device *dev; unsigned char *data = urb->transfer_buffer; int retval; __u16 raw_data_length; int status = urb->status; - dbg("%s", __func__); - if (status) { - dbg("%s - nonzero read bulk status received: %d", - __func__, status); + dev_dbg(&urb->dev->dev, "%s - nonzero read bulk status received: %d\n", + __func__, status); edge_serial->read_in_progress = false; return; } if (urb->actual_length == 0) { - dbg("%s - read bulk callback with no data", __func__); + dev_dbg(&urb->dev->dev, "%s - read bulk callback with no data\n", __func__); edge_serial->read_in_progress = false; return; } + dev = &edge_serial->serial->dev->dev; raw_data_length = urb->actual_length; - usb_serial_debug_data(debug, &edge_serial->serial->dev->dev, - __func__, raw_data_length, data); + usb_serial_debug_data(debug, dev, __func__, raw_data_length, data); spin_lock(&edge_serial->es_lock); /* decrement our rxBytes available by the number that we just got */ edge_serial->rxBytesAvail -= raw_data_length; - dbg("%s - Received = %d, rxBytesAvail %d", __func__, - raw_data_length, edge_serial->rxBytesAvail); + dev_dbg(dev, "%s - Received = %d, rxBytesAvail %d\n", __func__, + raw_data_length, edge_serial->rxBytesAvail); process_rcvd_data(edge_serial, data, urb->actual_length); /* check to see if there's any more data for us to read */ if (edge_serial->rxBytesAvail > 0) { - dbg("%s - posting a read", __func__); + dev_dbg(dev, "%s - posting a read\n", __func__); retval = usb_submit_urb(edge_serial->read_urb, GFP_ATOMIC); if (retval) { - dev_err(&urb->dev->dev, - "%s - usb_submit_urb(read bulk) failed, " - "retval = %d\n", __func__, retval); + dev_err(dev, + "%s - usb_submit_urb(read bulk) failed, retval = %d\n", + __func__, retval); edge_serial->read_in_progress = false; } } else { @@ -737,11 +746,10 @@ static void edge_bulk_out_data_callback(struct urb *urb) struct tty_struct *tty; int status = urb->status; - dbg("%s", __func__); - if (status) { - dbg("%s - nonzero write bulk status received: %d", - __func__, status); + dev_dbg(&urb->dev->dev, + "%s - nonzero write bulk status received: %d\n", + __func__, status); } tty = tty_port_tty_get(&edge_port->port->port); @@ -773,11 +781,9 @@ static void edge_bulk_out_cmd_callback(struct urb *urb) struct tty_struct *tty; int status = urb->status; - dbg("%s", __func__); - atomic_dec(&CmdUrbs); - dbg("%s - FREE URB %p (outstanding %d)", __func__, - urb, atomic_read(&CmdUrbs)); + dev_dbg(&urb->dev->dev, "%s - FREE URB %p (outstanding %d)\n", + __func__, urb, atomic_read(&CmdUrbs)); /* clean up the transfer buffer */ @@ -787,8 +793,9 @@ static void edge_bulk_out_cmd_callback(struct urb *urb) usb_free_urb(urb); if (status) { - dbg("%s - nonzero write bulk status received: %d", - __func__, status); + dev_dbg(&urb->dev->dev, + "%s - nonzero write bulk status received: %d\n", + __func__, status); return; } @@ -819,12 +826,11 @@ static void edge_bulk_out_cmd_callback(struct urb *urb) static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) { struct edgeport_port *edge_port = usb_get_serial_port_data(port); + struct device *dev = &port->dev; struct usb_serial *serial; struct edgeport_serial *edge_serial; int response; - dbg("%s - port %d", __func__, port->number); - if (edge_port == NULL) return -ENODEV; @@ -875,9 +881,8 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) response = usb_submit_urb(edge_serial->interrupt_read_urb, GFP_KERNEL); if (response) { - dev_err(&port->dev, - "%s - Error %d submitting control urb\n", - __func__, response); + dev_err(dev, "%s - Error %d submitting control urb\n", + __func__, response); } } @@ -902,8 +907,7 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) response = send_iosp_ext_cmd(edge_port, IOSP_CMD_OPEN_PORT, 0); if (response < 0) { - dev_err(&port->dev, "%s - error sending open port command\n", - __func__); + dev_err(dev, "%s - error sending open port command\n", __func__); edge_port->openPending = false; return -ENODEV; } @@ -914,7 +918,7 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) if (!edge_port->open) { /* open timed out */ - dbg("%s - open timedout", __func__); + dev_dbg(dev, "%s - open timedout\n", __func__); edge_port->openPending = false; return -ENODEV; } @@ -927,7 +931,7 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) edge_port->txfifo.fifo = kmalloc(edge_port->maxTxCredits, GFP_KERNEL); if (!edge_port->txfifo.fifo) { - dbg("%s - no memory", __func__); + dev_dbg(dev, "%s - no memory\n", __func__); edge_close(port); return -ENOMEM; } @@ -937,15 +941,13 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) edge_port->write_in_progress = false; if (!edge_port->write_urb) { - dbg("%s - no memory", __func__); + dev_dbg(dev, "%s - no memory\n", __func__); edge_close(port); return -ENOMEM; } - dbg("%s(%d) - Initialize TX fifo to %d bytes", - __func__, port->number, edge_port->maxTxCredits); - - dbg("%s exited", __func__); + dev_dbg(dev, "%s(%d) - Initialize TX fifo to %d bytes\n", + __func__, port->number, edge_port->maxTxCredits); return 0; } @@ -963,6 +965,7 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) ************************************************************************/ static void block_until_chase_response(struct edgeport_port *edge_port) { + struct device *dev = &edge_port->port->dev; DEFINE_WAIT(wait); __u16 lastCredits; int timeout = 1*HZ; @@ -974,11 +977,11 @@ static void block_until_chase_response(struct edgeport_port *edge_port) /* Did we get our Chase response */ if (!edge_port->chaseResponsePending) { - dbg("%s - Got Chase Response", __func__); + dev_dbg(dev, "%s - Got Chase Response\n", __func__); /* did we get all of our credit back? */ if (edge_port->txCredits == edge_port->maxTxCredits) { - dbg("%s - Got all credits", __func__); + dev_dbg(dev, "%s - Got all credits\n", __func__); return; } } @@ -994,12 +997,12 @@ static void block_until_chase_response(struct edgeport_port *edge_port) loop--; if (loop == 0) { edge_port->chaseResponsePending = false; - dbg("%s - Chase TIMEOUT", __func__); + dev_dbg(dev, "%s - Chase TIMEOUT\n", __func__); return; } } else { /* Reset timeout value back to 10 seconds */ - dbg("%s - Last %d, Current %d", __func__, + dev_dbg(dev, "%s - Last %d, Current %d\n", __func__, lastCredits, edge_port->txCredits); loop = 10; } @@ -1019,6 +1022,7 @@ static void block_until_chase_response(struct edgeport_port *edge_port) ************************************************************************/ static void block_until_tx_empty(struct edgeport_port *edge_port) { + struct device *dev = &edge_port->port->dev; DEFINE_WAIT(wait); struct TxFifo *fifo = &edge_port->txfifo; __u32 lastCount; @@ -1031,7 +1035,7 @@ static void block_until_tx_empty(struct edgeport_port *edge_port) /* Is the Edgeport Buffer empty? */ if (lastCount == 0) { - dbg("%s - TX Buffer Empty", __func__); + dev_dbg(dev, "%s - TX Buffer Empty\n", __func__); return; } @@ -1041,13 +1045,13 @@ static void block_until_tx_empty(struct edgeport_port *edge_port) schedule_timeout(timeout); finish_wait(&edge_port->wait_chase, &wait); - dbg("%s wait", __func__); + dev_dbg(dev, "%s wait\n", __func__); if (lastCount == fifo->count) { /* No activity.. count down. */ loop--; if (loop == 0) { - dbg("%s - TIMEOUT", __func__); + dev_dbg(dev, "%s - TIMEOUT\n", __func__); return; } } else { @@ -1068,8 +1072,6 @@ static void edge_close(struct usb_serial_port *port) struct edgeport_port *edge_port; int status; - dbg("%s - port %d", __func__, port->number); - edge_serial = usb_get_serial_data(port->serial); edge_port = usb_get_serial_port_data(port); if (edge_serial == NULL || edge_port == NULL) @@ -1086,7 +1088,7 @@ static void edge_close(struct usb_serial_port *port) /* flush and chase */ edge_port->chaseResponsePending = true; - dbg("%s - Sending IOSP_CMD_CHASE_PORT", __func__); + dev_dbg(&port->dev, "%s - Sending IOSP_CMD_CHASE_PORT\n", __func__); status = send_iosp_ext_cmd(edge_port, IOSP_CMD_CHASE_PORT, 0); if (status == 0) /* block until chase finished */ @@ -1099,7 +1101,7 @@ static void edge_close(struct usb_serial_port *port) ((edge_serial->is_epic) && (edge_serial->epic_descriptor.Supports.IOSPClose))) { /* close the port */ - dbg("%s - Sending IOSP_CMD_CLOSE_PORT", __func__); + dev_dbg(&port->dev, "%s - Sending IOSP_CMD_CLOSE_PORT\n", __func__); send_iosp_ext_cmd(edge_port, IOSP_CMD_CLOSE_PORT, 0); } @@ -1119,8 +1121,6 @@ static void edge_close(struct usb_serial_port *port) } kfree(edge_port->txfifo.fifo); edge_port->txfifo.fifo = NULL; - - dbg("%s exited", __func__); } /***************************************************************************** @@ -1141,8 +1141,6 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port, int secondhalf; unsigned long flags; - dbg("%s - port %d", __func__, port->number); - if (edge_port == NULL) return -ENODEV; @@ -1155,14 +1153,14 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port, copySize = min((unsigned int)count, (edge_port->txCredits - fifo->count)); - dbg("%s(%d) of %d byte(s) Fifo room %d -- will copy %d bytes", - __func__, port->number, count, + dev_dbg(&port->dev, "%s(%d) of %d byte(s) Fifo room %d -- will copy %d bytes\n", + __func__, port->number, count, edge_port->txCredits - fifo->count, copySize); /* catch writes of 0 bytes which the tty driver likes to give us, and when txCredits is empty */ if (copySize == 0) { - dbg("%s - copySize = Zero", __func__); + dev_dbg(&port->dev, "%s - copySize = Zero\n", __func__); goto finish_write; } @@ -1175,8 +1173,8 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port, */ bytesleft = fifo->size - fifo->head; firsthalf = min(bytesleft, copySize); - dbg("%s - copy %d bytes of %d into fifo ", __func__, - firsthalf, bytesleft); + dev_dbg(&port->dev, "%s - copy %d bytes of %d into fifo \n", __func__, + firsthalf, bytesleft); /* now copy our data */ memcpy(&fifo->fifo[fifo->head], data, firsthalf); @@ -1194,7 +1192,7 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port, secondhalf = copySize-firsthalf; if (secondhalf) { - dbg("%s - copy rest of data %d", __func__, secondhalf); + dev_dbg(&port->dev, "%s - copy rest of data %d\n", __func__, secondhalf); memcpy(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf); usb_serial_debug_data(debug, &port->dev, __func__, secondhalf, &fifo->fifo[fifo->head]); @@ -1212,8 +1210,8 @@ finish_write: send_more_port_data((struct edgeport_serial *) usb_get_serial_data(port->serial), edge_port); - dbg("%s wrote %d byte(s) TxCredits %d, Fifo %d", __func__, - copySize, edge_port->txCredits, fifo->count); + dev_dbg(&port->dev, "%s wrote %d byte(s) TxCredits %d, Fifo %d\n", + __func__, copySize, edge_port->txCredits, fifo->count); return copySize; } @@ -1236,6 +1234,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, struct edgeport_port *edge_port) { struct TxFifo *fifo = &edge_port->txfifo; + struct device *dev = &edge_port->port->dev; struct urb *urb; unsigned char *buffer; int status; @@ -1245,16 +1244,14 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, int secondhalf; unsigned long flags; - dbg("%s(%d)", __func__, edge_port->port->number); - spin_lock_irqsave(&edge_port->ep_lock, flags); if (edge_port->write_in_progress || !edge_port->open || (fifo->count == 0)) { - dbg("%s(%d) EXIT - fifo %d, PendingWrite = %d", - __func__, edge_port->port->number, - fifo->count, edge_port->write_in_progress); + dev_dbg(dev, "%s(%d) EXIT - fifo %d, PendingWrite = %d\n", + __func__, edge_port->port->number, + fifo->count, edge_port->write_in_progress); goto exit_send; } @@ -1266,7 +1263,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, * it's better to wait for more credits so we can do a larger write. */ if (edge_port->txCredits < EDGE_FW_GET_TX_CREDITS_SEND_THRESHOLD(edge_port->maxTxCredits, EDGE_FW_BULK_MAX_PACKET_SIZE)) { - dbg("%s(%d) Not enough credit - fifo %d TxCredit %d", + dev_dbg(dev, "%s(%d) Not enough credit - fifo %d TxCredit %d\n", __func__, edge_port->port->number, fifo->count, edge_port->txCredits); goto exit_send; @@ -1341,8 +1338,8 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, edge_port->txCredits += count; edge_port->icount.tx -= count; } - dbg("%s wrote %d byte(s) TxCredit %d, Fifo %d", - __func__, count, edge_port->txCredits, fifo->count); + dev_dbg(dev, "%s wrote %d byte(s) TxCredit %d, Fifo %d\n", + __func__, count, edge_port->txCredits, fifo->count); exit_send: spin_unlock_irqrestore(&edge_port->ep_lock, flags); @@ -1363,17 +1360,13 @@ static int edge_write_room(struct tty_struct *tty) int room; unsigned long flags; - dbg("%s", __func__); - if (edge_port == NULL) return 0; if (edge_port->closePending) return 0; - dbg("%s - port %d", __func__, port->number); - if (!edge_port->open) { - dbg("%s - port not opened", __func__); + dev_dbg(&port->dev, "%s - port not opened\n", __func__); return 0; } @@ -1382,7 +1375,7 @@ static int edge_write_room(struct tty_struct *tty) room = edge_port->txCredits - edge_port->txfifo.count; spin_unlock_irqrestore(&edge_port->ep_lock, flags); - dbg("%s - returns %d", __func__, room); + dev_dbg(&port->dev, "%s - returns %d\n", __func__, room); return room; } @@ -1403,15 +1396,13 @@ static int edge_chars_in_buffer(struct tty_struct *tty) int num_chars; unsigned long flags; - dbg("%s", __func__); - if (edge_port == NULL) return 0; if (edge_port->closePending) return 0; if (!edge_port->open) { - dbg("%s - port not opened", __func__); + dev_dbg(&port->dev, "%s - port not opened\n", __func__); return 0; } @@ -1420,8 +1411,8 @@ static int edge_chars_in_buffer(struct tty_struct *tty) edge_port->txfifo.count; spin_unlock_irqrestore(&edge_port->ep_lock, flags); if (num_chars) { - dbg("%s(port %d) - returns %d", __func__, - port->number, num_chars); + dev_dbg(&port->dev, "%s(port %d) - returns %d\n", __func__, + port->number, num_chars); } return num_chars; @@ -1439,13 +1430,11 @@ static void edge_throttle(struct tty_struct *tty) struct edgeport_port *edge_port = usb_get_serial_port_data(port); int status; - dbg("%s - port %d", __func__, port->number); - if (edge_port == NULL) return; if (!edge_port->open) { - dbg("%s - port not opened", __func__); + dev_dbg(&port->dev, "%s - port not opened\n", __func__); return; } @@ -1479,13 +1468,11 @@ static void edge_unthrottle(struct tty_struct *tty) struct edgeport_port *edge_port = usb_get_serial_port_data(port); int status; - dbg("%s - port %d", __func__, port->number); - if (edge_port == NULL) return; if (!edge_port->open) { - dbg("%s - port not opened", __func__); + dev_dbg(&port->dev, "%s - port not opened\n", __func__); return; } @@ -1517,18 +1504,14 @@ static void edge_set_termios(struct tty_struct *tty, unsigned int cflag; cflag = tty->termios->c_cflag; - dbg("%s - clfag %08x iflag %08x", __func__, - tty->termios->c_cflag, tty->termios->c_iflag); - dbg("%s - old clfag %08x old iflag %08x", __func__, - old_termios->c_cflag, old_termios->c_iflag); - - dbg("%s - port %d", __func__, port->number); + dev_dbg(&port->dev, "%s - clfag %08x iflag %08x\n", __func__, tty->termios->c_cflag, tty->termios->c_iflag); + dev_dbg(&port->dev, "%s - old clfag %08x old iflag %08x\n", __func__, old_termios->c_cflag, old_termios->c_iflag); if (edge_port == NULL) return; if (!edge_port->open) { - dbg("%s - port not opened", __func__); + dev_dbg(&port->dev, "%s - port not opened\n", __func__); return; } @@ -1556,7 +1539,7 @@ static int get_lsr_info(struct edgeport_port *edge_port, spin_lock_irqsave(&edge_port->ep_lock, flags); if (edge_port->maxTxCredits == edge_port->txCredits && edge_port->txfifo.count == 0) { - dbg("%s -- Empty", __func__); + dev_dbg(&edge_port->port->dev, "%s -- Empty\n", __func__); result = TIOCSER_TEMT; } spin_unlock_irqrestore(&edge_port->ep_lock, flags); @@ -1573,8 +1556,6 @@ static int edge_tiocmset(struct tty_struct *tty, struct edgeport_port *edge_port = usb_get_serial_port_data(port); unsigned int mcr; - dbg("%s - port %d", __func__, port->number); - mcr = edge_port->shadowMCR; if (set & TIOCM_RTS) mcr |= MCR_RTS; @@ -1605,8 +1586,6 @@ static int edge_tiocmget(struct tty_struct *tty) unsigned int msr; unsigned int mcr; - dbg("%s - port %d", __func__, port->number); - msr = edge_port->shadowMSR; mcr = edge_port->shadowMCR; result = ((mcr & MCR_DTR) ? TIOCM_DTR: 0) /* 0x002 */ @@ -1616,9 +1595,6 @@ static int edge_tiocmget(struct tty_struct *tty) | ((msr & EDGEPORT_MSR_RI) ? TIOCM_RI: 0) /* 0x080 */ | ((msr & EDGEPORT_MSR_DSR) ? TIOCM_DSR: 0); /* 0x100 */ - - dbg("%s -- %x", __func__, result); - return result; } @@ -1642,8 +1618,8 @@ static int edge_get_icount(struct tty_struct *tty, icount->brk = cnow.brk; icount->buf_overrun = cnow.buf_overrun; - dbg("%s (%d) TIOCGICOUNT RX=%d, TX=%d", - __func__, port->number, icount->rx, icount->tx); + dev_dbg(&port->dev, "%s (%d) TIOCGICOUNT RX=%d, TX=%d\n", __func__, + port->number, icount->rx, icount->tx); return 0; } @@ -1686,19 +1662,19 @@ static int edge_ioctl(struct tty_struct *tty, struct async_icount cnow; struct async_icount cprev; - dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); + dev_dbg(&port->dev, "%s - port %d, cmd = 0x%x\n", __func__, port->number, cmd); switch (cmd) { case TIOCSERGETLSR: - dbg("%s (%d) TIOCSERGETLSR", __func__, port->number); + dev_dbg(&port->dev, "%s (%d) TIOCSERGETLSR\n", __func__, port->number); return get_lsr_info(edge_port, (unsigned int __user *) arg); case TIOCGSERIAL: - dbg("%s (%d) TIOCGSERIAL", __func__, port->number); + dev_dbg(&port->dev, "%s (%d) TIOCGSERIAL\n", __func__, port->number); return get_serial_info(edge_port, (struct serial_struct __user *) arg); case TIOCMIWAIT: - dbg("%s (%d) TIOCMIWAIT", __func__, port->number); + dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__, port->number); cprev = edge_port->icount; while (1) { prepare_to_wait(&edge_port->delta_msr_wait, @@ -1745,7 +1721,7 @@ static void edge_break(struct tty_struct *tty, int break_state) /* flush and chase */ edge_port->chaseResponsePending = true; - dbg("%s - Sending IOSP_CMD_CHASE_PORT", __func__); + dev_dbg(&port->dev, "%s - Sending IOSP_CMD_CHASE_PORT\n", __func__); status = send_iosp_ext_cmd(edge_port, IOSP_CMD_CHASE_PORT, 0); if (status == 0) { /* block until chase finished */ @@ -1759,16 +1735,16 @@ static void edge_break(struct tty_struct *tty, int break_state) ((edge_serial->is_epic) && (edge_serial->epic_descriptor.Supports.IOSPSetClrBreak))) { if (break_state == -1) { - dbg("%s - Sending IOSP_CMD_SET_BREAK", __func__); + dev_dbg(&port->dev, "%s - Sending IOSP_CMD_SET_BREAK\n", __func__); status = send_iosp_ext_cmd(edge_port, IOSP_CMD_SET_BREAK, 0); } else { - dbg("%s - Sending IOSP_CMD_CLEAR_BREAK", __func__); + dev_dbg(&port->dev, "%s - Sending IOSP_CMD_CLEAR_BREAK\n", __func__); status = send_iosp_ext_cmd(edge_port, IOSP_CMD_CLEAR_BREAK, 0); } if (status) - dbg("%s - error sending break set/clear command.", + dev_dbg(&port->dev, "%s - error sending break set/clear command.\n", __func__); } } @@ -1781,20 +1757,19 @@ static void edge_break(struct tty_struct *tty, int break_state) static void process_rcvd_data(struct edgeport_serial *edge_serial, unsigned char *buffer, __u16 bufferLength) { + struct device *dev = &edge_serial->serial->dev->dev; struct usb_serial_port *port; struct edgeport_port *edge_port; struct tty_struct *tty; __u16 lastBufferLength; __u16 rxLen; - dbg("%s", __func__); - lastBufferLength = bufferLength + 1; while (bufferLength > 0) { /* failsafe incase we get a message that we don't understand */ if (lastBufferLength == bufferLength) { - dbg("%s - stuck in loop, exiting it.", __func__); + dev_dbg(dev, "%s - stuck in loop, exiting it.\n", __func__); break; } lastBufferLength = bufferLength; @@ -1815,8 +1790,8 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial, ++buffer; --bufferLength; - dbg("%s - Hdr1=%02X Hdr2=%02X", __func__, - edge_serial->rxHeader1, edge_serial->rxHeader2); + dev_dbg(dev, "%s - Hdr1=%02X Hdr2=%02X\n", __func__, + edge_serial->rxHeader1, edge_serial->rxHeader2); /* Process depending on whether this header is * data or status */ @@ -1855,10 +1830,10 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial, IOSP_GET_HDR_DATA_LEN( edge_serial->rxHeader1, edge_serial->rxHeader2); - dbg("%s - Data for Port %u Len %u", - __func__, - edge_serial->rxPort, - edge_serial->rxBytesRemaining); + dev_dbg(dev, "%s - Data for Port %u Len %u\n", + __func__, + edge_serial->rxPort, + edge_serial->rxBytesRemaining); /* ASSERT(DevExt->RxPort < DevExt->NumPorts); * ASSERT(DevExt->RxBytesRemaining < @@ -1896,7 +1871,7 @@ static void process_rcvd_data(struct edgeport_serial *edge_serial, tty = tty_port_tty_get( &edge_port->port->port); if (tty) { - dbg("%s - Sending %d bytes to TTY for port %d", + dev_dbg(dev, "%s - Sending %d bytes to TTY for port %d\n", __func__, rxLen, edge_serial->rxPort); edge_tty_recv(&edge_serial->serial->dev->dev, tty, buffer, rxLen); tty_kref_put(tty); @@ -1935,6 +1910,7 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial, struct usb_serial_port *port; struct edgeport_port *edge_port; struct tty_struct *tty; + struct device *dev; __u8 code = edge_serial->rxStatusCode; /* switch the port pointer to the one being currently talked about */ @@ -1946,16 +1922,15 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial, __func__, edge_serial->rxPort); return; } - - dbg("%s - port %d", __func__, edge_serial->rxPort); + dev = &port->dev; if (code == IOSP_EXT_STATUS) { switch (byte2) { case IOSP_EXT_STATUS_CHASE_RSP: /* we want to do EXT status regardless of port * open/closed */ - dbg("%s - Port %u EXT CHASE_RSP Data = %02x", - __func__, edge_serial->rxPort, byte3); + dev_dbg(dev, "%s - Port %u EXT CHASE_RSP Data = %02x\n", + __func__, edge_serial->rxPort, byte3); /* Currently, the only EXT_STATUS is Chase, so process * here instead of one more call to one more subroutine * If/when more EXT_STATUS, there'll be more work to do @@ -1970,7 +1945,8 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial, return; case IOSP_EXT_STATUS_RX_CHECK_RSP: - dbg("%s ========== Port %u CHECK_RSP Sequence = %02x =============", __func__, edge_serial->rxPort, byte3); + dev_dbg(dev, "%s ========== Port %u CHECK_RSP Sequence = %02x =============\n", + __func__, edge_serial->rxPort, byte3); /* Port->RxCheckRsp = true; */ return; } @@ -1979,7 +1955,8 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial, if (code == IOSP_STATUS_OPEN_RSP) { edge_port->txCredits = GET_TX_BUFFER_SIZE(byte3); edge_port->maxTxCredits = edge_port->txCredits; - dbg("%s - Port %u Open Response Initial MSR = %02x TxBufferSize = %d", __func__, edge_serial->rxPort, byte2, edge_port->txCredits); + dev_dbg(dev, "%s - Port %u Open Response Initial MSR = %02x TxBufferSize = %d\n", + __func__, edge_serial->rxPort, byte2, edge_port->txCredits); handle_new_msr(edge_port, byte2); /* send the current line settings to the port so we are @@ -2008,27 +1985,27 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial, switch (code) { /* Not currently sent by Edgeport */ case IOSP_STATUS_LSR: - dbg("%s - Port %u LSR Status = %02x", - __func__, edge_serial->rxPort, byte2); + dev_dbg(dev, "%s - Port %u LSR Status = %02x\n", + __func__, edge_serial->rxPort, byte2); handle_new_lsr(edge_port, false, byte2, 0); break; case IOSP_STATUS_LSR_DATA: - dbg("%s - Port %u LSR Status = %02x, Data = %02x", - __func__, edge_serial->rxPort, byte2, byte3); + dev_dbg(dev, "%s - Port %u LSR Status = %02x, Data = %02x\n", + __func__, edge_serial->rxPort, byte2, byte3); /* byte2 is LSR Register */ /* byte3 is broken data byte */ handle_new_lsr(edge_port, true, byte2, byte3); break; /* * case IOSP_EXT_4_STATUS: - * dbg("%s - Port %u LSR Status = %02x Data = %02x", + * dev_dbg(dev, "%s - Port %u LSR Status = %02x Data = %02x\n", * __func__, edge_serial->rxPort, byte2, byte3); * break; */ case IOSP_STATUS_MSR: - dbg("%s - Port %u MSR Status = %02x", - __func__, edge_serial->rxPort, byte2); + dev_dbg(dev, "%s - Port %u MSR Status = %02x\n", + __func__, edge_serial->rxPort, byte2); /* * Process this new modem status and generate appropriate * events, etc, based on the new status. This routine @@ -2038,7 +2015,7 @@ static void process_rcvd_status(struct edgeport_serial *edge_serial, break; default: - dbg("%s - Unrecognized IOSP status code %u", __func__, code); + dev_dbg(dev, "%s - Unrecognized IOSP status code %u\n", __func__, code); break; } } @@ -2073,8 +2050,6 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr) { struct async_icount *icount; - dbg("%s %02x", __func__, newMsr); - if (newMsr & (EDGEPORT_MSR_DELTA_CTS | EDGEPORT_MSR_DELTA_DSR | EDGEPORT_MSR_DELTA_RI | EDGEPORT_MSR_DELTA_CD)) { icount = &edge_port->icount; @@ -2107,8 +2082,6 @@ static void handle_new_lsr(struct edgeport_port *edge_port, __u8 lsrData, (LSR_OVER_ERR | LSR_PAR_ERR | LSR_FRM_ERR | LSR_BREAK)); struct async_icount *icount; - dbg("%s - %02x", __func__, newLsr); - edge_port->shadowLSR = lsr; if (newLsr & LSR_BREAK) { @@ -2156,7 +2129,7 @@ static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 current_length; unsigned char *transfer_buffer; - dbg("%s - %x, %x, %d", __func__, extAddr, addr, length); + dev_dbg(&serial->dev->dev, "%s - %x, %x, %d\n", __func__, extAddr, addr, length); transfer_buffer = kmalloc(64, GFP_KERNEL); if (!transfer_buffer) { @@ -2173,8 +2146,7 @@ static int sram_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, else current_length = length; -/* dbg("%s - writing %x, %x, %d", __func__, - extAddr, addr, current_length); */ +/* dev_dbg(&serial->dev->dev, "%s - writing %x, %x, %d\n", __func__, extAddr, addr, current_length); */ memcpy(transfer_buffer, data, current_length); result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), @@ -2207,8 +2179,6 @@ static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, __u16 current_length; unsigned char *transfer_buffer; -/* dbg("%s - %x, %x, %d", __func__, extAddr, addr, length); */ - transfer_buffer = kmalloc(64, GFP_KERNEL); if (!transfer_buffer) { dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", @@ -2223,8 +2193,6 @@ static int rom_write(struct usb_serial *serial, __u16 extAddr, __u16 addr, current_length = 64; else current_length = length; -/* dbg("%s - writing %x, %x, %d", __func__, - extAddr, addr, current_length); */ memcpy(transfer_buffer, data, current_length); result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), @@ -2257,8 +2225,6 @@ static int rom_read(struct usb_serial *serial, __u16 extAddr, __u16 current_length; unsigned char *transfer_buffer; - dbg("%s - %x, %x, %d", __func__, extAddr, addr, length); - transfer_buffer = kmalloc(64, GFP_KERNEL); if (!transfer_buffer) { dev_err(&serial->dev->dev, @@ -2273,8 +2239,6 @@ static int rom_read(struct usb_serial *serial, __u16 extAddr, current_length = 64; else current_length = length; -/* dbg("%s - %x, %x, %d", __func__, - extAddr, addr, current_length); */ result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), USB_REQUEST_ION_READ_ROM, @@ -2305,8 +2269,6 @@ static int send_iosp_ext_cmd(struct edgeport_port *edge_port, int length = 0; int status = 0; - dbg("%s - %d, %d", __func__, command, param); - buffer = kmalloc(10, GFP_ATOMIC); if (!buffer) { dev_err(&edge_port->port->dev, @@ -2339,11 +2301,11 @@ static int write_cmd_usb(struct edgeport_port *edge_port, { struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial); + struct device *dev = &edge_port->port->dev; int status = 0; struct urb *urb; - usb_serial_debug_data(debug, &edge_port->port->dev, - __func__, length, buffer); + usb_serial_debug_data(debug, dev, __func__, length, buffer); /* Allocate our next urb */ urb = usb_alloc_urb(0, GFP_ATOMIC); @@ -2351,8 +2313,8 @@ static int write_cmd_usb(struct edgeport_port *edge_port, return -ENOMEM; atomic_inc(&CmdUrbs); - dbg("%s - ALLOCATE URB %p (outstanding %d)", - __func__, urb, atomic_read(&CmdUrbs)); + dev_dbg(dev, "%s - ALLOCATE URB %p (outstanding %d)\n", + __func__, urb, atomic_read(&CmdUrbs)); usb_fill_bulk_urb(urb, edge_serial->serial->dev, usb_sndbulkpipe(edge_serial->serial->dev, @@ -2364,9 +2326,8 @@ static int write_cmd_usb(struct edgeport_port *edge_port, if (status) { /* something went wrong */ - dev_err(&edge_port->port->dev, - "%s - usb_submit_urb(write command) failed, status = %d\n", - __func__, status); + dev_err(dev, "%s - usb_submit_urb(write command) failed, status = %d\n", + __func__, status); usb_kill_urb(urb); usb_free_urb(urb); atomic_dec(&CmdUrbs); @@ -2378,7 +2339,7 @@ static int write_cmd_usb(struct edgeport_port *edge_port, if (edge_port->commandPending) { /* command timed out */ - dbg("%s - command timed out", __func__); + dev_dbg(dev, "%s - command timed out\n", __func__); status = -EINVAL; } #endif @@ -2396,6 +2357,7 @@ static int send_cmd_write_baud_rate(struct edgeport_port *edge_port, { struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial); + struct device *dev = &edge_port->port->dev; unsigned char *cmdBuffer; unsigned char *currCmd; int cmdLen = 0; @@ -2406,26 +2368,24 @@ static int send_cmd_write_baud_rate(struct edgeport_port *edge_port, if (edge_serial->is_epic && !edge_serial->epic_descriptor.Supports.IOSPSetBaudRate) { - dbg("SendCmdWriteBaudRate - NOT Setting baud rate for port = %d, baud = %d", - edge_port->port->number, baudRate); + dev_dbg(dev, "SendCmdWriteBaudRate - NOT Setting baud rate for port = %d, baud = %d\n", + edge_port->port->number, baudRate); return 0; } - dbg("%s - port = %d, baud = %d", __func__, - edge_port->port->number, baudRate); + dev_dbg(dev, "%s - port = %d, baud = %d\n", __func__, + edge_port->port->number, baudRate); - status = calc_baud_rate_divisor(baudRate, &divisor); + status = calc_baud_rate_divisor(dev, baudRate, &divisor); if (status) { - dev_err(&edge_port->port->dev, "%s - bad baud rate\n", - __func__); + dev_err(dev, "%s - bad baud rate\n", __func__); return status; } /* Alloc memory for the string of commands. */ cmdBuffer = kmalloc(0x100, GFP_ATOMIC); if (!cmdBuffer) { - dev_err(&edge_port->port->dev, - "%s - kmalloc(%d) failed.\n", __func__, 0x100); + dev_err(dev, "%s - kmalloc(%d) failed.\n", __func__, 0x100); return -ENOMEM; } currCmd = cmdBuffer; @@ -2456,14 +2416,11 @@ static int send_cmd_write_baud_rate(struct edgeport_port *edge_port, * this function calculates the proper baud rate divisor for the specified * baud rate. *****************************************************************************/ -static int calc_baud_rate_divisor(int baudrate, int *divisor) +static int calc_baud_rate_divisor(struct device *dev, int baudrate, int *divisor) { int i; __u16 custom; - - dbg("%s - %d", __func__, baudrate); - for (i = 0; i < ARRAY_SIZE(divisor_table); i++) { if (divisor_table[i].BaudRate == baudrate) { *divisor = divisor_table[i].Divisor; @@ -2480,7 +2437,7 @@ static int calc_baud_rate_divisor(int baudrate, int *divisor) *divisor = custom; - dbg("%s - Baud %d = %d", __func__, baudrate, custom); + dev_dbg(dev, "%s - Baud %d = %d\n", __func__, baudrate, custom); return 0; } @@ -2497,25 +2454,26 @@ static int send_cmd_write_uart_register(struct edgeport_port *edge_port, { struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial); + struct device *dev = &edge_port->port->dev; unsigned char *cmdBuffer; unsigned char *currCmd; unsigned long cmdLen = 0; int status; - dbg("%s - write to %s register 0x%02x", - (regNum == MCR) ? "MCR" : "LCR", __func__, regValue); + dev_dbg(dev, "%s - write to %s register 0x%02x\n", + (regNum == MCR) ? "MCR" : "LCR", __func__, regValue); if (edge_serial->is_epic && !edge_serial->epic_descriptor.Supports.IOSPWriteMCR && regNum == MCR) { - dbg("SendCmdWriteUartReg - Not writing to MCR Register"); + dev_dbg(dev, "SendCmdWriteUartReg - Not writing to MCR Register\n"); return 0; } if (edge_serial->is_epic && !edge_serial->epic_descriptor.Supports.IOSPWriteLCR && regNum == LCR) { - dbg("SendCmdWriteUartReg - Not writing to LCR Register"); + dev_dbg(dev, "SendCmdWriteUartReg - Not writing to LCR Register\n"); return 0; } @@ -2550,6 +2508,7 @@ static int send_cmd_write_uart_register(struct edgeport_port *edge_port, static void change_port_settings(struct tty_struct *tty, struct edgeport_port *edge_port, struct ktermios *old_termios) { + struct device *dev = &edge_port->port->dev; struct edgeport_serial *edge_serial = usb_get_serial_data(edge_port->port->serial); int baud; @@ -2562,11 +2521,11 @@ static void change_port_settings(struct tty_struct *tty, __u8 txFlow; int status; - dbg("%s - port %d", __func__, edge_port->port->number); + dev_dbg(dev, "%s - port %d\n", __func__, edge_port->port->number); if (!edge_port->open && !edge_port->openPending) { - dbg("%s - port not opened", __func__); + dev_dbg(dev, "%s - port not opened\n", __func__); return; } @@ -2575,20 +2534,20 @@ static void change_port_settings(struct tty_struct *tty, switch (cflag & CSIZE) { case CS5: lData = LCR_BITS_5; mask = 0x1f; - dbg("%s - data bits = 5", __func__); + dev_dbg(dev, "%s - data bits = 5\n", __func__); break; case CS6: lData = LCR_BITS_6; mask = 0x3f; - dbg("%s - data bits = 6", __func__); + dev_dbg(dev, "%s - data bits = 6\n", __func__); break; case CS7: lData = LCR_BITS_7; mask = 0x7f; - dbg("%s - data bits = 7", __func__); + dev_dbg(dev, "%s - data bits = 7\n", __func__); break; default: case CS8: lData = LCR_BITS_8; - dbg("%s - data bits = 8", __func__); + dev_dbg(dev, "%s - data bits = 8\n", __func__); break; } @@ -2597,28 +2556,28 @@ static void change_port_settings(struct tty_struct *tty, if (cflag & CMSPAR) { if (cflag & PARODD) { lParity = LCR_PAR_MARK; - dbg("%s - parity = mark", __func__); + dev_dbg(dev, "%s - parity = mark\n", __func__); } else { lParity = LCR_PAR_SPACE; - dbg("%s - parity = space", __func__); + dev_dbg(dev, "%s - parity = space\n", __func__); } } else if (cflag & PARODD) { lParity = LCR_PAR_ODD; - dbg("%s - parity = odd", __func__); + dev_dbg(dev, "%s - parity = odd\n", __func__); } else { lParity = LCR_PAR_EVEN; - dbg("%s - parity = even", __func__); + dev_dbg(dev, "%s - parity = even\n", __func__); } } else { - dbg("%s - parity = none", __func__); + dev_dbg(dev, "%s - parity = none\n", __func__); } if (cflag & CSTOPB) { lStop = LCR_STOP_2; - dbg("%s - stop bits = 2", __func__); + dev_dbg(dev, "%s - stop bits = 2\n", __func__); } else { lStop = LCR_STOP_1; - dbg("%s - stop bits = 1", __func__); + dev_dbg(dev, "%s - stop bits = 1\n", __func__); } /* figure out the flow control settings */ @@ -2626,9 +2585,9 @@ static void change_port_settings(struct tty_struct *tty, if (cflag & CRTSCTS) { rxFlow |= IOSP_RX_FLOW_RTS; txFlow |= IOSP_TX_FLOW_CTS; - dbg("%s - RTS/CTS is enabled", __func__); + dev_dbg(dev, "%s - RTS/CTS is enabled\n", __func__); } else { - dbg("%s - RTS/CTS is disabled", __func__); + dev_dbg(dev, "%s - RTS/CTS is disabled\n", __func__); } /* if we are implementing XON/XOFF, set the start and stop character @@ -2649,19 +2608,19 @@ static void change_port_settings(struct tty_struct *tty, /* if we are implementing INBOUND XON/XOFF */ if (I_IXOFF(tty)) { rxFlow |= IOSP_RX_FLOW_XON_XOFF; - dbg("%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", - __func__, start_char, stop_char); + dev_dbg(dev, "%s - INBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x\n", + __func__, start_char, stop_char); } else { - dbg("%s - INBOUND XON/XOFF is disabled", __func__); + dev_dbg(dev, "%s - INBOUND XON/XOFF is disabled\n", __func__); } /* if we are implementing OUTBOUND XON/XOFF */ if (I_IXON(tty)) { txFlow |= IOSP_TX_FLOW_XON_XOFF; - dbg("%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x", - __func__, start_char, stop_char); + dev_dbg(dev, "%s - OUTBOUND XON/XOFF is enabled, XON = %2x, XOFF = %2x\n", + __func__, start_char, stop_char); } else { - dbg("%s - OUTBOUND XON/XOFF is disabled", __func__); + dev_dbg(dev, "%s - OUTBOUND XON/XOFF is disabled\n", __func__); } } @@ -2704,7 +2663,7 @@ static void change_port_settings(struct tty_struct *tty, baud = 9600; } - dbg("%s - baud rate = %d", __func__, baud); + dev_dbg(dev, "%s - baud rate = %d\n", __func__, baud); status = send_cmd_write_baud_rate(edge_port, baud); if (status == -1) { /* Speed change was not possible - put back the old speed */ @@ -2746,9 +2705,10 @@ static void unicode_to_ascii(char *string, int buflen, ****************************************************************************/ static void get_manufacturing_desc(struct edgeport_serial *edge_serial) { + struct device *dev = &edge_serial->serial->dev->dev; int response; - dbg("getting manufacturer descriptor"); + dev_dbg(dev, "getting manufacturer descriptor\n"); response = rom_read(edge_serial->serial, (EDGE_MANUF_DESC_ADDR & 0xffff0000) >> 16, @@ -2757,42 +2717,41 @@ static void get_manufacturing_desc(struct edgeport_serial *edge_serial) (__u8 *)(&edge_serial->manuf_descriptor)); if (response < 1) - dev_err(&edge_serial->serial->dev->dev, - "error in getting manufacturer descriptor\n"); + dev_err(dev, "error in getting manufacturer descriptor\n"); else { char string[30]; - dbg("**Manufacturer Descriptor"); - dbg(" RomSize: %dK", + dev_dbg(dev, "**Manufacturer Descriptor\n"); + dev_dbg(dev, " RomSize: %dK\n", edge_serial->manuf_descriptor.RomSize); - dbg(" RamSize: %dK", + dev_dbg(dev, " RamSize: %dK\n", edge_serial->manuf_descriptor.RamSize); - dbg(" CpuRev: %d", + dev_dbg(dev, " CpuRev: %d\n", edge_serial->manuf_descriptor.CpuRev); - dbg(" BoardRev: %d", + dev_dbg(dev, " BoardRev: %d\n", edge_serial->manuf_descriptor.BoardRev); - dbg(" NumPorts: %d", + dev_dbg(dev, " NumPorts: %d\n", edge_serial->manuf_descriptor.NumPorts); - dbg(" DescDate: %d/%d/%d", + dev_dbg(dev, " DescDate: %d/%d/%d\n", edge_serial->manuf_descriptor.DescDate[0], edge_serial->manuf_descriptor.DescDate[1], edge_serial->manuf_descriptor.DescDate[2]+1900); unicode_to_ascii(string, sizeof(string), edge_serial->manuf_descriptor.SerialNumber, edge_serial->manuf_descriptor.SerNumLength/2); - dbg(" SerialNumber: %s", string); + dev_dbg(dev, " SerialNumber: %s\n", string); unicode_to_ascii(string, sizeof(string), edge_serial->manuf_descriptor.AssemblyNumber, edge_serial->manuf_descriptor.AssemblyNumLength/2); - dbg(" AssemblyNumber: %s", string); + dev_dbg(dev, " AssemblyNumber: %s\n", string); unicode_to_ascii(string, sizeof(string), edge_serial->manuf_descriptor.OemAssyNumber, edge_serial->manuf_descriptor.OemAssyNumLength/2); - dbg(" OemAssyNumber: %s", string); - dbg(" UartType: %d", + dev_dbg(dev, " OemAssyNumber: %s\n", string); + dev_dbg(dev, " UartType: %d\n", edge_serial->manuf_descriptor.UartType); - dbg(" IonPid: %d", + dev_dbg(dev, " IonPid: %d\n", edge_serial->manuf_descriptor.IonPid); - dbg(" IonConfig: %d", + dev_dbg(dev, " IonConfig: %d\n", edge_serial->manuf_descriptor.IonConfig); } } @@ -2805,9 +2764,10 @@ static void get_manufacturing_desc(struct edgeport_serial *edge_serial) ****************************************************************************/ static void get_boot_desc(struct edgeport_serial *edge_serial) { + struct device *dev = &edge_serial->serial->dev->dev; int response; - dbg("getting boot descriptor"); + dev_dbg(dev, "getting boot descriptor\n"); response = rom_read(edge_serial->serial, (EDGE_BOOT_DESC_ADDR & 0xffff0000) >> 16, @@ -2816,23 +2776,22 @@ static void get_boot_desc(struct edgeport_serial *edge_serial) (__u8 *)(&edge_serial->boot_descriptor)); if (response < 1) - dev_err(&edge_serial->serial->dev->dev, - "error in getting boot descriptor\n"); + dev_err(dev, "error in getting boot descriptor\n"); else { - dbg("**Boot Descriptor:"); - dbg(" BootCodeLength: %d", - le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength)); - dbg(" MajorVersion: %d", + dev_dbg(dev, "**Boot Descriptor:\n"); + dev_dbg(dev, " BootCodeLength: %d\n", + le16_to_cpu(edge_serial->boot_descriptor.BootCodeLength)); + dev_dbg(dev, " MajorVersion: %d\n", edge_serial->boot_descriptor.MajorVersion); - dbg(" MinorVersion: %d", + dev_dbg(dev, " MinorVersion: %d\n", edge_serial->boot_descriptor.MinorVersion); - dbg(" BuildNumber: %d", + dev_dbg(dev, " BuildNumber: %d\n", le16_to_cpu(edge_serial->boot_descriptor.BuildNumber)); - dbg(" Capabilities: 0x%x", + dev_dbg(dev, " Capabilities: 0x%x\n", le16_to_cpu(edge_serial->boot_descriptor.Capabilities)); - dbg(" UConfig0: %d", + dev_dbg(dev, " UConfig0: %d\n", edge_serial->boot_descriptor.UConfig0); - dbg(" UConfig1: %d", + dev_dbg(dev, " UConfig1: %d\n", edge_serial->boot_descriptor.UConfig1); } } @@ -2844,6 +2803,7 @@ static void get_boot_desc(struct edgeport_serial *edge_serial) ****************************************************************************/ static void load_application_firmware(struct edgeport_serial *edge_serial) { + struct device *dev = &edge_serial->serial->dev->dev; const struct ihex_binrec *rec; const struct firmware *fw; const char *fw_name; @@ -2864,7 +2824,7 @@ static void load_application_firmware(struct edgeport_serial *edge_serial) break; case EDGE_DOWNLOAD_FILE_NONE: - dbg("No download file specified, skipping download"); + dev_dbg(dev, "No download file specified, skipping download\n"); return; default: @@ -2874,7 +2834,7 @@ static void load_application_firmware(struct edgeport_serial *edge_serial) response = request_ihex_firmware(&fw, fw_name, &edge_serial->serial->dev->dev); if (response) { - printk(KERN_ERR "Failed to load image \"%s\" err %d\n", + dev_err(dev, "Failed to load image \"%s\" err %d\n", fw_name, response); return; } @@ -2882,7 +2842,7 @@ static void load_application_firmware(struct edgeport_serial *edge_serial) rec = (const struct ihex_binrec *)fw->data; build = (rec->data[2] << 8) | rec->data[3]; - dbg("%s %d.%d.%d", fw_info, rec->data[0], rec->data[1], build); + dev_dbg(dev, "%s %d.%d.%d\n", fw_info, rec->data[0], rec->data[1], build); edge_serial->product_info.FirmwareMajorVersion = rec->data[0]; edge_serial->product_info.FirmwareMinorVersion = rec->data[1]; @@ -2905,10 +2865,10 @@ static void load_application_firmware(struct edgeport_serial *edge_serial) } } - dbg("sending exec_dl_code"); - response = usb_control_msg (edge_serial->serial->dev, - usb_sndctrlpipe(edge_serial->serial->dev, 0), - USB_REQUEST_ION_EXEC_DL_CODE, + dev_dbg(dev, "sending exec_dl_code\n"); + response = usb_control_msg (edge_serial->serial->dev, + usb_sndctrlpipe(edge_serial->serial->dev, 0), + USB_REQUEST_ION_EXEC_DL_CODE, 0x40, 0x4000, 0x0001, NULL, 0, 3000); release_firmware(fw); @@ -2923,6 +2883,7 @@ static int edge_startup(struct usb_serial *serial) struct edgeport_serial *edge_serial; struct edgeport_port *edge_port; struct usb_device *dev; + struct device *ddev = &serial->dev->dev; int i, j; int response; bool interrupt_in_found; @@ -2974,32 +2935,31 @@ static int edge_startup(struct usb_serial *serial) /* serial->num_ports = serial->product_info.NumPorts; */ if ((!edge_serial->is_epic) && (edge_serial->product_info.NumPorts != serial->num_ports)) { - dev_warn(&serial->dev->dev, "Device Reported %d serial ports " - "vs. core thinking we have %d ports, email " - "greg@kroah.com this information.\n", + dev_warn(ddev, + "Device Reported %d serial ports vs. core thinking we have %d ports, email greg@kroah.com this information.\n", edge_serial->product_info.NumPorts, serial->num_ports); } - dbg("%s - time 1 %ld", __func__, jiffies); + dev_dbg(ddev, "%s - time 1 %ld\n", __func__, jiffies); /* If not an EPiC device */ if (!edge_serial->is_epic) { /* now load the application firmware into this device */ load_application_firmware(edge_serial); - dbg("%s - time 2 %ld", __func__, jiffies); + dev_dbg(ddev, "%s - time 2 %ld\n", __func__, jiffies); /* Check current Edgeport EEPROM and update if necessary */ update_edgeport_E2PROM(edge_serial); - dbg("%s - time 3 %ld", __func__, jiffies); + dev_dbg(ddev, "%s - time 3 %ld\n", __func__, jiffies); /* set the configuration to use #1 */ -/* dbg("set_configuration 1"); */ +/* dev_dbg(ddev, "set_configuration 1\n"); */ /* usb_set_configuration (dev, 1); */ } - dbg(" FirmwareMajorVersion %d.%d.%d", + dev_dbg(ddev, " FirmwareMajorVersion %d.%d.%d\n", edge_serial->product_info.FirmwareMajorVersion, edge_serial->product_info.FirmwareMinorVersion, le16_to_cpu(edge_serial->product_info.FirmwareBuildNumber)); @@ -3011,8 +2971,7 @@ static int edge_startup(struct usb_serial *serial) for (i = 0; i < serial->num_ports; ++i) { edge_port = kzalloc(sizeof(struct edgeport_port), GFP_KERNEL); if (edge_port == NULL) { - dev_err(&serial->dev->dev, "%s - Out of memory\n", - __func__); + dev_err(ddev, "%s - Out of memory\n", __func__); for (j = 0; j < i; ++j) { kfree(usb_get_serial_port_data(serial->port[j])); usb_set_serial_port_data(serial->port[j], @@ -3044,19 +3003,19 @@ static int edge_startup(struct usb_serial *serial) if (!interrupt_in_found && (usb_endpoint_is_int_in(endpoint))) { /* we found a interrupt in endpoint */ - dbg("found interrupt in"); + dev_dbg(ddev, "found interrupt in\n"); /* not set up yet, so do it now */ edge_serial->interrupt_read_urb = usb_alloc_urb(0, GFP_KERNEL); if (!edge_serial->interrupt_read_urb) { - dev_err(&dev->dev, "out of memory\n"); + dev_err(ddev, "out of memory\n"); return -ENOMEM; } edge_serial->interrupt_in_buffer = kmalloc(buffer_size, GFP_KERNEL); if (!edge_serial->interrupt_in_buffer) { - dev_err(&dev->dev, "out of memory\n"); + dev_err(ddev, "out of memory\n"); usb_free_urb(edge_serial->interrupt_read_urb); return -ENOMEM; } @@ -3081,13 +3040,13 @@ static int edge_startup(struct usb_serial *serial) if (!bulk_in_found && (usb_endpoint_is_bulk_in(endpoint))) { /* we found a bulk in endpoint */ - dbg("found bulk in"); + dev_dbg(ddev, "found bulk in\n"); /* not set up yet, so do it now */ edge_serial->read_urb = usb_alloc_urb(0, GFP_KERNEL); if (!edge_serial->read_urb) { - dev_err(&dev->dev, "out of memory\n"); + dev_err(ddev, "out of memory\n"); return -ENOMEM; } edge_serial->bulk_in_buffer = @@ -3114,7 +3073,7 @@ static int edge_startup(struct usb_serial *serial) if (!bulk_out_found && (usb_endpoint_is_bulk_out(endpoint))) { /* we found a bulk out endpoint */ - dbg("found bulk out"); + dev_dbg(ddev, "found bulk out\n"); edge_serial->bulk_out_endpoint = endpoint->bEndpointAddress; bulk_out_found = true; @@ -3122,8 +3081,7 @@ static int edge_startup(struct usb_serial *serial) } if (!interrupt_in_found || !bulk_in_found || !bulk_out_found) { - dev_err(&dev->dev, "Error - the proper endpoints " - "were not found!\n"); + dev_err(ddev, "Error - the proper endpoints were not found!\n"); return -ENODEV; } @@ -3132,8 +3090,7 @@ static int edge_startup(struct usb_serial *serial) response = usb_submit_urb(edge_serial->interrupt_read_urb, GFP_KERNEL); if (response) - dev_err(&dev->dev, - "%s - Error %d submitting control urb\n", + dev_err(ddev, "%s - Error %d submitting control urb\n", __func__, response); } return response; @@ -3148,8 +3105,6 @@ static void edge_disconnect(struct usb_serial *serial) { struct edgeport_serial *edge_serial = usb_get_serial_data(serial); - dbg("%s", __func__); - /* stop reads and writes on all ports */ /* free up our endpoint stuff */ if (edge_serial->is_epic) { @@ -3173,8 +3128,6 @@ static void edge_release(struct usb_serial *serial) struct edgeport_serial *edge_serial = usb_get_serial_data(serial); int i; - dbg("%s", __func__); - for (i = 0; i < serial->num_ports; ++i) kfree(usb_get_serial_port_data(serial->port[i])); -- cgit v0.10.2 From e8656b02ef353e73d0625302c85026f80958c531 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 01:35:12 -0700 Subject: USB: serial: serqt_usb2: remove dbg() usage dbg() was a very old USB-serial-specific macro. This patch removes it from being used in the driver and uses dev_dbg() instead. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c index 8a362f7..b1e8b9d 100644 --- a/drivers/staging/serqt_usb2/serqt_usb2.c +++ b/drivers/staging/serqt_usb2/serqt_usb2.c @@ -184,11 +184,11 @@ static int port_paranoia_check(struct usb_serial_port *port, const char *function) { if (!port) { - dbg("%s - port == NULL", function); + pr_debug("%s - port == NULL", function); return -1; } if (!port->serial) { - dbg("%s - port->serial == NULL\n", function); + pr_debug("%s - port->serial == NULL\n", function); return -1; } @@ -199,12 +199,12 @@ static int serial_paranoia_check(struct usb_serial *serial, const char *function) { if (!serial) { - dbg("%s - serial == NULL\n", function); + pr_debug("%s - serial == NULL\n", function); return -1; } if (!serial->type) { - dbg("%s - serial->type == NULL!", function); + pr_debug("%s - serial->type == NULL!", function); return -1; } @@ -276,7 +276,7 @@ static void qt_write_bulk_callback(struct urb *urb) status = urb->status; if (status) { - dbg("nonzero write bulk status received:%d\n", status); + dev_dbg(&urb->dev->dev, "nonzero write bulk status received:%d\n", status); return; } @@ -309,16 +309,14 @@ static void qt_read_bulk_callback(struct urb *urb) if (urb->status) { qt_port->ReadBulkStopped = 1; - dbg("%s - nonzero write bulk status received: %d\n", - __func__, urb->status); + dev_dbg(&urb->dev->dev, "%s - nonzero write bulk status received: %d\n", + __func__, urb->status); return; } tty = tty_port_tty_get(&port->port); - if (!tty) { - dbg("%s - bad tty pointer - exiting", __func__); + if (!tty) return; - } data = urb->transfer_buffer; @@ -327,21 +325,19 @@ static void qt_read_bulk_callback(struct urb *urb) /* index = MINOR(port->tty->device) - serial->minor; */ index = tty->index - serial->minor; - dbg("%s - port->RxHolding = %d\n", __func__, qt_port->RxHolding); + dev_dbg(&port->dev, "%s - port->RxHolding = %d\n", __func__, qt_port->RxHolding); if (port_paranoia_check(port, __func__) != 0) { - dbg("%s - port_paranoia_check, exiting\n", __func__); qt_port->ReadBulkStopped = 1; goto exit; } - if (!serial) { - dbg("%s - bad serial pointer, exiting\n", __func__); + if (!serial) goto exit; - } + if (qt_port->closePending == 1) { /* Were closing , stop reading */ - dbg("%s - (qt_port->closepending == 1\n", __func__); + dev_dbg(&port->dev, "%s - (qt_port->closepending == 1\n", __func__); qt_port->ReadBulkStopped = 1; goto exit; } @@ -359,8 +355,8 @@ static void qt_read_bulk_callback(struct urb *urb) if (urb->status) { qt_port->ReadBulkStopped = 1; - dbg("%s - nonzero read bulk status received: %d\n", - __func__, urb->status); + dev_dbg(&port->dev, "%s - nonzero read bulk status received: %d\n", + __func__, urb->status); goto exit; } @@ -375,7 +371,7 @@ static void qt_read_bulk_callback(struct urb *urb) case 0x00: /* line status change 4th byte must follow */ if (i > (RxCount - 4)) { - dbg("Illegal escape seuences in received data\n"); + dev_dbg(&port->dev, "Illegal escape seuences in received data\n"); break; } ProcessLineStatus(qt_port, data[i + 3]); @@ -385,9 +381,9 @@ static void qt_read_bulk_callback(struct urb *urb) case 0x01: /* Modem status status change 4th byte must follow */ - dbg("Modem status status.\n"); + dev_dbg(&port->dev, "Modem status status.\n"); if (i > (RxCount - 4)) { - dbg("Illegal escape sequences in received data\n"); + dev_dbg(&port->dev, "Illegal escape sequences in received data\n"); break; } ProcessModemStatus(qt_port, @@ -396,7 +392,7 @@ static void qt_read_bulk_callback(struct urb *urb) flag = 1; break; case 0xff: - dbg("No status sequence.\n"); + dev_dbg(&port->dev, "No status sequence.\n"); if (tty) { ProcessRxChar(tty, port, data[i]); @@ -425,8 +421,8 @@ static void qt_read_bulk_callback(struct urb *urb) qt_read_bulk_callback, port); result = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (result) - dbg("%s - failed resubmitting read urb, error %d", - __func__, result); + dev_dbg(&port->dev, "%s - failed resubmitting read urb, error %d", + __func__, result); else { if (tty && RxCount) { tty_flip_buffer_push(tty); @@ -521,7 +517,6 @@ static int qt_set_device(struct usb_serial *serial, PortSettings += ((__u16) (device_data->porta)); length = sizeof(struct qt_get_device_data); - dbg("%s - PortSettings = 0x%x\n", __func__, PortSettings); result = usb_control_msg(serial->dev, usb_sndctrlpipe(serial->dev, 0), QT_SET_GET_DEVICE, 0x40, PortSettings, @@ -695,6 +690,7 @@ static int BoxDisable_SW_FlowCtrl(struct usb_serial *serial, __u16 index) static int qt_startup(struct usb_serial *serial) { + struct device *dev = &serial->dev->dev; struct usb_serial_port *port; struct quatech_port *qt_port; struct qt_get_device_data DeviceData; @@ -706,8 +702,6 @@ static int qt_startup(struct usb_serial *serial) port = serial->port[i]; qt_port = kzalloc(sizeof(*qt_port), GFP_KERNEL); if (!qt_port) { - dbg("%s: kmalloc for quatech_port (%d) failed!.", - __func__, i); for (--i; i >= 0; i--) { port = serial->port[i]; kfree(usb_get_serial_port_data(port)); @@ -722,25 +716,23 @@ static int qt_startup(struct usb_serial *serial) } status = qt_get_device(serial, &DeviceData); - if (status < 0) { - dbg(__FILE__ "box_get_device failed"); + if (status < 0) goto startup_error; - } - dbg(__FILE__ "DeviceData.portb = 0x%x", DeviceData.portb); + dev_dbg(dev, "DeviceData.portb = 0x%x\n", DeviceData.portb); DeviceData.portb &= ~FULLPWRBIT; - dbg(__FILE__ "Changing DeviceData.portb to 0x%x", DeviceData.portb); + dev_dbg(dev, "Changing DeviceData.portb to 0x%x\n", DeviceData.portb); status = qt_set_device(serial, &DeviceData); if (status < 0) { - dbg(__FILE__ "qt_set_device failed\n"); + dev_dbg(dev, "qt_set_device failed\n"); goto startup_error; } status = qt_get_device(serial, &DeviceData); if (status < 0) { - dbg(__FILE__ "qt_get_device failed"); + dev_dbg(dev, "qt_get_device failed\n"); goto startup_error; } @@ -784,29 +776,27 @@ static int qt_startup(struct usb_serial *serial) status = BoxSetPrebufferLevel(serial); /* sets to default value */ if (status < 0) { - dbg(__FILE__ "BoxSetPrebufferLevel failed\n"); + dev_dbg(dev, "BoxSetPrebufferLevel failed\n"); goto startup_error; } status = BoxSetATC(serial, ATC_DISABLED); if (status < 0) { - dbg(__FILE__ "BoxSetATC failed\n"); + dev_dbg(dev, "BoxSetATC failed\n"); goto startup_error; } - dbg(__FILE__ "DeviceData.portb = 0x%x", DeviceData.portb); + dev_dbg(dev, "DeviceData.portb = 0x%x\n", DeviceData.portb); DeviceData.portb |= NEXT_BOARD_POWER_BIT; - dbg(__FILE__ "Changing DeviceData.portb to 0x%x", DeviceData.portb); + dev_dbg(dev, "Changing DeviceData.portb to 0x%x\n", DeviceData.portb); status = qt_set_device(serial, &DeviceData); if (status < 0) { - dbg(__FILE__ "qt_set_device failed\n"); + dev_dbg(dev, "qt_set_device failed\n"); goto startup_error; } - dbg("Exit Success %s\n", __func__); - return 0; startup_error: @@ -817,8 +807,6 @@ startup_error: usb_set_serial_port_data(port, NULL); } - dbg("Exit fail %s\n", __func__); - return -EIO; } @@ -873,10 +861,10 @@ static int qt_open(struct tty_struct *tty, /* Port specific setups */ result = qt_open_channel(serial, port->number, &ChannelData); if (result < 0) { - dbg(__FILE__ "qt_open_channel failed\n"); + dev_dbg(&port->dev, "qt_open_channel failed\n"); return result; } - dbg(__FILE__ "qt_open_channel completed.\n"); + dev_dbg(&port->dev, "qt_open_channel completed.\n"); /* FIXME: are these needed? Does it even do anything useful? */ quatech_port->shadowLSR = ChannelData.line_status & @@ -888,10 +876,10 @@ static int qt_open(struct tty_struct *tty, /* Set Baud rate to default and turn off (default)flow control here */ result = qt_setuart(serial, port->number, DEFAULT_DIVISOR, DEFAULT_LCR); if (result < 0) { - dbg(__FILE__ "qt_setuart failed\n"); + dev_dbg(&port->dev, "qt_setuart failed\n"); return result; } - dbg(__FILE__ "qt_setuart completed.\n"); + dev_dbg(&port->dev, "qt_setuart completed.\n"); /* * Put this here to make it responsive to stty and defaults set by @@ -928,12 +916,12 @@ static int qt_open(struct tty_struct *tty, } - dbg("port number is %d\n", port->number); - dbg("serial number is %d\n", port->serial->minor); - dbg("Bulkin endpoint is %d\n", port->bulk_in_endpointAddress); - dbg("BulkOut endpoint is %d\n", port->bulk_out_endpointAddress); - dbg("Interrupt endpoint is %d\n", port->interrupt_in_endpointAddress); - dbg("port's number in the device is %d\n", quatech_port->port_num); + dev_dbg(&port->dev, "port number is %d\n", port->number); + dev_dbg(&port->dev, "serial number is %d\n", port->serial->minor); + dev_dbg(&port->dev, "Bulkin endpoint is %d\n", port->bulk_in_endpointAddress); + dev_dbg(&port->dev, "BulkOut endpoint is %d\n", port->bulk_out_endpointAddress); + dev_dbg(&port->dev, "Interrupt endpoint is %d\n", port->interrupt_in_endpointAddress); + dev_dbg(&port->dev, "port's number in the device is %d\n", quatech_port->port_num); quatech_port->read_urb = port->read_urb; /* set up our bulk in urb */ @@ -946,7 +934,7 @@ static int qt_open(struct tty_struct *tty, quatech_port->read_urb->transfer_buffer_length, qt_read_bulk_callback, quatech_port); - dbg("qt_open: bulkin endpoint is %d\n", port->bulk_in_endpointAddress); + dev_dbg(&port->dev, "qt_open: bulkin endpoint is %d\n", port->bulk_in_endpointAddress); quatech_port->read_urb_busy = true; result = usb_submit_urb(quatech_port->read_urb, GFP_KERNEL); if (result) { @@ -980,8 +968,6 @@ static int qt_chars_in_buffer(struct tty_struct *tty) chars = port->write_urb->transfer_buffer_length; } - dbg("%s - returns %d\n", __func__, chars); - return chars; } @@ -1003,7 +989,7 @@ static void qt_block_until_empty(struct tty_struct *tty, wait--; if (wait == 0) { - dbg("%s - TIMEOUT", __func__); + dev_dbg(&qt_port->port->dev, "%s - TIMEOUT", __func__); return; } else { wait = 30; @@ -1041,17 +1027,15 @@ static void qt_close(struct usb_serial_port *port) /* Close uart channel */ status = qt_close_channel(serial, index); if (status < 0) - dbg("%s - port %d qt_close_channel failed.\n", - __func__, port->number); + dev_dbg(&port->dev, "%s - port %d qt_close_channel failed.\n", __func__, port->number); port0->open_ports--; - dbg("qt_num_open_ports in close%d:in port%d\n", - port0->open_ports, port->number); + dev_dbg(&port->dev, "qt_num_open_ports in close%d:in port%d\n", port0->open_ports, port->number); if (port0->open_ports == 0) { if (serial->port[0]->interrupt_in_urb) { - dbg("%s", "Shutdown interrupt_in_urb\n"); + dev_dbg(&port->dev, "%s", "Shutdown interrupt_in_urb\n"); usb_kill_urb(serial->port[0]->interrupt_in_urb); } @@ -1075,14 +1059,14 @@ static int qt_write(struct tty_struct *tty, struct usb_serial_port *port, return -ENODEV; if (count == 0) { - dbg("%s - write request of 0 bytes\n", __func__); + dev_dbg(&port->dev, "%s - write request of 0 bytes\n", __func__); return 0; } /* only do something if we have a bulk out endpoint */ if (serial->num_bulk_out) { if (port->write_urb->status == -EINPROGRESS) { - dbg("%s - already writing\n", __func__); + dev_dbg(&port->dev, "%s - already writing\n", __func__); return 0; } @@ -1102,8 +1086,8 @@ static int qt_write(struct tty_struct *tty, struct usb_serial_port *port, /* send the data out the bulk port */ result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) - dbg("%s - failed submitting write urb, error %d\n", - __func__, result); + dev_dbg(&port->dev, "%s - failed submitting write urb, error %d\n", + __func__, result); else result = count; @@ -1122,10 +1106,8 @@ static int qt_write_room(struct tty_struct *tty) int retval = -EINVAL; - if (port_paranoia_check(port, __func__)) { - dbg("%s", "Invalid port\n"); + if (port_paranoia_check(port, __func__)) return -1; - } serial = get_usb_serial(port, __func__); @@ -1154,7 +1136,7 @@ static int qt_ioctl(struct tty_struct *tty, struct usb_serial *serial = get_usb_serial(port, __func__); unsigned int index; - dbg("%s cmd 0x%04x", __func__, cmd); + dev_dbg(&port->dev, "%s cmd 0x%04x\n", __func__, cmd); index = tty->index - serial->minor; @@ -1187,7 +1169,7 @@ static int qt_ioctl(struct tty_struct *tty, return 0; } - dbg("%s -No ioctl for that one. port = %d\n", __func__, port->number); + dev_dbg(&port->dev, "%s -No ioctl for that one. port = %d\n", __func__, port->number); return -ENOIOCTLCMD; } @@ -1232,7 +1214,7 @@ static void qt_set_termios(struct tty_struct *tty, else new_LCR |= SERIAL_ONE_STOPB; - dbg("%s - 4\n", __func__); + dev_dbg(&port->dev, "%s - 4\n", __func__); /* Thats the LCR stuff, go ahead and set it */ baud = tty_get_baud_rate(tty); @@ -1240,7 +1222,7 @@ static void qt_set_termios(struct tty_struct *tty, /* pick a default, any default... */ baud = 9600; - dbg("%s - got baud = %d\n", __func__, baud); + dev_dbg(&port->dev, "%s - got baud = %d\n", __func__, baud); divisor = MAX_BAUD_RATE / baud; remainder = MAX_BAUD_RATE % baud; @@ -1254,30 +1236,28 @@ static void qt_set_termios(struct tty_struct *tty, status = qt_setuart(port->serial, index, (unsigned short)divisor, new_LCR); if (status < 0) { - dbg(__FILE__ "qt_setuart failed\n"); + dev_dbg(&port->dev, "qt_setuart failed\n"); return; } /* Now determine flow control */ if (cflag & CRTSCTS) { - dbg("%s - Enabling HW flow control port %d\n", __func__, - port->number); + dev_dbg(&port->dev, "%s - Enabling HW flow control port %d\n", __func__, port->number); /* Enable RTS/CTS flow control */ status = BoxSetHW_FlowCtrl(port->serial, index, 1); if (status < 0) { - dbg(__FILE__ "BoxSetHW_FlowCtrl failed\n"); + dev_dbg(&port->dev, "BoxSetHW_FlowCtrl failed\n"); return; } } else { /* Disable RTS/CTS flow control */ - dbg("%s - disabling HW flow control port %d\n", __func__, - port->number); + dev_dbg(&port->dev, "%s - disabling HW flow control port %d\n", __func__, port->number); status = BoxSetHW_FlowCtrl(port->serial, index, 0); if (status < 0) { - dbg(__FILE__ "BoxSetHW_FlowCtrl failed\n"); + dev_dbg(&port->dev, "BoxSetHW_FlowCtrl failed\n"); return; } @@ -1292,13 +1272,13 @@ static void qt_set_termios(struct tty_struct *tty, BoxSetSW_FlowCtrl(port->serial, index, stop_char, start_char); if (status < 0) - dbg(__FILE__ "BoxSetSW_FlowCtrl (enabled) failed\n"); + dev_dbg(&port->dev, "BoxSetSW_FlowCtrl (enabled) failed\n"); } else { /* disable SW flow control */ status = BoxDisable_SW_FlowCtrl(port->serial, index); if (status < 0) - dbg(__FILE__ "BoxSetSW_FlowCtrl (diabling) failed\n"); + dev_dbg(&port->dev, "BoxSetSW_FlowCtrl (diabling) failed\n"); } tty->termios->c_cflag &= ~CMSPAR; @@ -1476,10 +1456,10 @@ static void qt_unthrottle(struct tty_struct *tty) mutex_lock(&qt_port->lock); if (qt_port->RxHolding == 1) { - dbg("%s -qt_port->RxHolding == 1\n", __func__); + dev_dbg(&port->dev, "%s -qt_port->RxHolding == 1\n", __func__); qt_port->RxHolding = 0; - dbg("%s - qt_port->RxHolding = 0\n", __func__); + dev_dbg(&port->dev, "%s - qt_port->RxHolding = 0\n", __func__); /* if we have a bulk endpoint, start it up */ if ((serial->num_bulk_in) && (qt_port->ReadBulkStopped == 1)) { @@ -1507,11 +1487,6 @@ static int qt_calc_num_ports(struct usb_serial *serial) { int num_ports; - dbg("numberofendpoints: %d\n", - (int)serial->interface->cur_altsetting->desc.bNumEndpoints); - dbg("numberofendpoints: %d\n", - (int)serial->interface->altsetting->desc.bNumEndpoints); - num_ports = (serial->interface->cur_altsetting->desc.bNumEndpoints - 1) / 2; -- cgit v0.10.2 From 82760526e6d2e1d1e815abaf3eae42b8bb82968c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 09:38:33 +0100 Subject: USB: serial: remove dbg() from usb/serial.h Now that all in-kernel users of the dbg() macro are gone, we can remove it from the include/linux/usb/serial.h file. Good riddance. Signed-off-by: Greg Kroah-Hartman diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 6bed6db..e71bc5e 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -365,14 +365,6 @@ static inline void usb_serial_debug_data(int debug, function, size, size, data); } -/* Use our own dbg macro */ -#undef dbg -#define dbg(format, arg...) \ -do { \ - if (debug) \ - printk(KERN_DEBUG "%s: " format "\n", __FILE__, ##arg); \ -} while (0) - /* * Macro for reporting errors in write path to avoid inifinite loop * when port is used as a console. -- cgit v0.10.2 From 59d33f2fc2d63796296b1b76143e039d6e7cf532 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 09:58:57 +0100 Subject: USB: serial: remove debug parameter from usb_serial_debug_data() We should use dev_dbg() for usb_serial_debug_data() like all of the rest of the usb-serial drivers use, so remove the debug parameter as it's not needed. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index f8ce97d..07956e4 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -650,8 +650,7 @@ static void ark3116_read_int_callback(struct urb *urb) /* * Not sure what this data meant... */ - usb_serial_debug_data(debug, &port->dev, - __func__, + usb_serial_debug_data(&port->dev, __func__, urb->actual_length, urb->transfer_buffer); break; diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index 6b73656..1eff29e 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -206,8 +206,7 @@ static void belkin_sa_read_int_callback(struct urb *urb) goto exit; } - usb_serial_debug_data(debug, &port->dev, __func__, - urb->actual_length, data); + usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data); /* Handle known interrupt data */ /* ignore data[0] and data[1] */ diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index 9aae210..b07009b 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -463,7 +463,7 @@ static void ch341_read_int_callback(struct urb *urb) goto exit; } - usb_serial_debug_data(debug, &port->dev, __func__, + usb_serial_debug_data(&port->dev, __func__, urb->actual_length, urb->transfer_buffer); if (actual_length >= 4) { diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 9c90575..17066da 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -222,8 +222,7 @@ static int cyberjack_write(struct tty_struct *tty, /* Copy data */ memcpy(priv->wrbuf + priv->wrfilled, buf, count); - usb_serial_debug_data(debug, dev, __func__, count, - priv->wrbuf + priv->wrfilled); + usb_serial_debug_data(dev, __func__, count, priv->wrbuf + priv->wrfilled); priv->wrfilled += count; if (priv->wrfilled >= 3) { @@ -295,7 +294,7 @@ static void cyberjack_read_int_callback(struct urb *urb) if (status) return; - usb_serial_debug_data(debug, dev, __func__, urb->actual_length, data); + usb_serial_debug_data(dev, __func__, urb->actual_length, data); /* React only to interrupts signaling a bulk_in transfer */ if (urb->actual_length == 4 && data[0] == 0x01) { @@ -348,8 +347,7 @@ static void cyberjack_read_bulk_callback(struct urb *urb) int result; int status = urb->status; - usb_serial_debug_data(debug, &port->dev, __func__, - urb->actual_length, data); + usb_serial_debug_data(dev, __func__, urb->actual_length, data); if (status) { dev_dbg(dev, "%s - nonzero read bulk status received: %d\n", __func__, status); diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 872a45d..19f22e9 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -769,9 +769,8 @@ send: actual_size = count + (priv->pkt_fmt == packet_format_1 ? 2 : 1); - usb_serial_debug_data(debug, &port->dev, __func__, - port->interrupt_out_size, - port->interrupt_out_urb->transfer_buffer); + usb_serial_debug_data(dev, __func__, port->interrupt_out_size, + port->interrupt_out_urb->transfer_buffer); usb_fill_int_urb(port->interrupt_out_urb, port->serial->dev, usb_sndintpipe(port->serial->dev, port->interrupt_out_endpointAddress), @@ -1187,8 +1186,7 @@ static void cypress_read_int_callback(struct urb *urb) goto continue_read; } - usb_serial_debug_data(debug, &port->dev, __func__, - urb->actual_length, data); + usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data); spin_lock_irqsave(&priv->lock, flags); /* check to see if status has changed */ diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index 499b15f..9413688 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c @@ -85,7 +85,7 @@ static void f81232_read_int_callback(struct urb *urb) goto exit; } - usb_serial_debug_data(debug, &port->dev, __func__, + usb_serial_debug_data(&port->dev, __func__, urb->actual_length, urb->transfer_buffer); f81232_update_line_status(port, data, actual_length); diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 11029df..0e40610 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -258,10 +258,7 @@ static void send_to_tty(struct usb_serial_port *port, struct tty_struct *tty = tty_port_tty_get(&port->port); if (tty && actual_length) { - - usb_serial_debug_data(debug, &port->dev, - __func__, actual_length, data); - + usb_serial_debug_data(&port->dev, __func__, actual_length, data); tty_insert_flip_string(tty, data, actual_length); tty_flip_buffer_push(tty); } @@ -410,8 +407,8 @@ static int gsp_rec_packet(struct garmin_data *garmin_data_p, int count) int pktid = recpkt[0]; int size = recpkt[1]; - usb_serial_debug_data(debug, &garmin_data_p->port->dev, - __func__, count-GSP_INITIAL_OFFSET, recpkt); + usb_serial_debug_data(&garmin_data_p->port->dev, __func__, + count-GSP_INITIAL_OFFSET, recpkt); if (size != (count-GSP_INITIAL_OFFSET-3)) { dev_dbg(dev, "%s - invalid size, expected %d bytes, got %d\n", @@ -642,8 +639,8 @@ static int gsp_send(struct garmin_data *garmin_data_p, /* garmin_data_p->outbuffer now contains a complete packet */ - usb_serial_debug_data(debug, &garmin_data_p->port->dev, - __func__, k, garmin_data_p->outbuffer); + usb_serial_debug_data(&garmin_data_p->port->dev, __func__, k, + garmin_data_p->outbuffer); garmin_data_p->outsize = 0; @@ -1038,7 +1035,7 @@ static int garmin_write_bulk(struct usb_serial_port *port, memcpy(buffer, buf, count); - usb_serial_debug_data(debug, &port->dev, __func__, count, buffer); + usb_serial_debug_data(&port->dev, __func__, count, buffer); usb_fill_bulk_urb(urb, serial->dev, usb_sndbulkpipe(serial->dev, @@ -1084,7 +1081,7 @@ static int garmin_write(struct tty_struct *tty, struct usb_serial_port *port, struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); __le32 *privpkt = (__le32 *)garmin_data_p->privpkt; - usb_serial_debug_data(debug, dev, __func__, count, buf); + usb_serial_debug_data(dev, __func__, count, buf); if (garmin_data_p->state == STATE_RESET) return -EIO; @@ -1225,8 +1222,7 @@ static void garmin_read_bulk_callback(struct urb *urb) return; } - usb_serial_debug_data(debug, &port->dev, - __func__, urb->actual_length, data); + usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data); garmin_read_process(garmin_data_p, data, urb->actual_length, 1); @@ -1284,8 +1280,8 @@ static void garmin_read_int_callback(struct urb *urb) return; } - usb_serial_debug_data(debug, &port->dev, __func__, - urb->actual_length, urb->transfer_buffer); + usb_serial_debug_data(&port->dev, __func__, urb->actual_length, + urb->transfer_buffer); if (urb->actual_length == sizeof(GARMIN_BULK_IN_AVAIL_REPLY) && 0 == memcmp(data, GARMIN_BULK_IN_AVAIL_REPLY, diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 9b026bf..47e2280 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -171,8 +171,7 @@ retry: urb->transfer_buffer, port->bulk_out_size); urb->transfer_buffer_length = count; - usb_serial_debug_data(debug, &port->dev, __func__, count, - urb->transfer_buffer); + usb_serial_debug_data(&port->dev, __func__, count, urb->transfer_buffer); spin_lock_irqsave(&port->lock, flags); port->tx_bytes += count; spin_unlock_irqrestore(&port->lock, flags); @@ -365,8 +364,7 @@ void usb_serial_generic_read_bulk_callback(struct urb *urb) return; } - usb_serial_debug_data(debug, &port->dev, __func__, - urb->actual_length, data); + usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data); port->serial->type->process_read_urb(urb); /* Throttle the device if requested by tty */ diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 1a82697..06159fd 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -599,7 +599,7 @@ static void edge_interrupt_callback(struct urb *urb) /* process this interrupt-read even if there are no ports open */ if (length) { - usb_serial_debug_data(debug, dev, __func__, length, data); + usb_serial_debug_data(dev, __func__, length, data); if (length > 1) { bytes_avail = data[0] | (data[1] << 8); @@ -705,7 +705,7 @@ static void edge_bulk_in_callback(struct urb *urb) dev = &edge_serial->serial->dev->dev; raw_data_length = urb->actual_length; - usb_serial_debug_data(debug, dev, __func__, raw_data_length, data); + usb_serial_debug_data(dev, __func__, raw_data_length, data); spin_lock(&edge_serial->es_lock); @@ -1178,8 +1178,7 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port, /* now copy our data */ memcpy(&fifo->fifo[fifo->head], data, firsthalf); - usb_serial_debug_data(debug, &port->dev, __func__, - firsthalf, &fifo->fifo[fifo->head]); + usb_serial_debug_data(&port->dev, __func__, firsthalf, &fifo->fifo[fifo->head]); /* update the index and size */ fifo->head += firsthalf; @@ -1194,8 +1193,7 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port, if (secondhalf) { dev_dbg(&port->dev, "%s - copy rest of data %d\n", __func__, secondhalf); memcpy(&fifo->fifo[fifo->head], &data[firsthalf], secondhalf); - usb_serial_debug_data(debug, &port->dev, __func__, - secondhalf, &fifo->fifo[fifo->head]); + usb_serial_debug_data(&port->dev, __func__, secondhalf, &fifo->fifo[fifo->head]); /* update the index and size */ fifo->count += secondhalf; fifo->head += secondhalf; @@ -1312,8 +1310,7 @@ static void send_more_port_data(struct edgeport_serial *edge_serial, } if (count) - usb_serial_debug_data(debug, &edge_port->port->dev, - __func__, count, &buffer[2]); + usb_serial_debug_data(&edge_port->port->dev, __func__, count, &buffer[2]); /* fill up the urb with all of our data and submit it */ usb_fill_bulk_urb(urb, edge_serial->serial->dev, @@ -2305,7 +2302,7 @@ static int write_cmd_usb(struct edgeport_port *edge_port, int status = 0; struct urb *urb; - usb_serial_debug_data(debug, dev, __func__, length, buffer); + usb_serial_debug_data(dev, __func__, length, buffer); /* Allocate our next urb */ urb = usb_alloc_urb(0, GFP_ATOMIC); diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 54916d7..c6b8283 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -321,8 +321,7 @@ static int read_download_mem(struct usb_device *dev, int start_address, } if (read_length > 1) - usb_serial_debug_data(debug, &dev->dev, __func__, - read_length, buffer); + usb_serial_debug_data(&dev->dev, __func__, read_length, buffer); /* Update pointers/length */ start_address += read_length; @@ -359,8 +358,7 @@ static int read_boot_mem(struct edgeport_serial *serial, dev_dbg(&serial->serial->dev->dev, "%s - start_address = %x, length = %d\n", __func__, start_address, length); - usb_serial_debug_data(debug, &serial->serial->dev->dev, - __func__, length, buffer); + usb_serial_debug_data(&serial->serial->dev->dev, __func__, length, buffer); serial->TiReadI2C = 1; @@ -398,8 +396,7 @@ static int write_boot_mem(struct edgeport_serial *serial, } dev_dbg(&serial->serial->dev->dev, "%s - start_sddr = %x, length = %d\n", __func__, start_address, length); - usb_serial_debug_data(debug, &serial->serial->dev->dev, - __func__, length, buffer); + usb_serial_debug_data(&serial->serial->dev->dev, __func__, length, buffer); return status; } @@ -425,7 +422,7 @@ static int write_i2c_mem(struct edgeport_serial *serial, dev_dbg(dev, "%s - BytesInFirstPage Addr = %x, length = %d\n", __func__, start_address, write_length); - usb_serial_debug_data(debug, dev, __func__, write_length, buffer); + usb_serial_debug_data(dev, __func__, write_length, buffer); /* Write first page */ be_start_address = cpu_to_be16(start_address); @@ -452,7 +449,7 @@ static int write_i2c_mem(struct edgeport_serial *serial, dev_dbg(dev, "%s - Page Write Addr = %x, length = %d\n", __func__, start_address, write_length); - usb_serial_debug_data(debug, dev, __func__, write_length, buffer); + usb_serial_debug_data(dev, __func__, write_length, buffer); /* Write next page */ be_start_address = cpu_to_be16(start_address); @@ -1622,7 +1619,7 @@ static void edge_interrupt_callback(struct urb *urb) } dev = &edge_serial->serial->dev->dev; - usb_serial_debug_data(debug, dev, __func__, length, data); + usb_serial_debug_data(dev, __func__, length, data); if (length != 2) { dev_dbg(dev, "%s - expecting packet of size 2, got %d\n", __func__, length); @@ -1726,7 +1723,7 @@ static void edge_bulk_in_callback(struct urb *urb) tty = tty_port_tty_get(&edge_port->port->port); if (tty && urb->actual_length) { - usb_serial_debug_data(debug, dev, __func__, urb->actual_length, data); + usb_serial_debug_data(dev, __func__, urb->actual_length, data); if (edge_port->close_pending) dev_dbg(dev, "%s - close pending, dropping data on the floor\n", __func__); @@ -2059,8 +2056,7 @@ static void edge_send(struct tty_struct *tty) spin_unlock_irqrestore(&edge_port->ep_lock, flags); - usb_serial_debug_data(debug, &port->dev, __func__, count, - port->write_urb->transfer_buffer); + usb_serial_debug_data(&port->dev, __func__, count, port->write_urb->transfer_buffer); /* set up our urb */ port->write_urb->transfer_buffer_length = count; diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index a2f7230..33d7e18 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -392,8 +392,7 @@ static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, /* Copy data to buffer */ memcpy(priv->buf + priv->filled, buf, count); - usb_serial_debug_data(debug, &port->dev, __func__, count, - priv->buf + priv->filled); + usb_serial_debug_data(&port->dev, __func__, count, priv->buf + priv->filled); priv->filled = priv->filled + count; /* only send complete block. TWIN, KAAN SIM and adapter K diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index ab8f9ff..ef773ba 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -553,8 +553,7 @@ static void mct_u232_read_int_callback(struct urb *urb) goto exit; } - usb_serial_debug_data(debug, &port->dev, __func__, - urb->actual_length, data); + usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data); /* * Work-a-round: handle the 'usual' bulk-in pipe here diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 192191c..049bf6f 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -1266,7 +1266,7 @@ static int mos7720_write(struct tty_struct *tty, struct usb_serial_port *port, transfer_size = min(count, URB_TRANSFER_BUFFER_SIZE); memcpy(urb->transfer_buffer, current_position, transfer_size); - usb_serial_debug_data(debug, &port->dev, __func__, transfer_size, + usb_serial_debug_data(&port->dev, __func__, transfer_size, urb->transfer_buffer); /* fill urb with data and submit */ diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index ffbe4ee..a4880d6 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -796,7 +796,7 @@ static void mos7840_bulk_in_callback(struct urb *urb) } data = urb->transfer_buffer; - usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data); + usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data); if (urb->actual_length) { tty = tty_port_tty_get(&mos7840_port->port->port); diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c index d95452c..e0b4d4f 100644 --- a/drivers/usb/serial/navman.c +++ b/drivers/usb/serial/navman.c @@ -55,8 +55,7 @@ static void navman_read_int_callback(struct urb *urb) goto exit; } - usb_serial_debug_data(debug, &port->dev, __func__, - urb->actual_length, data); + usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data); tty = tty_port_tty_get(&port->port); if (tty && urb->actual_length) { diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index f524cd9..7e81ed0 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -228,8 +228,8 @@ static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, memcpy(wport->write_urb->transfer_buffer + OMNINET_DATAOFFSET, buf, count); - usb_serial_debug_data(debug, &port->dev, __func__, count, - wport->write_urb->transfer_buffer); + usb_serial_debug_data(&port->dev, __func__, count, + wport->write_urb->transfer_buffer); header->oh_seq = od->od_outseq++; header->oh_len = count; diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 6f05d64..d750772 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -87,8 +87,7 @@ static void opticon_read_bulk_callback(struct urb *urb) goto exit; } - usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, - data); + usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data); if (urb->actual_length > 2) { data_length = urb->actual_length - 2; @@ -276,7 +275,7 @@ static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, memcpy(buffer, buf, count); - usb_serial_debug_data(debug, &port->dev, __func__, count, buffer); + usb_serial_debug_data(&port->dev, __func__, count, buffer); /* The conncected devices do not have a bulk write endpoint, * to transmit data to de barcode device the control endpoint is used */ diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 13b8dd6..5eccbe5 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -741,7 +741,7 @@ static void pl2303_read_int_callback(struct urb *urb) goto exit; } - usb_serial_debug_data(debug, &port->dev, __func__, + usb_serial_debug_data(&port->dev, __func__, urb->actual_length, urb->transfer_buffer); pl2303_update_line_status(port, data, actual_length); diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 0274710..400bb13 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -518,7 +518,7 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port, memcpy(buffer, buf, writesize); - usb_serial_debug_data(debug, &port->dev, __func__, writesize, buffer); + usb_serial_debug_data(&port->dev, __func__, writesize, buffer); usb_fill_bulk_urb(urb, serial->dev, usb_sndbulkpipe(serial->dev, @@ -595,8 +595,8 @@ static void sierra_indat_callback(struct urb *urb) tty_flip_buffer_push(tty); tty_kref_put(tty); - usb_serial_debug_data(debug, &port->dev, - __func__, urb->actual_length, data); + usb_serial_debug_data(&port->dev, __func__, + urb->actual_length, data); } } else { dev_dbg(&port->dev, "%s: empty read urb" diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index e53d2aa..d0f1c21 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c @@ -71,8 +71,7 @@ static void symbol_int_callback(struct urb *urb) goto exit; } - usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, - data); + usb_serial_debug_data(&port->dev, __func__, urb->actual_length, data); if (urb->actual_length > 1) { data_length = urb->actual_length - 1; diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 0b113fa..5dbb741 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -1161,8 +1161,8 @@ static void ti_bulk_in_callback(struct urb *urb) tty = tty_port_tty_get(&port->port); if (tty) { if (urb->actual_length) { - usb_serial_debug_data(debug, dev, __func__, - urb->actual_length, urb->transfer_buffer); + usb_serial_debug_data(dev, __func__, urb->actual_length, + urb->transfer_buffer); if (!tport->tp_is_open) dev_dbg(dev, "%s - port closed, dropping data\n", @@ -1267,8 +1267,8 @@ static void ti_send(struct ti_port *tport) spin_unlock_irqrestore(&tport->tp_lock, flags); - usb_serial_debug_data(debug, &port->dev, __func__, count, - port->write_urb->transfer_buffer); + usb_serial_debug_data(&port->dev, __func__, count, + port->write_urb->transfer_buffer); usb_fill_bulk_urb(port->write_urb, port->serial->dev, usb_sndbulkpipe(port->serial->dev, diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index f253c91..97fe005 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -310,8 +310,8 @@ static void visor_read_int_callback(struct urb *urb) * Rumor has it this endpoint is used to notify when data * is ready to be read from the bulk ones. */ - usb_serial_debug_data(debug, &port->dev, __func__, - urb->actual_length, urb->transfer_buffer); + usb_serial_debug_data(&port->dev, __func__, urb->actual_length, + urb->transfer_buffer); exit: result = usb_submit_urb(urb, GFP_ATOMIC); @@ -443,8 +443,7 @@ static int palm_os_4_probe(struct usb_serial *serial, dev_err(dev, "%s - error %d getting connection info\n", __func__, retval); else - usb_serial_debug_data(debug, &serial->dev->dev, __func__, - retval, transfer_buffer); + usb_serial_debug_data(dev, __func__, retval, transfer_buffer); kfree(transfer_buffer); return 0; diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index d9456b4..64d3840 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -607,8 +607,7 @@ static void command_port_read_callback(struct urb *urb) return; } - usb_serial_debug_data(debug, &command_port->dev, - __func__, urb->actual_length, data); + usb_serial_debug_data(&command_port->dev, __func__, urb->actual_length, data); if (data[0] == WHITEHEAT_CMD_COMPLETE) { command_info->command_finished = WHITEHEAT_CMD_COMPLETE; diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index e71bc5e..b2b6d15 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -355,14 +355,12 @@ extern struct usb_serial_driver usb_serial_generic_device; extern struct bus_type usb_serial_bus_type; extern struct tty_driver *usb_serial_tty_driver; -static inline void usb_serial_debug_data(int debug, - struct device *dev, +static inline void usb_serial_debug_data(struct device *dev, const char *function, int size, const unsigned char *data) { - if (debug) - dev_printk(KERN_DEBUG, dev, "%s - length = %d, data = %*ph\n", - function, size, size, data); + dev_dbg(dev, "%s - length = %d, data = %*ph\n", + function, size, size, data); } /* -- cgit v0.10.2 From fee58d4821fc8765a7d47ab894385c6de63149d0 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:15:09 +0100 Subject: USB: Serial: serqt_usb2.c: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab CC: "Justin P. Mattock" Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/staging/serqt_usb2/serqt_usb2.c b/drivers/staging/serqt_usb2/serqt_usb2.c index b1e8b9d..376269b 100644 --- a/drivers/staging/serqt_usb2/serqt_usb2.c +++ b/drivers/staging/serqt_usb2/serqt_usb2.c @@ -16,8 +16,6 @@ #include #include -static bool debug; - /* Version Information */ #define DRIVER_VERSION "v2.14" #define DRIVER_AUTHOR "Tim Gobeli, Quatech, Inc" @@ -1527,6 +1525,3 @@ module_usb_serial_driver(serial_drivers, id_table); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v0.10.2 From 7ca98ceaa9e241b44349cc038435876132bd3c15 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:15:12 +0100 Subject: USB: Serial: ark3116.c: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab CC: Bart Hartgers Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index 07956e4..d154501 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c @@ -37,7 +37,6 @@ #include #include -static bool debug; /* * Version information */ @@ -749,9 +748,6 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Enable debug"); - /* * The following describes what I learned from studying the old * ark3116.c driver, disassembling the windows driver, and some lucky -- cgit v0.10.2 From 0a7e7a6ec6dba5c7310d10ca7a6ea82c67aa67cc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:15:13 +0100 Subject: USB: Serial: belkin_sa.c: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. CC: William Greathouse Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index 1eff29e..06af24d 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c @@ -37,8 +37,6 @@ #include #include "belkin_sa.h" -static bool debug; - /* * Version Information */ @@ -514,6 +512,3 @@ 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 enabled or not"); -- cgit v0.10.2 From 67ef930191983c6efbf01223fdde4c317873f367 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:15:17 +0100 Subject: USB: Serial: ch341.c: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. CC: Johan Hovold CC: Alan Stern CC: Rusty Russell CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index b07009b..e9c7046 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -70,8 +70,6 @@ #define CH341_NBREAK_BITS_REG2 0x40 -static bool debug; - static const struct usb_device_id id_table[] = { { USB_DEVICE(0x4348, 0x5523) }, { USB_DEVICE(0x1a86, 0x7523) }, @@ -621,6 +619,3 @@ static struct usb_serial_driver * const serial_drivers[] = { module_usb_serial_driver(serial_drivers, id_table); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v0.10.2 From 709a2ce621083a2443dd0d17600d10e56a65a958 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:15:18 +0100 Subject: USB: Serial: cyberjack.c: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. CC: Matthias Bruestle and Harald Welte Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 17066da..2a7aecc 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -43,8 +43,6 @@ #define CYBERJACK_LOCAL_BUF_SIZE 32 -static bool debug; - /* * Version Information */ @@ -456,6 +454,3 @@ 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 enabled or not"); -- cgit v0.10.2 From f462376e1a171f285b7bef3afa0d5a3123766128 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:15:18 +0100 Subject: USB: Serial: cypress_m8.c: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. CC: Lonnie Mendez Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 19f22e9..3f13cdd 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c @@ -46,7 +46,6 @@ #include "cypress_m8.h" -static bool debug; static bool stats; static int interval; static bool unstable_bauds; @@ -1308,8 +1307,6 @@ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_VERSION(DRIVER_VERSION); MODULE_LICENSE("GPL"); -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); module_param(stats, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(stats, "Enable statistics or not"); module_param(interval, int, S_IRUGO | S_IWUSR); -- cgit v0.10.2 From 9d27b6a63511aa8416e1cebcec9dd6ccdf02fe7e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:15:25 +0100 Subject: USB: Serial: f81232.c: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. CC: Alan Stern Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index 9413688..c571033 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c @@ -25,8 +25,6 @@ #include #include -static bool debug; - static const struct usb_device_id id_table[] = { { USB_DEVICE(0x1934, 0x0706) }, { } /* Terminating entry */ @@ -388,7 +386,3 @@ module_usb_serial_driver(serial_drivers, id_table); MODULE_DESCRIPTION("Fintek F81232 USB to serial adaptor driver"); MODULE_AUTHOR("Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:15:29 +0100 Subject: USB: Serial: garmin_gps.c: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. CC: Johan Hovold CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 0e40610..3ee9264 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -41,9 +41,6 @@ /* the mode to be set when the port ist opened */ static int initial_mode = 1; -/* debug flag */ -static bool debug; - #define GARMIN_VENDOR_ID 0x091E /* @@ -1108,15 +1105,6 @@ static int garmin_write(struct tty_struct *tty, struct usb_serial_port *port, garmin_clear(garmin_data_p); switch (pktid) { - - case PRIV_PKTID_SET_DEBUG: - if (pktsiz != 4) - return -EINVPKT; - debug = __le32_to_cpu(privpkt[3]); - dev_dbg(dev, "%s - debug level set to 0x%X\n", - __func__, debug); - break; - case PRIV_PKTID_SET_MODE: if (pktsiz != 4) return -EINVPKT; @@ -1498,7 +1486,5 @@ MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); -module_param(debug, bool, S_IWUSR | S_IRUGO); -MODULE_PARM_DESC(debug, "Debug enabled or not"); module_param(initial_mode, int, S_IRUGO); MODULE_PARM_DESC(initial_mode, "Initial mode"); -- cgit v0.10.2 From 9fa38332cf8975b23c0226f118538e2e3034037b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:15:33 +0100 Subject: USB: Serial: io_edgeport.c: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. CC: Johan Hovold CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index 06159fd..75b7ccd 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c @@ -190,9 +190,6 @@ static const struct divisor_table_entry divisor_table[] = { { 230400, 1}, }; -/* local variables */ -static bool debug; - /* Number of outstanding Command Write Urbs */ static atomic_t CmdUrbs = ATOMIC_INIT(0); @@ -3140,6 +3137,3 @@ MODULE_FIRMWARE("edgeport/boot.fw"); MODULE_FIRMWARE("edgeport/boot2.fw"); MODULE_FIRMWARE("edgeport/down.fw"); MODULE_FIRMWARE("edgeport/down2.fw"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v0.10.2 From 224975413d417d2a002ba97e3779fc604e8fef3d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:15:37 +0100 Subject: USB: Serial: io_ti.c: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. CC: Johan Hovold CC: "Eric W. Biederman" CC: Rusty Russell CC: Alan Stern Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index c6b8283..6317254 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -201,8 +201,6 @@ static unsigned char OperationalMajorVersion; static unsigned char OperationalMinorVersion; static unsigned short OperationalBuildNumber; -static bool debug; - static int closing_wait = EDGE_CLOSING_WAIT; static bool ignore_cpu_rev; static int default_uart_mode; /* RS232 */ @@ -2726,9 +2724,6 @@ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); MODULE_FIRMWARE("edgeport/down3.bin"); -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); - module_param(closing_wait, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(closing_wait, "Maximum wait for data to drain, in .01 secs"); -- cgit v0.10.2 From ca98bb7c4932eeb725be1dd940127305190ffb96 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:15:40 +0100 Subject: USB: Serial: iuu_phoenix.c: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. CC: Rusty Russell CC: Johan Hovold CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index f9832b7..91e6e37 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c @@ -32,13 +32,6 @@ #include "iuu_phoenix.h" #include - -#ifdef CONFIG_USB_SERIAL_DEBUG -static bool debug = 1; -#else -static bool debug; -#endif - /* * Version Information */ @@ -1248,8 +1241,6 @@ MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); MODULE_VERSION(DRIVER_VERSION); -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); module_param(xmas, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(xmas, "Xmas colors enabled or not"); -- cgit v0.10.2 From be4568beb8f447bfce2e70b6f11401267e5b208a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:15:41 +0100 Subject: USB: Serial: keyspan.c: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 1635f506..566056c 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -45,8 +45,6 @@ #include #include "keyspan.h" -static bool debug; - /* * Version Information */ @@ -2558,7 +2556,3 @@ MODULE_FIRMWARE("keyspan/usa18x.fw"); MODULE_FIRMWARE("keyspan/usa19w.fw"); MODULE_FIRMWARE("keyspan/usa49w.fw"); MODULE_FIRMWARE("keyspan/usa49wlc.fw"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); - -- cgit v0.10.2 From e40e275906e89fefe63cdcc1f039718e0384ad2e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:15:45 +0100 Subject: USB: Serial: kobil_sct.c: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. CC: Johan Hovold CC: Alan Stern CC: Felipe Balbi Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 33d7e18..30f07db 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -38,8 +38,6 @@ #include #include "kobil_sct.h" -static bool debug; - /* Version Information */ #define DRIVER_VERSION "21/05/2004" #define DRIVER_AUTHOR "KOBIL Systems GmbH - http://www.kobil.com" @@ -659,6 +657,3 @@ module_usb_serial_driver(serial_drivers, id_table); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v0.10.2 From 08e48a22a6608c82626499cf325eb9d9f7c2a84c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:15:49 +0100 Subject: USB: Serial: mct_u232.c: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. CC: Johan Hovold CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index ef773ba..8042582 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -45,8 +45,6 @@ #define DRIVER_AUTHOR "Wolfgang Grandegger " #define DRIVER_DESC "Magic Control Technology USB-RS232 converter driver" -static bool debug; - /* * Function prototypes */ @@ -878,6 +876,3 @@ module_usb_serial_driver(serial_drivers, id_table); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v0.10.2 From 274b63fa7818cc1aae33bf4232de4e75a8f45290 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:15:53 +0100 Subject: USB: Serial: mos7720.c: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. CC: Johan Hovold CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 049bf6f..af7bc9b 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c @@ -71,8 +71,6 @@ struct moschip_port { struct urb *write_urb_pool[NUM_URBS]; }; -static bool debug; - static struct usb_serial_driver moschip7720_2port_driver; #define USB_VENDOR_ID_MOSCHIP 0x9710 @@ -2133,6 +2131,3 @@ module_usb_serial_driver(serial_drivers, id_table); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v0.10.2 From a1253572b1108842fd90031ee0fcbd4b729f2679 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:15:57 +0100 Subject: USB: Serial: mos7840.c: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. CC: Johan Hovold CC: Mark Ferrell CC: Donald Lee CC: Tony Zelenoff Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index a4880d6..a94297d 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c @@ -252,8 +252,6 @@ struct moschip_port { struct timer_list led_timer2; /* Timer for LED off */ }; -static bool debug; - /* * mos7840_set_reg_sync * To set the Control register by calling usb_fill_control_urb function @@ -2694,6 +2692,3 @@ module_usb_serial_driver(serial_drivers, id_table); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v0.10.2 From ef0d54cd89e6c4a620fe2f69edac5bba1e701c86 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:16:01 +0100 Subject: USB: Serial: navman.c: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c index e0b4d4f..1566f8f 100644 --- a/drivers/usb/serial/navman.c +++ b/drivers/usb/serial/navman.c @@ -21,8 +21,6 @@ #include #include -static bool debug; - static const struct usb_device_id id_table[] = { { USB_DEVICE(0x0a99, 0x0001) }, /* Talon Technology device */ { USB_DEVICE(0x0df7, 0x0900) }, /* Mobile Action i-gotU */ @@ -122,6 +120,3 @@ static struct usb_serial_driver * const serial_drivers[] = { module_usb_serial_driver(serial_drivers, id_table); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v0.10.2 From 6e03b8cecbd836f729afe1a50814544baa5e5f97 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:16:04 +0100 Subject: USB: Serial: omninet.c: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. CC: Johan Hovold CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 7e81ed0..4803b5e 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -23,8 +23,6 @@ #include #include -static bool debug; - /* * Version Information */ @@ -172,17 +170,6 @@ static void omninet_read_bulk_callback(struct urb *urb) return; } - if (debug && header->oh_xxx != 0x30) { - if (urb->actual_length) { - printk(KERN_DEBUG "%s: omninet_read %d: ", - __FILE__, header->oh_len); - for (i = 0; i < (header->oh_len + - OMNINET_HEADERLEN); i++) - printk("%.2x ", data[i]); - printk("\n"); - } - } - if (urb->actual_length && header->oh_len) { struct tty_struct *tty = tty_port_tty_get(&port->port); if (tty) { @@ -306,6 +293,3 @@ module_usb_serial_driver(serial_drivers, id_table); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v0.10.2 From 059bb46a5177b5e271d3289a8fe9dd883550d90c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:16:08 +0100 Subject: USB: Serial: opticon.c: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. CC: Johan Hovold CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index d750772..41b1647 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -32,8 +32,6 @@ * an examples of 1D barcode types are EAN, UPC, Code39, IATA etc.. */ #define DRIVER_DESC "Opticon USB barcode to serial driver (1D)" -static bool debug; - static const struct usb_device_id id_table[] = { { USB_DEVICE(0x065a, 0x0009) }, { }, @@ -611,6 +609,3 @@ module_usb_serial_driver(serial_drivers, id_table); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v0.10.2 From 8c3b8f0aea54f5c9d77d3bd4bf037d8868026d72 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:16:12 +0100 Subject: USB: Serial: pl2303.c: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. CC: Johan Hovold CC: Alan Stern CC: Wang YanQing CC: Rusty Russell Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 5eccbe5..ef10a9c 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c @@ -36,8 +36,6 @@ */ #define DRIVER_DESC "Prolific PL2303 USB to serial adaptor driver" -static bool debug; - static const struct usb_device_id id_table[] = { { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID) }, { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_RSAQ2) }, @@ -839,7 +837,3 @@ module_usb_serial_driver(serial_drivers, id_table); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); - -- cgit v0.10.2 From f3c4bd30623f06a5cc36fe096c29c253fd88451b Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:16:16 +0100 Subject: USB: Serial: sierra.c: remove debug module parameter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. CC: Alan Stern CC: "Bjørn Mork" CC: Rusty Russell CC: Johan Hovold Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 400bb13..4ef30ac 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c @@ -46,7 +46,6 @@ allocations > PAGE_SIZE and the number of packets in a page is an integer 512 is the largest possible packet on EHCI */ -static bool debug; static bool nmea; /* Used in interface blacklisting */ @@ -765,7 +764,6 @@ static struct urb *sierra_setup_urb(struct usb_serial *serial, int endpoint, usb_sndbulkpipe(serial->dev, endpoint) | dir, buf, len, callback, ctx); - /* debug */ dev_dbg(&serial->dev->dev, "%s %c u : %p d:%p\n", __func__, dir == USB_DIR_IN ? 'i' : 'o', urb, buf); } else { @@ -1082,6 +1080,3 @@ MODULE_LICENSE("GPL"); module_param(nmea, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(nmea, "NMEA streaming"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug messages"); -- cgit v0.10.2 From 9dfea1b0904781e2673ef1ea0ae3113d0d4dca61 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:16:20 +0100 Subject: USB: Serial: symbolserial.c: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. CC: Rusty Russell CC: Johan Hovold CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index d0f1c21..701fffa 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c @@ -20,8 +20,6 @@ #include #include -static bool debug; - static const struct usb_device_id id_table[] = { { USB_DEVICE(0x05e0, 0x0600) }, { }, @@ -291,6 +289,3 @@ static struct usb_serial_driver * const serial_drivers[] = { module_usb_serial_driver(serial_drivers, id_table); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v0.10.2 From 0d3831f6b65dbb0023061925a8bb746270a0b20a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:16:24 +0100 Subject: USB: Serial: ti_usb_3410_5052.c: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. CC: Johan Hovold CC: Rusty Russell CC: Adhir Ramjiawan CC: Andrew Lunn Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 5dbb741..e6f492d 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -150,7 +150,6 @@ static int ti_download_firmware(struct ti_device *tdev); /* Data */ /* module parameters */ -static bool debug; static int closing_wait = TI_DEFAULT_CLOSING_WAIT; static ushort vendor_3410[TI_EXTRA_VID_PID_COUNT]; static unsigned int vendor_3410_count; @@ -288,9 +287,6 @@ MODULE_FIRMWARE("mts_edge.fw"); MODULE_FIRMWARE("mts_mt9234mu.fw"); MODULE_FIRMWARE("mts_mt9234zba.fw"); -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Enable debugging, 0=no, 1=yes"); - module_param(closing_wait, int, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(closing_wait, "Maximum wait for data to drain in close, in .01 secs, default is 4000"); -- cgit v0.10.2 From 60aa1a01360861113c821ef95230be27ac92fc10 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:16:28 +0100 Subject: USB: Serial: visor.c: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. CC: Rusty Russell CC: Alan Stern CC: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 97fe005..1129aa7 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c @@ -51,9 +51,6 @@ static int palm_os_3_probe(struct usb_serial *serial, static int palm_os_4_probe(struct usb_serial *serial, const struct usb_device_id *id); -/* Parameters that may be passed into the module. */ -static bool debug; - static struct usb_device_id id_table [] = { { USB_DEVICE(HANDSPRING_VENDOR_ID, HANDSPRING_VISOR_ID), .driver_info = (kernel_ulong_t)&palm_os_3_probe }, @@ -624,6 +621,3 @@ module_usb_serial_driver(serial_drivers, id_table_combined); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v0.10.2 From 07764958947c381ef095fc69503c1ef1775f316e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 10:16:28 +0100 Subject: USB: Serial: whiteheat.c: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. CC: Support Department Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 64d3840..80555fc 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -36,8 +36,6 @@ #include #include "whiteheat.h" /* WhiteHEAT specific commands */ -static bool debug; - #ifndef CMSPAR #define CMSPAR 0 #endif @@ -918,6 +916,3 @@ MODULE_LICENSE("GPL"); MODULE_FIRMWARE("whiteheat.fw"); MODULE_FIRMWARE("whiteheat_loader.fw"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v0.10.2 From d3d6c328e5030da560dcbaaa9ced063d5ba93642 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 15:27:50 +0100 Subject: USB: Serial: omninet: Fix compiler warning. I forgot to remove an unused variable. Reported-by: Fengguang Wu Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index 4803b5e..6def58b 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c @@ -162,7 +162,6 @@ static void omninet_read_bulk_callback(struct urb *urb) struct omninet_header *header = (struct omninet_header *) &data[0]; int status = urb->status; int result; - int i; if (status) { dev_dbg(&port->dev, "%s - nonzero read bulk status received: %d\n", -- cgit v0.10.2 From 3033bc8d74c1a9d9104b9f231283e780e6dd8de7 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 16:05:17 +0100 Subject: USB: Serial: usb-serial: remove debug module parameter Now that all usb-serial modules are only using dev_dbg() the debug module parameter does not do anything at all, so remove it to reduce any confusion if someone were to try to use it. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 335f98d..6ea18a1 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c @@ -22,8 +22,6 @@ #include #include -static int debug; - struct usbcons_info { int magic; int break_flag; @@ -283,10 +281,8 @@ void usb_serial_console_disconnect(struct usb_serial *serial) } } -void usb_serial_console_init(int serial_debug, int minor) +void usb_serial_console_init(int minor) { - debug = serial_debug; - if (minor == 0) { /* * Call register_console() if this is the first device plugged diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 47e2280..2966121 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -24,8 +24,6 @@ #include #include -static int debug; - #ifdef CONFIG_USB_SERIAL_GENERIC static __u16 vendor = 0x05f9; @@ -60,11 +58,10 @@ static struct usb_serial_driver * const serial_drivers[] = { #endif -int usb_serial_generic_register(int _debug) +int usb_serial_generic_register(void) { int retval = 0; - debug = _debug; #ifdef CONFIG_USB_SERIAL_GENERIC generic_device_ids[0].idVendor = vendor; generic_device_ids[0].idProduct = product; diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 8a9352b..001185d 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -52,7 +52,6 @@ drivers depend on it. */ -static bool debug; /* initially all NULL */ static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; static DEFINE_MUTEX(table_lock); @@ -1074,7 +1073,7 @@ static int usb_serial_probe(struct usb_interface *interface, serial->disconnected = 0; - usb_serial_console_init(debug, minor); + usb_serial_console_init(minor); exit: module_put(type->driver.owner); return 0; @@ -1259,7 +1258,7 @@ static int __init usb_serial_init(void) } /* register the generic driver, if we should */ - result = usb_serial_generic_register(debug); + result = usb_serial_generic_register(); if (result < 0) { pr_err("%s - registering generic driver failed\n", __func__); goto exit_generic; @@ -1464,6 +1463,3 @@ EXPORT_SYMBOL_GPL(usb_serial_deregister_drivers); MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index b2b6d15..5808713 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -307,11 +307,11 @@ extern int ezusb_set_reset(struct usb_device *dev, unsigned char reset_bit); /* USB Serial console functions */ #ifdef CONFIG_USB_SERIAL_CONSOLE -extern void usb_serial_console_init(int debug, int minor); +extern void usb_serial_console_init(int minor); extern void usb_serial_console_exit(void); extern void usb_serial_console_disconnect(struct usb_serial *serial); #else -static inline void usb_serial_console_init(int debug, int minor) { } +static inline void usb_serial_console_init(int minor) { } static inline void usb_serial_console_exit(void) { } static inline void usb_serial_console_disconnect(struct usb_serial *serial) {} #endif @@ -333,7 +333,7 @@ extern void usb_serial_generic_throttle(struct tty_struct *tty); extern void usb_serial_generic_unthrottle(struct tty_struct *tty); extern void usb_serial_generic_disconnect(struct usb_serial *serial); extern void usb_serial_generic_release(struct usb_serial *serial); -extern int usb_serial_generic_register(int debug); +extern int usb_serial_generic_register(void); extern void usb_serial_generic_deregister(void); extern int usb_serial_generic_submit_read_urbs(struct usb_serial_port *port, gfp_t mem_flags); -- cgit v0.10.2 From c6ab0158007e5ed9108fd74fe0f61b5b2a326eb9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 16:55:48 +0100 Subject: USB: serial: ezusb: remove last printk() call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This code shouldn't be calling printk(), no one needs to know this debug message, the return code is good enough. Cc: "René Bürgel" Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c index 3048b52d..a9b5263 100644 --- a/drivers/usb/serial/ezusb.c +++ b/drivers/usb/serial/ezusb.c @@ -26,11 +26,8 @@ int ezusb_writememory(struct usb_device *dev, int address, int result; unsigned char *transfer_buffer; - if (!dev) { - printk(KERN_ERR "ezusb: %s - no physical device present, " - "failing.\n", __func__); + if (!dev) return -ENODEV; - } transfer_buffer = kmemdup(data, length, GFP_KERNEL); if (!transfer_buffer) { -- cgit v0.10.2 From 1a71bd2e9731f04a72712aea936627b453233e1e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 16:57:35 +0100 Subject: USB: serial: ftdi_sio: remove startup message No one needs to know that the driver is loaded (almost all other USB serial drivers are now quiet), so just load quietly. Also remove unused, and unneeded version information from the driver, that was pointless. Cc: Uwe Bonnes Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index dcc05fd..8742a0e 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -48,10 +48,6 @@ #include "ftdi_sio.h" #include "ftdi_sio_ids.h" -/* - * Version Information - */ -#define DRIVER_VERSION "v1.6.0" #define DRIVER_AUTHOR "Greg Kroah-Hartman , Bill Ryder , Kuba Ober , Andreas Mohr, Johan Hovold " #define DRIVER_DESC "USB FTDI Serial Converters Driver" @@ -2419,8 +2415,6 @@ static int ftdi_ioctl(struct tty_struct *tty, static int __init ftdi_init(void) { - int retval; - if (vendor > 0 && product > 0) { /* Add user specified VID/PID to reserved element of table. */ int i; @@ -2430,11 +2424,7 @@ static int __init ftdi_init(void) id_table_combined[i].idVendor = vendor; id_table_combined[i].idProduct = product; } - retval = usb_serial_register_drivers(serial_drivers, KBUILD_MODNAME, id_table_combined); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; + return usb_serial_register_drivers(serial_drivers, KBUILD_MODNAME, id_table_combined); } static void __exit ftdi_exit(void) -- cgit v0.10.2 From d9bb03dc89c1d63e307cb0bad60b5f6faa16af6f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 16:59:23 +0100 Subject: USB: serial: io_ti: remove some remaining printk() calls Use dev_err() like the rest of that function does, and the rest of the driver does, to properly show what device and driver caused the problem. Cc: Johan Hovold Cc: "Eric W. Biederman" Cc: Rusty Russell Cc: Alan Stern Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 6317254..21c7efa 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c @@ -845,8 +845,8 @@ static int build_i2c_fw_hdr(__u8 *header, struct device *dev) err = request_firmware(&fw, fw_name, dev); if (err) { - printk(KERN_ERR "Failed to load image \"%s\" err %d\n", - fw_name, err); + dev_err(dev, "Failed to load image \"%s\" err %d\n", + fw_name, err); kfree(buffer); return err; } @@ -1404,8 +1404,8 @@ static int download_fw(struct edgeport_serial *serial) err = request_firmware(&fw, fw_name, dev); if (err) { - printk(KERN_ERR "Failed to load image \"%s\" err %d\n", - fw_name, err); + dev_err(dev, "Failed to load image \"%s\" err %d\n", + fw_name, err); kfree(buffer); return err; } -- cgit v0.10.2 From 7663e3088dcf810435c644f73bd2909362b8dc49 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 17:00:48 +0100 Subject: USB: serial: ir-usb: remove startup noise Don't be telling the syslog that the driver was loaded, the majority of the usb-serial drivers do not, so this one shouldn't either. Also remove the pointless driver version information. Cc: Rusty Russell Cc: Johan Hovold Cc: Alan Stern Cc: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 7b7319d..4ac3a3a 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c @@ -38,10 +38,6 @@ #include #include -/* - * Version Information - */ -#define DRIVER_VERSION "v0.5" #define DRIVER_AUTHOR "Greg Kroah-Hartman , Johan Hovold " #define DRIVER_DESC "USB IR Dongle driver" @@ -428,18 +424,12 @@ err_buf: static int __init ir_init(void) { - int retval; - if (buffer_size) { ir_device.bulk_in_size = buffer_size; ir_device.bulk_out_size = buffer_size; } - retval = usb_serial_register_drivers(serial_drivers, KBUILD_MODNAME, ir_id_table); - if (retval == 0) - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return retval; + return usb_serial_register_drivers(serial_drivers, KBUILD_MODNAME, ir_id_table); } static void __exit ir_exit(void) -- cgit v0.10.2 From 6c27ad83ace843d339f7893a4af0b65cdfeb130c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 17:03:31 +0100 Subject: USB: serial: kobil_sct: switch 4 remaining printk() calls to use dev_dbg These somehow got missed previously (as they weren't calling dbg(), but rather printk() directly), so move over to using dev_dbg() as we never want to see startup messages unless debugging is enabled. Cc: Johan Hovold Cc: Alan Stern Cc: Felipe Balbi Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 30f07db..ca62fcc 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -137,17 +137,16 @@ static int kobil_startup(struct usb_serial *serial) switch (priv->device_type) { case KOBIL_ADAPTER_B_PRODUCT_ID: - printk(KERN_DEBUG "KOBIL B1 PRO / KAAN PRO detected\n"); + dev_dbg(&serial->dev->dev, "KOBIL B1 PRO / KAAN PRO detected\n"); break; case KOBIL_ADAPTER_K_PRODUCT_ID: - printk(KERN_DEBUG - "KOBIL KAAN Standard Plus / SecOVID Reader Plus detected\n"); + dev_dbg(&serial->dev->dev, "KOBIL KAAN Standard Plus / SecOVID Reader Plus detected\n"); break; case KOBIL_USBTWIN_PRODUCT_ID: - printk(KERN_DEBUG "KOBIL USBTWIN detected\n"); + dev_dbg(&serial->dev->dev, "KOBIL USBTWIN detected\n"); break; case KOBIL_KAAN_SIM_PRODUCT_ID: - printk(KERN_DEBUG "KOBIL KAAN SIM detected\n"); + dev_dbg(&serial->dev->dev, "KOBIL KAAN SIM detected\n"); break; } usb_set_serial_port_data(serial->port[0], priv); -- cgit v0.10.2 From 788a661a9fa59740984f509832cae33dde4b0329 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 17:05:37 +0100 Subject: USB: serial: quatech2: fix up unneeded printk() call It should be calling dev_err() instead of printk(KERN_INFO...) so this change fixes that up properly. Cc: Bill Pemberton Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index e60f27b..c1024b1 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c @@ -1087,7 +1087,7 @@ static int qt2_write(struct tty_struct *tty, data = write_urb->transfer_buffer; spin_lock_irqsave(&port_priv->urb_lock, flags); if (port_priv->urb_in_use == true) { - printk(KERN_INFO "qt2_write - urb is in use\n"); + dev_err(&port->dev, "qt2_write - urb is in use\n"); goto write_out; } -- cgit v0.10.2 From 93ba0f037bfc7d6c6431c0db767f2244ac583578 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 17:07:24 +0100 Subject: USB: serial: safe-serial: fix up printk() usage The driver was calling printk() directly at startup, which is just noise. Switch over to using pr_info() where needed, and get rid of the totally useless version number that had never ever been incremented. Cc: Rusty Russell Cc: Alan Stern Cc: Mauro Carvalho Chehab Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/safe_serial.c b/drivers/usb/serial/safe_serial.c index e3457e2..c949ce6 100644 --- a/drivers/usb/serial/safe_serial.c +++ b/drivers/usb/serial/safe_serial.c @@ -62,6 +62,7 @@ * */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include #include @@ -84,7 +85,6 @@ static bool safe = 1; static bool padded = CONFIG_USB_SERIAL_SAFE_PADDED; -#define DRIVER_VERSION "v0.1" #define DRIVER_AUTHOR "sl@lineo.com, tbr@lineo.com, Johan Hovold " #define DRIVER_DESC "USB Safe Encapsulated Serial" @@ -311,13 +311,9 @@ static int __init safe_init(void) { int i; - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - /* if we have vendor / product parameters patch them into id list */ if (vendor || product) { - printk(KERN_INFO KBUILD_MODNAME ": vendor: %x product: %x\n", - vendor, product); + pr_info("vendor: %x product: %x\n", vendor, product); for (i = 0; i < ARRAY_SIZE(id_table); i++) { if (!id_table[i].idVendor && !id_table[i].idProduct) { -- cgit v0.10.2 From f378dfe4bef8d77dbd420a12bd75fd09395bc3d8 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 17:09:00 +0100 Subject: USB: serial: ti_usb_3410_5052: fix up noisy printk() usage The driver should not be sending any printk() messages when it is loaded, as no other USB serial driver does. This fixes that, and also removes the useless version number from the driver. Cc: Johan Hovold Cc: Rusty Russell Cc: Adhir Ramjiawan Cc: Andrew Lunn Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index e6f492d..648249e 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c @@ -40,7 +40,6 @@ /* Defines */ -#define TI_DRIVER_VERSION "v0.10" #define TI_DRIVER_AUTHOR "Al Borchers " #define TI_DRIVER_DESC "TI USB 3410/5052 Serial Driver" @@ -276,7 +275,6 @@ static struct usb_serial_driver * const serial_drivers[] = { MODULE_AUTHOR(TI_DRIVER_AUTHOR); MODULE_DESCRIPTION(TI_DRIVER_DESC); -MODULE_VERSION(TI_DRIVER_VERSION); MODULE_LICENSE("GPL"); MODULE_FIRMWARE("ti_3410.fw"); @@ -312,7 +310,6 @@ MODULE_DEVICE_TABLE(usb, ti_id_table_combined); static int __init ti_init(void) { int i, j, c; - int ret; /* insert extra vendor and product ids */ c = ARRAY_SIZE(ti_id_table_combined) - 2 * TI_EXTRA_VID_PID_COUNT - 1; @@ -335,11 +332,7 @@ static int __init ti_init(void) ti_id_table_combined[c].match_flags = USB_DEVICE_ID_MATCH_DEVICE; } - ret = usb_serial_register_drivers(serial_drivers, KBUILD_MODNAME, ti_id_table_combined); - if (ret == 0) - printk(KERN_INFO KBUILD_MODNAME ": " TI_DRIVER_VERSION ":" - TI_DRIVER_DESC "\n"); - return ret; + return usb_serial_register_drivers(serial_drivers, KBUILD_MODNAME, ti_id_table_combined); } static void __exit ti_exit(void) -- cgit v0.10.2 From ee42f6c9fc62d1d4d45b0d75e5f947e6645d8c30 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 18 Sep 2012 17:10:29 +0100 Subject: USB: serial: core: fix up printk() usage This moves to using pr_info() where needed instead of a "raw" printk() call, making the whole driver more unified. It also cleans up my email address in the MODULE_AUTHOR field. Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 001185d..011c520 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -39,10 +39,7 @@ #include #include "pl2303.h" -/* - * Version Information - */ -#define DRIVER_AUTHOR "Greg Kroah-Hartman, greg@kroah.com, http://www.kroah.com/linux/" +#define DRIVER_AUTHOR "Greg Kroah-Hartman " #define DRIVER_DESC "USB Serial Driver core" /* There is no MODULE_DEVICE_TABLE for usbserial.c. Instead @@ -1264,8 +1261,6 @@ static int __init usb_serial_init(void) goto exit_generic; } - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_DESC "\n"); - return result; exit_generic: @@ -1350,8 +1345,7 @@ static int usb_serial_register(struct usb_serial_driver *driver) pr_err("problem %d when registering driver %s\n", retval, driver->description); list_del(&driver->driver_list); } else - printk(KERN_INFO "USB Serial support registered for %s\n", - driver->description); + pr_info("USB Serial support registered for %s\n", driver->description); mutex_unlock(&table_lock); return retval; @@ -1359,8 +1353,7 @@ static int usb_serial_register(struct usb_serial_driver *driver) static void usb_serial_deregister(struct usb_serial_driver *device) { - printk(KERN_INFO "USB Serial deregistering driver %s\n", - device->description); + pr_info("USB Serial deregistering driver %s\n", device->description); mutex_lock(&table_lock); list_del(&device->driver_list); usb_serial_bus_deregister(device); -- cgit v0.10.2 From 9fa5780beea1274d498a224822397100022da7d4 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Tue, 18 Sep 2012 12:23:02 +0100 Subject: USB EHCI/Xen: propagate controller reset information to hypervisor Just like for the in-tree early console debug port driver, the hypervisor - when using a debug port based console - also needs to be told about controller resets, so it can suppress using and then re-initialize the debug port accordingly. Other than the in-tree driver, the hypervisor driver actually cares about doing this only for the device where the debug is port actually in use, i.e. it needs to be told the coordinates of the device being reset (quite obviously, leveraging the addition done for that would likely benefit the in-tree driver too). Signed-off-by: Jan Beulich Acked-by: Konrad Rzeszutek Wilk Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/early/ehci-dbgp.c b/drivers/usb/early/ehci-dbgp.c index 89dcf15..e426ad6 100644 --- a/drivers/usb/early/ehci-dbgp.c +++ b/drivers/usb/early/ehci-dbgp.c @@ -491,7 +491,7 @@ static int ehci_wait_for_port(int port); * Return -ENODEV for any general failure * Return -EIO if wait for port fails */ -int dbgp_external_startup(void) +static int _dbgp_external_startup(void) { int devnum; struct usb_debug_descriptor dbgp_desc; @@ -613,6 +613,11 @@ err: goto try_again; return -ENODEV; } + +int dbgp_external_startup(struct usb_hcd *hcd) +{ + return xen_dbgp_external_startup(hcd) ?: _dbgp_external_startup(); +} EXPORT_SYMBOL_GPL(dbgp_external_startup); static int ehci_reset_port(int port) @@ -804,7 +809,7 @@ try_next_port: dbgp_ehci_status("ehci skip - already configured"); } - ret = dbgp_external_startup(); + ret = _dbgp_external_startup(); if (ret == -EIO) goto next_debug_port; @@ -934,7 +939,7 @@ static void early_dbgp_write(struct console *con, const char *str, u32 n) ctrl = readl(&ehci_debug->control); if (!(ctrl & DBGP_ENABLED)) { dbgp_not_safe = 1; - dbgp_external_startup(); + _dbgp_external_startup(); } else { cmd |= CMD_RUN; writel(cmd, &ehci_regs->command); @@ -974,10 +979,14 @@ struct console early_dbgp_console = { .index = -1, }; -int dbgp_reset_prep(void) +int dbgp_reset_prep(struct usb_hcd *hcd) { + int ret = xen_dbgp_reset_prep(hcd); u32 ctrl; + if (ret) + return ret; + dbgp_not_safe = 1; if (!ehci_debug) return 0; diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index b05c686..6bf6c42 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -228,7 +228,7 @@ static int ehci_reset (struct ehci_hcd *ehci) /* If the EHCI debug controller is active, special care must be * taken before and after a host controller reset */ - if (ehci->debug && !dbgp_reset_prep()) + if (ehci->debug && !dbgp_reset_prep(ehci_to_hcd(ehci))) ehci->debug = NULL; command |= CMD_RESET; @@ -251,7 +251,7 @@ static int ehci_reset (struct ehci_hcd *ehci) tdi_reset (ehci); if (ehci->debug) - dbgp_external_startup(); + dbgp_external_startup(ehci_to_hcd(ehci)); ehci->port_c_suspend = ehci->suspended_ports = ehci->resuming_ports = 0; diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index c788022..914ce93 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -353,10 +353,10 @@ static int ehci_bus_resume (struct usb_hcd *hcd) goto shutdown; if (unlikely(ehci->debug)) { - if (!dbgp_reset_prep()) + if (!dbgp_reset_prep(hcd)) ehci->debug = NULL; else - dbgp_external_startup(); + dbgp_external_startup(hcd); } /* Ideally and we've got a real resume here, and no port's power diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index d80bea5..a4a3cab 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile @@ -18,7 +18,7 @@ obj-$(CONFIG_XEN_PVHVM) += platform-pci.o obj-$(CONFIG_XEN_TMEM) += tmem.o obj-$(CONFIG_SWIOTLB_XEN) += swiotlb-xen.o obj-$(CONFIG_XEN_DOM0) += pcpu.o -obj-$(CONFIG_XEN_DOM0) += pci.o acpi.o +obj-$(CONFIG_XEN_DOM0) += pci.o dbgp.o acpi.o obj-$(CONFIG_XEN_MCE_LOG) += mcelog.o obj-$(CONFIG_XEN_PCIDEV_BACKEND) += xen-pciback/ obj-$(CONFIG_XEN_PRIVCMD) += xen-privcmd.o diff --git a/drivers/xen/dbgp.c b/drivers/xen/dbgp.c new file mode 100644 index 0000000..42569c7 --- /dev/null +++ b/drivers/xen/dbgp.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include +#include +#include +#include + +static int xen_dbgp_op(struct usb_hcd *hcd, int op) +{ + const struct device *ctrlr = hcd_to_bus(hcd)->controller; + struct physdev_dbgp_op dbgp; + + if (!xen_initial_domain()) + return 0; + + dbgp.op = op; + +#ifdef CONFIG_PCI + if (ctrlr->bus == &pci_bus_type) { + const struct pci_dev *pdev = to_pci_dev(ctrlr); + + dbgp.u.pci.seg = pci_domain_nr(pdev->bus); + dbgp.u.pci.bus = pdev->bus->number; + dbgp.u.pci.devfn = pdev->devfn; + dbgp.bus = PHYSDEVOP_DBGP_BUS_PCI; + } else +#endif + dbgp.bus = PHYSDEVOP_DBGP_BUS_UNKNOWN; + + return HYPERVISOR_physdev_op(PHYSDEVOP_dbgp_op, &dbgp); +} + +int xen_dbgp_reset_prep(struct usb_hcd *hcd) +{ + return xen_dbgp_op(hcd, PHYSDEVOP_DBGP_RESET_PREPARE); +} + +int xen_dbgp_external_startup(struct usb_hcd *hcd) +{ + return xen_dbgp_op(hcd, PHYSDEVOP_DBGP_RESET_DONE); +} + +#ifndef CONFIG_EARLY_PRINTK_DBGP +#include +EXPORT_SYMBOL_GPL(xen_dbgp_reset_prep); +EXPORT_SYMBOL_GPL(xen_dbgp_external_startup); +#endif diff --git a/include/linux/usb/ehci_def.h b/include/linux/usb/ehci_def.h index de4b9ed..9a44630 100644 --- a/include/linux/usb/ehci_def.h +++ b/include/linux/usb/ehci_def.h @@ -221,18 +221,35 @@ extern int __init early_dbgp_init(char *s); extern struct console early_dbgp_console; #endif /* CONFIG_EARLY_PRINTK_DBGP */ +struct usb_hcd; + +#ifdef CONFIG_XEN_DOM0 +extern int xen_dbgp_reset_prep(struct usb_hcd *); +extern int xen_dbgp_external_startup(struct usb_hcd *); +#else +static inline int xen_dbgp_reset_prep(struct usb_hcd *hcd) +{ + return 1; /* Shouldn't this be 0? */ +} + +static inline int xen_dbgp_external_startup(struct usb_hcd *hcd) +{ + return -1; +} +#endif + #ifdef CONFIG_EARLY_PRINTK_DBGP /* Call backs from ehci host driver to ehci debug driver */ -extern int dbgp_external_startup(void); -extern int dbgp_reset_prep(void); +extern int dbgp_external_startup(struct usb_hcd *); +extern int dbgp_reset_prep(struct usb_hcd *hcd); #else -static inline int dbgp_reset_prep(void) +static inline int dbgp_reset_prep(struct usb_hcd *hcd) { - return 1; + return xen_dbgp_reset_prep(hcd); } -static inline int dbgp_external_startup(void) +static inline int dbgp_external_startup(struct usb_hcd *hcd) { - return -1; + return xen_dbgp_external_startup(hcd); } #endif diff --git a/include/xen/interface/physdev.h b/include/xen/interface/physdev.h index 9ce788d..bfa1d50 100644 --- a/include/xen/interface/physdev.h +++ b/include/xen/interface/physdev.h @@ -258,6 +258,22 @@ struct physdev_pci_device { uint8_t devfn; }; +#define PHYSDEVOP_DBGP_RESET_PREPARE 1 +#define PHYSDEVOP_DBGP_RESET_DONE 2 + +#define PHYSDEVOP_DBGP_BUS_UNKNOWN 0 +#define PHYSDEVOP_DBGP_BUS_PCI 1 + +#define PHYSDEVOP_dbgp_op 29 +struct physdev_dbgp_op { + /* IN */ + uint8_t op; + uint8_t bus; + union { + struct physdev_pci_device pci; + } u; +}; + /* * Notify that some PIRQ-bound event channels have been unmasked. * ** This command is obsolete since interface version 0x00030202 and is ** -- cgit v0.10.2 From cc183e2a5ebfdddc8d3498149cae6b4c40551a68 Mon Sep 17 00:00:00 2001 From: Rene Buergel Date: Tue, 18 Sep 2012 09:00:41 +0200 Subject: USB: ezusb: add support for Cypress FX2LP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This Patch adds support for the newer Cypress FX2LP. It also adapts three drivers currently using ezusb to the interface change. (whiteheat and keyspan[_pda]) Signed-off-by: René Bürgel Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c index a9b5263..bc3076f 100644 --- a/drivers/usb/serial/ezusb.c +++ b/drivers/usb/serial/ezusb.c @@ -14,11 +14,25 @@ #include #include -/* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */ -#define CPUCS_REG 0x7F92 +struct ezusb_fx_type { + /* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */ + unsigned short cpucs_reg; + unsigned short max_internal_adress; +}; -/* Command for writing to internal memory */ +struct ezusb_fx_type ezusb_fx1 = { + .cpucs_reg = 0x7F92, + .max_internal_adress = 0x1B3F, +}; + +struct ezusb_fx_type ezusb_fx2 = { + .cpucs_reg = 0xE600, + .max_internal_adress = 0x3FFF, +}; + +/* Commands for writing to memory */ #define WRITE_INT_RAM 0xA0 +#define WRITE_EXT_RAM 0xA3 int ezusb_writememory(struct usb_device *dev, int address, unsigned char *data, int length, __u8 request) @@ -44,13 +58,24 @@ int ezusb_writememory(struct usb_device *dev, int address, } EXPORT_SYMBOL_GPL(ezusb_writememory); -int ezusb_set_reset(struct usb_device *dev, unsigned char reset_bit) +int ezusb_set_reset(struct usb_device *dev, unsigned short cpucs_reg, + unsigned char reset_bit) { - int response = ezusb_writememory(dev, CPUCS_REG, &reset_bit, 1, WRITE_INT_RAM); + int response = ezusb_writememory(dev, cpucs_reg, &reset_bit, 1, WRITE_INT_RAM); if (response < 0) dev_err(&dev->dev, "%s-%d failed: %d\n", __func__, reset_bit, response); return response; } -EXPORT_SYMBOL_GPL(ezusb_set_reset); +int ezusb_fx1_set_reset(struct usb_device *dev, unsigned char reset_bit) +{ + return ezusb_set_reset(dev, ezusb_fx1.cpucs_reg, reset_bit); +} +EXPORT_SYMBOL_GPL(ezusb_fx1_set_reset); + +int ezusb_fx2_set_reset(struct usb_device *dev, unsigned char reset_bit) +{ + return ezusb_set_reset(dev, ezusb_fx2.cpucs_reg, reset_bit); +} +EXPORT_SYMBOL_GPL(ezusb_fx2_set_reset); diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 566056c..4f25849 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -43,6 +43,7 @@ #include #include #include +#include #include "keyspan.h" /* @@ -1245,7 +1246,7 @@ static int keyspan_fake_startup(struct usb_serial *serial) dev_dbg(&serial->dev->dev, "Uploading Keyspan %s firmware.\n", fw_name); /* download the firmware image */ - response = ezusb_set_reset(serial->dev, 1); + response = ezusb_fx1_set_reset(serial->dev, 1); record = (const struct ihex_binrec *)fw->data; @@ -1264,7 +1265,7 @@ static int keyspan_fake_startup(struct usb_serial *serial) release_firmware(fw); /* bring device out of reset. Renumeration will occur in a moment and the new device will bind to the real driver */ - response = ezusb_set_reset(serial->dev, 0); + response = ezusb_fx1_set_reset(serial->dev, 0); /* we don't want this device to have a driver assigned to it. */ return 1; diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 124d4e5..39ab668 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -30,6 +30,7 @@ #include #include #include +#include /* make a simple define to handle if we are compiling keyspan_pda or xircom support */ #if defined(CONFIG_USB_SERIAL_KEYSPAN_PDA) || defined(CONFIG_USB_SERIAL_KEYSPAN_PDA_MODULE) @@ -678,7 +679,7 @@ static int keyspan_pda_fake_startup(struct usb_serial *serial) const struct firmware *fw; /* download the firmware here ... */ - response = ezusb_set_reset(serial->dev, 1); + response = ezusb_fx1_set_reset(serial->dev, 1); if (0) { ; } #ifdef KEYSPAN @@ -718,7 +719,7 @@ static int keyspan_pda_fake_startup(struct usb_serial *serial) release_firmware(fw); /* bring device out of reset. Renumeration will occur in a moment and the new device will bind to the real driver */ - response = ezusb_set_reset(serial->dev, 0); + response = ezusb_fx1_set_reset(serial->dev, 0); /* we want this device to fail to have a driver assigned to it. */ return 1; diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 80555fc..8172ea3 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include "whiteheat.h" /* WhiteHEAT specific commands */ @@ -211,7 +212,7 @@ static int whiteheat_firmware_download(struct usb_serial *serial, goto out; } ret = 0; - response = ezusb_set_reset(serial->dev, 1); + response = ezusb_fx1_set_reset(serial->dev, 1); record = (const struct ihex_binrec *)loader_fw->data; while (record) { @@ -228,7 +229,7 @@ static int whiteheat_firmware_download(struct usb_serial *serial, record = ihex_next_binrec(record); } - response = ezusb_set_reset(serial->dev, 0); + response = ezusb_fx1_set_reset(serial->dev, 0); record = (const struct ihex_binrec *)firmware_fw->data; while (record && be32_to_cpu(record->addr) < 0x1b40) @@ -248,7 +249,7 @@ static int whiteheat_firmware_download(struct usb_serial *serial, ++record; } - response = ezusb_set_reset(serial->dev, 1); + response = ezusb_fx1_set_reset(serial->dev, 1); record = (const struct ihex_binrec *)firmware_fw->data; while (record && be32_to_cpu(record->addr) < 0x1b40) { @@ -266,7 +267,7 @@ static int whiteheat_firmware_download(struct usb_serial *serial, ++record; } ret = 0; - response = ezusb_set_reset(serial->dev, 0); + response = ezusb_fx1_set_reset(serial->dev, 0); out: release_firmware(loader_fw); release_firmware(firmware_fw); diff --git a/include/linux/usb/ezusb.h b/include/linux/usb/ezusb.h new file mode 100644 index 0000000..fc618d8 --- /dev/null +++ b/include/linux/usb/ezusb.h @@ -0,0 +1,16 @@ +#ifndef __EZUSB_H +#define __EZUSB_H + + +extern int ezusb_writememory(struct usb_device *dev, int address, + unsigned char *data, int length, __u8 bRequest); + +extern int ezusb_fx1_set_reset(struct usb_device *dev, unsigned char reset_bit); +extern int ezusb_fx2_set_reset(struct usb_device *dev, unsigned char reset_bit); + +extern int ezusb_fx1_ihex_firmware_download(struct usb_device *dev, + const char *firmware_path); +extern int ezusb_fx2_ihex_firmware_download(struct usb_device *dev, + const char *firmware_path); + +#endif /* __EZUSB_H */ diff --git a/include/linux/usb/serial.h b/include/linux/usb/serial.h index 5808713..ef9be7e 100644 --- a/include/linux/usb/serial.h +++ b/include/linux/usb/serial.h @@ -301,10 +301,6 @@ extern void usb_serial_port_softint(struct usb_serial_port *port); extern int usb_serial_suspend(struct usb_interface *intf, pm_message_t message); extern int usb_serial_resume(struct usb_interface *intf); -extern int ezusb_writememory(struct usb_device *dev, int address, - unsigned char *data, int length, __u8 bRequest); -extern int ezusb_set_reset(struct usb_device *dev, unsigned char reset_bit); - /* USB Serial console functions */ #ifdef CONFIG_USB_SERIAL_CONSOLE extern void usb_serial_console_init(int minor); -- cgit v0.10.2 From 8d733e26c076f47e7774c0e5baa74c9b1c01199a Mon Sep 17 00:00:00 2001 From: Rene Buergel Date: Tue, 18 Sep 2012 09:02:01 +0200 Subject: USB: ezusb: add functions for firmware download MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch adds new functions to upload firmware to the controller. The drivers currently using ezusb are adapted to use these new functions. This also fixes a bug occuring during firmware loading in the whiteheat-driver: The driver iterates over an ihex-formatted firmware using ++ on a "const struct ihex_binrec*" which leads to faulty results, because ihex data is read as length. The function "ihex_next_binrec(record)" has so be used to work correctly Signed-off-by: René Bürgel Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c index bc3076f..4223d76 100644 --- a/drivers/usb/serial/ezusb.c +++ b/drivers/usb/serial/ezusb.c @@ -13,6 +13,8 @@ #include #include #include +#include +#include struct ezusb_fx_type { /* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */ @@ -79,3 +81,80 @@ int ezusb_fx2_set_reset(struct usb_device *dev, unsigned char reset_bit) return ezusb_set_reset(dev, ezusb_fx2.cpucs_reg, reset_bit); } EXPORT_SYMBOL_GPL(ezusb_fx2_set_reset); + +static int ezusb_ihex_firmware_download(struct usb_device *dev, + struct ezusb_fx_type fx, + const char *firmware_path) +{ + int ret = -ENOENT; + const struct firmware *firmware = NULL; + const struct ihex_binrec *record; + + if (request_ihex_firmware(&firmware, firmware_path, + &dev->dev)) { + dev_err(&dev->dev, + "%s - request \"%s\" failed\n", + __func__, firmware_path); + goto out; + } + + ret = ezusb_set_reset(dev, fx.cpucs_reg, 0); + if (ret < 0) + goto out; + + record = (const struct ihex_binrec *)firmware->data; + for (; record; record = ihex_next_binrec(record)) { + if (be32_to_cpu(record->addr) > fx.max_internal_adress) { + ret = ezusb_writememory(dev, be32_to_cpu(record->addr), + (unsigned char *)record->data, + be16_to_cpu(record->len), WRITE_EXT_RAM); + if (ret < 0) { + dev_err(&dev->dev, "%s - ezusb_writememory " + "failed writing internal memory " + "(%d %04X %p %d)\n", __func__, ret, + be32_to_cpu(record->addr), record->data, + be16_to_cpu(record->len)); + goto out; + } + } + } + + ret = ezusb_set_reset(dev, fx.cpucs_reg, 1); + if (ret < 0) + goto out; + record = (const struct ihex_binrec *)firmware->data; + for (; record; record = ihex_next_binrec(record)) { + if (be32_to_cpu(record->addr) <= fx.max_internal_adress) { + ret = ezusb_writememory(dev, be32_to_cpu(record->addr), + (unsigned char *)record->data, + be16_to_cpu(record->len), WRITE_INT_RAM); + if (ret < 0) { + dev_err(&dev->dev, "%s - ezusb_writememory " + "failed writing external memory " + "(%d %04X %p %d)\n", __func__, ret, + be32_to_cpu(record->addr), record->data, + be16_to_cpu(record->len)); + goto out; + } + } + } + ret = ezusb_set_reset(dev, fx.cpucs_reg, 0); +out: + release_firmware(firmware); + return ret; +} + +int ezusb_fx1_ihex_firmware_download(struct usb_device *dev, + const char *firmware_path) +{ + return ezusb_ihex_firmware_download(dev, ezusb_fx1, firmware_path); +} +EXPORT_SYMBOL_GPL(ezusb_fx1_ihex_firmware_download); + +int ezusb_fx2_ihex_firmware_download(struct usb_device *dev, + const char *firmware_path) +{ + return ezusb_ihex_firmware_download(dev, ezusb_fx2, firmware_path); +} +EXPORT_SYMBOL_GPL(ezusb_fx2_ihex_firmware_download); + diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 4f25849..0acb071 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -38,8 +38,6 @@ #include #include #include -#include -#include #include #include #include @@ -1167,10 +1165,7 @@ static void keyspan_close(struct usb_serial_port *port) /* download the firmware to a pre-renumeration device */ static int keyspan_fake_startup(struct usb_serial *serial) { - int response; - const struct ihex_binrec *record; - char *fw_name; - const struct firmware *fw; + char *fw_name; dev_dbg(&serial->dev->dev, "Keyspan startup version %04x product %04x\n", le16_to_cpu(serial->dev->descriptor.bcdDevice), @@ -1238,34 +1233,16 @@ static int keyspan_fake_startup(struct usb_serial *serial) return 1; } - if (request_ihex_firmware(&fw, fw_name, &serial->dev->dev)) { - dev_err(&serial->dev->dev, "Required keyspan firmware image (%s) unavailable.\n", fw_name); - return 1; - } - dev_dbg(&serial->dev->dev, "Uploading Keyspan %s firmware.\n", fw_name); - /* download the firmware image */ - response = ezusb_fx1_set_reset(serial->dev, 1); - - record = (const struct ihex_binrec *)fw->data; - - while (record) { - response = ezusb_writememory(serial->dev, be32_to_cpu(record->addr), - (unsigned char *)record->data, - be16_to_cpu(record->len), 0xa0); - if (response < 0) { - dev_err(&serial->dev->dev, "ezusb_writememory failed for Keyspan firmware (%d %04X %p %d)\n", - response, be32_to_cpu(record->addr), - record->data, be16_to_cpu(record->len)); - break; - } - record = ihex_next_binrec(record); + if (ezusb_fx1_ihex_firmware_download(serial->dev, fw_name) < 0) { + dev_err(&serial->dev->dev, "failed to load firmware \"%s\"\n", + fw_name); + return -ENOENT; } - release_firmware(fw); - /* bring device out of reset. Renumeration will occur in a - moment and the new device will bind to the real driver */ - response = ezusb_fx1_set_reset(serial->dev, 0); + + /* after downloading firmware Renumeration will occur in a + moment and the new device will bind to the real driver */ /* we don't want this device to have a driver assigned to it. */ return 1; diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index 39ab668..e1cada3 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c @@ -25,8 +25,6 @@ #include #include #include -#include -#include #include #include #include @@ -675,8 +673,6 @@ static int keyspan_pda_fake_startup(struct usb_serial *serial) { int response; const char *fw_name; - const struct ihex_binrec *record; - const struct firmware *fw; /* download the firmware here ... */ response = ezusb_fx1_set_reset(serial->dev, 1); @@ -696,30 +692,15 @@ static int keyspan_pda_fake_startup(struct usb_serial *serial) __func__); return -ENODEV; } - if (request_ihex_firmware(&fw, fw_name, &serial->dev->dev)) { + + if (ezusb_fx1_ihex_firmware_download(serial->dev, fw_name) < 0) { dev_err(&serial->dev->dev, "failed to load firmware \"%s\"\n", fw_name); return -ENOENT; } - record = (const struct ihex_binrec *)fw->data; - - while (record) { - response = ezusb_writememory(serial->dev, be32_to_cpu(record->addr), - (unsigned char *)record->data, - be16_to_cpu(record->len), 0xa0); - if (response < 0) { - dev_err(&serial->dev->dev, "ezusb_writememory failed " - "for Keyspan PDA firmware (%d %04X %p %d)\n", - response, be32_to_cpu(record->addr), - record->data, be16_to_cpu(record->len)); - break; - } - record = ihex_next_binrec(record); - } - release_firmware(fw); - /* bring device out of reset. Renumeration will occur in a moment - and the new device will bind to the real driver */ - response = ezusb_fx1_set_reset(serial->dev, 0); + + /* after downloading firmware Renumeration will occur in a + moment and the new device will bind to the real driver */ /* we want this device to fail to have a driver assigned to it. */ return 1; diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 8172ea3..efa32bf 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c @@ -33,8 +33,6 @@ #include #include #include -#include -#include #include "whiteheat.h" /* WhiteHEAT specific commands */ #ifndef CMSPAR @@ -194,84 +192,15 @@ static int firm_report_tx_done(struct usb_serial_port *port); static int whiteheat_firmware_download(struct usb_serial *serial, const struct usb_device_id *id) { - int response, ret = -ENOENT; - const struct firmware *loader_fw = NULL, *firmware_fw = NULL; - const struct ihex_binrec *record; + int response; - if (request_ihex_firmware(&firmware_fw, "whiteheat.fw", - &serial->dev->dev)) { - dev_err(&serial->dev->dev, - "%s - request \"whiteheat.fw\" failed\n", __func__); - goto out; - } - if (request_ihex_firmware(&loader_fw, "whiteheat_loader.fw", - &serial->dev->dev)) { - dev_err(&serial->dev->dev, - "%s - request \"whiteheat_loader.fw\" failed\n", - __func__); - goto out; - } - ret = 0; - response = ezusb_fx1_set_reset(serial->dev, 1); - - record = (const struct ihex_binrec *)loader_fw->data; - while (record) { - response = ezusb_writememory(serial->dev, be32_to_cpu(record->addr), - (unsigned char *)record->data, - be16_to_cpu(record->len), 0xa0); - if (response < 0) { - dev_err(&serial->dev->dev, "%s - ezusb_writememory " - "failed for loader (%d %04X %p %d)\n", - __func__, response, be32_to_cpu(record->addr), - record->data, be16_to_cpu(record->len)); - break; - } - record = ihex_next_binrec(record); - } - - response = ezusb_fx1_set_reset(serial->dev, 0); - - record = (const struct ihex_binrec *)firmware_fw->data; - while (record && be32_to_cpu(record->addr) < 0x1b40) - record = ihex_next_binrec(record); - while (record) { - response = ezusb_writememory(serial->dev, be32_to_cpu(record->addr), - (unsigned char *)record->data, - be16_to_cpu(record->len), 0xa3); - if (response < 0) { - dev_err(&serial->dev->dev, "%s - ezusb_writememory " - "failed for first firmware step " - "(%d %04X %p %d)\n", __func__, response, - be32_to_cpu(record->addr), record->data, - be16_to_cpu(record->len)); - break; - } - ++record; - } - - response = ezusb_fx1_set_reset(serial->dev, 1); - - record = (const struct ihex_binrec *)firmware_fw->data; - while (record && be32_to_cpu(record->addr) < 0x1b40) { - response = ezusb_writememory(serial->dev, be32_to_cpu(record->addr), - (unsigned char *)record->data, - be16_to_cpu(record->len), 0xa0); - if (response < 0) { - dev_err(&serial->dev->dev, "%s - ezusb_writememory " - "failed for second firmware step " - "(%d %04X %p %d)\n", __func__, response, - be32_to_cpu(record->addr), record->data, - be16_to_cpu(record->len)); - break; - } - ++record; + response = ezusb_fx1_ihex_firmware_download(serial->dev, "whiteheat_loader.fw"); + if (response >= 0) { + response = ezusb_fx1_ihex_firmware_download(serial->dev, "whiteheat.fw"); + if (response >= 0) + return 0; } - ret = 0; - response = ezusb_fx1_set_reset(serial->dev, 0); - out: - release_firmware(loader_fw); - release_firmware(firmware_fw); - return ret; + return -ENOENT; } -- cgit v0.10.2 From 45c2da62199bcea380273b2fba7fa16c1ff27a30 Mon Sep 17 00:00:00 2001 From: Jim Lin Date: Tue, 18 Sep 2012 16:42:17 +0800 Subject: USB: EHCI: Tegra: Fix wrong register definition Fix the issue that EHCI registers, hostpc[0] and usbmode_ex, are not correctly accessed on Tegra3 platform. Signed-off-by: Jim Lin Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman diff --git a/include/linux/usb/ehci_def.h b/include/linux/usb/ehci_def.h index 9a44630..daec99a 100644 --- a/include/linux/usb/ehci_def.h +++ b/include/linux/usb/ehci_def.h @@ -171,18 +171,18 @@ struct ehci_regs { #define USBMODE_CM_HC (3<<0) /* host controller mode */ #define USBMODE_CM_IDLE (0<<0) /* idle state */ - u32 reserved4[7]; + u32 reserved4[6]; /* Moorestown has some non-standard registers, partially due to the fact that * its EHCI controller has both TT and LPM support. HOSTPCx are extensions to * PORTSCx */ /* HOSTPC: offset 0x84 */ - u32 hostpc[0]; /* HOSTPC extension */ + u32 hostpc[1]; /* HOSTPC extension */ #define HOSTPC_PHCD (1<<22) /* Phy clock disable */ #define HOSTPC_PSPD (3<<25) /* Port speed detection */ - u32 reserved5[17]; + u32 reserved5[16]; /* USBMODE_EX: offset 0xc8 */ u32 usbmode_ex; /* USB Device mode extension */ -- cgit v0.10.2 From 44b0f0836b62171617d56c6528c821ceaa6ea506 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 19 Sep 2012 08:15:21 +0100 Subject: USB: serial: fix up bug with missing {} As reported by Fengguang: FYI, coccinelle warns about drivers/usb/serial/usb-serial.c:1415:3-51: code aligned with following code on line 1416 vim +1415 drivers/usb/serial/usb-serial.c 1412 /* we only set the reset_resume field if the serial_driver has one */ 1413 for (sd = serial_drivers; *sd; ++sd) { 1414 if ((*sd)->reset_resume) > 1415 udriver->reset_resume = usb_serial_reset_resume; > 1416 break; 1417 } Reported-by: Fengguang Wu Cc: stable [3.5] Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 011c520..483919b 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1404,9 +1404,10 @@ int usb_serial_register_drivers(struct usb_serial_driver *const serial_drivers[] /* we only set the reset_resume field if the serial_driver has one */ for (sd = serial_drivers; *sd; ++sd) { - if ((*sd)->reset_resume) + if ((*sd)->reset_resume) { udriver->reset_resume = usb_serial_reset_resume; break; + } } rc = usb_register(udriver); -- cgit v0.10.2 From 0cb72e184ac4d83705147eee07ba978473b75015 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 21 Sep 2012 16:46:38 +0100 Subject: USB: serial: vizzini: remove outdated comment I fixed up all of the #ifdef stuff, so remove the comment saying it still needs to be removed. Reported-by: Alan Cox Cc: Rob Duncan Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/vizzini.c b/drivers/usb/serial/vizzini.c index 2ac48fe..7f43694 100644 --- a/drivers/usb/serial/vizzini.c +++ b/drivers/usb/serial/vizzini.c @@ -37,15 +37,6 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -/* This version of the Linux driver source contains a number of - abominable conditional compilation sections to manage the API - changes between kernel versions 2.6.18, 2.6.25, and the latest - (currently 2.6.27). At some point we'll hand a version of this - driver off to the mainline Linux source tree, and we'll strip all - these sections out. For now it makes it much easier to keep it all - in sync while the driver is being developed. */ - - #define DRIVER_VERSION "v.0.76" #define DRIVER_AUTHOR "Rob Duncan " #define DRIVER_DESC "USB Driver for Vizzini USB serial port" -- cgit v0.10.2 From 17dcfc9bd3dfb699e00205ec9d431b5a5cb00b34 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 19 Sep 2012 17:00:55 -0400 Subject: USB: EHCI: remove useless test This patch (as1605) removes a useless test from the EHCI debugfs code. There's no point checking whether p.qh is non-NULL; we already know it is and in any case it gets dereferenced aerlier in the function. The useless test was identified by smatch. Signed-off-by: Alan Stern Reported-by: Fengguang Wu Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-dbg.c b/drivers/usb/host/ehci-dbg.c index f0c00de..1599806 100644 --- a/drivers/usb/host/ehci-dbg.c +++ b/drivers/usb/host/ehci-dbg.c @@ -653,10 +653,8 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) seen [seen_count++].qh = p.qh; } else temp = 0; - if (p.qh) { - tag = Q_NEXT_TYPE(ehci, hw->hw_next); - p = p.qh->qh_next; - } + tag = Q_NEXT_TYPE(ehci, hw->hw_next); + p = p.qh->qh_next; break; case Q_TYPE_FSTN: temp = scnprintf (next, size, -- cgit v0.10.2 From d16ba48774913d244c7eb894d28d8ae2c019a827 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 19 Sep 2012 17:02:29 -0400 Subject: USB: EHCI: convert warning messages to debug-level This patch (as1606) converts two warning messages in the ehci-hcd driver to debug messages, and adds a little extra information to each. The log messages occur when an EHCI controller takes too long (more than 20 ms) to turn its async or periodic schedule on or off. If this happens at all, it's liable to happen quite often and there's no point spamming the system log with these warnings. Furthermore, there's nothing much we can do about it when the problem happens. Signed-off-by: Alan Stern Reported-and-tested-by: Thomas Voegtle Cc: stable # [3.6] Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c index eb896a2..20dbdcb 100644 --- a/drivers/usb/host/ehci-timer.c +++ b/drivers/usb/host/ehci-timer.c @@ -118,7 +118,8 @@ static void ehci_poll_ASS(struct ehci_hcd *ehci) ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true); return; } - ehci_warn(ehci, "Waited too long for the async schedule status, giving up\n"); + ehci_dbg(ehci, "Waited too long for the async schedule status (%x/%x), giving up\n", + want, actual); } ehci->ASS_poll_count = 0; @@ -163,7 +164,8 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci) ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true); return; } - ehci_warn(ehci, "Waited too long for the periodic schedule status, giving up\n"); + ehci_dbg(ehci, "Waited too long for the periodic schedule status (%x/%x), giving up\n", + want, actual); } ehci->PSS_poll_count = 0; -- cgit v0.10.2 From 160c9425ac52cb30502be2d9c5e848cec91bb115 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Wed, 19 Sep 2012 22:02:12 +0200 Subject: USB: option: blacklist QMI interface on ZTE MF683 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Interface #5 on ZTE MF683 is a QMI/wwan interface. Signed-off-by: Bjørn Mork Cc: stable Cc: Shawn J. Goff Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 53bd5f4..30cff03 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -870,7 +870,8 @@ static const struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0153, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0155, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0156, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff) }, + { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0157, 0xff, 0xff, 0xff), + .driver_info = (kernel_ulong_t)&net_intf5_blacklist }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0158, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0159, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0161, 0xff, 0xff, 0xff) }, -- cgit v0.10.2 From c638eb2872b3af079501e7ee44cbb8a5cce9b4b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= Date: Wed, 19 Sep 2012 22:02:03 +0200 Subject: USB: qcaux: add Pantech vendor class match MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The three Pantech devices UML190 (106c:3716), UML290 (106c:3718) and P4200 (106c:3721) all use the same subclasses to identify vendor specific functions. Replace the existing device specific entries with generic vendor matching, adding support for the P4200. Signed-off-by: Bjørn Mork Cc: stable Cc: Thomas Schäfer Acked-by: Dan Williams Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c index a4edc7e..9b1b96f 100644 --- a/drivers/usb/serial/qcaux.c +++ b/drivers/usb/serial/qcaux.c @@ -36,8 +36,6 @@ #define UTSTARCOM_PRODUCT_UM175_V1 0x3712 #define UTSTARCOM_PRODUCT_UM175_V2 0x3714 #define UTSTARCOM_PRODUCT_UM175_ALLTEL 0x3715 -#define PANTECH_PRODUCT_UML190_VZW 0x3716 -#define PANTECH_PRODUCT_UML290_VZW 0x3718 /* CMOTECH devices */ #define CMOTECH_VENDOR_ID 0x16d8 @@ -68,11 +66,9 @@ static struct usb_device_id id_table[] = { { USB_DEVICE_AND_INTERFACE_INFO(LG_VENDOR_ID, LG_PRODUCT_VX4400_6000, 0xff, 0xff, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(SANYO_VENDOR_ID, SANYO_PRODUCT_KATANA_LX, 0xff, 0xff, 0x00) }, { USB_DEVICE_AND_INTERFACE_INFO(SAMSUNG_VENDOR_ID, SAMSUNG_PRODUCT_U520, 0xff, 0x00, 0x00) }, - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML190_VZW, 0xff, 0xfe, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfd, 0xff) }, /* NMEA */ - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xfe, 0xff) }, /* WMC */ - { USB_DEVICE_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, PANTECH_PRODUCT_UML290_VZW, 0xff, 0xff, 0xff) }, /* DIAG */ + { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfd, 0xff) }, /* NMEA */ + { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfe, 0xff) }, /* WMC */ + { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xff, 0xff) }, /* DIAG */ { }, }; MODULE_DEVICE_TABLE(usb, id_table); -- cgit v0.10.2 From e98b6a4f9667e41eb96104991794eb29212ec2b7 Mon Sep 17 00:00:00 2001 From: Ramneek Mehresh Date: Wed, 19 Sep 2012 14:18:45 +0530 Subject: fsl/usb: Add support for USB controller version 2.4 Add support for USB controller version 2.4 Signed-off-by: Ramneek Mehresh Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c index 22ff6b3..1e77129 100644 --- a/drivers/usb/host/fsl-mph-dr-of.c +++ b/drivers/usb/host/fsl-mph-dr-of.c @@ -133,6 +133,8 @@ static int usb_get_ver_info(struct device_node *np) ver = FSL_USB_VER_1_6; else if (of_device_is_compatible(np, "fsl-usb2-dr-v2.2")) ver = FSL_USB_VER_2_2; + else if (of_device_is_compatible(np, "fsl-usb2-dr-v2.4")) + ver = FSL_USB_VER_2_4; else /* for previous controller versions */ ver = FSL_USB_VER_OLD; diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h index ccfc4bb..38b5660 100644 --- a/include/linux/fsl_devices.h +++ b/include/linux/fsl_devices.h @@ -23,6 +23,7 @@ #define FSL_USB_VER_OLD 0 #define FSL_USB_VER_1_6 1 #define FSL_USB_VER_2_2 2 +#define FSL_USB_VER_2_4 3 #include -- cgit v0.10.2 From 0220a3f01ab3d4673ca7087701d7466bea6b1d3a Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Wed, 19 Sep 2012 15:47:03 +0100 Subject: USB: sierra_ms: don't keep unused variable We need to call scsi_get_host_dev(sh) but we never use the return nor do we have any reason to check it. Signed-off-by: Alan Cox Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/storage/sierra_ms.c b/drivers/usb/storage/sierra_ms.c index 37539c8..17e3695 100644 --- a/drivers/usb/storage/sierra_ms.c +++ b/drivers/usb/storage/sierra_ms.c @@ -130,14 +130,13 @@ int sierra_ms_init(struct us_data *us) struct swoc_info *swocInfo; struct usb_device *udev; struct Scsi_Host *sh; - struct scsi_device *sd; retries = 3; result = 0; udev = us->pusb_dev; sh = us_to_host(us); - sd = scsi_get_host_dev(sh); + scsi_get_host_dev(sh); US_DEBUGP("SWIMS: sierra_ms_init called\n"); -- cgit v0.10.2 From f3f4bf5cf0896e58e9831ea53bcb8c7d88127d20 Mon Sep 17 00:00:00 2001 From: Joachim Eastwood Date: Sun, 23 Sep 2012 22:56:00 +0200 Subject: USB: ohci-at91: fix null pointer in ohci_hcd_at91_overcurrent_irq Fixes the following NULL pointer dereference: [ 7.740000] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver [ 7.810000] Unable to handle kernel NULL pointer dereference at virtual address 00000028 [ 7.810000] pgd = c3a38000 [ 7.810000] [00000028] *pgd=23a8c831, *pte=00000000, *ppte=00000000 [ 7.810000] Internal error: Oops: 17 [#1] PREEMPT ARM [ 7.810000] Modules linked in: ohci_hcd(+) regmap_i2c snd_pcm usbcore snd_page_alloc at91_cf snd_timer pcmcia_rsrc snd soundcore gpio_keys regmap_spi pcmcia_core usb_common nls_base [ 7.810000] CPU: 0 Not tainted (3.6.0-rc6-mpa+ #264) [ 7.810000] PC is at __gpio_to_irq+0x18/0x40 [ 7.810000] LR is at ohci_hcd_at91_overcurrent_irq+0x24/0xb4 [ohci_hcd] [ 7.810000] pc : [] lr : [] psr: 40000093 [ 7.810000] sp : c3a11c40 ip : c3a11c50 fp : c3a11c4c [ 7.810000] r10: 00000000 r9 : c02dcd6e r8 : fefff400 [ 7.810000] r7 : 00000000 r6 : c02cc928 r5 : 00000030 r4 : c02dd168 [ 7.810000] r3 : c02e7350 r2 : ffffffea r1 : c02cc928 r0 : 00000000 [ 7.810000] Flags: nZcv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user [ 7.810000] Control: c000717f Table: 23a38000 DAC: 00000015 [ 7.810000] Process modprobe (pid: 285, stack limit = 0xc3a10270) [ 7.810000] Stack: (0xc3a11c40 to 0xc3a12000) [ 7.810000] 1c40: c3a11c6c c3a11c50 bf08f694 c01392cc c3a11c84 c2c38b00 c3806900 00000030 [ 7.810000] 1c60: c3a11ca4 c3a11c70 c0051264 bf08f680 c3a11cac c3a11c80 c003e764 c3806900 [ 7.810000] 1c80: c2c38b00 c02cb05c c02cb000 fefff400 c3806930 c3a11cf4 c3a11cbc c3a11ca8 [ 7.810000] 1ca0: c005142c c005123c c3806900 c3805a00 c3a11cd4 c3a11cc0 c0053f24 c00513e4 [ 7.810000] 1cc0: c3a11cf4 00000030 c3a11cec c3a11cd8 c005120c c0053e88 00000000 00000000 [ 7.810000] 1ce0: c3a11d1c c3a11cf0 c00124d0 c00511e0 01400000 00000001 00000012 00000000 [ 7.810000] 1d00: ffffffff c3a11d94 00000030 00000000 c3a11d34 c3a11d20 c005120c c0012438 [ 7.810000] 1d20: c001dac4 00000012 c3a11d4c c3a11d38 c0009b08 c00511e0 c00523fc 60000013 [ 7.810000] 1d40: c3a11d5c c3a11d50 c0008510 c0009ab4 c3a11ddc c3a11d60 c0008eb4 c00084f0 [ 7.810000] 1d60: 00000000 00000030 00000000 00000080 60000013 bf08f670 c3806900 c2c38b00 [ 7.810000] 1d80: 00000030 c3806930 00000000 c3a11ddc c3a11d88 c3a11da8 c0054190 c00523fc [ 7.810000] 1da0: 60000013 ffffffff c3a11dec c3a11db8 00000000 c2c38b00 bf08f670 c3806900 [ 7.810000] 1dc0: 00000000 00000080 c02cc928 00000030 c3a11e0c c3a11de0 c0052764 c00520d8 [ 7.810000] 1de0: c3a11dfc 00000000 00000000 00000002 bf090f61 00000004 c02cc930 c02cc928 [ 7.810000] 1e00: c3a11e4c c3a11e10 bf090978 c005269c bf090f61 c02cc928 bf093000 c02dd170 [ 7.810000] 1e20: c3a11e3c c02cc930 c02cc930 bf0911d0 bf0911d0 bf093000 c3a10000 00000000 [ 7.810000] 1e40: c3a11e5c c3a11e50 c0155b7c bf090808 c3a11e7c c3a11e60 c0154690 c0155b6c [ 7.810000] 1e60: c02cc930 c02cc964 bf0911d0 c3a11ea0 c3a11e9c c3a11e80 c015484c c01545e8 [ 7.810000] 1e80: 00000000 00000000 c01547e4 bf0911d0 c3a11ec4 c3a11ea0 c0152e58 c01547f4 [ 7.810000] 1ea0: c381b88c c384ab10 c2c10540 bf0911d0 00000000 c02d7518 c3a11ed4 c3a11ec8 [ 7.810000] 1ec0: c01544c0 c0152e0c c3a11efc c3a11ed8 c01536cc c01544b0 bf091075 c3a11ee8 [ 7.810000] 1ee0: bf049af0 bf09120c bf0911d0 00000000 c3a11f1c c3a11f00 c0154e9c c0153628 [ 7.810000] 1f00: bf049af0 bf09120c 000ae190 00000000 c3a11f2c c3a11f20 c0155f58 c0154e04 [ 7.810000] 1f20: c3a11f44 c3a11f30 bf093054 c0155f1c 00000000 00006a4f c3a11f7c c3a11f48 [ 7.810000] 1f40: c0008638 bf093010 bf09120c 000ae190 00000000 c00093c4 00006a4f bf09120c [ 7.810000] 1f60: 000ae190 00000000 c00093c4 00000000 c3a11fa4 c3a11f80 c004fdc4 c000859c [ 7.810000] 1f80: c3a11fa4 000ae190 00006a4f 00016eb8 000ad018 00000080 00000000 c3a11fa8 [ 7.810000] 1fa0: c0009260 c004fd58 00006a4f 00016eb8 000ae190 00006a4f 000ae100 00000000 [ 7.810000] 1fc0: 00006a4f 00016eb8 000ad018 00000080 000adba0 000ad208 00000000 000ad3d8 [ 7.810000] 1fe0: beaf7ae8 beaf7ad8 000172b8 b6e4e940 20000010 000ae190 00000000 00000000 [ 7.810000] Backtrace: [ 7.810000] [] (__gpio_to_irq+0x0/0x40) from [] (ohci_hcd_at91_overcurrent_irq+0x24/0xb4 [ohci_hcd]) [ 7.810000] [] (ohci_hcd_at91_overcurrent_irq+0x0/0xb4 [ohci_hcd]) from [] (handle_irq_event_percpu+0x38/0x1a8) [ 7.810000] r6:00000030 r5:c3806900 r4:c2c38b00 [ 7.810000] [] (handle_irq_event_percpu+0x0/0x1a8) from [] (handle_irq_event+0x58/0x7c) [ 7.810000] [] (handle_irq_event+0x0/0x7c) from [] (handle_simple_irq+0xac/0xd8) [ 7.810000] r5:c3805a00 r4:c3806900 [ 7.810000] [] (handle_simple_irq+0x0/0xd8) from [] (generic_handle_irq+0x3c/0x48) [ 7.810000] r4:00000030 [ 7.810000] [] (generic_handle_irq+0x0/0x48) from [] (gpio_irq_handler+0xa8/0xfc) [ 7.810000] r4:00000000 [ 7.810000] [] (gpio_irq_handler+0x0/0xfc) from [] (generic_handle_irq+0x3c/0x48) [ 7.810000] [] (generic_handle_irq+0x0/0x48) from [] (handle_IRQ+0x64/0x88) [ 7.810000] r4:00000012 [ 7.810000] [] (handle_IRQ+0x0/0x88) from [] (at91_aic_handle_irq+0x30/0x38) [ 7.810000] r5:60000013 r4:c00523fc [ 7.810000] [] (at91_aic_handle_irq+0x0/0x38) from [] (__irq_svc+0x34/0x60) [ 7.810000] Exception stack(0xc3a11d60 to 0xc3a11da8) [ 7.810000] 1d60: 00000000 00000030 00000000 00000080 60000013 bf08f670 c3806900 c2c38b00 [ 7.810000] 1d80: 00000030 c3806930 00000000 c3a11ddc c3a11d88 c3a11da8 c0054190 c00523fc [ 7.810000] 1da0: 60000013 ffffffff [ 7.810000] [] (__setup_irq+0x0/0x458) from [] (request_threaded_irq+0xd8/0x134) [ 7.810000] [] (request_threaded_irq+0x0/0x134) from [] (ohci_hcd_at91_drv_probe+0x180/0x41c [ohci_hcd]) [ 7.810000] [] (ohci_hcd_at91_drv_probe+0x0/0x41c [ohci_hcd]) from [] (platform_drv_probe+0x20/0x24) [ 7.810000] [] (platform_drv_probe+0x0/0x24) from [] (driver_probe_device+0xb8/0x20c) [ 7.810000] [] (driver_probe_device+0x0/0x20c) from [] (__driver_attach+0x68/0x88) [ 7.810000] r7:c3a11ea0 r6:bf0911d0 r5:c02cc964 r4:c02cc930 [ 7.810000] [] (__driver_attach+0x0/0x88) from [] (bus_for_each_dev+0x5c/0x9c) [ 7.810000] r6:bf0911d0 r5:c01547e4 r4:00000000 [ 7.810000] [] (bus_for_each_dev+0x0/0x9c) from [] (driver_attach+0x20/0x28) [ 7.810000] r7:c02d7518 r6:00000000 r5:bf0911d0 r4:c2c10540 [ 7.810000] [] (driver_attach+0x0/0x28) from [] (bus_add_driver+0xb4/0x22c) [ 7.810000] [] (bus_add_driver+0x0/0x22c) from [] (driver_register+0xa8/0x144) [ 7.810000] r7:00000000 r6:bf0911d0 r5:bf09120c r4:bf049af0 [ 7.810000] [] (driver_register+0x0/0x144) from [] (platform_driver_register+0x4c/0x60) [ 7.810000] r7:00000000 r6:000ae190 r5:bf09120c r4:bf049af0 [ 7.810000] [] (platform_driver_register+0x0/0x60) from [] (ohci_hcd_mod_init+0x54/0x8c [ohci_hcd]) [ 7.810000] [] (ohci_hcd_mod_init+0x0/0x8c [ohci_hcd]) from [] (do_one_initcall+0xac/0x174) [ 7.810000] r4:00006a4f [ 7.810000] [] (do_one_initcall+0x0/0x174) from [] (sys_init_module+0x7c/0x1a0) [ 7.810000] [] (sys_init_module+0x0/0x1a0) from [] (ret_fast_syscall+0x0/0x2c) [ 7.810000] r7:00000080 r6:000ad018 r5:00016eb8 r4:00006a4f [ 7.810000] Code: e24cb004 e59f3028 e1a02000 e7930180 (e5903028) [ 7.810000] ---[ end trace 85aa37ed128143b5 ]--- [ 7.810000] Kernel panic - not syncing: Fatal exception in interrupt Commit 6fffb77c (USB: ohci-at91: fix PIO handling in relation with number of ports) started setting unused pins to EINVAL. But this exposed a bug in the ohci_hcd_at91_overcurrent_irq function where the gpio was used without being checked to see if it is valid. This patches fixed the issue by adding the gpio valid check. Signed-off-by: Joachim Eastwood Cc: stable # [3.4+] whereever 6fffb77c went Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index aaa8d2b..0bf72f9 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -467,7 +467,8 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data) /* From the GPIO notifying the over-current situation, find * out the corresponding port */ at91_for_each_port(port) { - if (gpio_to_irq(pdata->overcurrent_pin[port]) == irq) { + if (gpio_is_valid(pdata->overcurrent_pin[port]) && + gpio_to_irq(pdata->overcurrent_pin[port]) == irq) { gpio = pdata->overcurrent_pin[port]; break; } -- cgit v0.10.2 From a6e097dfdfd189b6929af6efa1d289af61858386 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Fri, 14 Sep 2012 13:05:49 -0400 Subject: Increase XHCI suspend timeout to 16ms The Intel XHCI specification says that after clearing the run/stop bit the controller may take up to 16ms to halt. We've seen a device take 14ms, which with the current timeout of 10ms causes the kernel to abort the suspend. Increasing the timeout to the recommended value fixes the problem. This patch should be backported to kernels as old as 2.6.37, that contain the commit 5535b1d5f8885695c6ded783c692e3c0d0eda8ca "USB: xHCI: PCI power management implementation". Signed-off-by: Michael Spang Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index a4b0ce1..52b04b0 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -888,7 +888,7 @@ int xhci_suspend(struct xhci_hcd *xhci) command &= ~CMD_RUN; xhci_writel(xhci, command, &xhci->op_regs->command); if (handshake(xhci, &xhci->op_regs->status, - STS_HALT, STS_HALT, 100*100)) { + STS_HALT, STS_HALT, XHCI_MAX_HALT_USEC)) { xhci_warn(xhci, "WARN: xHC CMD_RUN timeout\n"); spin_unlock_irq(&xhci->lock); return -ETIMEDOUT; -- cgit v0.10.2 From 457a73d346187c2cc5d599072f38676f18f130e0 Mon Sep 17 00:00:00 2001 From: Vivek Gautam Date: Sat, 22 Sep 2012 18:11:19 +0530 Subject: usb: host: xhci: Fix Null pointer dereferencing with 71c731a for non-x86 systems In 71c731a: usb: host: xhci: Fix Compliance Mode on SN65LVPE502CP Hardware when extracting DMI strings (vendor or product_name) to mark them as quirk we may get NULL pointer in case of non-x86 systems which won't define CONFIG_DMI. Hence susbsequent strstr() calls crash while driver probing. So, returning 'false' here in case we get a NULL vendor or product_name. This is tested with ARM (exynos) system. This patch should be backported to stable kernels as old as 3.6, that contain the commit 71c731a296f1b08a3724bd1b514b64f1bda87a23 "usb: host: xhci: Fix Compliance Mode on SN65LVPE502CP Hardware" Signed-off-by: Vivek Gautam Signed-off-by: Sarah Sharp Reported-by: Sebastian Gottschall (DD-WRT) Cc: stable@vger.kernel.org diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 52b04b0..8d7fcbb 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -471,6 +471,8 @@ static bool compliance_mode_recovery_timer_quirk_check(void) dmi_product_name = dmi_get_system_info(DMI_PRODUCT_NAME); dmi_sys_vendor = dmi_get_system_info(DMI_SYS_VENDOR); + if (!dmi_product_name || !dmi_sys_vendor) + return false; if (!(strstr(dmi_sys_vendor, "Hewlett-Packard"))) return false; -- cgit v0.10.2 From 64f0d8cd089ee7e501116181a343c3739df5fe53 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 24 Sep 2012 12:42:19 -0700 Subject: USB: serial: remove vizzini driver It's out-dated for the tty-layer stuff, and would require a bunch of work. That's not really a big deal, the big issue is that there is no company contact for the hardware, so questions we have about it (like why isn't this just handled by the cdc-acm driver instead?) go unanswered. So drop the driver. If someone comes along to help answer the questions, we can easily revert this and fix up the code. Cc: Alan Cox Cc: Rob Duncan Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index a5c1446..f604f70 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -182,14 +182,6 @@ config USB_SERIAL_VISOR To compile this driver as a module, choose M here: the module will be called visor. -config USB_SERIAL_VIZZINI - tristate "USB Vizzini Serial Converter Driver" - help - Say Y here if you have a Vizzini USB to serial device. - - To compile this driver as a module, choose M here: the - module will be called vizzini. - config USB_SERIAL_IPAQ tristate "USB PocketPC PDA Driver" help diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 5fd21a0..45871f9 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -59,7 +59,6 @@ obj-$(CONFIG_USB_SERIAL_SYMBOL) += symbolserial.o obj-$(CONFIG_USB_SERIAL_WWAN) += usb_wwan.o obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o -obj-$(CONFIG_USB_SERIAL_VIZZINI) += vizzini.o obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o obj-$(CONFIG_USB_SERIAL_XIRCOM) += keyspan_pda.o obj-$(CONFIG_USB_SERIAL_VIVOPAY_SERIAL) += vivopay-serial.o diff --git a/drivers/usb/serial/vizzini.c b/drivers/usb/serial/vizzini.c deleted file mode 100644 index 7f43694..0000000 --- a/drivers/usb/serial/vizzini.c +++ /dev/null @@ -1,1354 +0,0 @@ -/* - * vizzini.c - * - * Copyright (c) 2011 Exar Corporation, Inc. - * - * ChangeLog: - * v0.76- Support for 3.0.0 (Ubuntu 11.10) (Removed all Kernel source - * compiler conditions and now the base is Kernel 3.0. Ravi Reddy) - * v0.75- Support for 2.6.38.8 (Ubuntu 11.04) - Added - * .usb_driver = &vizzini_driver. - * v0.74- Support for 2.6.35.22 (Ubuntu 10.10) - Added - * #include to fix kmalloc/kfree error. - * v0.73- Fixed VZIOC_SET_REG (by Ravi Reddy). - * v0.72- Support for 2.6.32.21 (by Ravi Reddy, for Ubuntu 10.04). - * v0.71- Support for 2.6.31. - * v0.5 - Tentative support for compiling with the CentOS 5.1 - * kernel (2.6.18-53). - * v0.4 - First version. Lots of stuff lifted from - * cdc-acm.c (credits due to Armin Fuerst, Pavel Machek, - * Johannes Erdfelt, Vojtech Pavlik, David Kubicek) and - * and sierra.c (credit due to Kevin Lloyd). - */ - -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define DRIVER_VERSION "v.0.76" -#define DRIVER_AUTHOR "Rob Duncan " -#define DRIVER_DESC "USB Driver for Vizzini USB serial port" - -#undef VIZZINI_IWA - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#ifndef CDC_DATA_INTERFACE_TYPE -#define CDC_DATA_INTERFACE_TYPE 0x0a -#endif -#ifndef USB_RT_ACM -#define USB_RT_ACM (USB_TYPE_CLASS | USB_RECIP_INTERFACE) -#define ACM_CTRL_DTR 0x01 -#define ACM_CTRL_RTS 0x02 -#define ACM_CTRL_DCD 0x01 -#define ACM_CTRL_DSR 0x02 -#define ACM_CTRL_BRK 0x04 -#define ACM_CTRL_RI 0x08 -#define ACM_CTRL_FRAMING 0x10 -#define ACM_CTRL_PARITY 0x20 -#define ACM_CTRL_OVERRUN 0x40 -#endif - -#define XR_SET_REG 0 -#define XR_GETN_REG 1 - -#define UART_0_REG_BLOCK 0 -#define UART_1_REG_BLOCK 1 -#define UART_2_REG_BLOCK 2 -#define UART_3_REG_BLOCK 3 -#define URM_REG_BLOCK 4 -#define PRM_REG_BLOCK 5 -#define EPMERR_REG_BLOCK 6 -#define RAMCTL_REG_BLOCK 0x64 -#define TWI_ROM_REG_BLOCK 0x65 -#define EPLOCALS_REG_BLOCK 0x66 - -#define MEM_SHADOW_REG_SIZE_S 5 -#define MEM_SHADOW_REG_SIZE (1 << MEM_SHADOW_REG_SIZE_S) - -#define MEM_EP_LOCALS_SIZE_S 3 -#define MEM_EP_LOCALS_SIZE (1 << MEM_EP_LOCALS_SIZE_S) - -#define EP_WIDE_MODE 0x03 - - -#define UART_GPIO_MODE 0x01a - -#define UART_GPIO_MODE_SEL_M 0x7 -#define UART_GPIO_MODE_SEL_S 0 -#define UART_GPIO_MODE_SEL 0x007 - -#define UART_GPIO_MODE_SEL_GPIO (0x0 << UART_GPIO_MODE_SEL_S) -#define UART_GPIO_MODE_SEL_RTS_CTS (0x1 << UART_GPIO_MODE_SEL_S) -#define UART_GPIO_MODE_SEL_DTR_DSR (0x2 << UART_GPIO_MODE_SEL_S) -#define UART_GPIO_MODE_SEL_XCVR_EN_ACT (0x3 << UART_GPIO_MODE_SEL_S) -#define UART_GPIO_MODE_SEL_XCVR_EN_FLOW (0x4 << UART_GPIO_MODE_SEL_S) - -#define UART_GPIO_MODE_XCVR_EN_POL_M 0x1 -#define UART_GPIO_MODE_XCVR_EN_POL_S 3 -#define UART_GPIO_MODE_XCVR_EN_POL 0x008 - -#define UART_ENABLE 0x003 -#define UART_ENABLE_TX_M 0x1 -#define UART_ENABLE_TX_S 0 -#define UART_ENABLE_TX 0x001 -#define UART_ENABLE_RX_M 0x1 -#define UART_ENABLE_RX_S 1 -#define UART_ENABLE_RX 0x002 - -#define UART_CLOCK_DIVISOR_0 0x004 -#define UART_CLOCK_DIVISOR_1 0x005 -#define UART_CLOCK_DIVISOR_2 0x006 - -#define UART_CLOCK_DIVISOR_2_MSB_M 0x7 -#define UART_CLOCK_DIVISOR_2_MSB_S 0 -#define UART_CLOCK_DIVISOR_2_MSB 0x007 -#define UART_CLOCK_DIVISOR_2_DIAGMODE_M 0x1 -#define UART_CLOCK_DIVISOR_2_DIAGMODE_S 3 -#define UART_CLOCK_DIVISOR_2_DIAGMODE 0x008 - -#define UART_TX_CLOCK_MASK_0 0x007 -#define UART_TX_CLOCK_MASK_1 0x008 - -#define UART_RX_CLOCK_MASK_0 0x009 -#define UART_RX_CLOCK_MASK_1 0x00a - -#define UART_FORMAT 0x00b - -#define UART_FORMAT_SIZE_M 0xf -#define UART_FORMAT_SIZE_S 0 -#define UART_FORMAT_SIZE 0x00f - -#define UART_FORMAT_SIZE_7 (0x7 << UART_FORMAT_SIZE_S) -#define UART_FORMAT_SIZE_8 (0x8 << UART_FORMAT_SIZE_S) -#define UART_FORMAT_SIZE_9 (0x9 << UART_FORMAT_SIZE_S) - -#define UART_FORMAT_PARITY_M 0x7 -#define UART_FORMAT_PARITY_S 4 -#define UART_FORMAT_PARITY 0x070 - -#define UART_FORMAT_PARITY_NONE (0x0 << UART_FORMAT_PARITY_S) -#define UART_FORMAT_PARITY_ODD (0x1 << UART_FORMAT_PARITY_S) -#define UART_FORMAT_PARITY_EVEN (0x2 << UART_FORMAT_PARITY_S) -#define UART_FORMAT_PARITY_1 (0x3 << UART_FORMAT_PARITY_S) -#define UART_FORMAT_PARITY_0 (0x4 << UART_FORMAT_PARITY_S) - -#define UART_FORMAT_STOP_M 0x1 -#define UART_FORMAT_STOP_S 7 -#define UART_FORMAT_STOP 0x080 - -#define UART_FORMAT_STOP_1 (0x0 << UART_FORMAT_STOP_S) -#define UART_FORMAT_STOP_2 (0x1 << UART_FORMAT_STOP_S) - -#define UART_FORMAT_MODE_7N1 0 -#define UART_FORMAT_MODE_RES1 1 -#define UART_FORMAT_MODE_RES2 2 -#define UART_FORMAT_MODE_RES3 3 -#define UART_FORMAT_MODE_7N2 4 -#define UART_FORMAT_MODE_7P1 5 -#define UART_FORMAT_MODE_8N1 6 -#define UART_FORMAT_MODE_RES7 7 -#define UART_FORMAT_MODE_7P2 8 -#define UART_FORMAT_MODE_8N2 9 -#define UART_FORMAT_MODE_8P1 10 -#define UART_FORMAT_MODE_9N1 11 -#define UART_FORMAT_MODE_8P2 12 -#define UART_FORMAT_MODE_RESD 13 -#define UART_FORMAT_MODE_RESE 14 -#define UART_FORMAT_MODE_9N2 15 - -#define UART_FLOW 0x00c - -#define UART_FLOW_MODE_M 0x7 -#define UART_FLOW_MODE_S 0 -#define UART_FLOW_MODE 0x007 - -#define UART_FLOW_MODE_NONE (0x0 << UART_FLOW_MODE_S) -#define UART_FLOW_MODE_HW (0x1 << UART_FLOW_MODE_S) -#define UART_FLOW_MODE_SW (0x2 << UART_FLOW_MODE_S) -#define UART_FLOW_MODE_ADDR_MATCH (0x3 << UART_FLOW_MODE_S) -#define UART_FLOW_MODE_ADDR_MATCH_TX (0x4 << UART_FLOW_MODE_S) - -#define UART_FLOW_HALF_DUPLEX_M 0x1 -#define UART_FLOW_HALF_DUPLEX_S 3 -#define UART_FLOW_HALF_DUPLEX 0x008 - -#define UART_LOOPBACK_CTL 0x012 -#define UART_LOOPBACK_CTL_ENABLE_M 0x1 -#define UART_LOOPBACK_CTL_ENABLE_S 2 -#define UART_LOOPBACK_CTL_ENABLE 0x004 -#define UART_LOOPBACK_CTL_RX_SOURCE_M 0x3 -#define UART_LOOPBACK_CTL_RX_SOURCE_S 0 -#define UART_LOOPBACK_CTL_RX_SOURCE 0x003 -#define UART_LOOPBACK_CTL_RX_UART0 (0x0 << UART_LOOPBACK_CTL_RX_SOURCE_S) -#define UART_LOOPBACK_CTL_RX_UART1 (0x1 << UART_LOOPBACK_CTL_RX_SOURCE_S) -#define UART_LOOPBACK_CTL_RX_UART2 (0x2 << UART_LOOPBACK_CTL_RX_SOURCE_S) -#define UART_LOOPBACK_CTL_RX_UART3 (0x3 << UART_LOOPBACK_CTL_RX_SOURCE_S) - -#define UART_CHANNEL_NUM 0x00d - -#define UART_XON_CHAR 0x010 -#define UART_XOFF_CHAR 0x011 - -#define UART_GPIO_SET 0x01d -#define UART_GPIO_CLR 0x01e -#define UART_GPIO_STATUS 0x01f - -#define URM_ENABLE_BASE 0x010 -#define URM_ENABLE_0 0x010 -#define URM_ENABLE_0_TX_M 0x1 -#define URM_ENABLE_0_TX_S 0 -#define URM_ENABLE_0_TX 0x001 -#define URM_ENABLE_0_RX_M 0x1 -#define URM_ENABLE_0_RX_S 1 -#define URM_ENABLE_0_RX 0x002 - -#define URM_RX_FIFO_RESET_0 0x018 -#define URM_RX_FIFO_RESET_1 0x019 -#define URM_RX_FIFO_RESET_2 0x01a -#define URM_RX_FIFO_RESET_3 0x01b -#define URM_TX_FIFO_RESET_0 0x01c -#define URM_TX_FIFO_RESET_1 0x01d -#define URM_TX_FIFO_RESET_2 0x01e -#define URM_TX_FIFO_RESET_3 0x01f - - -#define RAMCTL_REGS_TXFIFO_0_LEVEL 0x000 -#define RAMCTL_REGS_TXFIFO_1_LEVEL 0x001 -#define RAMCTL_REGS_TXFIFO_2_LEVEL 0x002 -#define RAMCTL_REGS_TXFIFO_3_LEVEL 0x003 -#define RAMCTL_REGS_RXFIFO_0_LEVEL 0x004 - -#define RAMCTL_REGS_RXFIFO_0_LEVEL_LEVEL_M 0x7ff -#define RAMCTL_REGS_RXFIFO_0_LEVEL_LEVEL_S 0 -#define RAMCTL_REGS_RXFIFO_0_LEVEL_LEVEL 0x7ff -#define RAMCTL_REGS_RXFIFO_0_LEVEL_STALE_M 0x1 -#define RAMCTL_REGS_RXFIFO_0_LEVEL_STALE_S 11 -#define RAMCTL_REGS_RXFIFO_0_LEVEL_STALE 0x800 - -#define RAMCTL_REGS_RXFIFO_1_LEVEL 0x005 -#define RAMCTL_REGS_RXFIFO_2_LEVEL 0x006 -#define RAMCTL_REGS_RXFIFO_3_LEVEL 0x007 - -#define RAMCTL_BUFFER_PARITY 0x1 -#define RAMCTL_BUFFER_BREAK 0x2 -#define RAMCTL_BUFFER_FRAME 0x4 -#define RAMCTL_BUFFER_OVERRUN 0x8 - -#define N_IN_URB 4 -#define N_OUT_URB 4 -#define IN_BUFLEN 4096 - -static struct usb_device_id id_table[] = { - { USB_DEVICE(0x04e2, 0x1410) }, - { USB_DEVICE(0x04e2, 0x1412) }, - { USB_DEVICE(0x04e2, 0x1414) }, - { } -}; -MODULE_DEVICE_TABLE(usb, id_table); - -struct vizzini_serial_private { - struct usb_interface *data_interface; -}; - -struct vizzini_port_private { - spinlock_t lock; - int outstanding_urbs; - - struct urb *in_urbs[N_IN_URB]; - char *in_buffer[N_IN_URB]; - - int ctrlin; - int ctrlout; - int clocal; - - int block; - int preciseflags; /* USB: wide mode, TTY: flags per character */ - int trans9; /* USB: wide mode, serial 9N1 */ - unsigned int baud_base; /* setserial: used to hack in non-standard baud rates */ - int have_extra_byte; - int extra_byte; - - int bcd_device; - -#ifdef VIZZINI_IWA - int iwa; -#endif -}; - - -static int vizzini_rev_a(struct usb_serial_port *port) -{ - struct vizzini_port_private *portdata = usb_get_serial_port_data(port); - return portdata->bcd_device == 0; -} - -static int acm_ctrl_msg(struct usb_serial_port *port, int request, - int value, void *buf, int len) -{ - struct usb_serial *serial = port->serial; - int retval = usb_control_msg(serial->dev, - usb_sndctrlpipe(serial->dev, 0), - request, - USB_RT_ACM, - value, - serial->interface->cur_altsetting->desc.bInterfaceNumber, - buf, - len, - 5000); - dev_dbg(&port->dev, "acm_control_msg: rq: 0x%02x val: %#x len: %#x result: %d\n", request, value, len, retval); - return retval < 0 ? retval : 0; -} - -#define acm_set_control(port, control) \ - acm_ctrl_msg(port, USB_CDC_REQ_SET_CONTROL_LINE_STATE, control, NULL, 0) -#define acm_set_line(port, line) \ - acm_ctrl_msg(port, USB_CDC_REQ_SET_LINE_CODING, 0, line, sizeof *(line)) -#define acm_send_break(port, ms) \ - acm_ctrl_msg(port, USB_CDC_REQ_SEND_BREAK, ms, NULL, 0) - -static int vizzini_set_reg(struct usb_serial_port *port, int block, int regnum, int value) -{ - struct usb_serial *serial = port->serial; - int result; - - result = usb_control_msg(serial->dev, /* usb device */ - usb_sndctrlpipe(serial->dev, 0), /* endpoint pipe */ - XR_SET_REG, /* request */ - USB_DIR_OUT | USB_TYPE_VENDOR, /* request_type */ - value, /* request value */ - regnum | (block << 8), /* index */ - NULL, /* data */ - 0, /* size */ - 5000); /* timeout */ - - return result; -} - -static void vizzini_disable(struct usb_serial_port *port) -{ - struct vizzini_port_private *portdata = usb_get_serial_port_data(port); - int block = portdata->block; - - vizzini_set_reg(port, block, UART_ENABLE, 0); - vizzini_set_reg(port, URM_REG_BLOCK, URM_ENABLE_BASE + block, 0); -} - -static void vizzini_enable(struct usb_serial_port *port) -{ - struct vizzini_port_private *portdata = usb_get_serial_port_data(port); - int block = portdata->block; - - vizzini_set_reg(port, URM_REG_BLOCK, URM_ENABLE_BASE + block, URM_ENABLE_0_TX); - vizzini_set_reg(port, block, UART_ENABLE, UART_ENABLE_TX | UART_ENABLE_RX); - vizzini_set_reg(port, URM_REG_BLOCK, URM_ENABLE_BASE + block, URM_ENABLE_0_TX | URM_ENABLE_0_RX); -} - -struct vizzini_baud_rate { - unsigned int tx; - unsigned int rx0; - unsigned int rx1; -}; - -static struct vizzini_baud_rate vizzini_baud_rates[] = { - { 0x000, 0x000, 0x000 }, - { 0x000, 0x000, 0x000 }, - { 0x100, 0x000, 0x100 }, - { 0x020, 0x400, 0x020 }, - { 0x010, 0x100, 0x010 }, - { 0x208, 0x040, 0x208 }, - { 0x104, 0x820, 0x108 }, - { 0x844, 0x210, 0x884 }, - { 0x444, 0x110, 0x444 }, - { 0x122, 0x888, 0x224 }, - { 0x912, 0x448, 0x924 }, - { 0x492, 0x248, 0x492 }, - { 0x252, 0x928, 0x292 }, - { 0X94A, 0X4A4, 0XA52 }, - { 0X52A, 0XAA4, 0X54A }, - { 0XAAA, 0x954, 0X4AA }, - { 0XAAA, 0x554, 0XAAA }, - { 0x555, 0XAD4, 0X5AA }, - { 0XB55, 0XAB4, 0X55A }, - { 0X6B5, 0X5AC, 0XB56 }, - { 0X5B5, 0XD6C, 0X6D6 }, - { 0XB6D, 0XB6A, 0XDB6 }, - { 0X76D, 0X6DA, 0XBB6 }, - { 0XEDD, 0XDDA, 0X76E }, - { 0XDDD, 0XBBA, 0XEEE }, - { 0X7BB, 0XF7A, 0XDDE }, - { 0XF7B, 0XEF6, 0X7DE }, - { 0XDF7, 0XBF6, 0XF7E }, - { 0X7F7, 0XFEE, 0XEFE }, - { 0XFDF, 0XFBE, 0X7FE }, - { 0XF7F, 0XEFE, 0XFFE }, - { 0XFFF, 0XFFE, 0XFFD }, -}; - -static int vizzini_set_baud_rate(struct usb_serial_port *port, unsigned int rate) -{ - struct vizzini_port_private *portdata = usb_get_serial_port_data(port); - int block = portdata->block; - unsigned int divisor = 48000000 / rate; - unsigned int i = ((32 * 48000000) / rate) & 0x1f; - unsigned int tx_mask = vizzini_baud_rates[i].tx; - unsigned int rx_mask = (divisor & 1) ? vizzini_baud_rates[i].rx1 : vizzini_baud_rates[i].rx0; - - dev_dbg(&port->dev, "Setting baud rate to %d: i=%u div=%u tx=%03x rx=%03x\n", rate, i, divisor, tx_mask, rx_mask); - - vizzini_set_reg(port, block, UART_CLOCK_DIVISOR_0, (divisor >> 0) & 0xff); - vizzini_set_reg(port, block, UART_CLOCK_DIVISOR_1, (divisor >> 8) & 0xff); - vizzini_set_reg(port, block, UART_CLOCK_DIVISOR_2, (divisor >> 16) & 0xff); - vizzini_set_reg(port, block, UART_TX_CLOCK_MASK_0, (tx_mask >> 0) & 0xff); - vizzini_set_reg(port, block, UART_TX_CLOCK_MASK_1, (tx_mask >> 8) & 0xff); - vizzini_set_reg(port, block, UART_RX_CLOCK_MASK_0, (rx_mask >> 0) & 0xff); - vizzini_set_reg(port, block, UART_RX_CLOCK_MASK_1, (rx_mask >> 8) & 0xff); - - return -EINVAL; -} - -static void vizzini_set_termios(struct tty_struct *tty_param, - struct usb_serial_port *port, - struct ktermios *old_termios) -{ - struct vizzini_port_private *portdata = usb_get_serial_port_data(port); - unsigned int cflag, block; - speed_t rate; - unsigned int format_size, format_parity, format_stop, flow, gpio_mode; - struct tty_struct *tty = port->port.tty; - - cflag = tty->termios->c_cflag; - - portdata->clocal = ((cflag & CLOCAL) != 0); - - block = portdata->block; - - vizzini_disable(port); - - if ((cflag & CSIZE) == CS7) { - format_size = UART_FORMAT_SIZE_7; - } else if ((cflag & CSIZE) == CS5) { - /* Enabling 5-bit mode is really 9-bit mode! */ - format_size = UART_FORMAT_SIZE_9; - } else { - format_size = UART_FORMAT_SIZE_8; - } - portdata->trans9 = (format_size == UART_FORMAT_SIZE_9); - - if (cflag & PARENB) { - if (cflag & PARODD) { - if (cflag & CMSPAR) - format_parity = UART_FORMAT_PARITY_1; - else - format_parity = UART_FORMAT_PARITY_ODD; - } else { - if (cflag & CMSPAR) - format_parity = UART_FORMAT_PARITY_0; - else - format_parity = UART_FORMAT_PARITY_EVEN; - } - } else { - format_parity = UART_FORMAT_PARITY_NONE; - } - - if (cflag & CSTOPB) - format_stop = UART_FORMAT_STOP_2; - else - format_stop = UART_FORMAT_STOP_1; - -#ifdef VIZZINI_IWA - if (format_size == UART_FORMAT_SIZE_8) { - portdata->iwa = format_parity; - if (portdata->iwa != UART_FORMAT_PARITY_NONE) { - format_size = UART_FORMAT_SIZE_9; - format_parity = UART_FORMAT_PARITY_NONE; - } - } else { - portdata->iwa = UART_FORMAT_PARITY_NONE; - } -#endif - vizzini_set_reg(port, block, UART_FORMAT, format_size | format_parity | format_stop); - - if (cflag & CRTSCTS) { - flow = UART_FLOW_MODE_HW; - gpio_mode = UART_GPIO_MODE_SEL_RTS_CTS; - } else if (I_IXOFF(tty) || I_IXON(tty)) { - unsigned char start_char = START_CHAR(tty); - unsigned char stop_char = STOP_CHAR(tty); - - flow = UART_FLOW_MODE_SW; - gpio_mode = UART_GPIO_MODE_SEL_GPIO; - - vizzini_set_reg(port, block, UART_XON_CHAR, start_char); - vizzini_set_reg(port, block, UART_XOFF_CHAR, stop_char); - } else { - flow = UART_FLOW_MODE_NONE; - gpio_mode = UART_GPIO_MODE_SEL_GPIO; - } - - vizzini_set_reg(port, block, UART_FLOW, flow); - vizzini_set_reg(port, block, UART_GPIO_MODE, gpio_mode); - - if (portdata->trans9) { - /* Turn on wide mode if we're 9-bit transparent. */ - vizzini_set_reg(port, EPLOCALS_REG_BLOCK, (block * MEM_EP_LOCALS_SIZE) + EP_WIDE_MODE, 1); -#ifdef VIZZINI_IWA - } else if (portdata->iwa != UART_FORMAT_PARITY_NONE) { - vizzini_set_reg(port, EPLOCALS_REG_BLOCK, (block * MEM_EP_LOCALS_SIZE) + EP_WIDE_MODE, 1); -#endif - } else if (!portdata->preciseflags) { - /* Turn off wide mode unless we have precise flags. */ - vizzini_set_reg(port, EPLOCALS_REG_BLOCK, (block * MEM_EP_LOCALS_SIZE) + EP_WIDE_MODE, 0); - } - - rate = tty_get_baud_rate(tty); - if (rate) - vizzini_set_baud_rate(port, rate); - - vizzini_enable(port); -} - -static void vizzini_break_ctl(struct tty_struct *tty, int break_state) -{ - struct usb_serial_port *port = tty->driver_data; - - dev_dbg(&port->dev, "BREAK %d\n", break_state); - if (break_state) - acm_send_break(port, 0x10); - else - acm_send_break(port, 0x000); -} - -static int vizzini_tiocmget(struct tty_struct *tty) -{ - struct usb_serial_port *port = tty->driver_data; - struct vizzini_port_private *portdata = usb_get_serial_port_data(port); - - return (portdata->ctrlout & ACM_CTRL_DTR ? TIOCM_DTR : 0) | - (portdata->ctrlout & ACM_CTRL_RTS ? TIOCM_RTS : 0) | - (portdata->ctrlin & ACM_CTRL_DSR ? TIOCM_DSR : 0) | - (portdata->ctrlin & ACM_CTRL_RI ? TIOCM_RI : 0) | - (portdata->ctrlin & ACM_CTRL_DCD ? TIOCM_CD : 0) | - TIOCM_CTS; -} - -static int vizzini_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) -{ - struct usb_serial_port *port = tty->driver_data; - struct vizzini_port_private *portdata = usb_get_serial_port_data(port); - unsigned int newctrl; - - newctrl = portdata->ctrlout; - set = (set & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (set & TIOCM_RTS ? ACM_CTRL_RTS : 0); - clear = (clear & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (clear & TIOCM_RTS ? ACM_CTRL_RTS : 0); - - newctrl = (newctrl & ~clear) | set; - - if (portdata->ctrlout == newctrl) - return 0; - return acm_set_control(port, portdata->ctrlout = newctrl); -} - -static int vizzini_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) -{ - struct usb_serial_port *port = tty->driver_data; - struct vizzini_port_private *portdata = usb_get_serial_port_data(port); - struct serial_struct ss; - - dev_dbg(&port->dev, "%s %08x\n", __func__, cmd); - - switch (cmd) { - case TIOCGSERIAL: - if (!arg) - return -EFAULT; - memset(&ss, 0, sizeof(ss)); - ss.baud_base = portdata->baud_base; - if (copy_to_user((void __user *)arg, &ss, sizeof(ss))) - return -EFAULT; - break; - - case TIOCSSERIAL: - if (!arg) - return -EFAULT; - if (copy_from_user(&ss, (void __user *)arg, sizeof(ss))) - return -EFAULT; - portdata->baud_base = ss.baud_base; - dev_dbg(&port->dev, "baud_base=%d\n", portdata->baud_base); - - vizzini_disable(port); - if (portdata->baud_base) - vizzini_set_baud_rate(port, portdata->baud_base); - vizzini_enable(port); - break; - - default: - return -ENOIOCTLCMD; - } - - return 0; -} - -#ifdef VIZZINI_IWA -static const int vizzini_parity[] = { - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, - 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 -}; -#endif - -static void vizzini_out_callback(struct urb *urb) -{ - struct usb_serial_port *port = urb->context; - struct vizzini_port_private *portdata = usb_get_serial_port_data(port); - int status = urb->status; - unsigned long flags; - - dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number); - - /* free up the transfer buffer, as usb_free_urb() does not do this */ - kfree(urb->transfer_buffer); - - if (status) - dev_dbg(&port->dev, "%s - nonzero write bulk status received: %d\n", __func__, status); - - spin_lock_irqsave(&portdata->lock, flags); - --portdata->outstanding_urbs; - spin_unlock_irqrestore(&portdata->lock, flags); - - usb_serial_port_softint(port); -} - -static int vizzini_write_room(struct tty_struct *tty) -{ - struct usb_serial_port *port = tty->driver_data; - struct vizzini_port_private *portdata = usb_get_serial_port_data(port); - unsigned long flags; - - dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number); - - /* try to give a good number back based on if we have any free urbs at - * this point in time */ - spin_lock_irqsave(&portdata->lock, flags); - if (portdata->outstanding_urbs > N_OUT_URB * 2 / 3) { - spin_unlock_irqrestore(&portdata->lock, flags); - dev_dbg(&port->dev, "%s - write limit hit\n", __func__); - return 0; - } - spin_unlock_irqrestore(&portdata->lock, flags); - - return 2048; -} - -static int vizzini_write(struct tty_struct *tty, struct usb_serial_port *port, - const unsigned char *buf, int count) -{ - struct vizzini_port_private *portdata = usb_get_serial_port_data(port); - struct usb_serial *serial = port->serial; - int bufsize = count; - unsigned long flags; - unsigned char *buffer; - struct urb *urb; - int status; - - portdata = usb_get_serial_port_data(port); - - dev_dbg(&port->dev, "%s: write (%d chars)\n", __func__, count); - - spin_lock_irqsave(&portdata->lock, flags); - if (portdata->outstanding_urbs > N_OUT_URB) { - spin_unlock_irqrestore(&portdata->lock, flags); - dev_dbg(&port->dev, "%s - write limit hit\n", __func__); - return 0; - } - portdata->outstanding_urbs++; - spin_unlock_irqrestore(&portdata->lock, flags); - -#ifdef VIZZINI_IWA - if (portdata->iwa != UART_FORMAT_PARITY_NONE) - bufsize = count * 2; -#endif - buffer = kmalloc(bufsize, GFP_ATOMIC); - - if (!buffer) { - dev_err(&port->dev, "out of memory\n"); - count = -ENOMEM; - goto error_no_buffer; - } - - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!urb) { - dev_err(&port->dev, "no more free urbs\n"); - count = -ENOMEM; - goto error_no_urb; - } - -#ifdef VIZZINI_IWA - if (portdata->iwa != UART_FORMAT_PARITY_NONE) { - int i; - char *b = buffer; - for (i = 0; i < count; ++i) { - int c, p = 0; - c = buf[i]; - switch (portdata->iwa) { - case UART_FORMAT_PARITY_ODD: - p = !vizzini_parity[c]; - break; - case UART_FORMAT_PARITY_EVEN: - p = vizzini_parity[c]; - break; - case UART_FORMAT_PARITY_1: - p = 1; - break; - case UART_FORMAT_PARITY_0: - p = 0; - break; - } - *b++ = c; - *b++ = p; - } - } else -#endif - memcpy(buffer, buf, count); - - usb_fill_bulk_urb(urb, serial->dev, - usb_sndbulkpipe(serial->dev, - port->bulk_out_endpointAddress), - buffer, bufsize, vizzini_out_callback, port); - - /* send it down the pipe */ - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status) { - dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed with status = %d\n", __func__, status); - count = status; - goto error; - } - - /* we are done with this urb, so let the host driver - * really free it when it is finished with it */ - usb_free_urb(urb); - - return count; -error: - usb_free_urb(urb); -error_no_urb: - kfree(buffer); -error_no_buffer: - spin_lock_irqsave(&portdata->lock, flags); - --portdata->outstanding_urbs; - spin_unlock_irqrestore(&portdata->lock, flags); - return count; -} - -static void vizzini_in_callback(struct urb *urb) -{ - int endpoint = usb_pipeendpoint(urb->pipe); - struct usb_serial_port *port = urb->context; - struct vizzini_port_private *portdata = usb_get_serial_port_data(port); - struct tty_struct *tty = port->port.tty; - int preciseflags = portdata->preciseflags; - char *transfer_buffer = urb->transfer_buffer; - int length, room, have_extra_byte; - int err; - - if (urb->status) { - dev_dbg(&port->dev, "%s: nonzero status: %d on endpoint %02x.\n", __func__, urb->status, endpoint); - return; - } - -#ifdef VIZZINI_IWA - if (portdata->iwa != UART_FORMAT_PARITY_NONE) - preciseflags = true; -#endif - - length = urb->actual_length; - if (length == 0) { - dev_dbg(&port->dev, "%s: empty read urb received\n", __func__); - err = usb_submit_urb(urb, GFP_ATOMIC); - if (err) - dev_err(&port->dev, "resubmit read urb failed. (%d)\n", err); - return; - } - - length = length + (portdata->have_extra_byte ? 1 : 0); - have_extra_byte = (preciseflags && (length & 1)); - length = (preciseflags) ? (length / 2) : length; - - room = tty_buffer_request_room(tty, length); - if (room != length) - dev_dbg(&port->dev, "Not enough room in TTY buf, dropped %d chars.\n", length - room); - - if (room) { - if (preciseflags) { - char *dp = transfer_buffer; - int i, ch, ch_flags; - - for (i = 0; i < room; ++i) { - char tty_flag; - - if (i == 0) { - if (portdata->have_extra_byte) - ch = portdata->extra_byte; - else - ch = *dp++; - } else { - ch = *dp++; - } - ch_flags = *dp++; - -#ifdef VIZZINI_IWA - { - int p; - switch (portdata->iwa) { - case UART_FORMAT_PARITY_ODD: - p = !vizzini_parity[ch]; - break; - case UART_FORMAT_PARITY_EVEN: - p = vizzini_parity[ch]; - break; - case UART_FORMAT_PARITY_1: - p = 1; - break; - case UART_FORMAT_PARITY_0: - p = 0; - break; - default: - p = 0; - break; - } - ch_flags ^= p; - } -#endif - if (ch_flags & RAMCTL_BUFFER_PARITY) - tty_flag = TTY_PARITY; - else if (ch_flags & RAMCTL_BUFFER_BREAK) - tty_flag = TTY_BREAK; - else if (ch_flags & RAMCTL_BUFFER_FRAME) - tty_flag = TTY_FRAME; - else if (ch_flags & RAMCTL_BUFFER_OVERRUN) - tty_flag = TTY_OVERRUN; - else - tty_flag = TTY_NORMAL; - - tty_insert_flip_char(tty, ch, tty_flag); - } - } else { - tty_insert_flip_string(tty, transfer_buffer, room); - } - - tty_flip_buffer_push(tty); - } - - portdata->have_extra_byte = have_extra_byte; - if (have_extra_byte) - portdata->extra_byte = transfer_buffer[urb->actual_length - 1]; - - err = usb_submit_urb(urb, GFP_ATOMIC); - if (err) - dev_err(&port->dev, "resubmit read urb failed. (%d)\n", err); -} - -static void vizzini_int_callback(struct urb *urb) -{ - struct usb_serial_port *port = urb->context; - struct vizzini_port_private *portdata = usb_get_serial_port_data(port); - struct tty_struct *tty = port->port.tty; - - struct usb_cdc_notification *dr = urb->transfer_buffer; - unsigned char *data; - int newctrl; - int status; - - switch (urb->status) { - case 0: - /* success */ - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - dev_dbg(&port->dev, "urb shutting down with status: %d\n", urb->status); - return; - default: - dev_dbg(&port->dev, "nonzero urb status received: %d\n", urb->status); - goto exit; - } - - data = (unsigned char *)(dr + 1); - switch (dr->bNotificationType) { - - case USB_CDC_NOTIFY_NETWORK_CONNECTION: - dev_dbg(&port->dev, "%s network\n", dr->wValue ? "connected to" : "disconnected from"); - break; - - case USB_CDC_NOTIFY_SERIAL_STATE: - newctrl = le16_to_cpu(get_unaligned((__le16 *)data)); - - if (!portdata->clocal && (portdata->ctrlin & ~newctrl & ACM_CTRL_DCD)) { - dev_dbg(&port->dev, "calling hangup\n"); - tty_hangup(tty); - } - - portdata->ctrlin = newctrl; - - dev_dbg(&port->dev, "input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c\n", - portdata->ctrlin & ACM_CTRL_DCD ? '+' : '-', - portdata->ctrlin & ACM_CTRL_DSR ? '+' : '-', - portdata->ctrlin & ACM_CTRL_BRK ? '+' : '-', - portdata->ctrlin & ACM_CTRL_RI ? '+' : '-', - portdata->ctrlin & ACM_CTRL_FRAMING ? '+' : '-', - portdata->ctrlin & ACM_CTRL_PARITY ? '+' : '-', - portdata->ctrlin & ACM_CTRL_OVERRUN ? '+' : '-'); - break; - - default: - dev_dbg(&port->dev, "unknown notification %d received: index %d len %d data0 %d data1 %d\n", - dr->bNotificationType, dr->wIndex, - dr->wLength, data[0], data[1]); - break; - } -exit: - dev_dbg(&port->dev, "Resubmitting interrupt IN urb %p\n", urb); - status = usb_submit_urb(urb, GFP_ATOMIC); - if (status) - dev_err(&port->dev, "usb_submit_urb failed with result %d", status); -} - -static int vizzini_open(struct tty_struct *tty_param, struct usb_serial_port *port) -{ - struct vizzini_port_private *portdata; - struct usb_serial *serial = port->serial; - struct tty_struct *tty = port->port.tty; - int i; - struct urb *urb; - int result; - - portdata = usb_get_serial_port_data(port); - - acm_set_control(port, portdata->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS); - - /* Reset low level data toggle and start reading from endpoints */ - for (i = 0; i < N_IN_URB; i++) { - dev_dbg(&port->dev, "%s urb %d\n", __func__, i); - - urb = portdata->in_urbs[i]; - if (!urb) - continue; - if (urb->dev != serial->dev) { - dev_dbg(&port->dev, "%s: dev %p != %p\n", __func__, - urb->dev, serial->dev); - continue; - } - - /* - * make sure endpoint data toggle is synchronized with the - * device - */ - /* dev_dbg(&port->dev, "%s clearing halt on %x\n", __func__, urb->pipe); */ - /* usb_clear_halt(urb->dev, urb->pipe); */ - - dev_dbg(&port->dev, "%s submitting urb %p\n", __func__, urb); - result = usb_submit_urb(urb, GFP_KERNEL); - if (result) { - dev_err(&port->dev, "submit urb %d failed (%d) %d\n", - i, result, urb->transfer_buffer_length); - } - } - - tty->low_latency = 1; - - /* start up the interrupt endpoint if we have one */ - if (port->interrupt_in_urb) { - result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); - if (result) - dev_err(&port->dev, "submit irq_in urb failed %d\n", - result); - } - return 0; -} - -static void vizzini_close(struct usb_serial_port *port) -{ - int i; - struct usb_serial *serial = port->serial; - struct vizzini_port_private *portdata; - struct tty_struct *tty = port->port.tty; - - portdata = usb_get_serial_port_data(port); - - acm_set_control(port, portdata->ctrlout = 0); - - if (serial->dev) { - /* Stop reading/writing urbs */ - for (i = 0; i < N_IN_URB; i++) - usb_kill_urb(portdata->in_urbs[i]); - } - - usb_kill_urb(port->interrupt_in_urb); - - tty = NULL; /* FIXME */ -} - -static int vizzini_attach(struct usb_serial *serial) -{ - struct vizzini_serial_private *serial_priv = usb_get_serial_data(serial); - struct usb_interface *interface = serial_priv->data_interface; - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *endpoint; - struct usb_endpoint_descriptor *bulk_in_endpoint = NULL; - struct usb_endpoint_descriptor *bulk_out_endpoint = NULL; - - struct usb_serial_port *port; - struct vizzini_port_private *portdata; - struct urb *urb; - int i, j; - - /* Assume that there's exactly one serial port. */ - port = serial->port[0]; - - /* The usb_serial is now fully set up, but we want to make a - * couple of modifications. Namely, it was configured based - * upon the control interface and not the data interface, so - * it has no notion of the bulk in and out endpoints. So we - * essentially do some of the same allocations and - * configurations that the usb-serial core would have done if - * it had not made any faulty assumptions about the - * endpoints. */ - - iface_desc = interface->cur_altsetting; - for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { - endpoint = &iface_desc->endpoint[i].desc; - - if (usb_endpoint_is_bulk_in(endpoint)) - bulk_in_endpoint = endpoint; - - if (usb_endpoint_is_bulk_out(endpoint)) - bulk_out_endpoint = endpoint; - } - - if (!bulk_out_endpoint || !bulk_in_endpoint) { - dev_dbg(&port->dev, "Missing endpoint!\n"); - return -EINVAL; - } - - port->bulk_out_endpointAddress = bulk_out_endpoint->bEndpointAddress; - port->bulk_in_endpointAddress = bulk_in_endpoint->bEndpointAddress; - - portdata = kzalloc(sizeof(*portdata), GFP_KERNEL); - if (!portdata) { - dev_dbg(&port->dev, "%s: kmalloc for vizzini_port_private (%d) failed!.\n", - __func__, i); - return -ENOMEM; - } - spin_lock_init(&portdata->lock); - for (j = 0; j < N_IN_URB; j++) { - portdata->in_buffer[j] = kmalloc(IN_BUFLEN, GFP_KERNEL); - if (!portdata->in_buffer[j]) { - for (--j; j >= 0; j--) - kfree(portdata->in_buffer[j]); - kfree(portdata); - return -ENOMEM; - } - } - - /* Bulk OUT endpoints 0x1..0x4 map to register blocks 0..3 */ - portdata->block = port->bulk_out_endpointAddress - 1; - - usb_set_serial_port_data(port, portdata); - - portdata->bcd_device = le16_to_cpu(serial->dev->descriptor.bcdDevice); - if (vizzini_rev_a(port)) - dev_info(&port->dev, "Adapting to revA silicon\n"); - - /* initialize the in urbs */ - for (j = 0; j < N_IN_URB; ++j) { - urb = usb_alloc_urb(0, GFP_KERNEL); - if (urb == NULL) { - dev_dbg(&port->dev, "%s: alloc for in port failed.\n", __func__); - continue; - } - /* Fill URB using supplied data. */ - dev_dbg(&port->dev, "Filling URB %p, EP=%d buf=%p len=%d\n", urb, port->bulk_in_endpointAddress, portdata->in_buffer[j], IN_BUFLEN); - usb_fill_bulk_urb(urb, serial->dev, - usb_rcvbulkpipe(serial->dev, - port->bulk_in_endpointAddress), - portdata->in_buffer[j], IN_BUFLEN, - vizzini_in_callback, port); - portdata->in_urbs[j] = urb; - } - - return 0; -} - -static void vizzini_serial_disconnect(struct usb_serial *serial) -{ - struct usb_serial_port *port; - struct vizzini_port_private *portdata; - int i, j; - - dev_dbg(&serial->dev->dev, "%s %p\n", __func__, serial); - - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - if (!port) - continue; - portdata = usb_get_serial_port_data(port); - if (!portdata) - continue; - - for (j = 0; j < N_IN_URB; j++) { - usb_kill_urb(portdata->in_urbs[j]); - usb_free_urb(portdata->in_urbs[j]); - } - } -} - -static void vizzini_serial_release(struct usb_serial *serial) -{ - struct usb_serial_port *port; - struct vizzini_port_private *portdata; - int i, j; - - dev_dbg(&serial->dev->dev, "%s %p\n", __func__, serial); - - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - if (!port) - continue; - portdata = usb_get_serial_port_data(port); - if (!portdata) - continue; - - for (j = 0; j < N_IN_URB; j++) - kfree(portdata->in_buffer[j]); - - kfree(portdata); - usb_set_serial_port_data(port, NULL); - } -} - -static int vizzini_calc_num_ports(struct usb_serial *serial) -{ - return 1; -} - -static int vizzini_probe(struct usb_serial *serial, - const struct usb_device_id *id) -{ - struct usb_interface *intf = serial->interface; - unsigned char *buffer = intf->altsetting->extra; - int buflen = intf->altsetting->extralen; - struct usb_device *usb_dev = interface_to_usbdev(intf); - struct usb_cdc_union_desc *union_header = NULL; - struct usb_cdc_country_functional_desc *cfd = NULL; - int call_interface_num = -1; - int data_interface_num; - struct usb_interface *control_interface; - struct usb_interface *data_interface; - struct usb_endpoint_descriptor *epctrl; - struct usb_endpoint_descriptor *epread; - struct usb_endpoint_descriptor *epwrite; - struct vizzini_serial_private *serial_priv; - - if (!buffer) { - dev_err(&intf->dev, "Weird descriptor references\n"); - return -EINVAL; - } - - if (!buflen) { - if (intf->cur_altsetting->endpoint->extralen && intf->cur_altsetting->endpoint->extra) { - dev_dbg(&intf->dev, "Seeking extra descriptors on endpoint\n"); - buflen = intf->cur_altsetting->endpoint->extralen; - buffer = intf->cur_altsetting->endpoint->extra; - } else { - dev_err(&intf->dev, "Zero length descriptor references\n"); - return -EINVAL; - } - } - - while (buflen > 0) { - if (buffer[1] != USB_DT_CS_INTERFACE) { - dev_err(&intf->dev, "skipping garbage\n"); - goto next_desc; - } - - switch (buffer[2]) { - case USB_CDC_UNION_TYPE: /* we've found it */ - if (union_header) { - dev_err(&intf->dev, "More than one union descriptor, skipping ...\n"); - goto next_desc; - } - union_header = (struct usb_cdc_union_desc *)buffer; - break; - case USB_CDC_COUNTRY_TYPE: /* export through sysfs */ - cfd = (struct usb_cdc_country_functional_desc *)buffer; - break; - case USB_CDC_HEADER_TYPE: /* maybe check version */ - break; /* for now we ignore it */ - case USB_CDC_CALL_MANAGEMENT_TYPE: - call_interface_num = buffer[4]; - break; - default: - /* there are LOTS more CDC descriptors that - * could legitimately be found here. - */ - dev_dbg(&intf->dev, "Ignoring descriptor: type %02x, length %d\n", buffer[2], buffer[0]); - break; - } -next_desc: - buflen -= buffer[0]; - buffer += buffer[0]; - } - - if (!union_header) { - if (call_interface_num > 0) { - dev_dbg(&intf->dev, "No union descriptor, using call management descriptor\n"); - data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num)); - control_interface = intf; - } else { - dev_dbg(&intf->dev, "No union descriptor, giving up\n"); - return -ENODEV; - } - } else { - control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0); - data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0)); - if (!control_interface || !data_interface) { - dev_dbg(&intf->dev, "no interfaces\n"); - return -ENODEV; - } - } - - if (data_interface_num != call_interface_num) - dev_dbg(&intf->dev, "Separate call control interface. That is not fully supported.\n"); - - /* workaround for switched interfaces */ - if (data_interface->cur_altsetting->desc.bInterfaceClass != CDC_DATA_INTERFACE_TYPE) { - if (control_interface->cur_altsetting->desc.bInterfaceClass == CDC_DATA_INTERFACE_TYPE) { - struct usb_interface *t; - - t = control_interface; - control_interface = data_interface; - data_interface = t; - } else { - return -EINVAL; - } - } - - /* Accept probe requests only for the control interface */ - if (intf != control_interface) - return -ENODEV; - - if (usb_interface_claimed(data_interface)) { /* valid in this context */ - dev_dbg(&intf->dev, "The data interface isn't available\n"); - return -EBUSY; - } - - if (data_interface->cur_altsetting->desc.bNumEndpoints < 2) - return -EINVAL; - - epctrl = &control_interface->cur_altsetting->endpoint[0].desc; - epread = &data_interface->cur_altsetting->endpoint[0].desc; - epwrite = &data_interface->cur_altsetting->endpoint[1].desc; - if (!usb_endpoint_dir_in(epread)) { - struct usb_endpoint_descriptor *t; - t = epread; - epread = epwrite; - epwrite = t; - } - - /* The documentation suggests that we allocate private storage - * with the attach() entry point, but we can't allow the data - * interface to remain unclaimed until then; so we need - * somewhere to save the claimed interface now. */ - serial_priv = kzalloc(sizeof(struct vizzini_serial_private), - GFP_KERNEL); - if (!serial_priv) - goto alloc_fail; - usb_set_serial_data(serial, serial_priv); - - //usb_driver_claim_interface(&vizzini_driver, data_interface, NULL); - - /* Don't set the data interface private data. When we - * disconnect we test this field against NULL to discover - * whether we're dealing with the control or data - * interface. */ - serial_priv->data_interface = data_interface; - - return 0; - -alloc_fail: - return -ENOMEM; -} - -static struct usb_serial_driver vizzini_device = { - .driver = { - .owner = THIS_MODULE, - .name = "vizzini", - }, - .description = "Vizzini USB serial port", - .id_table = id_table, - .calc_num_ports = vizzini_calc_num_ports, - .probe = vizzini_probe, - .open = vizzini_open, - .close = vizzini_close, - .write = vizzini_write, - .write_room = vizzini_write_room, - .ioctl = vizzini_ioctl, - .set_termios = vizzini_set_termios, - .break_ctl = vizzini_break_ctl, - .tiocmget = vizzini_tiocmget, - .tiocmset = vizzini_tiocmset, - .attach = vizzini_attach, - .disconnect = vizzini_serial_disconnect, - .release = vizzini_serial_release, - .read_int_callback = vizzini_int_callback, -}; - -static struct usb_serial_driver * const serial_drivers[] = { - &vizzini_device, NULL -}; - -module_usb_serial_driver(serial_drivers, id_table); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION); -MODULE_LICENSE("GPL"); -- cgit v0.10.2 From a0693bd0aa95935bf1a720d7647619c2a4d789ed Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 24 Sep 2012 13:04:02 -0700 Subject: Revert "usb : Add sysfs files to control port power." This reverts commit ca9c9d0c922e4f1dac80699ebab1269d6dbaff85. Rafael wants more time to work on the user api to handle port power issues, so let's just revert the sysfs changes for now. Reported-by: Rafael J. Wysocki Cc: Lan Tianyu Cc: Alan Stern Cc: Sarah Sharp Signed-off-by: Greg Kroah-Hartman diff --git a/Documentation/ABI/testing/sysfs-bus-usb b/Documentation/ABI/testing/sysfs-bus-usb index 13f3eee..b6fbe51 100644 --- a/Documentation/ABI/testing/sysfs-bus-usb +++ b/Documentation/ABI/testing/sysfs-bus-usb @@ -227,27 +227,3 @@ Contact: Lan Tianyu Description: The /sys/bus/usb/devices/.../(hub interface)/portX is usb port device's sysfs directory. - -What: /sys/bus/usb/devices/.../(hub interface)/portX/control -Date: August 2012 -Contact: Lan Tianyu -Description: - The /sys/bus/usb/devices/.../(hub interface)/portX/control - attribute allows user space to control the power policy on - the usb port. - - All ports have one of the following two values for control - "on" - port power must be on. - "off" - port power must be off. - -What: /sys/bus/usb/devices/.../(hub interface)/portX/state -Date: August 2012 -Contact: Lan Tianyu -Description: - The /sys/bus/usb/devices/.../(hub interface)/portX/state - attribute allows user space to check hub port's power state. - - All ports have three following states - "on" - port power on - "off" - port power off - "error" - can't get the hub port's power state diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 6dc41c6..673ee46 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -39,17 +39,11 @@ #endif #endif -enum port_power_policy { - USB_PORT_POWER_ON = 0, - USB_PORT_POWER_OFF, -}; - struct usb_port { struct usb_device *child; struct device dev; struct dev_state *port_owner; enum usb_port_connect_type connect_type; - enum port_power_policy port_power_policy; }; struct usb_hub { @@ -99,10 +93,6 @@ struct usb_hub { struct usb_port **ports; }; -static const char on_string[] = "on"; -static const char off_string[] = "off"; -static const struct attribute_group *port_dev_group[]; - static inline int hub_is_superspeed(struct usb_device *hdev) { return (hdev->descriptor.bDeviceProtocol == USB_HUB_PR_SS); @@ -855,12 +845,7 @@ static unsigned hub_power_on(struct usb_hub *hub, bool do_delay) dev_dbg(hub->intfdev, "trying to enable port power on " "non-switchable hub\n"); for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++) - if (hub->ports[port1 - 1]->port_power_policy - == USB_PORT_POWER_ON) - set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER); - else - clear_port_feature(hub->hdev, port1, - USB_PORT_FEAT_POWER); + set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER); /* Wait at least 100 msec for power to become stable */ delay = max(pgood_delay, (unsigned) 100); @@ -1278,7 +1263,6 @@ static int usb_hub_create_port_device(struct usb_hub *hub, hub->ports[port1 - 1] = port_dev; port_dev->dev.parent = hub->intfdev; - port_dev->dev.groups = port_dev_group; port_dev->dev.type = &usb_port_device_type; dev_set_name(&port_dev->dev, "port%d", port1); @@ -2644,25 +2628,6 @@ static int port_is_power_on(struct usb_hub *hub, unsigned portstatus) return ret; } -static int usb_get_hub_port_power_state(struct usb_device *hdev, int port1) -{ - struct usb_hub *hub = hdev_to_hub(hdev); - struct usb_port_status data; - u16 portstatus; - int ret; - - ret = get_port_status(hub->hdev, port1, &data); - if (ret < 4) { - dev_err(hub->intfdev, - "%s failed (err = %d)\n", __func__, ret); - if (ret >= 0) - ret = -EIO; - return ret; - } else - portstatus = le16_to_cpu(data.wPortStatus); - return port_is_power_on(hub, portstatus); -} - #ifdef CONFIG_PM /* Check if a port is suspended(USB2.0 port) or in U3 state(USB3.0 port) */ @@ -4669,102 +4634,6 @@ static int hub_thread(void *__unused) return 0; } -static ssize_t show_port_power_state(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct usb_device *udev = to_usb_device(dev->parent->parent); - struct usb_interface *intf = to_usb_interface(dev->parent); - int port1, power_state; - const char *result; - - sscanf(dev_name(dev), "port%d", &port1); - usb_autopm_get_interface(intf); - power_state = usb_get_hub_port_power_state(udev, port1); - usb_autopm_put_interface(intf); - if (power_state == 1) - result = on_string; - else if (!power_state) - result = off_string; - else - result = "error"; - return sprintf(buf, "%s\n", result); -} -static DEVICE_ATTR(state, S_IRUGO, show_port_power_state, NULL); - -static ssize_t show_port_power_control(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct usb_port *hub_port = to_usb_port(dev); - const char *result; - - switch (hub_port->port_power_policy) { - case USB_PORT_POWER_ON: - result = on_string; - break; - case USB_PORT_POWER_OFF: - result = off_string; - break; - default: - return -EINVAL; - } - return sprintf(buf, "%s\n", result); -} - -static ssize_t store_port_power_control(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct usb_device *hdev = to_usb_device(dev->parent->parent); - struct usb_interface *intf = to_usb_interface(dev->parent); - struct usb_port *hub_port = to_usb_port(dev); - int port1, ret, len = count; - char *cp; - - sscanf(dev_name(dev), "port%d", &port1); - cp = memchr(buf, '\n', count); - if (cp) - len = cp - buf; - if (len == sizeof(on_string) - 1 - && strncmp(buf, on_string, len) == 0) { - hub_port->port_power_policy = USB_PORT_POWER_ON; - usb_autopm_get_interface(intf); - ret = set_port_feature(hdev, port1, USB_PORT_FEAT_POWER); - usb_autopm_put_interface(intf); - if (ret < 0) - return -EIO; - } else if (len == sizeof(off_string) - 1 - && strncmp(buf, off_string, len) == 0) { - struct usb_hub *hub = hdev_to_hub(hdev); - - hub_port->port_power_policy = USB_PORT_POWER_OFF; - usb_autopm_get_interface(intf); - hub_port_logical_disconnect(hub, port1); - ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_POWER); - usb_autopm_put_interface(intf); - if (ret < 0) - return -EIO; - } else - return -EINVAL; - - return count; -} -static DEVICE_ATTR(control, S_IWUSR | S_IRUGO, show_port_power_control, - store_port_power_control); - -static struct attribute *port_dev_attrs[] = { - &dev_attr_control.attr, - &dev_attr_state.attr, - NULL, -}; - -static struct attribute_group port_dev_attr_grp = { - .attrs = port_dev_attrs, -}; - -static const struct attribute_group *port_dev_group[] = { - &port_dev_attr_grp, - NULL, -}; - static const struct usb_device_id hub_id_table[] = { { .match_flags = USB_DEVICE_ID_MATCH_DEV_CLASS, .bDeviceClass = USB_CLASS_HUB}, -- cgit v0.10.2 From 54575b05af36959dfb6a49a3e9ca0c2b456b7126 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Sun, 23 Sep 2012 09:57:25 +0200 Subject: USB: ftdi_sio: add TIAO USB Multi-Protocol Adapter (TUMPA) support TIAO/DIYGADGET USB Multi-Protocol Adapter (TUMPA) is an FTDI FT2232H based device which provides an easily accessible JTAG, SPI, I2C, serial breakout. http://www.diygadget.com/tiao-usb-multi-protocol-adapter-jtag-spi-i2c-serial.html http://www.tiaowiki.com/w/TIAO_USB_Multi_Protocol_Adapter_User%27s_Manual FTDI FT2232H provides two serial channels (A and B), but on the TUMPA channel A is dedicated to JTAG/SPI while channel B can be used for UART/RS-232: use the ftdi_jtag_quirk to expose only channel B as a usb-serial interface to userspace. Signed-off-by: Antonio Ospite Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 8742a0e..9169f51 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -579,6 +579,8 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_IBS_PEDO_PID) }, { USB_DEVICE(FTDI_VID, FTDI_IBS_PROD_PID) }, { USB_DEVICE(FTDI_VID, FTDI_TAVIR_STK500_PID) }, + { USB_DEVICE(FTDI_VID, FTDI_TIAO_UMPA_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, /* * ELV devices: */ diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 41fe582..57c12ef 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h @@ -517,6 +517,11 @@ */ #define FTDI_TAVIR_STK500_PID 0xFA33 /* STK500 AVR programmer */ +/* + * TIAO product ids (FTDI_VID) + * http://www.tiaowiki.com/w/Main_Page + */ +#define FTDI_TIAO_UMPA_PID 0x8a98 /* TIAO/DIYGADGET USB Multi-Protocol Adapter */ /********************************/ -- cgit v0.10.2 From 5ed338778f917a035f0f0a52327fc4f72e36f7a1 Mon Sep 17 00:00:00 2001 From: Shengzhou Liu Date: Mon, 24 Sep 2012 22:01:35 +0800 Subject: powerpc/usb: remove checking PHY_CLK_VALID for UTMI PHY PHY_CLK_VALID bit doesn't work properly with UTMI PHY. e.g. This bit is always zero on P5040, etc. There is no need to check this bit for UTMI PHY, just keep checking for ULPI PHY to prevent system hanging. This patch should be squashed into previous commit 3735ba8db8e6e "powerpc/usb: fix bug of CPU hang when missing USB PHY clock" Signed-off-by: Shengzhou Liu Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index 11ff4b4..9bfde82 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c @@ -267,8 +267,7 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, break; } - if ((pdata->controller_ver) && ((phy_mode == FSL_USB2_PHY_ULPI) || - (phy_mode == FSL_USB2_PHY_UTMI))) { + if (pdata->controller_ver && (phy_mode == FSL_USB2_PHY_ULPI)) { /* check PHY_CLK_VALID to get phy clk valid */ if (!spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) & PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0)) { diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h index 38b5660..a82296a 100644 --- a/include/linux/fsl_devices.h +++ b/include/linux/fsl_devices.h @@ -19,7 +19,7 @@ #define FSL_UTMI_PHY_DLY 10 /*As per P1010RM, delay for UTMI PHY CLK to become stable - 10ms*/ -#define FSL_USB_PHY_CLK_TIMEOUT 1000 /* uSec */ +#define FSL_USB_PHY_CLK_TIMEOUT 10000 /* uSec */ #define FSL_USB_VER_OLD 0 #define FSL_USB_VER_1_6 1 #define FSL_USB_VER_2_2 2 -- cgit v0.10.2 From 80fab3b244a22e0ca539d2439bdda50e81e5666f Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Wed, 19 Sep 2012 16:27:26 -0700 Subject: xhci: Intel Panther Point BEI quirk. When a device with an isochronous endpoint is behind a hub plugged into the Intel Panther Point xHCI host controller, and the driver submits multiple frames per URB, the xHCI driver will set the Block Event Interrupt (BEI) flag on all but the last TD for the URB. This causes the host controller to place an event on the event ring, but not send an interrupt. When the last TD for the URB completes, BEI is cleared, and we get an interrupt for the whole URB. However, under a Panther Point xHCI host controller, if the parent hub is unplugged when one or more events from transfers with BEI set are on the event ring, a port status change event is placed on the event ring, but no interrupt is generated. This means URBs stop completing, and the USB device disconnect is not noticed. Something like a USB headset will cause mplayer to hang when the device is disconnected. If another transfer is sent (such as running `sudo lsusb -v`), the next transfer event seems to "unstick" the event ring, the xHCI driver gets an interrupt, and the disconnect is reported to the USB core. The fix is not to use the BEI flag under the Panther Point xHCI host. This will impact power consumption and system responsiveness, because the xHCI driver will receive an interrupt for every frame in all isochronous URBs instead of once per URB. Intel chipset developers confirm that this bug will be hit if the BEI flag is used on any endpoint, not just ones that are behind a hub. This patch should be backported to kernels as old as 3.0, that contain the commit 69e848c2090aebba5698a1620604c7dccb448684 "Intel xhci: Support EHCI/xHCI port switching." Signed-off-by: Sarah Sharp Cc: stable@vger.kernel.org diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index 9bfd4ca11..8345d7c 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c @@ -103,6 +103,7 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci) * PPT chipsets. */ xhci->quirks |= XHCI_SPURIOUS_REBOOT; + xhci->quirks |= XHCI_AVOID_BEI; } if (pdev->vendor == PCI_VENDOR_ID_ETRON && pdev->device == PCI_DEVICE_ID_ASROCK_P67) { diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index f270e70..c6ebb17 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -3672,7 +3672,9 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, } else { td->last_trb = ep_ring->enqueue; field |= TRB_IOC; - if (xhci->hci_version == 0x100) { + if (xhci->hci_version == 0x100 && + !(xhci->quirks & + XHCI_AVOID_BEI)) { /* Set BEI bit except for the last td */ if (i < num_tds - 1) field |= TRB_BEI; diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index e44e2d3..53df4e7 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h @@ -1511,6 +1511,7 @@ struct xhci_hcd { #define XHCI_INTEL_HOST (1 << 12) #define XHCI_SPURIOUS_REBOOT (1 << 13) #define XHCI_COMP_MODE_QUIRK (1 << 14) +#define XHCI_AVOID_BEI (1 << 15) unsigned int num_active_eps; unsigned int limit_active_eps; /* There are two roothubs to keep track of bus suspend info for */ -- cgit v0.10.2 From a0e39e346822d115b2446a7c0032d799c48ac1a5 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 25 Sep 2012 10:47:04 +0200 Subject: USB: uas: keep track of command urbs Signed-off-by: Gerd Hoffmann Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 638cd64..ab66365 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -41,6 +41,7 @@ struct sense_iu_old { struct uas_dev_info { struct usb_interface *intf; struct usb_device *udev; + struct usb_anchor cmd_urbs; struct usb_anchor sense_urbs; struct usb_anchor data_urbs; int qdepth, resetting; @@ -431,6 +432,7 @@ static int uas_submit_task_urb(struct scsi_cmnd *cmnd, gfp_t gfp, err = usb_submit_urb(urb, gfp); if (err) goto err; + usb_anchor_urb(urb, &devinfo->cmd_urbs); return 0; @@ -521,18 +523,22 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, if (cmdinfo->state & ALLOC_CMD_URB) { cmdinfo->cmd_urb = uas_alloc_cmd_urb(devinfo, gfp, cmnd, - cmdinfo->stream); + cmdinfo->stream); if (!cmdinfo->cmd_urb) return SCSI_MLQUEUE_DEVICE_BUSY; cmdinfo->state &= ~ALLOC_CMD_URB; } if (cmdinfo->state & SUBMIT_CMD_URB) { + usb_get_urb(cmdinfo->cmd_urb); if (usb_submit_urb(cmdinfo->cmd_urb, gfp)) { scmd_printk(KERN_INFO, cmnd, "cmd urb submission failure\n"); return SCSI_MLQUEUE_DEVICE_BUSY; } + usb_anchor_urb(cmdinfo->cmd_urb, &devinfo->cmd_urbs); + usb_put_urb(cmdinfo->cmd_urb); + cmdinfo->cmd_urb = NULL; cmdinfo->state &= ~SUBMIT_CMD_URB; cmdinfo->state |= COMMAND_INFLIGHT; } @@ -670,6 +676,7 @@ static int uas_eh_bus_reset_handler(struct scsi_cmnd *cmnd) int err; devinfo->resetting = 1; + usb_kill_anchored_urbs(&devinfo->cmd_urbs); usb_kill_anchored_urbs(&devinfo->sense_urbs); usb_kill_anchored_urbs(&devinfo->data_urbs); err = usb_reset_device(udev); @@ -868,6 +875,7 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) devinfo->intf = intf; devinfo->udev = udev; devinfo->resetting = 0; + init_usb_anchor(&devinfo->cmd_urbs); init_usb_anchor(&devinfo->sense_urbs); init_usb_anchor(&devinfo->data_urbs); uas_configure_endpoints(devinfo); @@ -913,6 +921,7 @@ static void uas_disconnect(struct usb_interface *intf) struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; scsi_remove_host(shost); + usb_kill_anchored_urbs(&devinfo->cmd_urbs); usb_kill_anchored_urbs(&devinfo->sense_urbs); usb_kill_anchored_urbs(&devinfo->data_urbs); uas_free_streams(devinfo); -- cgit v0.10.2 From 03939864954cdfccf41c0a8c20e5f2ba623cc482 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 25 Sep 2012 10:47:05 +0200 Subject: USB: uas: fix task management Allocate one tag for task management functions and use it properly. Signed-off-by: Gerd Hoffmann Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index ab66365..1d326c5 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -611,7 +611,7 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd, { struct Scsi_Host *shost = cmnd->device->host; struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; - u16 tag = 9999; /* FIXME */ + u16 tag = devinfo->qdepth - 1; memset(&devinfo->response, 0, sizeof(devinfo->response)); if (uas_submit_sense_urb(shost, GFP_NOIO, tag)) { @@ -701,7 +701,7 @@ static int uas_slave_configure(struct scsi_device *sdev) { struct uas_dev_info *devinfo = sdev->hostdata; scsi_set_tag_type(sdev, MSG_ORDERED_TAG); - scsi_activate_tcq(sdev, devinfo->qdepth - 2); + scsi_activate_tcq(sdev, devinfo->qdepth - 3); return 0; } @@ -880,7 +880,7 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) init_usb_anchor(&devinfo->data_urbs); uas_configure_endpoints(devinfo); - result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 2); + result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 3); if (result) goto free; -- cgit v0.10.2 From ef018cc9f894efcca7e785ee75f1dd546e11afee Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 25 Sep 2012 10:47:06 +0200 Subject: USB: uas: remove aborted field, replace with status bit. Signed-off-by: Gerd Hoffmann Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 1d326c5..42976ec 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -64,13 +64,13 @@ enum { DATA_IN_URB_INFLIGHT = (1 << 9), DATA_OUT_URB_INFLIGHT = (1 << 10), COMMAND_COMPLETED = (1 << 11), + COMMAND_ABORTED = (1 << 12), }; /* Overrides scsi_pointer */ struct uas_cmd_info { unsigned int state; unsigned int stream; - unsigned int aborted; struct urb *cmd_urb; struct urb *data_in_urb; struct urb *data_out_urb; @@ -163,7 +163,7 @@ static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *caller) struct uas_cmd_info *ci = (void *)&cmnd->SCp; scmd_printk(KERN_INFO, cmnd, "%s %p tag %d, inflight:" - "%s%s%s%s%s%s%s%s%s%s%s\n", + "%s%s%s%s%s%s%s%s%s%s%s%s\n", caller, cmnd, cmnd->request->tag, (ci->state & SUBMIT_STATUS_URB) ? " s-st" : "", (ci->state & ALLOC_DATA_IN_URB) ? " a-in" : "", @@ -175,7 +175,8 @@ static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *caller) (ci->state & COMMAND_INFLIGHT) ? " CMD" : "", (ci->state & DATA_IN_URB_INFLIGHT) ? " IN" : "", (ci->state & DATA_OUT_URB_INFLIGHT) ? " OUT" : "", - (ci->state & COMMAND_COMPLETED) ? " done" : ""); + (ci->state & COMMAND_COMPLETED) ? " done" : "", + (ci->state & COMMAND_ABORTED) ? " abort" : ""); } static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller) @@ -302,7 +303,7 @@ static void uas_data_cmplt(struct urb *urb) } else { sdb->resid = sdb->length - urb->actual_length; } - if (cmdinfo->aborted) { + if (cmdinfo->state & COMMAND_ABORTED) { return; } uas_try_complete(cmnd, __func__); @@ -570,7 +571,6 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, cmdinfo->state = SUBMIT_STATUS_URB | ALLOC_CMD_URB | SUBMIT_CMD_URB; - cmdinfo->aborted = 0; switch (cmnd->sc_data_direction) { case DMA_FROM_DEVICE: @@ -652,7 +652,7 @@ static int uas_eh_abort_handler(struct scsi_cmnd *cmnd) int ret; uas_log_cmd_state(cmnd, __func__); - cmdinfo->aborted = 1; + cmdinfo->state |= COMMAND_ABORTED; ret = uas_eh_task_mgmt(cmnd, "ABORT TASK", TMF_ABORT_TASK); if (cmdinfo->state & DATA_IN_URB_INFLIGHT) usb_kill_urb(cmdinfo->data_in_urb); -- cgit v0.10.2 From 0871d7d86ce3788ba40391df3a259df2285776cd Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 25 Sep 2012 10:47:07 +0200 Subject: USB: uas: fix abort Properly report aborted commands. Also don't access cmdinfo after kicking task management, it may not be valid any more once it returns. Signed-off-by: Gerd Hoffmann Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 42976ec..df1d72e 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -191,6 +191,10 @@ static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller) cmdinfo->state |= COMMAND_COMPLETED; usb_free_urb(cmdinfo->data_in_urb); usb_free_urb(cmdinfo->data_out_urb); + if (cmdinfo->state & COMMAND_ABORTED) { + scmd_printk(KERN_INFO, cmnd, "abort completed\n"); + cmnd->result = DID_ABORT << 16; + } cmnd->scsi_done(cmnd); return 0; } @@ -303,9 +307,6 @@ static void uas_data_cmplt(struct urb *urb) } else { sdb->resid = sdb->length - urb->actual_length; } - if (cmdinfo->state & COMMAND_ABORTED) { - return; - } uas_try_complete(cmnd, __func__); } @@ -654,10 +655,6 @@ static int uas_eh_abort_handler(struct scsi_cmnd *cmnd) uas_log_cmd_state(cmnd, __func__); cmdinfo->state |= COMMAND_ABORTED; ret = uas_eh_task_mgmt(cmnd, "ABORT TASK", TMF_ABORT_TASK); - if (cmdinfo->state & DATA_IN_URB_INFLIGHT) - usb_kill_urb(cmdinfo->data_in_urb); - if (cmdinfo->state & DATA_OUT_URB_INFLIGHT) - usb_kill_urb(cmdinfo->data_out_urb); return ret; } -- cgit v0.10.2 From e064852072c47b69f62325c6b7fa4a58332655bd Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Tue, 25 Sep 2012 10:47:08 +0200 Subject: USB: uas: add locking Add spinlock to protect uas data structures. [ v2: s/GFP_NOIO/GFP_ATOMIC/, better don't sleep when holding a spinlock ] Signed-off-by: Gerd Hoffmann Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index df1d72e..1578909 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -50,6 +50,7 @@ struct uas_dev_info { unsigned use_streams:1; unsigned uas_sense_old:1; struct scsi_cmnd *cmnd; + spinlock_t lock; }; enum { @@ -91,6 +92,7 @@ static void uas_do_work(struct work_struct *work) struct uas_cmd_info *cmdinfo; struct uas_cmd_info *temp; struct list_head list; + unsigned long flags; int err; spin_lock_irq(&uas_work_lock); @@ -101,7 +103,10 @@ static void uas_do_work(struct work_struct *work) struct scsi_pointer *scp = (void *)cmdinfo; struct scsi_cmnd *cmnd = container_of(scp, struct scsi_cmnd, SCp); - err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_NOIO); + struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata; + spin_lock_irqsave(&devinfo->lock, flags); + err = uas_submit_urbs(cmnd, cmnd->device->hostdata, GFP_ATOMIC); + spin_unlock_irqrestore(&devinfo->lock, flags); if (err) { list_del(&cmdinfo->list); spin_lock_irq(&uas_work_lock); @@ -182,7 +187,9 @@ static void uas_log_cmd_state(struct scsi_cmnd *cmnd, const char *caller) static int uas_try_complete(struct scsi_cmnd *cmnd, const char *caller) { struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; + struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata; + WARN_ON(!spin_is_locked(&devinfo->lock)); if (cmdinfo->state & (COMMAND_INFLIGHT | DATA_IN_URB_INFLIGHT | DATA_OUT_URB_INFLIGHT)) @@ -222,6 +229,7 @@ static void uas_stat_cmplt(struct urb *urb) struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; struct scsi_cmnd *cmnd; struct uas_cmd_info *cmdinfo; + unsigned long flags; u16 tag; if (urb->status) { @@ -235,6 +243,7 @@ static void uas_stat_cmplt(struct urb *urb) return; } + spin_lock_irqsave(&devinfo->lock, flags); tag = be16_to_cpup(&iu->tag) - 1; if (tag == 0) cmnd = devinfo->cmnd; @@ -243,6 +252,7 @@ static void uas_stat_cmplt(struct urb *urb) if (!cmnd) { if (iu->iu_id != IU_ID_RESPONSE) { usb_free_urb(urb); + spin_unlock_irqrestore(&devinfo->lock, flags); return; } } else { @@ -262,10 +272,16 @@ static void uas_stat_cmplt(struct urb *urb) uas_sense(urb, cmnd); if (cmnd->result != 0) { /* cancel data transfers on error */ - if (cmdinfo->state & DATA_IN_URB_INFLIGHT) + if (cmdinfo->state & DATA_IN_URB_INFLIGHT) { + spin_unlock_irqrestore(&devinfo->lock, flags); usb_unlink_urb(cmdinfo->data_in_urb); - if (cmdinfo->state & DATA_OUT_URB_INFLIGHT) + spin_lock_irqsave(&devinfo->lock, flags); + } + if (cmdinfo->state & DATA_OUT_URB_INFLIGHT) { + spin_unlock_irqrestore(&devinfo->lock, flags); usb_unlink_urb(cmdinfo->data_out_urb); + spin_lock_irqsave(&devinfo->lock, flags); + } } cmdinfo->state &= ~COMMAND_INFLIGHT; uas_try_complete(cmnd, __func__); @@ -285,14 +301,18 @@ static void uas_stat_cmplt(struct urb *urb) "Bogus IU (%d) received on status pipe\n", iu->iu_id); } usb_free_urb(urb); + spin_unlock_irqrestore(&devinfo->lock, flags); } static void uas_data_cmplt(struct urb *urb) { struct scsi_cmnd *cmnd = urb->context; struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; + struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata; struct scsi_data_buffer *sdb = NULL; + unsigned long flags; + spin_lock_irqsave(&devinfo->lock, flags); if (cmdinfo->data_in_urb == urb) { sdb = scsi_in(cmnd); cmdinfo->state &= ~DATA_IN_URB_INFLIGHT; @@ -308,6 +328,7 @@ static void uas_data_cmplt(struct urb *urb) sdb->resid = sdb->length - urb->actual_length; } uas_try_complete(cmnd, __func__); + spin_unlock_irqrestore(&devinfo->lock, flags); } static struct urb *uas_alloc_data_urb(struct uas_dev_info *devinfo, gfp_t gfp, @@ -474,6 +495,7 @@ static int uas_submit_urbs(struct scsi_cmnd *cmnd, struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; int err; + WARN_ON(!spin_is_locked(&devinfo->lock)); if (cmdinfo->state & SUBMIT_STATUS_URB) { err = uas_submit_sense_urb(cmnd->device->host, gfp, cmdinfo->stream); @@ -554,12 +576,16 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, struct scsi_device *sdev = cmnd->device; struct uas_dev_info *devinfo = sdev->hostdata; struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; + unsigned long flags; int err; BUILD_BUG_ON(sizeof(struct uas_cmd_info) > sizeof(struct scsi_pointer)); - if (devinfo->cmnd) + spin_lock_irqsave(&devinfo->lock, flags); + if (devinfo->cmnd) { + spin_unlock_irqrestore(&devinfo->lock, flags); return SCSI_MLQUEUE_DEVICE_BUSY; + } if (blk_rq_tagged(cmnd->request)) { cmdinfo->stream = cmnd->request->tag + 2; @@ -594,6 +620,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, if (err) { /* If we did nothing, give up now */ if (cmdinfo->state & SUBMIT_STATUS_URB) { + spin_unlock_irqrestore(&devinfo->lock, flags); return SCSI_MLQUEUE_DEVICE_BUSY; } spin_lock(&uas_work_lock); @@ -602,6 +629,7 @@ static int uas_queuecommand_lck(struct scsi_cmnd *cmnd, schedule_work(&uas_work); } + spin_unlock_irqrestore(&devinfo->lock, flags); return 0; } @@ -613,21 +641,25 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd, struct Scsi_Host *shost = cmnd->device->host; struct uas_dev_info *devinfo = (void *)shost->hostdata[0]; u16 tag = devinfo->qdepth - 1; + unsigned long flags; + spin_lock_irqsave(&devinfo->lock, flags); memset(&devinfo->response, 0, sizeof(devinfo->response)); - if (uas_submit_sense_urb(shost, GFP_NOIO, tag)) { + if (uas_submit_sense_urb(shost, GFP_ATOMIC, tag)) { shost_printk(KERN_INFO, shost, "%s: %s: submit sense urb failed\n", __func__, fname); return FAILED; } - if (uas_submit_task_urb(cmnd, GFP_NOIO, function, tag)) { + if (uas_submit_task_urb(cmnd, GFP_ATOMIC, function, tag)) { shost_printk(KERN_INFO, shost, "%s: %s: submit task mgmt urb failed\n", __func__, fname); return FAILED; } - if (0 == usb_wait_anchor_empty_timeout(&devinfo->sense_urbs, 3000)) { + spin_unlock_irqrestore(&devinfo->lock, flags); + + if (usb_wait_anchor_empty_timeout(&devinfo->sense_urbs, 3000) == 0) { shost_printk(KERN_INFO, shost, "%s: %s timed out\n", __func__, fname); return FAILED; @@ -650,10 +682,14 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd, static int uas_eh_abort_handler(struct scsi_cmnd *cmnd) { struct uas_cmd_info *cmdinfo = (void *)&cmnd->SCp; + struct uas_dev_info *devinfo = (void *)cmnd->device->hostdata; + unsigned long flags; int ret; uas_log_cmd_state(cmnd, __func__); + spin_lock_irqsave(&devinfo->lock, flags); cmdinfo->state |= COMMAND_ABORTED; + spin_unlock_irqrestore(&devinfo->lock, flags); ret = uas_eh_task_mgmt(cmnd, "ABORT TASK", TMF_ABORT_TASK); return ret; } @@ -875,6 +911,7 @@ static int uas_probe(struct usb_interface *intf, const struct usb_device_id *id) init_usb_anchor(&devinfo->cmd_urbs); init_usb_anchor(&devinfo->sense_urbs); init_usb_anchor(&devinfo->data_urbs); + spin_lock_init(&devinfo->lock); uas_configure_endpoints(devinfo); result = scsi_init_shared_tag_map(shost, devinfo->qdepth - 3); -- cgit v0.10.2 From 0a2314035cab62cafc38ea11ec5b6f95cf347b38 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 26 Sep 2012 13:09:53 -0400 Subject: USB: Fix race condition when removing host controllers This patch (as1607) fixes a race that can occur if a USB host controller is removed while a process is reading the /sys/kernel/debug/usb/devices file. The usb_device_read() routine uses the bus->root_hub pointer to determine whether or not the root hub is registered. The is not a valid test, because the pointer is set before the root hub gets registered and remains set even after the root hub is unregistered and deallocated. As a result, usb_device_read() or usb_device_dump() can access freed memory, causing an oops. The patch changes the test to use the hcd->rh_registered flag, which does get set and cleared at the appropriate times. It also makes sure to hold the usb_bus_list_lock mutex while setting the flag, so that usb_device_read() will become aware of new root hubs as soon as they are registered. Signed-off-by: Alan Stern Reported-by: Don Zickus Cc: stable Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index f4ead12..f460de3 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -623,7 +623,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, /* print devices for all busses */ list_for_each_entry(bus, &usb_bus_list, bus_list) { /* recurse through all children of the root hub */ - if (!bus->root_hub) + if (!bus_to_hcd(bus)->rh_registered) continue; usb_lock_device(bus->root_hub); ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos, diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 35b52f6..1e741bc 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1011,10 +1011,7 @@ static int register_root_hub(struct usb_hcd *hcd) if (retval) { dev_err (parent_dev, "can't register root hub for %s, %d\n", dev_name(&usb_dev->dev), retval); - } - mutex_unlock(&usb_bus_list_lock); - - if (retval == 0) { + } else { spin_lock_irq (&hcd_root_hub_lock); hcd->rh_registered = 1; spin_unlock_irq (&hcd_root_hub_lock); @@ -1023,6 +1020,7 @@ static int register_root_hub(struct usb_hcd *hcd) if (HCD_DEAD(hcd)) usb_hc_died (hcd); /* This time clean up */ } + mutex_unlock(&usb_bus_list_lock); return retval; } -- cgit v0.10.2 From 1994ff405e9c1a8916ca41e093e786262af42b42 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 26 Sep 2012 10:28:58 +0200 Subject: USB: uas: fix locking Forgot to unlock in the uas_eh_task_mgmt error paths. Signed-off-by: Gerd Hoffmann Reported-by: Fengguang Wu Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 1578909..4218701 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -649,12 +649,14 @@ static int uas_eh_task_mgmt(struct scsi_cmnd *cmnd, shost_printk(KERN_INFO, shost, "%s: %s: submit sense urb failed\n", __func__, fname); + spin_unlock_irqrestore(&devinfo->lock, flags); return FAILED; } if (uas_submit_task_urb(cmnd, GFP_ATOMIC, function, tag)) { shost_printk(KERN_INFO, shost, "%s: %s: submit task mgmt urb failed\n", __func__, fname); + spin_unlock_irqrestore(&devinfo->lock, flags); return FAILED; } spin_unlock_irqrestore(&devinfo->lock, flags); -- cgit v0.10.2 From e0423dee897734576cf4cc021165dd4521e9d3cc Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Wed, 26 Sep 2012 10:29:03 +0200 Subject: USB: uas: fix gcc warning Streamline control flow so it is easier for gcc to follow which paths can be taken and which can't. Fixes "warning: 'cmdinfo' may be used uninitialized in this function" Signed-off-by: Gerd Hoffmann Reported-by: Fengguang Wu Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c index 4218701..98b98ee 100644 --- a/drivers/usb/storage/uas.c +++ b/drivers/usb/storage/uas.c @@ -249,16 +249,18 @@ static void uas_stat_cmplt(struct urb *urb) cmnd = devinfo->cmnd; else cmnd = scsi_host_find_tag(shost, tag - 1); + if (!cmnd) { - if (iu->iu_id != IU_ID_RESPONSE) { - usb_free_urb(urb); - spin_unlock_irqrestore(&devinfo->lock, flags); - return; + if (iu->iu_id == IU_ID_RESPONSE) { + /* store results for uas_eh_task_mgmt() */ + memcpy(&devinfo->response, iu, sizeof(devinfo->response)); } - } else { - cmdinfo = (void *)&cmnd->SCp; + usb_free_urb(urb); + spin_unlock_irqrestore(&devinfo->lock, flags); + return; } + cmdinfo = (void *)&cmnd->SCp; switch (iu->iu_id) { case IU_ID_STATUS: if (devinfo->cmnd == cmnd) @@ -292,10 +294,6 @@ static void uas_stat_cmplt(struct urb *urb) case IU_ID_WRITE_READY: uas_xfer_data(urb, cmnd, SUBMIT_DATA_OUT_URB); break; - case IU_ID_RESPONSE: - /* store results for uas_eh_task_mgmt() */ - memcpy(&devinfo->response, iu, sizeof(devinfo->response)); - break; default: scmd_printk(KERN_ERR, cmnd, "Bogus IU (%d) received on status pipe\n", iu->iu_id); -- cgit v0.10.2 From 70c048a238c780c226eb4b115ebaa908cb3b34ec Mon Sep 17 00:00:00 2001 From: Rene Buergel Date: Wed, 26 Sep 2012 22:20:19 +0200 Subject: USB: ezusb: move ezusb.c from drivers/usb/serial to drivers/usb/misc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch - moves drivers/usb/serial/ezusb.c to drivers/usb/misc/ - renamed CONFIG_USB_EZUSB to CONFIG_USB_EZUSB_FX2 to avoid build errors - adapts Makefiles and Kconfigs switching from bool to tristate for CONFIG_USB_EZUSB_FX2 Signed-off-by: René Bürgel Signed-off-by: Greg Kroah-Hartman diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index 1bfcd02..a8f0523 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -244,3 +244,8 @@ config USB_YUREX To compile this driver as a module, choose M here: the module will be called yurex. +config USB_EZUSB_FX2 + tristate "Functions for loading firmware on EZUSB chips" + help + Say Y here if you need EZUSB device support. + (Cypress FX/FX2/FX2LP microcontrollers) diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 796ce7e..3e99a64 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -11,6 +11,7 @@ obj-$(CONFIG_USB_CYPRESS_CY7C63) += cypress_cy7c63.o obj-$(CONFIG_USB_CYTHERM) += cytherm.o obj-$(CONFIG_USB_EMI26) += emi26.o obj-$(CONFIG_USB_EMI62) += emi62.o +obj-$(CONFIG_USB_EZUSB_FX2) += ezusb.o obj-$(CONFIG_USB_FTDI_ELAN) += ftdi-elan.o obj-$(CONFIG_USB_IDMOUSE) += idmouse.o obj-$(CONFIG_USB_IOWARRIOR) += iowarrior.o diff --git a/drivers/usb/misc/ezusb.c b/drivers/usb/misc/ezusb.c new file mode 100644 index 0000000..4223d76 --- /dev/null +++ b/drivers/usb/misc/ezusb.c @@ -0,0 +1,160 @@ +/* + * EZ-USB specific functions used by some of the USB to Serial drivers. + * + * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com) + * + * 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 +#include +#include +#include +#include +#include +#include + +struct ezusb_fx_type { + /* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */ + unsigned short cpucs_reg; + unsigned short max_internal_adress; +}; + +struct ezusb_fx_type ezusb_fx1 = { + .cpucs_reg = 0x7F92, + .max_internal_adress = 0x1B3F, +}; + +struct ezusb_fx_type ezusb_fx2 = { + .cpucs_reg = 0xE600, + .max_internal_adress = 0x3FFF, +}; + +/* Commands for writing to memory */ +#define WRITE_INT_RAM 0xA0 +#define WRITE_EXT_RAM 0xA3 + +int ezusb_writememory(struct usb_device *dev, int address, + unsigned char *data, int length, __u8 request) +{ + int result; + unsigned char *transfer_buffer; + + if (!dev) + return -ENODEV; + + transfer_buffer = kmemdup(data, length, GFP_KERNEL); + if (!transfer_buffer) { + dev_err(&dev->dev, "%s - kmalloc(%d) failed.\n", + __func__, length); + return -ENOMEM; + } + result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + address, 0, transfer_buffer, length, 3000); + + kfree(transfer_buffer); + return result; +} +EXPORT_SYMBOL_GPL(ezusb_writememory); + +int ezusb_set_reset(struct usb_device *dev, unsigned short cpucs_reg, + unsigned char reset_bit) +{ + int response = ezusb_writememory(dev, cpucs_reg, &reset_bit, 1, WRITE_INT_RAM); + if (response < 0) + dev_err(&dev->dev, "%s-%d failed: %d\n", + __func__, reset_bit, response); + return response; +} + +int ezusb_fx1_set_reset(struct usb_device *dev, unsigned char reset_bit) +{ + return ezusb_set_reset(dev, ezusb_fx1.cpucs_reg, reset_bit); +} +EXPORT_SYMBOL_GPL(ezusb_fx1_set_reset); + +int ezusb_fx2_set_reset(struct usb_device *dev, unsigned char reset_bit) +{ + return ezusb_set_reset(dev, ezusb_fx2.cpucs_reg, reset_bit); +} +EXPORT_SYMBOL_GPL(ezusb_fx2_set_reset); + +static int ezusb_ihex_firmware_download(struct usb_device *dev, + struct ezusb_fx_type fx, + const char *firmware_path) +{ + int ret = -ENOENT; + const struct firmware *firmware = NULL; + const struct ihex_binrec *record; + + if (request_ihex_firmware(&firmware, firmware_path, + &dev->dev)) { + dev_err(&dev->dev, + "%s - request \"%s\" failed\n", + __func__, firmware_path); + goto out; + } + + ret = ezusb_set_reset(dev, fx.cpucs_reg, 0); + if (ret < 0) + goto out; + + record = (const struct ihex_binrec *)firmware->data; + for (; record; record = ihex_next_binrec(record)) { + if (be32_to_cpu(record->addr) > fx.max_internal_adress) { + ret = ezusb_writememory(dev, be32_to_cpu(record->addr), + (unsigned char *)record->data, + be16_to_cpu(record->len), WRITE_EXT_RAM); + if (ret < 0) { + dev_err(&dev->dev, "%s - ezusb_writememory " + "failed writing internal memory " + "(%d %04X %p %d)\n", __func__, ret, + be32_to_cpu(record->addr), record->data, + be16_to_cpu(record->len)); + goto out; + } + } + } + + ret = ezusb_set_reset(dev, fx.cpucs_reg, 1); + if (ret < 0) + goto out; + record = (const struct ihex_binrec *)firmware->data; + for (; record; record = ihex_next_binrec(record)) { + if (be32_to_cpu(record->addr) <= fx.max_internal_adress) { + ret = ezusb_writememory(dev, be32_to_cpu(record->addr), + (unsigned char *)record->data, + be16_to_cpu(record->len), WRITE_INT_RAM); + if (ret < 0) { + dev_err(&dev->dev, "%s - ezusb_writememory " + "failed writing external memory " + "(%d %04X %p %d)\n", __func__, ret, + be32_to_cpu(record->addr), record->data, + be16_to_cpu(record->len)); + goto out; + } + } + } + ret = ezusb_set_reset(dev, fx.cpucs_reg, 0); +out: + release_firmware(firmware); + return ret; +} + +int ezusb_fx1_ihex_firmware_download(struct usb_device *dev, + const char *firmware_path) +{ + return ezusb_ihex_firmware_download(dev, ezusb_fx1, firmware_path); +} +EXPORT_SYMBOL_GPL(ezusb_fx1_ihex_firmware_download); + +int ezusb_fx2_ihex_firmware_download(struct usb_device *dev, + const char *firmware_path) +{ + return ezusb_ihex_firmware_download(dev, ezusb_fx2, firmware_path); +} +EXPORT_SYMBOL_GPL(ezusb_fx2_ihex_firmware_download); + diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index f604f70..76f4622 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -42,11 +42,6 @@ config USB_SERIAL_CONSOLE If unsure, say N. -config USB_EZUSB - bool "Functions for loading firmware on EZUSB chips" - help - Say Y here if you need EZUSB device support. - config USB_SERIAL_GENERIC bool "USB Generic Serial Driver" help @@ -94,7 +89,7 @@ config USB_SERIAL_CH341 config USB_SERIAL_WHITEHEAT tristate "USB ConnectTech WhiteHEAT Serial Driver" - select USB_EZUSB + select USB_EZUSB_FX2 help Say Y here if you want to use a ConnectTech WhiteHEAT 4 port USB to serial converter device. @@ -281,7 +276,7 @@ config USB_SERIAL_IUU config USB_SERIAL_KEYSPAN_PDA tristate "USB Keyspan PDA Single Port Serial Driver" - select USB_EZUSB + select USB_EZUSB_FX2 help Say Y here if you want to use a Keyspan PDA single port USB to serial converter device. This driver makes use of firmware @@ -292,7 +287,7 @@ config USB_SERIAL_KEYSPAN_PDA config USB_SERIAL_KEYSPAN tristate "USB Keyspan USA-xxx Serial Driver" - select USB_EZUSB + select USB_EZUSB_FX2 ---help--- Say Y here if you want to use Keyspan USB to serial converter devices. This driver makes use of Keyspan's official firmware @@ -596,7 +591,7 @@ config USB_SERIAL_CYBERJACK config USB_SERIAL_XIRCOM tristate "USB Xircom / Entregra Single Port Serial Driver" - select USB_EZUSB + select USB_EZUSB_FX2 help Say Y here if you want to use a Xircom or Entregra single port USB to serial converter device. This driver makes use of firmware diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 45871f9..3b3e730 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -9,7 +9,6 @@ obj-$(CONFIG_USB_SERIAL) += usbserial.o usbserial-y := usb-serial.o generic.o bus.o usbserial-$(CONFIG_USB_SERIAL_CONSOLE) += console.o -usbserial-$(CONFIG_USB_EZUSB) += ezusb.o obj-$(CONFIG_USB_SERIAL_AIRCABLE) += aircable.o obj-$(CONFIG_USB_SERIAL_ARK3116) += ark3116.o diff --git a/drivers/usb/serial/ezusb.c b/drivers/usb/serial/ezusb.c deleted file mode 100644 index 4223d76..0000000 --- a/drivers/usb/serial/ezusb.c +++ /dev/null @@ -1,160 +0,0 @@ -/* - * EZ-USB specific functions used by some of the USB to Serial drivers. - * - * Copyright (C) 1999 - 2002 Greg Kroah-Hartman (greg@kroah.com) - * - * 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 -#include -#include -#include -#include -#include -#include - -struct ezusb_fx_type { - /* EZ-USB Control and Status Register. Bit 0 controls 8051 reset */ - unsigned short cpucs_reg; - unsigned short max_internal_adress; -}; - -struct ezusb_fx_type ezusb_fx1 = { - .cpucs_reg = 0x7F92, - .max_internal_adress = 0x1B3F, -}; - -struct ezusb_fx_type ezusb_fx2 = { - .cpucs_reg = 0xE600, - .max_internal_adress = 0x3FFF, -}; - -/* Commands for writing to memory */ -#define WRITE_INT_RAM 0xA0 -#define WRITE_EXT_RAM 0xA3 - -int ezusb_writememory(struct usb_device *dev, int address, - unsigned char *data, int length, __u8 request) -{ - int result; - unsigned char *transfer_buffer; - - if (!dev) - return -ENODEV; - - transfer_buffer = kmemdup(data, length, GFP_KERNEL); - if (!transfer_buffer) { - dev_err(&dev->dev, "%s - kmalloc(%d) failed.\n", - __func__, length); - return -ENOMEM; - } - result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), request, - USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, - address, 0, transfer_buffer, length, 3000); - - kfree(transfer_buffer); - return result; -} -EXPORT_SYMBOL_GPL(ezusb_writememory); - -int ezusb_set_reset(struct usb_device *dev, unsigned short cpucs_reg, - unsigned char reset_bit) -{ - int response = ezusb_writememory(dev, cpucs_reg, &reset_bit, 1, WRITE_INT_RAM); - if (response < 0) - dev_err(&dev->dev, "%s-%d failed: %d\n", - __func__, reset_bit, response); - return response; -} - -int ezusb_fx1_set_reset(struct usb_device *dev, unsigned char reset_bit) -{ - return ezusb_set_reset(dev, ezusb_fx1.cpucs_reg, reset_bit); -} -EXPORT_SYMBOL_GPL(ezusb_fx1_set_reset); - -int ezusb_fx2_set_reset(struct usb_device *dev, unsigned char reset_bit) -{ - return ezusb_set_reset(dev, ezusb_fx2.cpucs_reg, reset_bit); -} -EXPORT_SYMBOL_GPL(ezusb_fx2_set_reset); - -static int ezusb_ihex_firmware_download(struct usb_device *dev, - struct ezusb_fx_type fx, - const char *firmware_path) -{ - int ret = -ENOENT; - const struct firmware *firmware = NULL; - const struct ihex_binrec *record; - - if (request_ihex_firmware(&firmware, firmware_path, - &dev->dev)) { - dev_err(&dev->dev, - "%s - request \"%s\" failed\n", - __func__, firmware_path); - goto out; - } - - ret = ezusb_set_reset(dev, fx.cpucs_reg, 0); - if (ret < 0) - goto out; - - record = (const struct ihex_binrec *)firmware->data; - for (; record; record = ihex_next_binrec(record)) { - if (be32_to_cpu(record->addr) > fx.max_internal_adress) { - ret = ezusb_writememory(dev, be32_to_cpu(record->addr), - (unsigned char *)record->data, - be16_to_cpu(record->len), WRITE_EXT_RAM); - if (ret < 0) { - dev_err(&dev->dev, "%s - ezusb_writememory " - "failed writing internal memory " - "(%d %04X %p %d)\n", __func__, ret, - be32_to_cpu(record->addr), record->data, - be16_to_cpu(record->len)); - goto out; - } - } - } - - ret = ezusb_set_reset(dev, fx.cpucs_reg, 1); - if (ret < 0) - goto out; - record = (const struct ihex_binrec *)firmware->data; - for (; record; record = ihex_next_binrec(record)) { - if (be32_to_cpu(record->addr) <= fx.max_internal_adress) { - ret = ezusb_writememory(dev, be32_to_cpu(record->addr), - (unsigned char *)record->data, - be16_to_cpu(record->len), WRITE_INT_RAM); - if (ret < 0) { - dev_err(&dev->dev, "%s - ezusb_writememory " - "failed writing external memory " - "(%d %04X %p %d)\n", __func__, ret, - be32_to_cpu(record->addr), record->data, - be16_to_cpu(record->len)); - goto out; - } - } - } - ret = ezusb_set_reset(dev, fx.cpucs_reg, 0); -out: - release_firmware(firmware); - return ret; -} - -int ezusb_fx1_ihex_firmware_download(struct usb_device *dev, - const char *firmware_path) -{ - return ezusb_ihex_firmware_download(dev, ezusb_fx1, firmware_path); -} -EXPORT_SYMBOL_GPL(ezusb_fx1_ihex_firmware_download); - -int ezusb_fx2_ihex_firmware_download(struct usb_device *dev, - const char *firmware_path) -{ - return ezusb_ihex_firmware_download(dev, ezusb_fx2, firmware_path); -} -EXPORT_SYMBOL_GPL(ezusb_fx2_ihex_firmware_download); - -- cgit v0.10.2