Re: [RFC PATCH v3 5/6] dt-bindings: of: Add restricted DMA pool

2021-01-11 Thread Claire Chang
On Fri, Jan 8, 2021 at 2:15 AM Florian Fainelli  wrote:
>
> On 1/7/21 10:00 AM, Konrad Rzeszutek Wilk wrote:
> >>>
> >>>
> >>>  - Nothing stops the physical device from bypassing the SWIOTLB buffer.
> >>>That is if an errant device screwed up the length or DMA address, the
> >>>SWIOTLB would gladly do what the device told it do?
> >>
> >> So the system needs to provide a way to lock down the memory access, e.g. 
> >> MPU.
> >
> > OK! Would it be prudent to have this in the description above perhaps?
>
> Yes this is something that must be documented as a requirement for the
> restricted DMA pool users, otherwise attempting to do restricted DMA
> pool is no different than say, using a device private CMA region.
> Without the enforcement, this is just a best effort.

Will add in the next version.

> --
> Florian


Re: [RFC PATCH v3 0/6] Restricted DMA

2021-01-11 Thread Claire Chang
On Fri, Jan 8, 2021 at 1:59 AM Florian Fainelli  wrote:
>
> On 1/7/21 9:42 AM, Claire Chang wrote:
>
> >> Can you explain how ATF gets involved and to what extent it does help,
> >> besides enforcing a secure region from the ARM CPU's perpsective? Does
> >> the PCIe root complex not have an IOMMU but can somehow be denied access
> >> to a region that is marked NS=0 in the ARM CPU's MMU? If so, that is
> >> still some sort of basic protection that the HW enforces, right?
> >
> > We need the ATF support for memory MPU (memory protection unit).
> > Restricted DMA (with reserved-memory in dts) makes sure the predefined 
> > memory
> > region is for PCIe DMA only, but we still need MPU to locks down PCIe 
> > access to
> > that specific regions.
>
> OK so you do have a protection unit of some sort to enforce which region
> in DRAM the PCIE bridge is allowed to access, that makes sense,
> otherwise the restricted DMA region would only be a hint but nothing you
> can really enforce. This is almost entirely analogous to our systems then.

Here is the example of setting the MPU:
https://github.com/ARM-software/arm-trusted-firmware/blob/master/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c#L132

>
> There may be some value in standardizing on an ARM SMCCC call then since
> you already support two different SoC vendors.
>
> >
> >>
> >> On Broadcom STB SoCs we have had something similar for a while however
> >> and while we don't have an IOMMU for the PCIe bridge, we do have a a
> >> basic protection mechanism whereby we can configure a region in DRAM to
> >> be PCIe read/write and CPU read/write which then gets used as the PCIe
> >> inbound region for the PCIe EP. By default the PCIe bridge is not
> >> allowed access to DRAM so we must call into a security agent to allow
> >> the PCIe bridge to access the designated DRAM region.
> >>
> >> We have done this using a private CMA area region assigned via Device
> >> Tree, assigned with a and requiring the PCIe EP driver to use
> >> dma_alloc_from_contiguous() in order to allocate from this device
> >> private CMA area. The only drawback with that approach is that it
> >> requires knowing how much memory you need up front for buffers and DMA
> >> descriptors that the PCIe EP will need to process. The problem is that
> >> it requires driver modifications and that does not scale over the number
> >> of PCIe EP drivers, some we absolutely do not control, but there is no
> >> need to bounce buffer. Your approach scales better across PCIe EP
> >> drivers however it does require bounce buffering which could be a
> >> performance hit.
> >
> > Only the streaming DMA (map/unmap) needs bounce buffering.
>
> True, and typically only on transmit since you don't really control
> where the sk_buff are allocated from, right? On RX since you need to
> hand buffer addresses to the WLAN chip prior to DMA, you can allocate
> them from a pool that already falls within the restricted DMA region, right?
>

Right, but applying bounce buffering to RX will make it more secure.
The device won't be able to modify the content after unmap. Just like what
iommu_unmap does.

