Re: [PATCH v2 03/10] pwm: imx: Rewrite imx_pwm_*_v1 code to facilitate switch to atomic pwm operation

2016-10-31 Thread Lukasz Majewski
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

2016-10-31 Thread Lukasz Majewski
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

2016-10-31 Thread Baolin Wang
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

2016-10-31 Thread Baolin Wang
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

2016-10-31 Thread Kashyap Desai
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

2016-10-31 Thread Kashyap Desai
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

2016-10-31 Thread Baoquan He
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

2016-10-31 Thread Nasser
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

2016-10-31 Thread Baoquan He
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

2016-10-31 Thread Nasser
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

2016-10-31 Thread Jike Song
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: [PATCH v10 01/19] vfio: Mediated device Core driver

2016-10-31 Thread Jike Song
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

2016-10-31 Thread Kalle Valo
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: pull-request: wireless-drivers-next 2016-10-30

2016-10-31 Thread Kalle Valo
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

2016-10-31 Thread Brian Norris
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

2016-10-31 Thread Brian Norris
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

2016-10-31 Thread Dave Young
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

2016-10-31 Thread Dave Young
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

2016-10-31 Thread kys
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 1/1] vmbus: make sysfs names consistent with PCI

2016-10-31 Thread kys
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

2016-10-31 Thread Lu Baolu
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 3/4] usb: serial: usb_debug: add support for dbc debug device

2016-10-31 Thread Lu Baolu
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

2016-10-31 Thread Lu Baolu
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

[PATCH v4 4/4] usb: doc: add document for USB3 debug port usage

2016-10-31 Thread Lu Baolu
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

2016-10-31 Thread Lu Baolu
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

2016-10-31 Thread Lu Baolu
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

2016-10-31 Thread Lu Baolu
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

2016-10-31 Thread Lu Baolu
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

2016-10-31 Thread Lu Baolu
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



[PATCH v4 2/4] x86: add support for earlyprintk via USB3 debug port

2016-10-31 Thread Lu Baolu
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

2016-10-31 Thread Mauro Carvalho Chehab
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
> > 

Re: make pdfdocs fails with v4.9-rc3

2016-10-31 Thread Mauro Carvalho Chehab
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

2016-10-31 Thread Joel Holdsworth
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

2016-10-31 Thread Joel Holdsworth
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

2016-10-31 Thread Joel Holdsworth
---
 .../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

2016-10-31 Thread 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



[PATCH v6 2/3] Documentation: Add binding document for Lattice iCE40 FPGA manager

2016-10-31 Thread Joel Holdsworth
---
 .../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

2016-10-31 Thread 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



[PATCH v5 3/3] fpga: Add support for Lattice iCE40 FPGAs

2016-10-31 Thread Joel Holdsworth
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

2016-10-31 Thread Joel Holdsworth
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

2016-10-31 Thread Joel Holdsworth
---
 .../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

2016-10-31 Thread Dongli Zhang
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 2/3] Documentation: Add binding document for Lattice iCE40 FPGA manager

2016-10-31 Thread Joel Holdsworth
---
 .../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

2016-10-31 Thread Dongli Zhang
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

2016-10-31 Thread Joel Holdsworth
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



[PATCH v5 1/3] of: Add vendor prefix for Lattice Semiconductor

2016-10-31 Thread Joel Holdsworth
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

2016-10-31 Thread Rafael J. Wysocki
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] PM / Domains: check for negative return from of_count_phandle_with_args

2016-10-31 Thread Rafael J. Wysocki
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

2016-10-31 Thread Michael Ellerman
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


Re: [PATCH v2] console: use first console if stdout-path device doesn't appear

2016-10-31 Thread Michael Ellerman
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

2016-10-31 Thread Lee, Chun-Yi
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: setup accelerometer when machine has appropriate notify event

2016-10-31 Thread Lee, Chun-Yi
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

2016-10-31 Thread Lee, Chun-Yi
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



[PATCH] acer-wmi: only supports AMW0_GUID1 on acer family

2016-10-31 Thread Lee, Chun-Yi
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

2016-10-31 Thread Juergen Gross
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

2016-10-31 Thread Juergen Gross
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

2016-10-31 Thread Rafael J. Wysocki
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

2016-10-31 Thread Rafael J. Wysocki
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

2016-10-31 Thread Rafael J. Wysocki
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

2016-10-31 Thread Rafael J. Wysocki
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

2016-10-31 Thread Rafael J. Wysocki
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

2016-10-31 Thread Rafael J. Wysocki
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()

2016-10-31 Thread Matt Ranostay
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 1/6] staging: iio: set proper supply name to devm_regulator_get()

2016-10-31 Thread Matt Ranostay
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

2016-10-31 Thread Alex Williamson
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 v10 01/19] vfio: Mediated device Core driver

2016-10-31 Thread Alex Williamson
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

2016-10-31 Thread Rafael J. Wysocki
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

2016-10-31 Thread Rafael J. Wysocki
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

2016-10-31 Thread Rob Herring
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


Re: [RFC PATCH 0/6] UART slave devices using serio

2016-10-31 Thread Rob Herring
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'

2016-10-31 Thread kbuild test robot
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'

2016-10-31 Thread kbuild test robot
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

2016-10-31 Thread Vivien Didelot
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

2016-10-31 Thread Xing Zheng
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

2016-10-31 Thread Vivien Didelot
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

2016-10-31 Thread Vivien Didelot
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

2016-10-31 Thread Vivien Didelot
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

2016-10-31 Thread Vivien Didelot
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

2016-10-31 Thread Xing Zheng
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

2016-10-31 Thread Vivien Didelot
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

2016-10-31 Thread Vivien Didelot
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

2016-10-31 Thread Vivien Didelot
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

2016-10-31 Thread Vivien Didelot
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

2016-10-31 Thread Vivien Didelot
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

2016-10-31 Thread Vivien Didelot
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

2016-10-31 Thread Vivien Didelot
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

2016-10-31 Thread Vivien Didelot
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

2016-10-31 Thread Vivien Didelot
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

2016-10-31 Thread Vivien Didelot
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

2016-10-31 Thread Vivien Didelot
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

2016-10-31 Thread Vivien Didelot
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

2016-10-31 Thread Vivien Didelot
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

2016-10-31 Thread Vivien Didelot
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

2016-10-31 Thread Vivien Didelot
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

2016-10-31 Thread Vivien Didelot
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

2016-10-31 Thread Vivien Didelot
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

2016-10-31 Thread Vivien Didelot
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

2016-10-31 Thread Vivien Didelot
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

2016-10-31 Thread Baolin Wang
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 

Re: [PATCH v1] usb: dwc3: gadget: wait for End Transfer to complete

2016-10-31 Thread Baolin Wang
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;
+  }

> +
> + 

  1   2   3   4   5   6   7   8   9   10   >