Re: [PATCH v2 03/10] pwm: imx: Rewrite imx_pwm_*_v1 code to facilitate switch to atomic pwm operation
Hi Sascha, > The current assumption as discussed by Philipp and me is that the ipg > clk is only needed when the pwm output is driven by the ipg clk > (MX3_PWMCR[16:17] = MX3_PWMCR_CLKSRC_IPG) At least on my setup (i.MX6q) the ipg clock (ipg_clk) don't need to be explicitly enabled in the ->apply() callback (in the pwm-imx.c) when MX3_PWMCR_CLKSRC_IPG (0x01 - ipg_clk) is selected as the PWM source. Best regards, Łukasz Majewski pgp5t_QIQmyKK.pgp Description: OpenPGP digital signature
Re: [PATCH v2 03/10] pwm: imx: Rewrite imx_pwm_*_v1 code to facilitate switch to atomic pwm operation
Hi Sascha, > The current assumption as discussed by Philipp and me is that the ipg > clk is only needed when the pwm output is driven by the ipg clk > (MX3_PWMCR[16:17] = MX3_PWMCR_CLKSRC_IPG) At least on my setup (i.MX6q) the ipg clock (ipg_clk) don't need to be explicitly enabled in the ->apply() callback (in the pwm-imx.c) when MX3_PWMCR_CLKSRC_IPG (0x01 - ipg_clk) is selected as the PWM source. Best regards, Łukasz Majewski pgp5t_QIQmyKK.pgp Description: OpenPGP digital signature
[PATCH v2] usb: dwc3: gadget: wait for End Transfer to complete
Instead of just delaying for 100us, we should actually wait for End Transfer Command Complete interrupt before moving on. Note that this should only be done if we're dealing with one of the core revisions that actually require the interrupt before moving on. [ felipe.ba...@linux.intel.com: minor improvements ] Signed-off-by: Baolin Wang--- Changes since v1: - Move the suspend checking to right place to avoid checking twice. --- drivers/usb/dwc3/core.h |8 drivers/usb/dwc3/gadget.c | 49 + 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 23765a1..c5fd862 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -496,6 +497,7 @@ struct dwc3_event_buffer { * @endpoint: usb endpoint * @pending_list: list of pending requests for this endpoint * @started_list: list of started requests on this endpoint + * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete * @lock: spinlock for endpoint request queue traversal * @regs: pointer to first endpoint register * @trb_pool: array of transaction buffers @@ -521,6 +523,8 @@ struct dwc3_ep { struct list_headpending_list; struct list_headstarted_list; + wait_queue_head_t wait_end_transfer; + spinlock_t lock; void __iomem*regs; @@ -537,6 +541,7 @@ struct dwc3_ep { #define DWC3_EP_BUSY (1 << 4) #define DWC3_EP_PENDING_REQUEST(1 << 5) #define DWC3_EP_MISSED_ISOC(1 << 6) +#define DWC3_EP_END_TRANSFER_PENDING (1 << 7) /* This last one is specific to EP0 */ #define DWC3_EP0_DIR_IN(1 << 31) @@ -1044,6 +1049,9 @@ struct dwc3_event_depevt { #define DEPEVT_TRANSFER_BUS_EXPIRY 2 u32 parameters:16; + +/* For Command Complete Events */ +#define DEPEVT_PARAMETER_CMD(n)(((n) & (0xf << 8)) >> 8) } __packed; /** diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 3722c90..e248bd3 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -570,11 +570,14 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, dep->comp_desc = comp_desc; dep->type = usb_endpoint_type(desc); dep->flags |= DWC3_EP_ENABLED; + dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING; reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); reg |= DWC3_DALEPENA_EP(dep->number); dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); + init_waitqueue_head(>wait_end_transfer); + if (usb_endpoint_xfer_control(desc)) return 0; @@ -647,7 +650,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) dep->endpoint.desc = NULL; dep->comp_desc = NULL; dep->type = 0; - dep->flags = 0; + dep->flags &= DWC3_EP_END_TRANSFER_PENDING; return 0; } @@ -1736,12 +1739,38 @@ static int dwc3_gadget_stop(struct usb_gadget *g) { struct dwc3 *dwc = gadget_to_dwc(g); unsigned long flags; + int epnum; spin_lock_irqsave(>lock, flags); __dwc3_gadget_stop(dwc); dwc->gadget_driver = NULL; + + /* +* If the dwc3 core has been in suspend state, we will never get +* the command complete event, thus ignore. +*/ + if (pm_runtime_suspended(dwc->dev)) { + spin_unlock_irqrestore(>lock, flags); + goto out; + } + + for (epnum = 2; epnum < DWC3_ENDPOINTS_NUM; epnum++) { + struct dwc3_ep *dep = dwc->eps[epnum]; + + if (!dep) + continue; + + if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) + continue; + + wait_event_lock_irq(dep->wait_end_transfer, + !(dep->flags & DWC3_EP_END_TRANSFER_PENDING), + dwc->lock); + } + spin_unlock_irqrestore(>lock, flags); +out: free_irq(dwc->irq_gadget, dwc->ev_buf); return 0; @@ -2105,10 +2134,12 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, { struct dwc3_ep *dep; u8 epnum = event->endpoint_number; + u8 cmd; dep = dwc->eps[epnum]; - if (!(dep->flags & DWC3_EP_ENABLED)) + if (!(dep->flags & DWC3_EP_ENABLED) && + !(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) return; if (epnum == 0 || epnum == 1) { @@ -2180,6 +2211,13 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, dwc3_trace(trace_dwc3_gadget, "%s FIFO Overrun",
[PATCH v2] usb: dwc3: gadget: wait for End Transfer to complete
Instead of just delaying for 100us, we should actually wait for End Transfer Command Complete interrupt before moving on. Note that this should only be done if we're dealing with one of the core revisions that actually require the interrupt before moving on. [ felipe.ba...@linux.intel.com: minor improvements ] Signed-off-by: Baolin Wang --- Changes since v1: - Move the suspend checking to right place to avoid checking twice. --- drivers/usb/dwc3/core.h |8 drivers/usb/dwc3/gadget.c | 49 + 2 files changed, 53 insertions(+), 4 deletions(-) diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h index 23765a1..c5fd862 100644 --- a/drivers/usb/dwc3/core.h +++ b/drivers/usb/dwc3/core.h @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -496,6 +497,7 @@ struct dwc3_event_buffer { * @endpoint: usb endpoint * @pending_list: list of pending requests for this endpoint * @started_list: list of started requests on this endpoint + * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete * @lock: spinlock for endpoint request queue traversal * @regs: pointer to first endpoint register * @trb_pool: array of transaction buffers @@ -521,6 +523,8 @@ struct dwc3_ep { struct list_headpending_list; struct list_headstarted_list; + wait_queue_head_t wait_end_transfer; + spinlock_t lock; void __iomem*regs; @@ -537,6 +541,7 @@ struct dwc3_ep { #define DWC3_EP_BUSY (1 << 4) #define DWC3_EP_PENDING_REQUEST(1 << 5) #define DWC3_EP_MISSED_ISOC(1 << 6) +#define DWC3_EP_END_TRANSFER_PENDING (1 << 7) /* This last one is specific to EP0 */ #define DWC3_EP0_DIR_IN(1 << 31) @@ -1044,6 +1049,9 @@ struct dwc3_event_depevt { #define DEPEVT_TRANSFER_BUS_EXPIRY 2 u32 parameters:16; + +/* For Command Complete Events */ +#define DEPEVT_PARAMETER_CMD(n)(((n) & (0xf << 8)) >> 8) } __packed; /** diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 3722c90..e248bd3 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -570,11 +570,14 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, dep->comp_desc = comp_desc; dep->type = usb_endpoint_type(desc); dep->flags |= DWC3_EP_ENABLED; + dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING; reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); reg |= DWC3_DALEPENA_EP(dep->number); dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); + init_waitqueue_head(>wait_end_transfer); + if (usb_endpoint_xfer_control(desc)) return 0; @@ -647,7 +650,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) dep->endpoint.desc = NULL; dep->comp_desc = NULL; dep->type = 0; - dep->flags = 0; + dep->flags &= DWC3_EP_END_TRANSFER_PENDING; return 0; } @@ -1736,12 +1739,38 @@ static int dwc3_gadget_stop(struct usb_gadget *g) { struct dwc3 *dwc = gadget_to_dwc(g); unsigned long flags; + int epnum; spin_lock_irqsave(>lock, flags); __dwc3_gadget_stop(dwc); dwc->gadget_driver = NULL; + + /* +* If the dwc3 core has been in suspend state, we will never get +* the command complete event, thus ignore. +*/ + if (pm_runtime_suspended(dwc->dev)) { + spin_unlock_irqrestore(>lock, flags); + goto out; + } + + for (epnum = 2; epnum < DWC3_ENDPOINTS_NUM; epnum++) { + struct dwc3_ep *dep = dwc->eps[epnum]; + + if (!dep) + continue; + + if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) + continue; + + wait_event_lock_irq(dep->wait_end_transfer, + !(dep->flags & DWC3_EP_END_TRANSFER_PENDING), + dwc->lock); + } + spin_unlock_irqrestore(>lock, flags); +out: free_irq(dwc->irq_gadget, dwc->ev_buf); return 0; @@ -2105,10 +2134,12 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, { struct dwc3_ep *dep; u8 epnum = event->endpoint_number; + u8 cmd; dep = dwc->eps[epnum]; - if (!(dep->flags & DWC3_EP_ENABLED)) + if (!(dep->flags & DWC3_EP_ENABLED) && + !(dep->flags & DWC3_EP_END_TRANSFER_PENDING)) return; if (epnum == 0 || epnum == 1) { @@ -2180,6 +2211,13 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, dwc3_trace(trace_dwc3_gadget, "%s FIFO Overrun", dep->name);
RE: Device or HBA level QD throttling creates randomness in sequetial workload
Jens- Replied inline. Omar - I tested your WIP repo and figure out System hangs only if I pass " scsi_mod.use_blk_mq=Y". Without this, your WIP branch works fine, but I am looking for scsi_mod.use_blk_mq=Y. Also below is snippet of blktrace. In case of higher per device QD, I see Requeue request in blktrace. 65,128 10 6268 2.432404509 18594 P N [fio] 65,128 10 6269 2.432405013 18594 U N [fio] 1 65,128 10 6270 2.432405143 18594 I WS 148800 + 8 [fio] 65,128 10 6271 2.432405740 18594 R WS 148800 + 8 [0] 65,128 10 6272 2.432409794 18594 Q WS 148808 + 8 [fio] 65,128 10 6273 2.432410234 18594 G WS 148808 + 8 [fio] 65,128 10 6274 2.432410424 18594 S WS 148808 + 8 [fio] 65,128 23 3626 2.432432595 16232 D WS 148800 + 8 [kworker/23:1H] 65,128 22 3279 2.432973482 0 C WS 147432 + 8 [0] 65,128 7 6126 2.433032637 18594 P N [fio] 65,128 7 6127 2.433033204 18594 U N [fio] 1 65,128 7 6128 2.433033346 18594 I WS 148808 + 8 [fio] 65,128 7 6129 2.433033871 18594 D WS 148808 + 8 [fio] 65,128 7 6130 2.433034559 18594 R WS 148808 + 8 [0] 65,128 7 6131 2.433039796 18594 Q WS 148816 + 8 [fio] 65,128 7 6132 2.433040206 18594 G WS 148816 + 8 [fio] 65,128 7 6133 2.433040351 18594 S WS 148816 + 8 [fio] 65,128 9 6392 2.433133729 0 C WS 147240 + 8 [0] 65,128 9 6393 2.433138166 905 D WS 148808 + 8 [kworker/9:1H] 65,128 7 6134 2.433167450 18594 P N [fio] 65,128 7 6135 2.433167911 18594 U N [fio] 1 65,128 7 6136 2.433168074 18594 I WS 148816 + 8 [fio] 65,128 7 6137 2.433168492 18594 D WS 148816 + 8 [fio] 65,128 7 6138 2.433174016 18594 Q WS 148824 + 8 [fio] 65,128 7 6139 2.433174282 18594 G WS 148824 + 8 [fio] 65,128 7 6140 2.433174613 18594 S WS 148824 + 8 [fio] CPU0 (sdy): Reads Queued: 0,0KiB Writes Queued: 79, 316KiB Read Dispatches:0,0KiB Write Dispatches: 67, 18,446,744,073PiB Reads Requeued: 0 Writes Requeued:86 Reads Completed:0,0KiB Writes Completed: 98, 392KiB Read Merges:0,0KiB Write Merges:0, 0KiB Read depth: 0 Write depth: 5 IO unplugs:79 Timer unplugs: 0 ` Kashyap > -Original Message- > From: Jens Axboe [mailto:ax...@kernel.dk] > Sent: Monday, October 31, 2016 10:54 PM > To: Kashyap Desai; Omar Sandoval > Cc: linux-s...@vger.kernel.org; linux-kernel@vger.kernel.org; linux- > bl...@vger.kernel.org; Christoph Hellwig; paolo.vale...@linaro.org > Subject: Re: Device or HBA level QD throttling creates randomness in > sequetial > workload > > Hi, > > One guess would be that this isn't around a requeue condition, but rather > the > fact that we don't really guarantee any sort of hard FIFO behavior between > the > software queues. Can you try this test patch to see if it changes the > behavior for > you? Warning: untested... Jens - I tested the patch, but I still see random IO pattern for expected Sequential Run. I am intentionally running case of Re-queue and seeing issue at the time of Re-queue. If there is no Requeue, I see no issue at LLD. > > diff --git a/block/blk-mq.c b/block/blk-mq.c index > f3d27a6dee09..5404ca9c71b2 > 100644 > --- a/block/blk-mq.c > +++ b/block/blk-mq.c > @@ -772,6 +772,14 @@ static inline unsigned int queued_to_index(unsigned > int > queued) > return min(BLK_MQ_MAX_DISPATCH_ORDER - 1, ilog2(queued) + 1); > } > > +static int rq_pos_cmp(void *priv, struct list_head *a, struct list_head > +*b) { > + struct request *rqa = container_of(a, struct request, queuelist); > + struct request *rqb = container_of(b, struct request, queuelist); > + > + return blk_rq_pos(rqa) < blk_rq_pos(rqb); } > + > /* >* Run this hardware queue, pulling any software queues mapped to it in. >* Note that this function currently has various problems around > ordering @@ - > 812,6 +820,14 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx > *hctx) > } > > /* > + * If the device is rotational, sort the list sanely to avoid > + * unecessary seeks. The software queues are roughly FIFO, but > + * only roughly, there are no hard guarantees. > + */ > + if (!blk_queue_nonrot(q)) > + list_sort(NULL, _list, rq_pos_cmp); > + > + /* >* Start off with dptr being NULL, so we start the first request >* immediately, even if we have more pending. >*/ > > -- > Jens Axboe
RE: Device or HBA level QD throttling creates randomness in sequetial workload
Jens- Replied inline. Omar - I tested your WIP repo and figure out System hangs only if I pass " scsi_mod.use_blk_mq=Y". Without this, your WIP branch works fine, but I am looking for scsi_mod.use_blk_mq=Y. Also below is snippet of blktrace. In case of higher per device QD, I see Requeue request in blktrace. 65,128 10 6268 2.432404509 18594 P N [fio] 65,128 10 6269 2.432405013 18594 U N [fio] 1 65,128 10 6270 2.432405143 18594 I WS 148800 + 8 [fio] 65,128 10 6271 2.432405740 18594 R WS 148800 + 8 [0] 65,128 10 6272 2.432409794 18594 Q WS 148808 + 8 [fio] 65,128 10 6273 2.432410234 18594 G WS 148808 + 8 [fio] 65,128 10 6274 2.432410424 18594 S WS 148808 + 8 [fio] 65,128 23 3626 2.432432595 16232 D WS 148800 + 8 [kworker/23:1H] 65,128 22 3279 2.432973482 0 C WS 147432 + 8 [0] 65,128 7 6126 2.433032637 18594 P N [fio] 65,128 7 6127 2.433033204 18594 U N [fio] 1 65,128 7 6128 2.433033346 18594 I WS 148808 + 8 [fio] 65,128 7 6129 2.433033871 18594 D WS 148808 + 8 [fio] 65,128 7 6130 2.433034559 18594 R WS 148808 + 8 [0] 65,128 7 6131 2.433039796 18594 Q WS 148816 + 8 [fio] 65,128 7 6132 2.433040206 18594 G WS 148816 + 8 [fio] 65,128 7 6133 2.433040351 18594 S WS 148816 + 8 [fio] 65,128 9 6392 2.433133729 0 C WS 147240 + 8 [0] 65,128 9 6393 2.433138166 905 D WS 148808 + 8 [kworker/9:1H] 65,128 7 6134 2.433167450 18594 P N [fio] 65,128 7 6135 2.433167911 18594 U N [fio] 1 65,128 7 6136 2.433168074 18594 I WS 148816 + 8 [fio] 65,128 7 6137 2.433168492 18594 D WS 148816 + 8 [fio] 65,128 7 6138 2.433174016 18594 Q WS 148824 + 8 [fio] 65,128 7 6139 2.433174282 18594 G WS 148824 + 8 [fio] 65,128 7 6140 2.433174613 18594 S WS 148824 + 8 [fio] CPU0 (sdy): Reads Queued: 0,0KiB Writes Queued: 79, 316KiB Read Dispatches:0,0KiB Write Dispatches: 67, 18,446,744,073PiB Reads Requeued: 0 Writes Requeued:86 Reads Completed:0,0KiB Writes Completed: 98, 392KiB Read Merges:0,0KiB Write Merges:0, 0KiB Read depth: 0 Write depth: 5 IO unplugs:79 Timer unplugs: 0 ` Kashyap > -Original Message- > From: Jens Axboe [mailto:ax...@kernel.dk] > Sent: Monday, October 31, 2016 10:54 PM > To: Kashyap Desai; Omar Sandoval > Cc: linux-s...@vger.kernel.org; linux-kernel@vger.kernel.org; linux- > bl...@vger.kernel.org; Christoph Hellwig; paolo.vale...@linaro.org > Subject: Re: Device or HBA level QD throttling creates randomness in > sequetial > workload > > Hi, > > One guess would be that this isn't around a requeue condition, but rather > the > fact that we don't really guarantee any sort of hard FIFO behavior between > the > software queues. Can you try this test patch to see if it changes the > behavior for > you? Warning: untested... Jens - I tested the patch, but I still see random IO pattern for expected Sequential Run. I am intentionally running case of Re-queue and seeing issue at the time of Re-queue. If there is no Requeue, I see no issue at LLD. > > diff --git a/block/blk-mq.c b/block/blk-mq.c index > f3d27a6dee09..5404ca9c71b2 > 100644 > --- a/block/blk-mq.c > +++ b/block/blk-mq.c > @@ -772,6 +772,14 @@ static inline unsigned int queued_to_index(unsigned > int > queued) > return min(BLK_MQ_MAX_DISPATCH_ORDER - 1, ilog2(queued) + 1); > } > > +static int rq_pos_cmp(void *priv, struct list_head *a, struct list_head > +*b) { > + struct request *rqa = container_of(a, struct request, queuelist); > + struct request *rqb = container_of(b, struct request, queuelist); > + > + return blk_rq_pos(rqa) < blk_rq_pos(rqb); } > + > /* >* Run this hardware queue, pulling any software queues mapped to it in. >* Note that this function currently has various problems around > ordering @@ - > 812,6 +820,14 @@ static void __blk_mq_run_hw_queue(struct blk_mq_hw_ctx > *hctx) > } > > /* > + * If the device is rotational, sort the list sanely to avoid > + * unecessary seeks. The software queues are roughly FIFO, but > + * only roughly, there are no hard guarantees. > + */ > + if (!blk_queue_nonrot(q)) > + list_sort(NULL, _list, rq_pos_cmp); > + > + /* >* Start off with dptr being NULL, so we start the first request >* immediately, even if we have more pending. >*/ > > -- > Jens Axboe
Re: [PATCH] kexec: Export memory sections virtual addresses to vmcoreinfo
On 11/01/16 at 01:10pm, Dave Young wrote: > On 10/06/16 at 04:46pm, Baoquan He wrote: > > KASLR memory randomization can randomize the base of the physical memory > > mapping (PAGE_OFFSET), vmalloc (VMALLOC_START) and vmemmap > > (VMEMMAP_START). These need be exported to VMCOREINFO so that user space > > utility, mainly makedumpfile can use them to identify the base of each > > memory section. Here using VMCOREINFO_NUMBER we can reuse the existing > > struct number_table in makedumpfile to import data easily. > > > > Since they are related to x86_64 only, put them into > > arch_crash_save_vmcoreinfo. And move the exportion of KERNEL_IMAGE_SIZE > > together since it's also for x86_64 only. > > > > Signed-off-by: Baoquan He> > --- > > arch/x86/kernel/machine_kexec_64.c | 4 > > kernel/kexec_core.c| 3 --- > > 2 files changed, 4 insertions(+), 3 deletions(-) > > > > diff --git a/arch/x86/kernel/machine_kexec_64.c > > b/arch/x86/kernel/machine_kexec_64.c > > index 5a294e4..e150dd7 100644 > > --- a/arch/x86/kernel/machine_kexec_64.c > > +++ b/arch/x86/kernel/machine_kexec_64.c > > @@ -337,6 +337,10 @@ void arch_crash_save_vmcoreinfo(void) > > #endif > > vmcoreinfo_append_str("KERNELOFFSET=%lx\n", > > kaslr_offset()); > > + VMCOREINFO_NUMBER(KERNEL_IMAGE_SIZE); > > + VMCOREINFO_NUMBER(PAGE_OFFSET); > > + VMCOREINFO_NUMBER(VMALLOC_START); > > + VMCOREINFO_NUMBER(VMEMMAP_START); > > Pratyush has posted makedumpfile patches below to avoid the VMCOREINFO: > http://lists.infradead.org/pipermail/kexec/2016-October/017540.html > > But we have this in mainline which also introduced the VMCOREINFO > numbers, can you send a patch to revert them? OK, will do. However for find_vmemmap_x86_64() in makedumpfile, vmemmap_start is still needed. I checked code, seems no better way to avoid. I am not sure how many people are really using "-e" option to exclude unused vmemmap pages. Maybe just leave it as is, and fix it when people complain? > commit 0549a3c02efb350776bc869685a361045efd3a29 > Author: Thomas Garnier > Date: Tue Oct 11 13:55:08 2016 -0700 > > kdump, vmcoreinfo: report memory sections virtual addresses > [snip]] > > > } > > > > /* arch-dependent functionality related to kexec file-based syscall */ > > diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c > > index 5616755..8ad3a29e 100644 > > --- a/kernel/kexec_core.c > > +++ b/kernel/kexec_core.c > > @@ -1467,9 +1467,6 @@ static int __init crash_save_vmcoreinfo_init(void) > > #endif > > VMCOREINFO_NUMBER(PG_head_mask); > > VMCOREINFO_NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE); > > -#ifdef CONFIG_X86 > > - VMCOREINFO_NUMBER(KERNEL_IMAGE_SIZE); > > -#endif > > Moving KERNEL_IMAGE_SIZE to x86 should be a standalone patch. > I remember Dave Anderson said he use it in crash utility, cced him. > > > #ifdef CONFIG_HUGETLB_PAGE > > VMCOREINFO_NUMBER(HUGETLB_PAGE_DTOR); > > #endif > > -- > > 2.5.5 > > > > > > ___ > > kexec mailing list > > ke...@lists.infradead.org > > http://lists.infradead.org/mailman/listinfo/kexec > > Thanks > Dave
S5PV210 boot problem
Dear friends, I have problem booting my custom HW (around s5pv210 SoC) using the latest stable kernel release (v4.8.5). Of course this is the first DT based kernel I'm trying to boot with in this HW. I chose s5pv210_defconfig and by checking CONFIG_ARM_APPENDED_DTB, appended the DTB (s5pv210-smdkv210.dtb) at the end of zImage. The boot loader is based on the old u-boot v1.3.4. Due to some problems with kernel decompression, I revert 1fdc08abfa26f30fcef0ce1333e9ac6f80350f30 ARM: decompressor: avoid speculative prefetch from non-RAM areas for a successful boot on every new kernel and it worked till now (for non-DT kernels) Boot log messages is attached. There are some problems with clock settings and obviously "Division by zero in kernel". Can anybody shed some light on the possible issue(s)? ## Transferring control to Linux (at address 20008000) ... Starting kernel ... Uncompressing Linux... done, booting the kernel. Booting Linux on physical CPU 0x0 Linux version 4.8.5-1-g0ab (smart@smart-ThinkPad-T410) (gcc version 4.7.3 (Ubuntu/Linaro 4.7.3-12ubuntu1) ) #5 PREEMPT Mon Oct 36 CPU: ARMv7 Processor [412fc082] revision 2 (ARMv7), cr=10c5387d CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache OF: fdt:Machine model: YIC System SMDKV210 based on S5PV210 debug: ignoring loglevel setting. bootconsole [earlycon0] enabled Memory policy: Data cache writeback On node 0 totalpages: 262144 free_area_init_node: node 0, pgdat 80517730, node_mem_map bf7f8000 Normal zone: 2048 pages used for memmap Normal zone: 0 pages reserved Normal zone: 262144 pages, LIFO batch:31 CPU: All CPU(s) started in SVC mode. pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768 pcpu-alloc: [0] 0 Built 1 zonelists in Zone order, mobility grouping on. Total pages: 260096 Kernel command line: console=ttySAC0,115200n8 root=/dev/mmcblk0p1 rw rootwait ignore_loglevel earlyprintk PID hash table entries: 4096 (order: 2, 16384 bytes) Dentry cache hash table entries: 131072 (order: 7, 524288 bytes) Inode-cache hash table entries: 65536 (order: 6, 262144 bytes) Memory: 1034972K/1048576K available (2048K kernel code, 95K rwdata, 700K rodata, 1024K init, 208K bss, 13604K reserved, 0K cma-reserved) Virtual kernel memory layout: vector : 0x - 0x1000 ( 4 kB) fixmap : 0xffc0 - 0xfff0 (3072 kB) vmalloc : 0xc080 - 0xff80 (1008 MB) lowmem : 0x8000 - 0xc000 (1024 MB) modules : 0x7f00 - 0x8000 ( 16 MB) .text : 0x80008000 - 0x8030 (3040 kB) .init : 0x8040 - 0x8050 (1024 kB) .data : 0x8050 - 0x80517e40 ( 96 kB) .bss : 0x80517e40 - 0x8054bfec ( 209 kB) SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 Preemptible hierarchical RCU implementation. Build-time adjustment of leaf fanout to 32. NR_IRQS:16 nr_irqs:16 16 VIC @c080: id 0x00041192, vendor 0x41 VIC @c0802000: id 0x00041192, vendor 0x41 VIC @c0804000: id 0x00041192, vendor 0x41 VIC @c0806000: id 0x00041192, vendor 0x41 S5PV210 clocks: mout_apll = 0, mout_mpll = 0 mout_epll = 0, mout_vpll = 0 Division by zero in kernel. CPU: 0 PID: 0 Comm: swapper Not tainted 4.8.5-1-g0ab #5 Hardware name: Samsung S5PC110/S5PV210-based board [<8010c1ac>] (unwind_backtrace) from [<8010a084>] (show_stack+0x10/0x14) [<8010a084>] (show_stack) from [<8024a07c>] (Ldiv0+0x8/0x14) [<8024a07c>] (Ldiv0) from [<8015c6f0>] (clockevents_config+0x24/0x7c) [<8015c6f0>] (clockevents_config) from [<8015c75c>] (clockevents_config_and_register+0x14/0x20) [<8015c75c>] (clockevents_config_and_register) from [<80416d6c>] (_samsung_pwm_clocksource_init+0x124/0x264) [<80416d6c>] (_samsung_pwm_clocksource_init) from [<80416fc4>] (samsung_pwm_alloc+0x118/0x13c) [<80416fc4>] (samsung_pwm_alloc) from [<80416be0>] (clocksource_probe+0x44/0xac) [<80416be0>] (clocksource_probe) from [<80400af0>] (start_kernel+0x224/0x388) [<80400af0>] (start_kernel) from [<20008078>] (0x20008078) [ cut here ] WARNING: CPU: 0 PID: 0 at kernel/time/clockevents.c:44 cev_delta2ns+0x130/0x14c Modules linked in: CPU: 0 PID: 0 Comm: swapper Not tainted 4.8.5-1-g0ab #5 Hardware name: Samsung S5PC110/S5PV210-based board [<8010c1ac>] (unwind_backtrace) from [<8010a084>] (show_stack+0x10/0x14) [<8010a084>] (show_stack) from [<801158f4>] (__warn+0xd4/0xfc) [<801158f4>] (__warn) from [<8011593c>] (warn_slowpath_null+0x20/0x28) [<8011593c>] (warn_slowpath_null) from [<8015bfec>] (cev_delta2ns+0x130/0x14c) [<8015bfec>] (cev_delta2ns) from [<8015c728>] (clockevents_config+0x5c/0x7c) [<8015c728>] (clockevents_config) from [<8015c75c>] (clockevents_config_and_register+0x14/0x20) [<8015c75c>] (clockevents_config_and_register) from [<80416d6c>] (_samsung_pwm_clocksource_init+0x124/0x264) [<80416d6c>] (_samsung_pwm_clocksource_init) from [<80416fc4>] (samsung_pwm_alloc+0x118/0x13c) [<80416fc4>] (samsung_pwm_alloc) from [<80416be0>]
Re: [PATCH] kexec: Export memory sections virtual addresses to vmcoreinfo
On 11/01/16 at 01:10pm, Dave Young wrote: > On 10/06/16 at 04:46pm, Baoquan He wrote: > > KASLR memory randomization can randomize the base of the physical memory > > mapping (PAGE_OFFSET), vmalloc (VMALLOC_START) and vmemmap > > (VMEMMAP_START). These need be exported to VMCOREINFO so that user space > > utility, mainly makedumpfile can use them to identify the base of each > > memory section. Here using VMCOREINFO_NUMBER we can reuse the existing > > struct number_table in makedumpfile to import data easily. > > > > Since they are related to x86_64 only, put them into > > arch_crash_save_vmcoreinfo. And move the exportion of KERNEL_IMAGE_SIZE > > together since it's also for x86_64 only. > > > > Signed-off-by: Baoquan He > > --- > > arch/x86/kernel/machine_kexec_64.c | 4 > > kernel/kexec_core.c| 3 --- > > 2 files changed, 4 insertions(+), 3 deletions(-) > > > > diff --git a/arch/x86/kernel/machine_kexec_64.c > > b/arch/x86/kernel/machine_kexec_64.c > > index 5a294e4..e150dd7 100644 > > --- a/arch/x86/kernel/machine_kexec_64.c > > +++ b/arch/x86/kernel/machine_kexec_64.c > > @@ -337,6 +337,10 @@ void arch_crash_save_vmcoreinfo(void) > > #endif > > vmcoreinfo_append_str("KERNELOFFSET=%lx\n", > > kaslr_offset()); > > + VMCOREINFO_NUMBER(KERNEL_IMAGE_SIZE); > > + VMCOREINFO_NUMBER(PAGE_OFFSET); > > + VMCOREINFO_NUMBER(VMALLOC_START); > > + VMCOREINFO_NUMBER(VMEMMAP_START); > > Pratyush has posted makedumpfile patches below to avoid the VMCOREINFO: > http://lists.infradead.org/pipermail/kexec/2016-October/017540.html > > But we have this in mainline which also introduced the VMCOREINFO > numbers, can you send a patch to revert them? OK, will do. However for find_vmemmap_x86_64() in makedumpfile, vmemmap_start is still needed. I checked code, seems no better way to avoid. I am not sure how many people are really using "-e" option to exclude unused vmemmap pages. Maybe just leave it as is, and fix it when people complain? > commit 0549a3c02efb350776bc869685a361045efd3a29 > Author: Thomas Garnier > Date: Tue Oct 11 13:55:08 2016 -0700 > > kdump, vmcoreinfo: report memory sections virtual addresses > [snip]] > > > } > > > > /* arch-dependent functionality related to kexec file-based syscall */ > > diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c > > index 5616755..8ad3a29e 100644 > > --- a/kernel/kexec_core.c > > +++ b/kernel/kexec_core.c > > @@ -1467,9 +1467,6 @@ static int __init crash_save_vmcoreinfo_init(void) > > #endif > > VMCOREINFO_NUMBER(PG_head_mask); > > VMCOREINFO_NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE); > > -#ifdef CONFIG_X86 > > - VMCOREINFO_NUMBER(KERNEL_IMAGE_SIZE); > > -#endif > > Moving KERNEL_IMAGE_SIZE to x86 should be a standalone patch. > I remember Dave Anderson said he use it in crash utility, cced him. > > > #ifdef CONFIG_HUGETLB_PAGE > > VMCOREINFO_NUMBER(HUGETLB_PAGE_DTOR); > > #endif > > -- > > 2.5.5 > > > > > > ___ > > kexec mailing list > > ke...@lists.infradead.org > > http://lists.infradead.org/mailman/listinfo/kexec > > Thanks > Dave
S5PV210 boot problem
Dear friends, I have problem booting my custom HW (around s5pv210 SoC) using the latest stable kernel release (v4.8.5). Of course this is the first DT based kernel I'm trying to boot with in this HW. I chose s5pv210_defconfig and by checking CONFIG_ARM_APPENDED_DTB, appended the DTB (s5pv210-smdkv210.dtb) at the end of zImage. The boot loader is based on the old u-boot v1.3.4. Due to some problems with kernel decompression, I revert 1fdc08abfa26f30fcef0ce1333e9ac6f80350f30 ARM: decompressor: avoid speculative prefetch from non-RAM areas for a successful boot on every new kernel and it worked till now (for non-DT kernels) Boot log messages is attached. There are some problems with clock settings and obviously "Division by zero in kernel". Can anybody shed some light on the possible issue(s)? ## Transferring control to Linux (at address 20008000) ... Starting kernel ... Uncompressing Linux... done, booting the kernel. Booting Linux on physical CPU 0x0 Linux version 4.8.5-1-g0ab (smart@smart-ThinkPad-T410) (gcc version 4.7.3 (Ubuntu/Linaro 4.7.3-12ubuntu1) ) #5 PREEMPT Mon Oct 36 CPU: ARMv7 Processor [412fc082] revision 2 (ARMv7), cr=10c5387d CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing instruction cache OF: fdt:Machine model: YIC System SMDKV210 based on S5PV210 debug: ignoring loglevel setting. bootconsole [earlycon0] enabled Memory policy: Data cache writeback On node 0 totalpages: 262144 free_area_init_node: node 0, pgdat 80517730, node_mem_map bf7f8000 Normal zone: 2048 pages used for memmap Normal zone: 0 pages reserved Normal zone: 262144 pages, LIFO batch:31 CPU: All CPU(s) started in SVC mode. pcpu-alloc: s0 r0 d32768 u32768 alloc=1*32768 pcpu-alloc: [0] 0 Built 1 zonelists in Zone order, mobility grouping on. Total pages: 260096 Kernel command line: console=ttySAC0,115200n8 root=/dev/mmcblk0p1 rw rootwait ignore_loglevel earlyprintk PID hash table entries: 4096 (order: 2, 16384 bytes) Dentry cache hash table entries: 131072 (order: 7, 524288 bytes) Inode-cache hash table entries: 65536 (order: 6, 262144 bytes) Memory: 1034972K/1048576K available (2048K kernel code, 95K rwdata, 700K rodata, 1024K init, 208K bss, 13604K reserved, 0K cma-reserved) Virtual kernel memory layout: vector : 0x - 0x1000 ( 4 kB) fixmap : 0xffc0 - 0xfff0 (3072 kB) vmalloc : 0xc080 - 0xff80 (1008 MB) lowmem : 0x8000 - 0xc000 (1024 MB) modules : 0x7f00 - 0x8000 ( 16 MB) .text : 0x80008000 - 0x8030 (3040 kB) .init : 0x8040 - 0x8050 (1024 kB) .data : 0x8050 - 0x80517e40 ( 96 kB) .bss : 0x80517e40 - 0x8054bfec ( 209 kB) SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 Preemptible hierarchical RCU implementation. Build-time adjustment of leaf fanout to 32. NR_IRQS:16 nr_irqs:16 16 VIC @c080: id 0x00041192, vendor 0x41 VIC @c0802000: id 0x00041192, vendor 0x41 VIC @c0804000: id 0x00041192, vendor 0x41 VIC @c0806000: id 0x00041192, vendor 0x41 S5PV210 clocks: mout_apll = 0, mout_mpll = 0 mout_epll = 0, mout_vpll = 0 Division by zero in kernel. CPU: 0 PID: 0 Comm: swapper Not tainted 4.8.5-1-g0ab #5 Hardware name: Samsung S5PC110/S5PV210-based board [<8010c1ac>] (unwind_backtrace) from [<8010a084>] (show_stack+0x10/0x14) [<8010a084>] (show_stack) from [<8024a07c>] (Ldiv0+0x8/0x14) [<8024a07c>] (Ldiv0) from [<8015c6f0>] (clockevents_config+0x24/0x7c) [<8015c6f0>] (clockevents_config) from [<8015c75c>] (clockevents_config_and_register+0x14/0x20) [<8015c75c>] (clockevents_config_and_register) from [<80416d6c>] (_samsung_pwm_clocksource_init+0x124/0x264) [<80416d6c>] (_samsung_pwm_clocksource_init) from [<80416fc4>] (samsung_pwm_alloc+0x118/0x13c) [<80416fc4>] (samsung_pwm_alloc) from [<80416be0>] (clocksource_probe+0x44/0xac) [<80416be0>] (clocksource_probe) from [<80400af0>] (start_kernel+0x224/0x388) [<80400af0>] (start_kernel) from [<20008078>] (0x20008078) [ cut here ] WARNING: CPU: 0 PID: 0 at kernel/time/clockevents.c:44 cev_delta2ns+0x130/0x14c Modules linked in: CPU: 0 PID: 0 Comm: swapper Not tainted 4.8.5-1-g0ab #5 Hardware name: Samsung S5PC110/S5PV210-based board [<8010c1ac>] (unwind_backtrace) from [<8010a084>] (show_stack+0x10/0x14) [<8010a084>] (show_stack) from [<801158f4>] (__warn+0xd4/0xfc) [<801158f4>] (__warn) from [<8011593c>] (warn_slowpath_null+0x20/0x28) [<8011593c>] (warn_slowpath_null) from [<8015bfec>] (cev_delta2ns+0x130/0x14c) [<8015bfec>] (cev_delta2ns) from [<8015c728>] (clockevents_config+0x5c/0x7c) [<8015c728>] (clockevents_config) from [<8015c75c>] (clockevents_config_and_register+0x14/0x20) [<8015c75c>] (clockevents_config_and_register) from [<80416d6c>] (_samsung_pwm_clocksource_init+0x124/0x264) [<80416d6c>] (_samsung_pwm_clocksource_init) from [<80416fc4>] (samsung_pwm_alloc+0x118/0x13c) [<80416fc4>] (samsung_pwm_alloc) from [<80416be0>]
Re: [PATCH v10 01/19] vfio: Mediated device Core driver
On 11/01/2016 11:44 AM, Alex Williamson wrote: > On Tue, 01 Nov 2016 11:08:15 +0800 > Jike Songwrote: >> On 10/27/2016 05:29 AM, Kirti Wankhede wrote: >>> +static int mdev_attach_iommu(struct mdev_device *mdev) >>> +{ >>> + int ret; >>> + struct iommu_group *group; >>> + >>> + group = iommu_group_alloc(); >>> + if (IS_ERR(group)) >>> + return PTR_ERR(group); >> >> Maybe I overthought, but where the iommu_group is released? On successful >> return you already have a ref, I didn't find an iommu_group_put after that. > ... >>> + >>> + ret = iommu_group_add_device(group, >dev); >>> + if (ret) >>> + goto attach_fail; >>> + >>> + dev_info(>dev, "MDEV: group_id = %d\n", >>> +iommu_group_id(group)); >>> +attach_fail: >>> + iommu_group_put(group); >>> + return ret; >>> +} >>> + >>> +static void mdev_detach_iommu(struct mdev_device *mdev) >>> +{ >>> + iommu_group_remove_device(>dev); > > Here. Adding a device to the group takes a group reference so we can > 'put' the group to release the reference from the alloc as soon as a > device is added. When we remove the device, that reference is removed > and this should result in a release of the group if all other > references are balanced. Thanks, Now I understand, thanks :) -- Thanks, Jike
Re: [PATCH v10 01/19] vfio: Mediated device Core driver
On 11/01/2016 11:44 AM, Alex Williamson wrote: > On Tue, 01 Nov 2016 11:08:15 +0800 > Jike Song wrote: >> On 10/27/2016 05:29 AM, Kirti Wankhede wrote: >>> +static int mdev_attach_iommu(struct mdev_device *mdev) >>> +{ >>> + int ret; >>> + struct iommu_group *group; >>> + >>> + group = iommu_group_alloc(); >>> + if (IS_ERR(group)) >>> + return PTR_ERR(group); >> >> Maybe I overthought, but where the iommu_group is released? On successful >> return you already have a ref, I didn't find an iommu_group_put after that. > ... >>> + >>> + ret = iommu_group_add_device(group, >dev); >>> + if (ret) >>> + goto attach_fail; >>> + >>> + dev_info(>dev, "MDEV: group_id = %d\n", >>> +iommu_group_id(group)); >>> +attach_fail: >>> + iommu_group_put(group); >>> + return ret; >>> +} >>> + >>> +static void mdev_detach_iommu(struct mdev_device *mdev) >>> +{ >>> + iommu_group_remove_device(>dev); > > Here. Adding a device to the group takes a group reference so we can > 'put' the group to release the reference from the alloc as soon as a > device is added. When we remove the device, that reference is removed > and this should result in a release of the group if all other > references are balanced. Thanks, Now I understand, thanks :) -- Thanks, Jike
Re: pull-request: wireless-drivers-next 2016-10-30
David Millerwrites: > From: Kalle Valo > Date: Sun, 30 Oct 2016 11:20:46 +0200 > >> few fixes for 4.9. I tagged this on the plane over a slow mosh >> connection while travelling to Plumbers so I might have done something >> wrong, please check more carefully than usually. For example I had to >> redo the signed tag because of some whitespace damage. >> >> Please let me know if there are any problems. > > Your subject line says "-next" but clearly these are bug fixes for 'net' > so that's where I pulled this into. Correct, that -next was a mistake. Sorry about that. -- Kalle Valo
Re: pull-request: wireless-drivers-next 2016-10-30
David Miller writes: > From: Kalle Valo > Date: Sun, 30 Oct 2016 11:20:46 +0200 > >> few fixes for 4.9. I tagged this on the plane over a slow mosh >> connection while travelling to Plumbers so I might have done something >> wrong, please check more carefully than usually. For example I had to >> redo the signed tag because of some whitespace damage. >> >> Please let me know if there are any problems. > > Your subject line says "-next" but clearly these are bug fixes for 'net' > so that's where I pulled this into. Correct, that -next was a mistake. Sorry about that. -- Kalle Valo
Re: [PATCH v2 2/2] PM / sleep: don't suspend parent when async child suspend_{noirq,late} fails
Hi Rafael, On Tue, Nov 01, 2016 at 05:25:39AM +0100, Rafael J. Wysocki wrote: > On Thursday, October 27, 2016 09:05:34 AM Brian Norris wrote: > > diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c > > index c58563581345..eaf6b53463a5 100644 > > --- a/drivers/base/power/main.c > > +++ b/drivers/base/power/main.c > > @@ -1040,6 +1040,9 @@ static int __device_suspend_noirq(struct device *dev, > > pm_message_t state, bool a > > > > dpm_wait_for_children(dev, async); > > > > + if (async_error) > > + goto Complete; > > + > > This is a second chech for async_error in this routine and is the first one > really needed after adding this? Maybe not? I confess I'm not 100% sure on all the reasons for the code structure as-is, but it looks like we're trying to catch pending wakeups early, and because that procedure utilizes 'async_error' to stash the -EBUSY, it seemingly makes sense to check if it's non-zero before overwriting it. But then, that's all kind of racy, since there can be multiple writers to that variable, no? So it can't matter *that* much if we clobber the error, as long as we abort somewhere. Anyway, maybe it's best if dpm_wait_for_children() just moves to be first thing in this function (after the tracepoints). That seems just as correct to me, and shouldn't waste any additional time suspending devices for a failed system suspend attempt -- as long as we're still catching wakeups before we suspend the current device. (That also incidentally matches the structure of __device_suspend() more closely. Why did this all get out of sync (pun unintended) when copied from the suspend() to the suspend_{late,noirq}() phase?) All in all, the short response is that I wrote the smallest patch that fixes the bug, AFAICT. But actually I think the above would be both shorter and better. I'll give that a go. > > if (dev->pm_domain) { > > info = "noirq power domain "; > > callback = pm_noirq_op(>pm_domain->ops, state); > > @@ -1187,6 +1190,9 @@ static int __device_suspend_late(struct device *dev, > > pm_message_t state, bool as > > > > dpm_wait_for_children(dev, async); > > > > + if (async_error) > > + goto Complete; > > + > > Same question. Same answer :) Brian > > if (dev->pm_domain) { > > info = "late power domain "; > > callback = pm_late_early_op(>pm_domain->ops, state); > > > > Thanks, > Rafael >
Re: [PATCH v2 2/2] PM / sleep: don't suspend parent when async child suspend_{noirq,late} fails
Hi Rafael, On Tue, Nov 01, 2016 at 05:25:39AM +0100, Rafael J. Wysocki wrote: > On Thursday, October 27, 2016 09:05:34 AM Brian Norris wrote: > > diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c > > index c58563581345..eaf6b53463a5 100644 > > --- a/drivers/base/power/main.c > > +++ b/drivers/base/power/main.c > > @@ -1040,6 +1040,9 @@ static int __device_suspend_noirq(struct device *dev, > > pm_message_t state, bool a > > > > dpm_wait_for_children(dev, async); > > > > + if (async_error) > > + goto Complete; > > + > > This is a second chech for async_error in this routine and is the first one > really needed after adding this? Maybe not? I confess I'm not 100% sure on all the reasons for the code structure as-is, but it looks like we're trying to catch pending wakeups early, and because that procedure utilizes 'async_error' to stash the -EBUSY, it seemingly makes sense to check if it's non-zero before overwriting it. But then, that's all kind of racy, since there can be multiple writers to that variable, no? So it can't matter *that* much if we clobber the error, as long as we abort somewhere. Anyway, maybe it's best if dpm_wait_for_children() just moves to be first thing in this function (after the tracepoints). That seems just as correct to me, and shouldn't waste any additional time suspending devices for a failed system suspend attempt -- as long as we're still catching wakeups before we suspend the current device. (That also incidentally matches the structure of __device_suspend() more closely. Why did this all get out of sync (pun unintended) when copied from the suspend() to the suspend_{late,noirq}() phase?) All in all, the short response is that I wrote the smallest patch that fixes the bug, AFAICT. But actually I think the above would be both shorter and better. I'll give that a go. > > if (dev->pm_domain) { > > info = "noirq power domain "; > > callback = pm_noirq_op(>pm_domain->ops, state); > > @@ -1187,6 +1190,9 @@ static int __device_suspend_late(struct device *dev, > > pm_message_t state, bool as > > > > dpm_wait_for_children(dev, async); > > > > + if (async_error) > > + goto Complete; > > + > > Same question. Same answer :) Brian > > if (dev->pm_domain) { > > info = "late power domain "; > > callback = pm_late_early_op(>pm_domain->ops, state); > > > > Thanks, > Rafael >
Re: [PATCH] kexec: Export memory sections virtual addresses to vmcoreinfo
On 10/06/16 at 04:46pm, Baoquan He wrote: > KASLR memory randomization can randomize the base of the physical memory > mapping (PAGE_OFFSET), vmalloc (VMALLOC_START) and vmemmap > (VMEMMAP_START). These need be exported to VMCOREINFO so that user space > utility, mainly makedumpfile can use them to identify the base of each > memory section. Here using VMCOREINFO_NUMBER we can reuse the existing > struct number_table in makedumpfile to import data easily. > > Since they are related to x86_64 only, put them into > arch_crash_save_vmcoreinfo. And move the exportion of KERNEL_IMAGE_SIZE > together since it's also for x86_64 only. > > Signed-off-by: Baoquan He> --- > arch/x86/kernel/machine_kexec_64.c | 4 > kernel/kexec_core.c| 3 --- > 2 files changed, 4 insertions(+), 3 deletions(-) > > diff --git a/arch/x86/kernel/machine_kexec_64.c > b/arch/x86/kernel/machine_kexec_64.c > index 5a294e4..e150dd7 100644 > --- a/arch/x86/kernel/machine_kexec_64.c > +++ b/arch/x86/kernel/machine_kexec_64.c > @@ -337,6 +337,10 @@ void arch_crash_save_vmcoreinfo(void) > #endif > vmcoreinfo_append_str("KERNELOFFSET=%lx\n", > kaslr_offset()); > + VMCOREINFO_NUMBER(KERNEL_IMAGE_SIZE); > + VMCOREINFO_NUMBER(PAGE_OFFSET); > + VMCOREINFO_NUMBER(VMALLOC_START); > + VMCOREINFO_NUMBER(VMEMMAP_START); Pratyush has posted makedumpfile patches below to avoid the VMCOREINFO: http://lists.infradead.org/pipermail/kexec/2016-October/017540.html But we have this in mainline which also introduced the VMCOREINFO numbers, can you send a patch to revert them? commit 0549a3c02efb350776bc869685a361045efd3a29 Author: Thomas Garnier Date: Tue Oct 11 13:55:08 2016 -0700 kdump, vmcoreinfo: report memory sections virtual addresses [snip]] > } > > /* arch-dependent functionality related to kexec file-based syscall */ > diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c > index 5616755..8ad3a29e 100644 > --- a/kernel/kexec_core.c > +++ b/kernel/kexec_core.c > @@ -1467,9 +1467,6 @@ static int __init crash_save_vmcoreinfo_init(void) > #endif > VMCOREINFO_NUMBER(PG_head_mask); > VMCOREINFO_NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE); > -#ifdef CONFIG_X86 > - VMCOREINFO_NUMBER(KERNEL_IMAGE_SIZE); > -#endif Moving KERNEL_IMAGE_SIZE to x86 should be a standalone patch. I remember Dave Anderson said he use it in crash utility, cced him. > #ifdef CONFIG_HUGETLB_PAGE > VMCOREINFO_NUMBER(HUGETLB_PAGE_DTOR); > #endif > -- > 2.5.5 > > > ___ > kexec mailing list > ke...@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/kexec Thanks Dave
Re: [PATCH] kexec: Export memory sections virtual addresses to vmcoreinfo
On 10/06/16 at 04:46pm, Baoquan He wrote: > KASLR memory randomization can randomize the base of the physical memory > mapping (PAGE_OFFSET), vmalloc (VMALLOC_START) and vmemmap > (VMEMMAP_START). These need be exported to VMCOREINFO so that user space > utility, mainly makedumpfile can use them to identify the base of each > memory section. Here using VMCOREINFO_NUMBER we can reuse the existing > struct number_table in makedumpfile to import data easily. > > Since they are related to x86_64 only, put them into > arch_crash_save_vmcoreinfo. And move the exportion of KERNEL_IMAGE_SIZE > together since it's also for x86_64 only. > > Signed-off-by: Baoquan He > --- > arch/x86/kernel/machine_kexec_64.c | 4 > kernel/kexec_core.c| 3 --- > 2 files changed, 4 insertions(+), 3 deletions(-) > > diff --git a/arch/x86/kernel/machine_kexec_64.c > b/arch/x86/kernel/machine_kexec_64.c > index 5a294e4..e150dd7 100644 > --- a/arch/x86/kernel/machine_kexec_64.c > +++ b/arch/x86/kernel/machine_kexec_64.c > @@ -337,6 +337,10 @@ void arch_crash_save_vmcoreinfo(void) > #endif > vmcoreinfo_append_str("KERNELOFFSET=%lx\n", > kaslr_offset()); > + VMCOREINFO_NUMBER(KERNEL_IMAGE_SIZE); > + VMCOREINFO_NUMBER(PAGE_OFFSET); > + VMCOREINFO_NUMBER(VMALLOC_START); > + VMCOREINFO_NUMBER(VMEMMAP_START); Pratyush has posted makedumpfile patches below to avoid the VMCOREINFO: http://lists.infradead.org/pipermail/kexec/2016-October/017540.html But we have this in mainline which also introduced the VMCOREINFO numbers, can you send a patch to revert them? commit 0549a3c02efb350776bc869685a361045efd3a29 Author: Thomas Garnier Date: Tue Oct 11 13:55:08 2016 -0700 kdump, vmcoreinfo: report memory sections virtual addresses [snip]] > } > > /* arch-dependent functionality related to kexec file-based syscall */ > diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c > index 5616755..8ad3a29e 100644 > --- a/kernel/kexec_core.c > +++ b/kernel/kexec_core.c > @@ -1467,9 +1467,6 @@ static int __init crash_save_vmcoreinfo_init(void) > #endif > VMCOREINFO_NUMBER(PG_head_mask); > VMCOREINFO_NUMBER(PAGE_BUDDY_MAPCOUNT_VALUE); > -#ifdef CONFIG_X86 > - VMCOREINFO_NUMBER(KERNEL_IMAGE_SIZE); > -#endif Moving KERNEL_IMAGE_SIZE to x86 should be a standalone patch. I remember Dave Anderson said he use it in crash utility, cced him. > #ifdef CONFIG_HUGETLB_PAGE > VMCOREINFO_NUMBER(HUGETLB_PAGE_DTOR); > #endif > -- > 2.5.5 > > > ___ > kexec mailing list > ke...@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/kexec Thanks Dave
[PATCH 1/1] vmbus: make sysfs names consistent with PCI
From: Stephen HemmingerIn commit 9a56e5d6a0ba ("Drivers: hv: make VMBus bus ids persistent") the name of vmbus devices in sysfs changed to be (in 4.9-rc1): /sys/bus/vmbus/vmbus-6aebe374-9ba0-11e6-933c-00259086b36b The prefix ("vmbus-") is redundant and differs from how PCI is represented in sysfs. Therefore simplify to: /sys/bus/vmbus/6aebe374-9ba0-11e6-933c-00259086b36b Please merge this before 4.9 is released and the old format has to live forever. Signed-off-by: Stephen Hemminger Signed-off-by: K. Y. Srinivasan --- drivers/hv/vmbus_drv.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index a259e18..0276d2e 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -961,7 +961,7 @@ int vmbus_device_register(struct hv_device *child_device_obj) { int ret = 0; - dev_set_name(_device_obj->device, "vmbus-%pUl", + dev_set_name(_device_obj->device, "%pUl", child_device_obj->channel->offermsg.offer.if_instance.b); child_device_obj->device.bus = _bus; -- 1.7.4.1
[PATCH 1/1] vmbus: make sysfs names consistent with PCI
From: Stephen Hemminger In commit 9a56e5d6a0ba ("Drivers: hv: make VMBus bus ids persistent") the name of vmbus devices in sysfs changed to be (in 4.9-rc1): /sys/bus/vmbus/vmbus-6aebe374-9ba0-11e6-933c-00259086b36b The prefix ("vmbus-") is redundant and differs from how PCI is represented in sysfs. Therefore simplify to: /sys/bus/vmbus/6aebe374-9ba0-11e6-933c-00259086b36b Please merge this before 4.9 is released and the old format has to live forever. Signed-off-by: Stephen Hemminger Signed-off-by: K. Y. Srinivasan --- drivers/hv/vmbus_drv.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c index a259e18..0276d2e 100644 --- a/drivers/hv/vmbus_drv.c +++ b/drivers/hv/vmbus_drv.c @@ -961,7 +961,7 @@ int vmbus_device_register(struct hv_device *child_device_obj) { int ret = 0; - dev_set_name(_device_obj->device, "vmbus-%pUl", + dev_set_name(_device_obj->device, "%pUl", child_device_obj->channel->offermsg.offer.if_instance.b); child_device_obj->device.bus = _bus; -- 1.7.4.1
[PATCH v4 3/4] usb: serial: usb_debug: add support for dbc debug device
This patch add dbc debug device support in usb_debug driver. Signed-off-by: Lu BaoluAcked-by: Johan Hovold --- drivers/usb/serial/usb_debug.c | 28 +--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c index ca2fa5b..92f7e5c 100644 --- a/drivers/usb/serial/usb_debug.c +++ b/drivers/usb/serial/usb_debug.c @@ -32,7 +32,18 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x0525, 0x127a) }, { }, }; -MODULE_DEVICE_TABLE(usb, id_table); + +static const struct usb_device_id dbc_id_table[] = { + { USB_DEVICE(0x1d6b, 0x0004) }, + { }, +}; + +static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(0x0525, 0x127a) }, + { USB_DEVICE(0x1d6b, 0x0004) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table_combined); /* This HW really does not support a serial break, so one will be * emulated when ever the break state is set to true. @@ -71,9 +82,20 @@ static struct usb_serial_driver debug_device = { .process_read_urb = usb_debug_process_read_urb, }; +static struct usb_serial_driver dbc_device = { + .driver = { + .owner =THIS_MODULE, + .name = "xhci_dbc", + }, + .id_table = dbc_id_table, + .num_ports =1, + .break_ctl =usb_debug_break_ctl, + .process_read_urb = usb_debug_process_read_urb, +}; + static struct usb_serial_driver * const serial_drivers[] = { - _device, NULL + _device, _device, NULL }; -module_usb_serial_driver(serial_drivers, id_table); +module_usb_serial_driver(serial_drivers, id_table_combined); MODULE_LICENSE("GPL"); -- 2.1.4
[PATCH v4 3/4] usb: serial: usb_debug: add support for dbc debug device
This patch add dbc debug device support in usb_debug driver. Signed-off-by: Lu Baolu Acked-by: Johan Hovold --- drivers/usb/serial/usb_debug.c | 28 +--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/drivers/usb/serial/usb_debug.c b/drivers/usb/serial/usb_debug.c index ca2fa5b..92f7e5c 100644 --- a/drivers/usb/serial/usb_debug.c +++ b/drivers/usb/serial/usb_debug.c @@ -32,7 +32,18 @@ static const struct usb_device_id id_table[] = { { USB_DEVICE(0x0525, 0x127a) }, { }, }; -MODULE_DEVICE_TABLE(usb, id_table); + +static const struct usb_device_id dbc_id_table[] = { + { USB_DEVICE(0x1d6b, 0x0004) }, + { }, +}; + +static const struct usb_device_id id_table_combined[] = { + { USB_DEVICE(0x0525, 0x127a) }, + { USB_DEVICE(0x1d6b, 0x0004) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table_combined); /* This HW really does not support a serial break, so one will be * emulated when ever the break state is set to true. @@ -71,9 +82,20 @@ static struct usb_serial_driver debug_device = { .process_read_urb = usb_debug_process_read_urb, }; +static struct usb_serial_driver dbc_device = { + .driver = { + .owner =THIS_MODULE, + .name = "xhci_dbc", + }, + .id_table = dbc_id_table, + .num_ports =1, + .break_ctl =usb_debug_break_ctl, + .process_read_urb = usb_debug_process_read_urb, +}; + static struct usb_serial_driver * const serial_drivers[] = { - _device, NULL + _device, _device, NULL }; -module_usb_serial_driver(serial_drivers, id_table); +module_usb_serial_driver(serial_drivers, id_table_combined); MODULE_LICENSE("GPL"); -- 2.1.4
[PATCH v4 1/4] usb: dbc: early driver for xhci debug capability
xHCI debug capability (DbC) is an optional but standalone functionality provided by an xHCI host controller. Software learns this capability by walking through the extended capability list of the host. xHCI specification describes DbC in section 7.6. This patch introduces the code to probe and initialize the debug capability hardware during early boot. With hardware initialized, the debug target (system on which this code is running) will present a debug device through the debug port (normally the first USB3 port). The debug device is fully compliant with the USB framework and provides the equivalent of a very high performance (USB3) full-duplex serial link between the debug host and target. The DbC functionality is independent of xHCI host. There isn't any precondition from xHCI host side for DbC to work. This patch also includes bulk out and bulk in interfaces. These interfaces could be used to implement early printk bootconsole or hook to various system debuggers. This code is designed to be only used for kernel debugging when machine crashes very early before the console code is initialized. For normal operation it is not recommended. Cc: Mathias NymanSigned-off-by: Lu Baolu --- arch/x86/Kconfig.debug| 14 + drivers/usb/Kconfig |3 + drivers/usb/Makefile |2 +- drivers/usb/early/Makefile|1 + drivers/usb/early/xhci-dbc.c | 1050 + drivers/usb/early/xhci-dbc.h | 202 include/linux/usb/xhci-dbgp.h | 22 + 7 files changed, 1293 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/early/xhci-dbc.c create mode 100644 drivers/usb/early/xhci-dbc.h create mode 100644 include/linux/usb/xhci-dbgp.h diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 67eec55..13e85b7 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -29,6 +29,7 @@ config EARLY_PRINTK config EARLY_PRINTK_DBGP bool "Early printk via EHCI debug port" depends on EARLY_PRINTK && PCI + select USB_EARLY_PRINTK ---help--- Write kernel log output directly into the EHCI debug port. @@ -48,6 +49,19 @@ config EARLY_PRINTK_EFI This is useful for kernel debugging when your machine crashes very early before the console code is initialized. +config EARLY_PRINTK_XDBC + bool "Early printk via xHCI debug port" + depends on EARLY_PRINTK && PCI + select USB_EARLY_PRINTK + ---help--- + Write kernel log output directly into the xHCI debug port. + + This is useful for kernel debugging when your machine crashes very + early before the console code is initialized. For normal operation + it is not recommended because it looks ugly and doesn't cooperate + with klogd/syslogd or the X server. You should normally N here, + unless you want to debug such a crash. + config X86_PTDUMP_CORE def_bool n diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index fbe493d..9313fff 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -19,6 +19,9 @@ config USB_EHCI_BIG_ENDIAN_MMIO config USB_EHCI_BIG_ENDIAN_DESC bool +config USB_EARLY_PRINTK + bool + menuconfig USB_SUPPORT bool "USB support" depends on HAS_IOMEM diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 7791af6..0c37838 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -49,7 +49,7 @@ obj-$(CONFIG_USB_MICROTEK)+= image/ obj-$(CONFIG_USB_SERIAL) += serial/ obj-$(CONFIG_USB) += misc/ -obj-$(CONFIG_EARLY_PRINTK_DBGP)+= early/ +obj-$(CONFIG_USB_EARLY_PRINTK) += early/ obj-$(CONFIG_USB_ATM) += atm/ obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ diff --git a/drivers/usb/early/Makefile b/drivers/usb/early/Makefile index 24bbe51..2db5906 100644 --- a/drivers/usb/early/Makefile +++ b/drivers/usb/early/Makefile @@ -3,3 +3,4 @@ # obj-$(CONFIG_EARLY_PRINTK_DBGP) += ehci-dbgp.o +obj-$(CONFIG_EARLY_PRINTK_XDBC) += xhci-dbc.o diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c new file mode 100644 index 000..728a1a0 --- /dev/null +++ b/drivers/usb/early/xhci-dbc.c @@ -0,0 +1,1050 @@ +/** + * xhci-dbc.c - xHCI debug capability early driver + * + * Copyright (C) 2016 Intel Corporation + * + * Author: Lu Baolu + * + * 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. + */ + +#define pr_fmt(fmt)KBUILD_MODNAME ":%s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../host/xhci.h" +#include "xhci-dbc.h" + +static struct xdbc_state xdbc; +static int early_console_keep; + +#ifdef XDBC_TRACE
[PATCH v4 4/4] usb: doc: add document for USB3 debug port usage
Add Documentation/usb/usb3-debug-port.rst. This document includes the user guide for USB3 debug port. Cc: linux-...@vger.kernel.org Signed-off-by: Lu Baolu--- Documentation/usb/usb3-debug-port.rst | 95 +++ 1 file changed, 95 insertions(+) create mode 100644 Documentation/usb/usb3-debug-port.rst diff --git a/Documentation/usb/usb3-debug-port.rst b/Documentation/usb/usb3-debug-port.rst new file mode 100644 index 000..70eabe4 --- /dev/null +++ b/Documentation/usb/usb3-debug-port.rst @@ -0,0 +1,95 @@ +=== +USB3 debug port +=== + +:Author: Lu Baolu +:Date: October 2016 + +GENERAL +=== + +This is a HOWTO for using USB3 debug port on x86 systems. + +Before using any kernel debugging functionalities based on USB3 +debug port, you need to check 1) whether debug port is supported +by the xHCI host, 2) which port is used for debugging purpose +(normally the first USB3 root port). You must have a USB 3.0 +super-speed A-to-A debugging cable to connect the debug target +with a debug host. In this document, a debug target stands for +the system under debugging; while, a debug host stands for a +stand-alone system that is able to talk to the debugging target +through the USB3 debug port. + +EARLY PRINTK + + +On debug target system, you need to customize a debugging kernel +with CONFIG_EARLY_PRINTK_XDBC enabled. And add below kernel boot +parameter:: + + "earlyprintk=xdbc" + +If there are multiple xHCI controllers in the system, you can +append a host contoller index to this kernel parameter. This +index is started from 0. + +If you are going to leverage the keep option defined by the +early printk framework to keep the boot console alive after +early boot, you'd better add below kernel boot parameter:: + + "usbcore.autosuspend=-1" + +On debug host side, you don't need to customize the kernel, but +you need to disable usb subsystem runtime power management by +adding below kernel boot parameter:: + + "usbcore.autosuspend=-1" + +Before starting the debug target, you should connect the debug +port on debug target with a root port or port of any external hub +on the debug host. The cable used to connect these two ports +should be a USB 3.0 super-speed A-to-A debugging cable. + +During early boot of debug target, DbC (the debug engine for USB3 +debug port) hardware gets initialized. Debug host should be able +to enumerate the debug target as a debug device. Debug host will +then bind the debug device with the usb_debug driver module and +create the /dev/ttyUSB0 device. + +If device enumeration goes smoothly, you should be able to see +below kernel messages on debug host:: + + # tail -f /var/log/kern.log + [ 1815.983374] usb 4-3: new SuperSpeed USB device number 4 using xhci_hcd + [ 1815.999595] usb 4-3: LPM exit latency is zeroed, disabling LPM. + [ 1815.999899] usb 4-3: New USB device found, idVendor=1d6b, idProduct=0004 + [ 1815.02] usb 4-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3 + [ 1815.03] usb 4-3: Product: Remote GDB + [ 1815.04] usb 4-3: Manufacturer: Linux + [ 1815.05] usb 4-3: SerialNumber: 0001 + [ 1816.000240] usb_debug 4-3:1.0: xhci_dbc converter detected + [ 1816.000360] usb 4-3: xhci_dbc converter now attached to ttyUSB0 + +You can run below bash scripts on debug host to read the kernel +log sent from debug target. + +.. code-block:: sh + + = start of bash scripts = + #!/bin/bash + + while true ; do + while [ ! -d /sys/class/tty/ttyUSB0 ] ; do + : + done + cat /dev/ttyUSB0 >> xdbc.log + done + = end of bash scripts === + +You should be able to see the early boot message in xdbc.log. + +If it doesn't work, please ask it on the +mailing list. Below USB hosts have been verified to work:: + + Intel Corporation Sunrise Point-H USB 3.0 xHCI Controller + Intel Corporation Wildcat Point-LP USB xHCI Controller -- 2.1.4
[PATCH v4 4/4] usb: doc: add document for USB3 debug port usage
Add Documentation/usb/usb3-debug-port.rst. This document includes the user guide for USB3 debug port. Cc: linux-...@vger.kernel.org Signed-off-by: Lu Baolu --- Documentation/usb/usb3-debug-port.rst | 95 +++ 1 file changed, 95 insertions(+) create mode 100644 Documentation/usb/usb3-debug-port.rst diff --git a/Documentation/usb/usb3-debug-port.rst b/Documentation/usb/usb3-debug-port.rst new file mode 100644 index 000..70eabe4 --- /dev/null +++ b/Documentation/usb/usb3-debug-port.rst @@ -0,0 +1,95 @@ +=== +USB3 debug port +=== + +:Author: Lu Baolu +:Date: October 2016 + +GENERAL +=== + +This is a HOWTO for using USB3 debug port on x86 systems. + +Before using any kernel debugging functionalities based on USB3 +debug port, you need to check 1) whether debug port is supported +by the xHCI host, 2) which port is used for debugging purpose +(normally the first USB3 root port). You must have a USB 3.0 +super-speed A-to-A debugging cable to connect the debug target +with a debug host. In this document, a debug target stands for +the system under debugging; while, a debug host stands for a +stand-alone system that is able to talk to the debugging target +through the USB3 debug port. + +EARLY PRINTK + + +On debug target system, you need to customize a debugging kernel +with CONFIG_EARLY_PRINTK_XDBC enabled. And add below kernel boot +parameter:: + + "earlyprintk=xdbc" + +If there are multiple xHCI controllers in the system, you can +append a host contoller index to this kernel parameter. This +index is started from 0. + +If you are going to leverage the keep option defined by the +early printk framework to keep the boot console alive after +early boot, you'd better add below kernel boot parameter:: + + "usbcore.autosuspend=-1" + +On debug host side, you don't need to customize the kernel, but +you need to disable usb subsystem runtime power management by +adding below kernel boot parameter:: + + "usbcore.autosuspend=-1" + +Before starting the debug target, you should connect the debug +port on debug target with a root port or port of any external hub +on the debug host. The cable used to connect these two ports +should be a USB 3.0 super-speed A-to-A debugging cable. + +During early boot of debug target, DbC (the debug engine for USB3 +debug port) hardware gets initialized. Debug host should be able +to enumerate the debug target as a debug device. Debug host will +then bind the debug device with the usb_debug driver module and +create the /dev/ttyUSB0 device. + +If device enumeration goes smoothly, you should be able to see +below kernel messages on debug host:: + + # tail -f /var/log/kern.log + [ 1815.983374] usb 4-3: new SuperSpeed USB device number 4 using xhci_hcd + [ 1815.999595] usb 4-3: LPM exit latency is zeroed, disabling LPM. + [ 1815.999899] usb 4-3: New USB device found, idVendor=1d6b, idProduct=0004 + [ 1815.02] usb 4-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3 + [ 1815.03] usb 4-3: Product: Remote GDB + [ 1815.04] usb 4-3: Manufacturer: Linux + [ 1815.05] usb 4-3: SerialNumber: 0001 + [ 1816.000240] usb_debug 4-3:1.0: xhci_dbc converter detected + [ 1816.000360] usb 4-3: xhci_dbc converter now attached to ttyUSB0 + +You can run below bash scripts on debug host to read the kernel +log sent from debug target. + +.. code-block:: sh + + = start of bash scripts = + #!/bin/bash + + while true ; do + while [ ! -d /sys/class/tty/ttyUSB0 ] ; do + : + done + cat /dev/ttyUSB0 >> xdbc.log + done + = end of bash scripts === + +You should be able to see the early boot message in xdbc.log. + +If it doesn't work, please ask it on the +mailing list. Below USB hosts have been verified to work:: + + Intel Corporation Sunrise Point-H USB 3.0 xHCI Controller + Intel Corporation Wildcat Point-LP USB xHCI Controller -- 2.1.4
[PATCH v4 1/4] usb: dbc: early driver for xhci debug capability
xHCI debug capability (DbC) is an optional but standalone functionality provided by an xHCI host controller. Software learns this capability by walking through the extended capability list of the host. xHCI specification describes DbC in section 7.6. This patch introduces the code to probe and initialize the debug capability hardware during early boot. With hardware initialized, the debug target (system on which this code is running) will present a debug device through the debug port (normally the first USB3 port). The debug device is fully compliant with the USB framework and provides the equivalent of a very high performance (USB3) full-duplex serial link between the debug host and target. The DbC functionality is independent of xHCI host. There isn't any precondition from xHCI host side for DbC to work. This patch also includes bulk out and bulk in interfaces. These interfaces could be used to implement early printk bootconsole or hook to various system debuggers. This code is designed to be only used for kernel debugging when machine crashes very early before the console code is initialized. For normal operation it is not recommended. Cc: Mathias Nyman Signed-off-by: Lu Baolu --- arch/x86/Kconfig.debug| 14 + drivers/usb/Kconfig |3 + drivers/usb/Makefile |2 +- drivers/usb/early/Makefile|1 + drivers/usb/early/xhci-dbc.c | 1050 + drivers/usb/early/xhci-dbc.h | 202 include/linux/usb/xhci-dbgp.h | 22 + 7 files changed, 1293 insertions(+), 1 deletion(-) create mode 100644 drivers/usb/early/xhci-dbc.c create mode 100644 drivers/usb/early/xhci-dbc.h create mode 100644 include/linux/usb/xhci-dbgp.h diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 67eec55..13e85b7 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -29,6 +29,7 @@ config EARLY_PRINTK config EARLY_PRINTK_DBGP bool "Early printk via EHCI debug port" depends on EARLY_PRINTK && PCI + select USB_EARLY_PRINTK ---help--- Write kernel log output directly into the EHCI debug port. @@ -48,6 +49,19 @@ config EARLY_PRINTK_EFI This is useful for kernel debugging when your machine crashes very early before the console code is initialized. +config EARLY_PRINTK_XDBC + bool "Early printk via xHCI debug port" + depends on EARLY_PRINTK && PCI + select USB_EARLY_PRINTK + ---help--- + Write kernel log output directly into the xHCI debug port. + + This is useful for kernel debugging when your machine crashes very + early before the console code is initialized. For normal operation + it is not recommended because it looks ugly and doesn't cooperate + with klogd/syslogd or the X server. You should normally N here, + unless you want to debug such a crash. + config X86_PTDUMP_CORE def_bool n diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index fbe493d..9313fff 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -19,6 +19,9 @@ config USB_EHCI_BIG_ENDIAN_MMIO config USB_EHCI_BIG_ENDIAN_DESC bool +config USB_EARLY_PRINTK + bool + menuconfig USB_SUPPORT bool "USB support" depends on HAS_IOMEM diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 7791af6..0c37838 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -49,7 +49,7 @@ obj-$(CONFIG_USB_MICROTEK)+= image/ obj-$(CONFIG_USB_SERIAL) += serial/ obj-$(CONFIG_USB) += misc/ -obj-$(CONFIG_EARLY_PRINTK_DBGP)+= early/ +obj-$(CONFIG_USB_EARLY_PRINTK) += early/ obj-$(CONFIG_USB_ATM) += atm/ obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ diff --git a/drivers/usb/early/Makefile b/drivers/usb/early/Makefile index 24bbe51..2db5906 100644 --- a/drivers/usb/early/Makefile +++ b/drivers/usb/early/Makefile @@ -3,3 +3,4 @@ # obj-$(CONFIG_EARLY_PRINTK_DBGP) += ehci-dbgp.o +obj-$(CONFIG_EARLY_PRINTK_XDBC) += xhci-dbc.o diff --git a/drivers/usb/early/xhci-dbc.c b/drivers/usb/early/xhci-dbc.c new file mode 100644 index 000..728a1a0 --- /dev/null +++ b/drivers/usb/early/xhci-dbc.c @@ -0,0 +1,1050 @@ +/** + * xhci-dbc.c - xHCI debug capability early driver + * + * Copyright (C) 2016 Intel Corporation + * + * Author: Lu Baolu + * + * 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. + */ + +#define pr_fmt(fmt)KBUILD_MODNAME ":%s: " fmt, __func__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../host/xhci.h" +#include "xhci-dbc.h" + +static struct xdbc_state xdbc; +static int early_console_keep; + +#ifdef XDBC_TRACE +#definexdbc_trace trace_printk +#else +static inline void
[PATCH v4 0/4] usb: early: add support for early printk through USB3 debug port
xHCI debug capability (DbC) is an optional but standalone functionality provided by an xHCI host controller. With DbC hardware initialized, the system will present a debug device through the USB3 debug port (normally the first USB3 port). The debug device is fully compliant with the USB framework and provides the equivalent of a very high performance (USB3) full-duplex serial link between the debug host and target. The DbC functionality is independent of xHCI host. There isn't any precondition from xHCI host side for DbC to work. This patch set adds support for early printk functionality through a USB3 debug port by 1) initializing and enabling the DbC hardware during early boot; 2) registering a boot console to the system so that early printk messages can go through the USB3 debug port. It also includes some lines of changes in usb_debug driver so that it can be bound when a USB3 debug device is enumerated. This code is designed to be used only for kernel debugging when machine crashes very early before the console code is initialized. It makes the life of kernel debugging easier when people work with a modern machine without any legacy serial ports. --- Change log: v3->v4: - Rename the document with .dst suffix. - Add the list of hardware that has been succesfuly tested on in the document. v2->v3: - Removed spinlock usage. - Removed work queue usage. - Refined the user guide document. v1->v2: - Refactor the duplicate code in xdbc_early_start() and xdbc_handle_external_reset(). - Free resources when hardware not used any more. - Refine the user guide document. Lu Baolu (4): usb: dbc: early driver for xhci debug capability x86: add support for earlyprintk via USB3 debug port usb: serial: usb_debug: add support for dbc debug device usb: doc: add document for USB3 debug port usage Documentation/kernel-parameters.txt |1 + Documentation/usb/usb3-debug-port.rst | 95 +++ arch/x86/Kconfig.debug| 14 + arch/x86/kernel/early_printk.c|5 + arch/x86/kernel/setup.c |7 + drivers/usb/Kconfig |3 + drivers/usb/Makefile |2 +- drivers/usb/early/Makefile|1 + drivers/usb/early/xhci-dbc.c | 1050 + drivers/usb/early/xhci-dbc.h | 202 +++ drivers/usb/serial/usb_debug.c| 28 +- include/linux/usb/xhci-dbgp.h | 22 + 12 files changed, 1426 insertions(+), 4 deletions(-) create mode 100644 Documentation/usb/usb3-debug-port.rst create mode 100644 drivers/usb/early/xhci-dbc.c create mode 100644 drivers/usb/early/xhci-dbc.h create mode 100644 include/linux/usb/xhci-dbgp.h -- 2.1.4
[PATCH v4 0/4] usb: early: add support for early printk through USB3 debug port
xHCI debug capability (DbC) is an optional but standalone functionality provided by an xHCI host controller. With DbC hardware initialized, the system will present a debug device through the USB3 debug port (normally the first USB3 port). The debug device is fully compliant with the USB framework and provides the equivalent of a very high performance (USB3) full-duplex serial link between the debug host and target. The DbC functionality is independent of xHCI host. There isn't any precondition from xHCI host side for DbC to work. This patch set adds support for early printk functionality through a USB3 debug port by 1) initializing and enabling the DbC hardware during early boot; 2) registering a boot console to the system so that early printk messages can go through the USB3 debug port. It also includes some lines of changes in usb_debug driver so that it can be bound when a USB3 debug device is enumerated. This code is designed to be used only for kernel debugging when machine crashes very early before the console code is initialized. It makes the life of kernel debugging easier when people work with a modern machine without any legacy serial ports. --- Change log: v3->v4: - Rename the document with .dst suffix. - Add the list of hardware that has been succesfuly tested on in the document. v2->v3: - Removed spinlock usage. - Removed work queue usage. - Refined the user guide document. v1->v2: - Refactor the duplicate code in xdbc_early_start() and xdbc_handle_external_reset(). - Free resources when hardware not used any more. - Refine the user guide document. Lu Baolu (4): usb: dbc: early driver for xhci debug capability x86: add support for earlyprintk via USB3 debug port usb: serial: usb_debug: add support for dbc debug device usb: doc: add document for USB3 debug port usage Documentation/kernel-parameters.txt |1 + Documentation/usb/usb3-debug-port.rst | 95 +++ arch/x86/Kconfig.debug| 14 + arch/x86/kernel/early_printk.c|5 + arch/x86/kernel/setup.c |7 + drivers/usb/Kconfig |3 + drivers/usb/Makefile |2 +- drivers/usb/early/Makefile|1 + drivers/usb/early/xhci-dbc.c | 1050 + drivers/usb/early/xhci-dbc.h | 202 +++ drivers/usb/serial/usb_debug.c| 28 +- include/linux/usb/xhci-dbgp.h | 22 + 12 files changed, 1426 insertions(+), 4 deletions(-) create mode 100644 Documentation/usb/usb3-debug-port.rst create mode 100644 drivers/usb/early/xhci-dbc.c create mode 100644 drivers/usb/early/xhci-dbc.h create mode 100644 include/linux/usb/xhci-dbgp.h -- 2.1.4
[PATCH v4 2/4] x86: add support for earlyprintk via USB3 debug port
Add support for early printk by writing debug messages to the USB3 debug port. Users can use this type of early printk by specifying kernel parameter of "earlyprintk=xdbc". This gives users a chance of providing debug output. The hardware for USB3 debug port requires DMA memory blocks. This requires to delay setting up debugging hardware and registering boot console until the memblocks are filled. Cc: Ingo MolnarCc: x...@kernel.org Signed-off-by: Lu Baolu --- Documentation/kernel-parameters.txt | 1 + arch/x86/kernel/early_printk.c | 5 + arch/x86/kernel/setup.c | 7 +++ 3 files changed, 13 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 37babf9..99b64b3 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1178,6 +1178,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. earlyprintk=ttySn[,baudrate] earlyprintk=dbgp[debugController#] earlyprintk=pciserial,bus:device.function[,baudrate] + earlyprintk=xdbc[xhciController#] earlyprintk is useful when the kernel crashes before the normal console is initialized. It is not enabled by diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index 8a12199..c4031b9 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -381,6 +382,10 @@ static int __init setup_early_printk(char *buf) if (!strncmp(buf, "efi", 3)) early_console_register(_efi_console, keep); #endif +#ifdef CONFIG_EARLY_PRINTK_XDBC + if (!strncmp(buf, "xdbc", 4)) + early_xdbc_parse_parameter(buf + 4); +#endif buf++; } diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 9c337b0..09d4a56 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -70,6 +70,8 @@ #include #include +#include + #include #include @@ -1096,6 +1098,11 @@ void __init setup_arch(char **cmdline_p) memblock_set_current_limit(ISA_END_ADDRESS); memblock_x86_fill(); +#ifdef CONFIG_EARLY_PRINTK_XDBC + if (!early_xdbc_setup_hardware()) + early_xdbc_register_console(); +#endif + reserve_bios_regions(); if (efi_enabled(EFI_MEMMAP)) { -- 2.1.4
[PATCH v4 2/4] x86: add support for earlyprintk via USB3 debug port
Add support for early printk by writing debug messages to the USB3 debug port. Users can use this type of early printk by specifying kernel parameter of "earlyprintk=xdbc". This gives users a chance of providing debug output. The hardware for USB3 debug port requires DMA memory blocks. This requires to delay setting up debugging hardware and registering boot console until the memblocks are filled. Cc: Ingo Molnar Cc: x...@kernel.org Signed-off-by: Lu Baolu --- Documentation/kernel-parameters.txt | 1 + arch/x86/kernel/early_printk.c | 5 + arch/x86/kernel/setup.c | 7 +++ 3 files changed, 13 insertions(+) diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 37babf9..99b64b3 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1178,6 +1178,7 @@ bytes respectively. Such letter suffixes can also be entirely omitted. earlyprintk=ttySn[,baudrate] earlyprintk=dbgp[debugController#] earlyprintk=pciserial,bus:device.function[,baudrate] + earlyprintk=xdbc[xhciController#] earlyprintk is useful when the kernel crashes before the normal console is initialized. It is not enabled by diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c index 8a12199..c4031b9 100644 --- a/arch/x86/kernel/early_printk.c +++ b/arch/x86/kernel/early_printk.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -381,6 +382,10 @@ static int __init setup_early_printk(char *buf) if (!strncmp(buf, "efi", 3)) early_console_register(_efi_console, keep); #endif +#ifdef CONFIG_EARLY_PRINTK_XDBC + if (!strncmp(buf, "xdbc", 4)) + early_xdbc_parse_parameter(buf + 4); +#endif buf++; } diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 9c337b0..09d4a56 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -70,6 +70,8 @@ #include #include +#include + #include #include @@ -1096,6 +1098,11 @@ void __init setup_arch(char **cmdline_p) memblock_set_current_limit(ISA_END_ADDRESS); memblock_x86_fill(); +#ifdef CONFIG_EARLY_PRINTK_XDBC + if (!early_xdbc_setup_hardware()) + early_xdbc_register_console(); +#endif + reserve_bios_regions(); if (efi_enabled(EFI_MEMMAP)) { -- 2.1.4
Re: make pdfdocs fails with v4.9-rc3
Em Mon, 31 Oct 2016 16:41:48 -0600 Mauro Carvalho Chehabescreveu: > Em Mon, 31 Oct 2016 16:40:02 -0600 > Mauro Carvalho Chehab escreveu: > > > Em Mon, 31 Oct 2016 15:04:42 -0700 > > Jim Davis escreveu: > > > > > On Mon, Oct 31, 2016 at 1:58 PM, Mauro Carvalho Chehab > > > wrote: > > > > Em Mon, 31 Oct 2016 14:17:59 -0600 > > > > Mauro Carvalho Chehab escreveu: > > > > > > > >> Em Mon, 31 Oct 2016 13:15:24 -0600 > > > >> Jonathan Corbet escreveu: > > > >> > > > >> > On Mon, 31 Oct 2016 11:51:20 -0700 > > > >> > Jim Davis wrote: > > > >> > > > > >> > > Running make pdfdocs on a Ubuntu 16.04 system fails with > > > >> > > > > > >> > > Makefile:58: recipe for target 'media.pdf' failed > > > >> > > make[2]: *** [media.pdf] Error 1 > > > >> > > Documentation/Makefile.sphinx:79: recipe for target 'pdfdocs' > > > >> > > failed > > > >> > > make[1]: *** [pdfdocs] Error 2 > > > >> > > Makefile:1442: recipe for target 'pdfdocs' failed > > > >> > > make: *** [pdfdocs] Error 2 > > > >> > > > > > >> > > It's not clear from the voluminous (>5MB) output from make pdfdocs > > > >> > > exactly which stage is failing, and there are some pdf files > > > >> > > produced > > > >> > > in output/latex. > > > >> > > > > >> > Hmm, so it does. It comes down to this: > > > >> > > > > >> > ! LaTeX Error: \DUrole undefined. > > > >> > > > > >> > See the LaTeX manual or LaTeX Companion for explanation. > > > >> > Type H for immediate help. > > > >> > ... > > > >> > > > > >> > l.195 \renewcommand*{\DUrole} > > > >> > [2]{ #2 } > > > >> > > > > >> > Where the offending command is in Documentation/media/index.rst. > > > >> > Mauro, > > > >> > got an idea for what's going on there? > > > >> > > > >> Sphinx is really a poor solution when it comes to PDF output. In this > > > >> specific case, this is meant to fix a problem with cross-references. > > > >> > > > >> What happens is that Sphinx 1.4.6 (and later?) define reference names > > > >> without > > > >> being properly escaped. So, for some references, it causes the PDF > > > >> output > > > >> to crash. That happens at one of the DVB header files, if I remember > > > >> well. > > > >> > > > >> This commit restores the sphinx 1.2.x behavior: > > > >> > > > >> commit e61a39baf74dddb6cd236147bd19b55c10188d78 > > > >> Author: Mauro Carvalho Chehab > > > >> Date: Sun Aug 21 15:14:57 2016 -0300 > > > >> > > > >> [media] index.rst: Fix LaTeX error in interactive mode on Sphinx > > > >> 1.4.x > > > >> > > > >> The Sphinx 1.4.x definition for \DUrole is: > > > >> > > > >> \providecommand*{\DUrole}[2]{% > > > >> \ifcsname DUrole#1\endcsname% > > > >> \csname DUrole#1\endcsname{#2}% > > > >> \else% backwards compatibility: try \docutilsrole#1{#2} > > > >> \ifcsname docutilsrole#1\endcsname% > > > >> \csname docutilsrole#1\endcsname{#2}% > > > >> \else% > > > >> #2% > > > >> \fi% > > > >> \fi% > > > >> } > > > >> > > > >> This is broken when it is used inside a \begin{alltt} block. > > > >> So, replace it by just "#2", as this won't cause troubles, and > > > >> it is one of the fallback methods for it. > > > >> > > > >> Signed-off-by: Mauro Carvalho Chehab > > > >> > > > >> At the time I tested, it worked fine, but maybe it is redefining the > > > >> \DUrole too late. > > > >> > > > >> Maybe we could move it to LaTeX preamble instead. Please check if this > > > >> untested patch fixes the issue. > > > > > > > > Yes, this seems to be the case. The patch below should fix it. > > > > > > > > [PATCH] docs-rst: fix PDF build errors > > > > > > > > PDF build on Kernel 4.9-rc? returns an error. This is > > > > because we're re-defining a command too late. Move > > > > such redefinition to LaTeX preamble. > > > > > > > > Tested by building the documentation on interactive mode: > > > > make PDFLATEX=xelatex -C Documentation/output/./latex > > > > > > > > Fixes: e61a39baf74d ("[media] index.rst: Fix LaTeX error in interactive > > > > mode on Sphinx 1.4.x") > > > > > > > > Signed-off-by: Mauro Carvalho Chehab > > > > > > > > diff --git a/Documentation/conf.py b/Documentation/conf.py > > > > index d9bad21dd427..d9ebfeb431a9 100644 > > > > --- a/Documentation/conf.py > > > > +++ b/Documentation/conf.py > > > > @@ -329,6 +329,9 @@ latex_elements = { > > > > % To allow adjusting table sizes > > > > \\usepackage{adjustbox} > > > > > > > > + % Fix reference escape troubles with Sphinx 1.4.x > > > > + \\renewcommand*{\\DUrole}[2]{ #2 } > > > > + > > > > ''' > > > > } > > > > > > > > diff --git a/Documentation/media/index.rst > > > > b/Documentation/media/index.rst > >
Re: make pdfdocs fails with v4.9-rc3
Em Mon, 31 Oct 2016 16:41:48 -0600 Mauro Carvalho Chehab escreveu: > Em Mon, 31 Oct 2016 16:40:02 -0600 > Mauro Carvalho Chehab escreveu: > > > Em Mon, 31 Oct 2016 15:04:42 -0700 > > Jim Davis escreveu: > > > > > On Mon, Oct 31, 2016 at 1:58 PM, Mauro Carvalho Chehab > > > wrote: > > > > Em Mon, 31 Oct 2016 14:17:59 -0600 > > > > Mauro Carvalho Chehab escreveu: > > > > > > > >> Em Mon, 31 Oct 2016 13:15:24 -0600 > > > >> Jonathan Corbet escreveu: > > > >> > > > >> > On Mon, 31 Oct 2016 11:51:20 -0700 > > > >> > Jim Davis wrote: > > > >> > > > > >> > > Running make pdfdocs on a Ubuntu 16.04 system fails with > > > >> > > > > > >> > > Makefile:58: recipe for target 'media.pdf' failed > > > >> > > make[2]: *** [media.pdf] Error 1 > > > >> > > Documentation/Makefile.sphinx:79: recipe for target 'pdfdocs' > > > >> > > failed > > > >> > > make[1]: *** [pdfdocs] Error 2 > > > >> > > Makefile:1442: recipe for target 'pdfdocs' failed > > > >> > > make: *** [pdfdocs] Error 2 > > > >> > > > > > >> > > It's not clear from the voluminous (>5MB) output from make pdfdocs > > > >> > > exactly which stage is failing, and there are some pdf files > > > >> > > produced > > > >> > > in output/latex. > > > >> > > > > >> > Hmm, so it does. It comes down to this: > > > >> > > > > >> > ! LaTeX Error: \DUrole undefined. > > > >> > > > > >> > See the LaTeX manual or LaTeX Companion for explanation. > > > >> > Type H for immediate help. > > > >> > ... > > > >> > > > > >> > l.195 \renewcommand*{\DUrole} > > > >> > [2]{ #2 } > > > >> > > > > >> > Where the offending command is in Documentation/media/index.rst. > > > >> > Mauro, > > > >> > got an idea for what's going on there? > > > >> > > > >> Sphinx is really a poor solution when it comes to PDF output. In this > > > >> specific case, this is meant to fix a problem with cross-references. > > > >> > > > >> What happens is that Sphinx 1.4.6 (and later?) define reference names > > > >> without > > > >> being properly escaped. So, for some references, it causes the PDF > > > >> output > > > >> to crash. That happens at one of the DVB header files, if I remember > > > >> well. > > > >> > > > >> This commit restores the sphinx 1.2.x behavior: > > > >> > > > >> commit e61a39baf74dddb6cd236147bd19b55c10188d78 > > > >> Author: Mauro Carvalho Chehab > > > >> Date: Sun Aug 21 15:14:57 2016 -0300 > > > >> > > > >> [media] index.rst: Fix LaTeX error in interactive mode on Sphinx > > > >> 1.4.x > > > >> > > > >> The Sphinx 1.4.x definition for \DUrole is: > > > >> > > > >> \providecommand*{\DUrole}[2]{% > > > >> \ifcsname DUrole#1\endcsname% > > > >> \csname DUrole#1\endcsname{#2}% > > > >> \else% backwards compatibility: try \docutilsrole#1{#2} > > > >> \ifcsname docutilsrole#1\endcsname% > > > >> \csname docutilsrole#1\endcsname{#2}% > > > >> \else% > > > >> #2% > > > >> \fi% > > > >> \fi% > > > >> } > > > >> > > > >> This is broken when it is used inside a \begin{alltt} block. > > > >> So, replace it by just "#2", as this won't cause troubles, and > > > >> it is one of the fallback methods for it. > > > >> > > > >> Signed-off-by: Mauro Carvalho Chehab > > > >> > > > >> At the time I tested, it worked fine, but maybe it is redefining the > > > >> \DUrole too late. > > > >> > > > >> Maybe we could move it to LaTeX preamble instead. Please check if this > > > >> untested patch fixes the issue. > > > > > > > > Yes, this seems to be the case. The patch below should fix it. > > > > > > > > [PATCH] docs-rst: fix PDF build errors > > > > > > > > PDF build on Kernel 4.9-rc? returns an error. This is > > > > because we're re-defining a command too late. Move > > > > such redefinition to LaTeX preamble. > > > > > > > > Tested by building the documentation on interactive mode: > > > > make PDFLATEX=xelatex -C Documentation/output/./latex > > > > > > > > Fixes: e61a39baf74d ("[media] index.rst: Fix LaTeX error in interactive > > > > mode on Sphinx 1.4.x") > > > > > > > > Signed-off-by: Mauro Carvalho Chehab > > > > > > > > diff --git a/Documentation/conf.py b/Documentation/conf.py > > > > index d9bad21dd427..d9ebfeb431a9 100644 > > > > --- a/Documentation/conf.py > > > > +++ b/Documentation/conf.py > > > > @@ -329,6 +329,9 @@ latex_elements = { > > > > % To allow adjusting table sizes > > > > \\usepackage{adjustbox} > > > > > > > > + % Fix reference escape troubles with Sphinx 1.4.x > > > > + \\renewcommand*{\\DUrole}[2]{ #2 } > > > > + > > > > ''' > > > > } > > > > > > > > diff --git a/Documentation/media/index.rst > > > > b/Documentation/media/index.rst > > > > index e347a3e7bdef..7f8f0af620ce 100644 > > > > --- a/Documentation/media/index.rst > > > > +++ b/Documentation/media/index.rst > > > > @@ -1,11 +1,6 @@ > > > > Linux Media Subsystem Documentation > > > >
[PATCH v6 3/3] fpga: Add support for Lattice iCE40 FPGAs
The Lattice iCE40 is a family of FPGAs with a minimalistic architecture and very regular structure, designed for low-cost, high-volume consumer and system applications. This patch adds support to the FPGA manager for configuring the SRAM of iCE40LM, iCE40LP, iCE40HX, iCE40 Ultra, iCE40 UltraLite and iCE40 UltraPlus devices, through slave SPI. The iCE40 family is notable because it is the first FPGA family to have complete reverse engineered bit-stream documentation for the iCE40LP and iCE40HX devices. Furthermore, there is now a Free Software Verilog synthesis tool-chain: the "IceStorm" tool-chain. This project is the work of Clifford Wolf, who is the maintainer of Yosys Verilog RTL synthesis framework, and Mathias Lasser, with notable contributions from "Cotton Seed", the main author of "arachne-pnr"; a place-and-route tool for iCE40 FPGAs. Having a Free Software synthesis tool-chain offers interesting opportunities for embedded devices that are able reconfigure themselves with open firmware that is generated on the device itself. For example a mobile device might have an application processor with an iCE40 FPGA attached, which implements slave devices, or through which the processor communicates with other devices through the FPGA fabric. A kernel driver for the iCE40 is useful, because in some cases, the FPGA may need to be configured before other devices can be accessed. An example of such a device is the icoBoard; a RaspberryPI HAT which features an iCE40HX8K with a 1 or 8 MBit SRAM and ports for Digilent-compatible PMOD modules. A PMOD module may contain a device with which the kernel communicates, via the FPGA. --- drivers/fpga/Kconfig | 6 ++ drivers/fpga/Makefile| 1 + drivers/fpga/ice40-spi.c | 219 +++ 3 files changed, 226 insertions(+) create mode 100644 drivers/fpga/ice40-spi.c diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index d614102..85ff429 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -13,6 +13,12 @@ config FPGA if FPGA +config FPGA_MGR_ICE40_SPI + tristate "Lattice iCE40 SPI" + depends on SPI + help + FPGA manager driver support for Lattice iCE40 FPGAs over SPI. + config FPGA_MGR_SOCFPGA tristate "Altera SOCFPGA FPGA Manager" depends on ARCH_SOCFPGA diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index 8d83fc6..adb5811 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -6,5 +6,6 @@ obj-$(CONFIG_FPGA) += fpga-mgr.o # FPGA Manager Drivers +obj-$(CONFIG_FPGA_MGR_ICE40_SPI) += ice40-spi.o obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o diff --git a/drivers/fpga/ice40-spi.c b/drivers/fpga/ice40-spi.c new file mode 100644 index 000..c39e6f0 --- /dev/null +++ b/drivers/fpga/ice40-spi.c @@ -0,0 +1,219 @@ +/* + * FPGA Manager Driver for Lattice iCE40. + * + * Copyright (c) 2016 Joel Holdsworth + * + * 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; version 2 of the License. + * + * This driver adds support to the FPGA manager for configuring the SRAM of + * Lattice iCE40 FPGAs through slave SPI. + */ + +#include +#include +#include +#include + +#define ICE40_SPI_FPGAMGR_RESET_DELAY 1 /* us (>200ns) */ +#define ICE40_SPI_FPGAMGR_HOUSEKEEPING_DELAY 1200 /* us */ + +#define ICE40_SPI_FPGAMGR_NUM_ACTIVATION_BITS 49 /* bits */ + +struct ice40_fpga_priv { + struct spi_device *dev; + struct gpio_desc *reset; + struct gpio_desc *cdone; +}; + +static enum fpga_mgr_states ice40_fpga_ops_state(struct fpga_manager *mgr) +{ + struct ice40_fpga_priv *priv = mgr->priv; + return gpiod_get_value(priv->cdone) ? FPGA_MGR_STATE_OPERATING : + FPGA_MGR_STATE_UNKNOWN; +} + +static int ice40_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags, +const char *buf, size_t count) +{ + struct ice40_fpga_priv *priv = mgr->priv; + struct spi_device *dev = priv->dev; + struct spi_message message; + int ret; + + if ((flags & FPGA_MGR_PARTIAL_RECONFIG)) { + dev_err(>dev, + "Partial reconfiguration is not supported\n"); + return -ENOTSUPP; + } + + /* Lock the bus, assert CRESET_B and SS_B and delay >200ns */ + ret = spi_bus_lock(dev->master); + if (ret) { + dev_err(>dev, "Failed to lock SPI bus, ret: %d\n", ret); + return ret; + } + + gpiod_set_value(priv->reset, 1); + + spi_message_init(); + spi_message_add_tail(&(struct spi_transfer){.cs_change = 1, + .delay_usecs = ICE40_SPI_FPGAMGR_RESET_DELAY}, ); + ret = spi_sync_locked(dev, ); + if (ret) { + dev_err(>dev,
[PATCH v6 3/3] fpga: Add support for Lattice iCE40 FPGAs
The Lattice iCE40 is a family of FPGAs with a minimalistic architecture and very regular structure, designed for low-cost, high-volume consumer and system applications. This patch adds support to the FPGA manager for configuring the SRAM of iCE40LM, iCE40LP, iCE40HX, iCE40 Ultra, iCE40 UltraLite and iCE40 UltraPlus devices, through slave SPI. The iCE40 family is notable because it is the first FPGA family to have complete reverse engineered bit-stream documentation for the iCE40LP and iCE40HX devices. Furthermore, there is now a Free Software Verilog synthesis tool-chain: the "IceStorm" tool-chain. This project is the work of Clifford Wolf, who is the maintainer of Yosys Verilog RTL synthesis framework, and Mathias Lasser, with notable contributions from "Cotton Seed", the main author of "arachne-pnr"; a place-and-route tool for iCE40 FPGAs. Having a Free Software synthesis tool-chain offers interesting opportunities for embedded devices that are able reconfigure themselves with open firmware that is generated on the device itself. For example a mobile device might have an application processor with an iCE40 FPGA attached, which implements slave devices, or through which the processor communicates with other devices through the FPGA fabric. A kernel driver for the iCE40 is useful, because in some cases, the FPGA may need to be configured before other devices can be accessed. An example of such a device is the icoBoard; a RaspberryPI HAT which features an iCE40HX8K with a 1 or 8 MBit SRAM and ports for Digilent-compatible PMOD modules. A PMOD module may contain a device with which the kernel communicates, via the FPGA. --- drivers/fpga/Kconfig | 6 ++ drivers/fpga/Makefile| 1 + drivers/fpga/ice40-spi.c | 219 +++ 3 files changed, 226 insertions(+) create mode 100644 drivers/fpga/ice40-spi.c diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index d614102..85ff429 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -13,6 +13,12 @@ config FPGA if FPGA +config FPGA_MGR_ICE40_SPI + tristate "Lattice iCE40 SPI" + depends on SPI + help + FPGA manager driver support for Lattice iCE40 FPGAs over SPI. + config FPGA_MGR_SOCFPGA tristate "Altera SOCFPGA FPGA Manager" depends on ARCH_SOCFPGA diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index 8d83fc6..adb5811 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -6,5 +6,6 @@ obj-$(CONFIG_FPGA) += fpga-mgr.o # FPGA Manager Drivers +obj-$(CONFIG_FPGA_MGR_ICE40_SPI) += ice40-spi.o obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o diff --git a/drivers/fpga/ice40-spi.c b/drivers/fpga/ice40-spi.c new file mode 100644 index 000..c39e6f0 --- /dev/null +++ b/drivers/fpga/ice40-spi.c @@ -0,0 +1,219 @@ +/* + * FPGA Manager Driver for Lattice iCE40. + * + * Copyright (c) 2016 Joel Holdsworth + * + * 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; version 2 of the License. + * + * This driver adds support to the FPGA manager for configuring the SRAM of + * Lattice iCE40 FPGAs through slave SPI. + */ + +#include +#include +#include +#include + +#define ICE40_SPI_FPGAMGR_RESET_DELAY 1 /* us (>200ns) */ +#define ICE40_SPI_FPGAMGR_HOUSEKEEPING_DELAY 1200 /* us */ + +#define ICE40_SPI_FPGAMGR_NUM_ACTIVATION_BITS 49 /* bits */ + +struct ice40_fpga_priv { + struct spi_device *dev; + struct gpio_desc *reset; + struct gpio_desc *cdone; +}; + +static enum fpga_mgr_states ice40_fpga_ops_state(struct fpga_manager *mgr) +{ + struct ice40_fpga_priv *priv = mgr->priv; + return gpiod_get_value(priv->cdone) ? FPGA_MGR_STATE_OPERATING : + FPGA_MGR_STATE_UNKNOWN; +} + +static int ice40_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags, +const char *buf, size_t count) +{ + struct ice40_fpga_priv *priv = mgr->priv; + struct spi_device *dev = priv->dev; + struct spi_message message; + int ret; + + if ((flags & FPGA_MGR_PARTIAL_RECONFIG)) { + dev_err(>dev, + "Partial reconfiguration is not supported\n"); + return -ENOTSUPP; + } + + /* Lock the bus, assert CRESET_B and SS_B and delay >200ns */ + ret = spi_bus_lock(dev->master); + if (ret) { + dev_err(>dev, "Failed to lock SPI bus, ret: %d\n", ret); + return ret; + } + + gpiod_set_value(priv->reset, 1); + + spi_message_init(); + spi_message_add_tail(&(struct spi_transfer){.cs_change = 1, + .delay_usecs = ICE40_SPI_FPGAMGR_RESET_DELAY}, ); + ret = spi_sync_locked(dev, ); + if (ret) { + dev_err(>dev,
[PATCH v6 2/3] Documentation: Add binding document for Lattice iCE40 FPGA manager
--- .../bindings/fpga/lattice-ice40-fpga-mgr.txt| 21 + 1 file changed, 21 insertions(+) create mode 100644 Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt diff --git a/Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt b/Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt new file mode 100644 index 000..cb64184 --- /dev/null +++ b/Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt @@ -0,0 +1,21 @@ +Lattice iCE40 FPGA Manager + +Required properties: +- compatible: Should contain "lattice,ice40-fpga-mgr" +- reg: SPI chip select +- spi-max-frequency: Maximum SPI frequency (>=100, <=2500) +- cdone-gpios: GPIO input connected to CDONE pin +- reset-gpios: Active-low GPIO output connected to CRESET_B pin. Note + that unless the GPIO is held low during startup, the + FPGA will enter Master SPI mode and drive SCK with a + clock signal, potentially jamming other devices on the + bus until the firmware is loaded. + +Example: + ice40: ice40@0 { + compatible = "lattice,ice40-fpga-mgr"; + reg = <0>; + spi-max-frequency = <100>; + cdone-gpios = < 24 GPIO_ACTIVE_HIGH>; + creset_b-gpios = < 22 GPIO_ACTIVE_LOW>; + }; -- 2.7.4
[PATCH v6 1/3] of: Add vendor prefix for Lattice Semiconductor
Acked-by: Rob Herring--- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 1992aa9..d64a835 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -146,6 +146,7 @@ kosagi Sutajio Ko-Usagi PTE Ltd. kyoKyocera Corporation lacie LaCie lantiq Lantiq Semiconductor +latticeLattice Semiconductor lenovo Lenovo Group Ltd. lg LG Corporation linux Linux-specific binding -- 2.7.4
[PATCH v6 2/3] Documentation: Add binding document for Lattice iCE40 FPGA manager
--- .../bindings/fpga/lattice-ice40-fpga-mgr.txt| 21 + 1 file changed, 21 insertions(+) create mode 100644 Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt diff --git a/Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt b/Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt new file mode 100644 index 000..cb64184 --- /dev/null +++ b/Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt @@ -0,0 +1,21 @@ +Lattice iCE40 FPGA Manager + +Required properties: +- compatible: Should contain "lattice,ice40-fpga-mgr" +- reg: SPI chip select +- spi-max-frequency: Maximum SPI frequency (>=100, <=2500) +- cdone-gpios: GPIO input connected to CDONE pin +- reset-gpios: Active-low GPIO output connected to CRESET_B pin. Note + that unless the GPIO is held low during startup, the + FPGA will enter Master SPI mode and drive SCK with a + clock signal, potentially jamming other devices on the + bus until the firmware is loaded. + +Example: + ice40: ice40@0 { + compatible = "lattice,ice40-fpga-mgr"; + reg = <0>; + spi-max-frequency = <100>; + cdone-gpios = < 24 GPIO_ACTIVE_HIGH>; + creset_b-gpios = < 22 GPIO_ACTIVE_LOW>; + }; -- 2.7.4
[PATCH v6 1/3] of: Add vendor prefix for Lattice Semiconductor
Acked-by: Rob Herring --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 1992aa9..d64a835 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -146,6 +146,7 @@ kosagi Sutajio Ko-Usagi PTE Ltd. kyoKyocera Corporation lacie LaCie lantiq Lantiq Semiconductor +latticeLattice Semiconductor lenovo Lenovo Group Ltd. lg LG Corporation linux Linux-specific binding -- 2.7.4
[PATCH v5 3/3] fpga: Add support for Lattice iCE40 FPGAs
The Lattice iCE40 is a family of FPGAs with a minimalistic architecture and very regular structure, designed for low-cost, high-volume consumer and system applications. This patch adds support to the FPGA manager for configuring the SRAM of iCE40LM, iCE40LP, iCE40HX, iCE40 Ultra, iCE40 UltraLite and iCE40 UltraPlus devices, through slave SPI. The iCE40 family is notable because it is the first FPGA family to have complete reverse engineered bit-stream documentation for the iCE40LP and iCE40HX devices. Furthermore, there is now a Free Software Verilog synthesis tool-chain: the "IceStorm" tool-chain. This project is the work of Clifford Wolf, who is the maintainer of Yosys Verilog RTL synthesis framework, and Mathias Lasser, with notable contributions from "Cotton Seed", the main author of "arachne-pnr"; a place-and-route tool for iCE40 FPGAs. Having a Free Software synthesis tool-chain offers interesting opportunities for embedded devices that are able reconfigure themselves with open firmware that is generated on the device itself. For example a mobile device might have an application processor with an iCE40 FPGA attached, which implements slave devices, or through which the processor communicates with other devices through the FPGA fabric. A kernel driver for the iCE40 is useful, because in some cases, the FPGA may need to be configured before other devices can be accessed. An example of such a device is the icoBoard; a RaspberryPI HAT which features an iCE40HX8K with a 1 or 8 MBit SRAM and ports for Digilent-compatible PMOD modules. A PMOD module may contain a device with which the kernel communicates, via the FPGA. --- drivers/fpga/Kconfig | 6 ++ drivers/fpga/Makefile| 1 + drivers/fpga/ice40-spi.c | 219 +++ 3 files changed, 226 insertions(+) create mode 100644 drivers/fpga/ice40-spi.c diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index d614102..85ff429 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -13,6 +13,12 @@ config FPGA if FPGA +config FPGA_MGR_ICE40_SPI + tristate "Lattice iCE40 SPI" + depends on SPI + help + FPGA manager driver support for Lattice iCE40 FPGAs over SPI. + config FPGA_MGR_SOCFPGA tristate "Altera SOCFPGA FPGA Manager" depends on ARCH_SOCFPGA diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index 8d83fc6..adb5811 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -6,5 +6,6 @@ obj-$(CONFIG_FPGA) += fpga-mgr.o # FPGA Manager Drivers +obj-$(CONFIG_FPGA_MGR_ICE40_SPI) += ice40-spi.o obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o diff --git a/drivers/fpga/ice40-spi.c b/drivers/fpga/ice40-spi.c new file mode 100644 index 000..c39e6f0 --- /dev/null +++ b/drivers/fpga/ice40-spi.c @@ -0,0 +1,219 @@ +/* + * FPGA Manager Driver for Lattice iCE40. + * + * Copyright (c) 2016 Joel Holdsworth + * + * 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; version 2 of the License. + * + * This driver adds support to the FPGA manager for configuring the SRAM of + * Lattice iCE40 FPGAs through slave SPI. + */ + +#include +#include +#include +#include + +#define ICE40_SPI_FPGAMGR_RESET_DELAY 1 /* us (>200ns) */ +#define ICE40_SPI_FPGAMGR_HOUSEKEEPING_DELAY 1200 /* us */ + +#define ICE40_SPI_FPGAMGR_NUM_ACTIVATION_BITS 49 /* bits */ + +struct ice40_fpga_priv { + struct spi_device *dev; + struct gpio_desc *reset; + struct gpio_desc *cdone; +}; + +static enum fpga_mgr_states ice40_fpga_ops_state(struct fpga_manager *mgr) +{ + struct ice40_fpga_priv *priv = mgr->priv; + return gpiod_get_value(priv->cdone) ? FPGA_MGR_STATE_OPERATING : + FPGA_MGR_STATE_UNKNOWN; +} + +static int ice40_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags, +const char *buf, size_t count) +{ + struct ice40_fpga_priv *priv = mgr->priv; + struct spi_device *dev = priv->dev; + struct spi_message message; + int ret; + + if ((flags & FPGA_MGR_PARTIAL_RECONFIG)) { + dev_err(>dev, + "Partial reconfiguration is not supported\n"); + return -ENOTSUPP; + } + + /* Lock the bus, assert CRESET_B and SS_B and delay >200ns */ + ret = spi_bus_lock(dev->master); + if (ret) { + dev_err(>dev, "Failed to lock SPI bus, ret: %d\n", ret); + return ret; + } + + gpiod_set_value(priv->reset, 1); + + spi_message_init(); + spi_message_add_tail(&(struct spi_transfer){.cs_change = 1, + .delay_usecs = ICE40_SPI_FPGAMGR_RESET_DELAY}, ); + ret = spi_sync_locked(dev, ); + if (ret) { + dev_err(>dev,
[PATCH v5 3/3] fpga: Add support for Lattice iCE40 FPGAs
The Lattice iCE40 is a family of FPGAs with a minimalistic architecture and very regular structure, designed for low-cost, high-volume consumer and system applications. This patch adds support to the FPGA manager for configuring the SRAM of iCE40LM, iCE40LP, iCE40HX, iCE40 Ultra, iCE40 UltraLite and iCE40 UltraPlus devices, through slave SPI. The iCE40 family is notable because it is the first FPGA family to have complete reverse engineered bit-stream documentation for the iCE40LP and iCE40HX devices. Furthermore, there is now a Free Software Verilog synthesis tool-chain: the "IceStorm" tool-chain. This project is the work of Clifford Wolf, who is the maintainer of Yosys Verilog RTL synthesis framework, and Mathias Lasser, with notable contributions from "Cotton Seed", the main author of "arachne-pnr"; a place-and-route tool for iCE40 FPGAs. Having a Free Software synthesis tool-chain offers interesting opportunities for embedded devices that are able reconfigure themselves with open firmware that is generated on the device itself. For example a mobile device might have an application processor with an iCE40 FPGA attached, which implements slave devices, or through which the processor communicates with other devices through the FPGA fabric. A kernel driver for the iCE40 is useful, because in some cases, the FPGA may need to be configured before other devices can be accessed. An example of such a device is the icoBoard; a RaspberryPI HAT which features an iCE40HX8K with a 1 or 8 MBit SRAM and ports for Digilent-compatible PMOD modules. A PMOD module may contain a device with which the kernel communicates, via the FPGA. --- drivers/fpga/Kconfig | 6 ++ drivers/fpga/Makefile| 1 + drivers/fpga/ice40-spi.c | 219 +++ 3 files changed, 226 insertions(+) create mode 100644 drivers/fpga/ice40-spi.c diff --git a/drivers/fpga/Kconfig b/drivers/fpga/Kconfig index d614102..85ff429 100644 --- a/drivers/fpga/Kconfig +++ b/drivers/fpga/Kconfig @@ -13,6 +13,12 @@ config FPGA if FPGA +config FPGA_MGR_ICE40_SPI + tristate "Lattice iCE40 SPI" + depends on SPI + help + FPGA manager driver support for Lattice iCE40 FPGAs over SPI. + config FPGA_MGR_SOCFPGA tristate "Altera SOCFPGA FPGA Manager" depends on ARCH_SOCFPGA diff --git a/drivers/fpga/Makefile b/drivers/fpga/Makefile index 8d83fc6..adb5811 100644 --- a/drivers/fpga/Makefile +++ b/drivers/fpga/Makefile @@ -6,5 +6,6 @@ obj-$(CONFIG_FPGA) += fpga-mgr.o # FPGA Manager Drivers +obj-$(CONFIG_FPGA_MGR_ICE40_SPI) += ice40-spi.o obj-$(CONFIG_FPGA_MGR_SOCFPGA) += socfpga.o obj-$(CONFIG_FPGA_MGR_ZYNQ_FPGA) += zynq-fpga.o diff --git a/drivers/fpga/ice40-spi.c b/drivers/fpga/ice40-spi.c new file mode 100644 index 000..c39e6f0 --- /dev/null +++ b/drivers/fpga/ice40-spi.c @@ -0,0 +1,219 @@ +/* + * FPGA Manager Driver for Lattice iCE40. + * + * Copyright (c) 2016 Joel Holdsworth + * + * 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; version 2 of the License. + * + * This driver adds support to the FPGA manager for configuring the SRAM of + * Lattice iCE40 FPGAs through slave SPI. + */ + +#include +#include +#include +#include + +#define ICE40_SPI_FPGAMGR_RESET_DELAY 1 /* us (>200ns) */ +#define ICE40_SPI_FPGAMGR_HOUSEKEEPING_DELAY 1200 /* us */ + +#define ICE40_SPI_FPGAMGR_NUM_ACTIVATION_BITS 49 /* bits */ + +struct ice40_fpga_priv { + struct spi_device *dev; + struct gpio_desc *reset; + struct gpio_desc *cdone; +}; + +static enum fpga_mgr_states ice40_fpga_ops_state(struct fpga_manager *mgr) +{ + struct ice40_fpga_priv *priv = mgr->priv; + return gpiod_get_value(priv->cdone) ? FPGA_MGR_STATE_OPERATING : + FPGA_MGR_STATE_UNKNOWN; +} + +static int ice40_fpga_ops_write_init(struct fpga_manager *mgr, u32 flags, +const char *buf, size_t count) +{ + struct ice40_fpga_priv *priv = mgr->priv; + struct spi_device *dev = priv->dev; + struct spi_message message; + int ret; + + if ((flags & FPGA_MGR_PARTIAL_RECONFIG)) { + dev_err(>dev, + "Partial reconfiguration is not supported\n"); + return -ENOTSUPP; + } + + /* Lock the bus, assert CRESET_B and SS_B and delay >200ns */ + ret = spi_bus_lock(dev->master); + if (ret) { + dev_err(>dev, "Failed to lock SPI bus, ret: %d\n", ret); + return ret; + } + + gpiod_set_value(priv->reset, 1); + + spi_message_init(); + spi_message_add_tail(&(struct spi_transfer){.cs_change = 1, + .delay_usecs = ICE40_SPI_FPGAMGR_RESET_DELAY}, ); + ret = spi_sync_locked(dev, ); + if (ret) { + dev_err(>dev,
[PATCH v5 2/3] Documentation: Add binding document for Lattice iCE40 FPGA manager
--- .../bindings/fpga/lattice-ice40-fpga-mgr.txt| 21 + 1 file changed, 21 insertions(+) create mode 100644 Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt diff --git a/Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt b/Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt new file mode 100644 index 000..cb64184 --- /dev/null +++ b/Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt @@ -0,0 +1,21 @@ +Lattice iCE40 FPGA Manager + +Required properties: +- compatible: Should contain "lattice,ice40-fpga-mgr" +- reg: SPI chip select +- spi-max-frequency: Maximum SPI frequency (>=100, <=2500) +- cdone-gpios: GPIO input connected to CDONE pin +- reset-gpios: Active-low GPIO output connected to CRESET_B pin. Note + that unless the GPIO is held low during startup, the + FPGA will enter Master SPI mode and drive SCK with a + clock signal, potentially jamming other devices on the + bus until the firmware is loaded. + +Example: + ice40: ice40@0 { + compatible = "lattice,ice40-fpga-mgr"; + reg = <0>; + spi-max-frequency = <100>; + cdone-gpios = < 24 GPIO_ACTIVE_HIGH>; + creset_b-gpios = < 22 GPIO_ACTIVE_LOW>; + }; -- 2.7.4
Re: [PATCH 1/1] xen-netfront: do not cast grant table reference to signed short
Hi David and Jan, I did more testing on the code. Casting to either (long) or (unsigned long) would be fine. However, there is still an issue that ref is of type uint32_t and IS_ERR_VALUE((unsigned long)ref) would not return true when ref=-ENOSPC (or other error code). IS_ERR_VALUE((long)ref) would return false as well. The solution is to cast ref to (int) first as follows: - BUG_ON((signed short)ref < 0); + WARN_ON_ONCE(IS_ERR_VALUE((unsigned long)(int)ref)); David, I am very sorry for this error and I will be careful the next time. Would you please let me know if I should resend a new patch or an incremental based on previous one at https://git.kernel.org/cgit/linux/kernel/git/davem/net.git? Thank you very much! Dongli Zhang - Original Message - From: da...@davemloft.net To: dongli.zh...@oracle.com Cc: linux-kernel@vger.kernel.org, xen-de...@lists.xenproject.org, net...@vger.kernel.org, boris.ostrov...@oracle.com, david.vra...@citrix.com, jgr...@suse.com Sent: Tuesday, November 1, 2016 4:06:27 AM GMT +08:00 Beijing / Chongqing / Hong Kong / Urumqi Subject: Re: [PATCH 1/1] xen-netfront: do not cast grant table reference to signed short From: Dongli ZhangDate: Mon, 31 Oct 2016 13:38:29 +0800 > While grant reference is of type uint32_t, xen-netfront erroneously casts > it to signed short in BUG_ON(). > > This would lead to the xen domU panic during boot-up or migration when it > is attached with lots of paravirtual devices. > > Signed-off-by: Dongli Zhang Since this is consistent with how the macros in linux/err.h handle "is this an error" checks, this change looks good to me. Applied, thanks.
[PATCH v5 2/3] Documentation: Add binding document for Lattice iCE40 FPGA manager
--- .../bindings/fpga/lattice-ice40-fpga-mgr.txt| 21 + 1 file changed, 21 insertions(+) create mode 100644 Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt diff --git a/Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt b/Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt new file mode 100644 index 000..cb64184 --- /dev/null +++ b/Documentation/devicetree/bindings/fpga/lattice-ice40-fpga-mgr.txt @@ -0,0 +1,21 @@ +Lattice iCE40 FPGA Manager + +Required properties: +- compatible: Should contain "lattice,ice40-fpga-mgr" +- reg: SPI chip select +- spi-max-frequency: Maximum SPI frequency (>=100, <=2500) +- cdone-gpios: GPIO input connected to CDONE pin +- reset-gpios: Active-low GPIO output connected to CRESET_B pin. Note + that unless the GPIO is held low during startup, the + FPGA will enter Master SPI mode and drive SCK with a + clock signal, potentially jamming other devices on the + bus until the firmware is loaded. + +Example: + ice40: ice40@0 { + compatible = "lattice,ice40-fpga-mgr"; + reg = <0>; + spi-max-frequency = <100>; + cdone-gpios = < 24 GPIO_ACTIVE_HIGH>; + creset_b-gpios = < 22 GPIO_ACTIVE_LOW>; + }; -- 2.7.4
Re: [PATCH 1/1] xen-netfront: do not cast grant table reference to signed short
Hi David and Jan, I did more testing on the code. Casting to either (long) or (unsigned long) would be fine. However, there is still an issue that ref is of type uint32_t and IS_ERR_VALUE((unsigned long)ref) would not return true when ref=-ENOSPC (or other error code). IS_ERR_VALUE((long)ref) would return false as well. The solution is to cast ref to (int) first as follows: - BUG_ON((signed short)ref < 0); + WARN_ON_ONCE(IS_ERR_VALUE((unsigned long)(int)ref)); David, I am very sorry for this error and I will be careful the next time. Would you please let me know if I should resend a new patch or an incremental based on previous one at https://git.kernel.org/cgit/linux/kernel/git/davem/net.git? Thank you very much! Dongli Zhang - Original Message - From: da...@davemloft.net To: dongli.zh...@oracle.com Cc: linux-kernel@vger.kernel.org, xen-de...@lists.xenproject.org, net...@vger.kernel.org, boris.ostrov...@oracle.com, david.vra...@citrix.com, jgr...@suse.com Sent: Tuesday, November 1, 2016 4:06:27 AM GMT +08:00 Beijing / Chongqing / Hong Kong / Urumqi Subject: Re: [PATCH 1/1] xen-netfront: do not cast grant table reference to signed short From: Dongli Zhang Date: Mon, 31 Oct 2016 13:38:29 +0800 > While grant reference is of type uint32_t, xen-netfront erroneously casts > it to signed short in BUG_ON(). > > This would lead to the xen domU panic during boot-up or migration when it > is attached with lots of paravirtual devices. > > Signed-off-by: Dongli Zhang Since this is consistent with how the macros in linux/err.h handle "is this an error" checks, this change looks good to me. Applied, thanks.
[PATCH v5 1/3] of: Add vendor prefix for Lattice Semiconductor
From: Joel HoldsworthAcked-by: Rob Herring --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 1992aa9..d64a835 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -146,6 +146,7 @@ kosagi Sutajio Ko-Usagi PTE Ltd. kyoKyocera Corporation lacie LaCie lantiq Lantiq Semiconductor +latticeLattice Semiconductor lenovo Lenovo Group Ltd. lg LG Corporation linux Linux-specific binding -- 2.7.4
[PATCH v5 1/3] of: Add vendor prefix for Lattice Semiconductor
From: Joel Holdsworth Acked-by: Rob Herring --- Documentation/devicetree/bindings/vendor-prefixes.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 1992aa9..d64a835 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -146,6 +146,7 @@ kosagi Sutajio Ko-Usagi PTE Ltd. kyoKyocera Corporation lacie LaCie lantiq Lantiq Semiconductor +latticeLattice Semiconductor lenovo Lenovo Group Ltd. lg LG Corporation linux Linux-specific binding -- 2.7.4
Re: [PATCH] PM / Domains: check for negative return from of_count_phandle_with_args
On Wednesday, October 26, 2016 01:00:08 PM Pavel Machek wrote: > > --zhXaljGHf11kAtnf > Content-Type: text/plain; charset=us-ascii > Content-Disposition: inline > Content-Transfer-Encoding: quoted-printable > > On Tue 2016-10-25 11:14:40, Kevin Hilman wrote: > > Colin Kingwrites: > >=20 > > > From: Colin Ian King > > > > > > The return from of_count_phandle_with_args can be negative, so we > > > should avoid kcalloc of a negative count of genpd_power_stat structs > > > by sanity checking if count is zero or less. > > > > > > Signed-off-by: Colin Ian King > >=20 > > Acked-by: Kevin Hilman > > Acked-by: Pavel Machek Applied, thanks! Rafael
Re: [PATCH] PM / Domains: check for negative return from of_count_phandle_with_args
On Wednesday, October 26, 2016 01:00:08 PM Pavel Machek wrote: > > --zhXaljGHf11kAtnf > Content-Type: text/plain; charset=us-ascii > Content-Disposition: inline > Content-Transfer-Encoding: quoted-printable > > On Tue 2016-10-25 11:14:40, Kevin Hilman wrote: > > Colin King writes: > >=20 > > > From: Colin Ian King > > > > > > The return from of_count_phandle_with_args can be negative, so we > > > should avoid kcalloc of a negative count of genpd_power_stat structs > > > by sanity checking if count is zero or less. > > > > > > Signed-off-by: Colin Ian King > >=20 > > Acked-by: Kevin Hilman > > Acked-by: Pavel Machek Applied, thanks! Rafael
Re: [PATCH v2] console: use first console if stdout-path device doesn't appear
Sergey Senozhatskywrites: > On (10/31/16 15:50), Paul Burton wrote: > [..] >> Actually whilst this fixes the output in QEMU it has other problems. I'm >> still >> digging... > > I propose a revert of '05fd007e46296', so you guys can find the > problem and fix it, not being under 'rc3' pressure. Yeah I agree. The v2 fix doesn't work for me either. Paul are you OK with that? And if so are you happy to send a revert to Linus? cheers
Re: [PATCH v2] console: use first console if stdout-path device doesn't appear
Sergey Senozhatsky writes: > On (10/31/16 15:50), Paul Burton wrote: > [..] >> Actually whilst this fixes the output in QEMU it has other problems. I'm >> still >> digging... > > I propose a revert of '05fd007e46296', so you guys can find the > problem and fix it, not being under 'rc3' pressure. Yeah I agree. The v2 fix doesn't work for me either. Paul are you OK with that? And if so are you happy to send a revert to Linus? cheers
[PATCH] acer-wmi: setup accelerometer when machine has appropriate notify event
The accelerometer event relies on on the ACERWMID_EVENT_GUID notify. So, this patch changes the codes to setup accelerometer input device when detected ACERWMID_EVENT_GUID. It avoids that the accel input device created on every acer machines. In addition, patch adds a clearly parsing logic of accelerometer hid to acer_wmi_get_handle_cb callback function. It is positive matching the "SENR" name with "BST0001" device to avoid non-supported hardware. Reported-by: Bjørn MorkTested-by: Bjørn Mork Cc: Darren Hart Signed-off-by: Lee, Chun-Yi --- drivers/platform/x86/acer-wmi.c | 22 ++ 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 79d64ea..3bb3162 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -1808,11 +1808,24 @@ static int __init acer_wmi_enable_lm(void) return status; } +#define ACER_WMID_ACCEL_HID"BST0001" + static acpi_status __init acer_wmi_get_handle_cb(acpi_handle ah, u32 level, void *ctx, void **retval) { + struct acpi_device *dev; + + if (strcmp(ctx, "SENR")) { + if (acpi_bus_get_device(ah, )) + return AE_OK; + if (!strcmp(ACER_WMID_ACCEL_HID, acpi_device_hid(dev))) + return AE_OK; + } else + return AE_OK; + *(acpi_handle *)retval = ah; - return AE_OK; + + return AE_CTRL_TERMINATE; } static int __init acer_wmi_get_handle(const char *name, const char *prop, @@ -1839,7 +1852,7 @@ static int __init acer_wmi_accel_setup(void) { int err; - err = acer_wmi_get_handle("SENR", "BST0001", _handle); + err = acer_wmi_get_handle("SENR", ACER_WMID_ACCEL_HID, _handle); if (err) return err; @@ -2177,10 +2190,11 @@ static int __init acer_wmi_init(void) err = acer_wmi_input_setup(); if (err) return err; + err = acer_wmi_accel_setup(); + if (err) + return err; } - acer_wmi_accel_setup(); - err = platform_driver_register(_platform_driver); if (err) { pr_err("Unable to register platform driver\n"); -- 2.1.4
[PATCH] acer-wmi: setup accelerometer when machine has appropriate notify event
The accelerometer event relies on on the ACERWMID_EVENT_GUID notify. So, this patch changes the codes to setup accelerometer input device when detected ACERWMID_EVENT_GUID. It avoids that the accel input device created on every acer machines. In addition, patch adds a clearly parsing logic of accelerometer hid to acer_wmi_get_handle_cb callback function. It is positive matching the "SENR" name with "BST0001" device to avoid non-supported hardware. Reported-by: Bjørn Mork Tested-by: Bjørn Mork Cc: Darren Hart Signed-off-by: Lee, Chun-Yi --- drivers/platform/x86/acer-wmi.c | 22 ++ 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 79d64ea..3bb3162 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -1808,11 +1808,24 @@ static int __init acer_wmi_enable_lm(void) return status; } +#define ACER_WMID_ACCEL_HID"BST0001" + static acpi_status __init acer_wmi_get_handle_cb(acpi_handle ah, u32 level, void *ctx, void **retval) { + struct acpi_device *dev; + + if (strcmp(ctx, "SENR")) { + if (acpi_bus_get_device(ah, )) + return AE_OK; + if (!strcmp(ACER_WMID_ACCEL_HID, acpi_device_hid(dev))) + return AE_OK; + } else + return AE_OK; + *(acpi_handle *)retval = ah; - return AE_OK; + + return AE_CTRL_TERMINATE; } static int __init acer_wmi_get_handle(const char *name, const char *prop, @@ -1839,7 +1852,7 @@ static int __init acer_wmi_accel_setup(void) { int err; - err = acer_wmi_get_handle("SENR", "BST0001", _handle); + err = acer_wmi_get_handle("SENR", ACER_WMID_ACCEL_HID, _handle); if (err) return err; @@ -2177,10 +2190,11 @@ static int __init acer_wmi_init(void) err = acer_wmi_input_setup(); if (err) return err; + err = acer_wmi_accel_setup(); + if (err) + return err; } - acer_wmi_accel_setup(); - err = platform_driver_register(_platform_driver); if (err) { pr_err("Unable to register platform driver\n"); -- 2.1.4
[PATCH] acer-wmi: only supports AMW0_GUID1 on acer family
The AMW0_GUID1 wmi is not only found on Acer family but also other machines like Lenovo, Fujitsu and Medion. In the past days, acer-wmi driver handled those non-Acer machines by quirks list. But actually acer-wmi driver was loaded on any machines that have AMW0_GUID1. This behavior is strange because those machines should be supported by appropriate wmi drivers. e.g. fujitsu-laptop, ideapad-laptop. So, This patch adds the logic to check the machine that has AMW0_GUID1 should be in Acer/Packard Bell/Gateway white list. But, it still keeps the quirk list of those supported non-acer machines for backward compatible. Tested-by: Bjørn MorkCc: Darren Hart Signed-off-by: Lee, Chun-Yi --- drivers/platform/x86/acer-wmi.c | 56 + 1 file changed, 56 insertions(+) diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 3bb3162..734f0da 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -355,6 +355,32 @@ static const struct dmi_system_id acer_blacklist[] __initconst = { {} }; +static const struct dmi_system_id amw0_whitelist[] __initconst = { + { + .ident = "Acer", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + }, + }, + { + .ident = "Gateway", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Gateway"), + }, + }, + { + .ident = "Packard Bell", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Packard Bell"), + }, + }, + {} +}; + +/* + * This quirk table is only for Acer/Gateway/Packard Bell family + * that those machines are supported by acer-wmi driver. + */ static const struct dmi_system_id acer_quirks[] __initconst = { { .callback = dmi_matched, @@ -464,6 +490,17 @@ static const struct dmi_system_id acer_quirks[] __initconst = { }, .driver_data = _acer_travelmate_2490, }, + {} +}; + +/* + * This quirk list is for those non-acer machines that have AMW0_GUID1 + * but supported by acer-wmi in past days. Keeping this quirk list here + * is only for backward compatible. Please do not add new machine to + * here anymore. Those non-acer machines should be supported by + * appropriate wmi drivers. + */ +static const struct dmi_system_id non_acer_quirks[] __initconst = { { .callback = dmi_matched, .ident = "Fujitsu Siemens Amilo Li 1718", @@ -598,6 +635,7 @@ static void __init find_quirks(void) { if (!force_series) { dmi_check_system(acer_quirks); + dmi_check_system(non_acer_quirks); } else if (force_series == 2490) { quirks = _acer_travelmate_2490; } @@ -2121,6 +2159,24 @@ static int __init acer_wmi_init(void) find_quirks(); /* +* The AMW0_GUID1 wmi is not only found on Acer family but also other +* machines like Lenovo, Fujitsu and Medion. In the past days, +* acer-wmi driver handled those non-Acer machines by quirks list. +* But actually acer-wmi driver was loaded on any machines that have +* AMW0_GUID1. This behavior is strange because those machines should +* be supported by appropriate wmi drivers. e.g. fujitsu-laptop, +* ideapad-laptop. So, here checks the machine that has AMW0_GUID1 +* should be in Acer/Gateway/Packard Bell white list, or it's already +* in the past quirk list. +*/ + if (wmi_has_guid(AMW0_GUID1) && + !dmi_check_system(amw0_whitelist) && + quirks == _unknown) { + pr_err("Unsupported machine has AMW0_GUID1, unable to load\n"); + return -ENODEV; + } + + /* * Detect which ACPI-WMI interface we're using. */ if (wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1)) -- 2.1.4
[PATCH] acer-wmi: only supports AMW0_GUID1 on acer family
The AMW0_GUID1 wmi is not only found on Acer family but also other machines like Lenovo, Fujitsu and Medion. In the past days, acer-wmi driver handled those non-Acer machines by quirks list. But actually acer-wmi driver was loaded on any machines that have AMW0_GUID1. This behavior is strange because those machines should be supported by appropriate wmi drivers. e.g. fujitsu-laptop, ideapad-laptop. So, This patch adds the logic to check the machine that has AMW0_GUID1 should be in Acer/Packard Bell/Gateway white list. But, it still keeps the quirk list of those supported non-acer machines for backward compatible. Tested-by: Bjørn Mork Cc: Darren Hart Signed-off-by: Lee, Chun-Yi --- drivers/platform/x86/acer-wmi.c | 56 + 1 file changed, 56 insertions(+) diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 3bb3162..734f0da 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -355,6 +355,32 @@ static const struct dmi_system_id acer_blacklist[] __initconst = { {} }; +static const struct dmi_system_id amw0_whitelist[] __initconst = { + { + .ident = "Acer", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + }, + }, + { + .ident = "Gateway", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Gateway"), + }, + }, + { + .ident = "Packard Bell", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Packard Bell"), + }, + }, + {} +}; + +/* + * This quirk table is only for Acer/Gateway/Packard Bell family + * that those machines are supported by acer-wmi driver. + */ static const struct dmi_system_id acer_quirks[] __initconst = { { .callback = dmi_matched, @@ -464,6 +490,17 @@ static const struct dmi_system_id acer_quirks[] __initconst = { }, .driver_data = _acer_travelmate_2490, }, + {} +}; + +/* + * This quirk list is for those non-acer machines that have AMW0_GUID1 + * but supported by acer-wmi in past days. Keeping this quirk list here + * is only for backward compatible. Please do not add new machine to + * here anymore. Those non-acer machines should be supported by + * appropriate wmi drivers. + */ +static const struct dmi_system_id non_acer_quirks[] __initconst = { { .callback = dmi_matched, .ident = "Fujitsu Siemens Amilo Li 1718", @@ -598,6 +635,7 @@ static void __init find_quirks(void) { if (!force_series) { dmi_check_system(acer_quirks); + dmi_check_system(non_acer_quirks); } else if (force_series == 2490) { quirks = _acer_travelmate_2490; } @@ -2121,6 +2159,24 @@ static int __init acer_wmi_init(void) find_quirks(); /* +* The AMW0_GUID1 wmi is not only found on Acer family but also other +* machines like Lenovo, Fujitsu and Medion. In the past days, +* acer-wmi driver handled those non-Acer machines by quirks list. +* But actually acer-wmi driver was loaded on any machines that have +* AMW0_GUID1. This behavior is strange because those machines should +* be supported by appropriate wmi drivers. e.g. fujitsu-laptop, +* ideapad-laptop. So, here checks the machine that has AMW0_GUID1 +* should be in Acer/Gateway/Packard Bell white list, or it's already +* in the past quirk list. +*/ + if (wmi_has_guid(AMW0_GUID1) && + !dmi_check_system(amw0_whitelist) && + quirks == _unknown) { + pr_err("Unsupported machine has AMW0_GUID1, unable to load\n"); + return -ENODEV; + } + + /* * Detect which ACPI-WMI interface we're using. */ if (wmi_has_guid(AMW0_GUID1) && wmi_has_guid(WMID_GUID1)) -- 2.1.4
Re: [PATCH 00/12] xen: add common function for reading optional value
On 31/10/16 18:08, David Miller wrote: > From: Juergen Gross> Date: Mon, 31 Oct 2016 17:48:18 +0100 > >> There are multiple instances of code reading an optional unsigned >> parameter from Xenstore via xenbus_scanf(). Instead of repeating the >> same code over and over add a service function doing the job and >> replace the call of xenbus_scanf() with the call of the new function >> where appropriate. > > As this seems to be a series that will go through some tree other > than mine, I assume the networking bits will be taken care of that > way. > If accepted I expect this series to go through the Xen tree. Juergen
Re: [PATCH 00/12] xen: add common function for reading optional value
On 31/10/16 18:08, David Miller wrote: > From: Juergen Gross > Date: Mon, 31 Oct 2016 17:48:18 +0100 > >> There are multiple instances of code reading an optional unsigned >> parameter from Xenstore via xenbus_scanf(). Instead of repeating the >> same code over and over add a service function doing the job and >> replace the call of xenbus_scanf() with the call of the new function >> where appropriate. > > As this seems to be a series that will go through some tree other > than mine, I assume the networking bits will be taken care of that > way. > If accepted I expect this series to go through the Xen tree. Juergen
Re: [RESEND PATCH 1/2] PM / sleep: print function name of callbacks
On Wednesday, October 19, 2016 05:26:09 PM Brian Norris wrote: > From: Douglas Anderson> > The printouts writen to the logs by suspend can be a bit opaque: it can > be hard to track them down to the actual function called. You might > see: > > calling rfkill1+ @ 19473, parent: phy0 > call rfkill1+ returned 0 after 1 usecs > calling phy0+ @ 19473, parent: mmc2:0001:1 > call phy0+ returned 0 after 19 usecs > > It's a bit hard to know what's actually happening. Instead, it's nice > to see: > > calling rfkill1+ @ 15793, parent: phy0, cb: rfkill_suspend > call rfkill1+ returned 0 after 1 usecs > calling phy0+ @ 15793, parent: mmc2:0001:1, cb: wiphy_suspend [cfg80211] > call phy0+ returned 0 after 7 usecs > > That makes it very obvious what's going on. It also has the nice side > effect of making the suspend/resume spew a little more obvious, since > many resume functions have the word "resume" in the name: > > calling phy0+ @ 15793, parent: mmc2:0001:1, cb: wiphy_resume [cfg80211] > call phy0+ returned 0 after 12 usecs > calling rfkill1+ @ 15793, parent: phy0, cb: rfkill_resume > call rfkill1+ returned 0 after 1 usecs > > Signed-off-by: Douglas Anderson > Acked-by: Pavel Machek > Signed-off-by: Brian Norris Any reason why you need to rely on the initcall_debug stuff instead of using the tracepoints we have there (for exactly the reason why you are pushing this patch)? Thanks, Rafael
Re: [RESEND PATCH 1/2] PM / sleep: print function name of callbacks
On Wednesday, October 19, 2016 05:26:09 PM Brian Norris wrote: > From: Douglas Anderson > > The printouts writen to the logs by suspend can be a bit opaque: it can > be hard to track them down to the actual function called. You might > see: > > calling rfkill1+ @ 19473, parent: phy0 > call rfkill1+ returned 0 after 1 usecs > calling phy0+ @ 19473, parent: mmc2:0001:1 > call phy0+ returned 0 after 19 usecs > > It's a bit hard to know what's actually happening. Instead, it's nice > to see: > > calling rfkill1+ @ 15793, parent: phy0, cb: rfkill_suspend > call rfkill1+ returned 0 after 1 usecs > calling phy0+ @ 15793, parent: mmc2:0001:1, cb: wiphy_suspend [cfg80211] > call phy0+ returned 0 after 7 usecs > > That makes it very obvious what's going on. It also has the nice side > effect of making the suspend/resume spew a little more obvious, since > many resume functions have the word "resume" in the name: > > calling phy0+ @ 15793, parent: mmc2:0001:1, cb: wiphy_resume [cfg80211] > call phy0+ returned 0 after 12 usecs > calling rfkill1+ @ 15793, parent: phy0, cb: rfkill_resume > call rfkill1+ returned 0 after 1 usecs > > Signed-off-by: Douglas Anderson > Acked-by: Pavel Machek > Signed-off-by: Brian Norris Any reason why you need to rely on the initcall_debug stuff instead of using the tracepoints we have there (for exactly the reason why you are pushing this patch)? Thanks, Rafael
Re: [PATCH v2 2/2] PM / sleep: don't suspend parent when async child suspend_{noirq,late} fails
On Thursday, October 27, 2016 09:05:34 AM Brian Norris wrote: > Consider two devices, A and B, where B is a child of A, and B utilizes > asynchronous suspend (it does not matter whether A is sync or async). If > B fails to suspend_noirq() or suspend_late(), or is interrupted by a > wakeup (pm_wakeup_pending()), then it aborts and sets the async_error > variable. However, device A does not (immediately) check the async_error > variable; it may continue to run its own suspend_noirq()/suspend_late() > callback. This is bad. > > We can resolve this problem by checking the async_error flag after > waiting for children to suspend, using the same logic for the noirq and > late suspend cases as we already do for __device_suspend(). > > It's easy to observe this erroneous behavior by, for example, forcing a > device to sleep a bit in its suspend_noirq() (to ensure the parent is > waiting for the child to complete), then return an error, and watch the > parent suspend_noirq() still get called. (Or similarly, fake a wakeup > event at the right (or is it wrong?) time.) > > Fixes: de377b397272 ("PM / sleep: Asynchronous threads for suspend_late") > Fixes: 28b6fd6e3779 ("PM / sleep: Asynchronous threads for suspend_noirq") > Reported-by: Jeffy Chen> Signed-off-by: Brian Norris > Reviewed-by: Dmitry Torokhov > --- > v2: s/early/late/ in commit message > > drivers/base/power/main.c | 6 ++ > 1 file changed, 6 insertions(+) > > diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c > index c58563581345..eaf6b53463a5 100644 > --- a/drivers/base/power/main.c > +++ b/drivers/base/power/main.c > @@ -1040,6 +1040,9 @@ static int __device_suspend_noirq(struct device *dev, > pm_message_t state, bool a > > dpm_wait_for_children(dev, async); > > + if (async_error) > + goto Complete; > + This is a second chech for async_error in this routine and is the first one really needed after adding this? > if (dev->pm_domain) { > info = "noirq power domain "; > callback = pm_noirq_op(>pm_domain->ops, state); > @@ -1187,6 +1190,9 @@ static int __device_suspend_late(struct device *dev, > pm_message_t state, bool as > > dpm_wait_for_children(dev, async); > > + if (async_error) > + goto Complete; > + Same question. > if (dev->pm_domain) { > info = "late power domain "; > callback = pm_late_early_op(>pm_domain->ops, state); > Thanks, Rafael
Re: [PATCH v2 2/2] PM / sleep: don't suspend parent when async child suspend_{noirq,late} fails
On Thursday, October 27, 2016 09:05:34 AM Brian Norris wrote: > Consider two devices, A and B, where B is a child of A, and B utilizes > asynchronous suspend (it does not matter whether A is sync or async). If > B fails to suspend_noirq() or suspend_late(), or is interrupted by a > wakeup (pm_wakeup_pending()), then it aborts and sets the async_error > variable. However, device A does not (immediately) check the async_error > variable; it may continue to run its own suspend_noirq()/suspend_late() > callback. This is bad. > > We can resolve this problem by checking the async_error flag after > waiting for children to suspend, using the same logic for the noirq and > late suspend cases as we already do for __device_suspend(). > > It's easy to observe this erroneous behavior by, for example, forcing a > device to sleep a bit in its suspend_noirq() (to ensure the parent is > waiting for the child to complete), then return an error, and watch the > parent suspend_noirq() still get called. (Or similarly, fake a wakeup > event at the right (or is it wrong?) time.) > > Fixes: de377b397272 ("PM / sleep: Asynchronous threads for suspend_late") > Fixes: 28b6fd6e3779 ("PM / sleep: Asynchronous threads for suspend_noirq") > Reported-by: Jeffy Chen > Signed-off-by: Brian Norris > Reviewed-by: Dmitry Torokhov > --- > v2: s/early/late/ in commit message > > drivers/base/power/main.c | 6 ++ > 1 file changed, 6 insertions(+) > > diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c > index c58563581345..eaf6b53463a5 100644 > --- a/drivers/base/power/main.c > +++ b/drivers/base/power/main.c > @@ -1040,6 +1040,9 @@ static int __device_suspend_noirq(struct device *dev, > pm_message_t state, bool a > > dpm_wait_for_children(dev, async); > > + if (async_error) > + goto Complete; > + This is a second chech for async_error in this routine and is the first one really needed after adding this? > if (dev->pm_domain) { > info = "noirq power domain "; > callback = pm_noirq_op(>pm_domain->ops, state); > @@ -1187,6 +1190,9 @@ static int __device_suspend_late(struct device *dev, > pm_message_t state, bool as > > dpm_wait_for_children(dev, async); > > + if (async_error) > + goto Complete; > + Same question. > if (dev->pm_domain) { > info = "late power domain "; > callback = pm_late_early_op(>pm_domain->ops, state); > Thanks, Rafael
Re: [PATCH v2 0/3] powernv:stop: Use psscr_val,mask provided by firmware
On Thursday, October 27, 2016 02:05:04 PM Gautham R. Shenoy wrote: > From: "Gautham R. Shenoy"> > Hi, > > This is the second iteration of the patchset to use the psscr_val and > psscr_mask provided by the firmware for each of the stop states. > > The previous version can be found here: > https://lkml.org/lkml/2016/9/29/45 > > The main changes in this version are: > > 1) Add a helper function in powernv-cpuidle.c to help initialize the >powernv_states cpuidle table. > > 2) Handle the older firmware which populates only the Requested Level >(RL) fields of the psscr and psscr_mask in the device tree. This >patchset ensures that in the presence of the older firmware, the >other fields of PSSCR are initalized to sane default values. > > > Synopsis > == > In the current implementation, the code for ISA v3.0 stop > implementation has a couple of shortcomings. > > a) The code hand-codes the values for ESL,EC,TR,MTL bits of PSSCR and >uses only the RL field from the firmware. While this is not >incorrect, since the hand-coded values are legitimate, it is not a >very flexible design since the firmware has the capability to >communicate these values via the "ibm,cpu-idle-state-psscr" and >"ibm,cpu-idle-state-psscr-mask" properties. In case where the >firmware provides values for these fields that is different from >the hand-coded values, the current code will not work as intended. > > b) Due to issue a), the current code assumes that ESL=EC=1 for all the >stop states and hence the wakeup from the stop instruction will >happen at 0x100, the system-reset vector. However, the ISA v3.0 >allows the ESL=EC=0 behaviour where the corresponding stop-state >loses no state and wakes up from the subsequent instruction. The >current code doesn't handle this case. > > This patch series addresses these issues. > > The first patch in the series renames the existing > IDLE_STATE_ENTER_SEQ macro to IDLE_STATE_ENTER_SEQ_NORET. It reuses > the name IDLE_STATE_ENTER_SEQ for entering into stop-states which wake > up at the subsequent instruction. > > The second patch adds a helper function in cpuidle-powernv.c for > initializing entries of the powernv_states[] table that is passed to > the cpu-idle core. This eliminates some of the code duplication in the > function that discovers and initializes the stop states. > > The third patch in the series fixes issues a) and b) by ensuring that > the psscr-value and the psscr-mask provided by the firmware are what > will be used to set a particular stop state. It also adds support for > handling wake-up from stop states which were entered with ESL=EC=0. > > The third patch also handles the older firmware which sets only the > Requested Level (RL) field in the psscr and psscr-mask exposed in the > device tree. In the presence of such older firmware, this patch will > set the default sane values for for remaining PSSCR fields (i.e PSLL, > MTL, ESL, EC, and TR). > > The skiboot patch populates all the relevant fields in the PSSCR > values and the mask for all the stop states can be found here: > https://lists.ozlabs.org/pipermail/skiboot/2016-September/004869.html > > The patches are based on top of > git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git fixes > > Gautham R. Shenoy (3): > powernv:idle: Add IDLE_STATE_ENTER_SEQ_NORET macro > cpuidle:powernv: Add helper function to populate powernv idle states. > powernv: Pass PSSCR value and mask to power9_idle_stop OK I need someone to review this for me. Thanks, Rafael
Re: [PATCH v2 0/3] powernv:stop: Use psscr_val,mask provided by firmware
On Thursday, October 27, 2016 02:05:04 PM Gautham R. Shenoy wrote: > From: "Gautham R. Shenoy" > > Hi, > > This is the second iteration of the patchset to use the psscr_val and > psscr_mask provided by the firmware for each of the stop states. > > The previous version can be found here: > https://lkml.org/lkml/2016/9/29/45 > > The main changes in this version are: > > 1) Add a helper function in powernv-cpuidle.c to help initialize the >powernv_states cpuidle table. > > 2) Handle the older firmware which populates only the Requested Level >(RL) fields of the psscr and psscr_mask in the device tree. This >patchset ensures that in the presence of the older firmware, the >other fields of PSSCR are initalized to sane default values. > > > Synopsis > == > In the current implementation, the code for ISA v3.0 stop > implementation has a couple of shortcomings. > > a) The code hand-codes the values for ESL,EC,TR,MTL bits of PSSCR and >uses only the RL field from the firmware. While this is not >incorrect, since the hand-coded values are legitimate, it is not a >very flexible design since the firmware has the capability to >communicate these values via the "ibm,cpu-idle-state-psscr" and >"ibm,cpu-idle-state-psscr-mask" properties. In case where the >firmware provides values for these fields that is different from >the hand-coded values, the current code will not work as intended. > > b) Due to issue a), the current code assumes that ESL=EC=1 for all the >stop states and hence the wakeup from the stop instruction will >happen at 0x100, the system-reset vector. However, the ISA v3.0 >allows the ESL=EC=0 behaviour where the corresponding stop-state >loses no state and wakes up from the subsequent instruction. The >current code doesn't handle this case. > > This patch series addresses these issues. > > The first patch in the series renames the existing > IDLE_STATE_ENTER_SEQ macro to IDLE_STATE_ENTER_SEQ_NORET. It reuses > the name IDLE_STATE_ENTER_SEQ for entering into stop-states which wake > up at the subsequent instruction. > > The second patch adds a helper function in cpuidle-powernv.c for > initializing entries of the powernv_states[] table that is passed to > the cpu-idle core. This eliminates some of the code duplication in the > function that discovers and initializes the stop states. > > The third patch in the series fixes issues a) and b) by ensuring that > the psscr-value and the psscr-mask provided by the firmware are what > will be used to set a particular stop state. It also adds support for > handling wake-up from stop states which were entered with ESL=EC=0. > > The third patch also handles the older firmware which sets only the > Requested Level (RL) field in the psscr and psscr-mask exposed in the > device tree. In the presence of such older firmware, this patch will > set the default sane values for for remaining PSSCR fields (i.e PSLL, > MTL, ESL, EC, and TR). > > The skiboot patch populates all the relevant fields in the PSSCR > values and the mask for all the stop states can be found here: > https://lists.ozlabs.org/pipermail/skiboot/2016-September/004869.html > > The patches are based on top of > git://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git fixes > > Gautham R. Shenoy (3): > powernv:idle: Add IDLE_STATE_ENTER_SEQ_NORET macro > cpuidle:powernv: Add helper function to populate powernv idle states. > powernv: Pass PSSCR value and mask to power9_idle_stop OK I need someone to review this for me. Thanks, Rafael
Re: [PATCH 1/6] staging: iio: set proper supply name to devm_regulator_get()
On Mon, Oct 31, 2016 at 10:04 AM, Eva Rachel Retuyawrote: > The name passed to devm_regulator_get() should match the name of the > supply as specified in the device datasheet. This makes it clear what > power supply is being referred to in case of presence of other > regulators. > > Currently, the supply name specified on the affected devices is 'vcc'. > Use lowercase version of the datasheet name to specify the supply > voltage. > Aren't we possibly breaking current device tree definitions that people may have? We should still check the old name after the new datasheet name in my opinion. > Suggested-by: Lars-Peter Clausen > Signed-off-by: Eva Rachel Retuya > --- > drivers/staging/iio/adc/ad7192.c| 2 +- > drivers/staging/iio/adc/ad7780.c| 2 +- > drivers/staging/iio/frequency/ad9832.c | 2 +- > drivers/staging/iio/frequency/ad9834.c | 2 +- > drivers/staging/iio/impedance-analyzer/ad5933.c | 2 +- > 5 files changed, 5 insertions(+), 5 deletions(-) > > diff --git a/drivers/staging/iio/adc/ad7192.c > b/drivers/staging/iio/adc/ad7192.c > index bfa12ce..41fb32d 100644 > --- a/drivers/staging/iio/adc/ad7192.c > +++ b/drivers/staging/iio/adc/ad7192.c > @@ -633,7 +633,7 @@ static int ad7192_probe(struct spi_device *spi) > > st = iio_priv(indio_dev); > > - st->reg = devm_regulator_get(>dev, "vcc"); > + st->reg = devm_regulator_get(>dev, "avdd"); > if (!IS_ERR(st->reg)) { > ret = regulator_enable(st->reg); > if (ret) > diff --git a/drivers/staging/iio/adc/ad7780.c > b/drivers/staging/iio/adc/ad7780.c > index c9a0c2a..a88236e 100644 > --- a/drivers/staging/iio/adc/ad7780.c > +++ b/drivers/staging/iio/adc/ad7780.c > @@ -173,7 +173,7 @@ static int ad7780_probe(struct spi_device *spi) > > ad_sd_init(>sd, indio_dev, spi, _sigma_delta_info); > > - st->reg = devm_regulator_get(>dev, "vcc"); > + st->reg = devm_regulator_get(>dev, "avdd"); > if (!IS_ERR(st->reg)) { > ret = regulator_enable(st->reg); > if (ret) > diff --git a/drivers/staging/iio/frequency/ad9832.c > b/drivers/staging/iio/frequency/ad9832.c > index 358400b..744c8ee 100644 > --- a/drivers/staging/iio/frequency/ad9832.c > +++ b/drivers/staging/iio/frequency/ad9832.c > @@ -212,7 +212,7 @@ static int ad9832_probe(struct spi_device *spi) > return -ENODEV; > } > > - reg = devm_regulator_get(>dev, "vcc"); > + reg = devm_regulator_get(>dev, "avdd"); > if (!IS_ERR(reg)) { > ret = regulator_enable(reg); > if (ret) > diff --git a/drivers/staging/iio/frequency/ad9834.c > b/drivers/staging/iio/frequency/ad9834.c > index 6366216..ca3cea6 100644 > --- a/drivers/staging/iio/frequency/ad9834.c > +++ b/drivers/staging/iio/frequency/ad9834.c > @@ -329,7 +329,7 @@ static int ad9834_probe(struct spi_device *spi) > return -ENODEV; > } > > - reg = devm_regulator_get(>dev, "vcc"); > + reg = devm_regulator_get(>dev, "avdd"); > if (!IS_ERR(reg)) { > ret = regulator_enable(reg); > if (ret) > diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c > b/drivers/staging/iio/impedance-analyzer/ad5933.c > index 5eecf1c..62f61bc 100644 > --- a/drivers/staging/iio/impedance-analyzer/ad5933.c > +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c > @@ -723,7 +723,7 @@ static int ad5933_probe(struct i2c_client *client, > if (!pdata) > pdata = _default_pdata; > > - st->reg = devm_regulator_get(>dev, "vcc"); > + st->reg = devm_regulator_get(>dev, "vdd"); > if (!IS_ERR(st->reg)) { > ret = regulator_enable(st->reg); > if (ret) > -- > 2.7.4 >
Re: [PATCH 1/6] staging: iio: set proper supply name to devm_regulator_get()
On Mon, Oct 31, 2016 at 10:04 AM, Eva Rachel Retuya wrote: > The name passed to devm_regulator_get() should match the name of the > supply as specified in the device datasheet. This makes it clear what > power supply is being referred to in case of presence of other > regulators. > > Currently, the supply name specified on the affected devices is 'vcc'. > Use lowercase version of the datasheet name to specify the supply > voltage. > Aren't we possibly breaking current device tree definitions that people may have? We should still check the old name after the new datasheet name in my opinion. > Suggested-by: Lars-Peter Clausen > Signed-off-by: Eva Rachel Retuya > --- > drivers/staging/iio/adc/ad7192.c| 2 +- > drivers/staging/iio/adc/ad7780.c| 2 +- > drivers/staging/iio/frequency/ad9832.c | 2 +- > drivers/staging/iio/frequency/ad9834.c | 2 +- > drivers/staging/iio/impedance-analyzer/ad5933.c | 2 +- > 5 files changed, 5 insertions(+), 5 deletions(-) > > diff --git a/drivers/staging/iio/adc/ad7192.c > b/drivers/staging/iio/adc/ad7192.c > index bfa12ce..41fb32d 100644 > --- a/drivers/staging/iio/adc/ad7192.c > +++ b/drivers/staging/iio/adc/ad7192.c > @@ -633,7 +633,7 @@ static int ad7192_probe(struct spi_device *spi) > > st = iio_priv(indio_dev); > > - st->reg = devm_regulator_get(>dev, "vcc"); > + st->reg = devm_regulator_get(>dev, "avdd"); > if (!IS_ERR(st->reg)) { > ret = regulator_enable(st->reg); > if (ret) > diff --git a/drivers/staging/iio/adc/ad7780.c > b/drivers/staging/iio/adc/ad7780.c > index c9a0c2a..a88236e 100644 > --- a/drivers/staging/iio/adc/ad7780.c > +++ b/drivers/staging/iio/adc/ad7780.c > @@ -173,7 +173,7 @@ static int ad7780_probe(struct spi_device *spi) > > ad_sd_init(>sd, indio_dev, spi, _sigma_delta_info); > > - st->reg = devm_regulator_get(>dev, "vcc"); > + st->reg = devm_regulator_get(>dev, "avdd"); > if (!IS_ERR(st->reg)) { > ret = regulator_enable(st->reg); > if (ret) > diff --git a/drivers/staging/iio/frequency/ad9832.c > b/drivers/staging/iio/frequency/ad9832.c > index 358400b..744c8ee 100644 > --- a/drivers/staging/iio/frequency/ad9832.c > +++ b/drivers/staging/iio/frequency/ad9832.c > @@ -212,7 +212,7 @@ static int ad9832_probe(struct spi_device *spi) > return -ENODEV; > } > > - reg = devm_regulator_get(>dev, "vcc"); > + reg = devm_regulator_get(>dev, "avdd"); > if (!IS_ERR(reg)) { > ret = regulator_enable(reg); > if (ret) > diff --git a/drivers/staging/iio/frequency/ad9834.c > b/drivers/staging/iio/frequency/ad9834.c > index 6366216..ca3cea6 100644 > --- a/drivers/staging/iio/frequency/ad9834.c > +++ b/drivers/staging/iio/frequency/ad9834.c > @@ -329,7 +329,7 @@ static int ad9834_probe(struct spi_device *spi) > return -ENODEV; > } > > - reg = devm_regulator_get(>dev, "vcc"); > + reg = devm_regulator_get(>dev, "avdd"); > if (!IS_ERR(reg)) { > ret = regulator_enable(reg); > if (ret) > diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c > b/drivers/staging/iio/impedance-analyzer/ad5933.c > index 5eecf1c..62f61bc 100644 > --- a/drivers/staging/iio/impedance-analyzer/ad5933.c > +++ b/drivers/staging/iio/impedance-analyzer/ad5933.c > @@ -723,7 +723,7 @@ static int ad5933_probe(struct i2c_client *client, > if (!pdata) > pdata = _default_pdata; > > - st->reg = devm_regulator_get(>dev, "vcc"); > + st->reg = devm_regulator_get(>dev, "vdd"); > if (!IS_ERR(st->reg)) { > ret = regulator_enable(st->reg); > if (ret) > -- > 2.7.4 >
Re: [PATCH v10 01/19] vfio: Mediated device Core driver
On Tue, 01 Nov 2016 11:08:15 +0800 Jike Songwrote: > On 10/27/2016 05:29 AM, Kirti Wankhede wrote: > > +static int mdev_attach_iommu(struct mdev_device *mdev) > > +{ > > + int ret; > > + struct iommu_group *group; > > + > > + group = iommu_group_alloc(); > > + if (IS_ERR(group)) > > + return PTR_ERR(group); > > Maybe I overthought, but where the iommu_group is released? On successful > return you already have a ref, I didn't find an iommu_group_put after that. ... > > + > > + ret = iommu_group_add_device(group, >dev); > > + if (ret) > > + goto attach_fail; > > + > > + dev_info(>dev, "MDEV: group_id = %d\n", > > +iommu_group_id(group)); > > +attach_fail: > > + iommu_group_put(group); > > + return ret; > > +} > > + > > +static void mdev_detach_iommu(struct mdev_device *mdev) > > +{ > > + iommu_group_remove_device(>dev); Here. Adding a device to the group takes a group reference so we can 'put' the group to release the reference from the alloc as soon as a device is added. When we remove the device, that reference is removed and this should result in a release of the group if all other references are balanced. Thanks, Alex > > + dev_info(>dev, "MDEV: detaching iommu\n"); > > +} > > + >
Re: [PATCH v10 01/19] vfio: Mediated device Core driver
On Tue, 01 Nov 2016 11:08:15 +0800 Jike Song wrote: > On 10/27/2016 05:29 AM, Kirti Wankhede wrote: > > +static int mdev_attach_iommu(struct mdev_device *mdev) > > +{ > > + int ret; > > + struct iommu_group *group; > > + > > + group = iommu_group_alloc(); > > + if (IS_ERR(group)) > > + return PTR_ERR(group); > > Maybe I overthought, but where the iommu_group is released? On successful > return you already have a ref, I didn't find an iommu_group_put after that. ... > > + > > + ret = iommu_group_add_device(group, >dev); > > + if (ret) > > + goto attach_fail; > > + > > + dev_info(>dev, "MDEV: group_id = %d\n", > > +iommu_group_id(group)); > > +attach_fail: > > + iommu_group_put(group); > > + return ret; > > +} > > + > > +static void mdev_detach_iommu(struct mdev_device *mdev) > > +{ > > + iommu_group_remove_device(>dev); Here. Adding a device to the group takes a group reference so we can 'put' the group to release the reference from the alloc as soon as a device is added. When we remove the device, that reference is removed and this should result in a release of the group if all other references are balanced. Thanks, Alex > > + dev_info(>dev, "MDEV: detaching iommu\n"); > > +} > > + >
Re: [PATCH v6 0/5] Functional dependencies between devices
On Monday, October 31, 2016 11:47:03 AM Greg Kroah-Hartman wrote: > On Sun, Oct 30, 2016 at 05:22:13PM +0100, Rafael J. Wysocki wrote: > > Hi, > > > > Let me quote from the previous intro messages for this series first: > > > > > > Time for another update. :-) > > > > > > > > Fewer changes this time, mostly to address issues found by Lukas and > > > > Marek. > > > > > > > > The most significant one is to make device_link_add() cope with the case > > > > when > > > > the consumer device has not been registered yet when it is called. The > > > > supplier device still is required to be registered and the function will > > > > return NULL if that is not the case. > > > > > > > > Another significant change is in patch [4/5] that now makes the core > > > > apply > > > > pm_runtime_get_sync()/pm_runtime_put() to supplier devices around the > > > > probing of a consumer one (in analogy with the parent). > > > > > > One more update after some conversations during LinuxCon Europe. > > > > > > The main point was to make it possible for device_link_add() to figure out > > > the initial state of the link instead of expecting the caller to provide > > > it > > > which might not be reliable enough in general. > > > > > > In this version device_link_add() takes three arguments, the supplier and > > > consumer pointers and flags and it sets the correct initial state of the > > > link automatically (unless invoked with the "stateless" flag, of course). > > > The cost is one additional field in struct device (I moved all of the > > > links-related fields in struct device to a separate sub-structure while at > > > it) to track the "driver presence status" of the device (to be used by > > > device_link_add()). > > > > > > In addition to that, the links list walks in the core.c and dd.c code are > > > under the device links mutex now, so the iternal link spinlock is not > > > needed > > > any more and I have renamed symbols to distinguish between flags, link > > > states and device "driver presence statuses". > > > > The most significant change in this revision with respect to the previous > > one is > > related to the fact that SRCU is not available on some architectures, so the > > code falls back to using an RW semaphore for synchronization if SRCU is not > > there. Fortunately, the code changes needed for that turned out to be quite > > straightforward and confined to the second patch. > > > > Apart from this, the flags are defined using BIT(x) now (instead of open > > coding > > the latter in the flag definitions). > > > > Updated is mostly patch [2/5]. Patches [1,3,5/5] have not changed (except > > for > > trivial rebasing) and patch [4/5] needed to be refreshed on top of the > > modified > > [2/5]. > > > > FWIW, I've run the series through 0-day which has not reported any problems > > with it. > > Great, they are now applied to my tree, thanks again for doing this > work. Thanks!
Re: [PATCH v6 0/5] Functional dependencies between devices
On Monday, October 31, 2016 11:47:03 AM Greg Kroah-Hartman wrote: > On Sun, Oct 30, 2016 at 05:22:13PM +0100, Rafael J. Wysocki wrote: > > Hi, > > > > Let me quote from the previous intro messages for this series first: > > > > > > Time for another update. :-) > > > > > > > > Fewer changes this time, mostly to address issues found by Lukas and > > > > Marek. > > > > > > > > The most significant one is to make device_link_add() cope with the case > > > > when > > > > the consumer device has not been registered yet when it is called. The > > > > supplier device still is required to be registered and the function will > > > > return NULL if that is not the case. > > > > > > > > Another significant change is in patch [4/5] that now makes the core > > > > apply > > > > pm_runtime_get_sync()/pm_runtime_put() to supplier devices around the > > > > probing of a consumer one (in analogy with the parent). > > > > > > One more update after some conversations during LinuxCon Europe. > > > > > > The main point was to make it possible for device_link_add() to figure out > > > the initial state of the link instead of expecting the caller to provide > > > it > > > which might not be reliable enough in general. > > > > > > In this version device_link_add() takes three arguments, the supplier and > > > consumer pointers and flags and it sets the correct initial state of the > > > link automatically (unless invoked with the "stateless" flag, of course). > > > The cost is one additional field in struct device (I moved all of the > > > links-related fields in struct device to a separate sub-structure while at > > > it) to track the "driver presence status" of the device (to be used by > > > device_link_add()). > > > > > > In addition to that, the links list walks in the core.c and dd.c code are > > > under the device links mutex now, so the iternal link spinlock is not > > > needed > > > any more and I have renamed symbols to distinguish between flags, link > > > states and device "driver presence statuses". > > > > The most significant change in this revision with respect to the previous > > one is > > related to the fact that SRCU is not available on some architectures, so the > > code falls back to using an RW semaphore for synchronization if SRCU is not > > there. Fortunately, the code changes needed for that turned out to be quite > > straightforward and confined to the second patch. > > > > Apart from this, the flags are defined using BIT(x) now (instead of open > > coding > > the latter in the flag definitions). > > > > Updated is mostly patch [2/5]. Patches [1,3,5/5] have not changed (except > > for > > trivial rebasing) and patch [4/5] needed to be refreshed on top of the > > modified > > [2/5]. > > > > FWIW, I've run the series through 0-day which has not reported any problems > > with it. > > Great, they are now applied to my tree, thanks again for doing this > work. Thanks!
Re: [RFC PATCH 0/6] UART slave devices using serio
On Mon, Oct 31, 2016 at 3:00 PM, Peter Hurleywrote: > On Tue, Oct 25, 2016 at 4:02 PM, Rob Herring wrote: >> >> > Maybe you can try to find some minutes at the Kernel Summit to talk >> > about this? >> >> Still waiting for my invite... >> >> But I will be at Plumbers if folks want to discuss this. > > > Hey Rob, > > I'm here so let's make time to discuss this. Tomorrow should be good for me after the complex device dependencies discussion. Rob
Re: [RFC PATCH 0/6] UART slave devices using serio
On Mon, Oct 31, 2016 at 3:00 PM, Peter Hurley wrote: > On Tue, Oct 25, 2016 at 4:02 PM, Rob Herring wrote: >> >> > Maybe you can try to find some minutes at the Kernel Summit to talk >> > about this? >> >> Still waiting for my invite... >> >> But I will be at Plumbers if folks want to discuss this. > > > Hey Rob, > > I'm here so let's make time to discuss this. Tomorrow should be good for me after the complex device dependencies discussion. Rob
cygnus-pcm.c:undefined reference to `bad_dma_ops'
Hi Mark, FYI, the error/warning still remains. tree: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master head: 0c183d92b20b5c84ca655b45ef57b3318b83eb9e commit: 3ceeda1cbee9f93bb5537c9b840d1f7e767d7c01 Merge remote-tracking branches 'asoc/topic/cs53l30', 'asoc/topic/cygnus', 'asoc/topic/da7219' and 'asoc/topic/davinci' into asoc-next date: 3 months ago config: m32r-allyesconfig (attached as .config) compiler: m32r-linux-gcc (GCC) 6.2.0 reproduce: wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross git checkout 3ceeda1cbee9f93bb5537c9b840d1f7e767d7c01 # save the attached .config to linux build tree make.cross ARCH=m32r All errors (new ones prefixed by >>): sound/built-in.o: In function `snd_pcm_lib_default_mmap': (.text+0xfcf4): undefined reference to `bad_dma_ops' sound/built-in.o: In function `snd_pcm_lib_default_mmap': (.text+0xfcf8): undefined reference to `bad_dma_ops' sound/built-in.o: In function `snd_pcm_lib_default_mmap': (.text+0xfd48): undefined reference to `dma_common_mmap' sound/built-in.o: In function `snd_pcm_lib_default_mmap': (.text+0xfd48): relocation truncated to fit: R_M32R_26_PCREL_RELA against undefined symbol `dma_common_mmap' sound/built-in.o: In function `cygnus_pcm_preallocate_dma_buffer': >> cygnus-pcm.c:(.text+0x10e94c): undefined reference to `bad_dma_ops' cygnus-pcm.c:(.text+0x10e950): undefined reference to `bad_dma_ops' cygnus-pcm.c:(.text+0x10e984): undefined reference to `bad_dma_ops' sound/built-in.o: In function `cygnus_dma_free_dma_buffers': cygnus-pcm.c:(.text+0x10ea84): undefined reference to `bad_dma_ops' cygnus-pcm.c:(.text+0x10ea8c): undefined reference to `bad_dma_ops' sound/built-in.o:cygnus-pcm.c:(.text+0x10eb24): more undefined references to `bad_dma_ops' follow --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation .config.gz Description: application/gzip
cygnus-pcm.c:undefined reference to `bad_dma_ops'
Hi Mark, FYI, the error/warning still remains. tree: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git master head: 0c183d92b20b5c84ca655b45ef57b3318b83eb9e commit: 3ceeda1cbee9f93bb5537c9b840d1f7e767d7c01 Merge remote-tracking branches 'asoc/topic/cs53l30', 'asoc/topic/cygnus', 'asoc/topic/da7219' and 'asoc/topic/davinci' into asoc-next date: 3 months ago config: m32r-allyesconfig (attached as .config) compiler: m32r-linux-gcc (GCC) 6.2.0 reproduce: wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross git checkout 3ceeda1cbee9f93bb5537c9b840d1f7e767d7c01 # save the attached .config to linux build tree make.cross ARCH=m32r All errors (new ones prefixed by >>): sound/built-in.o: In function `snd_pcm_lib_default_mmap': (.text+0xfcf4): undefined reference to `bad_dma_ops' sound/built-in.o: In function `snd_pcm_lib_default_mmap': (.text+0xfcf8): undefined reference to `bad_dma_ops' sound/built-in.o: In function `snd_pcm_lib_default_mmap': (.text+0xfd48): undefined reference to `dma_common_mmap' sound/built-in.o: In function `snd_pcm_lib_default_mmap': (.text+0xfd48): relocation truncated to fit: R_M32R_26_PCREL_RELA against undefined symbol `dma_common_mmap' sound/built-in.o: In function `cygnus_pcm_preallocate_dma_buffer': >> cygnus-pcm.c:(.text+0x10e94c): undefined reference to `bad_dma_ops' cygnus-pcm.c:(.text+0x10e950): undefined reference to `bad_dma_ops' cygnus-pcm.c:(.text+0x10e984): undefined reference to `bad_dma_ops' sound/built-in.o: In function `cygnus_dma_free_dma_buffers': cygnus-pcm.c:(.text+0x10ea84): undefined reference to `bad_dma_ops' cygnus-pcm.c:(.text+0x10ea8c): undefined reference to `bad_dma_ops' sound/built-in.o:cygnus-pcm.c:(.text+0x10eb24): more undefined references to `bad_dma_ops' follow --- 0-DAY kernel test infrastructureOpen Source Technology Center https://lists.01.org/pipermail/kbuild-all Intel Corporation .config.gz Description: application/gzip
[PATCH net-next 04/11] net: dsa: mv88e6xxx: add port FID accessors
Add functions to port files to access the ports default FID. Signed-off-by: Vivien Didelot--- drivers/net/dsa/mv88e6xxx/chip.c | 77 +++- drivers/net/dsa/mv88e6xxx/port.c | 67 ++ drivers/net/dsa/mv88e6xxx/port.h | 3 ++ 3 files changed, 74 insertions(+), 73 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 087..20f59f1 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1674,75 +1674,6 @@ static int _mv88e6xxx_stu_loadpurge(struct mv88e6xxx_chip *chip, return _mv88e6xxx_vtu_cmd(chip, GLOBAL_VTU_OP_STU_LOAD_PURGE); } -static int _mv88e6xxx_port_fid(struct mv88e6xxx_chip *chip, int port, - u16 *new, u16 *old) -{ - struct dsa_switch *ds = chip->ds; - u16 upper_mask; - u16 fid; - u16 reg; - int err; - - if (mv88e6xxx_num_databases(chip) == 4096) - upper_mask = 0xff; - else if (mv88e6xxx_num_databases(chip) == 256) - upper_mask = 0xf; - else - return -EOPNOTSUPP; - - /* Port's default FID bits 3:0 are located in reg 0x06, offset 12 */ - err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, ); - if (err) - return err; - - fid = (reg & PORT_BASE_VLAN_FID_3_0_MASK) >> 12; - - if (new) { - reg &= ~PORT_BASE_VLAN_FID_3_0_MASK; - reg |= (*new << 12) & PORT_BASE_VLAN_FID_3_0_MASK; - - err = mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg); - if (err) - return err; - } - - /* Port's default FID bits 11:4 are located in reg 0x05, offset 0 */ - err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_1, ); - if (err) - return err; - - fid |= (reg & upper_mask) << 4; - - if (new) { - reg &= ~upper_mask; - reg |= (*new >> 4) & upper_mask; - - err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_1, reg); - if (err) - return err; - - netdev_dbg(ds->ports[port].netdev, - "FID %d (was %d)\n", *new, fid); - } - - if (old) - *old = fid; - - return 0; -} - -static int _mv88e6xxx_port_fid_get(struct mv88e6xxx_chip *chip, - int port, u16 *fid) -{ - return _mv88e6xxx_port_fid(chip, port, NULL, fid); -} - -static int _mv88e6xxx_port_fid_set(struct mv88e6xxx_chip *chip, - int port, u16 fid) -{ - return _mv88e6xxx_port_fid(chip, port, , NULL); -} - static int _mv88e6xxx_fid_new(struct mv88e6xxx_chip *chip, u16 *fid) { DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID); @@ -1753,7 +1684,7 @@ static int _mv88e6xxx_fid_new(struct mv88e6xxx_chip *chip, u16 *fid) /* Set every FID bit used by the (un)bridged ports */ for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) { - err = _mv88e6xxx_port_fid_get(chip, i, fid); + err = mv88e6xxx_port_get_fid(chip, i, fid); if (err) return err; @@ -2203,7 +2134,7 @@ static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port, /* Null VLAN ID corresponds to the port private database */ if (vid == 0) - err = _mv88e6xxx_port_fid_get(chip, port, ); + err = mv88e6xxx_port_get_fid(chip, port, ); else err = _mv88e6xxx_vtu_get(chip, vid, , false); if (err) @@ -2379,7 +2310,7 @@ static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port, int err; /* Dump port's default Filtering Information Database (VLAN ID 0) */ - err = _mv88e6xxx_port_fid_get(chip, port, ); + err = mv88e6xxx_port_get_fid(chip, port, ); if (err) return err; @@ -2782,7 +2713,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) * database, and allow bidirectional communication between the * CPU and DSA port(s), and the other ports. */ - err = _mv88e6xxx_port_fid_set(chip, port, 0); + err = mv88e6xxx_port_set_fid(chip, port, 0); if (err) return err; diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index c6a22ae..a7da812 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -61,6 +61,8 @@ int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state) return 0; } +/* Offset 0x05: Port Control 1 */ + /* Offset 0x06: Port Based VLAN Map */ int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map) @@ -85,3 +87,68 @@ int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int
[PATCH] clk: rockchip: optimize the configuration for 800MHz and 1GHz on RK3399
Usually, the 800MHz and 1GHz are supplied for CPLL and NPLL in the RK3399. But dues to the carelessly copying from RK3036 when the RK3399 bringing up, the refdiv == 6, it will increase the lock time, and it is not an optimal configuration. Please let's fix them for the lock time and jitter are lower: 800 MHz: - FVCO == 2.4 GHz, revdiv == 1. 1 GHz: - FVCO == 3 GHz, revdiv == 1. Signed-off-by: Xing Zheng--- drivers/clk/rockchip/clk-rk3399.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c index a5a3f41..28aff45 100644 --- a/drivers/clk/rockchip/clk-rk3399.c +++ b/drivers/clk/rockchip/clk-rk3399.c @@ -77,7 +77,7 @@ static struct rockchip_pll_rate_table rk3399_pll_rates[] = { RK3036_PLL_RATE(110400, 1, 46, 1, 1, 1, 0), RK3036_PLL_RATE(11, 12, 550, 1, 1, 1, 0), RK3036_PLL_RATE(100800, 1, 84, 2, 1, 1, 0), - RK3036_PLL_RATE(10, 6, 500, 2, 1, 1, 0), + RK3036_PLL_RATE(10, 1, 125, 3, 1, 1, 0), RK3036_PLL_RATE( 98400, 1, 82, 2, 1, 1, 0), RK3036_PLL_RATE( 96000, 1, 80, 2, 1, 1, 0), RK3036_PLL_RATE( 93600, 1, 78, 2, 1, 1, 0), @@ -87,7 +87,7 @@ static struct rockchip_pll_rate_table rk3399_pll_rates[] = { RK3036_PLL_RATE( 86400, 1, 72, 2, 1, 1, 0), RK3036_PLL_RATE( 84000, 1, 70, 2, 1, 1, 0), RK3036_PLL_RATE( 81600, 1, 68, 2, 1, 1, 0), - RK3036_PLL_RATE( 8, 6, 400, 2, 1, 1, 0), + RK3036_PLL_RATE( 8, 1, 100, 3, 1, 1, 0), RK3036_PLL_RATE( 7, 6, 350, 2, 1, 1, 0), RK3036_PLL_RATE( 69600, 1, 58, 2, 1, 1, 0), RK3036_PLL_RATE( 67600, 3, 169, 2, 1, 1, 0), -- 2.7.4
[PATCH net-next 02/11] net: dsa: mv88e6xxx: add port state setter
Add the port STP state setter to the port files. Signed-off-by: Vivien Didelot--- drivers/net/dsa/mv88e6xxx/chip.c | 49 drivers/net/dsa/mv88e6xxx/port.c | 31 + drivers/net/dsa/mv88e6xxx/port.h | 2 ++ 3 files changed, 37 insertions(+), 45 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index b32b242..12c1175 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1215,41 +1215,6 @@ static int _mv88e6xxx_atu_remove(struct mv88e6xxx_chip *chip, u16 fid, return _mv88e6xxx_atu_move(chip, fid, port, 0x0f, static_too); } -static const char * const mv88e6xxx_port_state_names[] = { - [PORT_CONTROL_STATE_DISABLED] = "Disabled", - [PORT_CONTROL_STATE_BLOCKING] = "Blocking/Listening", - [PORT_CONTROL_STATE_LEARNING] = "Learning", - [PORT_CONTROL_STATE_FORWARDING] = "Forwarding", -}; - -static int _mv88e6xxx_port_state(struct mv88e6xxx_chip *chip, int port, -u8 state) -{ - struct dsa_switch *ds = chip->ds; - u16 reg; - int err; - u8 oldstate; - - err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, ); - if (err) - return err; - - oldstate = reg & PORT_CONTROL_STATE_MASK; - - reg &= ~PORT_CONTROL_STATE_MASK; - reg |= state; - - err = mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg); - if (err) - return err; - - netdev_dbg(ds->ports[port].netdev, "PortState %s (was %s)\n", - mv88e6xxx_port_state_names[state], - mv88e6xxx_port_state_names[oldstate]); - - return 0; -} - static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_chip *chip, int port) { struct net_device *bridge = chip->ports[port].bridge_dev; @@ -1313,13 +1278,11 @@ static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port, } mutex_lock(>reg_lock); - err = _mv88e6xxx_port_state(chip, port, stp_state); + err = mv88e6xxx_port_set_state(chip, port, stp_state); mutex_unlock(>reg_lock); if (err) - netdev_err(ds->ports[port].netdev, - "failed to update state to %s\n", - mv88e6xxx_port_state_names[stp_state]); + netdev_err(ds->ports[port].netdev, "failed to update state\n"); } static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port) @@ -2526,12 +2489,8 @@ static int mv88e6xxx_switch_reset(struct mv88e6xxx_chip *chip) /* Set all ports to the disabled state. */ for (i = 0; i < mv88e6xxx_num_ports(chip); i++) { - err = mv88e6xxx_port_read(chip, i, PORT_CONTROL, ); - if (err) - return err; - - err = mv88e6xxx_port_write(chip, i, PORT_CONTROL, - reg & 0xfffc); + err = mv88e6xxx_port_set_state(chip, i, + PORT_CONTROL_STATE_DISABLED); if (err) return err; } diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 3b36c92..8d59fe7 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -29,3 +29,34 @@ int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, return mv88e6xxx_write(chip, addr, reg, val); } + +/* Offset 0x04: Port Control Register */ + +static const char * const mv88e6xxx_port_state_names[] = { + [PORT_CONTROL_STATE_DISABLED] = "Disabled", + [PORT_CONTROL_STATE_BLOCKING] = "Blocking/Listening", + [PORT_CONTROL_STATE_LEARNING] = "Learning", + [PORT_CONTROL_STATE_FORWARDING] = "Forwarding", +}; + +int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state) +{ + u16 reg; + int err; + + err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, ); + if (err) + return err; + + reg &= ~PORT_CONTROL_STATE_MASK; + reg |= state; + + err = mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg); + if (err) + return err; + + netdev_dbg(chip->ds->ports[port].netdev, "PortState set to %s\n", + mv88e6xxx_port_state_names[state]); + + return 0; +} diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index ae1ae2b..ac13988 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -21,4 +21,6 @@ int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg, int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, u16 val); +int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state); + #endif /* _MV88E6XXX_PORT_H */ -- 2.10.2
[PATCH net-next 11/11] net: dsa: mv88e6xxx: setup port's MAC
Now that we have setters to configure the port's MAC, use them to refactor the port setup and adjust_link code. Note that port's MAC speed, duplex or RGMII delay must not be changed unless the port's link is forced down. So wrap all that in a mv88e6xxx_port_ctrl_mac function. Signed-off-by: Vivien Didelot--- drivers/net/dsa/mv88e6xxx/chip.c | 138 --- 1 file changed, 58 insertions(+), 80 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 23c05e3..56d60fd 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -701,6 +701,47 @@ static bool mv88e6xxx_6352_family(struct mv88e6xxx_chip *chip) return chip->info->family == MV88E6XXX_FAMILY_6352; } +static int mv88e6xxx_port_ctrl_mac(struct mv88e6xxx_chip *chip, int port, + int link, int speed, int duplex, + phy_interface_t mode) +{ + int err; + + if (!chip->info->ops->port_set_link) + return 0; + + /* Port's MAC control must not be changed unless the link is down */ + err = chip->info->ops->port_set_link(chip, port, 0); + if (err) + return err; + + if (chip->info->ops->port_set_speed) { + err = chip->info->ops->port_set_speed(chip, port, speed); + if (err && err != -EOPNOTSUPP) + goto restore_link; + } + + if (chip->info->ops->port_set_duplex) { + err = chip->info->ops->port_set_duplex(chip, port, duplex); + if (err && err != -EOPNOTSUPP) + goto restore_link; + } + + if (chip->info->ops->port_set_rgmii_delay) { + err = chip->info->ops->port_set_rgmii_delay(chip, port, mode); + if (err && err != -EOPNOTSUPP) + goto restore_link; + } + + err = 0; +restore_link: + if (chip->info->ops->port_set_link(chip, port, link)) + netdev_err(chip->ds->ports[port].netdev, + "failed to restore MAC's link\n"); + + return err; +} + /* We expect the switch to perform auto negotiation if there is a real * phy. However, in the case of a fixed link phy, we force the port * settings from the fixed link settings. @@ -709,64 +750,18 @@ static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port, struct phy_device *phydev) { struct mv88e6xxx_chip *chip = ds->priv; - u16 reg; int err; if (!phy_is_pseudo_fixed_link(phydev)) return; mutex_lock(>reg_lock); - - err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, ); - if (err) - goto out; - - reg &= ~(PORT_PCS_CTRL_LINK_UP | -PORT_PCS_CTRL_FORCE_LINK | -PORT_PCS_CTRL_DUPLEX_FULL | -PORT_PCS_CTRL_FORCE_DUPLEX | -PORT_PCS_CTRL_SPEED_UNFORCED); - - reg |= PORT_PCS_CTRL_FORCE_LINK; - if (phydev->link) - reg |= PORT_PCS_CTRL_LINK_UP; - - if (mv88e6xxx_6065_family(chip) && phydev->speed > SPEED_100) - goto out; - - switch (phydev->speed) { - case SPEED_1000: - reg |= PORT_PCS_CTRL_SPEED_1000; - break; - case SPEED_100: - reg |= PORT_PCS_CTRL_SPEED_100; - break; - case SPEED_10: - reg |= PORT_PCS_CTRL_SPEED_10; - break; - default: - pr_info("Unknown speed"); - goto out; - } - - reg |= PORT_PCS_CTRL_FORCE_DUPLEX; - if (phydev->duplex == DUPLEX_FULL) - reg |= PORT_PCS_CTRL_DUPLEX_FULL; - - if ((mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip)) && - (port >= mv88e6xxx_num_ports(chip) - 2)) { - if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) - reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK; - if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) - reg |= PORT_PCS_CTRL_RGMII_DELAY_TXCLK; - if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) - reg |= (PORT_PCS_CTRL_RGMII_DELAY_RXCLK | - PORT_PCS_CTRL_RGMII_DELAY_TXCLK); - } - mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg); - -out: + err = mv88e6xxx_port_ctrl_mac(chip, port, phydev->link, phydev->speed, + phydev->duplex, phydev->interface); mutex_unlock(>reg_lock); + + if (err && err != -EOPNOTSUPP) + netdev_err(ds->ports[port].netdev, "failed to configure MAC\n"); } static int _mv88e6xxx_stats_wait(struct mv88e6xxx_chip *chip) @@ -2409,35 +2404,18 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip
[PATCH net-next 11/11] net: dsa: mv88e6xxx: setup port's MAC
Now that we have setters to configure the port's MAC, use them to refactor the port setup and adjust_link code. Note that port's MAC speed, duplex or RGMII delay must not be changed unless the port's link is forced down. So wrap all that in a mv88e6xxx_port_ctrl_mac function. Signed-off-by: Vivien Didelot --- drivers/net/dsa/mv88e6xxx/chip.c | 138 --- 1 file changed, 58 insertions(+), 80 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 23c05e3..56d60fd 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -701,6 +701,47 @@ static bool mv88e6xxx_6352_family(struct mv88e6xxx_chip *chip) return chip->info->family == MV88E6XXX_FAMILY_6352; } +static int mv88e6xxx_port_ctrl_mac(struct mv88e6xxx_chip *chip, int port, + int link, int speed, int duplex, + phy_interface_t mode) +{ + int err; + + if (!chip->info->ops->port_set_link) + return 0; + + /* Port's MAC control must not be changed unless the link is down */ + err = chip->info->ops->port_set_link(chip, port, 0); + if (err) + return err; + + if (chip->info->ops->port_set_speed) { + err = chip->info->ops->port_set_speed(chip, port, speed); + if (err && err != -EOPNOTSUPP) + goto restore_link; + } + + if (chip->info->ops->port_set_duplex) { + err = chip->info->ops->port_set_duplex(chip, port, duplex); + if (err && err != -EOPNOTSUPP) + goto restore_link; + } + + if (chip->info->ops->port_set_rgmii_delay) { + err = chip->info->ops->port_set_rgmii_delay(chip, port, mode); + if (err && err != -EOPNOTSUPP) + goto restore_link; + } + + err = 0; +restore_link: + if (chip->info->ops->port_set_link(chip, port, link)) + netdev_err(chip->ds->ports[port].netdev, + "failed to restore MAC's link\n"); + + return err; +} + /* We expect the switch to perform auto negotiation if there is a real * phy. However, in the case of a fixed link phy, we force the port * settings from the fixed link settings. @@ -709,64 +750,18 @@ static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port, struct phy_device *phydev) { struct mv88e6xxx_chip *chip = ds->priv; - u16 reg; int err; if (!phy_is_pseudo_fixed_link(phydev)) return; mutex_lock(>reg_lock); - - err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, ); - if (err) - goto out; - - reg &= ~(PORT_PCS_CTRL_LINK_UP | -PORT_PCS_CTRL_FORCE_LINK | -PORT_PCS_CTRL_DUPLEX_FULL | -PORT_PCS_CTRL_FORCE_DUPLEX | -PORT_PCS_CTRL_SPEED_UNFORCED); - - reg |= PORT_PCS_CTRL_FORCE_LINK; - if (phydev->link) - reg |= PORT_PCS_CTRL_LINK_UP; - - if (mv88e6xxx_6065_family(chip) && phydev->speed > SPEED_100) - goto out; - - switch (phydev->speed) { - case SPEED_1000: - reg |= PORT_PCS_CTRL_SPEED_1000; - break; - case SPEED_100: - reg |= PORT_PCS_CTRL_SPEED_100; - break; - case SPEED_10: - reg |= PORT_PCS_CTRL_SPEED_10; - break; - default: - pr_info("Unknown speed"); - goto out; - } - - reg |= PORT_PCS_CTRL_FORCE_DUPLEX; - if (phydev->duplex == DUPLEX_FULL) - reg |= PORT_PCS_CTRL_DUPLEX_FULL; - - if ((mv88e6xxx_6352_family(chip) || mv88e6xxx_6351_family(chip)) && - (port >= mv88e6xxx_num_ports(chip) - 2)) { - if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) - reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK; - if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) - reg |= PORT_PCS_CTRL_RGMII_DELAY_TXCLK; - if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) - reg |= (PORT_PCS_CTRL_RGMII_DELAY_RXCLK | - PORT_PCS_CTRL_RGMII_DELAY_TXCLK); - } - mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg); - -out: + err = mv88e6xxx_port_ctrl_mac(chip, port, phydev->link, phydev->speed, + phydev->duplex, phydev->interface); mutex_unlock(>reg_lock); + + if (err && err != -EOPNOTSUPP) + netdev_err(ds->ports[port].netdev, "failed to configure MAC\n"); } static int _mv88e6xxx_stats_wait(struct mv88e6xxx_chip *chip) @@ -2409,35 +2404,18 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) int err;
[PATCH net-next 04/11] net: dsa: mv88e6xxx: add port FID accessors
Add functions to port files to access the ports default FID. Signed-off-by: Vivien Didelot --- drivers/net/dsa/mv88e6xxx/chip.c | 77 +++- drivers/net/dsa/mv88e6xxx/port.c | 67 ++ drivers/net/dsa/mv88e6xxx/port.h | 3 ++ 3 files changed, 74 insertions(+), 73 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 087..20f59f1 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1674,75 +1674,6 @@ static int _mv88e6xxx_stu_loadpurge(struct mv88e6xxx_chip *chip, return _mv88e6xxx_vtu_cmd(chip, GLOBAL_VTU_OP_STU_LOAD_PURGE); } -static int _mv88e6xxx_port_fid(struct mv88e6xxx_chip *chip, int port, - u16 *new, u16 *old) -{ - struct dsa_switch *ds = chip->ds; - u16 upper_mask; - u16 fid; - u16 reg; - int err; - - if (mv88e6xxx_num_databases(chip) == 4096) - upper_mask = 0xff; - else if (mv88e6xxx_num_databases(chip) == 256) - upper_mask = 0xf; - else - return -EOPNOTSUPP; - - /* Port's default FID bits 3:0 are located in reg 0x06, offset 12 */ - err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, ); - if (err) - return err; - - fid = (reg & PORT_BASE_VLAN_FID_3_0_MASK) >> 12; - - if (new) { - reg &= ~PORT_BASE_VLAN_FID_3_0_MASK; - reg |= (*new << 12) & PORT_BASE_VLAN_FID_3_0_MASK; - - err = mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg); - if (err) - return err; - } - - /* Port's default FID bits 11:4 are located in reg 0x05, offset 0 */ - err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_1, ); - if (err) - return err; - - fid |= (reg & upper_mask) << 4; - - if (new) { - reg &= ~upper_mask; - reg |= (*new >> 4) & upper_mask; - - err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_1, reg); - if (err) - return err; - - netdev_dbg(ds->ports[port].netdev, - "FID %d (was %d)\n", *new, fid); - } - - if (old) - *old = fid; - - return 0; -} - -static int _mv88e6xxx_port_fid_get(struct mv88e6xxx_chip *chip, - int port, u16 *fid) -{ - return _mv88e6xxx_port_fid(chip, port, NULL, fid); -} - -static int _mv88e6xxx_port_fid_set(struct mv88e6xxx_chip *chip, - int port, u16 fid) -{ - return _mv88e6xxx_port_fid(chip, port, , NULL); -} - static int _mv88e6xxx_fid_new(struct mv88e6xxx_chip *chip, u16 *fid) { DECLARE_BITMAP(fid_bitmap, MV88E6XXX_N_FID); @@ -1753,7 +1684,7 @@ static int _mv88e6xxx_fid_new(struct mv88e6xxx_chip *chip, u16 *fid) /* Set every FID bit used by the (un)bridged ports */ for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) { - err = _mv88e6xxx_port_fid_get(chip, i, fid); + err = mv88e6xxx_port_get_fid(chip, i, fid); if (err) return err; @@ -2203,7 +2134,7 @@ static int mv88e6xxx_port_db_load_purge(struct mv88e6xxx_chip *chip, int port, /* Null VLAN ID corresponds to the port private database */ if (vid == 0) - err = _mv88e6xxx_port_fid_get(chip, port, ); + err = mv88e6xxx_port_get_fid(chip, port, ); else err = _mv88e6xxx_vtu_get(chip, vid, , false); if (err) @@ -2379,7 +2310,7 @@ static int mv88e6xxx_port_db_dump(struct mv88e6xxx_chip *chip, int port, int err; /* Dump port's default Filtering Information Database (VLAN ID 0) */ - err = _mv88e6xxx_port_fid_get(chip, port, ); + err = mv88e6xxx_port_get_fid(chip, port, ); if (err) return err; @@ -2782,7 +2713,7 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) * database, and allow bidirectional communication between the * CPU and DSA port(s), and the other ports. */ - err = _mv88e6xxx_port_fid_set(chip, port, 0); + err = mv88e6xxx_port_set_fid(chip, port, 0); if (err) return err; diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index c6a22ae..a7da812 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -61,6 +61,8 @@ int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state) return 0; } +/* Offset 0x05: Port Control 1 */ + /* Offset 0x06: Port Based VLAN Map */ int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map) @@ -85,3 +87,68 @@ int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map) return 0;
[PATCH] clk: rockchip: optimize the configuration for 800MHz and 1GHz on RK3399
Usually, the 800MHz and 1GHz are supplied for CPLL and NPLL in the RK3399. But dues to the carelessly copying from RK3036 when the RK3399 bringing up, the refdiv == 6, it will increase the lock time, and it is not an optimal configuration. Please let's fix them for the lock time and jitter are lower: 800 MHz: - FVCO == 2.4 GHz, revdiv == 1. 1 GHz: - FVCO == 3 GHz, revdiv == 1. Signed-off-by: Xing Zheng --- drivers/clk/rockchip/clk-rk3399.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/rockchip/clk-rk3399.c b/drivers/clk/rockchip/clk-rk3399.c index a5a3f41..28aff45 100644 --- a/drivers/clk/rockchip/clk-rk3399.c +++ b/drivers/clk/rockchip/clk-rk3399.c @@ -77,7 +77,7 @@ static struct rockchip_pll_rate_table rk3399_pll_rates[] = { RK3036_PLL_RATE(110400, 1, 46, 1, 1, 1, 0), RK3036_PLL_RATE(11, 12, 550, 1, 1, 1, 0), RK3036_PLL_RATE(100800, 1, 84, 2, 1, 1, 0), - RK3036_PLL_RATE(10, 6, 500, 2, 1, 1, 0), + RK3036_PLL_RATE(10, 1, 125, 3, 1, 1, 0), RK3036_PLL_RATE( 98400, 1, 82, 2, 1, 1, 0), RK3036_PLL_RATE( 96000, 1, 80, 2, 1, 1, 0), RK3036_PLL_RATE( 93600, 1, 78, 2, 1, 1, 0), @@ -87,7 +87,7 @@ static struct rockchip_pll_rate_table rk3399_pll_rates[] = { RK3036_PLL_RATE( 86400, 1, 72, 2, 1, 1, 0), RK3036_PLL_RATE( 84000, 1, 70, 2, 1, 1, 0), RK3036_PLL_RATE( 81600, 1, 68, 2, 1, 1, 0), - RK3036_PLL_RATE( 8, 6, 400, 2, 1, 1, 0), + RK3036_PLL_RATE( 8, 1, 100, 3, 1, 1, 0), RK3036_PLL_RATE( 7, 6, 350, 2, 1, 1, 0), RK3036_PLL_RATE( 69600, 1, 58, 2, 1, 1, 0), RK3036_PLL_RATE( 67600, 3, 169, 2, 1, 1, 0), -- 2.7.4
[PATCH net-next 02/11] net: dsa: mv88e6xxx: add port state setter
Add the port STP state setter to the port files. Signed-off-by: Vivien Didelot --- drivers/net/dsa/mv88e6xxx/chip.c | 49 drivers/net/dsa/mv88e6xxx/port.c | 31 + drivers/net/dsa/mv88e6xxx/port.h | 2 ++ 3 files changed, 37 insertions(+), 45 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index b32b242..12c1175 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1215,41 +1215,6 @@ static int _mv88e6xxx_atu_remove(struct mv88e6xxx_chip *chip, u16 fid, return _mv88e6xxx_atu_move(chip, fid, port, 0x0f, static_too); } -static const char * const mv88e6xxx_port_state_names[] = { - [PORT_CONTROL_STATE_DISABLED] = "Disabled", - [PORT_CONTROL_STATE_BLOCKING] = "Blocking/Listening", - [PORT_CONTROL_STATE_LEARNING] = "Learning", - [PORT_CONTROL_STATE_FORWARDING] = "Forwarding", -}; - -static int _mv88e6xxx_port_state(struct mv88e6xxx_chip *chip, int port, -u8 state) -{ - struct dsa_switch *ds = chip->ds; - u16 reg; - int err; - u8 oldstate; - - err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, ); - if (err) - return err; - - oldstate = reg & PORT_CONTROL_STATE_MASK; - - reg &= ~PORT_CONTROL_STATE_MASK; - reg |= state; - - err = mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg); - if (err) - return err; - - netdev_dbg(ds->ports[port].netdev, "PortState %s (was %s)\n", - mv88e6xxx_port_state_names[state], - mv88e6xxx_port_state_names[oldstate]); - - return 0; -} - static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_chip *chip, int port) { struct net_device *bridge = chip->ports[port].bridge_dev; @@ -1313,13 +1278,11 @@ static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port, } mutex_lock(>reg_lock); - err = _mv88e6xxx_port_state(chip, port, stp_state); + err = mv88e6xxx_port_set_state(chip, port, stp_state); mutex_unlock(>reg_lock); if (err) - netdev_err(ds->ports[port].netdev, - "failed to update state to %s\n", - mv88e6xxx_port_state_names[stp_state]); + netdev_err(ds->ports[port].netdev, "failed to update state\n"); } static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port) @@ -2526,12 +2489,8 @@ static int mv88e6xxx_switch_reset(struct mv88e6xxx_chip *chip) /* Set all ports to the disabled state. */ for (i = 0; i < mv88e6xxx_num_ports(chip); i++) { - err = mv88e6xxx_port_read(chip, i, PORT_CONTROL, ); - if (err) - return err; - - err = mv88e6xxx_port_write(chip, i, PORT_CONTROL, - reg & 0xfffc); + err = mv88e6xxx_port_set_state(chip, i, + PORT_CONTROL_STATE_DISABLED); if (err) return err; } diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 3b36c92..8d59fe7 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -29,3 +29,34 @@ int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, return mv88e6xxx_write(chip, addr, reg, val); } + +/* Offset 0x04: Port Control Register */ + +static const char * const mv88e6xxx_port_state_names[] = { + [PORT_CONTROL_STATE_DISABLED] = "Disabled", + [PORT_CONTROL_STATE_BLOCKING] = "Blocking/Listening", + [PORT_CONTROL_STATE_LEARNING] = "Learning", + [PORT_CONTROL_STATE_FORWARDING] = "Forwarding", +}; + +int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state) +{ + u16 reg; + int err; + + err = mv88e6xxx_port_read(chip, port, PORT_CONTROL, ); + if (err) + return err; + + reg &= ~PORT_CONTROL_STATE_MASK; + reg |= state; + + err = mv88e6xxx_port_write(chip, port, PORT_CONTROL, reg); + if (err) + return err; + + netdev_dbg(chip->ds->ports[port].netdev, "PortState set to %s\n", + mv88e6xxx_port_state_names[state]); + + return 0; +} diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index ae1ae2b..ac13988 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -21,4 +21,6 @@ int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg, int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, u16 val); +int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state); + #endif /* _MV88E6XXX_PORT_H */ -- 2.10.2
[PATCH net-next 01/11] net: dsa: mv88e6xxx: add port files
The Marvell switches contains one internal SMI device per port, called "Port Registers". Depending on the model, the addresses of these devices start from 0x0, 0x8 or 0x10. Start moving Port Registers specific code to their own files. Signed-off-by: Vivien Didelot--- drivers/net/dsa/mv88e6xxx/Makefile | 1 + drivers/net/dsa/mv88e6xxx/chip.c | 17 + drivers/net/dsa/mv88e6xxx/port.c | 31 +++ drivers/net/dsa/mv88e6xxx/port.h | 24 4 files changed, 57 insertions(+), 16 deletions(-) create mode 100644 drivers/net/dsa/mv88e6xxx/port.c create mode 100644 drivers/net/dsa/mv88e6xxx/port.h diff --git a/drivers/net/dsa/mv88e6xxx/Makefile b/drivers/net/dsa/mv88e6xxx/Makefile index 10ce820..c36be31 100644 --- a/drivers/net/dsa/mv88e6xxx/Makefile +++ b/drivers/net/dsa/mv88e6xxx/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx.o mv88e6xxx-objs := chip.o mv88e6xxx-objs += global1.o mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_GLOBAL2) += global2.o +mv88e6xxx-objs += port.o diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 72b9dac2..b32b242 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -37,6 +37,7 @@ #include "mv88e6xxx.h" #include "global1.h" #include "global2.h" +#include "port.h" static void assert_reg_lock(struct mv88e6xxx_chip *chip) { @@ -221,22 +222,6 @@ int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val) return 0; } -static int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg, - u16 *val) -{ - int addr = chip->info->port_base_addr + port; - - return mv88e6xxx_read(chip, addr, reg, val); -} - -static int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, - u16 val) -{ - int addr = chip->info->port_base_addr + port; - - return mv88e6xxx_write(chip, addr, reg, val); -} - static int mv88e6xxx_phy_read(struct mv88e6xxx_chip *chip, int phy, int reg, u16 *val) { diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c new file mode 100644 index 000..3b36c92 --- /dev/null +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -0,0 +1,31 @@ +/* + * Marvell 88E6xxx Switch Port Registers support + * + * Copyright (c) 2008 Marvell Semiconductor + * + * Copyright (c) 2016 Vivien Didelot + * + * 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 "mv88e6xxx.h" +#include "port.h" + +int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg, + u16 *val) +{ + int addr = chip->info->port_base_addr + port; + + return mv88e6xxx_read(chip, addr, reg, val); +} + +int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, +u16 val) +{ + int addr = chip->info->port_base_addr + port; + + return mv88e6xxx_write(chip, addr, reg, val); +} diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h new file mode 100644 index 000..ae1ae2b --- /dev/null +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -0,0 +1,24 @@ +/* + * Marvell 88E6xxx Switch Port Registers support + * + * Copyright (c) 2008 Marvell Semiconductor + * + * Copyright (c) 2016 Vivien Didelot + * + * 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 _MV88E6XXX_PORT_H +#define _MV88E6XXX_PORT_H + +#include "mv88e6xxx.h" + +int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg, + u16 *val); +int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, +u16 val); + +#endif /* _MV88E6XXX_PORT_H */ -- 2.10.2
[PATCH net-next 03/11] net: dsa: mv88e6xxx: add port vlan map setter
Add a port function to access the Port Based VLAN Map register. Signed-off-by: Vivien Didelot--- drivers/net/dsa/mv88e6xxx/chip.c | 14 ++ drivers/net/dsa/mv88e6xxx/port.c | 25 + drivers/net/dsa/mv88e6xxx/port.h | 2 ++ 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 12c1175..087 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1218,16 +1218,13 @@ static int _mv88e6xxx_atu_remove(struct mv88e6xxx_chip *chip, u16 fid, static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_chip *chip, int port) { struct net_device *bridge = chip->ports[port].bridge_dev; - const u16 mask = (1 << mv88e6xxx_num_ports(chip)) - 1; struct dsa_switch *ds = chip->ds; u16 output_ports = 0; - u16 reg; - int err; int i; /* allow CPU port or DSA link(s) to send frames to every port */ if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) { - output_ports = mask; + output_ports = ~0; } else { for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) { /* allow sending frames to every group member */ @@ -1243,14 +1240,7 @@ static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_chip *chip, int port) /* prevent frames from going back out of the port they came in on */ output_ports &= ~BIT(port); - err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, ); - if (err) - return err; - - reg &= ~mask; - reg |= output_ports & mask; - - return mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg); + return mv88e6xxx_port_set_vlan_map(chip, port, output_ports); } static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port, diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 8d59fe7..c6a22ae 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -60,3 +60,28 @@ int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state) return 0; } + +/* Offset 0x06: Port Based VLAN Map */ + +int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map) +{ + const u16 mask = GENMASK(mv88e6xxx_num_ports(chip) - 1, 0); + u16 reg; + int err; + + err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, ); + if (err) + return err; + + reg &= ~mask; + reg |= map & mask; + + err = mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg); + if (err) + return err; + + netdev_dbg(chip->ds->ports[port].netdev, "VLANTable set to %.3x\n", + map); + + return 0; +} diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index ac13988..037d638 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -23,4 +23,6 @@ int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state); +int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map); + #endif /* _MV88E6XXX_PORT_H */ -- 2.10.2
[PATCH net-next 03/11] net: dsa: mv88e6xxx: add port vlan map setter
Add a port function to access the Port Based VLAN Map register. Signed-off-by: Vivien Didelot --- drivers/net/dsa/mv88e6xxx/chip.c | 14 ++ drivers/net/dsa/mv88e6xxx/port.c | 25 + drivers/net/dsa/mv88e6xxx/port.h | 2 ++ 3 files changed, 29 insertions(+), 12 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 12c1175..087 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1218,16 +1218,13 @@ static int _mv88e6xxx_atu_remove(struct mv88e6xxx_chip *chip, u16 fid, static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_chip *chip, int port) { struct net_device *bridge = chip->ports[port].bridge_dev; - const u16 mask = (1 << mv88e6xxx_num_ports(chip)) - 1; struct dsa_switch *ds = chip->ds; u16 output_ports = 0; - u16 reg; - int err; int i; /* allow CPU port or DSA link(s) to send frames to every port */ if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) { - output_ports = mask; + output_ports = ~0; } else { for (i = 0; i < mv88e6xxx_num_ports(chip); ++i) { /* allow sending frames to every group member */ @@ -1243,14 +1240,7 @@ static int _mv88e6xxx_port_based_vlan_map(struct mv88e6xxx_chip *chip, int port) /* prevent frames from going back out of the port they came in on */ output_ports &= ~BIT(port); - err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, ); - if (err) - return err; - - reg &= ~mask; - reg |= output_ports & mask; - - return mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg); + return mv88e6xxx_port_set_vlan_map(chip, port, output_ports); } static void mv88e6xxx_port_stp_state_set(struct dsa_switch *ds, int port, diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 8d59fe7..c6a22ae 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -60,3 +60,28 @@ int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state) return 0; } + +/* Offset 0x06: Port Based VLAN Map */ + +int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map) +{ + const u16 mask = GENMASK(mv88e6xxx_num_ports(chip) - 1, 0); + u16 reg; + int err; + + err = mv88e6xxx_port_read(chip, port, PORT_BASE_VLAN, ); + if (err) + return err; + + reg &= ~mask; + reg |= map & mask; + + err = mv88e6xxx_port_write(chip, port, PORT_BASE_VLAN, reg); + if (err) + return err; + + netdev_dbg(chip->ds->ports[port].netdev, "VLANTable set to %.3x\n", + map); + + return 0; +} diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index ac13988..037d638 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -23,4 +23,6 @@ int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, int mv88e6xxx_port_set_state(struct mv88e6xxx_chip *chip, int port, u8 state); +int mv88e6xxx_port_set_vlan_map(struct mv88e6xxx_chip *chip, int port, u16 map); + #endif /* _MV88E6XXX_PORT_H */ -- 2.10.2
[PATCH net-next 01/11] net: dsa: mv88e6xxx: add port files
The Marvell switches contains one internal SMI device per port, called "Port Registers". Depending on the model, the addresses of these devices start from 0x0, 0x8 or 0x10. Start moving Port Registers specific code to their own files. Signed-off-by: Vivien Didelot --- drivers/net/dsa/mv88e6xxx/Makefile | 1 + drivers/net/dsa/mv88e6xxx/chip.c | 17 + drivers/net/dsa/mv88e6xxx/port.c | 31 +++ drivers/net/dsa/mv88e6xxx/port.h | 24 4 files changed, 57 insertions(+), 16 deletions(-) create mode 100644 drivers/net/dsa/mv88e6xxx/port.c create mode 100644 drivers/net/dsa/mv88e6xxx/port.h diff --git a/drivers/net/dsa/mv88e6xxx/Makefile b/drivers/net/dsa/mv88e6xxx/Makefile index 10ce820..c36be31 100644 --- a/drivers/net/dsa/mv88e6xxx/Makefile +++ b/drivers/net/dsa/mv88e6xxx/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx.o mv88e6xxx-objs := chip.o mv88e6xxx-objs += global1.o mv88e6xxx-$(CONFIG_NET_DSA_MV88E6XXX_GLOBAL2) += global2.o +mv88e6xxx-objs += port.o diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 72b9dac2..b32b242 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -37,6 +37,7 @@ #include "mv88e6xxx.h" #include "global1.h" #include "global2.h" +#include "port.h" static void assert_reg_lock(struct mv88e6xxx_chip *chip) { @@ -221,22 +222,6 @@ int mv88e6xxx_write(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val) return 0; } -static int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg, - u16 *val) -{ - int addr = chip->info->port_base_addr + port; - - return mv88e6xxx_read(chip, addr, reg, val); -} - -static int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, - u16 val) -{ - int addr = chip->info->port_base_addr + port; - - return mv88e6xxx_write(chip, addr, reg, val); -} - static int mv88e6xxx_phy_read(struct mv88e6xxx_chip *chip, int phy, int reg, u16 *val) { diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c new file mode 100644 index 000..3b36c92 --- /dev/null +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -0,0 +1,31 @@ +/* + * Marvell 88E6xxx Switch Port Registers support + * + * Copyright (c) 2008 Marvell Semiconductor + * + * Copyright (c) 2016 Vivien Didelot + * + * 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 "mv88e6xxx.h" +#include "port.h" + +int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg, + u16 *val) +{ + int addr = chip->info->port_base_addr + port; + + return mv88e6xxx_read(chip, addr, reg, val); +} + +int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, +u16 val) +{ + int addr = chip->info->port_base_addr + port; + + return mv88e6xxx_write(chip, addr, reg, val); +} diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h new file mode 100644 index 000..ae1ae2b --- /dev/null +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -0,0 +1,24 @@ +/* + * Marvell 88E6xxx Switch Port Registers support + * + * Copyright (c) 2008 Marvell Semiconductor + * + * Copyright (c) 2016 Vivien Didelot + * + * 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 _MV88E6XXX_PORT_H +#define _MV88E6XXX_PORT_H + +#include "mv88e6xxx.h" + +int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg, + u16 *val); +int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, +u16 val); + +#endif /* _MV88E6XXX_PORT_H */ -- 2.10.2
[PATCH net-next 07/11] net: dsa: mv88e6xxx: add port link setter
Most of the chips will have a port register control bits to force the port's link up, down, or let normal link detection occurs. Implement such operation to use it later when setting duplex, etc. Signed-off-by: Vivien Didelot--- drivers/net/dsa/mv88e6xxx/chip.c | 17 + drivers/net/dsa/mv88e6xxx/mv88e6xxx.h | 8 drivers/net/dsa/mv88e6xxx/port.c | 33 + drivers/net/dsa/mv88e6xxx/port.h | 2 ++ 4 files changed, 60 insertions(+) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 181d3b9..cc43e6f 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -3160,42 +3160,49 @@ static const struct mv88e6xxx_ops mv88e6085_ops = { .set_switch_mac = mv88e6xxx_g1_set_switch_mac, .phy_read = mv88e6xxx_phy_ppu_read, .phy_write = mv88e6xxx_phy_ppu_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6095_ops = { .set_switch_mac = mv88e6xxx_g1_set_switch_mac, .phy_read = mv88e6xxx_phy_ppu_read, .phy_write = mv88e6xxx_phy_ppu_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6123_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_read, .phy_write = mv88e6xxx_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6131_ops = { .set_switch_mac = mv88e6xxx_g1_set_switch_mac, .phy_read = mv88e6xxx_phy_ppu_read, .phy_write = mv88e6xxx_phy_ppu_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6161_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_read, .phy_write = mv88e6xxx_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6165_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_read, .phy_write = mv88e6xxx_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6171_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6172_ops = { @@ -3204,12 +3211,14 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6175_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6176_ops = { @@ -3218,12 +3227,14 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6185_ops = { .set_switch_mac = mv88e6xxx_g1_set_switch_mac, .phy_read = mv88e6xxx_phy_ppu_read, .phy_write = mv88e6xxx_phy_ppu_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6240_ops = { @@ -3232,6 +3243,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6320_ops = { @@ -3240,6 +3252,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6321_ops = { @@ -3248,18 +3261,21 @@ static const struct mv88e6xxx_ops mv88e6321_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6350_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6351_ops = {
[PATCH net-next 05/11] net: dsa: mv88e6xxx: add port PVID accessors
Add port functions to access the ports default VID. Signed-off-by: Vivien Didelot--- drivers/net/dsa/mv88e6xxx/chip.c | 51 drivers/net/dsa/mv88e6xxx/port.c | 38 ++ drivers/net/dsa/mv88e6xxx/port.h | 3 +++ 3 files changed, 45 insertions(+), 47 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 20f59f1..9c0a028 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1288,49 +1288,6 @@ static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port) netdev_err(ds->ports[port].netdev, "failed to flush ATU\n"); } -static int _mv88e6xxx_port_pvid(struct mv88e6xxx_chip *chip, int port, - u16 *new, u16 *old) -{ - struct dsa_switch *ds = chip->ds; - u16 pvid, reg; - int err; - - err = mv88e6xxx_port_read(chip, port, PORT_DEFAULT_VLAN, ); - if (err) - return err; - - pvid = reg & PORT_DEFAULT_VLAN_MASK; - - if (new) { - reg &= ~PORT_DEFAULT_VLAN_MASK; - reg |= *new & PORT_DEFAULT_VLAN_MASK; - - err = mv88e6xxx_port_write(chip, port, PORT_DEFAULT_VLAN, reg); - if (err) - return err; - - netdev_dbg(ds->ports[port].netdev, - "DefaultVID %d (was %d)\n", *new, pvid); - } - - if (old) - *old = pvid; - - return 0; -} - -static int _mv88e6xxx_port_pvid_get(struct mv88e6xxx_chip *chip, - int port, u16 *pvid) -{ - return _mv88e6xxx_port_pvid(chip, port, NULL, pvid); -} - -static int _mv88e6xxx_port_pvid_set(struct mv88e6xxx_chip *chip, - int port, u16 pvid) -{ - return _mv88e6xxx_port_pvid(chip, port, , NULL); -} - static int _mv88e6xxx_vtu_wait(struct mv88e6xxx_chip *chip) { return mv88e6xxx_g1_wait(chip, GLOBAL_VTU_OP, GLOBAL_VTU_OP_BUSY); @@ -1510,7 +1467,7 @@ static int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port, mutex_lock(>reg_lock); - err = _mv88e6xxx_port_pvid_get(chip, port, ); + err = mv88e6xxx_port_get_pvid(chip, port, ); if (err) goto unlock; @@ -1958,7 +1915,7 @@ static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, "failed to add VLAN %d%c\n", vid, untagged ? 'u' : 't'); - if (pvid && _mv88e6xxx_port_pvid_set(chip, port, vlan->vid_end)) + if (pvid && mv88e6xxx_port_set_pvid(chip, port, vlan->vid_end)) netdev_err(ds->ports[port].netdev, "failed to set PVID %d\n", vlan->vid_end); @@ -2013,7 +1970,7 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, mutex_lock(>reg_lock); - err = _mv88e6xxx_port_pvid_get(chip, port, ); + err = mv88e6xxx_port_get_pvid(chip, port, ); if (err) goto unlock; @@ -2023,7 +1980,7 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, goto unlock; if (vid == pvid) { - err = _mv88e6xxx_port_pvid_set(chip, port, 0); + err = mv88e6xxx_port_set_pvid(chip, port, 0); if (err) goto unlock; } diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index a7da812..104fe2d 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -152,3 +152,41 @@ int mv88e6xxx_port_set_fid(struct mv88e6xxx_chip *chip, int port, u16 fid) return 0; } + +/* Offset 0x07: Default Port VLAN ID & Priority */ + +int mv88e6xxx_port_get_pvid(struct mv88e6xxx_chip *chip, int port, u16 *pvid) +{ + u16 reg; + int err; + + err = mv88e6xxx_port_read(chip, port, PORT_DEFAULT_VLAN, ); + if (err) + return err; + + *pvid = reg & PORT_DEFAULT_VLAN_MASK; + + return 0; +} + +int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid) +{ + u16 reg; + int err; + + err = mv88e6xxx_port_read(chip, port, PORT_DEFAULT_VLAN, ); + if (err) + return err; + + reg &= ~PORT_DEFAULT_VLAN_MASK; + reg |= pvid & PORT_DEFAULT_VLAN_MASK; + + err = mv88e6xxx_port_write(chip, port, PORT_DEFAULT_VLAN, reg); + if (err) + return err; + + netdev_dbg(chip->ds->ports[port].netdev, "DefaultVID set to %u\n", + pvid); + + return 0; +} diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index 0df29b9..4489d9e 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -28,4 +28,7 @@ int
[PATCH net-next 07/11] net: dsa: mv88e6xxx: add port link setter
Most of the chips will have a port register control bits to force the port's link up, down, or let normal link detection occurs. Implement such operation to use it later when setting duplex, etc. Signed-off-by: Vivien Didelot --- drivers/net/dsa/mv88e6xxx/chip.c | 17 + drivers/net/dsa/mv88e6xxx/mv88e6xxx.h | 8 drivers/net/dsa/mv88e6xxx/port.c | 33 + drivers/net/dsa/mv88e6xxx/port.h | 2 ++ 4 files changed, 60 insertions(+) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 181d3b9..cc43e6f 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -3160,42 +3160,49 @@ static const struct mv88e6xxx_ops mv88e6085_ops = { .set_switch_mac = mv88e6xxx_g1_set_switch_mac, .phy_read = mv88e6xxx_phy_ppu_read, .phy_write = mv88e6xxx_phy_ppu_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6095_ops = { .set_switch_mac = mv88e6xxx_g1_set_switch_mac, .phy_read = mv88e6xxx_phy_ppu_read, .phy_write = mv88e6xxx_phy_ppu_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6123_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_read, .phy_write = mv88e6xxx_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6131_ops = { .set_switch_mac = mv88e6xxx_g1_set_switch_mac, .phy_read = mv88e6xxx_phy_ppu_read, .phy_write = mv88e6xxx_phy_ppu_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6161_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_read, .phy_write = mv88e6xxx_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6165_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_read, .phy_write = mv88e6xxx_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6171_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6172_ops = { @@ -3204,12 +3211,14 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6175_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6176_ops = { @@ -3218,12 +3227,14 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6185_ops = { .set_switch_mac = mv88e6xxx_g1_set_switch_mac, .phy_read = mv88e6xxx_phy_ppu_read, .phy_write = mv88e6xxx_phy_ppu_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6240_ops = { @@ -3232,6 +3243,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6320_ops = { @@ -3240,6 +3252,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6321_ops = { @@ -3248,18 +3261,21 @@ static const struct mv88e6xxx_ops mv88e6321_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6350_ops = { .set_switch_mac = mv88e6xxx_g2_set_switch_mac, .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, + .port_set_link = mv88e6xxx_port_set_link, }; static const struct mv88e6xxx_ops mv88e6351_ops = { .set_switch_mac =
[PATCH net-next 05/11] net: dsa: mv88e6xxx: add port PVID accessors
Add port functions to access the ports default VID. Signed-off-by: Vivien Didelot --- drivers/net/dsa/mv88e6xxx/chip.c | 51 drivers/net/dsa/mv88e6xxx/port.c | 38 ++ drivers/net/dsa/mv88e6xxx/port.h | 3 +++ 3 files changed, 45 insertions(+), 47 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 20f59f1..9c0a028 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1288,49 +1288,6 @@ static void mv88e6xxx_port_fast_age(struct dsa_switch *ds, int port) netdev_err(ds->ports[port].netdev, "failed to flush ATU\n"); } -static int _mv88e6xxx_port_pvid(struct mv88e6xxx_chip *chip, int port, - u16 *new, u16 *old) -{ - struct dsa_switch *ds = chip->ds; - u16 pvid, reg; - int err; - - err = mv88e6xxx_port_read(chip, port, PORT_DEFAULT_VLAN, ); - if (err) - return err; - - pvid = reg & PORT_DEFAULT_VLAN_MASK; - - if (new) { - reg &= ~PORT_DEFAULT_VLAN_MASK; - reg |= *new & PORT_DEFAULT_VLAN_MASK; - - err = mv88e6xxx_port_write(chip, port, PORT_DEFAULT_VLAN, reg); - if (err) - return err; - - netdev_dbg(ds->ports[port].netdev, - "DefaultVID %d (was %d)\n", *new, pvid); - } - - if (old) - *old = pvid; - - return 0; -} - -static int _mv88e6xxx_port_pvid_get(struct mv88e6xxx_chip *chip, - int port, u16 *pvid) -{ - return _mv88e6xxx_port_pvid(chip, port, NULL, pvid); -} - -static int _mv88e6xxx_port_pvid_set(struct mv88e6xxx_chip *chip, - int port, u16 pvid) -{ - return _mv88e6xxx_port_pvid(chip, port, , NULL); -} - static int _mv88e6xxx_vtu_wait(struct mv88e6xxx_chip *chip) { return mv88e6xxx_g1_wait(chip, GLOBAL_VTU_OP, GLOBAL_VTU_OP_BUSY); @@ -1510,7 +1467,7 @@ static int mv88e6xxx_port_vlan_dump(struct dsa_switch *ds, int port, mutex_lock(>reg_lock); - err = _mv88e6xxx_port_pvid_get(chip, port, ); + err = mv88e6xxx_port_get_pvid(chip, port, ); if (err) goto unlock; @@ -1958,7 +1915,7 @@ static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, "failed to add VLAN %d%c\n", vid, untagged ? 'u' : 't'); - if (pvid && _mv88e6xxx_port_pvid_set(chip, port, vlan->vid_end)) + if (pvid && mv88e6xxx_port_set_pvid(chip, port, vlan->vid_end)) netdev_err(ds->ports[port].netdev, "failed to set PVID %d\n", vlan->vid_end); @@ -2013,7 +1970,7 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, mutex_lock(>reg_lock); - err = _mv88e6xxx_port_pvid_get(chip, port, ); + err = mv88e6xxx_port_get_pvid(chip, port, ); if (err) goto unlock; @@ -2023,7 +1980,7 @@ static int mv88e6xxx_port_vlan_del(struct dsa_switch *ds, int port, goto unlock; if (vid == pvid) { - err = _mv88e6xxx_port_pvid_set(chip, port, 0); + err = mv88e6xxx_port_set_pvid(chip, port, 0); if (err) goto unlock; } diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index a7da812..104fe2d 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -152,3 +152,41 @@ int mv88e6xxx_port_set_fid(struct mv88e6xxx_chip *chip, int port, u16 fid) return 0; } + +/* Offset 0x07: Default Port VLAN ID & Priority */ + +int mv88e6xxx_port_get_pvid(struct mv88e6xxx_chip *chip, int port, u16 *pvid) +{ + u16 reg; + int err; + + err = mv88e6xxx_port_read(chip, port, PORT_DEFAULT_VLAN, ); + if (err) + return err; + + *pvid = reg & PORT_DEFAULT_VLAN_MASK; + + return 0; +} + +int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid) +{ + u16 reg; + int err; + + err = mv88e6xxx_port_read(chip, port, PORT_DEFAULT_VLAN, ); + if (err) + return err; + + reg &= ~PORT_DEFAULT_VLAN_MASK; + reg |= pvid & PORT_DEFAULT_VLAN_MASK; + + err = mv88e6xxx_port_write(chip, port, PORT_DEFAULT_VLAN, reg); + if (err) + return err; + + netdev_dbg(chip->ds->ports[port].netdev, "DefaultVID set to %u\n", + pvid); + + return 0; +} diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index 0df29b9..4489d9e 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -28,4 +28,7 @@ int mv88e6xxx_port_set_vlan_map(struct
[PATCH net-next 08/11] net: dsa: mv88e6xxx: add port duplex setter
Similarly to port's link, add setter to force port's half duplex, full duplex or let normal duplex detection occurs. Signed-off-by: Vivien Didelot--- drivers/net/dsa/mv88e6xxx/chip.c | 17 + drivers/net/dsa/mv88e6xxx/mv88e6xxx.h | 7 +++ drivers/net/dsa/mv88e6xxx/port.c | 34 ++ drivers/net/dsa/mv88e6xxx/port.h | 2 ++ 4 files changed, 60 insertions(+) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index cc43e6f..49a6935 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -3161,6 +3161,7 @@ static const struct mv88e6xxx_ops mv88e6085_ops = { .phy_read = mv88e6xxx_phy_ppu_read, .phy_write = mv88e6xxx_phy_ppu_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6095_ops = { @@ -3168,6 +3169,7 @@ static const struct mv88e6xxx_ops mv88e6095_ops = { .phy_read = mv88e6xxx_phy_ppu_read, .phy_write = mv88e6xxx_phy_ppu_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6123_ops = { @@ -3175,6 +3177,7 @@ static const struct mv88e6xxx_ops mv88e6123_ops = { .phy_read = mv88e6xxx_read, .phy_write = mv88e6xxx_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6131_ops = { @@ -3182,6 +3185,7 @@ static const struct mv88e6xxx_ops mv88e6131_ops = { .phy_read = mv88e6xxx_phy_ppu_read, .phy_write = mv88e6xxx_phy_ppu_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6161_ops = { @@ -3189,6 +3193,7 @@ static const struct mv88e6xxx_ops mv88e6161_ops = { .phy_read = mv88e6xxx_read, .phy_write = mv88e6xxx_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6165_ops = { @@ -3196,6 +3201,7 @@ static const struct mv88e6xxx_ops mv88e6165_ops = { .phy_read = mv88e6xxx_read, .phy_write = mv88e6xxx_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6171_ops = { @@ -3203,6 +3209,7 @@ static const struct mv88e6xxx_ops mv88e6171_ops = { .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6172_ops = { @@ -3212,6 +3219,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6175_ops = { @@ -3219,6 +3227,7 @@ static const struct mv88e6xxx_ops mv88e6175_ops = { .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6176_ops = { @@ -3228,6 +3237,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6185_ops = { @@ -3235,6 +3245,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = { .phy_read = mv88e6xxx_phy_ppu_read, .phy_write = mv88e6xxx_phy_ppu_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6240_ops = { @@ -3244,6 +3255,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6320_ops = { @@ -3253,6 +3265,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6321_ops = { @@ -3262,6 +3275,7 @@ static const struct mv88e6xxx_ops mv88e6321_ops = { .phy_read =
[PATCH net-next 09/11] net: dsa: mv88e6xxx: add port's RGMII delay setter
Some chips such as 88E6352 and 88E6390 can be programmed to add delays to RXCLK for IND inputs or to GTXCLK for OUTD outputs when port is in RGMII mode. Add a port function to program such delays according to the provided PHY interface mode. Signed-off-by: Vivien Didelot--- drivers/net/dsa/mv88e6xxx/chip.c | 4 +++ drivers/net/dsa/mv88e6xxx/mv88e6xxx.h | 6 drivers/net/dsa/mv88e6xxx/port.c | 58 +++ drivers/net/dsa/mv88e6xxx/port.h | 5 +++ 4 files changed, 73 insertions(+) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 49a6935..bb93d0a 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -3220,6 +3220,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, }; static const struct mv88e6xxx_ops mv88e6175_ops = { @@ -3238,6 +3239,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, }; static const struct mv88e6xxx_ops mv88e6185_ops = { @@ -3256,6 +3258,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, }; static const struct mv88e6xxx_ops mv88e6320_ops = { @@ -3302,6 +3305,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, }; static const struct mv88e6xxx_info mv88e6xxx_table[] = { diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h index 35420ed..0d3223b 100644 --- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h @@ -728,6 +728,12 @@ struct mv88e6xxx_ops { int (*phy_write)(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val); + /* RGMII Receive/Transmit Timing Control +* Add delay on PHY_INTERFACE_MODE_RGMII_*ID, no delay otherwise. +*/ + int (*port_set_rgmii_delay)(struct mv88e6xxx_chip *chip, int port, + phy_interface_t mode); + #define LINK_UNKNOWN -1 /* Port's MAC link state diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 386db46..ef6efc9 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -35,6 +35,64 @@ int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, * Link, Duplex and Flow Control have one force bit, one value bit. */ +static int mv88e6xxx_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port, + phy_interface_t mode) +{ + u16 reg; + int err; + + err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, ); + if (err) + return err; + + reg &= ~(PORT_PCS_CTRL_RGMII_DELAY_RXCLK | +PORT_PCS_CTRL_RGMII_DELAY_TXCLK); + + switch (mode) { + case PHY_INTERFACE_MODE_RGMII_RXID: + reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK; + break; + case PHY_INTERFACE_MODE_RGMII_TXID: + reg |= PORT_PCS_CTRL_RGMII_DELAY_TXCLK; + break; + case PHY_INTERFACE_MODE_RGMII_ID: + reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK | + PORT_PCS_CTRL_RGMII_DELAY_TXCLK; + break; + default: + /* no delay */ + break; + } + + err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg); + if (err) + return err; + + netdev_dbg(chip->ds->ports[port].netdev, "delay RXCLK %s, TXCLK %s\n", + reg & PORT_PCS_CTRL_RGMII_DELAY_RXCLK ? "yes" : "no", + reg & PORT_PCS_CTRL_RGMII_DELAY_TXCLK ? "yes" : "no"); + + return 0; +} + +int mv88e6352_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port, + phy_interface_t mode) +{ + if (port < 5) + return -EOPNOTSUPP; + + return mv88e6xxx_port_set_rgmii_delay(chip, port, mode); +} + +int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port, + phy_interface_t mode) +{ + if (port != 0) + return -EOPNOTSUPP; + +
[PATCH net-next 08/11] net: dsa: mv88e6xxx: add port duplex setter
Similarly to port's link, add setter to force port's half duplex, full duplex or let normal duplex detection occurs. Signed-off-by: Vivien Didelot --- drivers/net/dsa/mv88e6xxx/chip.c | 17 + drivers/net/dsa/mv88e6xxx/mv88e6xxx.h | 7 +++ drivers/net/dsa/mv88e6xxx/port.c | 34 ++ drivers/net/dsa/mv88e6xxx/port.h | 2 ++ 4 files changed, 60 insertions(+) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index cc43e6f..49a6935 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -3161,6 +3161,7 @@ static const struct mv88e6xxx_ops mv88e6085_ops = { .phy_read = mv88e6xxx_phy_ppu_read, .phy_write = mv88e6xxx_phy_ppu_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6095_ops = { @@ -3168,6 +3169,7 @@ static const struct mv88e6xxx_ops mv88e6095_ops = { .phy_read = mv88e6xxx_phy_ppu_read, .phy_write = mv88e6xxx_phy_ppu_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6123_ops = { @@ -3175,6 +3177,7 @@ static const struct mv88e6xxx_ops mv88e6123_ops = { .phy_read = mv88e6xxx_read, .phy_write = mv88e6xxx_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6131_ops = { @@ -3182,6 +3185,7 @@ static const struct mv88e6xxx_ops mv88e6131_ops = { .phy_read = mv88e6xxx_phy_ppu_read, .phy_write = mv88e6xxx_phy_ppu_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6161_ops = { @@ -3189,6 +3193,7 @@ static const struct mv88e6xxx_ops mv88e6161_ops = { .phy_read = mv88e6xxx_read, .phy_write = mv88e6xxx_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6165_ops = { @@ -3196,6 +3201,7 @@ static const struct mv88e6xxx_ops mv88e6165_ops = { .phy_read = mv88e6xxx_read, .phy_write = mv88e6xxx_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6171_ops = { @@ -3203,6 +3209,7 @@ static const struct mv88e6xxx_ops mv88e6171_ops = { .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6172_ops = { @@ -3212,6 +3219,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6175_ops = { @@ -3219,6 +3227,7 @@ static const struct mv88e6xxx_ops mv88e6175_ops = { .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6176_ops = { @@ -3228,6 +3237,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6185_ops = { @@ -3235,6 +3245,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = { .phy_read = mv88e6xxx_phy_ppu_read, .phy_write = mv88e6xxx_phy_ppu_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6240_ops = { @@ -3244,6 +3255,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6320_ops = { @@ -3253,6 +3265,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = { .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, + .port_set_duplex = mv88e6xxx_port_set_duplex, }; static const struct mv88e6xxx_ops mv88e6321_ops = { @@ -3262,6 +3275,7 @@ static const struct mv88e6xxx_ops mv88e6321_ops = { .phy_read = mv88e6xxx_g2_smi_phy_read, .phy_write =
[PATCH net-next 09/11] net: dsa: mv88e6xxx: add port's RGMII delay setter
Some chips such as 88E6352 and 88E6390 can be programmed to add delays to RXCLK for IND inputs or to GTXCLK for OUTD outputs when port is in RGMII mode. Add a port function to program such delays according to the provided PHY interface mode. Signed-off-by: Vivien Didelot --- drivers/net/dsa/mv88e6xxx/chip.c | 4 +++ drivers/net/dsa/mv88e6xxx/mv88e6xxx.h | 6 drivers/net/dsa/mv88e6xxx/port.c | 58 +++ drivers/net/dsa/mv88e6xxx/port.h | 5 +++ 4 files changed, 73 insertions(+) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 49a6935..bb93d0a 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -3220,6 +3220,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = { .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, }; static const struct mv88e6xxx_ops mv88e6175_ops = { @@ -3238,6 +3239,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = { .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, }; static const struct mv88e6xxx_ops mv88e6185_ops = { @@ -3256,6 +3258,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = { .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, }; static const struct mv88e6xxx_ops mv88e6320_ops = { @@ -3302,6 +3305,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = { .phy_write = mv88e6xxx_g2_smi_phy_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_rgmii_delay = mv88e6352_port_set_rgmii_delay, }; static const struct mv88e6xxx_info mv88e6xxx_table[] = { diff --git a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h index 35420ed..0d3223b 100644 --- a/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h +++ b/drivers/net/dsa/mv88e6xxx/mv88e6xxx.h @@ -728,6 +728,12 @@ struct mv88e6xxx_ops { int (*phy_write)(struct mv88e6xxx_chip *chip, int addr, int reg, u16 val); + /* RGMII Receive/Transmit Timing Control +* Add delay on PHY_INTERFACE_MODE_RGMII_*ID, no delay otherwise. +*/ + int (*port_set_rgmii_delay)(struct mv88e6xxx_chip *chip, int port, + phy_interface_t mode); + #define LINK_UNKNOWN -1 /* Port's MAC link state diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 386db46..ef6efc9 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -35,6 +35,64 @@ int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg, * Link, Duplex and Flow Control have one force bit, one value bit. */ +static int mv88e6xxx_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port, + phy_interface_t mode) +{ + u16 reg; + int err; + + err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, ); + if (err) + return err; + + reg &= ~(PORT_PCS_CTRL_RGMII_DELAY_RXCLK | +PORT_PCS_CTRL_RGMII_DELAY_TXCLK); + + switch (mode) { + case PHY_INTERFACE_MODE_RGMII_RXID: + reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK; + break; + case PHY_INTERFACE_MODE_RGMII_TXID: + reg |= PORT_PCS_CTRL_RGMII_DELAY_TXCLK; + break; + case PHY_INTERFACE_MODE_RGMII_ID: + reg |= PORT_PCS_CTRL_RGMII_DELAY_RXCLK | + PORT_PCS_CTRL_RGMII_DELAY_TXCLK; + break; + default: + /* no delay */ + break; + } + + err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg); + if (err) + return err; + + netdev_dbg(chip->ds->ports[port].netdev, "delay RXCLK %s, TXCLK %s\n", + reg & PORT_PCS_CTRL_RGMII_DELAY_RXCLK ? "yes" : "no", + reg & PORT_PCS_CTRL_RGMII_DELAY_TXCLK ? "yes" : "no"); + + return 0; +} + +int mv88e6352_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port, + phy_interface_t mode) +{ + if (port < 5) + return -EOPNOTSUPP; + + return mv88e6xxx_port_set_rgmii_delay(chip, port, mode); +} + +int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port, + phy_interface_t mode) +{ + if (port != 0) + return -EOPNOTSUPP; + + return
[PATCH net-next 06/11] net: dsa: mv88e6xxx: add port 802.1Q mode setter
Add port functions to set the port 802.1Q mode. Signed-off-by: Vivien Didelot--- drivers/net/dsa/mv88e6xxx/chip.c | 33 ++--- drivers/net/dsa/mv88e6xxx/port.c | 32 drivers/net/dsa/mv88e6xxx/port.h | 3 +++ 3 files changed, 37 insertions(+), 31 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 9c0a028..181d3b9 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1806,48 +1806,19 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port, return err; } -static const char * const mv88e6xxx_port_8021q_mode_names[] = { - [PORT_CONTROL_2_8021Q_DISABLED] = "Disabled", - [PORT_CONTROL_2_8021Q_FALLBACK] = "Fallback", - [PORT_CONTROL_2_8021Q_CHECK] = "Check", - [PORT_CONTROL_2_8021Q_SECURE] = "Secure", -}; - static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering) { struct mv88e6xxx_chip *chip = ds->priv; - u16 old, new = vlan_filtering ? PORT_CONTROL_2_8021Q_SECURE : + u16 mode = vlan_filtering ? PORT_CONTROL_2_8021Q_SECURE : PORT_CONTROL_2_8021Q_DISABLED; - u16 reg; int err; if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_VTU)) return -EOPNOTSUPP; mutex_lock(>reg_lock); - - err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, ); - if (err) - goto unlock; - - old = reg & PORT_CONTROL_2_8021Q_MASK; - - if (new != old) { - reg &= ~PORT_CONTROL_2_8021Q_MASK; - reg |= new & PORT_CONTROL_2_8021Q_MASK; - - err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg); - if (err) - goto unlock; - - netdev_dbg(ds->ports[port].netdev, "802.1Q Mode %s (was %s)\n", - mv88e6xxx_port_8021q_mode_names[new], - mv88e6xxx_port_8021q_mode_names[old]); - } - - err = 0; -unlock: + err = mv88e6xxx_port_set_8021q_mode(chip, port, mode); mutex_unlock(>reg_lock); return err; diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 104fe2d..53d17e6 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -190,3 +190,35 @@ int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid) return 0; } + +/* Offset 0x08: Port Control 2 Register */ + +static const char * const mv88e6xxx_port_8021q_mode_names[] = { + [PORT_CONTROL_2_8021Q_DISABLED] = "Disabled", + [PORT_CONTROL_2_8021Q_FALLBACK] = "Fallback", + [PORT_CONTROL_2_8021Q_CHECK] = "Check", + [PORT_CONTROL_2_8021Q_SECURE] = "Secure", +}; + +int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port, + u16 mode) +{ + u16 reg; + int err; + + err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, ); + if (err) + return err; + + reg &= ~PORT_CONTROL_2_8021Q_MASK; + reg |= mode & PORT_CONTROL_2_8021Q_MASK; + + err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg); + if (err) + return err; + + netdev_dbg(chip->ds->ports[port].netdev, "802.1QMode set to %s\n", + mv88e6xxx_port_8021q_mode_names[mode]); + + return 0; +} diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index 4489d9e..921eecf 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -31,4 +31,7 @@ int mv88e6xxx_port_set_fid(struct mv88e6xxx_chip *chip, int port, u16 fid); int mv88e6xxx_port_get_pvid(struct mv88e6xxx_chip *chip, int port, u16 *pvid); int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid); +int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port, + u16 mode); + #endif /* _MV88E6XXX_PORT_H */ -- 2.10.2
[PATCH net-next 10/11] net: dsa: mv88e6xxx: add port's MAC speed setter
While the two bits for link, duplex or RGMII delays are used the same way on chips supporting the said feature, the two bits for speed have different meaning for most of the chips out there. Speed value is stored in bits 1:0, 0x3 means unforce (normal detection). Some chips reuse values for alternative speeds when bit 12 is set. Newer chips with speed > 1Gbps reuse value 0x3 thus need a new bit 13. Here are the values to write in register 0x1 to (un)force speed: | Speed | 88E6065 | 88E6185 | 88E6352 | 88E6390 | 88E6390X | | --- | --- | --- | --- | --- | | | 10 | 0x | 0x | 0x | 0x2000 | 0x2000 | | 100 | 0x0001 | 0x0001 | 0x0001 | 0x2001 | 0x2001 | | 200 | 0x0002 | NA | 0x1001 | 0x3001 | 0x3001 | | 1000| NA | 0x0002 | 0x0002 | 0x2002 | 0x2002 | | 2500| NA | NA | NA | 0x3003 | 0x3003 | | 1 | NA | NA | NA | NA | 0x2003 | | unforce | 0x0003 | 0x0003 | 0x0003 | 0x | 0x | This patch implements a generic mv88e6xxx_port_set_speed() function used by chip-specific wrappers to filter supported ports and speeds. Signed-off-by: Vivien Didelot--- drivers/net/dsa/mv88e6xxx/chip.c | 33 ++-- drivers/net/dsa/mv88e6xxx/mv88e6xxx.h | 23 +- drivers/net/dsa/mv88e6xxx/port.c | 138 ++ drivers/net/dsa/mv88e6xxx/port.h | 6 ++ 4 files changed, 188 insertions(+), 12 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index bb93d0a..23c05e3 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -725,7 +725,7 @@ static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port, PORT_PCS_CTRL_FORCE_LINK | PORT_PCS_CTRL_DUPLEX_FULL | PORT_PCS_CTRL_FORCE_DUPLEX | -PORT_PCS_CTRL_UNFORCED); +PORT_PCS_CTRL_SPEED_UNFORCED); reg |= PORT_PCS_CTRL_FORCE_LINK; if (phydev->link) @@ -736,13 +736,13 @@ static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port, switch (phydev->speed) { case SPEED_1000: - reg |= PORT_PCS_CTRL_1000; + reg |= PORT_PCS_CTRL_SPEED_1000; break; case SPEED_100: - reg |= PORT_PCS_CTRL_100; + reg |= PORT_PCS_CTRL_SPEED_100; break; case SPEED_10: - reg |= PORT_PCS_CTRL_10; + reg |= PORT_PCS_CTRL_SPEED_10; break; default: pr_info("Unknown speed"); @@ -2421,17 +2421,17 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) */ err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, ); if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) { - reg &= ~PORT_PCS_CTRL_UNFORCED; + reg &= ~PORT_PCS_CTRL_SPEED_UNFORCED; reg |= PORT_PCS_CTRL_FORCE_LINK | PORT_PCS_CTRL_LINK_UP | PORT_PCS_CTRL_DUPLEX_FULL | PORT_PCS_CTRL_FORCE_DUPLEX; if (mv88e6xxx_6065_family(chip)) - reg |= PORT_PCS_CTRL_100; + reg |= PORT_PCS_CTRL_SPEED_100; else - reg |= PORT_PCS_CTRL_1000; + reg |= PORT_PCS_CTRL_SPEED_1000; } else { - reg |= PORT_PCS_CTRL_UNFORCED; + reg |= PORT_PCS_CTRL_SPEED_UNFORCED; } err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg); @@ -3162,6 +3162,7 @@ static const struct mv88e6xxx_ops mv88e6085_ops = { .phy_write = mv88e6xxx_phy_ppu_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_speed = mv88e6185_port_set_speed, }; static const struct mv88e6xxx_ops mv88e6095_ops = { @@ -3170,6 +3171,7 @@ static const struct mv88e6xxx_ops mv88e6095_ops = { .phy_write = mv88e6xxx_phy_ppu_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_speed = mv88e6185_port_set_speed, }; static const struct mv88e6xxx_ops mv88e6123_ops = { @@ -3178,6 +3180,7 @@ static const struct mv88e6xxx_ops mv88e6123_ops = { .phy_write = mv88e6xxx_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_speed = mv88e6185_port_set_speed, }; static const struct mv88e6xxx_ops mv88e6131_ops = { @@ -3186,6 +3189,7 @@ static const struct mv88e6xxx_ops mv88e6131_ops = {
[PATCH net-next 06/11] net: dsa: mv88e6xxx: add port 802.1Q mode setter
Add port functions to set the port 802.1Q mode. Signed-off-by: Vivien Didelot --- drivers/net/dsa/mv88e6xxx/chip.c | 33 ++--- drivers/net/dsa/mv88e6xxx/port.c | 32 drivers/net/dsa/mv88e6xxx/port.h | 3 +++ 3 files changed, 37 insertions(+), 31 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 9c0a028..181d3b9 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1806,48 +1806,19 @@ static int mv88e6xxx_port_check_hw_vlan(struct dsa_switch *ds, int port, return err; } -static const char * const mv88e6xxx_port_8021q_mode_names[] = { - [PORT_CONTROL_2_8021Q_DISABLED] = "Disabled", - [PORT_CONTROL_2_8021Q_FALLBACK] = "Fallback", - [PORT_CONTROL_2_8021Q_CHECK] = "Check", - [PORT_CONTROL_2_8021Q_SECURE] = "Secure", -}; - static int mv88e6xxx_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering) { struct mv88e6xxx_chip *chip = ds->priv; - u16 old, new = vlan_filtering ? PORT_CONTROL_2_8021Q_SECURE : + u16 mode = vlan_filtering ? PORT_CONTROL_2_8021Q_SECURE : PORT_CONTROL_2_8021Q_DISABLED; - u16 reg; int err; if (!mv88e6xxx_has(chip, MV88E6XXX_FLAG_VTU)) return -EOPNOTSUPP; mutex_lock(>reg_lock); - - err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, ); - if (err) - goto unlock; - - old = reg & PORT_CONTROL_2_8021Q_MASK; - - if (new != old) { - reg &= ~PORT_CONTROL_2_8021Q_MASK; - reg |= new & PORT_CONTROL_2_8021Q_MASK; - - err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg); - if (err) - goto unlock; - - netdev_dbg(ds->ports[port].netdev, "802.1Q Mode %s (was %s)\n", - mv88e6xxx_port_8021q_mode_names[new], - mv88e6xxx_port_8021q_mode_names[old]); - } - - err = 0; -unlock: + err = mv88e6xxx_port_set_8021q_mode(chip, port, mode); mutex_unlock(>reg_lock); return err; diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c index 104fe2d..53d17e6 100644 --- a/drivers/net/dsa/mv88e6xxx/port.c +++ b/drivers/net/dsa/mv88e6xxx/port.c @@ -190,3 +190,35 @@ int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid) return 0; } + +/* Offset 0x08: Port Control 2 Register */ + +static const char * const mv88e6xxx_port_8021q_mode_names[] = { + [PORT_CONTROL_2_8021Q_DISABLED] = "Disabled", + [PORT_CONTROL_2_8021Q_FALLBACK] = "Fallback", + [PORT_CONTROL_2_8021Q_CHECK] = "Check", + [PORT_CONTROL_2_8021Q_SECURE] = "Secure", +}; + +int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port, + u16 mode) +{ + u16 reg; + int err; + + err = mv88e6xxx_port_read(chip, port, PORT_CONTROL_2, ); + if (err) + return err; + + reg &= ~PORT_CONTROL_2_8021Q_MASK; + reg |= mode & PORT_CONTROL_2_8021Q_MASK; + + err = mv88e6xxx_port_write(chip, port, PORT_CONTROL_2, reg); + if (err) + return err; + + netdev_dbg(chip->ds->ports[port].netdev, "802.1QMode set to %s\n", + mv88e6xxx_port_8021q_mode_names[mode]); + + return 0; +} diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h index 4489d9e..921eecf 100644 --- a/drivers/net/dsa/mv88e6xxx/port.h +++ b/drivers/net/dsa/mv88e6xxx/port.h @@ -31,4 +31,7 @@ int mv88e6xxx_port_set_fid(struct mv88e6xxx_chip *chip, int port, u16 fid); int mv88e6xxx_port_get_pvid(struct mv88e6xxx_chip *chip, int port, u16 *pvid); int mv88e6xxx_port_set_pvid(struct mv88e6xxx_chip *chip, int port, u16 pvid); +int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port, + u16 mode); + #endif /* _MV88E6XXX_PORT_H */ -- 2.10.2
[PATCH net-next 10/11] net: dsa: mv88e6xxx: add port's MAC speed setter
While the two bits for link, duplex or RGMII delays are used the same way on chips supporting the said feature, the two bits for speed have different meaning for most of the chips out there. Speed value is stored in bits 1:0, 0x3 means unforce (normal detection). Some chips reuse values for alternative speeds when bit 12 is set. Newer chips with speed > 1Gbps reuse value 0x3 thus need a new bit 13. Here are the values to write in register 0x1 to (un)force speed: | Speed | 88E6065 | 88E6185 | 88E6352 | 88E6390 | 88E6390X | | --- | --- | --- | --- | --- | | | 10 | 0x | 0x | 0x | 0x2000 | 0x2000 | | 100 | 0x0001 | 0x0001 | 0x0001 | 0x2001 | 0x2001 | | 200 | 0x0002 | NA | 0x1001 | 0x3001 | 0x3001 | | 1000| NA | 0x0002 | 0x0002 | 0x2002 | 0x2002 | | 2500| NA | NA | NA | 0x3003 | 0x3003 | | 1 | NA | NA | NA | NA | 0x2003 | | unforce | 0x0003 | 0x0003 | 0x0003 | 0x | 0x | This patch implements a generic mv88e6xxx_port_set_speed() function used by chip-specific wrappers to filter supported ports and speeds. Signed-off-by: Vivien Didelot --- drivers/net/dsa/mv88e6xxx/chip.c | 33 ++-- drivers/net/dsa/mv88e6xxx/mv88e6xxx.h | 23 +- drivers/net/dsa/mv88e6xxx/port.c | 138 ++ drivers/net/dsa/mv88e6xxx/port.h | 6 ++ 4 files changed, 188 insertions(+), 12 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index bb93d0a..23c05e3 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -725,7 +725,7 @@ static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port, PORT_PCS_CTRL_FORCE_LINK | PORT_PCS_CTRL_DUPLEX_FULL | PORT_PCS_CTRL_FORCE_DUPLEX | -PORT_PCS_CTRL_UNFORCED); +PORT_PCS_CTRL_SPEED_UNFORCED); reg |= PORT_PCS_CTRL_FORCE_LINK; if (phydev->link) @@ -736,13 +736,13 @@ static void mv88e6xxx_adjust_link(struct dsa_switch *ds, int port, switch (phydev->speed) { case SPEED_1000: - reg |= PORT_PCS_CTRL_1000; + reg |= PORT_PCS_CTRL_SPEED_1000; break; case SPEED_100: - reg |= PORT_PCS_CTRL_100; + reg |= PORT_PCS_CTRL_SPEED_100; break; case SPEED_10: - reg |= PORT_PCS_CTRL_10; + reg |= PORT_PCS_CTRL_SPEED_10; break; default: pr_info("Unknown speed"); @@ -2421,17 +2421,17 @@ static int mv88e6xxx_setup_port(struct mv88e6xxx_chip *chip, int port) */ err = mv88e6xxx_port_read(chip, port, PORT_PCS_CTRL, ); if (dsa_is_cpu_port(ds, port) || dsa_is_dsa_port(ds, port)) { - reg &= ~PORT_PCS_CTRL_UNFORCED; + reg &= ~PORT_PCS_CTRL_SPEED_UNFORCED; reg |= PORT_PCS_CTRL_FORCE_LINK | PORT_PCS_CTRL_LINK_UP | PORT_PCS_CTRL_DUPLEX_FULL | PORT_PCS_CTRL_FORCE_DUPLEX; if (mv88e6xxx_6065_family(chip)) - reg |= PORT_PCS_CTRL_100; + reg |= PORT_PCS_CTRL_SPEED_100; else - reg |= PORT_PCS_CTRL_1000; + reg |= PORT_PCS_CTRL_SPEED_1000; } else { - reg |= PORT_PCS_CTRL_UNFORCED; + reg |= PORT_PCS_CTRL_SPEED_UNFORCED; } err = mv88e6xxx_port_write(chip, port, PORT_PCS_CTRL, reg); @@ -3162,6 +3162,7 @@ static const struct mv88e6xxx_ops mv88e6085_ops = { .phy_write = mv88e6xxx_phy_ppu_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_speed = mv88e6185_port_set_speed, }; static const struct mv88e6xxx_ops mv88e6095_ops = { @@ -3170,6 +3171,7 @@ static const struct mv88e6xxx_ops mv88e6095_ops = { .phy_write = mv88e6xxx_phy_ppu_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_speed = mv88e6185_port_set_speed, }; static const struct mv88e6xxx_ops mv88e6123_ops = { @@ -3178,6 +3180,7 @@ static const struct mv88e6xxx_ops mv88e6123_ops = { .phy_write = mv88e6xxx_write, .port_set_link = mv88e6xxx_port_set_link, .port_set_duplex = mv88e6xxx_port_set_duplex, + .port_set_speed = mv88e6185_port_set_speed, }; static const struct mv88e6xxx_ops mv88e6131_ops = { @@ -3186,6 +3189,7 @@ static const struct mv88e6xxx_ops mv88e6131_ops = { .phy_write =
[PATCH net-next 00/11] net: dsa: mv88e6xxx: refine port operations
The Marvell chips have one internal SMI device per port, containing a set of registers used to configure a port's link, STP state, default VLAN or addresses database, etc. This patchset creates port files to implement the port operations as described in datasheets, and extend the chip ops structure with them. Patches 1 to 6 implement accessors for port's STP state, port based VLAN map, default FID, default VID, and 802.1Q mode. Patches 7 to 11 implement the port's MAC setup of link state, duplex mode, RGMII delay and speed, all accessed through port's register 0x01. The new port's MAC setup code is used to re-implement the adjust_link code and correctly force the link down before changing any of the MAC settings, as requested by the datasheets. The port's MAC accessors use values compatible with struct phy_device (e.g. DUPLEX_FULL) and extend them when needed (e.g. SPEED_MAX). Vivien Didelot (11): net: dsa: mv88e6xxx: add port files net: dsa: mv88e6xxx: add port state setter net: dsa: mv88e6xxx: add port vlan map setter net: dsa: mv88e6xxx: add port FID accessors net: dsa: mv88e6xxx: add port PVID accessors net: dsa: mv88e6xxx: add port 802.1Q mode setter net: dsa: mv88e6xxx: add port link setter net: dsa: mv88e6xxx: add port duplex setter net: dsa: mv88e6xxx: add port's RGMII delay setter net: dsa: mv88e6xxx: add port's MAC speed setter net: dsa: mv88e6xxx: setup port's MAC drivers/net/dsa/mv88e6xxx/Makefile| 1 + drivers/net/dsa/mv88e6xxx/chip.c | 434 +- drivers/net/dsa/mv88e6xxx/mv88e6xxx.h | 44 ++- drivers/net/dsa/mv88e6xxx/port.c | 487 ++ drivers/net/dsa/mv88e6xxx/port.h | 52 5 files changed, 710 insertions(+), 308 deletions(-) create mode 100644 drivers/net/dsa/mv88e6xxx/port.c create mode 100644 drivers/net/dsa/mv88e6xxx/port.h -- 2.10.2
[PATCH net-next 00/11] net: dsa: mv88e6xxx: refine port operations
The Marvell chips have one internal SMI device per port, containing a set of registers used to configure a port's link, STP state, default VLAN or addresses database, etc. This patchset creates port files to implement the port operations as described in datasheets, and extend the chip ops structure with them. Patches 1 to 6 implement accessors for port's STP state, port based VLAN map, default FID, default VID, and 802.1Q mode. Patches 7 to 11 implement the port's MAC setup of link state, duplex mode, RGMII delay and speed, all accessed through port's register 0x01. The new port's MAC setup code is used to re-implement the adjust_link code and correctly force the link down before changing any of the MAC settings, as requested by the datasheets. The port's MAC accessors use values compatible with struct phy_device (e.g. DUPLEX_FULL) and extend them when needed (e.g. SPEED_MAX). Vivien Didelot (11): net: dsa: mv88e6xxx: add port files net: dsa: mv88e6xxx: add port state setter net: dsa: mv88e6xxx: add port vlan map setter net: dsa: mv88e6xxx: add port FID accessors net: dsa: mv88e6xxx: add port PVID accessors net: dsa: mv88e6xxx: add port 802.1Q mode setter net: dsa: mv88e6xxx: add port link setter net: dsa: mv88e6xxx: add port duplex setter net: dsa: mv88e6xxx: add port's RGMII delay setter net: dsa: mv88e6xxx: add port's MAC speed setter net: dsa: mv88e6xxx: setup port's MAC drivers/net/dsa/mv88e6xxx/Makefile| 1 + drivers/net/dsa/mv88e6xxx/chip.c | 434 +- drivers/net/dsa/mv88e6xxx/mv88e6xxx.h | 44 ++- drivers/net/dsa/mv88e6xxx/port.c | 487 ++ drivers/net/dsa/mv88e6xxx/port.h | 52 5 files changed, 710 insertions(+), 308 deletions(-) create mode 100644 drivers/net/dsa/mv88e6xxx/port.c create mode 100644 drivers/net/dsa/mv88e6xxx/port.h -- 2.10.2
Re: [PATCH v1] usb: dwc3: gadget: wait for End Transfer to complete
Hi, On 31 October 2016 at 20:53, Felipe Balbiwrote: > > Hi, > > Baolin Wang writes: >> Instead of just delaying for 100us, we should >> actually wait for End Transfer Command Complete >> interrupt before moving on. Note that this should >> only be done if we're dealing with one of the core >> revisions that actually require the interrupt before >> moving on. >> >> [ felipe.ba...@linux.intel.com: minor improvements ] >> >> Signed-off-by: Baolin Wang > > I made one extra modification to prevent us from checking for > pm_runtime_suspended() twice: > > commit 8f48e8d6d3dfe75b5582c8a7b1ee5739a393748c > Author: Baolin Wang > Date: Mon Oct 31 19:38:36 2016 +0800 > > usb: dwc3: gadget: wait for End Transfer to complete > > Instead of just delaying for 100us, we should > actually wait for End Transfer Command Complete > interrupt before moving on. Note that this should > only be done if we're dealing with one of the core > revisions that actually require the interrupt before > moving on. > > [ felipe.ba...@linux.intel.com: minor improvements ] > > Signed-off-by: Baolin Wang > Signed-off-by: Felipe Balbi > > diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h > index 5fc437021ac7..c2b86856e85d 100644 > --- a/drivers/usb/dwc3/core.h > +++ b/drivers/usb/dwc3/core.h > @@ -26,6 +26,7 @@ > #include > #include > #include > +#include > > #include > #include > @@ -505,6 +506,7 @@ struct dwc3_event_buffer { > * @endpoint: usb endpoint > * @pending_list: list of pending requests for this endpoint > * @started_list: list of started requests on this endpoint > + * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete > * @lock: spinlock for endpoint request queue traversal > * @regs: pointer to first endpoint register > * @trb_pool: array of transaction buffers > @@ -530,6 +532,8 @@ struct dwc3_ep { > struct list_headpending_list; > struct list_headstarted_list; > > + wait_queue_head_t wait_end_transfer; > + > spinlock_t lock; > void __iomem*regs; > > @@ -546,6 +550,7 @@ struct dwc3_ep { > #define DWC3_EP_BUSY (1 << 4) > #define DWC3_EP_PENDING_REQUEST(1 << 5) > #define DWC3_EP_MISSED_ISOC(1 << 6) > +#define DWC3_EP_END_TRANSFER_PENDING (1 << 7) > > /* This last one is specific to EP0 */ > #define DWC3_EP0_DIR_IN(1 << 31) > @@ -1050,6 +1055,9 @@ struct dwc3_event_depevt { > #define DEPEVT_TRANSFER_BUS_EXPIRY 2 > > u32 parameters:16; > + > +/* For Command Complete Events */ > +#define DEPEVT_PARAMETER_CMD(n)(((n) & (0xf << 8)) >> 8) > } __packed; > > /** > diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c > index 3b53a5714df4..d544e7369776 100644 > --- a/drivers/usb/dwc3/gadget.c > +++ b/drivers/usb/dwc3/gadget.c > @@ -593,11 +593,14 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, > dep->comp_desc = comp_desc; > dep->type = usb_endpoint_type(desc); > dep->flags |= DWC3_EP_ENABLED; > + dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING; > > reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); > reg |= DWC3_DALEPENA_EP(dep->number); > dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); > > + init_waitqueue_head(>wait_end_transfer); > + > if (usb_endpoint_xfer_control(desc)) > return 0; > > @@ -699,7 +702,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) > dep->endpoint.desc = NULL; > dep->comp_desc = NULL; > dep->type = 0; > - dep->flags = 0; > + dep->flags &= DWC3_EP_END_TRANSFER_PENDING; > > return 0; > } > @@ -1783,9 +1786,6 @@ static int dwc3_gadget_start(struct usb_gadget *g, > > static void __dwc3_gadget_stop(struct dwc3 *dwc) > { > - if (pm_runtime_suspended(dwc->dev)) > - return; > - > dwc3_gadget_disable_irq(dwc); > __dwc3_gadget_ep_disable(dwc->eps[0]); > __dwc3_gadget_ep_disable(dwc->eps[1]); > @@ -1795,10 +1795,29 @@ static int dwc3_gadget_stop(struct usb_gadget *g) > { > struct dwc3 *dwc = gadget_to_dwc(g); > unsigned long flags; > + int epnum; > + > + if (pm_runtime_suspended(dwc->dev)) > + return 0; If we set the suspend checking at here, we will lose the chance to free gadget irq when stopping gadget. > > spin_lock_irqsave(>lock, flags); > __dwc3_gadget_stop(dwc); > dwc->gadget_driver = NULL; Can we set the suspend checking at here? And we should not delete the suspend checking in __dwc3_gadget_stop() function. + if
Re: [PATCH v1] usb: dwc3: gadget: wait for End Transfer to complete
Hi, On 31 October 2016 at 20:53, Felipe Balbi wrote: > > Hi, > > Baolin Wang writes: >> Instead of just delaying for 100us, we should >> actually wait for End Transfer Command Complete >> interrupt before moving on. Note that this should >> only be done if we're dealing with one of the core >> revisions that actually require the interrupt before >> moving on. >> >> [ felipe.ba...@linux.intel.com: minor improvements ] >> >> Signed-off-by: Baolin Wang > > I made one extra modification to prevent us from checking for > pm_runtime_suspended() twice: > > commit 8f48e8d6d3dfe75b5582c8a7b1ee5739a393748c > Author: Baolin Wang > Date: Mon Oct 31 19:38:36 2016 +0800 > > usb: dwc3: gadget: wait for End Transfer to complete > > Instead of just delaying for 100us, we should > actually wait for End Transfer Command Complete > interrupt before moving on. Note that this should > only be done if we're dealing with one of the core > revisions that actually require the interrupt before > moving on. > > [ felipe.ba...@linux.intel.com: minor improvements ] > > Signed-off-by: Baolin Wang > Signed-off-by: Felipe Balbi > > diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h > index 5fc437021ac7..c2b86856e85d 100644 > --- a/drivers/usb/dwc3/core.h > +++ b/drivers/usb/dwc3/core.h > @@ -26,6 +26,7 @@ > #include > #include > #include > +#include > > #include > #include > @@ -505,6 +506,7 @@ struct dwc3_event_buffer { > * @endpoint: usb endpoint > * @pending_list: list of pending requests for this endpoint > * @started_list: list of started requests on this endpoint > + * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete > * @lock: spinlock for endpoint request queue traversal > * @regs: pointer to first endpoint register > * @trb_pool: array of transaction buffers > @@ -530,6 +532,8 @@ struct dwc3_ep { > struct list_headpending_list; > struct list_headstarted_list; > > + wait_queue_head_t wait_end_transfer; > + > spinlock_t lock; > void __iomem*regs; > > @@ -546,6 +550,7 @@ struct dwc3_ep { > #define DWC3_EP_BUSY (1 << 4) > #define DWC3_EP_PENDING_REQUEST(1 << 5) > #define DWC3_EP_MISSED_ISOC(1 << 6) > +#define DWC3_EP_END_TRANSFER_PENDING (1 << 7) > > /* This last one is specific to EP0 */ > #define DWC3_EP0_DIR_IN(1 << 31) > @@ -1050,6 +1055,9 @@ struct dwc3_event_depevt { > #define DEPEVT_TRANSFER_BUS_EXPIRY 2 > > u32 parameters:16; > + > +/* For Command Complete Events */ > +#define DEPEVT_PARAMETER_CMD(n)(((n) & (0xf << 8)) >> 8) > } __packed; > > /** > diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c > index 3b53a5714df4..d544e7369776 100644 > --- a/drivers/usb/dwc3/gadget.c > +++ b/drivers/usb/dwc3/gadget.c > @@ -593,11 +593,14 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, > dep->comp_desc = comp_desc; > dep->type = usb_endpoint_type(desc); > dep->flags |= DWC3_EP_ENABLED; > + dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING; > > reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); > reg |= DWC3_DALEPENA_EP(dep->number); > dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); > > + init_waitqueue_head(>wait_end_transfer); > + > if (usb_endpoint_xfer_control(desc)) > return 0; > > @@ -699,7 +702,7 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) > dep->endpoint.desc = NULL; > dep->comp_desc = NULL; > dep->type = 0; > - dep->flags = 0; > + dep->flags &= DWC3_EP_END_TRANSFER_PENDING; > > return 0; > } > @@ -1783,9 +1786,6 @@ static int dwc3_gadget_start(struct usb_gadget *g, > > static void __dwc3_gadget_stop(struct dwc3 *dwc) > { > - if (pm_runtime_suspended(dwc->dev)) > - return; > - > dwc3_gadget_disable_irq(dwc); > __dwc3_gadget_ep_disable(dwc->eps[0]); > __dwc3_gadget_ep_disable(dwc->eps[1]); > @@ -1795,10 +1795,29 @@ static int dwc3_gadget_stop(struct usb_gadget *g) > { > struct dwc3 *dwc = gadget_to_dwc(g); > unsigned long flags; > + int epnum; > + > + if (pm_runtime_suspended(dwc->dev)) > + return 0; If we set the suspend checking at here, we will lose the chance to free gadget irq when stopping gadget. > > spin_lock_irqsave(>lock, flags); > __dwc3_gadget_stop(dwc); > dwc->gadget_driver = NULL; Can we set the suspend checking at here? And we should not delete the suspend checking in __dwc3_gadget_stop() function. + if (pm_runtime_suspended(dwc->dev)) { + spin_unlock_irqrestore(>lock, flags); + goto out; + } > + > +