> > I also added alloc/free support in this series
> > (https://lore.kernel.org/patchwork/patch/1360995/), so dma_direct_alloc() 
> > will
> > try to allocate memory from the predefined memory region.
> >
> > As for the performance hit, it should be similar to the default swiotlb.
> > Here are my experiment results. Both SoCs lack IOMMU for PCIe.
> >
> > PCIe wifi vht80 throughput -
> >
> >   MTK SoC  tcp_tx tcp_rxudp_tx   udp_rx
> >   w/o Restricted DMA  244.1 134.66   312.56   350.79
> >   w/ Restricted DMA246.95   136.59   363.21   351.99
> >
> >   Rockchip SoC   tcp_tx tcp_rxudp_tx   udp_rx
> >   w/o Restricted DMA  237.87   133.86   288.28   361.88
> >   w/ Restricted DMA256.01   130.95   292.28   353.19
>
> How come you get better throughput with restricted DMA? Is it because
> doing DMA to/from a contiguous region allows for better grouping of
> transactions from the DRAM controller's perspective somehow?

I'm not sure, but actually, enabling the default swiotlb for wifi also helps the
throughput a little bit for me.

>
> >
> > The CPU usage doesn't increase too much either.
> > Although I didn't measure the CPU usage very precisely, it's ~3% with a 
> > single
> > big core (Cortex-A72) and ~5% with a single small core (Cortex-A53).
> >
> > Thanks!
> >
> >>
> >> Thanks!
> >> --
> >> Florian
>
>
> --
> Florian


Re: [PATCH v2] powerpc/vdso: fix clock_gettime_fallback for vdso32

2021-01-11 Thread Michael Ellerman
Christophe Leroy  writes:
> From: Andreas Schwab 
>
> The second argument of __kernel_clock_gettime64 points to a struct
> __kernel_timespec, with 64-bit time_t, so use the clock_gettime64 syscall
> in the fallback function for the 32-bit vdso.  Similarily,
> clock_getres_fallback should use the clock_getres_time64 syscall, though
> it isn't yet called from the 32-bit vdso.
>
> Signed-off-by: Andreas Schwab 
> [chleroy: Moved into the #ifdef CONFIG_VDSO32 block]

That doesn't build for 64-bit with compat VDSO. Should I just take
Andreas' version, or do you want to send a v3?

cheers

> Fixes: d0e3fc69d00d ("powerpc/vdso: Provide __kernel_clock_gettime64() on 
> vdso32")
> Signed-off-by: Christophe Leroy 
> ---
>  arch/powerpc/include/asm/vdso/gettimeofday.h | 27 +++-
>  1 file changed, 21 insertions(+), 6 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/vdso/gettimeofday.h 
> b/arch/powerpc/include/asm/vdso/gettimeofday.h
> index 7a215cc5da77..3ecddd9c6302 100644
> --- a/arch/powerpc/include/asm/vdso/gettimeofday.h
> +++ b/arch/powerpc/include/asm/vdso/gettimeofday.h
> @@ -102,22 +102,22 @@ int gettimeofday_fallback(struct __kernel_old_timeval 
> *_tv, struct timezone *_tz
>   return do_syscall_2(__NR_gettimeofday, (unsigned long)_tv, (unsigned 
> long)_tz);
>  }
>  
> +#ifdef CONFIG_VDSO32
> +
> +#define BUILD_VDSO32 1
> +
>  static __always_inline
>  int clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
>  {
> - return do_syscall_2(__NR_clock_gettime, _clkid, (unsigned long)_ts);
> + return do_syscall_2(__NR_clock_gettime64, _clkid, (unsigned long)_ts);
>  }
>  
>  static __always_inline
>  int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
>  {
> - return do_syscall_2(__NR_clock_getres, _clkid, (unsigned long)_ts);
> + return do_syscall_2(__NR_clock_getres_time64, _clkid, (unsigned 
> long)_ts);
>  }
>  
> -#ifdef CONFIG_VDSO32
> -
> -#define BUILD_VDSO32 1
> -
>  static __always_inline
>  int clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
>  {
> @@ -129,6 +129,21 @@ int clock_getres32_fallback(clockid_t _clkid, struct 
> old_timespec32 *_ts)
>  {
>   return do_syscall_2(__NR_clock_getres, _clkid, (unsigned long)_ts);
>  }
> +
> +#else
> +
> +static __always_inline
> +int clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
> +{
> + return do_syscall_2(__NR_clock_gettime, _clkid, (unsigned long)_ts);
> +}
> +
> +static __always_inline
> +int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
> +{
> + return do_syscall_2(__NR_clock_getres, _clkid, (unsigned long)_ts);
> +}
> +
>  #endif
>  
>  static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
> -- 
> 2.25.0


[PATCH v4 19/21] ibmvfc: purge scsi channels after transport loss/reset

2021-01-11 Thread Tyrel Datwyler
Grab the queue and list lock for each Sub-CRQ and add any uncompleted
events to the host purge list.

Signed-off-by: Tyrel Datwyler 
---
 drivers/scsi/ibmvscsi/ibmvfc.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 24e1278acfeb..b413f5da71ce 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -1056,7 +1056,13 @@ static void ibmvfc_fail_request(struct ibmvfc_event 
*evt, int error_code)
 static void ibmvfc_purge_requests(struct ibmvfc_host *vhost, int error_code)
 {
struct ibmvfc_event *evt, *pos;
+   struct ibmvfc_queue *queues = vhost->scsi_scrqs.scrqs;
unsigned long flags;
+   int hwqs = 0;
+   int i;
+
+   if (vhost->using_channels)
+   hwqs = vhost->scsi_scrqs.active_queues;
 
ibmvfc_dbg(vhost, "Purging all requests\n");
spin_lock_irqsave(>crq.l_lock, flags);
@@ -1064,6 +1070,16 @@ static void ibmvfc_purge_requests(struct ibmvfc_host 
*vhost, int error_code)
ibmvfc_fail_request(evt, error_code);
list_splice_init(>crq.sent, >purge);
spin_unlock_irqrestore(>crq.l_lock, flags);
+
+   for (i = 0; i < hwqs; i++) {
+   spin_lock_irqsave(queues[i].q_lock, flags);
+   spin_lock([i].l_lock);
+   list_for_each_entry_safe(evt, pos, [i].sent, queue_list)
+   ibmvfc_fail_request(evt, error_code);
+   list_splice_init([i].sent, >purge);
+   spin_unlock([i].l_lock);
+   spin_unlock_irqrestore(queues[i].q_lock, flags);
+   }
 }
 
 /**
-- 
2.27.0



[PATCH v4 21/21] ibmvfc: provide modules parameters for MQ settings

2021-01-11 Thread Tyrel Datwyler
Add the various module parameter toggles for adjusting the MQ
characteristics at boot/load time as well as a device attribute for
changing the client scsi channel request amount.

Signed-off-by: Tyrel Datwyler 
---
 drivers/scsi/ibmvscsi/ibmvfc.c | 75 ++
 1 file changed, 66 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index b413f5da71ce..6a64735d9652 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -40,6 +40,12 @@ static unsigned int disc_threads = IBMVFC_MAX_DISC_THREADS;
 static unsigned int ibmvfc_debug = IBMVFC_DEBUG;
 static unsigned int log_level = IBMVFC_DEFAULT_LOG_LEVEL;
 static unsigned int cls3_error = IBMVFC_CLS3_ERROR;
+static unsigned int mq_enabled = IBMVFC_MQ;
+static unsigned int nr_scsi_hw_queues = IBMVFC_SCSI_HW_QUEUES;
+static unsigned int nr_scsi_channels = IBMVFC_SCSI_CHANNELS;
+static unsigned int mig_channels_only = IBMVFC_MIG_NO_SUB_TO_CRQ;
+static unsigned int mig_no_less_channels = IBMVFC_MIG_NO_N_TO_M;
+
 static LIST_HEAD(ibmvfc_head);
 static DEFINE_SPINLOCK(ibmvfc_driver_lock);
 static struct scsi_transport_template *ibmvfc_transport_template;
@@ -49,6 +55,22 @@ MODULE_AUTHOR("Brian King ");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(IBMVFC_DRIVER_VERSION);
 
+module_param_named(mq, mq_enabled, uint, S_IRUGO);
+MODULE_PARM_DESC(mq, "Enable multiqueue support. "
+"[Default=" __stringify(IBMVFC_MQ) "]");
+module_param_named(scsi_host_queues, nr_scsi_hw_queues, uint, S_IRUGO);
+MODULE_PARM_DESC(scsi_host_queues, "Number of SCSI Host submission queues. "
+"[Default=" __stringify(IBMVFC_SCSI_HW_QUEUES) "]");
+module_param_named(scsi_hw_channels, nr_scsi_channels, uint, S_IRUGO);
+MODULE_PARM_DESC(scsi_hw_channels, "Number of hw scsi channels to request. "
+"[Default=" __stringify(IBMVFC_SCSI_CHANNELS) "]");
+module_param_named(mig_channels_only, mig_channels_only, uint, S_IRUGO);
+MODULE_PARM_DESC(mig_channels_only, "Prevent migration to non-channelized 
system. "
+"[Default=" __stringify(IBMVFC_MIG_NO_SUB_TO_CRQ) "]");
+module_param_named(mig_no_less_channels, mig_no_less_channels, uint, S_IRUGO);
+MODULE_PARM_DESC(mig_no_less_channels, "Prevent migration to system with less 
channels. "
+"[Default=" __stringify(IBMVFC_MIG_NO_N_TO_M) "]");
+
 module_param_named(init_timeout, init_timeout, uint, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(init_timeout, "Initialization timeout in seconds. "
 "[Default=" __stringify(IBMVFC_INIT_TIMEOUT) "]");
@@ -926,7 +948,7 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
crq->cur = 0;
 
if (vhost->scsi_scrqs.scrqs) {
-   for (i = 0; i < IBMVFC_SCSI_HW_QUEUES; i++) {
+   for (i = 0; i < nr_scsi_hw_queues; i++) {
scrq = >scsi_scrqs.scrqs[i];
spin_lock(scrq->q_lock);
memset(scrq->msgs.scrq, 0, PAGE_SIZE);
@@ -3394,6 +3416,37 @@ static ssize_t ibmvfc_store_log_level(struct device *dev,
return strlen(buf);
 }
 
+static ssize_t ibmvfc_show_scsi_channels(struct device *dev,
+struct device_attribute *attr, char 
*buf)
+{
+   struct Scsi_Host *shost = class_to_shost(dev);
+   struct ibmvfc_host *vhost = shost_priv(shost);
+   unsigned long flags = 0;
+   int len;
+
+   spin_lock_irqsave(shost->host_lock, flags);
+   len = snprintf(buf, PAGE_SIZE, "%d\n", vhost->client_scsi_channels);
+   spin_unlock_irqrestore(shost->host_lock, flags);
+   return len;
+}
+
+static ssize_t ibmvfc_store_scsi_channels(struct device *dev,
+struct device_attribute *attr,
+const char *buf, size_t count)
+{
+   struct Scsi_Host *shost = class_to_shost(dev);
+   struct ibmvfc_host *vhost = shost_priv(shost);
+   unsigned long flags = 0;
+   unsigned int channels;
+
+   spin_lock_irqsave(shost->host_lock, flags);
+   channels = simple_strtoul(buf, NULL, 10);
+   vhost->client_scsi_channels = min(channels, nr_scsi_hw_queues);
+   ibmvfc_hard_reset_host(vhost);
+   spin_unlock_irqrestore(shost->host_lock, flags);
+   return strlen(buf);
+}
+
 static DEVICE_ATTR(partition_name, S_IRUGO, ibmvfc_show_host_partition_name, 
NULL);
 static DEVICE_ATTR(device_name, S_IRUGO, ibmvfc_show_host_device_name, NULL);
 static DEVICE_ATTR(port_loc_code, S_IRUGO, ibmvfc_show_host_loc_code, NULL);
@@ -3402,6 +3455,8 @@ static DEVICE_ATTR(npiv_version, S_IRUGO, 
ibmvfc_show_host_npiv_version, NULL);
 static DEVICE_ATTR(capabilities, S_IRUGO, ibmvfc_show_host_capabilities, NULL);
 static DEVICE_ATTR(log_level, S_IRUGO | S_IWUSR,
   ibmvfc_show_log_level, ibmvfc_store_log_level);
+static DEVICE_ATTR(nr_scsi_channels, S_IRUGO | S_IWUSR,
+  

[PATCH v4 20/21] ibmvfc: enable MQ and set reasonable defaults

2021-01-11 Thread Tyrel Datwyler
Turn on MQ by default and set sane values for the upper limit on hw
queues for the scsi host, and number of hw scsi channels to request from
the partner VIOS.

Signed-off-by: Tyrel Datwyler 
---
 drivers/scsi/ibmvscsi/ibmvfc.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index c3bb83c9d8a6..0391cb746d0b 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -41,9 +41,9 @@
 #define IBMVFC_DEFAULT_LOG_LEVEL   2
 #define IBMVFC_MAX_CDB_LEN 16
 #define IBMVFC_CLS3_ERROR  0
-#define IBMVFC_MQ  0
-#define IBMVFC_SCSI_CHANNELS   0
-#define IBMVFC_SCSI_HW_QUEUES  1
+#define IBMVFC_MQ  1
+#define IBMVFC_SCSI_CHANNELS   8
+#define IBMVFC_SCSI_HW_QUEUES  8
 #define IBMVFC_MIG_NO_SUB_TO_CRQ   0
 #define IBMVFC_MIG_NO_N_TO_M   0
 
-- 
2.27.0



[PATCH v4 18/21] ibmvfc: send Cancel MAD down each hw scsi channel

2021-01-11 Thread Tyrel Datwyler
In general the client needs to send Cancel MADs and task management
commands down the same channel as the command(s) intended to cancel or
abort. The client assigns cancel keys per LUN and thus must send a
Cancel down each channel commands were submitted for that LUN. Further,
the client then must wait for those cancel completions prior to
submitting a LUN RESET or ABORT TASK SET.

Add a cancel rsp iu syncronization field to the ibmvfc_queue struct such
that the cancel routine can sync the cancel response to each queue that
requires a cancel command. Build a list of each cancel event sent and
wait for the completion of each submitted cancel.

Signed-off-by: Tyrel Datwyler 
---
 drivers/scsi/ibmvscsi/ibmvfc.c | 106 +
 drivers/scsi/ibmvscsi/ibmvfc.h |   3 +
 2 files changed, 97 insertions(+), 12 deletions(-)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index b0b0212344f3..24e1278acfeb 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -2418,18 +2418,79 @@ static struct ibmvfc_event *ibmvfc_init_tmf(struct 
ibmvfc_queue *queue,
return evt;
 }
 
-/**
- * ibmvfc_cancel_all - Cancel all outstanding commands to the device
- * @sdev:  scsi device to cancel commands
- * @type:  type of error recovery being performed
- *
- * This sends a cancel to the VIOS for the specified device. This does
- * NOT send any abort to the actual device. That must be done separately.
- *
- * Returns:
- * 0 on success / other on failure
- **/
-static int ibmvfc_cancel_all(struct scsi_device *sdev, int type)
+static int ibmvfc_cancel_all_mq(struct scsi_device *sdev, int type)
+{
+   struct ibmvfc_host *vhost = shost_priv(sdev->host);
+   struct ibmvfc_event *evt, *found_evt, *temp;
+   struct ibmvfc_queue *queues = vhost->scsi_scrqs.scrqs;
+   unsigned long flags;
+   int num_hwq, i;
+   LIST_HEAD(cancelq);
+   u16 status;
+
+   ENTER;
+   spin_lock_irqsave(vhost->host->host_lock, flags);
+   num_hwq = vhost->scsi_scrqs.active_queues;
+   for (i = 0; i < num_hwq; i++) {
+   spin_lock(queues[i].q_lock);
+   spin_lock([i].l_lock);
+   found_evt = NULL;
+   list_for_each_entry(evt, [i].sent, queue_list) {
+   if (evt->cmnd && evt->cmnd->device == sdev) {
+   found_evt = evt;
+   break;
+   }
+   }
+   spin_unlock([i].l_lock);
+
+   if (!found_evt)
+   continue;
+
+   if (vhost->logged_in) {
+   evt = ibmvfc_init_tmf([i], sdev, type);
+   evt->sync_iu = [i].cancel_rsp;
+   ibmvfc_send_event(evt, vhost, default_timeout);
+   list_add_tail(>cancel, );
+   }
+   }
+
+   for (i = 0; i < num_hwq; i++)
+   spin_unlock(queues[i].q_lock);
+   spin_unlock_irqrestore(vhost->host->host_lock, flags);
+
+   if (list_empty()) {
+   if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL)
+   sdev_printk(KERN_INFO, sdev, "No events found to 
cancel\n");
+   return 0;
+   }
+
+   sdev_printk(KERN_INFO, sdev, "Cancelling outstanding commands.\n");
+
+   list_for_each_entry_safe(evt, temp, , cancel) {
+   wait_for_completion(>comp);
+   status = be16_to_cpu(evt->queue->cancel_rsp.mad_common.status);
+   ibmvfc_free_event(evt);
+
+   if (status != IBMVFC_MAD_SUCCESS) {
+   sdev_printk(KERN_WARNING, sdev, "Cancel failed with 
rc=%x\n", status);
+   switch (status) {
+   case IBMVFC_MAD_DRIVER_FAILED:
+   case IBMVFC_MAD_CRQ_ERROR:
+   /* Host adapter most likely going through reset, return 
success to
+* the caller will wait for the command being cancelled 
to get returned
+*/
+   break;
+   default:
+   break;
+   }
+   }
+   }
+
+   sdev_printk(KERN_INFO, sdev, "Successfully cancelled outstanding 
commands\n");
+   return 0;
+}
+
+static int ibmvfc_cancel_all_sq(struct scsi_device *sdev, int type)
 {
struct ibmvfc_host *vhost = shost_priv(sdev->host);
struct ibmvfc_event *evt, *found_evt;
@@ -2498,6 +2559,27 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, 
int type)
return 0;
 }
 
+/**
+ * ibmvfc_cancel_all - Cancel all outstanding commands to the device
+ * @sdev:  scsi device to cancel commands
+ * @type:  type of error recovery being performed
+ *
+ * This sends a cancel to the VIOS for the specified device. This does
+ * NOT send any abort to the actual device. That must 

[PATCH v4 16/21] ibmvfc: register Sub-CRQ handles with VIOS during channel setup

2021-01-11 Thread Tyrel Datwyler
If the ibmvfc client adapter requests channels it must submit a number
of Sub-CRQ handles matching the number of channels being requested. The
VIOS in its response will overwrite the actual number of channel
resources allocated which may be less than what was requested. The
client then must store the VIOS Sub-CRQ handle for each queue. This VIOS
handle is needed as a parameter with  h_send_sub_crq().

Signed-off-by: Tyrel Datwyler 
---
 drivers/scsi/ibmvscsi/ibmvfc.c | 32 +++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 865b87881d86..578e27180f10 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -4627,15 +4627,35 @@ static void ibmvfc_discover_targets(struct ibmvfc_host 
*vhost)
 static void ibmvfc_channel_setup_done(struct ibmvfc_event *evt)
 {
struct ibmvfc_host *vhost = evt->vhost;
+   struct ibmvfc_channel_setup *setup = vhost->channel_setup_buf;
+   struct ibmvfc_scsi_channels *scrqs = >scsi_scrqs;
u32 mad_status = be16_to_cpu(evt->xfer_iu->channel_setup.common.status);
int level = IBMVFC_DEFAULT_LOG_LEVEL;
+   int flags, active_queues, i;
 
ibmvfc_free_event(evt);
 
switch (mad_status) {
case IBMVFC_MAD_SUCCESS:
ibmvfc_dbg(vhost, "Channel Setup succeded\n");
+   flags = be32_to_cpu(setup->flags);
vhost->do_enquiry = 0;
+   active_queues = be32_to_cpu(setup->num_scsi_subq_channels);
+   scrqs->active_queues = active_queues;
+
+   if (flags & IBMVFC_CHANNELS_CANCELED) {
+   ibmvfc_dbg(vhost, "Channels Canceled\n");
+   vhost->using_channels = 0;
+   } else {
+   if (active_queues)
+   vhost->using_channels = 1;
+   for (i = 0; i < active_queues; i++)
+   scrqs->scrqs[i].vios_cookie =
+   be64_to_cpu(setup->channel_handles[i]);
+
+   ibmvfc_dbg(vhost, "Using %u channels\n",
+  vhost->scsi_scrqs.active_queues);
+   }
break;
case IBMVFC_MAD_FAILED:
level += ibmvfc_retry_host_init(vhost);
@@ -4659,9 +4679,19 @@ static void ibmvfc_channel_setup(struct ibmvfc_host 
*vhost)
struct ibmvfc_channel_setup_mad *mad;
struct ibmvfc_channel_setup *setup_buf = vhost->channel_setup_buf;
struct ibmvfc_event *evt = ibmvfc_get_event(>crq);
+   struct ibmvfc_scsi_channels *scrqs = >scsi_scrqs;
+   unsigned int num_channels =
+   min(vhost->client_scsi_channels, vhost->max_vios_scsi_channels);
+   int i;
 
memset(setup_buf, 0, sizeof(*setup_buf));
-   setup_buf->flags = cpu_to_be32(IBMVFC_CANCEL_CHANNELS);
+   if (num_channels == 0)
+   setup_buf->flags = cpu_to_be32(IBMVFC_CANCEL_CHANNELS);
+   else {
+   setup_buf->num_scsi_subq_channels = cpu_to_be32(num_channels);
+   for (i = 0; i < num_channels; i++)
+   setup_buf->channel_handles[i] = 
cpu_to_be64(scrqs->scrqs[i].cookie);
+   }
 
ibmvfc_init_event(evt, ibmvfc_channel_setup_done, IBMVFC_MAD_FORMAT);
mad = >iu.channel_setup;
-- 
2.27.0



[PATCH v4 17/21] ibmvfc: add cancel mad initialization helper

2021-01-11 Thread Tyrel Datwyler
Add a helper routine for initializing a Cancel MAD. This will be useful
for a channelized client that needs to send Cancel commands down every
channel commands were sent for a particular LUN.

Signed-off-by: Tyrel Datwyler 
---
 drivers/scsi/ibmvscsi/ibmvfc.c | 68 --
 1 file changed, 40 insertions(+), 28 deletions(-)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 578e27180f10..b0b0212344f3 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -2379,6 +2379,45 @@ static int ibmvfc_wait_for_ops(struct ibmvfc_host 
*vhost, void *device,
return SUCCESS;
 }
 
+static struct ibmvfc_event *ibmvfc_init_tmf(struct ibmvfc_queue *queue,
+   struct scsi_device *sdev,
+   int type)
+{
+   struct ibmvfc_host *vhost = shost_priv(sdev->host);
+   struct scsi_target *starget = scsi_target(sdev);
+   struct fc_rport *rport = starget_to_rport(starget);
+   struct ibmvfc_event *evt;
+   struct ibmvfc_tmf *tmf;
+
+   evt = ibmvfc_get_event(queue);
+   ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_MAD_FORMAT);
+
+   tmf = >iu.tmf;
+   memset(tmf, 0, sizeof(*tmf));
+   if (ibmvfc_check_caps(vhost, IBMVFC_HANDLE_VF_WWPN)) {
+   tmf->common.version = cpu_to_be32(2);
+   tmf->target_wwpn = cpu_to_be64(rport->port_name);
+   } else {
+   tmf->common.version = cpu_to_be32(1);
+   }
+   tmf->common.opcode = cpu_to_be32(IBMVFC_TMF_MAD);
+   tmf->common.length = cpu_to_be16(sizeof(*tmf));
+   tmf->scsi_id = cpu_to_be64(rport->port_id);
+   int_to_scsilun(sdev->lun, >lun);
+   if (!ibmvfc_check_caps(vhost, IBMVFC_CAN_SUPPRESS_ABTS))
+   type &= ~IBMVFC_TMF_SUPPRESS_ABTS;
+   if (vhost->state == IBMVFC_ACTIVE)
+   tmf->flags = cpu_to_be32((type | IBMVFC_TMF_LUA_VALID));
+   else
+   tmf->flags = cpu_to_be32(((type & IBMVFC_TMF_SUPPRESS_ABTS) | 
IBMVFC_TMF_LUA_VALID));
+   tmf->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata);
+   tmf->my_cancel_key = cpu_to_be32((unsigned long)starget->hostdata);
+
+   init_completion(>comp);
+
+   return evt;
+}
+
 /**
  * ibmvfc_cancel_all - Cancel all outstanding commands to the device
  * @sdev:  scsi device to cancel commands
@@ -2393,9 +2432,6 @@ static int ibmvfc_wait_for_ops(struct ibmvfc_host *vhost, 
void *device,
 static int ibmvfc_cancel_all(struct scsi_device *sdev, int type)
 {
struct ibmvfc_host *vhost = shost_priv(sdev->host);
-   struct scsi_target *starget = scsi_target(sdev);
-   struct fc_rport *rport = starget_to_rport(starget);
-   struct ibmvfc_tmf *tmf;
struct ibmvfc_event *evt, *found_evt;
union ibmvfc_iu rsp;
int rsp_rc = -EBUSY;
@@ -2422,32 +2458,8 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, 
int type)
}
 
if (vhost->logged_in) {
-   evt = ibmvfc_get_event(>crq);
-   ibmvfc_init_event(evt, ibmvfc_sync_completion, 
IBMVFC_MAD_FORMAT);
-
-   tmf = >iu.tmf;
-   memset(tmf, 0, sizeof(*tmf));
-   if (ibmvfc_check_caps(vhost, IBMVFC_HANDLE_VF_WWPN)) {
-   tmf->common.version = cpu_to_be32(2);
-   tmf->target_wwpn = cpu_to_be64(rport->port_name);
-   } else {
-   tmf->common.version = cpu_to_be32(1);
-   }
-   tmf->common.opcode = cpu_to_be32(IBMVFC_TMF_MAD);
-   tmf->common.length = cpu_to_be16(sizeof(*tmf));
-   tmf->scsi_id = cpu_to_be64(rport->port_id);
-   int_to_scsilun(sdev->lun, >lun);
-   if (!ibmvfc_check_caps(vhost, IBMVFC_CAN_SUPPRESS_ABTS))
-   type &= ~IBMVFC_TMF_SUPPRESS_ABTS;
-   if (vhost->state == IBMVFC_ACTIVE)
-   tmf->flags = cpu_to_be32((type | IBMVFC_TMF_LUA_VALID));
-   else
-   tmf->flags = cpu_to_be32(((type & 
IBMVFC_TMF_SUPPRESS_ABTS) | IBMVFC_TMF_LUA_VALID));
-   tmf->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata);
-   tmf->my_cancel_key = cpu_to_be32((unsigned 
long)starget->hostdata);
-
+   evt = ibmvfc_init_tmf(>crq, sdev, type);
evt->sync_iu = 
-   init_completion(>comp);
rsp_rc = ibmvfc_send_event(evt, vhost, default_timeout);
}
 
-- 
2.27.0



[PATCH v4 11/21] ibmvfc: map/request irq and register Sub-CRQ interrupt handler

2021-01-11 Thread Tyrel Datwyler
Create an irq mapping for the hw_irq number provided from phyp firmware.
Request an irq assigned our Sub-CRQ interrupt handler. Unmap these irqs
at Sub-CRQ teardown.

Signed-off-by: Tyrel Datwyler 
---
 drivers/scsi/ibmvscsi/ibmvfc.c | 25 +
 1 file changed, 25 insertions(+)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 51bcafad9490..d3d7c6b53d4f 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -5292,12 +5292,34 @@ static int ibmvfc_register_scsi_channel(struct 
ibmvfc_host *vhost,
goto reg_failed;
}
 
+   scrq->irq = irq_create_mapping(NULL, scrq->hw_irq);
+
+   if (!scrq->irq) {
+   rc = -EINVAL;
+   dev_err(dev, "Error mapping sub-crq[%d] irq\n", index);
+   goto irq_failed;
+   }
+
+   snprintf(scrq->name, sizeof(scrq->name), "ibmvfc-%x-scsi%d",
+vdev->unit_address, index);
+   rc = request_irq(scrq->irq, ibmvfc_interrupt_scsi, 0, scrq->name, scrq);
+
+   if (rc) {
+   dev_err(dev, "Couldn't register sub-crq[%d] irq\n", index);
+   irq_dispose_mapping(scrq->irq);
+   goto irq_failed;
+   }
+
scrq->hwq_id = index;
scrq->vhost = vhost;
 
LEAVE;
return 0;
 
+irq_failed:
+   do {
+   plpar_hcall_norets(H_FREE_SUB_CRQ, vdev->unit_address, 
scrq->cookie);
+   } while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
 reg_failed:
ibmvfc_free_queue(vhost, scrq);
LEAVE;
@@ -5313,6 +5335,9 @@ static void ibmvfc_deregister_scsi_channel(struct 
ibmvfc_host *vhost, int index)
 
ENTER;
 
+   free_irq(scrq->irq, scrq);
+   irq_dispose_mapping(scrq->irq);
+
do {
rc = plpar_hcall_norets(H_FREE_SUB_CRQ, vdev->unit_address,
scrq->cookie);
-- 
2.27.0



[PATCH v4 13/21] ibmvfc: advertise client support for using hardware channels

2021-01-11 Thread Tyrel Datwyler
Previous patches have plumbed the necessary Sub-CRQ interface and
channel negotiation MADs to fully channelize via hardware backed queues.

Advertise client support via NPIV Login capability
IBMVFC_CAN_USE_CHANNELS when the client bits have MQ enabled via
vhost->mq_enabled, or when channels were already in use during a
subsequent NPIV Login. The later is required because channel support is
only renegotiated after a CRQ pair is broken. Simple NPIV Logout/Logins
require the client to continue to advertise the channel capability until
the CRQ pair between the client is broken.

Signed-off-by: Tyrel Datwyler 
---
 drivers/scsi/ibmvscsi/ibmvfc.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index a00f38558613..0653d52d4ea0 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -1410,6 +1410,10 @@ static void ibmvfc_set_login_info(struct ibmvfc_host 
*vhost)
 
login_info->max_cmds = cpu_to_be32(max_requests + 
IBMVFC_NUM_INTERNAL_REQ);
login_info->capabilities = cpu_to_be64(IBMVFC_CAN_MIGRATE | 
IBMVFC_CAN_SEND_VF_WWPN);
+
+   if (vhost->mq_enabled || vhost->using_channels)
+   login_info->capabilities |= 
cpu_to_be64(IBMVFC_CAN_USE_CHANNELS);
+
login_info->async.va = cpu_to_be64(vhost->async_crq.msg_token);
login_info->async.len = cpu_to_be32(async_crq->size *
sizeof(*async_crq->msgs.async));
-- 
2.27.0



[PATCH v4 15/21] ibmvfc: send commands down HW Sub-CRQ when channelized

2021-01-11 Thread Tyrel Datwyler
When the client has negotiated the use of channels all vfcFrames are
required to go down a Sub-CRQ channel or it is a protocoal violation. If
the adapter state is channelized submit vfcFrames to the appropriate
Sub-CRQ via the h_send_sub_crq() helper.

Signed-off-by: Tyrel Datwyler 
---
 drivers/scsi/ibmvscsi/ibmvfc.c | 39 --
 1 file changed, 33 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 3f3cc37a263f..865b87881d86 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -704,6 +704,15 @@ static int ibmvfc_send_crq(struct ibmvfc_host *vhost, u64 
word1, u64 word2)
return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, word1, word2);
 }
 
+static int ibmvfc_send_sub_crq(struct ibmvfc_host *vhost, u64 cookie, u64 
word1,
+  u64 word2, u64 word3, u64 word4)
+{
+   struct vio_dev *vdev = to_vio_dev(vhost->dev);
+
+   return plpar_hcall_norets(H_SEND_SUB_CRQ, vdev->unit_address, cookie,
+ word1, word2, word3, word4);
+}
+
 /**
  * ibmvfc_send_crq_init - Send a CRQ init message
  * @vhost: ibmvfc host struct
@@ -1623,8 +1632,17 @@ static int ibmvfc_send_event(struct ibmvfc_event *evt,
 
mb();
 
-   if ((rc = ibmvfc_send_crq(vhost, be64_to_cpu(crq_as_u64[0]),
- be64_to_cpu(crq_as_u64[1] {
+   if (evt->queue->fmt == IBMVFC_SUB_CRQ_FMT)
+   rc = ibmvfc_send_sub_crq(vhost,
+evt->queue->vios_cookie,
+be64_to_cpu(crq_as_u64[0]),
+be64_to_cpu(crq_as_u64[1]),
+0, 0);
+   else
+   rc = ibmvfc_send_crq(vhost, be64_to_cpu(crq_as_u64[0]),
+be64_to_cpu(crq_as_u64[1]));
+
+   if (rc) {
list_del(>queue_list);
spin_unlock_irqrestore(>queue->l_lock, flags);
del_timer(>timer);
@@ -1842,6 +1860,7 @@ static int ibmvfc_queuecommand(struct Scsi_Host *shost, 
struct scsi_cmnd *cmnd)
struct ibmvfc_event *evt;
u32 tag_and_hwq = blk_mq_unique_tag(cmnd->request);
u16 hwq = blk_mq_unique_tag_to_hwq(tag_and_hwq);
+   u16 scsi_channel;
int rc;
 
if (unlikely((rc = fc_remote_port_chkready(rport))) ||
@@ -1852,7 +1871,13 @@ static int ibmvfc_queuecommand(struct Scsi_Host *shost, 
struct scsi_cmnd *cmnd)
}
 
cmnd->result = (DID_OK << 16);
-   evt = ibmvfc_get_event(>crq);
+   if (vhost->using_channels) {
+   scsi_channel = hwq % vhost->scsi_scrqs.active_queues;
+   evt = ibmvfc_get_event(>scsi_scrqs.scrqs[scsi_channel]);
+   evt->hwq = hwq % vhost->scsi_scrqs.active_queues;
+   } else
+   evt = ibmvfc_get_event(>crq);
+
ibmvfc_init_event(evt, ibmvfc_scsi_done, IBMVFC_CMD_FORMAT);
evt->cmnd = cmnd;
 
@@ -1868,8 +1893,6 @@ static int ibmvfc_queuecommand(struct Scsi_Host *shost, 
struct scsi_cmnd *cmnd)
}
 
vfc_cmd->correlation = cpu_to_be64((u64)evt);
-   if (vhost->using_channels)
-   evt->hwq = hwq % vhost->scsi_scrqs.active_queues;
 
if (likely(!(rc = ibmvfc_map_sg_data(cmnd, evt, vfc_cmd, vhost->dev
return ibmvfc_send_event(evt, vhost, 0);
@@ -2200,7 +2223,11 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, 
int type, char *desc)
 
spin_lock_irqsave(vhost->host->host_lock, flags);
if (vhost->state == IBMVFC_ACTIVE) {
-   evt = ibmvfc_get_event(>crq);
+   if (vhost->using_channels)
+   evt = ibmvfc_get_event(>scsi_scrqs.scrqs[0]);
+   else
+   evt = ibmvfc_get_event(>crq);
+
ibmvfc_init_event(evt, ibmvfc_sync_completion, 
IBMVFC_CMD_FORMAT);
tmf = ibmvfc_init_vfc_cmd(evt, sdev);
iu = ibmvfc_get_fcp_iu(vhost, tmf);
-- 
2.27.0



[PATCH v4 08/21] ibmvfc: add Sub-CRQ IRQ enable/disable routine

2021-01-11 Thread Tyrel Datwyler
Each Sub-CRQ has its own interrupt. A hypercall is required to toggle
the IRQ state. Provide the necessary mechanism via a helper function.

Signed-off-by: Tyrel Datwyler 
---
 drivers/scsi/ibmvscsi/ibmvfc.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index a198e118887d..5d7ada0ed0d6 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -3465,6 +3465,26 @@ static void ibmvfc_tasklet(void *data)
}
 }
 
+static int ibmvfc_toggle_scrq_irq(struct ibmvfc_queue *scrq, int enable)
+{
+   struct device *dev = scrq->vhost->dev;
+   struct vio_dev *vdev = to_vio_dev(dev);
+   unsigned long rc;
+   int irq_action = H_ENABLE_VIO_INTERRUPT;
+
+   if (!enable)
+   irq_action = H_DISABLE_VIO_INTERRUPT;
+
+   rc = plpar_hcall_norets(H_VIOCTL, vdev->unit_address, irq_action,
+   scrq->hw_irq, 0, 0);
+
+   if (rc)
+   dev_err(dev, "Couldn't %s sub-crq[%lu] irq. rc=%ld\n",
+   enable ? "enable" : "disable", scrq->hwq_id, rc);
+
+   return rc;
+}
+
 /**
  * ibmvfc_init_tgt - Set the next init job step for the target
  * @tgt:   ibmvfc target struct
-- 
2.27.0



[PATCH v4 14/21] ibmvfc: set and track hw queue in ibmvfc_event struct

2021-01-11 Thread Tyrel Datwyler
Extract the hwq id from a SCSI command and store it in the ibmvfc_event
structure to identify which Sub-CRQ to send the command down when
channels are being utilized.

Signed-off-by: Tyrel Datwyler 
---
 drivers/scsi/ibmvscsi/ibmvfc.c | 5 +
 drivers/scsi/ibmvscsi/ibmvfc.h | 1 +
 2 files changed, 6 insertions(+)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 0653d52d4ea0..3f3cc37a263f 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -1483,6 +1483,7 @@ static void ibmvfc_init_event(struct ibmvfc_event *evt,
evt->_done = done;
evt->done = ibmvfc_locked_done;
}
+   evt->hwq = 0;
 }
 
 /**
@@ -1839,6 +1840,8 @@ static int ibmvfc_queuecommand(struct Scsi_Host *shost, 
struct scsi_cmnd *cmnd)
struct ibmvfc_cmd *vfc_cmd;
struct ibmvfc_fcp_cmd_iu *iu;
struct ibmvfc_event *evt;
+   u32 tag_and_hwq = blk_mq_unique_tag(cmnd->request);
+   u16 hwq = blk_mq_unique_tag_to_hwq(tag_and_hwq);
int rc;
 
if (unlikely((rc = fc_remote_port_chkready(rport))) ||
@@ -1865,6 +1868,8 @@ static int ibmvfc_queuecommand(struct Scsi_Host *shost, 
struct scsi_cmnd *cmnd)
}
 
vfc_cmd->correlation = cpu_to_be64((u64)evt);
+   if (vhost->using_channels)
+   evt->hwq = hwq % vhost->scsi_scrqs.active_queues;
 
if (likely(!(rc = ibmvfc_map_sg_data(cmnd, evt, vfc_cmd, vhost->dev
return ibmvfc_send_event(evt, vhost, 0);
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index 3d76cd3c1fd9..2dbce7071409 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -753,6 +753,7 @@ struct ibmvfc_event {
struct completion comp;
struct completion *eh_comp;
struct timer_list timer;
+   u16 hwq;
 };
 
 /* a pool of event structs for use */
-- 
2.27.0



[PATCH v4 09/21] ibmvfc: add handlers to drain and complete Sub-CRQ responses

2021-01-11 Thread Tyrel Datwyler
The logic for iterating over the Sub-CRQ responses is similiar to that
of the primary CRQ. Add the necessary handlers for processing those
responses.

Signed-off-by: Tyrel Datwyler 
---
 drivers/scsi/ibmvscsi/ibmvfc.c | 86 ++
 1 file changed, 86 insertions(+)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 5d7ada0ed0d6..f3cd092478ee 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -3485,6 +3485,92 @@ static int ibmvfc_toggle_scrq_irq(struct ibmvfc_queue 
*scrq, int enable)
return rc;
 }
 
+static void ibmvfc_handle_scrq(struct ibmvfc_crq *crq, struct ibmvfc_host 
*vhost,
+  struct list_head *evt_doneq)
+{
+   struct ibmvfc_event *evt = (struct ibmvfc_event 
*)be64_to_cpu(crq->ioba);
+
+   switch (crq->valid) {
+   case IBMVFC_CRQ_CMD_RSP:
+   break;
+   case IBMVFC_CRQ_XPORT_EVENT:
+   return;
+   default:
+   dev_err(vhost->dev, "Got and invalid message type 0x%02x\n", 
crq->valid);
+   return;
+   }
+
+   /* The only kind of payload CRQs we should get are responses to
+* things we send. Make sure this response is to something we
+* actually sent
+*/
+   if (unlikely(!ibmvfc_valid_event(>queue->evt_pool, evt))) {
+   dev_err(vhost->dev, "Returned correlation_token 0x%08llx is 
invalid!\n",
+   crq->ioba);
+   return;
+   }
+
+   if (unlikely(atomic_read(>free))) {
+   dev_err(vhost->dev, "Received duplicate correlation_token 
0x%08llx!\n",
+   crq->ioba);
+   return;
+   }
+
+   spin_lock(>queue->l_lock);
+   list_move_tail(>queue_list, evt_doneq);
+   spin_unlock(>queue->l_lock);
+}
+
+static struct ibmvfc_crq *ibmvfc_next_scrq(struct ibmvfc_queue *scrq)
+{
+   struct ibmvfc_crq *crq;
+
+   crq = >msgs.scrq[scrq->cur].crq;
+   if (crq->valid & 0x80) {
+   if (++scrq->cur == scrq->size)
+   scrq->cur = 0;
+   rmb();
+   } else
+   crq = NULL;
+
+   return crq;
+}
+
+static void ibmvfc_drain_sub_crq(struct ibmvfc_queue *scrq)
+{
+   struct ibmvfc_crq *crq;
+   struct ibmvfc_event *evt, *temp;
+   unsigned long flags;
+   int done = 0;
+   LIST_HEAD(evt_doneq);
+
+   spin_lock_irqsave(scrq->q_lock, flags);
+   while (!done) {
+   while ((crq = ibmvfc_next_scrq(scrq)) != NULL) {
+   ibmvfc_handle_scrq(crq, scrq->vhost, _doneq);
+   crq->valid = 0;
+   wmb();
+   }
+
+   ibmvfc_toggle_scrq_irq(scrq, 1);
+   if ((crq = ibmvfc_next_scrq(scrq)) != NULL) {
+   ibmvfc_toggle_scrq_irq(scrq, 0);
+   ibmvfc_handle_scrq(crq, scrq->vhost, _doneq);
+   crq->valid = 0;
+   wmb();
+   } else
+   done = 1;
+   }
+   spin_unlock_irqrestore(scrq->q_lock, flags);
+
+   list_for_each_entry_safe(evt, temp, _doneq, queue_list) {
+   del_timer(>timer);
+   list_del(>queue_list);
+   ibmvfc_trc_end(evt);
+   evt->done(evt);
+   }
+}
+
 /**
  * ibmvfc_init_tgt - Set the next init job step for the target
  * @tgt:   ibmvfc target struct
-- 
2.27.0



[PATCH v4 12/21] ibmvfc: implement channel enquiry and setup commands

2021-01-11 Thread Tyrel Datwyler
New NPIV_ENQUIRY_CHANNEL and NPIV_SETUP_CHANNEL management datagrams
(MADs) were defined in a previous patchset. If the client advertises a
desire to use channels and the partner VIOS is channel capable then the
client must proceed with channel enquiry to determine the maximum number
of channels the VIOS is capable of providing, and registering SubCRQs
via channel setup with the VIOS immediately following NPIV Login. This
handshaking should not be performed for subsequent NPIV Logins unless
the CRQ connection has been reset.

Implement these two new MADs and issue them following a successful NPIV
login where the VIOS has set the SUPPORT_CHANNELS capability bit in the
NPIV Login response.

Signed-off-by: Tyrel Datwyler 
---
 drivers/scsi/ibmvscsi/ibmvfc.c | 135 -
 drivers/scsi/ibmvscsi/ibmvfc.h |   3 +
 2 files changed, 136 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index d3d7c6b53d4f..a00f38558613 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -909,6 +909,8 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
spin_lock(vhost->crq.q_lock);
vhost->state = IBMVFC_NO_CRQ;
vhost->logged_in = 0;
+   vhost->do_enquiry = 1;
+   vhost->using_channels = 0;
 
/* Clean out the queue */
memset(crq->msgs.crq, 0, PAGE_SIZE);
@@ -4586,6 +4588,118 @@ static void ibmvfc_discover_targets(struct ibmvfc_host 
*vhost)
ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
 }
 
+static void ibmvfc_channel_setup_done(struct ibmvfc_event *evt)
+{
+   struct ibmvfc_host *vhost = evt->vhost;
+   u32 mad_status = be16_to_cpu(evt->xfer_iu->channel_setup.common.status);
+   int level = IBMVFC_DEFAULT_LOG_LEVEL;
+
+   ibmvfc_free_event(evt);
+
+   switch (mad_status) {
+   case IBMVFC_MAD_SUCCESS:
+   ibmvfc_dbg(vhost, "Channel Setup succeded\n");
+   vhost->do_enquiry = 0;
+   break;
+   case IBMVFC_MAD_FAILED:
+   level += ibmvfc_retry_host_init(vhost);
+   ibmvfc_log(vhost, level, "Channel Setup failed\n");
+   fallthrough;
+   case IBMVFC_MAD_DRIVER_FAILED:
+   return;
+   default:
+   dev_err(vhost->dev, "Invalid Channel Setup response: 0x%x\n",
+   mad_status);
+   ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
+   return;
+   }
+
+   ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY);
+   wake_up(>work_wait_q);
+}
+
+static void ibmvfc_channel_setup(struct ibmvfc_host *vhost)
+{
+   struct ibmvfc_channel_setup_mad *mad;
+   struct ibmvfc_channel_setup *setup_buf = vhost->channel_setup_buf;
+   struct ibmvfc_event *evt = ibmvfc_get_event(>crq);
+
+   memset(setup_buf, 0, sizeof(*setup_buf));
+   setup_buf->flags = cpu_to_be32(IBMVFC_CANCEL_CHANNELS);
+
+   ibmvfc_init_event(evt, ibmvfc_channel_setup_done, IBMVFC_MAD_FORMAT);
+   mad = >iu.channel_setup;
+   memset(mad, 0, sizeof(*mad));
+   mad->common.version = cpu_to_be32(1);
+   mad->common.opcode = cpu_to_be32(IBMVFC_CHANNEL_SETUP);
+   mad->common.length = cpu_to_be16(sizeof(*mad));
+   mad->buffer.va = cpu_to_be64(vhost->channel_setup_dma);
+   mad->buffer.len = cpu_to_be32(sizeof(*vhost->channel_setup_buf));
+
+   ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT_WAIT);
+
+   if (!ibmvfc_send_event(evt, vhost, default_timeout))
+   ibmvfc_dbg(vhost, "Sent channel setup\n");
+   else
+   ibmvfc_link_down(vhost, IBMVFC_LINK_DOWN);
+}
+
+static void ibmvfc_channel_enquiry_done(struct ibmvfc_event *evt)
+{
+   struct ibmvfc_host *vhost = evt->vhost;
+   struct ibmvfc_channel_enquiry *rsp = >xfer_iu->channel_enquiry;
+   u32 mad_status = be16_to_cpu(rsp->common.status);
+   int level = IBMVFC_DEFAULT_LOG_LEVEL;
+
+   switch (mad_status) {
+   case IBMVFC_MAD_SUCCESS:
+   ibmvfc_dbg(vhost, "Channel Enquiry succeeded\n");
+   vhost->max_vios_scsi_channels = 
be32_to_cpu(rsp->num_scsi_subq_channels);
+   ibmvfc_free_event(evt);
+   break;
+   case IBMVFC_MAD_FAILED:
+   level += ibmvfc_retry_host_init(vhost);
+   ibmvfc_log(vhost, level, "Channel Enquiry failed\n");
+   fallthrough;
+   case IBMVFC_MAD_DRIVER_FAILED:
+   ibmvfc_free_event(evt);
+   return;
+   default:
+   dev_err(vhost->dev, "Invalid Channel Enquiry response: 0x%x\n",
+   mad_status);
+   ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD);
+   ibmvfc_free_event(evt);
+   return;
+   }
+
+   ibmvfc_channel_setup(vhost);
+}
+
+static void ibmvfc_channel_enquiry(struct ibmvfc_host *vhost)
+{
+   struct ibmvfc_channel_enquiry *mad;
+   

[PATCH v4 10/21] ibmvfc: define Sub-CRQ interrupt handler routine

2021-01-11 Thread Tyrel Datwyler
Simple handler that calls Sub-CRQ drain routine directly.

Signed-off-by: Tyrel Datwyler 
---
 drivers/scsi/ibmvscsi/ibmvfc.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index f3cd092478ee..51bcafad9490 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -3571,6 +3571,16 @@ static void ibmvfc_drain_sub_crq(struct ibmvfc_queue 
*scrq)
}
 }
 
+static irqreturn_t ibmvfc_interrupt_scsi(int irq, void *scrq_instance)
+{
+   struct ibmvfc_queue *scrq = (struct ibmvfc_queue *)scrq_instance;
+
+   ibmvfc_toggle_scrq_irq(scrq, 0);
+   ibmvfc_drain_sub_crq(scrq);
+
+   return IRQ_HANDLED;
+}
+
 /**
  * ibmvfc_init_tgt - Set the next init job step for the target
  * @tgt:   ibmvfc target struct
-- 
2.27.0



[PATCH v4 00/21] ibmvfc: initial MQ development

2021-01-11 Thread Tyrel Datwyler
Recent updates in pHyp Firmware and VIOS releases provide new infrastructure
towards enabling Subordinate Command Response Queues (Sub-CRQs) such that each
Sub-CRQ is a channel backed by an actual hardware queue in the FC stack on the
partner VIOS. Sub-CRQs are registered with the firmware via hypercalls and then
negotiated with the VIOS via new Management Datagrams (MADs) for channel setup.

This initial implementation adds the necessary Sub-CRQ framework and implements
the new MADs for negotiating and assigning a set of Sub-CRQs to associated VIOS
HW backed channels.

This latest series is completely rebased and reimplemented on top of the recent
("ibmvfc: MQ prepartory locking work") series. [1]

[1] 
https://lore.kernel.org/linux-scsi/20210106201835.1053593-1-tyr...@linux.ibm.com/

changes in v4:
* Series rebased and reworked on top of previous ibmvfc locking series
* Dropped all previous Reviewed-by tags

changes in v3:
* Patch 4: changed firmware support logging to dev_warn_once
* Patch 6: adjusted locking
* Patch 15: dropped logging verbosity, moved cancel event tracking into subqueue
* Patch 17: removed write permission for migration module parameters
drive hard reset after update to num of scsi channels

changes in v2:
* Patch 4: NULL'd scsi_scrq reference after deallocation
* Patch 6: Added switch case to handle XPORT event
* Patch 9: fixed ibmvfc_event leak and double free
* added support for cancel command with MQ
* added parameter toggles for MQ settings

Tyrel Datwyler (21):
  ibmvfc: add vhost fields and defaults for MQ enablement
  ibmvfc: move event pool init/free routines
  ibmvfc: init/free event pool during queue allocation/free
  ibmvfc: add size parameter to ibmvfc_init_event_pool
  ibmvfc: define hcall wrapper for registering a Sub-CRQ
  ibmvfc: add Subordinate CRQ definitions
  ibmvfc: add alloc/dealloc routines for SCSI Sub-CRQ Channels
  ibmvfc: add Sub-CRQ IRQ enable/disable routine
  ibmvfc: add handlers to drain and complete Sub-CRQ responses
  ibmvfc: define Sub-CRQ interrupt handler routine
  ibmvfc: map/request irq and register Sub-CRQ interrupt handler
  ibmvfc: implement channel enquiry and setup commands
  ibmvfc: advertise client support for using hardware channels
  ibmvfc: set and track hw queue in ibmvfc_event struct
  ibmvfc: send commands down HW Sub-CRQ when channelized
  ibmvfc: register Sub-CRQ handles with VIOS during channel setup
  ibmvfc: add cancel mad initialization helper
  ibmvfc: send Cancel MAD down each hw scsi channel
  ibmvfc: purge scsi channels after transport loss/reset
  ibmvfc: enable MQ and set reasonable defaults
  ibmvfc: provide modules parameters for MQ settings

 drivers/scsi/ibmvscsi/ibmvfc.c | 914 -
 drivers/scsi/ibmvscsi/ibmvfc.h |  38 ++
 2 files changed, 824 insertions(+), 128 deletions(-)

-- 
2.27.0



[PATCH v4 05/21] ibmvfc: define hcall wrapper for registering a Sub-CRQ

2021-01-11 Thread Tyrel Datwyler
Sub-CRQs are registred with firmware via a hypercall. Abstract that
interface into a simpler helper function.

Signed-off-by: Tyrel Datwyler 
---
 drivers/scsi/ibmvscsi/ibmvfc.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 524e81164d70..612c7f3d7bd3 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -138,6 +138,20 @@ static void ibmvfc_tgt_move_login(struct ibmvfc_target *);
 
 static const char *unknown_error = "unknown error";
 
+static long h_reg_sub_crq(unsigned long unit_address, unsigned long ioba,
+ unsigned long length, unsigned long *cookie,
+ unsigned long *irq)
+{
+   unsigned long retbuf[PLPAR_HCALL_BUFSIZE];
+   long rc;
+
+   rc = plpar_hcall(H_REG_SUB_CRQ, retbuf, unit_address, ioba, length);
+   *cookie = retbuf[0];
+   *irq = retbuf[1];
+
+   return rc;
+}
+
 static int ibmvfc_check_caps(struct ibmvfc_host *vhost, unsigned long 
cap_flags)
 {
u64 host_caps = be64_to_cpu(vhost->login_buf->resp.capabilities);
-- 
2.27.0



[PATCH v4 02/21] ibmvfc: move event pool init/free routines

2021-01-11 Thread Tyrel Datwyler
The next patch in this series reworks the event pool allocation calls to
happen within the individual queue allocation routines instead of as
independent calls.

Move the init/free routines earlier in ibmvfc.c to prevent undefined
reference errors when calling these functions from the queue allocation
code. No functional change.

Signed-off-by: Tyrel Datwyler 
---
 drivers/scsi/ibmvscsi/ibmvfc.c | 151 +
 1 file changed, 76 insertions(+), 75 deletions(-)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 9200fe49c57e..cd9273a5fadb 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -716,6 +716,82 @@ static int ibmvfc_send_crq_init_complete(struct 
ibmvfc_host *vhost)
return ibmvfc_send_crq(vhost, 0xC002LL, 0);
 }
 
+/**
+ * ibmvfc_init_event_pool - Allocates and initializes the event pool for a host
+ * @vhost: ibmvfc host who owns the event pool
+ *
+ * Returns zero on success.
+ **/
+static int ibmvfc_init_event_pool(struct ibmvfc_host *vhost,
+ struct ibmvfc_queue *queue)
+{
+   int i;
+   struct ibmvfc_event_pool *pool = >evt_pool;
+
+   ENTER;
+   pool->size = max_requests + IBMVFC_NUM_INTERNAL_REQ;
+   pool->events = kcalloc(pool->size, sizeof(*pool->events), GFP_KERNEL);
+   if (!pool->events)
+   return -ENOMEM;
+
+   pool->iu_storage = dma_alloc_coherent(vhost->dev,
+ pool->size * 
sizeof(*pool->iu_storage),
+ >iu_token, 0);
+
+   if (!pool->iu_storage) {
+   kfree(pool->events);
+   return -ENOMEM;
+   }
+
+   INIT_LIST_HEAD(>sent);
+   INIT_LIST_HEAD(>free);
+   spin_lock_init(>l_lock);
+
+   for (i = 0; i < pool->size; ++i) {
+   struct ibmvfc_event *evt = >events[i];
+
+   atomic_set(>free, 1);
+   evt->crq.valid = 0x80;
+   evt->crq.ioba = cpu_to_be64(pool->iu_token + 
(sizeof(*evt->xfer_iu) * i));
+   evt->xfer_iu = pool->iu_storage + i;
+   evt->vhost = vhost;
+   evt->queue = queue;
+   evt->ext_list = NULL;
+   list_add_tail(>queue_list, >free);
+   }
+
+   LEAVE;
+   return 0;
+}
+
+/**
+ * ibmvfc_free_event_pool - Frees memory of the event pool of a host
+ * @vhost: ibmvfc host who owns the event pool
+ *
+ **/
+static void ibmvfc_free_event_pool(struct ibmvfc_host *vhost,
+  struct ibmvfc_queue *queue)
+{
+   int i;
+   struct ibmvfc_event_pool *pool = >evt_pool;
+
+   ENTER;
+   for (i = 0; i < pool->size; ++i) {
+   list_del(>events[i].queue_list);
+   BUG_ON(atomic_read(>events[i].free) != 1);
+   if (pool->events[i].ext_list)
+   dma_pool_free(vhost->sg_pool,
+ pool->events[i].ext_list,
+ pool->events[i].ext_list_token);
+   }
+
+   kfree(pool->events);
+   dma_free_coherent(vhost->dev,
+ pool->size * sizeof(*pool->iu_storage),
+ pool->iu_storage, pool->iu_token);
+   LEAVE;
+}
+
 /**
  * ibmvfc_free_queue - Deallocate queue
  * @vhost: ibmvfc host struct
@@ -1312,81 +1388,6 @@ static void ibmvfc_set_login_info(struct ibmvfc_host 
*vhost)
strncpy(login_info->drc_name, location, IBMVFC_MAX_NAME);
 }
 
-/**
- * ibmvfc_init_event_pool - Allocates and initializes the event pool for a host
- * @vhost: ibmvfc host who owns the event pool
- *
- * Returns zero on success.
- **/
-static int ibmvfc_init_event_pool(struct ibmvfc_host *vhost,
- struct ibmvfc_queue *queue)
-{
-   int i;
-   struct ibmvfc_event_pool *pool = >evt_pool;
-
-   ENTER;
-   pool->size = max_requests + IBMVFC_NUM_INTERNAL_REQ;
-   pool->events = kcalloc(pool->size, sizeof(*pool->events), GFP_KERNEL);
-   if (!pool->events)
-   return -ENOMEM;
-
-   pool->iu_storage = dma_alloc_coherent(vhost->dev,
- pool->size * 
sizeof(*pool->iu_storage),
- >iu_token, 0);
-
-   if (!pool->iu_storage) {
-   kfree(pool->events);
-   return -ENOMEM;
-   }
-
-   INIT_LIST_HEAD(>sent);
-   INIT_LIST_HEAD(>free);
-   spin_lock_init(>l_lock);
-
-   for (i = 0; i < pool->size; ++i) {
-   struct ibmvfc_event *evt = >events[i];
-   atomic_set(>free, 1);
-   evt->crq.valid = 0x80;
-   evt->crq.ioba = cpu_to_be64(pool->iu_token + 
(sizeof(*evt->xfer_iu) * i));
-   evt->xfer_iu = pool->iu_storage + i;
-   evt->vhost = vhost;
-   evt->queue = queue;
-   

[PATCH v4 01/21] ibmvfc: add vhost fields and defaults for MQ enablement

2021-01-11 Thread Tyrel Datwyler
Introduce several new vhost fields for managing MQ state of the adapter
as well as initial defaults for MQ enablement.

Signed-off-by: Tyrel Datwyler 
---
 drivers/scsi/ibmvscsi/ibmvfc.c | 8 
 drivers/scsi/ibmvscsi/ibmvfc.h | 9 +
 2 files changed, 17 insertions(+)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index ba95438a8912..9200fe49c57e 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -3302,6 +3302,7 @@ static struct scsi_host_template driver_template = {
.max_sectors = IBMVFC_MAX_SECTORS,
.shost_attrs = ibmvfc_attrs,
.track_queue_depth = 1,
+   .host_tagset = 1,
 };
 
 /**
@@ -5290,6 +5291,7 @@ static int ibmvfc_probe(struct vio_dev *vdev, const 
struct vio_device_id *id)
shost->max_sectors = IBMVFC_MAX_SECTORS;
shost->max_cmd_len = IBMVFC_MAX_CDB_LEN;
shost->unique_id = shost->host_no;
+   shost->nr_hw_queues = IBMVFC_MQ ? IBMVFC_SCSI_HW_QUEUES : 1;
 
vhost = shost_priv(shost);
INIT_LIST_HEAD(>targets);
@@ -5300,6 +5302,12 @@ static int ibmvfc_probe(struct vio_dev *vdev, const 
struct vio_device_id *id)
vhost->partition_number = -1;
vhost->log_level = log_level;
vhost->task_set = 1;
+
+   vhost->mq_enabled = IBMVFC_MQ;
+   vhost->client_scsi_channels = IBMVFC_SCSI_CHANNELS;
+   vhost->using_channels = 0;
+   vhost->do_enquiry = 1;
+
strcpy(vhost->partition_name, "UNKNOWN");
init_waitqueue_head(>work_wait_q);
init_waitqueue_head(>init_wait_q);
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index 632e977449c5..dd6d89292867 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -41,6 +41,11 @@
 #define IBMVFC_DEFAULT_LOG_LEVEL   2
 #define IBMVFC_MAX_CDB_LEN 16
 #define IBMVFC_CLS3_ERROR  0
+#define IBMVFC_MQ  0
+#define IBMVFC_SCSI_CHANNELS   0
+#define IBMVFC_SCSI_HW_QUEUES  1
+#define IBMVFC_MIG_NO_SUB_TO_CRQ   0
+#define IBMVFC_MIG_NO_N_TO_M   0
 
 /*
  * Ensure we have resources for ERP and initialization:
@@ -840,6 +845,10 @@ struct ibmvfc_host {
int delay_init;
int scan_complete;
int logged_in;
+   int mq_enabled;
+   int using_channels;
+   int do_enquiry;
+   int client_scsi_channels;
int aborting_passthru;
int events_to_log;
 #define IBMVFC_AE_LINKUP   0x0001
-- 
2.27.0



[PATCH v4 06/21] ibmvfc: add Subordinate CRQ definitions

2021-01-11 Thread Tyrel Datwyler
Subordinate Command Response Queues (Sub CRQ) are used in conjunction
with the primary CRQ when more than one queue is needed by the virtual
IO adapter. Recent phyp firmware versions support Sub CRQ's with ibmvfc
adapters. This feature is a prerequisite for supporting multiple
hardware backed submission queues in the vfc adapter.

The Sub CRQ command element differs from the standard CRQ in that it is
32bytes long as opposed to 16bytes for the latter. Despite this extra
16bytes the ibmvfc protocol will use the original CRQ command element
mapped to the first 16bytes of the Sub CRQ element initially.

Add definitions for the Sub CRQ command element and queue.

Signed-off-by: Tyrel Datwyler 
---
 drivers/scsi/ibmvscsi/ibmvfc.h | 21 +
 1 file changed, 21 insertions(+)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index dd6d89292867..b9eed05c165f 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -650,6 +650,11 @@ struct ibmvfc_crq {
volatile __be64 ioba;
 } __packed __aligned(8);
 
+struct ibmvfc_sub_crq {
+   struct ibmvfc_crq crq;
+   __be64 reserved[2];
+} __packed __aligned(8);
+
 enum ibmvfc_ae_link_state {
IBMVFC_AE_LS_LINK_UP= 0x01,
IBMVFC_AE_LS_LINK_BOUNCED   = 0x02,
@@ -761,12 +766,14 @@ struct ibmvfc_event_pool {
 enum ibmvfc_msg_fmt {
IBMVFC_CRQ_FMT = 0,
IBMVFC_ASYNC_FMT,
+   IBMVFC_SUB_CRQ_FMT,
 };
 
 union ibmvfc_msgs {
void *handle;
struct ibmvfc_crq *crq;
struct ibmvfc_async_crq *async;
+   struct ibmvfc_sub_crq *scrq;
 };
 
 struct ibmvfc_queue {
@@ -781,6 +788,20 @@ struct ibmvfc_queue {
struct list_head sent;
struct list_head free;
spinlock_t l_lock;
+
+   /* Sub-CRQ fields */
+   struct ibmvfc_host *vhost;
+   unsigned long cookie;
+   unsigned long vios_cookie;
+   unsigned long hw_irq;
+   unsigned long irq;
+   unsigned long hwq_id;
+   char name[32];
+};
+
+struct ibmvfc_scsi_channels {
+   struct ibmvfc_queue *scrqs;
+   unsigned int active_queues;
 };
 
 enum ibmvfc_host_action {
-- 
2.27.0



[PATCH v4 04/21] ibmvfc: add size parameter to ibmvfc_init_event_pool

2021-01-11 Thread Tyrel Datwyler
With the upcoming addition of Sub-CRQs the event pool size may vary
per-queue.

Add a size parameter to ibmvfc_init_event_pool such that different size
event pools can be requested by ibmvfc_alloc_queue.

Signed-off-by: Tyrel Datwyler 
---
 drivers/scsi/ibmvscsi/ibmvfc.c | 25 -
 1 file changed, 16 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 9330f5a65a7e..524e81164d70 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -723,19 +723,23 @@ static int ibmvfc_send_crq_init_complete(struct 
ibmvfc_host *vhost)
  * Returns zero on success.
  **/
 static int ibmvfc_init_event_pool(struct ibmvfc_host *vhost,
- struct ibmvfc_queue *queue)
+ struct ibmvfc_queue *queue,
+ unsigned int size)
 {
int i;
struct ibmvfc_event_pool *pool = >evt_pool;
 
ENTER;
-   pool->size = max_requests + IBMVFC_NUM_INTERNAL_REQ;
-   pool->events = kcalloc(pool->size, sizeof(*pool->events), GFP_KERNEL);
+   if (!size)
+   return 0;
+
+   pool->size = size;
+   pool->events = kcalloc(size, sizeof(*pool->events), GFP_KERNEL);
if (!pool->events)
return -ENOMEM;
 
pool->iu_storage = dma_alloc_coherent(vhost->dev,
- pool->size * 
sizeof(*pool->iu_storage),
+ size * sizeof(*pool->iu_storage),
  >iu_token, 0);
 
if (!pool->iu_storage) {
@@ -747,7 +751,7 @@ static int ibmvfc_init_event_pool(struct ibmvfc_host *vhost,
INIT_LIST_HEAD(>free);
spin_lock_init(>l_lock);
 
-   for (i = 0; i < pool->size; ++i) {
+   for (i = 0; i < size; ++i) {
struct ibmvfc_event *evt = >events[i];
 
atomic_set(>free, 1);
@@ -5013,6 +5017,7 @@ static int ibmvfc_alloc_queue(struct ibmvfc_host *vhost,
 {
struct device *dev = vhost->dev;
size_t fmt_size;
+   unsigned int pool_size = 0;
 
ENTER;
spin_lock_init(>_lock);
@@ -5021,10 +5026,7 @@ static int ibmvfc_alloc_queue(struct ibmvfc_host *vhost,
switch (fmt) {
case IBMVFC_CRQ_FMT:
fmt_size = sizeof(*queue->msgs.crq);
-   if (ibmvfc_init_event_pool(vhost, queue)) {
-   dev_err(dev, "Couldn't initialize event pool.\n");
-   return -ENOMEM;
-   }
+   pool_size = max_requests + IBMVFC_NUM_INTERNAL_REQ;
break;
case IBMVFC_ASYNC_FMT:
fmt_size = sizeof(*queue->msgs.async);
@@ -5034,6 +5036,11 @@ static int ibmvfc_alloc_queue(struct ibmvfc_host *vhost,
return -EINVAL;
}
 
+   if (ibmvfc_init_event_pool(vhost, queue, pool_size)) {
+   dev_err(dev, "Couldn't initialize event pool.\n");
+   return -ENOMEM;
+   }
+
queue->msgs.handle = (void *)get_zeroed_page(GFP_KERNEL);
if (!queue->msgs.handle)
return -ENOMEM;
-- 
2.27.0



[PATCH v4 07/21] ibmvfc: add alloc/dealloc routines for SCSI Sub-CRQ Channels

2021-01-11 Thread Tyrel Datwyler
Allocate a set of Sub-CRQs in advance. During channel setup the client
and VIOS negotiate the number of queues the VIOS supports and the number
that the client desires to request. Its possible that the final channel
resources allocated is less than requested, but the client is still
responsible for sending handles for every queue it is hoping for.

Also, provide deallocation cleanup routines.

Signed-off-by: Tyrel Datwyler 
---
 drivers/scsi/ibmvscsi/ibmvfc.c | 125 +
 drivers/scsi/ibmvscsi/ibmvfc.h |   1 +
 2 files changed, 126 insertions(+)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 612c7f3d7bd3..a198e118887d 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -895,6 +895,8 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
unsigned long flags;
struct vio_dev *vdev = to_vio_dev(vhost->dev);
struct ibmvfc_queue *crq = >crq;
+   struct ibmvfc_queue *scrq;
+   int i;
 
/* Close the CRQ */
do {
@@ -912,6 +914,16 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
memset(crq->msgs.crq, 0, PAGE_SIZE);
crq->cur = 0;
 
+   if (vhost->scsi_scrqs.scrqs) {
+   for (i = 0; i < IBMVFC_SCSI_HW_QUEUES; i++) {
+   scrq = >scsi_scrqs.scrqs[i];
+   spin_lock(scrq->q_lock);
+   memset(scrq->msgs.scrq, 0, PAGE_SIZE);
+   scrq->cur = 0;
+   spin_unlock(scrq->q_lock);
+   }
+   }
+
/* And re-open it again */
rc = plpar_hcall_norets(H_REG_CRQ, vdev->unit_address,
crq->msg_token, PAGE_SIZE);
@@ -5045,6 +5057,11 @@ static int ibmvfc_alloc_queue(struct ibmvfc_host *vhost,
case IBMVFC_ASYNC_FMT:
fmt_size = sizeof(*queue->msgs.async);
break;
+   case IBMVFC_SUB_CRQ_FMT:
+   fmt_size = sizeof(*queue->msgs.scrq);
+   /* We need one extra event for Cancel Commands */
+   pool_size = max_requests + 1;
+   break;
default:
dev_warn(dev, "Unknown command/response queue message format: 
%d\n", fmt);
return -EINVAL;
@@ -5136,6 +5153,107 @@ static int ibmvfc_init_crq(struct ibmvfc_host *vhost)
return retrc;
 }
 
+static int ibmvfc_register_scsi_channel(struct ibmvfc_host *vhost,
+ int index)
+{
+   struct device *dev = vhost->dev;
+   struct vio_dev *vdev = to_vio_dev(dev);
+   struct ibmvfc_queue *scrq = >scsi_scrqs.scrqs[index];
+   int rc = -ENOMEM;
+
+   ENTER;
+
+   if (ibmvfc_alloc_queue(vhost, scrq, IBMVFC_SUB_CRQ_FMT))
+   return -ENOMEM;
+
+   rc = h_reg_sub_crq(vdev->unit_address, scrq->msg_token, PAGE_SIZE,
+  >cookie, >hw_irq);
+
+   if (rc) {
+   dev_warn(dev, "Error registering sub-crq: %d\n", rc);
+   if (rc == H_PARAMETER)
+   dev_warn_once(dev, "Firmware may not support MQ\n");
+   goto reg_failed;
+   }
+
+   scrq->hwq_id = index;
+   scrq->vhost = vhost;
+
+   LEAVE;
+   return 0;
+
+reg_failed:
+   ibmvfc_free_queue(vhost, scrq);
+   LEAVE;
+   return rc;
+}
+
+static void ibmvfc_deregister_scsi_channel(struct ibmvfc_host *vhost, int 
index)
+{
+   struct device *dev = vhost->dev;
+   struct vio_dev *vdev = to_vio_dev(dev);
+   struct ibmvfc_queue *scrq = >scsi_scrqs.scrqs[index];
+   long rc;
+
+   ENTER;
+
+   do {
+   rc = plpar_hcall_norets(H_FREE_SUB_CRQ, vdev->unit_address,
+   scrq->cookie);
+   } while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
+
+   if (rc)
+   dev_err(dev, "Failed to free sub-crq[%d]: rc=%ld\n", index, rc);
+
+   ibmvfc_free_queue(vhost, scrq);
+   LEAVE;
+}
+
+static int ibmvfc_init_sub_crqs(struct ibmvfc_host *vhost)
+{
+   int i, j;
+
+   ENTER;
+
+   vhost->scsi_scrqs.scrqs = kcalloc(IBMVFC_SCSI_HW_QUEUES,
+ sizeof(*vhost->scsi_scrqs.scrqs),
+ GFP_KERNEL);
+   if (!vhost->scsi_scrqs.scrqs)
+   return -1;
+
+   for (i = 0; i < IBMVFC_SCSI_HW_QUEUES; i++) {
+   if (ibmvfc_register_scsi_channel(vhost, i)) {
+   for (j = i; j > 0; j--)
+   ibmvfc_deregister_scsi_channel(vhost, j - 1);
+   kfree(vhost->scsi_scrqs.scrqs);
+   vhost->scsi_scrqs.scrqs = NULL;
+   vhost->scsi_scrqs.active_queues = 0;
+   LEAVE;
+   return -1;
+   }
+   }
+
+   LEAVE;
+   return 0;
+}
+
+static void ibmvfc_release_sub_crqs(struct ibmvfc_host *vhost)
+{
+ 

[PATCH v4 03/21] ibmvfc: init/free event pool during queue allocation/free

2021-01-11 Thread Tyrel Datwyler
The event pool and CRQ used to be separate entities of the adapter host
structure and as such were allocated and freed independently of each
other. Recent work as defined a generic queue structure with an event
pool specific to each queue. As such the event pool for each queue
shouldn't be allocated/freed independently, but instead performed as
part of the queue allocation/free routines.

Move the calls to ibmvfc_event_pool_{init|free} into
ibmvfc_{alloc|free}_queue respectively. The only functional change here
is that the CRQ cannot be released in ibmvfc_remove until after the
event pool has been successfully purged since releasing the queue will
also free the event pool.

Signed-off-by: Tyrel Datwyler 
---
 drivers/scsi/ibmvscsi/ibmvfc.c | 18 --
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index cd9273a5fadb..9330f5a65a7e 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -807,6 +807,8 @@ static void ibmvfc_free_queue(struct ibmvfc_host *vhost,
dma_unmap_single(dev, queue->msg_token, PAGE_SIZE, DMA_BIDIRECTIONAL);
free_page((unsigned long)queue->msgs.handle);
queue->msgs.handle = NULL;
+
+   ibmvfc_free_event_pool(vhost, queue);
 }
 
 /**
@@ -5019,6 +5021,10 @@ static int ibmvfc_alloc_queue(struct ibmvfc_host *vhost,
switch (fmt) {
case IBMVFC_CRQ_FMT:
fmt_size = sizeof(*queue->msgs.crq);
+   if (ibmvfc_init_event_pool(vhost, queue)) {
+   dev_err(dev, "Couldn't initialize event pool.\n");
+   return -ENOMEM;
+   }
break;
case IBMVFC_ASYNC_FMT:
fmt_size = sizeof(*queue->msgs.async);
@@ -5333,13 +5339,8 @@ static int ibmvfc_probe(struct vio_dev *vdev, const 
struct vio_device_id *id)
goto kill_kthread;
}
 
-   if ((rc = ibmvfc_init_event_pool(vhost, >crq))) {
-   dev_err(dev, "Couldn't initialize event pool. rc=%d\n", rc);
-   goto release_crq;
-   }
-
if ((rc = scsi_add_host(shost, dev)))
-   goto release_event_pool;
+   goto release_crq;
 
fc_host_dev_loss_tmo(shost) = IBMVFC_DEV_LOSS_TMO;
 
@@ -5362,8 +5363,6 @@ static int ibmvfc_probe(struct vio_dev *vdev, const 
struct vio_device_id *id)
 
 remove_shost:
scsi_remove_host(shost);
-release_event_pool:
-   ibmvfc_free_event_pool(vhost, >crq);
 release_crq:
ibmvfc_release_crq_queue(vhost);
 kill_kthread:
@@ -5398,7 +5397,6 @@ static int ibmvfc_remove(struct vio_dev *vdev)
spin_unlock_irqrestore(vhost->host->host_lock, flags);
 
ibmvfc_wait_while_resetting(vhost);
-   ibmvfc_release_crq_queue(vhost);
kthread_stop(vhost->work_thread);
fc_remove_host(vhost->host);
scsi_remove_host(vhost->host);
@@ -5408,7 +5406,7 @@ static int ibmvfc_remove(struct vio_dev *vdev)
list_splice_init(>purge, );
spin_unlock_irqrestore(vhost->host->host_lock, flags);
ibmvfc_complete_purge();
-   ibmvfc_free_event_pool(vhost, >crq);
+   ibmvfc_release_crq_queue(vhost);
 
ibmvfc_free_mem(vhost);
spin_lock(_driver_lock);
-- 
2.27.0



Re: [PATCH v2] powerpc/vdso: fix clock_gettime_fallback for vdso32

2021-01-11 Thread kernel test robot
Hi Christophe,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on powerpc/next]
[also build test ERROR on v5.11-rc3 next-20210111]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:
https://github.com/0day-ci/linux/commits/Christophe-Leroy/powerpc-vdso-fix-clock_gettime_fallback-for-vdso32/20210112-005359
base:   https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git next
config: powerpc-allyesconfig (attached as .config)
compiler: powerpc64-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
wget 
https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O 
~/bin/make.cross
chmod +x ~/bin/make.cross
# 
https://github.com/0day-ci/linux/commit/49b084da4df1e1cf12240826b7d6db743c761e7c
git remote add linux-review https://github.com/0day-ci/linux
git fetch --no-tags linux-review 
Christophe-Leroy/powerpc-vdso-fix-clock_gettime_fallback-for-vdso32/20210112-005359
git checkout 49b084da4df1e1cf12240826b7d6db743c761e7c
# save the attached .config to linux build tree
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross 
ARCH=powerpc 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot 

All errors (new ones prefixed by >>):

   In file included from include/vdso/datapage.h:137,
from arch/powerpc/include/asm/vdso_datapage.h:39,
from arch/powerpc/kernel/asm-offsets.c:37:
   arch/powerpc/include/asm/vdso/gettimeofday.h: In function 
'clock_gettime_fallback':
>> arch/powerpc/include/asm/vdso/gettimeofday.h:113:22: error: 
>> '__NR_clock_gettime64' undeclared (first use in this function)
 113 |  return do_syscall_2(__NR_clock_gettime64, _clkid, (unsigned 
long)_ts);
 |  ^~~~
   arch/powerpc/include/asm/vdso/gettimeofday.h:113:22: note: each undeclared 
identifier is reported only once for each function it appears in
   arch/powerpc/include/asm/vdso/gettimeofday.h: In function 
'clock_getres_fallback':
>> arch/powerpc/include/asm/vdso/gettimeofday.h:119:22: error: 
>> '__NR_clock_getres_time64' undeclared (first use in this function)
 119 |  return do_syscall_2(__NR_clock_getres_time64, _clkid, (unsigned 
long)_ts);
 |  ^~~~
--
   In file included from include/vdso/datapage.h:137,
from arch/powerpc/include/asm/vdso_datapage.h:39,
from arch/powerpc/kernel/asm-offsets.c:37:
   arch/powerpc/include/asm/vdso/gettimeofday.h: In function 
'clock_gettime_fallback':
>> arch/powerpc/include/asm/vdso/gettimeofday.h:113:22: error: 
>> '__NR_clock_gettime64' undeclared (first use in this function)
 113 |  return do_syscall_2(__NR_clock_gettime64, _clkid, (unsigned 
long)_ts);
 |  ^~~~
   arch/powerpc/include/asm/vdso/gettimeofday.h:113:22: note: each undeclared 
identifier is reported only once for each function it appears in
   arch/powerpc/include/asm/vdso/gettimeofday.h: In function 
'clock_getres_fallback':
>> arch/powerpc/include/asm/vdso/gettimeofday.h:119:22: error: 
>> '__NR_clock_getres_time64' undeclared (first use in this function)
 119 |  return do_syscall_2(__NR_clock_getres_time64, _clkid, (unsigned 
long)_ts);
 |  ^~~~
   make[2]: *** [scripts/Makefile.build:117: arch/powerpc/kernel/asm-offsets.s] 
Error 1
   make[2]: Target '__build' not remade because of errors.
   make[1]: *** [Makefile:1206: prepare0] Error 2
   make[1]: Target 'modules_prepare' not remade because of errors.
   make: *** [Makefile:185: __sub-make] Error 2
   make: Target 'modules_prepare' not remade because of errors.
--
   In file included from include/vdso/datapage.h:137,
from arch/powerpc/include/asm/vdso_datapage.h:39,
from arch/powerpc/kernel/asm-offsets.c:37:
   arch/powerpc/include/asm/vdso/gettimeofday.h: In function 
'clock_gettime_fallback':
>> arch/powerpc/include/asm/vdso/gettimeofday.h:113:22: error: 
>> '__NR_clock_gettime64' undeclared (first use in this function)
 113 |  return do_syscall_2(__NR_clock_gettime64, _clkid, (unsigned 
long)_ts);
 |  ^~~~
   arch/powerpc/include/asm/vdso/gettimeofday.h:113:22: note: each undeclared 
identifier is reported only once for each function it appears in
   arch/powerpc/include/asm/vdso/gettimeofday.h: In function 
'clock_getres_fallback':
>> arch/powerpc/include/asm/vdso/gettimeofday.h:119:22: error: 
>> '__NR_clock_getres_time64' undeclared (first use in this function)
 11

Re: [PATCH 02/17] rtc: pl031: use RTC_FEATURE_ALARM

2021-01-11 Thread Linus Walleij
On Mon, Jan 11, 2021 at 12:18 AM Alexandre Belloni
 wrote:

> Clear RTC_FEATURE_ALARM instead of setting set_alarm, read_alarm and
> alarm_irq_enable to NULL.
>
> Signed-off-by: Alexandre Belloni 

Acked-by: Linus Walleij 

Yours,
Linus Walleij


[PATCH v2] powerpc/vdso: fix clock_gettime_fallback for vdso32

2021-01-11 Thread Christophe Leroy
From: Andreas Schwab 

The second argument of __kernel_clock_gettime64 points to a struct
__kernel_timespec, with 64-bit time_t, so use the clock_gettime64 syscall
in the fallback function for the 32-bit vdso.  Similarily,
clock_getres_fallback should use the clock_getres_time64 syscall, though
it isn't yet called from the 32-bit vdso.

Signed-off-by: Andreas Schwab 
[chleroy: Moved into the #ifdef CONFIG_VDSO32 block]
Fixes: d0e3fc69d00d ("powerpc/vdso: Provide __kernel_clock_gettime64() on 
vdso32")
Signed-off-by: Christophe Leroy 
---
 arch/powerpc/include/asm/vdso/gettimeofday.h | 27 +++-
 1 file changed, 21 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/include/asm/vdso/gettimeofday.h 
b/arch/powerpc/include/asm/vdso/gettimeofday.h
index 7a215cc5da77..3ecddd9c6302 100644
--- a/arch/powerpc/include/asm/vdso/gettimeofday.h
+++ b/arch/powerpc/include/asm/vdso/gettimeofday.h
@@ -102,22 +102,22 @@ int gettimeofday_fallback(struct __kernel_old_timeval 
*_tv, struct timezone *_tz
return do_syscall_2(__NR_gettimeofday, (unsigned long)_tv, (unsigned 
long)_tz);
 }
 
+#ifdef CONFIG_VDSO32
+
+#define BUILD_VDSO32   1
+
 static __always_inline
 int clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
 {
-   return do_syscall_2(__NR_clock_gettime, _clkid, (unsigned long)_ts);
+   return do_syscall_2(__NR_clock_gettime64, _clkid, (unsigned long)_ts);
 }
 
 static __always_inline
 int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
 {
-   return do_syscall_2(__NR_clock_getres, _clkid, (unsigned long)_ts);
+   return do_syscall_2(__NR_clock_getres_time64, _clkid, (unsigned 
long)_ts);
 }
 
-#ifdef CONFIG_VDSO32
-
-#define BUILD_VDSO32   1
-
 static __always_inline
 int clock_gettime32_fallback(clockid_t _clkid, struct old_timespec32 *_ts)
 {
@@ -129,6 +129,21 @@ int clock_getres32_fallback(clockid_t _clkid, struct 
old_timespec32 *_ts)
 {
return do_syscall_2(__NR_clock_getres, _clkid, (unsigned long)_ts);
 }
+
+#else
+
+static __always_inline
+int clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
+{
+   return do_syscall_2(__NR_clock_gettime, _clkid, (unsigned long)_ts);
+}
+
+static __always_inline
+int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
+{
+   return do_syscall_2(__NR_clock_getres, _clkid, (unsigned long)_ts);
+}
+
 #endif
 
 static __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
-- 
2.25.0



Re: [PATCH] powerpc/vdso: fix clock_gettime_fallback for vdso32

2021-01-11 Thread Christophe Leroy




Le 11/01/2021 à 16:18, Andreas Schwab a écrit :

The second argument of __kernel_clock_gettime64 points to a struct
__kernel_timespec, with 64-bit time_t, so use the clock_gettime64 syscall
in the fallback function for the 32-bit vdso.  Similarily,
clock_getres_fallback should use the clock_getres_time64 syscall, though
it isn't yet called from the 32-bit vdso.

Signed-off-by: Andreas Schwab 


Fixes: d0e3fc69d00d ("powerpc/vdso: Provide __kernel_clock_gettime64() on 
vdso32")


---
  arch/powerpc/include/asm/vdso/gettimeofday.h | 8 
  1 file changed, 8 insertions(+)

diff --git a/arch/powerpc/include/asm/vdso/gettimeofday.h 
b/arch/powerpc/include/asm/vdso/gettimeofday.h
index 81671aa365b3..a26c12df2c9a 100644
--- a/arch/powerpc/include/asm/vdso/gettimeofday.h
+++ b/arch/powerpc/include/asm/vdso/gettimeofday.h
@@ -106,13 +106,21 @@ int gettimeofday_fallback(struct __kernel_old_timeval 
*_tv, struct timezone *_tz
  static __always_inline
  int clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
  {
+#ifndef __powerpc64__


I think we should do like x86, create a second version of clock_gettime_fallback() inside the #ifdef 
CONFIG_VDSO32, and move that one in a matching (non existing yet) #else



+   return do_syscall_2(__NR_clock_gettime64, _clkid, (unsigned long)_ts);
+#else
return do_syscall_2(__NR_clock_gettime, _clkid, (unsigned long)_ts);
+#endif
  }
  
  static __always_inline

  int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
  {
+#ifndef __powerpc64__


Same.


+   return do_syscall_2(__NR_clock_getres_time64, _clkid, (unsigned 
long)_ts);
+#else
return do_syscall_2(__NR_clock_getres, _clkid, (unsigned long)_ts);
+#endif
  }
  
  #ifdef CONFIG_VDSO32




Christophe


[PATCH] powerpc/vdso: fix clock_gettime_fallback for vdso32

2021-01-11 Thread Andreas Schwab
The second argument of __kernel_clock_gettime64 points to a struct
__kernel_timespec, with 64-bit time_t, so use the clock_gettime64 syscall
in the fallback function for the 32-bit vdso.  Similarily,
clock_getres_fallback should use the clock_getres_time64 syscall, though
it isn't yet called from the 32-bit vdso.

Signed-off-by: Andreas Schwab 
---
 arch/powerpc/include/asm/vdso/gettimeofday.h | 8 
 1 file changed, 8 insertions(+)

diff --git a/arch/powerpc/include/asm/vdso/gettimeofday.h 
b/arch/powerpc/include/asm/vdso/gettimeofday.h
index 81671aa365b3..a26c12df2c9a 100644
--- a/arch/powerpc/include/asm/vdso/gettimeofday.h
+++ b/arch/powerpc/include/asm/vdso/gettimeofday.h
@@ -106,13 +106,21 @@ int gettimeofday_fallback(struct __kernel_old_timeval 
*_tv, struct timezone *_tz
 static __always_inline
 int clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
 {
+#ifndef __powerpc64__
+   return do_syscall_2(__NR_clock_gettime64, _clkid, (unsigned long)_ts);
+#else
return do_syscall_2(__NR_clock_gettime, _clkid, (unsigned long)_ts);
+#endif
 }
 
 static __always_inline
 int clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
 {
+#ifndef __powerpc64__
+   return do_syscall_2(__NR_clock_getres_time64, _clkid, (unsigned 
long)_ts);
+#else
return do_syscall_2(__NR_clock_getres, _clkid, (unsigned long)_ts);
+#endif
 }
 
 #ifdef CONFIG_VDSO32
-- 
2.30.0


-- 
Andreas Schwab, sch...@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510  2552 DF73 E780 A9DA AEC1
"And now for something completely different."


[PATCH v2] powerpc/perf: Adds support for programming of Thresholding in P10

2021-01-11 Thread Kajol Jain
Thresholding, a performance monitoring unit feature, can be
used to identify marked instructions which take more than
expected cycles between start event and end event.
Threshold compare (thresh_cmp) bits are programmed in MMCRA
register. In Power9, thresh_cmp bits were part of the
event code. But in case of P10, thresh_cmp are not part of
event code due to inclusion of MMCR3 bits.

Patch here adds an option to use attr.config1 variable
to be used to pass thresh_cmp value to be programmed in
MMCRA register. A new ppmu flag called PPMU_HAS_ATTR_CONFIG1
has been added and this flag is used to notify the use of
attr.config1 variable.

Patch has extended the parameter list of 'compute_mmcr',
to include power_pmu's 'flags' element and parameter list of
get_constraint to include attr.config1 value.

As stated by commit ef0e3b650f8d ("powerpc/perf: Fix Threshold
Event Counter Multiplier width for P10"), constraint bits for
thresh_cmp is also needed to be increased to 11 bits, which is
handled as part of this patch. We added bit number 53 as part
of constraint bits of thresh_cmp for power10 to make it an
11 bit field.

Updated layout for p10:

/*
 * Layout of constraint bits:
 *
 *60565248444036
32
 * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - 
- - |
 *   [   fab_match   ] [   thresh_cmp  ] [   thresh_ctl] [  
 ]
 *  |  |
 *   [  thresh_cmp bits for p10]   thresh_sel -*
 *
 *2824201612 8 4
 0
 * | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - - - | - - 
- - |
 *   [ ] |   [ ] |  [  sample ]   [ ]   [6] [5]   [4] [3]   [2] 
[1]
 *|  ||  |  |
 *  BHRB IFM -*  ||  |*radix_scope  |  Count of events for each 
PMC.
 *  EBB -*| |p1, p2, p3, p4, p5, p6.
 *  L1 I/D qualifier -* |
 * nc - number of counters -*
 *
 * The PMC fields P1..P6, and NC, are adder fields. As we accumulate constraints
 * we want the low bit of each field to be added to any existing value.
 *
 * Everything else is a value field.
 */

Result:
command#: cat /sys/devices/cpu/format/thresh_cmp
config1:0-17

ex. usage:

command#: perf record -I --weight -d  -e
 cpu/event=0x67340101EC,thresh_cmp=500/ ./ebizzy -S 2 -t 1 -s 4096
1826636 records/s
real  2.00 s
user  2.00 s
sys   0.00 s
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.038 MB perf.data (61 samples) ]

Signed-off-by: Kajol Jain 
---
 arch/powerpc/include/asm/perf_event_server.h |  5 +-
 arch/powerpc/perf/core-book3s.c  | 24 +--
 arch/powerpc/perf/isa207-common.c| 71 +---
 arch/powerpc/perf/isa207-common.h| 15 +++--
 arch/powerpc/perf/mpc7450-pmu.c  |  5 +-
 arch/powerpc/perf/power10-pmu.c  |  4 +-
 arch/powerpc/perf/power5+-pmu.c  |  5 +-
 arch/powerpc/perf/power5-pmu.c   |  5 +-
 arch/powerpc/perf/power6-pmu.c   |  5 +-
 arch/powerpc/perf/power7-pmu.c   |  5 +-
 arch/powerpc/perf/ppc970-pmu.c   |  5 +-
 11 files changed, 116 insertions(+), 33 deletions(-)

---
Changelog
v1 -> v2
- Add new function 'p10_thresh_cmp_val' to evaluate thresh_cmp
  value.
- Extended the parameter list of get_constraint function
  to include attr.config1 value.
- Added bit number 53 as part of constraint bits of thresh_cmp
  to make it a 11 bit field for power10.
- Updated PPMU_HAS_ATTR_CONFIG1 value to 0x0800
- Add new field 'events_config1' in struct cpu_hw_events and also
  update this field in all required functions accordingly.
---
diff --git a/arch/powerpc/include/asm/perf_event_server.h 
b/arch/powerpc/include/asm/perf_event_server.h
index 3b7baba01c92..00e7e671bb4b 100644
--- a/arch/powerpc/include/asm/perf_event_server.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -36,9 +36,9 @@ struct power_pmu {
unsigned long   test_adder;
int (*compute_mmcr)(u64 events[], int n_ev,
unsigned int hwc[], struct mmcr_regs *mmcr,
-   struct perf_event *pevents[]);
+   struct perf_event *pevents[], u32 flags);
int (*get_constraint)(u64 event_id, unsigned long *mskp,
-   unsigned long *valp);
+   unsigned long *valp, u64 event_config1);
int (*get_alternatives)(u64 event_id, unsigned int flags,
u64 alt[]);
void(*get_mem_data_src)(union perf_mem_data_src *dsrc,
@@ -83,6 +83,7 @@ struct power_pmu {
 #define PPMU_NO_SIAR   

Re: [PATCH v3 4/8] powerpc/signal64: Remove TM ifdefery in middle of if/else block

2021-01-11 Thread Christophe Leroy




Le 09/01/2021 à 04:25, Christopher M. Riedl a écrit :

Rework the messy ifdef breaking up the if-else for TM similar to
commit f1cf4f93de2f ("powerpc/signal32: Remove ifdefery in middle of if/else").

Unlike that commit for ppc32, the ifdef can't be removed entirely since
uc_transact in sigframe depends on CONFIG_PPC_TRANSACTIONAL_MEM.

Signed-off-by: Christopher M. Riedl 
---
  arch/powerpc/kernel/signal_64.c | 17 +++--
  1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/arch/powerpc/kernel/signal_64.c b/arch/powerpc/kernel/signal_64.c
index b211a8ea4f6e..dd3787f67a78 100644
--- a/arch/powerpc/kernel/signal_64.c
+++ b/arch/powerpc/kernel/signal_64.c
@@ -710,9 +710,7 @@ SYSCALL_DEFINE0(rt_sigreturn)
struct pt_regs *regs = current_pt_regs();
struct ucontext __user *uc = (struct ucontext __user *)regs->gpr[1];
sigset_t set;
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
unsigned long msr;
-#endif
  
  	/* Always make any pending restarted system calls return -EINTR */

current->restart_block.fn = do_no_restart_syscall;
@@ -762,10 +760,12 @@ SYSCALL_DEFINE0(rt_sigreturn)
 * restore_tm_sigcontexts.
 */
regs->msr &= ~MSR_TS_MASK;
+#endif
  
  	if (__get_user(msr, >uc_mcontext.gp_regs[PT_MSR]))

goto badframe;


This means you are doing that __get_user() even when msr is not used. That 
should be avoided.


if (MSR_TM_ACTIVE(msr)) {
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
/* We recheckpoint on return. */
struct ucontext __user *uc_transact;
  
@@ -778,9 +778,8 @@ SYSCALL_DEFINE0(rt_sigreturn)

if (restore_tm_sigcontexts(current, >uc_mcontext,
   _transact->uc_mcontext))
goto badframe;
-   } else
  #endif
-   {
+   } else {
/*
 * Fall through, for non-TM restore
 *
@@ -818,10 +817,8 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
unsigned long newsp = 0;
long err = 0;
struct pt_regs *regs = tsk->thread.regs;
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
/* Save the thread's msr before get_tm_stackpointer() changes it */
-   unsigned long msr = regs->msr;
-#endif
+   unsigned long msr __maybe_unused = regs->msr;


I don't thing __maybe_unused() is the right solution.

I think MSR_TM_ACTIVE() should be fixed instead, either by changing it into a static inline 
function, or doing something similar to 
https://github.com/linuxppc/linux/commit/05a4ab823983d9136a460b7b5e0d49ee709a6f86


  
  	frame = get_sigframe(ksig, tsk, sizeof(*frame), 0);

if (!access_ok(frame, sizeof(*frame)))
@@ -836,8 +833,9 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
/* Create the ucontext.  */
err |= __put_user(0, >uc.uc_flags);
err |= __save_altstack(>uc.uc_stack, regs->gpr[1]);
-#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
+
if (MSR_TM_ACTIVE(msr)) {
+#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
/* The ucontext_t passed to userland points to the second
 * ucontext_t (for transactional state) with its uc_link ptr.
 */
@@ -847,9 +845,8 @@ int handle_rt_signal64(struct ksignal *ksig, sigset_t *set,
tsk, ksig->sig, NULL,
(unsigned 
long)ksig->ka.sa.sa_handler,
msr);
-   } else
  #endif
-   {
+   } else {
err |= __put_user(0, >uc.uc_link);
prepare_setup_sigcontext(tsk, 1);
err |= setup_sigcontext(>uc.uc_mcontext, tsk, ksig->sig,



Christophe


Re: [PATCH v3 1/8] powerpc/uaccess: Add unsafe_copy_from_user

2021-01-11 Thread Christophe Leroy




Le 09/01/2021 à 04:25, Christopher M. Riedl a écrit :

Implement raw_copy_from_user_allowed() which assumes that userspace read
access is open. Use this new function to implement raw_copy_from_user().
Finally, wrap the new function to follow the usual "unsafe_" convention
of taking a label argument.


I think there is no point implementing raw_copy_from_user_allowed(), see 
https://github.com/linuxppc/linux/commit/4b842e4e25b1 and 
https://patchwork.ozlabs.org/project/linuxppc-dev/patch/8c74fc9ce8131cabb10b3e95dc0e430f396ee83e.1610369143.git.christophe.le...@csgroup.eu/


You should simply do:

#define unsafe_copy_from_user(d, s, l, e) \
unsafe_op_wrap(__copy_tofrom_user((__force void __user *)d, s, 
l), e)


Christophe



The new raw_copy_from_user_allowed() calls non-inline __copy_tofrom_user()
internally. This is still safe to call inside user access blocks formed
with user_*_access_begin()/user_*_access_end() since asm functions are not
instrumented for tracing.

Signed-off-by: Christopher M. Riedl 
---
  arch/powerpc/include/asm/uaccess.h | 28 +++-
  1 file changed, 19 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/include/asm/uaccess.h 
b/arch/powerpc/include/asm/uaccess.h
index 501c9a79038c..698f3a6d6ae5 100644
--- a/arch/powerpc/include/asm/uaccess.h
+++ b/arch/powerpc/include/asm/uaccess.h
@@ -403,38 +403,45 @@ raw_copy_in_user(void __user *to, const void __user 
*from, unsigned long n)
  }
  #endif /* __powerpc64__ */
  
-static inline unsigned long raw_copy_from_user(void *to,

-   const void __user *from, unsigned long n)
+static inline unsigned long
+raw_copy_from_user_allowed(void *to, const void __user *from, unsigned long n)
  {
-   unsigned long ret;
if (__builtin_constant_p(n) && (n <= 8)) {
-   ret = 1;
+   unsigned long ret = 1;
  
  		switch (n) {

case 1:
barrier_nospec();
-   __get_user_size(*(u8 *)to, from, 1, ret);
+   __get_user_size_allowed(*(u8 *)to, from, 1, ret);
break;
case 2:
barrier_nospec();
-   __get_user_size(*(u16 *)to, from, 2, ret);
+   __get_user_size_allowed(*(u16 *)to, from, 2, ret);
break;
case 4:
barrier_nospec();
-   __get_user_size(*(u32 *)to, from, 4, ret);
+   __get_user_size_allowed(*(u32 *)to, from, 4, ret);
break;
case 8:
barrier_nospec();
-   __get_user_size(*(u64 *)to, from, 8, ret);
+   __get_user_size_allowed(*(u64 *)to, from, 8, ret);
break;
}
if (ret == 0)
return 0;
}
  
+	return __copy_tofrom_user((__force void __user *)to, from, n);

+}
+
+static inline unsigned long
+raw_copy_from_user(void *to, const void __user *from, unsigned long n)
+{
+   unsigned long ret;
+
barrier_nospec();
allow_read_from_user(from, n);
-   ret = __copy_tofrom_user((__force void __user *)to, from, n);
+   ret = raw_copy_from_user_allowed(to, from, n);
prevent_read_from_user(from, n);
return ret;
  }
@@ -542,6 +549,9 @@ user_write_access_begin(const void __user *ptr, size_t len)
  #define unsafe_get_user(x, p, e) unsafe_op_wrap(__get_user_allowed(x, p), e)
  #define unsafe_put_user(x, p, e) __put_user_goto(x, p, e)
  
+#define unsafe_copy_from_user(d, s, l, e) \

+   unsafe_op_wrap(raw_copy_from_user_allowed(d, s, l), e)
+
  #define unsafe_copy_to_user(d, s, l, e) \
  do {  \
u8 __user *_dst = (u8 __user *)(d); \



[PATCH 3/3] powerpc: Merge raw_copy_to_user_allowed() into raw_copy_to_user()

2021-01-11 Thread Christophe Leroy
Since commit 17bc43367fc2 ("powerpc/uaccess: Implement
unsafe_copy_to_user() as a simple loop"), raw_copy_to_user_allowed()
is only used by raw_copy_to_user().

Merge raw_copy_to_user_allowed() into raw_copy_to_user().

Signed-off-by: Christophe Leroy 
---
 arch/powerpc/include/asm/uaccess.h | 8 +---
 1 file changed, 1 insertion(+), 7 deletions(-)

diff --git a/arch/powerpc/include/asm/uaccess.h 
b/arch/powerpc/include/asm/uaccess.h
index f1df444bfb04..ff550d5dbf38 100644
--- a/arch/powerpc/include/asm/uaccess.h
+++ b/arch/powerpc/include/asm/uaccess.h
@@ -411,19 +411,13 @@ static inline unsigned long raw_copy_from_user(void *to,
return ret;
 }
 
-static inline unsigned long
-raw_copy_to_user_allowed(void __user *to, const void *from, unsigned long n)
-{
-   return __copy_tofrom_user(to, (__force const void __user *)from, n);
-}
-
 static inline unsigned long
 raw_copy_to_user(void __user *to, const void *from, unsigned long n)
 {
unsigned long ret;
 
allow_write_to_user(to, n);
-   ret = raw_copy_to_user_allowed(to, from, n);
+   ret = __copy_tofrom_user(to, (__force const void __user *)from, n);
prevent_write_to_user(to, n);
return ret;
 }
-- 
2.25.0



[PATCH 2/3] powerpc: Merge __put_user_size_allowed() into __put_user_size()

2021-01-11 Thread Christophe Leroy
__put_user_size_allowed() is only called from __put_user_size() now.

Merge them together.

Signed-off-by: Christophe Leroy 
---
 arch/powerpc/include/asm/uaccess.h | 10 +++---
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/arch/powerpc/include/asm/uaccess.h 
b/arch/powerpc/include/asm/uaccess.h
index 6e97616e03e8..f1df444bfb04 100644
--- a/arch/powerpc/include/asm/uaccess.h
+++ b/arch/powerpc/include/asm/uaccess.h
@@ -110,22 +110,18 @@ static inline bool __access_ok(unsigned long addr, 
unsigned long size)
 
 extern long __put_user_bad(void);
 
-#define __put_user_size_allowed(x, ptr, size, retval)  \
+#define __put_user_size(x, ptr, size, retval)  \
 do {   \
__label__ __pu_failed;  \
\
retval = 0; \
+   allow_write_to_user(ptr, size); \
__put_user_size_goto(x, ptr, size, __pu_failed);\
+   prevent_write_to_user(ptr, size);   \
break;  \
\
 __pu_failed:   \
retval = -EFAULT;   \
-} while (0)
-
-#define __put_user_size(x, ptr, size, retval)  \
-do {   \
-   allow_write_to_user(ptr, size); \
-   __put_user_size_allowed(x, ptr, size, retval);  \
prevent_write_to_user(ptr, size);   \
 } while (0)
 
-- 
2.25.0



[PATCH 1/3] powerpc: get rid of small constant size cases in raw_copy_{to,from}_user()

2021-01-11 Thread Christophe Leroy
Copied from commit 4b842e4e25b1 ("x86: get rid of small
constant size cases in raw_copy_{to,from}_user()")

Very few call sites where that would be triggered remain, and none
of those is anywhere near hot enough to bother.

Signed-off-by: Christophe Leroy 
---
 arch/powerpc/include/asm/uaccess.h | 45 --
 1 file changed, 45 deletions(-)

diff --git a/arch/powerpc/include/asm/uaccess.h 
b/arch/powerpc/include/asm/uaccess.h
index 501c9a79038c..6e97616e03e8 100644
--- a/arch/powerpc/include/asm/uaccess.h
+++ b/arch/powerpc/include/asm/uaccess.h
@@ -407,30 +407,6 @@ static inline unsigned long raw_copy_from_user(void *to,
const void __user *from, unsigned long n)
 {
unsigned long ret;
-   if (__builtin_constant_p(n) && (n <= 8)) {
-   ret = 1;
-
-   switch (n) {
-   case 1:
-   barrier_nospec();
-   __get_user_size(*(u8 *)to, from, 1, ret);
-   break;
-   case 2:
-   barrier_nospec();
-   __get_user_size(*(u16 *)to, from, 2, ret);
-   break;
-   case 4:
-   barrier_nospec();
-   __get_user_size(*(u32 *)to, from, 4, ret);
-   break;
-   case 8:
-   barrier_nospec();
-   __get_user_size(*(u64 *)to, from, 8, ret);
-   break;
-   }
-   if (ret == 0)
-   return 0;
-   }
 
barrier_nospec();
allow_read_from_user(from, n);
@@ -442,27 +418,6 @@ static inline unsigned long raw_copy_from_user(void *to,
 static inline unsigned long
 raw_copy_to_user_allowed(void __user *to, const void *from, unsigned long n)
 {
-   if (__builtin_constant_p(n) && (n <= 8)) {
-   unsigned long ret = 1;
-
-   switch (n) {
-   case 1:
-   __put_user_size_allowed(*(u8 *)from, (u8 __user *)to, 
1, ret);
-   break;
-   case 2:
-   __put_user_size_allowed(*(u16 *)from, (u16 __user *)to, 
2, ret);
-   break;
-   case 4:
-   __put_user_size_allowed(*(u32 *)from, (u32 __user *)to, 
4, ret);
-   break;
-   case 8:
-   __put_user_size_allowed(*(u64 *)from, (u64 __user *)to, 
8, ret);
-   break;
-   }
-   if (ret == 0)
-   return 0;
-   }
-
return __copy_tofrom_user(to, (__force const void __user *)from, n);
 }
 
-- 
2.25.0



Re: [patch V3 13/37] mips/mm/highmem: Switch to generic kmap atomic

2021-01-11 Thread Sebastian Andrzej Siewior
On 2021-01-09 01:33:52 [+0100], Thomas Bogendoerfer wrote:
> On Sat, Jan 09, 2021 at 12:58:05AM +0100, Thomas Bogendoerfer wrote:
> > On Fri, Jan 08, 2021 at 08:20:43PM +, Paul Cercueil wrote:
> > > Hi Thomas,
> > > 
> > > 5.11 does not boot anymore on Ingenic SoCs, I bisected it to this commit.
> > > 
> > > Any idea what could be happening?
> > 
> > not yet, kernel crash log of a Malta QEMU is below.
> 
> update:
> 
> This dirty hack lets the Malta QEMU boot again:
> 
> diff --git a/mm/highmem.c b/mm/highmem.c
> index c3a9ea7875ef..190cdda1149d 100644
> --- a/mm/highmem.c
> +++ b/mm/highmem.c
> @@ -515,7 +515,7 @@ void *__kmap_local_pfn_prot(unsigned long pfn, pgprot_t 
> prot)
>   vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
>   BUG_ON(!pte_none(*(kmap_pte - idx)));
>   pteval = pfn_pte(pfn, prot);
> - set_pte_at(_mm, vaddr, kmap_pte - idx, pteval);
> + set_pte(kmap_pte - idx, pteval);
>   arch_kmap_local_post_map(vaddr, pteval);
>   current->kmap_ctrl.pteval[kmap_local_idx()] = pteval;
>   preempt_enable();
> 
> set_pte_at() tries to update cache and could do an kmap_atomic() there.
So the old implementation used set_pte() while the new one uses
set_pte_at().

> Not sure, if this is allowed at this point.
The problem is the recursion
  kmap_atomic() -> __update_cache() -> kmap_atomic()

and kmap_local_idx_push() runs out if index space before stack space.

I'm not sure if the __update_cache() worked for highmem. It has been
added for that in commit
   f4281bba81810 ("MIPS: Handle highmem pages in __update_cache")

but it assumes that the address returned by kmap_atomic() is the same or
related enough for flush_data_cache_page() to work.

> Thomas.
> 

Sebastian


[PATCH 1/3] powerpc: retire sbc8548 board support

2021-01-11 Thread Paul Gortmaker
The support was for this was mainlined 13 years ago, in v2.6.25
[0e0fffe88767] just around the ppc --> powerpc migration.

I believe the board was introduced a year or two before that, so it
is roughly a 15 year old platform - with the CPU speed and memory size
that was typical for that era.

I haven't had one of these boards for several years, and availability
was discontinued several years before that.

Given that, there is no point in adding a burden to testing coverage
that builds all possible defconfigs, so it makes sense to remove it.

Of course it will remain in the git history forever, for anyone who
happens to find a functional board and wants to tinker with it.

Cc: Scott Wood 
Cc: Michael Ellerman 
Cc: Benjamin Herrenschmidt 
Cc: Paul Mackerras 
Signed-off-by: Paul Gortmaker 
---
 arch/powerpc/boot/Makefile  |   1 -
 arch/powerpc/boot/dts/sbc8548-altflash.dts  | 111 
 arch/powerpc/boot/dts/sbc8548-post.dtsi | 289 
 arch/powerpc/boot/dts/sbc8548-pre.dtsi  |  48 
 arch/powerpc/boot/dts/sbc8548.dts   | 106 ---
 arch/powerpc/boot/wrapper   |   2 +-
 arch/powerpc/configs/85xx/sbc8548_defconfig |  50 
 arch/powerpc/configs/mpc85xx_base.config|   1 -
 arch/powerpc/platforms/85xx/Kconfig |   6 -
 arch/powerpc/platforms/85xx/Makefile|   1 -
 arch/powerpc/platforms/85xx/sbc8548.c   | 134 -
 11 files changed, 1 insertion(+), 748 deletions(-)
 delete mode 100644 arch/powerpc/boot/dts/sbc8548-altflash.dts
 delete mode 100644 arch/powerpc/boot/dts/sbc8548-post.dtsi
 delete mode 100644 arch/powerpc/boot/dts/sbc8548-pre.dtsi
 delete mode 100644 arch/powerpc/boot/dts/sbc8548.dts
 delete mode 100644 arch/powerpc/configs/85xx/sbc8548_defconfig
 delete mode 100644 arch/powerpc/platforms/85xx/sbc8548.c

diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 2b8da923ceca..8edb85b9ae11 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -339,7 +339,6 @@ image-$(CONFIG_TQM8541) += 
cuImage.tqm8541
 image-$(CONFIG_TQM8548)+= cuImage.tqm8548
 image-$(CONFIG_TQM8555)+= cuImage.tqm8555
 image-$(CONFIG_TQM8560)+= cuImage.tqm8560
-image-$(CONFIG_SBC8548)+= cuImage.sbc8548
 image-$(CONFIG_KSI8560)+= cuImage.ksi8560
 
 # Board ports in arch/powerpc/platform/86xx/Kconfig
diff --git a/arch/powerpc/boot/dts/sbc8548-altflash.dts 
b/arch/powerpc/boot/dts/sbc8548-altflash.dts
deleted file mode 100644
index bb7a1e712bb7..
--- a/arch/powerpc/boot/dts/sbc8548-altflash.dts
+++ /dev/null
@@ -1,111 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * SBC8548 Device Tree Source
- *
- * Configured for booting off the alternate (64MB SODIMM) flash.
- * Requires switching JP12 jumpers and changing SW2.8 setting.
- *
- * Copyright 2013 Wind River Systems Inc.
- *
- * Paul Gortmaker (see MAINTAINERS for contact information)
- */
-
-
-/dts-v1/;
-
-/include/ "sbc8548-pre.dtsi"
-
-/{
-   localbus@e000 {
-   #address-cells = <2>;
-   #size-cells = <1>;
-   compatible = "simple-bus";
-   reg = <0xe000 0x5000>;
-   interrupt-parent = <>;
-
-   ranges = <0x0 0x0 0xfc00 0x0400 /*64MB Flash*/
- 0x3 0x0 0xf000 0x0400 /*64MB SDRAM*/
- 0x4 0x0 0xf400 0x0400 /*64MB SDRAM*/
- 0x5 0x0 0xf800 0x00b1 /* EPLD */
- 0x6 0x0 0xef80 0x0080>;   /*8MB Flash*/
-
-   flash@0,0 {
-   #address-cells = <1>;
-   #size-cells = <1>;
-   reg = <0x0 0x0 0x0400>;
-   compatible = "intel,JS28F128", "cfi-flash";
-   bank-width = <4>;
-   device-width = <1>;
-   partition@0 {
-   label = "space";
-   /* FC00 -> FFEF */
-   reg = <0x 0x03f0>;
-   };
-   partition@3f0 {
-   label = "bootloader";
-   /* FFF0 ->  */
-   reg = <0x03f0 0x0010>;
-   read-only;
-   };
-};
-
-
-   epld@5,0 {
-   compatible = "wrs,epld-localbus";
-   #address-cells = <2>;
-   #size-cells = <1>;
-   reg = <0x5 0x0 0x00b1>;
-   ranges = <
-   0x0 0x0 0x5 0x00 0x1fff /* LED */
-   0x1 0x0 0x5 0x10 

[PATCH 2/3] powerpc: retire sbc8641d board support

2021-01-11 Thread Paul Gortmaker
The support was for this was added to mainline over 12 years ago, in
v2.6.26 [4e8aae89a35d] just around the ppc --> powerpc migration.

I believe the board was introduced shortly after the sbc8548 board,
making it roughly a 14 year old platform - with the CPU speed and
memory size typical for that era.

I haven't had one of these boards for several years, and availability
was discontinued several years before that.

Given that, there is no point in adding a burden to testing coverage
that builds all possible defconfigs, so it makes sense to remove it.

Of course it will remain in the git history forever, for anyone who
happens to find a functional board and wants to tinker with it.

Cc: Michael Ellerman 
Cc: Benjamin Herrenschmidt 
Cc: Paul Mackerras 
Signed-off-by: Paul Gortmaker 
---
 arch/powerpc/boot/dts/fsl/sbc8641d.dts   | 176 ---
 arch/powerpc/configs/mpc86xx_base.config |   1 -
 arch/powerpc/configs/ppc6xx_defconfig|   1 -
 arch/powerpc/platforms/86xx/Kconfig  |   8 +-
 arch/powerpc/platforms/86xx/Makefile |   1 -
 arch/powerpc/platforms/86xx/sbc8641d.c   |  87 ---
 6 files changed, 1 insertion(+), 273 deletions(-)
 delete mode 100644 arch/powerpc/boot/dts/fsl/sbc8641d.dts
 delete mode 100644 arch/powerpc/platforms/86xx/sbc8641d.c

diff --git a/arch/powerpc/boot/dts/fsl/sbc8641d.dts 
b/arch/powerpc/boot/dts/fsl/sbc8641d.dts
deleted file mode 100644
index 3dca10acc161..
--- a/arch/powerpc/boot/dts/fsl/sbc8641d.dts
+++ /dev/null
@@ -1,176 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * SBC8641D Device Tree Source
- *
- * Copyright 2008 Wind River Systems Inc.
- *
- * Paul Gortmaker (see MAINTAINERS for contact information)
- *
- * Based largely on the mpc8641_hpcn.dts by Freescale Semiconductor Inc.
- */
-
-/include/ "mpc8641si-pre.dtsi"
-
-/ {
-   model = "SBC8641D";
-   compatible = "wind,sbc8641";
-
-   memory {
-   device_type = "memory";
-   reg = <0x 0x2000>;  // 512M at 0x0
-   };
-
-   lbc: localbus@f8005000 {
-   reg = <0xf8005000 0x1000>;
-
-   ranges = <0 0 0xff00 0x0100 // 16MB Boot flash
- 1 0 0xf000 0x0001 // 64KB EEPROM
- 2 0 0xf100 0x0010 // EPLD (1MB)
- 3 0 0xe000 0x0400 // 64MB LB SDRAM (CS3)
- 4 0 0xe400 0x0400 // 64MB LB SDRAM (CS4)
- 6 0 0xf400 0x0010 // LCD display (1MB)
- 7 0 0xe800 0x0400>;   // 64MB OneNAND
-
-   flash@0,0 {
-   compatible = "cfi-flash";
-   reg = <0 0 0x0100>;
-   bank-width = <2>;
-   device-width = <2>;
-   #address-cells = <1>;
-   #size-cells = <1>;
-   partition@0 {
-   label = "dtb";
-   reg = <0x 0x0010>;
-   read-only;
-   };
-   partition@30 {
-   label = "kernel";
-   reg = <0x0010 0x0040>;
-   read-only;
-   };
-   partition@40 {
-   label = "fs";
-   reg = <0x0050 0x00a0>;
-   };
-   partition@70 {
-   label = "firmware";
-   reg = <0x00f0 0x0010>;
-   read-only;
-   };
-   };
-
-   epld@2,0 {
-   compatible = "wrs,epld-localbus";
-   #address-cells = <2>;
-   #size-cells = <1>;
-   reg = <2 0 0x10>;
-   ranges = <0 0 5 0 1 // User switches
- 1 0 5 1 1 // Board ID/Rev
- 3 0 5 3 1>;   // LEDs
-   };
-   };
-
-   soc: soc@f800 {
-   ranges = <0x 0xf800 0x0010>;
-
-   enet0: ethernet@24000 {
-   tbi-handle = <>;
-   phy-handle = <>;
-   phy-connection-type = "rgmii-id";
-   };
-
-   mdio@24520 {
-   phy0: ethernet-phy@1f {
-   reg = <0x1f>;
-   };
-   phy1: ethernet-phy@0 {
-   reg = <0>;
-   };
-   phy2: ethernet-phy@1 {
-   reg = <1>;
-   };
-   phy3: ethernet-phy@2 {
-   

[PATCH 3/3] MAINTAINERS: update for Paul Gortmaker

2021-01-11 Thread Paul Gortmaker
Signed-off-by: Paul Gortmaker 
---
 MAINTAINERS | 1 -
 1 file changed, 1 deletion(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index cc1e6a5ee6e6..c5f5cdb24674 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6529,7 +6529,6 @@ F:Documentation/admin-guide/media/em28xx*
 F: drivers/media/usb/em28xx/
 
 EMBEDDED LINUX
-M: Paul Gortmaker 
 M: Matt Mackall 
 M: David Woodhouse 
 L: linux-embed...@vger.kernel.org
-- 
2.17.1



[PATCH 0/3] Retire remaining WindRiver embedded SBC BSPs

2021-01-11 Thread Paul Gortmaker
In v2.6.27 (2008, 917f0af9e5a9) the sbc8260 support was implicitly
retired by not being carried forward through the ppc --> powerpc
device tree transition.

Then, in v3.6 (2012, b048b4e17cbb) we retired the support for the
sbc8560 boards.

Next, in v4.18 (2017, 3bc6cf5a86e5) we retired the support for the
2006 vintage sbc834x boards.

The sbc8548 and sbc8641d boards were maybe 1-2 years newer than the
sbc834x boards, but it is also 3+ years later, so it makes sense to
now retire them as well - which is what is done here.

These two remaining WR boards were based on the Freescale MPC8548-CDS
and the MPC8641D-HPCN reference board implementations.  Having had the
chance to use these and many other Fsl ref boards, I know this:  The
Freescale reference boards were typically produced in limited quantity
and primarily available to BSP developers and hardware designers, and
not likely to have found a 2nd life with hobbyists and/or collectors.

It was good to have that BSP code subjected to mainline review and
hence also widely available back in the day. But given the above, we
should probably also be giving serious consideration to retiring
additional similar age/type reference board platforms as well.

I've always felt it is important for us to be proactive in retiring
old code, since it has a genuine non-zero carrying cost, as described
in the 930d52c012b8 merge log.  But for the here and now, we just
clean up the remaining BSP code that I had added for SBC platforms.

Paul.
-- 

Cc: Benjamin Herrenschmidt 
Cc: Michael Ellerman 
Cc: Paul Mackerras 
Cc: Scott Wood 

The following changes since commit 7c53f6b671f4aba70ff15e1b05148b10d58c2837:

  Linux 5.11-rc3 (2021-01-10 14:34:50 -0800)

are available in the Git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/paulg/linux.git wr_sbc-delete

for you to fetch changes up to 1dfb28199572e3f6517cada41f6a150551749da1:

  MAINTAINERS: update for Paul Gortmaker (2021-01-11 00:06:01 -0500)


Paul Gortmaker (3):
  powerpc: retire sbc8548 board support
  powerpc: retire sbc8641d board support
  MAINTAINERS: update for Paul Gortmaker

 MAINTAINERS |   1 -
 arch/powerpc/boot/Makefile  |   1 -
 arch/powerpc/boot/dts/fsl/sbc8641d.dts  | 176 -
 arch/powerpc/boot/dts/sbc8548-altflash.dts  | 111 ---
 arch/powerpc/boot/dts/sbc8548-post.dtsi | 289 
 arch/powerpc/boot/dts/sbc8548-pre.dtsi  |  48 -
 arch/powerpc/boot/dts/sbc8548.dts   | 106 --
 arch/powerpc/boot/wrapper   |   2 +-
 arch/powerpc/configs/85xx/sbc8548_defconfig |  50 -
 arch/powerpc/configs/mpc85xx_base.config|   1 -
 arch/powerpc/configs/mpc86xx_base.config|   1 -
 arch/powerpc/configs/ppc6xx_defconfig   |   1 -
 arch/powerpc/platforms/85xx/Kconfig |   6 -
 arch/powerpc/platforms/85xx/Makefile|   1 -
 arch/powerpc/platforms/85xx/sbc8548.c   | 134 -
 arch/powerpc/platforms/86xx/Kconfig |   8 +-
 arch/powerpc/platforms/86xx/Makefile|   1 -
 arch/powerpc/platforms/86xx/sbc8641d.c  |  87 -
 18 files changed, 2 insertions(+), 1022 deletions(-)
 delete mode 100644 arch/powerpc/boot/dts/fsl/sbc8641d.dts
 delete mode 100644 arch/powerpc/boot/dts/sbc8548-altflash.dts
 delete mode 100644 arch/powerpc/boot/dts/sbc8548-post.dtsi
 delete mode 100644 arch/powerpc/boot/dts/sbc8548-pre.dtsi
 delete mode 100644 arch/powerpc/boot/dts/sbc8548.dts
 delete mode 100644 arch/powerpc/configs/85xx/sbc8548_defconfig
 delete mode 100644 arch/powerpc/platforms/85xx/sbc8548.c
 delete mode 100644 arch/powerpc/platforms/86xx/sbc8641d.c