Re: [PATCH 1/9] scsi: ufs: Allowing power mode change

2018-02-22 Thread Asutosh Das (asd)

On 2/23/2018 10:40 AM, Kyuho Choi wrote:

Hi Asutosh,

I've simple question in below.

On 2/21/18, Asutosh Das  wrote:

From: Yaniv Gardi 

Due to M-PHY issues, moving from HS to any other mode or gear or
even Hibern8 causes some un-predicted behavior of the device.
This patch fixes this issues.

Signed-off-by: Yaniv Gardi 
Signed-off-by: Subhash Jadavani 
Signed-off-by: Can Guo 
Signed-off-by: Asutosh Das 
---
  drivers/scsi/ufs/ufshcd.c | 6 +-
  1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 011c336..d74d529 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -4167,9 +4167,13 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
goto out;
} while (ret && retries--);

-   if (ret)
+   if (ret) {
/* failed to get the link up... retire */
goto out;
+   } else {
+   ufshcd_dme_set(hba, UIC_ARG_MIB(TX_LCC_ENABLE), 0);
+   ufshcd_dme_set(hba, UIC_ARG_MIB(TX_LCC_ENABLE), 1);
+   }



Every ufs host has same issue and affected?.


if (link_startup_again) {
link_startup_again = false;
--
Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center,
Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux
Foundation Collaborative Project.



Hi Choi
Thanks for the review.

No - I can't say if every host has the same issue. However, I get your 
point. It could be done with a quirk.


I'll fix this in v2 after collating all the comments from the rest of 
the patches.


-asd

--
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a 
Linux Foundation Collaborative Project


Re: hpsa crashes on boot in 4.16-rc2-00062

2018-02-22 Thread Meelis Roos
> This happens on a HP DL360 G6 with Smart Array 410i.
> 
> Will try to bisect.
> 
> IO completion timeout could be because of some IRQ toubles?

Reverting 84676c1f21e8ff54befe985f4f14dc1edc10046b fixes it for me (as 
suggested by Laurence Oberman).

-- 
Meelis Roos (mr...@linux.ee)


Re: [PATCH 1/9] scsi: ufs: Allowing power mode change

2018-02-22 Thread Kyuho Choi
Hi Asutosh,

I've simple question in below.

On 2/21/18, Asutosh Das  wrote:
> From: Yaniv Gardi 
>
> Due to M-PHY issues, moving from HS to any other mode or gear or
> even Hibern8 causes some un-predicted behavior of the device.
> This patch fixes this issues.
>
> Signed-off-by: Yaniv Gardi 
> Signed-off-by: Subhash Jadavani 
> Signed-off-by: Can Guo 
> Signed-off-by: Asutosh Das 
> ---
>  drivers/scsi/ufs/ufshcd.c | 6 +-
>  1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
> index 011c336..d74d529 100644
> --- a/drivers/scsi/ufs/ufshcd.c
> +++ b/drivers/scsi/ufs/ufshcd.c
> @@ -4167,9 +4167,13 @@ static int ufshcd_link_startup(struct ufs_hba *hba)
>   goto out;
>   } while (ret && retries--);
>
> - if (ret)
> + if (ret) {
>   /* failed to get the link up... retire */
>   goto out;
> + } else {
> + ufshcd_dme_set(hba, UIC_ARG_MIB(TX_LCC_ENABLE), 0);
> + ufshcd_dme_set(hba, UIC_ARG_MIB(TX_LCC_ENABLE), 1);
> + }
>

Every ufs host has same issue and affected?.

>   if (link_startup_again) {
>   link_startup_again = false;
> --
> Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center,
> Inc.
> Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux
> Foundation Collaborative Project.
>
>


Re: [PATCH 04/38] cxlflash: Introduce OpenCXL backend

2018-02-22 Thread Andrew Donnellan

On 23/02/18 09:22, Uma Krishnan wrote:

Add initial infrastructure to support a new cxlflash transport, OpenCXL.

Claim a dependency on OpenCXL (OCXL) and add a new file, ocxl_hw.c, which
will host the backend routines that are specific to OpenCXL.

Signed-off-by: Uma Krishnan 


Is it necessary to depend on OCXL in all cases? IMHO it should be 
possible to build a cxl-only version without ocxl, though I don't feel 
very strongly on this.


--
Andrew Donnellan  OzLabs, ADL Canberra
andrew.donnel...@au1.ibm.com  IBM Australia Limited



Re: [PATCH 00/38] cxlflash: OpenCXL transport support

2018-02-22 Thread Andrew Donnellan

On 23/02/18 09:20, Uma Krishnan wrote:

This patch series adds OpenCXL support to the cxlflash driver. With
this support, new devices using the OpenCXL transport will be supported
by the cxlflash driver along with the existing CXL devices. An effort is
made to keep this transport specific function independent of the existing
core driver that communicates with the AFU.


It's "OpenCAPI" for the standard, and "ocxl" for the driver - I'd rather 
not add "OpenCXL" to our already somewhat confusing proliferation of 
names :)


I'll try to review as much of the ocxl-specific stuff as I can get to, 
though I'm a bit busy with the OpenCAPI skiboot work and reviewing the 
libocxl userspace library at the moment.



Andrew

--
Andrew Donnellan  OzLabs, ADL Canberra
andrew.donnel...@au1.ibm.com  IBM Australia Limited



Re: [GIT PULL] SCSI fixes for 4.16-rc2

2018-02-22 Thread James Bottomley
On Thu, 2018-02-22 at 16:37 -0800, Linus Torvalds wrote:
> On Thu, Feb 22, 2018 at 11:28 AM, James Bottomley
>  wrote:
> > 
> > 
> > git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git scsi-
> > fixes
> 
> When I pull that, I get something completely different from what you
> claim I should get. Much bigger, and a lot more commits.
> 
> Hmm?
> 
> Dropped.

OK, I see the problem, but I don't currently have an explanation for
how it happened.  The scsi-fixes tag somehow became attached to a push
of the misc tree for the next merge window instead of the fixes branch.

I've reset it to where it should be

commit 1bc5ad3a6acdcf56f83272f2de1cd2389ea9e9e2
Author: Manish Rangankar 
Date:   Sun Feb 11 22:48:41 2018 -0800

scsi: qla4xxx: skip error recovery in case of register disconnect.

So it should all be correct if you re-pull.

I suppose it's good that the checks and balances of changelog +
diffstat caught this; I'll poke about in my current preparation scripts
to see if I can find out what went wrong.

James



Re: [PATCH 5/9] scsi: ufs: add reference counting for scsi block requests

2018-02-22 Thread Asutosh Das (asd)

On 2/21/2018 6:48 PM, Stanislav Nijnikov wrote:




-Original Message-
From: linux-scsi-ow...@vger.kernel.org [mailto:linux-scsi-
ow...@vger.kernel.org] On Behalf Of Asutosh Das
Sent: Wednesday, February 21, 2018 6:57 AM
To: subha...@codeaurora.org; c...@codeaurora.org;
vivek.gau...@codeaurora.org; rna...@codeaurora.org;
vinholika...@gmail.com; j...@linux.vnet.ibm.com;
martin.peter...@oracle.com
Cc: linux-scsi@vger.kernel.org; Asutosh Das ;
open list 
Subject: [PATCH 5/9] scsi: ufs: add reference counting for scsi block requests

From: Subhash Jadavani 

Currently we call the scsi_block_requests()/scsi_unblock_requests()
whenever we want to block/unblock scsi requests but as there is no
reference counting, nesting of these calls could leave us in undesired state
sometime. Consider following call flow sequence:
1. func1() calls scsi_block_requests() but calls func2() before
calling scsi_unblock_requests()
2. func2() calls scsi_block_requests()
3. func2() calls scsi_unblock_requests() 4. func1() calls
scsi_unblock_requests()

As there is no reference counting, we will have scsi requests unblocked after
#3 instead of it to be unblocked only after #4. Though we may not have
failures seen with this, we might run into some failures in future.
Better solution would be to fix this by adding reference counting.

Signed-off-by: Subhash Jadavani 
Signed-off-by: Can Guo 
Signed-off-by: Asutosh Das 
---
  drivers/scsi/ufs/ufshcd.c | 44
+---
  drivers/scsi/ufs/ufshcd.h |  5 +
  2 files changed, 42 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index
7a4df95..987b81b 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -264,6 +264,36 @@ static inline void ufshcd_disable_irq(struct ufs_hba
*hba)
}
  }

+void ufshcd_scsi_unblock_requests(struct ufs_hba *hba) {
+   unsigned long flags;
+   bool unblock = false;
+
+   spin_lock_irqsave(hba->host->host_lock, flags);
+   hba->scsi_block_reqs_cnt--;
+   unblock = !hba->scsi_block_reqs_cnt;
+   spin_unlock_irqrestore(hba->host->host_lock, flags);
+   if (unblock)
+   scsi_unblock_requests(hba->host);
+}
+EXPORT_SYMBOL(ufshcd_scsi_unblock_requests);
+
+static inline void __ufshcd_scsi_block_requests(struct ufs_hba *hba) {
+   if (!hba->scsi_block_reqs_cnt++)
+   scsi_block_requests(hba->host);
+}
+
+void ufshcd_scsi_block_requests(struct ufs_hba *hba) {
+   unsigned long flags;
+
+   spin_lock_irqsave(hba->host->host_lock, flags);
+   __ufshcd_scsi_block_requests(hba);
+   spin_unlock_irqrestore(hba->host->host_lock, flags); }
+EXPORT_SYMBOL(ufshcd_scsi_block_requests);
+
  /* replace non-printable or non-ASCII characters with spaces */  static inline
void ufshcd_remove_non_printable(char *val)  { @@ -1079,12 +1109,12 @@
static int ufshcd_clock_scaling_prepare(struct ufs_hba *hba)
 * make sure that there are no outstanding requests when
 * clock scaling is in progress
 */
-   scsi_block_requests(hba->host);
+   ufshcd_scsi_block_requests(hba);
down_write(>clk_scaling_lock);
if (ufshcd_wait_for_doorbell_clr(hba, DOORBELL_CLR_TOUT_US)) {
ret = -EBUSY;
up_write(>clk_scaling_lock);
-   scsi_unblock_requests(hba->host);
+   ufshcd_scsi_unblock_requests(hba);
}

return ret;
@@ -1093,7 +1123,7 @@ static int ufshcd_clock_scaling_prepare(struct
ufs_hba *hba)  static void ufshcd_clock_scaling_unprepare(struct ufs_hba
*hba)  {
up_write(>clk_scaling_lock);
-   scsi_unblock_requests(hba->host);
+   ufshcd_scsi_unblock_requests(hba);
  }

  /**
@@ -1413,7 +1443,7 @@ static void ufshcd_ungate_work(struct work_struct
*work)
hba->clk_gating.is_suspended = false;
}
  unblock_reqs:
-   scsi_unblock_requests(hba->host);
+   ufshcd_scsi_unblock_requests(hba);
  }

  /**
@@ -1469,7 +1499,7 @@ int ufshcd_hold(struct ufs_hba *hba, bool async)
 * work and to enable clocks.
 */
case CLKS_OFF:
-   scsi_block_requests(hba->host);
+   __ufshcd_scsi_block_requests(hba);
hba->clk_gating.state = REQ_CLKS_ON;
trace_ufshcd_clk_gating(dev_name(hba->dev),
hba->clk_gating.state);
@@ -5197,7 +5227,7 @@ static void ufshcd_err_handler(struct work_struct
*work)

  out:
spin_unlock_irqrestore(hba->host->host_lock, flags);
-   scsi_unblock_requests(hba->host);
+   ufshcd_scsi_unblock_requests(hba);
ufshcd_release(hba);
pm_runtime_put_sync(hba->dev);
  }
@@ -5299,7 +5329,7 @@ static void ufshcd_check_errors(struct ufs_hba
*hba)

Re: [PATCH 1/8] dt-bindings: scsi: hisi_sas: add an property of signal attenuation

2018-02-22 Thread Martin K. Petersen

> From: Xiaofei Tan 
>
> For some new boards with hip07 chipset we are required to
> set PHY config registers differently. The hw property which
> determines how to set these registers is in the PHY signal
> attenuation readings.
>
> This patch add an devicetree property, signal-attenuation, which
> is used to describe the signal attenuation of an board.
>
> Cc: Rob Herring 
> Cc: Mark Rutland 
> Signed-off-by: Xiaofei Tan 
> Signed-off-by: John Garry 
> ---
>  Documentation/devicetree/bindings/scsi/hisilicon-sas.txt | 7 +++
>  1 file changed, 7 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt 
> b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
> index df3bef7..bd32ecd 100644
> --- a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
> +++ b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
> @@ -53,6 +53,13 @@ Main node required properties:
>  Optional main node properties:
>   - hip06-sas-v2-quirk-amt : when set, indicates that the v2 controller has 
> the
>   "am-max-transmissions" limitation.
> + - signal-attenuation : array of 3 32-bit values, containing de-emphasis,
> + preshoot, and boost attenuation readings for the board. They
> + are used to describe the signal attenuation of the board. These
> + values' range is 7600 to 12400, and used to represent -24dB to
> + 24dB.
> + The formula is "y = (x-1)/1". For example, 10478
> + means 4.78dB.
>  
>  Example:
>   sas0: sas@c100 {

Rob/Mark: Please review!

-- 
Martin K. Petersen  Oracle Linux Engineering


Re: [PATCH v5 00/13] lpfc new hardware patches for 12.0.0.0

2018-02-22 Thread Martin K. Petersen

James,

> This patch set adds support for Broadcom's new G7 product that
> supports G4G FC.

Applied to 4.17/scsi-queue. Thank you!

-- 
Martin K. Petersen  Oracle Linux Engineering


Re: [PATCH 0/3] qla2xxx: driver fails to log into remote ports

2018-02-22 Thread Martin K. Petersen

Hannes,

> with the latest updates the qla2xxx driver fails to log into remote
> ports, whereas P2P connections continued to work.
> After a lengthy debugging session I found that latest update has
> several less-than-perfect patches, all of which contributing to
> the failed (or, rather, not attempted) login.
> With these patches the problem is no longer seen and the driver
> behaves as expected.

Applied to 4.16/scsi-fixes. Thanks!

-- 
Martin K. Petersen  Oracle Linux Engineering


Re: [PATCH v2] scsi: qla2xxx: Use dma_pool_zalloc()

2018-02-22 Thread Martin K. Petersen

Souptick,

> Use dma_pool_zalloc() instead of dma_pool_alloc + memset

Applied to 4.17/scsi-queue.

-- 
Martin K. Petersen  Oracle Linux Engineering


Re: [PATCH] qla2xxx: Fix NULL pointer crash due to active timer for ABTS

2018-02-22 Thread Martin K. Petersen

Himanshu,

> Can you please queue this patch for 4.16-rc3

Applied to 4.16/scsi-fixes with the missing Fixes: tag. Thank you!

-- 
Martin K. Petersen  Oracle Linux Engineering


Re: [PATCH] qla2xxx: Fix NULL pointer crash due to active timer for ABTS

2018-02-22 Thread Madhani, Himanshu
Hi Martin, 

> On Feb 14, 2018, at 11:58 AM, Madhani, Himanshu  
> wrote:
> 
> Hi John,
> 
>> On Feb 13, 2018, at 2:54 AM, John Garry  wrote:
>> 
>> On 12/02/2018 18:28, Himanshu Madhani wrote:
>>> This patch fixes NULL pointer crash due to active timer running
>>> for abort IOCB.
>>> 
 From crash dump analysis it was discoverd that get_next_timer_interrupt()
>>> encountered a corrupted entry on the timer list.
>>> 
>>> #9 [95e1f6f0fd40] page_fault at 914fe8f8
>>>   [exception RIP: get_next_timer_interrupt+440]
>>>   RIP: 90ea3088  RSP: 95e1f6f0fdf0  RFLAGS: 00010013
>>>   RAX: 95e1f6451028  RBX: 000218e2389e5f40  RCX: 0001232ad600
>>>   RDX: 0001  RSI: 95e1f6f0fdf0  RDI: 01232ad6
>>>   RBP: 95e1f6f0fe40   R8: 95e1f6451188   R9: 0001
>>>   R10: 0016  R11: 0016  R12: 0001232ad5f6
>>>   R13: 95e1f645  R14: 95e1f6f0fdf8  R15: 95e1f6f0fe10
>>>   ORIG_RAX:   CS: 0010  SS: 0018
>>> 
>>> Looking at the assembly of get_next_timer_interrupt(), address came
>>> from %r8 (95e1f6451188) which is pointing to list_head with single
>>> entry at 95e5ff621178.
>>> 
>>> 0x90ea307a :  mov(%r8),%rdx
>>> 0x90ea307d :  cmp%r8,%rdx
>>> 0x90ea3080 :  je 
>>> 0x90ea30a7 
>>> 0x90ea3082 :  nopw   
>>> 0x0(%rax,%rax,1)
>>> 0x90ea3088 :  testb  
>>> $0x1,0x18(%rdx)
>>> 
>>> crash> rd 95e1f6451188 10
>>> 95e1f6451188:  95e5ff621178 95e5ff621178   x.b.x.b.
>>> 95e1f6451198:  95e1f6451198 95e1f6451198   ..E...E.
>>> 95e1f64511a8:  95e1f64511a8 95e1f64511a8   ..E...E.
>>> 95e1f64511b8:  95e77cf509a0 95e77cf509a0   ...|...|
>>> 95e1f64511c8:  95e1f64511c8 95e1f64511c8   ..E...E.
>>> 
>>> crash> rd 95e5ff621178 10
>>> 95e5ff621178:  0001 95e15936aa00   ..6Y
>>> 95e5ff621188:      
>>> 95e5ff621198:  00a0 0010   
>>> 95e5ff6211a8:  95e5ff621198 000c   ..b.
>>> 95e5ff6211b8:  0f58 95e751f8d720   X... ..Q
>>> 
>>> 95e5ff621178 belongs to freed mempool object at 95e5ff621080.
>>> 
>>> CACHENAME OBJSIZE  ALLOCATED TOTAL  SLABS  
>>> SSIZE
>>> 95dc7fd74d00 mnt_cache384  19785 24948594   
>>>  16k
>>>  SLAB  MEMORYNODE  TOTAL  ALLOCATED  FREE
>>>  dc5dabfd8800  95e5ff62 1 42 2913
>>>  FREE / [ALLOCATED]
>>>   95e5ff621080  (cpu 6 cache)
>>> 
>>> Examining the contents of that memory reveals a pointer to a constant
>>> string in the driver, "abort\0", which is set by qla24xx_async_abort_cmd().
>>> 
>>> crash> rd c059277c 20
>>> c059277c:  6e490074726f6261 0074707572726574   abort.Interrupt.
>>> c059278c:  00676e696c6c6f50 6920726576697244   Polling.Driver i
>>> c059279c:  646f6d207325206e 6974736554000a65   n %s mode..Testi
>>> c05927ac:  636976656420676e 786c252074612065   ng device at %lx
>>> c05927bc:  6b63656843000a2e 646f727020676e69   ...Checking prod
>>> c05927cc:  6f20444920746375 0a2e706968632066   uct ID of chip..
>>> c05927dc:  5120646e756f4600 204130303232414c   .Found QLA2200A
>>> c05927ec:  43000a2e70696843 20676e696b636568   Chip...Checking
>>> c05927fc:  65786f626c69616d 6c636e69000a2e73   mailboxes...incl
>>> c059280c:  756e696c2f656475 616d2d616d642f78   ude/linux/dma-ma
>>> 
>>> crash> struct -ox srb_iocb
>>> struct srb_iocb {
>>>  union {
>>>  struct {...} logio;
>>>  struct {...} els_logo;
>>>  struct {...} tmf;
>>>  struct {...} fxiocb;
>>>  struct {...} abt;
>>>  struct ct_arg ctarg;
>>>  struct {...} mbx;
>>>  struct {...} nack;
>>>   [0x0 ] } u;
>>>   [0xb8] struct timer_list timer;
>>>   [0x108] void (*timeout)(void *);
>>> }
>>> SIZE: 0x110
>>> 
>>> crash> ! bc
>>> ibase=16
>>> obase=10
>>> B8+40
>>> F8
>>> 
>>> The object is a srb_t, and at offset 0xf8 within that structure
>>> (i.e. 95e5ff621080 + f8 -> 95e5ff621178) is a struct timer_list.
>>> 
>>> Cc:  #4.4+
>>> Signed-off-by: Himanshu Madhani 
>>> ---
>>> Hi Martin,
>>> 
>>> This patch addresses crash due to NULL pointer access because driver
>>> left active timer running for abort IOCB.
>>> 
>>> Please apply this patch to 4.16/scsi-fixes at your 

target documentation patches?

2018-02-22 Thread Randy Dunlap
Hi Nicholas,

I posted several patches for target documentation cleanups and adding
a chapter to the driver-api chapter back in December.

Do I need to repost those?  Do you want someone else to merge them, even
though several of them are in drivers/target/ ?


[PATCH] target: fix kernel-doc warnings in 
drivers/target/target_core_transport.c
https://www.spinics.net/lists/target-devel/msg16378.html

[PATCH] target: cleanup target_core_transport.c for kernel-doc
https://www.spinics.net/lists/target-devel/msg16381.html

[PATCH] target: add kernel-doc overview in target_core_user.[hc]
https://www.spinics.net/lists/target-devel/msg16380.html

[PATCH v2] target: add a target/iscsi driver-api Documentation chapter
https://www.spinics.net/lists/target-devel/msg16383.html

This patch has already been merged:
[PATCH] scsi: fix iscsi-related kernel-doc warnings
  https://marc.info/?l=linux-scsi=151398051426923=2


thanks,
-- 
~Randy


Re: [GIT PULL] SCSI fixes for 4.16-rc2

2018-02-22 Thread Linus Torvalds
On Thu, Feb 22, 2018 at 11:28 AM, James Bottomley
 wrote:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git scsi-fixes

When I pull that, I get something completely different from what you
claim I should get. Much bigger, and a lot more commits.

Hmm?

Dropped.

  Linus


[PATCH 38/38] cxlflash: Enable OpenCXL operations

2018-02-22 Thread Uma Krishnan
This commit enables the OpenCXL operations for the OpenCXL devices.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/main.c | 9 +++--
 drivers/scsi/cxlflash/main.h | 1 +
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 8c55fcd..42a95b7 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -3168,7 +3168,8 @@ static struct dev_dependent_vals dev_corsa_vals = { 
CXLFLASH_MAX_SECTORS,
 static struct dev_dependent_vals dev_flash_gt_vals = { CXLFLASH_MAX_SECTORS,
CXLFLASH_NOTIFY_SHUTDOWN };
 static struct dev_dependent_vals dev_briard_vals = { CXLFLASH_MAX_SECTORS,
-   CXLFLASH_NOTIFY_SHUTDOWN };
+   (CXLFLASH_NOTIFY_SHUTDOWN |
+   CXLFLASH_OCXL_DEV) };
 
 /*
  * PCI device binding table
@@ -3679,9 +3680,13 @@ static int cxlflash_probe(struct pci_dev *pdev,
 
cfg->init_state = INIT_STATE_NONE;
cfg->dev = pdev;
-   cfg->ops = _cxl_ops;
cfg->cxl_fops = cxlflash_cxl_fops;
 
+   if (ddv->flags & CXLFLASH_OCXL_DEV)
+   cfg->ops = _ocxl_ops;
+   else
+   cfg->ops = _cxl_ops;
+
/*
 * Promoted LUNs move to the top of the LUN table. The rest stay on
 * the bottom half. The bottom half grows from the end (index = 255),
diff --git a/drivers/scsi/cxlflash/main.h b/drivers/scsi/cxlflash/main.h
index ba0108a..6f1be62 100644
--- a/drivers/scsi/cxlflash/main.h
+++ b/drivers/scsi/cxlflash/main.h
@@ -97,6 +97,7 @@ struct dev_dependent_vals {
u64 flags;
 #define CXLFLASH_NOTIFY_SHUTDOWN   0x0001ULL
 #define CXLFLASH_WWPN_VPD_REQUIRED 0x0002ULL
+#define CXLFLASH_OCXL_DEV  0x0004ULL
 };
 
 struct asyc_intr_info {
-- 
2.1.0



[PATCH 36/38] cxlflash: Register for translation errors

2018-02-22 Thread Uma Krishnan
While enabling a context on the link, a predefined callback can be
registered with the OCXL provider services to be notified on translation
errors. These errors can in turn be passed back to the user on a read
operation.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 31 +--
 drivers/scsi/cxlflash/ocxl_hw.h |  4 
 2 files changed, 33 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 535b21a..dc45ed2 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -335,6 +335,25 @@ static u64 ocxlflash_get_irq_objhndl(void *ctx_cookie, int 
irq)
 }
 
 /**
+ * ocxlflash_xsl_fault() - callback when translation error is triggered
+ * @data:  Private data provided at callback registration, the context.
+ * @addr:  Address that triggered the error.
+ * @dsisr: Value of dsisr register.
+ */
+static void ocxlflash_xsl_fault(void *data, u64 addr, u64 dsisr)
+{
+   struct ocxlflash_context *ctx = data;
+
+   spin_lock(>slock);
+   ctx->fault_addr = addr;
+   ctx->fault_dsisr = dsisr;
+   ctx->pending_fault = true;
+   spin_unlock(>slock);
+
+   wake_up_all(>wq);
+}
+
+/**
  * start_context() - local routine to start a context
  * @ctx:   Adapter context to be started.
  *
@@ -378,7 +397,8 @@ static int start_context(struct ocxlflash_context *ctx)
mm = current->mm;
}
 
-   rc = ocxl_link_add_pe(link_token, ctx->pe, pid, 0, 0, mm, NULL, NULL);
+   rc = ocxl_link_add_pe(link_token, ctx->pe, pid, 0, 0, mm,
+ ocxlflash_xsl_fault, ctx);
if (unlikely(rc)) {
dev_err(dev, "%s: ocxl_link_add_pe failed rc=%d\n",
__func__, rc);
@@ -512,6 +532,7 @@ static void *ocxlflash_dev_context_init(struct pci_dev 
*pdev, void *afu_cookie)
ctx->hw_afu = afu;
ctx->irq_bitmap = 0;
ctx->pending_irq = false;
+   ctx->pending_fault = false;
 out:
return ctx;
 err2:
@@ -957,7 +978,7 @@ static void *ocxlflash_create_afu(struct pci_dev *pdev)
  */
 static inline bool ctx_event_pending(struct ocxlflash_context *ctx)
 {
-   if (ctx->pending_irq)
+   if (ctx->pending_irq || ctx->pending_fault)
return true;
 
return false;
@@ -1062,6 +1083,12 @@ static ssize_t afu_read(struct file *file, char __user 
*buf, size_t count,
event.irq.irq = bit + 1;
if (bitmap_empty(>irq_bitmap, ctx->num_irqs))
ctx->pending_irq = false;
+   } else if (ctx->pending_fault) {
+   event.header.size += sizeof(struct cxl_event_data_storage);
+   event.header.type = CXL_EVENT_DATA_STORAGE;
+   event.fault.addr = ctx->fault_addr;
+   event.fault.dsisr = ctx->fault_dsisr;
+   ctx->pending_fault = false;
}
 
spin_unlock_irqrestore(>slock, lock_flags);
diff --git a/drivers/scsi/cxlflash/ocxl_hw.h b/drivers/scsi/cxlflash/ocxl_hw.h
index c23b681..c48465a 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.h
+++ b/drivers/scsi/cxlflash/ocxl_hw.h
@@ -69,4 +69,8 @@ struct ocxlflash_context {
int num_irqs;   /* Number of interrupts */
bool pending_irq;   /* Pending interrupt on the context */
ulong irq_bitmap;   /* Bits indicating pending irq num */
+
+   u64 fault_addr; /* Address that triggered the fault */
+   u64 fault_dsisr;/* Value of dsisr register at fault */
+   bool pending_fault; /* Pending translation fault */
 };
-- 
2.1.0



[PATCH 31/38] cxlflash: Introduce object handle fop

2018-02-22 Thread Uma Krishnan
OpenCXL requires that AFUs use an opaque object handle to represent
an AFU interrupt. The specification does not provide a common means
to communicate the object handle to the AFU - each AFU must define
this within the AFU specification. To support this model, the object
handle must be passed back to the core driver as it manages the AFU
specification (SISLite) for cxlflash. Note that for Power systems,
the object handle is the effective address of the trigger page.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/backend.h |  1 +
 drivers/scsi/cxlflash/cxl_hw.c  |  7 +++
 drivers/scsi/cxlflash/ocxl_hw.c | 18 ++
 3 files changed, 26 insertions(+)

diff --git a/drivers/scsi/cxlflash/backend.h b/drivers/scsi/cxlflash/backend.h
index f675bcb..bcd8a6c 100644
--- a/drivers/scsi/cxlflash/backend.h
+++ b/drivers/scsi/cxlflash/backend.h
@@ -23,6 +23,7 @@ struct cxlflash_backend_ops {
int (*map_afu_irq)(void *ctx_cookie, int num, irq_handler_t handler,
   void *cookie, char *name);
void (*unmap_afu_irq)(void *ctx_cookie, int num, void *cookie);
+   u64 (*get_irq_objhndl)(void *ctx_cookie, int irq);
int (*start_context)(void *ctx_cookie);
int (*stop_context)(void *ctx_cookie);
int (*afu_reset)(void *ctx_cookie);
diff --git a/drivers/scsi/cxlflash/cxl_hw.c b/drivers/scsi/cxlflash/cxl_hw.c
index a1d6d12..b42da88 100644
--- a/drivers/scsi/cxlflash/cxl_hw.c
+++ b/drivers/scsi/cxlflash/cxl_hw.c
@@ -49,6 +49,12 @@ static void cxlflash_unmap_afu_irq(void *ctx_cookie, int 
num, void *cookie)
cxl_unmap_afu_irq(ctx_cookie, num, cookie);
 }
 
+static u64 cxlflash_get_irq_objhndl(void *ctx_cookie, int irq)
+{
+   /* Dummy fop for cxl */
+   return 0;
+}
+
 static int cxlflash_start_context(void *ctx_cookie)
 {
return cxl_start_context(ctx_cookie, 0, NULL);
@@ -153,6 +159,7 @@ const struct cxlflash_backend_ops cxlflash_cxl_ops = {
.process_element= cxlflash_process_element,
.map_afu_irq= cxlflash_map_afu_irq,
.unmap_afu_irq  = cxlflash_unmap_afu_irq,
+   .get_irq_objhndl= cxlflash_get_irq_objhndl,
.start_context  = cxlflash_start_context,
.stop_context   = cxlflash_stop_context,
.afu_reset  = cxlflash_afu_reset,
diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 119481c..1044bee 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -308,6 +308,23 @@ static void ocxlflash_unmap_afu_irq(void *ctx_cookie, int 
num, void *cookie)
 }
 
 /**
+ * ocxlflash_get_irq_objhndl() - get the object handle for an interrupt
+ * @ctx_cookie:Context associated with the interrupt.
+ * @irq:   Interrupt number.
+ *
+ * Return: effective address of the mapped region
+ */
+static u64 ocxlflash_get_irq_objhndl(void *ctx_cookie, int irq)
+{
+   struct ocxlflash_context *ctx = ctx_cookie;
+
+   if (irq < 0 || irq >= ctx->num_irqs)
+   return 0;
+
+   return (__force u64)ctx->irqs[irq].vtrig;
+}
+
+/**
  * start_context() - local routine to start a context
  * @ctx:   Adapter context to be started.
  *
@@ -1293,6 +1310,7 @@ const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
.process_element= ocxlflash_process_element,
.map_afu_irq= ocxlflash_map_afu_irq,
.unmap_afu_irq  = ocxlflash_unmap_afu_irq,
+   .get_irq_objhndl= ocxlflash_get_irq_objhndl,
.start_context  = ocxlflash_start_context,
.stop_context   = ocxlflash_stop_context,
.set_master = ocxlflash_set_master,
-- 
2.1.0



[PATCH 34/38] cxlflash: Update synchronous interrupt status bits

2018-02-22 Thread Uma Krishnan
The SISLite specification has been updated to define new synchronous
interrupt status bits. These bits are set by the AFU when a given PASID or
EA is bad and a synchronous interrupt is triggered.

The SISLite header file is updated to support these new bits. Note that
there are also some formatting updates to some of the existing bits to
allow all of the definitions to line up uniformly.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/sislite.h | 35 +--
 1 file changed, 21 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/cxlflash/sislite.h b/drivers/scsi/cxlflash/sislite.h
index c08b9d3..874abce 100644
--- a/drivers/scsi/cxlflash/sislite.h
+++ b/drivers/scsi/cxlflash/sislite.h
@@ -258,23 +258,30 @@ struct sisl_host_map {
 * exit since there is no way to tell which
 * command caused the error.
 */
-#define SISL_ISTATUS_PERM_ERR_CMDROOM0x0010ULL /* b59, user error */
-#define SISL_ISTATUS_PERM_ERR_RCB_READ   0x0008ULL /* b60, user error */
-#define SISL_ISTATUS_PERM_ERR_SA_WRITE   0x0004ULL /* b61, user error */
-#define SISL_ISTATUS_PERM_ERR_RRQ_WRITE  0x0002ULL /* b62, user error */
+#define SISL_ISTATUS_PERM_ERR_LISN_3_EA0x0400ULL /* b53, user 
error */
+#define SISL_ISTATUS_PERM_ERR_LISN_2_EA0x0200ULL /* b54, user 
error */
+#define SISL_ISTATUS_PERM_ERR_LISN_1_EA0x0100ULL /* b55, user 
error */
+#define SISL_ISTATUS_PERM_ERR_LISN_3_PASID 0x0080ULL /* b56, user error */
+#define SISL_ISTATUS_PERM_ERR_LISN_2_PASID 0x0040ULL /* b57, user error */
+#define SISL_ISTATUS_PERM_ERR_LISN_1_PASID 0x0020ULL /* b58, user error */
+#define SISL_ISTATUS_PERM_ERR_CMDROOM  0x0010ULL /* b59, user error */
+#define SISL_ISTATUS_PERM_ERR_RCB_READ 0x0008ULL /* b60, user error */
+#define SISL_ISTATUS_PERM_ERR_SA_WRITE 0x0004ULL /* b61, user error */
+#define SISL_ISTATUS_PERM_ERR_RRQ_WRITE0x0002ULL /* b62, user 
error */
/* Page in wait accessing RCB/IOASA/RRQ is reported in b63.
 * Same error in data/LXT/RHT access is reported via IOASA.
 */
-#define SISL_ISTATUS_TEMP_ERR_PAGEIN 0x0001ULL /* b63, can be generated
-* only when AFU auto
-* retry is disabled.
-* If user can determine
-* the command that
-* caused the error, it
-* can be retried.
-*/
-#define SISL_ISTATUS_UNMASK  (0x001FULL)   /* 1 means unmasked */
-#define SISL_ISTATUS_MASK~(SISL_ISTATUS_UNMASK)/* 1 means masked */
+#define SISL_ISTATUS_TEMP_ERR_PAGEIN   0x0001ULL /* b63, can only be
+  * generated when AFU
+  * auto retry is
+  * disabled. If user
+  * can determine the
+  * command that caused
+  * the error, it can
+  * be retried.
+  */
+#define SISL_ISTATUS_UNMASK(0x07FFULL) /* 1 means unmasked */
+#define SISL_ISTATUS_MASK  ~(SISL_ISTATUS_UNMASK)  /* 1 means masked */
 
__be64 intr_clear;
__be64 intr_mask;
-- 
2.1.0



[PATCH 35/38] cxlflash: Introduce OCXL context state machine

2018-02-22 Thread Uma Krishnan
In order to protect the OCXL hardware contexts from getting clobbered,
a simple state machine is added to indicate when a context is in open,
close or start state. The expected states are validated throughout the
code to prevent illegal operations on a context. A mutex is added to
protect writes to the context state field.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 59 ++---
 drivers/scsi/cxlflash/ocxl_hw.h |  8 ++
 2 files changed, 64 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 1044bee..535b21a 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -163,6 +163,16 @@ static struct file *ocxlflash_getfile(struct device *dev, 
const char *name,
 static void __iomem *ocxlflash_psa_map(void *ctx_cookie)
 {
struct ocxlflash_context *ctx = ctx_cookie;
+   struct device *dev = ctx->hw_afu->dev;
+
+   mutex_lock(>state_mutex);
+   if (ctx->state != STARTED) {
+   dev_err(dev, "%s: Context not started, state=%d\n", __func__,
+   ctx->state);
+   mutex_unlock(>state_mutex);
+   return NULL;
+   }
+   mutex_unlock(>state_mutex);
 
return ioremap(ctx->psn_phys, ctx->psn_size);
 }
@@ -343,6 +353,14 @@ static int start_context(struct ocxlflash_context *ctx)
int rc = 0;
u32 pid;
 
+   mutex_lock(>state_mutex);
+   if (ctx->state != OPENED) {
+   dev_err(dev, "%s: Context state invalid, state=%d\n",
+   __func__, ctx->state);
+   rc = -EINVAL;
+   goto out;
+   }
+
if (master) {
ctx->psn_size = acfg->global_mmio_size;
ctx->psn_phys = afu->gmmio_phys;
@@ -366,7 +384,10 @@ static int start_context(struct ocxlflash_context *ctx)
__func__, rc);
goto out;
}
+
+   ctx->state = STARTED;
 out:
+   mutex_unlock(>state_mutex);
return rc;
 }
 
@@ -396,7 +417,15 @@ static int ocxlflash_stop_context(void *ctx_cookie)
struct ocxl_afu_config *acfg = >acfg;
struct pci_dev *pdev = afu->pdev;
struct device *dev = afu->dev;
-   int rc;
+   enum ocxlflash_ctx_state state;
+   int rc = 0;
+
+   mutex_lock(>state_mutex);
+   state = ctx->state;
+   ctx->state = CLOSED;
+   mutex_unlock(>state_mutex);
+   if (state != STARTED)
+   goto out;
 
rc = ocxl_config_terminate_pasid(pdev, acfg->dvsec_afu_control_pos,
 ctx->pe);
@@ -474,7 +503,9 @@ static void *ocxlflash_dev_context_init(struct pci_dev 
*pdev, void *afu_cookie)
 
spin_lock_init(>slock);
init_waitqueue_head(>wq);
+   mutex_init(>state_mutex);
 
+   ctx->state = OPENED;
ctx->pe = rc;
ctx->master = false;
ctx->mapping = NULL;
@@ -499,11 +530,23 @@ static void *ocxlflash_dev_context_init(struct pci_dev 
*pdev, void *afu_cookie)
 static int ocxlflash_release_context(void *ctx_cookie)
 {
struct ocxlflash_context *ctx = ctx_cookie;
+   struct device *dev;
int rc = 0;
 
if (!ctx)
goto out;
 
+   dev = ctx->hw_afu->dev;
+   mutex_lock(>state_mutex);
+   if (ctx->state >= STARTED) {
+   dev_err(dev, "%s: Context in use, state=%d\n", __func__,
+   ctx->state);
+   mutex_unlock(>state_mutex);
+   rc = -EBUSY;
+   goto out;
+   }
+   mutex_unlock(>state_mutex);
+
idr_remove(>hw_afu->idr, ctx->pe);
ocxlflash_release_mapping(ctx);
kfree(ctx);
@@ -939,7 +982,7 @@ static unsigned int afu_poll(struct file *file, struct 
poll_table_struct *poll)
spin_lock_irqsave(>slock, lock_flags);
if (ctx_event_pending(ctx))
mask |= POLLIN | POLLRDNORM;
-   else
+   else if (ctx->state == CLOSED)
mask |= POLLERR;
spin_unlock_irqrestore(>slock, lock_flags);
 
@@ -982,7 +1025,7 @@ static ssize_t afu_read(struct file *file, char __user 
*buf, size_t count,
for (;;) {
prepare_to_wait(>wq, _wait, TASK_INTERRUPTIBLE);
 
-   if (ctx_event_pending(ctx))
+   if (ctx_event_pending(ctx) || (ctx->state == CLOSED))
break;
 
if (file->f_flags & O_NONBLOCK) {
@@ -1068,12 +,22 @@ static int ocxlflash_mmap_fault(struct vm_fault *vmf)
 {
struct vm_area_struct *vma = vmf->vma;
struct ocxlflash_context *ctx = vma->vm_file->private_data;
+   struct device *dev = ctx->hw_afu->dev;
u64 mmio_area, offset;
 
offset = vmf->pgoff << PAGE_SHIFT;
if (offset >= ctx->psn_size)
return VM_FAULT_SIGBUS;
 
+   mutex_lock(>state_mutex);
+   if 

[PATCH 37/38] cxlflash: Support AFU reset

2018-02-22 Thread Uma Krishnan
The cxlflash core driver resets the AFU when the master contexts are
created in the initialization or recovery paths. Today, the OCXL
provider service to perform this operation is pending implementation.
To avoid a crash due to a missing fop, log an error once and return
success to continue with execution.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 17 +
 1 file changed, 17 insertions(+)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index dc45ed2..8a1a9fc 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -468,6 +468,22 @@ static int ocxlflash_stop_context(void *ctx_cookie)
 }
 
 /**
+ * ocxlflash_afu_reset() - reset the AFU
+ * @ctx_cookie:Adapter context.
+ */
+static int ocxlflash_afu_reset(void *ctx_cookie)
+{
+   struct ocxlflash_context *ctx = ctx_cookie;
+   struct device *dev = ctx->hw_afu->dev;
+
+   /* Pending implementation from OCXL transport services */
+   dev_err_once(dev, "%s: afu_reset() fop not supported\n", __func__);
+
+   /* Silently return success until it is implemented */
+   return 0;
+}
+
+/**
  * ocxlflash_set_master() - sets the context as master
  * @ctx_cookie:Adapter context to set as master.
  */
@@ -1393,6 +1409,7 @@ const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
.get_irq_objhndl= ocxlflash_get_irq_objhndl,
.start_context  = ocxlflash_start_context,
.stop_context   = ocxlflash_stop_context,
+   .afu_reset  = ocxlflash_afu_reset,
.set_master = ocxlflash_set_master,
.get_context= ocxlflash_get_context,
.dev_context_init   = ocxlflash_dev_context_init,
-- 
2.1.0



[PATCH 32/38] cxlflash: Setup LISNs for user contexts

2018-02-22 Thread Uma Krishnan
The SISLite specification has been updated for OpenCXL to support
communicating data to generate AFU interrupts to the AFU. This includes
a new capability bit that is advertised for OpenCXL AFUs and new registers
to hold the object handle and translation PASID of each interrupt. For
Power, the object handle is the mapped trigger page. Note that because
these mappings are kernel only, the PASID of a kernel context must be
used to satisfy the translation.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/common.h|  5 +
 drivers/scsi/cxlflash/sislite.h   |  5 +
 drivers/scsi/cxlflash/superpipe.c | 14 ++
 3 files changed, 24 insertions(+)

diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h
index d7fccea..b69fd32 100644
--- a/drivers/scsi/cxlflash/common.h
+++ b/drivers/scsi/cxlflash/common.h
@@ -273,6 +273,11 @@ static inline bool afu_has_cap(struct afu *afu, u64 cap)
return afu_cap & cap;
 }
 
+static inline bool afu_is_ocxl_lisn(struct afu *afu)
+{
+   return afu_has_cap(afu, SISL_INTVER_CAP_OCXL_LISN);
+}
+
 static inline bool afu_is_afu_debug(struct afu *afu)
 {
return afu_has_cap(afu, SISL_INTVER_CAP_AFU_DEBUG);
diff --git a/drivers/scsi/cxlflash/sislite.h b/drivers/scsi/cxlflash/sislite.h
index d8940f1..c08b9d3 100644
--- a/drivers/scsi/cxlflash/sislite.h
+++ b/drivers/scsi/cxlflash/sislite.h
@@ -310,6 +310,10 @@ struct sisl_ctrl_map {
 #define SISL_CTX_CAP_WRITE_CMD 0x0002ULL /* afu_rc 0x21 */
 #define SISL_CTX_CAP_READ_CMD  0x0001ULL /* afu_rc 0x21 */
__be64 mbox_r;
+   __be64 lisn_pasid[2];
+   /* pasid _a arg must be ULL */
+#define SISL_LISN_PASID(_a, _b)(((_a) << 32) | (_b))
+   __be64 lisn_ea[3];
 };
 
 /* single copy global regs */
@@ -416,6 +420,7 @@ struct sisl_global_regs {
 #define SISL_INTVER_CAP_RESERVED_CMD_MODE_B0x1000ULL
 #define SISL_INTVER_CAP_LUN_PROVISION  0x0800ULL
 #define SISL_INTVER_CAP_AFU_DEBUG  0x0400ULL
+#define SISL_INTVER_CAP_OCXL_LISN  0x0200ULL
 };
 
 #define CXLFLASH_NUM_FC_PORTS_PER_BANK 2   /* fixed # of ports per bank */
diff --git a/drivers/scsi/cxlflash/superpipe.c 
b/drivers/scsi/cxlflash/superpipe.c
index 2fe79df..04a3bf9 100644
--- a/drivers/scsi/cxlflash/superpipe.c
+++ b/drivers/scsi/cxlflash/superpipe.c
@@ -269,6 +269,7 @@ static int afu_attach(struct cxlflash_cfg *cfg, struct 
ctx_info *ctxi)
int rc = 0;
struct hwq *hwq = get_hwq(afu, PRIMARY_HWQ);
u64 val;
+   int i;
 
/* Unlock cap and restrict user to read/write cmds in translated mode */
readq_be(_map->mbox_r);
@@ -282,6 +283,19 @@ static int afu_attach(struct cxlflash_cfg *cfg, struct 
ctx_info *ctxi)
goto out;
}
 
+   if (afu_is_ocxl_lisn(afu)) {
+   /* Set up the LISN effective address for each interrupt */
+   for (i = 0; i < ctxi->irqs; i++) {
+   val = cfg->ops->get_irq_objhndl(ctxi->ctx, i);
+   writeq_be(val, _map->lisn_ea[i]);
+   }
+
+   /* Use primary HWQ PASID as identifier for all interrupts */
+   val = hwq->ctx_hndl;
+   writeq_be(SISL_LISN_PASID(val, val), _map->lisn_pasid[0]);
+   writeq_be(SISL_LISN_PASID(0UL, val), _map->lisn_pasid[1]);
+   }
+
/* Set up MMIO registers pointing to the RHT */
writeq_be((u64)ctxi->rht_start, _map->rht_start);
val = SISL_RHT_CNT_ID((u64)MAX_RHT_PER_CONTEXT, (u64)(hwq->ctx_hndl));
-- 
2.1.0



[PATCH 33/38] cxlflash: Setup LISNs for master contexts

2018-02-22 Thread Uma Krishnan
Similar to user contexts, master contexts also require that the per-context
LISN registers be programmed for certain AFUs. The mapped trigger page is
obtained from underlying transport and registered with AFU for each master
context.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/main.c | 21 +
 1 file changed, 21 insertions(+)

diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 5d754d1..8c55fcd 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -1756,6 +1756,8 @@ static int init_global(struct cxlflash_cfg *cfg)
u64 wwpn[MAX_FC_PORTS]; /* wwpn of AFU ports */
int i = 0, num_ports = 0;
int rc = 0;
+   int j;
+   void *ctx;
u64 reg;
 
rc = read_vpd(cfg, [0]);
@@ -1816,6 +1818,25 @@ static int init_global(struct cxlflash_cfg *cfg)
msleep(100);
}
 
+   if (afu_is_ocxl_lisn(afu)) {
+   /* Set up the LISN effective address for each master */
+   for (i = 0; i < afu->num_hwqs; i++) {
+   hwq = get_hwq(afu, i);
+   ctx = hwq->ctx_cookie;
+
+   for (j = 0; j < hwq->num_irqs; j++) {
+   reg = cfg->ops->get_irq_objhndl(ctx, j);
+   writeq_be(reg, >ctrl_map->lisn_ea[j]);
+   }
+
+   reg = hwq->ctx_hndl;
+   writeq_be(SISL_LISN_PASID(reg, reg),
+ >ctrl_map->lisn_pasid[0]);
+   writeq_be(SISL_LISN_PASID(0UL, reg),
+ >ctrl_map->lisn_pasid[1]);
+   }
+   }
+
/* Set up master's own CTX_CAP to allow real mode, host translation */
/* tables, afu cmds and read/write GSCSI cmds. */
/* First, unlock ctx_cap write by reading mbox */
-- 
2.1.0



[PATCH 29/38] cxlflash: Support adapter context mmap and release

2018-02-22 Thread Uma Krishnan
The cxlflash userspace API requires that users be able to mmap and release
the adapter context. Support mapping by implementing the AFU mmap fop to
map the context MMIO space and install the corresponding page table entry
upon page fault. Similarly, implement the AFU release fop to terminate and
clean up the context when invoked.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 72 +
 1 file changed, 72 insertions(+)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index e504dd2..f090563 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -1021,10 +1021,80 @@ static ssize_t afu_read(struct file *file, char __user 
*buf, size_t count,
goto out;
 }
 
+/**
+ * afu_release() - release and free the context
+ * @inode: File inode pointer.
+ * @file:  File associated with the context.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int afu_release(struct inode *inode, struct file *file)
+{
+   struct ocxlflash_context *ctx = file->private_data;
+   int i;
+
+   /* Unmap and free the interrupts associated with the context */
+   for (i = ctx->num_irqs; i >= 0; i--)
+   afu_unmap_irq(0, ctx, i, ctx);
+   free_afu_irqs(ctx);
+
+   return ocxlflash_release_context(ctx);
+}
+
+/**
+ * ocxlflash_mmap_fault() - mmap fault handler
+ * @vmf:   VM fault associated with current fault.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ocxlflash_mmap_fault(struct vm_fault *vmf)
+{
+   struct vm_area_struct *vma = vmf->vma;
+   struct ocxlflash_context *ctx = vma->vm_file->private_data;
+   u64 mmio_area, offset;
+
+   offset = vmf->pgoff << PAGE_SHIFT;
+   if (offset >= ctx->psn_size)
+   return VM_FAULT_SIGBUS;
+
+   mmio_area = ctx->psn_phys;
+   mmio_area += offset;
+
+   vm_insert_pfn(vma, vmf->address, mmio_area >> PAGE_SHIFT);
+   return VM_FAULT_NOPAGE;
+}
+
+static const struct vm_operations_struct ocxlflash_vmops = {
+   .fault = ocxlflash_mmap_fault,
+};
+
+/**
+ * afu_mmap() - map the fault handler operations
+ * @file:  File associated with the context.
+ * @vma:   VM area associated with mapping.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int afu_mmap(struct file *file, struct vm_area_struct *vma)
+{
+   struct ocxlflash_context *ctx = file->private_data;
+
+   if ((vma_pages(vma) + vma->vm_pgoff) >
+   (ctx->psn_size >> PAGE_SHIFT))
+   return -EINVAL;
+
+   vma->vm_flags |= VM_IO | VM_PFNMAP;
+   vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+   vma->vm_ops = _vmops;
+   return 0;
+}
+
 static const struct file_operations ocxl_afu_fops = {
.owner  = THIS_MODULE,
.poll   = afu_poll,
.read   = afu_read,
+   .release= afu_release,
+   .mmap   = afu_mmap,
 };
 
 #define PATCH_FOPS(NAME)   \
@@ -1071,6 +1141,8 @@ static struct file *ocxlflash_get_fd(void *ctx_cookie,
if (fops) {
PATCH_FOPS(poll);
PATCH_FOPS(read);
+   PATCH_FOPS(release);
+   PATCH_FOPS(mmap);
} else /* Use default ops */
fops = (struct file_operations *)_afu_fops;
 
-- 
2.1.0



[PATCH 26/38] cxlflash: Support starting user contexts

2018-02-22 Thread Uma Krishnan
User contexts request interrupts and are started using the "start work"
interface. Populate the start_work() fop to allocate and map interrupts
before starting the user context. As part of starting the context, update
the user process identification logic to properly derive the data required
by the SPA. Also, introduce a skeleton interrupt handler using a bitmap,
flag, and spinlock to track interrupts. This handler will be expanded in
future commits.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 99 -
 drivers/scsi/cxlflash/ocxl_hw.h |  3 ++
 2 files changed, 100 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 3b28c2a..4ca4a72 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -318,7 +318,9 @@ static int start_context(struct ocxlflash_context *ctx)
void *link_token = afu->link_token;
struct device *dev = afu->dev;
bool master = ctx->master;
+   struct mm_struct *mm;
int rc = 0;
+   u32 pid;
 
if (master) {
ctx->psn_size = acfg->global_mmio_size;
@@ -328,9 +330,16 @@ static int start_context(struct ocxlflash_context *ctx)
ctx->psn_phys = afu->ppmmio_phys + (ctx->pe * ctx->psn_size);
}
 
+   /* pid and mm not set for master contexts */
+   if (master) {
+   pid = 0;
+   mm = NULL;
+   } else {
+   pid = current->mm->context.id;
+   mm = current->mm;
+   }
 
-   /* pid, tid, amr and mm are zeroes/NULL for a kernel context */
-   rc = ocxl_link_add_pe(link_token, ctx->pe, 0, 0, 0, NULL, NULL, NULL);
+   rc = ocxl_link_add_pe(link_token, ctx->pe, pid, 0, 0, mm, NULL, NULL);
if (unlikely(rc)) {
dev_err(dev, "%s: ocxl_link_add_pe failed rc=%d\n",
__func__, rc);
@@ -442,10 +451,14 @@ static void *ocxlflash_dev_context_init(struct pci_dev 
*pdev, void *afu_cookie)
goto err2;
}
 
+   spin_lock_init(>slock);
+
ctx->pe = rc;
ctx->master = false;
ctx->mapping = NULL;
ctx->hw_afu = afu;
+   ctx->irq_bitmap = 0;
+   ctx->pending_irq = false;
 out:
return ctx;
 err2:
@@ -948,6 +961,87 @@ static void *ocxlflash_fops_get_context(struct file *file)
return file->private_data;
 }
 
+/**
+ * ocxlflash_afu_irq() - interrupt handler for user contexts
+ * @irq:   Interrupt number.
+ * @data:  Private data provided at interrupt registration, the context.
+ *
+ * Return: Always return IRQ_HANDLED.
+ */
+static irqreturn_t ocxlflash_afu_irq(int irq, void *data)
+{
+   struct ocxlflash_context *ctx = data;
+   struct device *dev = ctx->hw_afu->dev;
+   int i;
+
+   dev_dbg(dev, "%s: Interrupt raised for pe %i virq %i\n",
+   __func__, ctx->pe, irq);
+
+   for (i = 0; i < ctx->num_irqs; i++) {
+   if (ctx->irqs[i].virq == irq)
+   break;
+   }
+   if (unlikely(i >= ctx->num_irqs)) {
+   dev_err(dev, "%s: Received AFU IRQ out of range\n", __func__);
+   goto out;
+   }
+
+   spin_lock(>slock);
+   set_bit(i - 1, >irq_bitmap);
+   ctx->pending_irq = true;
+   spin_unlock(>slock);
+out:
+   return IRQ_HANDLED;
+}
+
+/**
+ * ocxlflash_start_work() - start a user context
+ * @ctx_cookie:Context to be started.
+ * @num_irqs:  Number of interrupts requested.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ocxlflash_start_work(void *ctx_cookie, u64 num_irqs)
+{
+   struct ocxlflash_context *ctx = ctx_cookie;
+   struct ocxl_hw_afu *afu = ctx->hw_afu;
+   struct device *dev = afu->dev;
+   char *name;
+   int rc = 0;
+   int i;
+
+   rc = alloc_afu_irqs(ctx, num_irqs);
+   if (unlikely(rc < 0)) {
+   dev_err(dev, "%s: alloc_afu_irqs failed rc=%d\n", __func__, rc);
+   goto out;
+   }
+
+   for (i = 0; i < num_irqs; i++) {
+   name = kasprintf(GFP_KERNEL, "ocxlflash-%s-pe%i-%i",
+dev_name(dev), ctx->pe, i);
+   rc = afu_map_irq(0, ctx, i, ocxlflash_afu_irq, ctx, name);
+   kfree(name);
+   if (unlikely(rc < 0)) {
+   dev_err(dev, "%s: afu_map_irq failed rc=%d\n",
+   __func__, rc);
+   goto err;
+   }
+   }
+
+   rc = start_context(ctx);
+   if (unlikely(rc)) {
+   dev_err(dev, "%s: start_context failed rc=%d\n", __func__, rc);
+   goto err;
+   }
+out:
+   return rc;
+err:
+   for (i = i-1; i >= 0; i--)
+   afu_unmap_irq(0, ctx, i, ctx);
+   free_afu_irqs(ctx);
+   goto out;
+}
+
 /* Backend ops to ocxlflash services */
 const 

[PATCH 30/38] cxlflash: Support file descriptor mapping

2018-02-22 Thread Uma Krishnan
The cxlflash core fop API requires a way to invoke the fault and release
handlers of underlying transports using their native file-based APIs. This
provides the core with the ability to insert selectively itself into the
processing stream of these operations for cleanup. Implement these two
fops to map and release when requested.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index f090563..119481c 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -1259,6 +1259,30 @@ static int ocxlflash_start_work(void *ctx_cookie, u64 
num_irqs)
afu_unmap_irq(0, ctx, i, ctx);
free_afu_irqs(ctx);
goto out;
+};
+
+/**
+ * ocxlflash_fd_mmap() - mmap handler for adapter file descriptor
+ * @file:  File installed with adapter file descriptor.
+ * @vma:   VM area associated with mapping.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ocxlflash_fd_mmap(struct file *file, struct vm_area_struct *vma)
+{
+   return afu_mmap(file, vma);
+}
+
+/**
+ * ocxlflash_fd_release() - release the context associated with the file
+ * @inode: File inode pointer.
+ * @file:  File associated with the adapter context.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ocxlflash_fd_release(struct inode *inode, struct file *file)
+{
+   return afu_release(inode, file);
 }
 
 /* Backend ops to ocxlflash services */
@@ -1284,4 +1308,6 @@ const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
.get_fd = ocxlflash_get_fd,
.fops_get_context   = ocxlflash_fops_get_context,
.start_work = ocxlflash_start_work,
+   .fd_mmap= ocxlflash_fd_mmap,
+   .fd_release = ocxlflash_fd_release,
 };
-- 
2.1.0



[PATCH 28/38] cxlflash: Support adapter context reading

2018-02-22 Thread Uma Krishnan
The cxlflash userspace API requires that users be able to read the adapter
context for any pending events or interrupts from the AFU. Support reading
various events by implementing the AFU read fop to copy out event data.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 94 +
 1 file changed, 94 insertions(+)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 3297934..e504dd2 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -17,9 +17,12 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
+#include 
+
 #include "backend.h"
 #include "ocxl_hw.h"
 
@@ -929,9 +932,99 @@ static unsigned int afu_poll(struct file *file, struct 
poll_table_struct *poll)
return mask;
 }
 
+/**
+ * afu_read() - perform a read on the context for any event
+ * @file:  File associated with the adapter context.
+ * @buf:   Buffer to receive the data.
+ * @count: Size of buffer (maximum bytes that can be read).
+ * @off:   Offset.
+ *
+ * Return: size of the data read on success, -errno on failure
+ */
+static ssize_t afu_read(struct file *file, char __user *buf, size_t count,
+   loff_t *off)
+{
+   struct ocxlflash_context *ctx = file->private_data;
+   struct device *dev = ctx->hw_afu->dev;
+   struct cxl_event event;
+   ulong lock_flags;
+   ssize_t esize;
+   ssize_t rc;
+   int bit;
+   DEFINE_WAIT(event_wait);
+
+   if (*off != 0) {
+   dev_err(dev, "%s: Non-zero offset not supported, off=%lld\n",
+   __func__, *off);
+   rc = -EINVAL;
+   goto out;
+   }
+
+   spin_lock_irqsave(>slock, lock_flags);
+
+   for (;;) {
+   prepare_to_wait(>wq, _wait, TASK_INTERRUPTIBLE);
+
+   if (ctx_event_pending(ctx))
+   break;
+
+   if (file->f_flags & O_NONBLOCK) {
+   dev_err(dev, "%s: File cannot be blocked on I/O\n",
+   __func__);
+   rc = -EAGAIN;
+   goto err;
+   }
+
+   if (signal_pending(current)) {
+   dev_err(dev, "%s: Signal pending on the process\n",
+   __func__);
+   rc = -ERESTARTSYS;
+   goto err;
+   }
+
+   spin_unlock_irqrestore(>slock, lock_flags);
+   schedule();
+   spin_lock_irqsave(>slock, lock_flags);
+   }
+
+   finish_wait(>wq, _wait);
+
+   memset(, 0, sizeof(event));
+   event.header.process_element = ctx->pe;
+   event.header.size = sizeof(struct cxl_event_header);
+   if (ctx->pending_irq) {
+   esize = sizeof(struct cxl_event_afu_interrupt);
+   event.header.size += esize;
+   event.header.type = CXL_EVENT_AFU_INTERRUPT;
+
+   bit = find_first_bit(>irq_bitmap, ctx->num_irqs);
+   clear_bit(bit, >irq_bitmap);
+   event.irq.irq = bit + 1;
+   if (bitmap_empty(>irq_bitmap, ctx->num_irqs))
+   ctx->pending_irq = false;
+   }
+
+   spin_unlock_irqrestore(>slock, lock_flags);
+
+   if (copy_to_user(buf, , event.header.size)) {
+   dev_err(dev, "%s: copy_to_user failed\n", __func__);
+   rc = -EFAULT;
+   goto out;
+   }
+
+   rc = event.header.size;
+out:
+   return rc;
+err:
+   finish_wait(>wq, _wait);
+   spin_unlock_irqrestore(>slock, lock_flags);
+   goto out;
+}
+
 static const struct file_operations ocxl_afu_fops = {
.owner  = THIS_MODULE,
.poll   = afu_poll,
+   .read   = afu_read,
 };
 
 #define PATCH_FOPS(NAME)   \
@@ -977,6 +1070,7 @@ static struct file *ocxlflash_get_fd(void *ctx_cookie,
/* Patch the file ops that are not defined */
if (fops) {
PATCH_FOPS(poll);
+   PATCH_FOPS(read);
} else /* Use default ops */
fops = (struct file_operations *)_afu_fops;
 
-- 
2.1.0



[PATCH 27/38] cxlflash: Support adapter context polling

2018-02-22 Thread Uma Krishnan
The cxlflash userspace API requires that users be able to poll the adapter
context for any pending events or interrupts from the AFU. Support polling
on various events by implementing the AFU poll fop using a waitqueue.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 57 +++--
 drivers/scsi/cxlflash/ocxl_hw.h |  2 ++
 2 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 4ca4a72..3297934 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 
@@ -452,6 +453,7 @@ static void *ocxlflash_dev_context_init(struct pci_dev 
*pdev, void *afu_cookie)
}
 
spin_lock_init(>slock);
+   init_waitqueue_head(>wq);
 
ctx->pe = rc;
ctx->master = false;
@@ -884,10 +886,57 @@ static void *ocxlflash_create_afu(struct pci_dev *pdev)
goto out;
 }
 
+/**
+ * ctx_event_pending() - check for any event pending on the context
+ * @ctx:   Context to be checked.
+ *
+ * Return: true if there is an event pending, false if none pending
+ */
+static inline bool ctx_event_pending(struct ocxlflash_context *ctx)
+{
+   if (ctx->pending_irq)
+   return true;
+
+   return false;
+}
+
+/**
+ * afu_poll() - poll the AFU for events on the context
+ * @file:  File associated with the adapter context.
+ * @poll:  Poll structure from the user.
+ *
+ * Return: poll mask
+ */
+static unsigned int afu_poll(struct file *file, struct poll_table_struct *poll)
+{
+   struct ocxlflash_context *ctx = file->private_data;
+   struct device *dev = ctx->hw_afu->dev;
+   ulong lock_flags;
+   int mask = 0;
+
+   poll_wait(file, >wq, poll);
+
+   spin_lock_irqsave(>slock, lock_flags);
+   if (ctx_event_pending(ctx))
+   mask |= POLLIN | POLLRDNORM;
+   else
+   mask |= POLLERR;
+   spin_unlock_irqrestore(>slock, lock_flags);
+
+   dev_dbg(dev, "%s: Poll wait completed for pe %i mask %i\n",
+   __func__, ctx->pe, mask);
+
+   return mask;
+}
+
 static const struct file_operations ocxl_afu_fops = {
.owner  = THIS_MODULE,
+   .poll   = afu_poll,
 };
 
+#define PATCH_FOPS(NAME)   \
+   do { if (!fops->NAME) fops->NAME = ocxl_afu_fops.NAME; } while (0)
+
 /**
  * ocxlflash_get_fd() - get file descriptor for an adapter context
  * @ctx_cookie:Adapter context.
@@ -925,8 +974,10 @@ static struct file *ocxlflash_get_fd(void *ctx_cookie,
}
fdtmp = rc;
 
-   /* Use default ops if there is no fops */
-   if (!fops)
+   /* Patch the file ops that are not defined */
+   if (fops) {
+   PATCH_FOPS(poll);
+   } else /* Use default ops */
fops = (struct file_operations *)_afu_fops;
 
name = kasprintf(GFP_KERNEL, "ocxlflash:%d", ctx->pe);
@@ -990,6 +1041,8 @@ static irqreturn_t ocxlflash_afu_irq(int irq, void *data)
set_bit(i - 1, >irq_bitmap);
ctx->pending_irq = true;
spin_unlock(>slock);
+
+   wake_up_all(>wq);
 out:
return IRQ_HANDLED;
 }
diff --git a/drivers/scsi/cxlflash/ocxl_hw.h b/drivers/scsi/cxlflash/ocxl_hw.h
index c7cbf67..bdf9422 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.h
+++ b/drivers/scsi/cxlflash/ocxl_hw.h
@@ -55,6 +55,8 @@ struct ocxlflash_context {
u64 psn_size;   /* Process mapping size */
 
spinlock_t slock;   /* Protects irq/fault/event updates */
+   wait_queue_head_t wq;   /* Wait queue for poll and interrupts */
+
struct ocxlflash_irqs *irqs;/* Pointer to array of structures */
int num_irqs;   /* Number of interrupts */
bool pending_irq;   /* Pending interrupt on the context */
-- 
2.1.0



[PATCH 25/38] cxlflash: Support AFU interrupt mapping and registration

2018-02-22 Thread Uma Krishnan
Add support to map and unmap the irq space and manage irq registrations
with the kernel for each allocated AFU interrupt. Also support mapping
the physical trigger page to obtain an effective address that will be
provided to the cxlflash core in a future commit.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 120 
 drivers/scsi/cxlflash/ocxl_hw.h |   2 +
 2 files changed, 122 insertions(+)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index acba10f..3b28c2a 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -186,6 +186,124 @@ static int ocxlflash_process_element(void *ctx_cookie)
 }
 
 /**
+ * afu_map_irq() - map the interrupt of the adapter context
+ * @flags: Flags.
+ * @ctx:   Adapter context.
+ * @num:   Per-context AFU interrupt number.
+ * @handler:   Interrupt handler to register.
+ * @cookie:Interrupt handler private data.
+ * @name:  Name of the interrupt.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int afu_map_irq(u64 flags, struct ocxlflash_context *ctx, int num,
+  irq_handler_t handler, void *cookie, char *name)
+{
+   struct ocxl_hw_afu *afu = ctx->hw_afu;
+   struct device *dev = afu->dev;
+   struct ocxlflash_irqs *irq;
+   void __iomem *vtrig;
+   u32 virq;
+   int rc = 0;
+
+   if (num < 0 || num >= ctx->num_irqs) {
+   dev_err(dev, "%s: Interrupt %d not allocated\n", __func__, num);
+   rc = -ENOENT;
+   goto out;
+   }
+
+   irq = >irqs[num];
+   virq = irq_create_mapping(NULL, irq->hwirq);
+   if (unlikely(!virq)) {
+   dev_err(dev, "%s: irq_create_mapping failed\n", __func__);
+   rc = -ENOMEM;
+   goto out;
+   }
+
+   rc = request_irq(virq, handler, 0, name, cookie);
+   if (unlikely(rc)) {
+   dev_err(dev, "%s: request_irq failed rc=%d\n", __func__, rc);
+   goto err1;
+   }
+
+   vtrig = ioremap(irq->ptrig, PAGE_SIZE);
+   if (unlikely(!vtrig)) {
+   dev_err(dev, "%s: Trigger page mapping failed\n", __func__);
+   rc = -ENOMEM;
+   goto err2;
+   }
+
+   irq->virq = virq;
+   irq->vtrig = vtrig;
+out:
+   return rc;
+err2:
+   free_irq(virq, cookie);
+err1:
+   irq_dispose_mapping(virq);
+   goto out;
+}
+
+/**
+ * ocxlflash_map_afu_irq() - map the interrupt of the adapter context
+ * @ctx_cookie:Adapter context.
+ * @num:   Per-context AFU interrupt number.
+ * @handler:   Interrupt handler to register.
+ * @cookie:Interrupt handler private data.
+ * @name:  Name of the interrupt.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ocxlflash_map_afu_irq(void *ctx_cookie, int num,
+irq_handler_t handler, void *cookie,
+char *name)
+{
+   return afu_map_irq(0, ctx_cookie, num, handler, cookie, name);
+}
+
+/**
+ * afu_unmap_irq() - unmap the interrupt
+ * @flags: Flags.
+ * @ctx:   Adapter context.
+ * @num:   Per-context AFU interrupt number.
+ * @cookie:Interrupt handler private data.
+ */
+static void afu_unmap_irq(u64 flags, struct ocxlflash_context *ctx, int num,
+ void *cookie)
+{
+   struct ocxl_hw_afu *afu = ctx->hw_afu;
+   struct device *dev = afu->dev;
+   struct ocxlflash_irqs *irq;
+
+   if (num < 0 || num >= ctx->num_irqs) {
+   dev_err(dev, "%s: Interrupt %d not allocated\n", __func__, num);
+   return;
+   }
+
+   irq = >irqs[num];
+   if (irq->vtrig)
+   iounmap(irq->vtrig);
+
+   if (irq_find_mapping(NULL, irq->hwirq)) {
+   free_irq(irq->virq, cookie);
+   irq_dispose_mapping(irq->virq);
+   }
+
+   memset(irq, 0, sizeof(*irq));
+}
+
+/**
+ * ocxlflash_unmap_afu_irq() - unmap the interrupt
+ * @ctx_cookie:Adapter context.
+ * @num:   Per-context AFU interrupt number.
+ * @cookie:Interrupt handler private data.
+ */
+static void ocxlflash_unmap_afu_irq(void *ctx_cookie, int num, void *cookie)
+{
+   return afu_unmap_irq(0, ctx_cookie, num, cookie);
+}
+
+/**
  * start_context() - local routine to start a context
  * @ctx:   Adapter context to be started.
  *
@@ -836,6 +954,8 @@ const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
.psa_map= ocxlflash_psa_map,
.psa_unmap  = ocxlflash_psa_unmap,
.process_element= ocxlflash_process_element,
+   .map_afu_irq= ocxlflash_map_afu_irq,
+   .unmap_afu_irq  = ocxlflash_unmap_afu_irq,
.start_context  = ocxlflash_start_context,
.stop_context   = ocxlflash_stop_context,
.set_master = 

[PATCH 21/38] cxlflash: Setup function OpenCXL link

2018-02-22 Thread Uma Krishnan
After reading and modifying the function configuration, setup the OpenCXL
link using the OCXL provider services. The link is released when the
adapter is unconfigured.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 25 ++---
 drivers/scsi/cxlflash/ocxl_hw.h |  1 +
 2 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 8dcb7aa..3a1ad61 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -412,11 +412,28 @@ static int ocxlflash_config_fn(struct pci_dev *pdev, 
struct ocxl_hw_afu *afu)
ocxl_config_set_actag(pdev, fcfg->dvsec_function_pos, base, enabled);
dev_dbg(dev, "%s: Function acTag range base=%u enabled=%u\n",
__func__, base, enabled);
+
+   rc = ocxl_link_setup(pdev, 0, >link_token);
+   if (unlikely(rc)) {
+   dev_err(dev, "%s: ocxl_link_setup failed rc=%d\n",
+   __func__, rc);
+   goto out;
+   }
 out:
return rc;
 }
 
 /**
+ * ocxlflash_unconfig_fn() - unconfigure the host function
+ * @pdev:  PCI device associated with the host.
+ * @afu:   AFU associated with the host.
+ */
+static void ocxlflash_unconfig_fn(struct pci_dev *pdev, struct ocxl_hw_afu 
*afu)
+{
+   ocxl_link_release(pdev, afu->link_token);
+}
+
+/**
  * ocxlflash_map_mmio() - map the AFU MMIO space
  * @afu: AFU associated with the host.
  *
@@ -552,7 +569,7 @@ static void *ocxlflash_create_afu(struct pci_dev *pdev)
if (unlikely(rc)) {
dev_err(dev, "%s: AFU configuration failed rc=%d\n",
__func__, rc);
-   goto err1;
+   goto err2;
}
 
ctx = ocxlflash_dev_context_init(pdev, afu);
@@ -560,15 +577,17 @@ static void *ocxlflash_create_afu(struct pci_dev *pdev)
rc = PTR_ERR(ctx);
dev_err(dev, "%s: ocxlflash_dev_context_init failed rc=%d\n",
__func__, rc);
-   goto err2;
+   goto err3;
}
 
idr_init(>idr);
afu->ocxl_ctx = ctx;
 out:
return afu;
-err2:
+err3:
ocxlflash_unconfig_afu(afu);
+err2:
+   ocxlflash_unconfig_fn(pdev, afu);
 err1:
kfree(afu);
afu = NULL;
diff --git a/drivers/scsi/cxlflash/ocxl_hw.h b/drivers/scsi/cxlflash/ocxl_hw.h
index 6912dd1..77c2550 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.h
+++ b/drivers/scsi/cxlflash/ocxl_hw.h
@@ -31,6 +31,7 @@ struct ocxl_hw_afu {
phys_addr_t gmmio_phys; /* Global AFU MMIO space */
void __iomem *gmmio_virt;   /* Global MMIO map */
 
+   void *link_token;   /* Link token for the SPA */
struct idr idr; /* IDR to manage contexts */
int max_pasid;  /* Maximum number of contexts */
 };
-- 
2.1.0



[PATCH 22/38] cxlflash: Setup OpenCXL transaction layer

2018-02-22 Thread Uma Krishnan
The first function of the link needs to configure the transaction layer
between the host and device. This is accomplished by a call to the OCXL
provider services.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 3a1ad61..74447f8 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -419,8 +419,18 @@ static int ocxlflash_config_fn(struct pci_dev *pdev, 
struct ocxl_hw_afu *afu)
__func__, rc);
goto out;
}
+
+   rc = ocxl_config_set_TL(pdev, fcfg->dvsec_tl_pos);
+   if (unlikely(rc)) {
+   dev_err(dev, "%s: ocxl_config_set_TL failed rc=%d\n",
+   __func__, rc);
+   goto err;
+   }
 out:
return rc;
+err:
+   ocxl_link_release(pdev, afu->link_token);
+   goto out;
 }
 
 /**
-- 
2.1.0



[PATCH 23/38] cxlflash: Support process element lifecycle

2018-02-22 Thread Uma Krishnan
As part of the context lifecycle, the associated process element within
the Shared Process Area (SPA) of the link must be updated. Each process
is defined by various parameters (pid, tid, PASID mm) that are stored in
the SPA upon starting a context and invalidated when a context is stopped.

Use the OCXL provider services to configure the SPA with the appropriate
data that is unique to the process when starting a context. Initially only
kernel contexts are supported and therefore these process values are not
applicable. Note that the OCXL service used has an optional callback for
translation fault error notification. While not used here, it will be
expanded in a future commit.

Also add a service to stop a context by terminating the corresponding
PASID and remove the process element from the SPA.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 52 +++--
 1 file changed, 50 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 74447f8..1dd679d 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -189,7 +189,7 @@ static int ocxlflash_process_element(void *ctx_cookie)
  * start_context() - local routine to start a context
  * @ctx:   Adapter context to be started.
  *
- * Assign the context specific MMIO space.
+ * Assign the context specific MMIO space, add and enable the PE.
  *
  * Return: 0 on success, -errno on failure
  */
@@ -197,7 +197,10 @@ static int start_context(struct ocxlflash_context *ctx)
 {
struct ocxl_hw_afu *afu = ctx->hw_afu;
struct ocxl_afu_config *acfg = >acfg;
+   void *link_token = afu->link_token;
+   struct device *dev = afu->dev;
bool master = ctx->master;
+   int rc = 0;
 
if (master) {
ctx->psn_size = acfg->global_mmio_size;
@@ -207,7 +210,16 @@ static int start_context(struct ocxlflash_context *ctx)
ctx->psn_phys = afu->ppmmio_phys + (ctx->pe * ctx->psn_size);
}
 
-   return 0;
+
+   /* pid, tid, amr and mm are zeroes/NULL for a kernel context */
+   rc = ocxl_link_add_pe(link_token, ctx->pe, 0, 0, 0, NULL, NULL, NULL);
+   if (unlikely(rc)) {
+   dev_err(dev, "%s: ocxl_link_add_pe failed rc=%d\n",
+   __func__, rc);
+   goto out;
+   }
+out:
+   return rc;
 }
 
 /**
@@ -224,6 +236,41 @@ static int ocxlflash_start_context(void *ctx_cookie)
 }
 
 /**
+ * ocxlflash_stop_context() - stop a context
+ * @ctx_cookie:Adapter context to be stopped.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ocxlflash_stop_context(void *ctx_cookie)
+{
+   struct ocxlflash_context *ctx = ctx_cookie;
+   struct ocxl_hw_afu *afu = ctx->hw_afu;
+   struct ocxl_afu_config *acfg = >acfg;
+   struct pci_dev *pdev = afu->pdev;
+   struct device *dev = afu->dev;
+   int rc;
+
+   rc = ocxl_config_terminate_pasid(pdev, acfg->dvsec_afu_control_pos,
+ctx->pe);
+   if (unlikely(rc)) {
+   dev_err(dev, "%s: ocxl_config_terminate_pasid failed rc=%d\n",
+   __func__, rc);
+   /* If EBUSY, PE could be referenced in future by the AFU */
+   if (rc == -EBUSY)
+   goto out;
+   }
+
+   rc = ocxl_link_remove_pe(afu->link_token, ctx->pe);
+   if (unlikely(rc)) {
+   dev_err(dev, "%s: ocxl_link_remove_pe failed rc=%d\n",
+   __func__, rc);
+   goto out;
+   }
+out:
+   return rc;
+}
+
+/**
  * ocxlflash_set_master() - sets the context as master
  * @ctx_cookie:Adapter context to set as master.
  */
@@ -688,6 +735,7 @@ const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
.psa_unmap  = ocxlflash_psa_unmap,
.process_element= ocxlflash_process_element,
.start_context  = ocxlflash_start_context,
+   .stop_context   = ocxlflash_stop_context,
.set_master = ocxlflash_set_master,
.get_context= ocxlflash_get_context,
.dev_context_init   = ocxlflash_dev_context_init,
-- 
2.1.0



[PATCH 24/38] cxlflash: Support AFU interrupt management

2018-02-22 Thread Uma Krishnan
Add support to allocate and free AFU interrupts using the OCXL provider
services. The trigger page returned upon successful allocation will be
mapped and exposed to the cxlflash core in a future commit.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 104 
 drivers/scsi/cxlflash/ocxl_hw.h |  10 
 2 files changed, 114 insertions(+)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 1dd679d..acba10f 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -385,6 +385,108 @@ static ssize_t ocxlflash_read_adapter_vpd(struct pci_dev 
*pdev, void *buf,
 }
 
 /**
+ * free_afu_irqs() - internal service to free interrupts
+ * @ctx:   Adapter context.
+ */
+static void free_afu_irqs(struct ocxlflash_context *ctx)
+{
+   struct ocxl_hw_afu *afu = ctx->hw_afu;
+   struct device *dev = afu->dev;
+   int i;
+
+   if (!ctx->irqs) {
+   dev_err(dev, "%s: Interrupts not allocated\n", __func__);
+   return;
+   }
+
+   for (i = ctx->num_irqs; i >= 0; i--)
+   ocxl_link_free_irq(afu->link_token, ctx->irqs[i].hwirq);
+
+   kfree(ctx->irqs);
+   ctx->irqs = NULL;
+}
+
+/**
+ * alloc_afu_irqs() - internal service to allocate interrupts
+ * @ctx:   Context associated with the request.
+ * @num:   Number of interrupts requested.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int alloc_afu_irqs(struct ocxlflash_context *ctx, int num)
+{
+   struct ocxl_hw_afu *afu = ctx->hw_afu;
+   struct device *dev = afu->dev;
+   struct ocxlflash_irqs *irqs;
+   u64 addr;
+   int rc = 0;
+   int hwirq;
+   int i;
+
+   if (ctx->irqs) {
+   dev_err(dev, "%s: Interrupts already allocated\n", __func__);
+   rc = -EEXIST;
+   goto out;
+   }
+
+   if (num > OCXL_MAX_IRQS) {
+   dev_err(dev, "%s: Too many interrupts num=%d\n", __func__, num);
+   rc = -EINVAL;
+   goto out;
+   }
+
+   irqs = kcalloc(num, sizeof(*irqs), GFP_KERNEL);
+   if (unlikely(!irqs)) {
+   dev_err(dev, "%s: Context irqs allocation failed\n", __func__);
+   rc = -ENOMEM;
+   goto out;
+   }
+
+   for (i = 0; i < num; i++) {
+   rc = ocxl_link_irq_alloc(afu->link_token, , );
+   if (unlikely(rc)) {
+   dev_err(dev, "%s: ocxl_link_irq_alloc failed rc=%d\n",
+   __func__, rc);
+   goto err;
+   }
+
+   irqs[i].hwirq = hwirq;
+   irqs[i].ptrig = addr;
+   }
+
+   ctx->irqs = irqs;
+   ctx->num_irqs = num;
+out:
+   return rc;
+err:
+   for (i = i-1; i >= 0; i--)
+   ocxl_link_free_irq(afu->link_token, irqs[i].hwirq);
+   kfree(irqs);
+   goto out;
+}
+
+/**
+ * ocxlflash_allocate_afu_irqs() - allocates the requested number of interrupts
+ * @ctx_cookie:Context associated with the request.
+ * @num:   Number of interrupts requested.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ocxlflash_allocate_afu_irqs(void *ctx_cookie, int num)
+{
+   return alloc_afu_irqs(ctx_cookie, num);
+}
+
+/**
+ * ocxlflash_free_afu_irqs() - frees the interrupts of an adapter context
+ * @ctx_cookie:Adapter context.
+ */
+static void ocxlflash_free_afu_irqs(void *ctx_cookie)
+{
+   free_afu_irqs(ctx_cookie);
+}
+
+/**
  * ocxlflash_unconfig_afu() - unconfigure the AFU
  * @afu: AFU associated with the host.
  */
@@ -742,6 +844,8 @@ const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
.release_context= ocxlflash_release_context,
.perst_reloads_same_image = ocxlflash_perst_reloads_same_image,
.read_adapter_vpd   = ocxlflash_read_adapter_vpd,
+   .allocate_afu_irqs  = ocxlflash_allocate_afu_irqs,
+   .free_afu_irqs  = ocxlflash_free_afu_irqs,
.create_afu = ocxlflash_create_afu,
.destroy_afu= ocxlflash_destroy_afu,
.get_fd = ocxlflash_get_fd,
diff --git a/drivers/scsi/cxlflash/ocxl_hw.h b/drivers/scsi/cxlflash/ocxl_hw.h
index 77c2550..c889368 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.h
+++ b/drivers/scsi/cxlflash/ocxl_hw.h
@@ -12,6 +12,13 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#define OCXL_MAX_IRQS  4   /* Max interrupts per process */
+
+struct ocxlflash_irqs {
+   int hwirq;
+   u64 ptrig;
+};
+
 /* OpenCXL hardware AFU associated with the host */
 struct ocxl_hw_afu {
struct ocxlflash_context *ocxl_ctx; /* Host context */
@@ -44,4 +51,7 @@ struct ocxlflash_context {
 
phys_addr_t psn_phys;   /* Process mapping */
u64 psn_size;   /* Process mapping size */
+
+   

[PATCH 20/38] cxlflash: Support reading adapter VPD data

2018-02-22 Thread Uma Krishnan
Use the PCI VPD services to support reading the VPD data of the
underlying adapter.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 7279f67..8dcb7aa 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -324,6 +324,20 @@ static void ocxlflash_perst_reloads_same_image(void 
*afu_cookie, bool image)
 }
 
 /**
+ * ocxlflash_read_adapter_vpd() - reads the adapter VPD
+ * @pdev:  PCI device associated with the host.
+ * @buf:   Buffer to get the VPD data.
+ * @count: Size of buffer (maximum bytes that can be read).
+ *
+ * Return: size of VPD on success, -errno on failure
+ */
+static ssize_t ocxlflash_read_adapter_vpd(struct pci_dev *pdev, void *buf,
+ size_t count)
+{
+   return pci_read_vpd(pdev, 0, count, buf);
+}
+
+/**
  * ocxlflash_unconfig_afu() - unconfigure the AFU
  * @afu: AFU associated with the host.
  */
@@ -650,6 +664,7 @@ const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
.dev_context_init   = ocxlflash_dev_context_init,
.release_context= ocxlflash_release_context,
.perst_reloads_same_image = ocxlflash_perst_reloads_same_image,
+   .read_adapter_vpd   = ocxlflash_read_adapter_vpd,
.create_afu = ocxlflash_create_afu,
.destroy_afu= ocxlflash_destroy_afu,
.get_fd = ocxlflash_get_fd,
-- 
2.1.0



[PATCH 19/38] cxlflash: Support AFU state toggling

2018-02-22 Thread Uma Krishnan
The AFU should be enabled following a successful configuration and
disabled near the end of the cleanup path.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 548438f..7279f67 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -342,12 +342,18 @@ static void ocxlflash_unconfig_afu(struct ocxl_hw_afu 
*afu)
 static void ocxlflash_destroy_afu(void *afu_cookie)
 {
struct ocxl_hw_afu *afu = afu_cookie;
+   int pos;
 
if (!afu)
return;
 
ocxlflash_release_context(afu->ocxl_ctx);
idr_destroy(>idr);
+
+   /* Disable the AFU */
+   pos = afu->acfg.dvsec_afu_control_pos;
+   ocxl_config_set_afu_state(afu->pdev, pos, 0);
+
ocxlflash_unconfig_afu(afu);
kfree(afu);
 }
@@ -492,6 +498,9 @@ static int ocxlflash_config_afu(struct pci_dev *pdev, 
struct ocxl_hw_afu *afu)
__func__, rc);
goto out;
}
+
+   /* Enable the AFU */
+   ocxl_config_set_afu_state(pdev, acfg->dvsec_afu_control_pos, 1);
 out:
return rc;
 }
-- 
2.1.0



[PATCH 18/38] cxlflash: Support process specific mappings

2018-02-22 Thread Uma Krishnan
Once the context is started, the assigned MMIO space can be mapped
and unmapped. Provide means to map and unmap the context MMIO space.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 7d92df0..548438f 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -151,6 +151,28 @@ static struct file *ocxlflash_getfile(struct device *dev, 
const char *name,
 }
 
 /**
+ * ocxlflash_psa_map() - map the process specific MMIO space
+ * @ctx_cookie:Adapter context for which the mapping needs to be done.
+ *
+ * Return: MMIO pointer of the mapped region
+ */
+static void __iomem *ocxlflash_psa_map(void *ctx_cookie)
+{
+   struct ocxlflash_context *ctx = ctx_cookie;
+
+   return ioremap(ctx->psn_phys, ctx->psn_size);
+}
+
+/**
+ * ocxlflash_psa_unmap() - unmap the process specific MMIO space
+ * @addr:  MMIO pointer to unmap.
+ */
+static void ocxlflash_psa_unmap(void __iomem *addr)
+{
+   iounmap(addr);
+}
+
+/**
  * ocxlflash_process_element() - get process element of the adapter context
  * @ctx_cookie:Adapter context associated with the process element.
  *
@@ -610,6 +632,8 @@ static void *ocxlflash_fops_get_context(struct file *file)
 /* Backend ops to ocxlflash services */
 const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
.module = THIS_MODULE,
+   .psa_map= ocxlflash_psa_map,
+   .psa_unmap  = ocxlflash_psa_unmap,
.process_element= ocxlflash_process_element,
.start_context  = ocxlflash_start_context,
.set_master = ocxlflash_set_master,
-- 
2.1.0



[PATCH 14/38] cxlflash: Support adapter context discovery

2018-02-22 Thread Uma Krishnan
Provide means to obtain the process element of an adapter context as well
as locate an adapter context by file.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index ee3702d..2dab547 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -151,6 +151,19 @@ static struct file *ocxlflash_getfile(struct device *dev, 
const char *name,
 }
 
 /**
+ * ocxlflash_process_element() - get process element of the adapter context
+ * @ctx_cookie:Adapter context associated with the process element.
+ *
+ * Return: process element of the adapter context
+ */
+static int ocxlflash_process_element(void *ctx_cookie)
+{
+   struct ocxlflash_context *ctx = ctx_cookie;
+
+   return ctx->pe;
+}
+
+/**
  * ocxlflash_set_master() - sets the context as master
  * @ctx_cookie:Adapter context to set as master.
  */
@@ -461,9 +474,21 @@ static struct file *ocxlflash_get_fd(void *ctx_cookie,
goto out;
 }
 
+/**
+ * ocxlflash_fops_get_context() - get the context associated with the file
+ * @file:  File associated with the adapter context.
+ *
+ * Return: pointer to the context
+ */
+static void *ocxlflash_fops_get_context(struct file *file)
+{
+   return file->private_data;
+}
+
 /* Backend ops to ocxlflash services */
 const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
.module = THIS_MODULE,
+   .process_element= ocxlflash_process_element,
.set_master = ocxlflash_set_master,
.get_context= ocxlflash_get_context,
.dev_context_init   = ocxlflash_dev_context_init,
@@ -471,4 +496,5 @@ const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
.create_afu = ocxlflash_create_afu,
.destroy_afu= ocxlflash_destroy_afu,
.get_fd = ocxlflash_get_fd,
+   .fops_get_context   = ocxlflash_fops_get_context,
 };
-- 
2.1.0



[PATCH 17/38] cxlflash: Support starting an adapter context

2018-02-22 Thread Uma Krishnan
Once the adapter context is created, it needs to be started by assigning
the MMIO space for the context and by enabling the process element in the
link. This commit adds the skeleton for starting the context and assigns
the context specific MMIO space. Master contexts have access to the global
MMIO space while the rest have access to the context specific space.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 39 +++
 drivers/scsi/cxlflash/ocxl_hw.h |  3 +++
 2 files changed, 42 insertions(+)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 824d789..7d92df0 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -164,6 +164,44 @@ static int ocxlflash_process_element(void *ctx_cookie)
 }
 
 /**
+ * start_context() - local routine to start a context
+ * @ctx:   Adapter context to be started.
+ *
+ * Assign the context specific MMIO space.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int start_context(struct ocxlflash_context *ctx)
+{
+   struct ocxl_hw_afu *afu = ctx->hw_afu;
+   struct ocxl_afu_config *acfg = >acfg;
+   bool master = ctx->master;
+
+   if (master) {
+   ctx->psn_size = acfg->global_mmio_size;
+   ctx->psn_phys = afu->gmmio_phys;
+   } else {
+   ctx->psn_size = acfg->pp_mmio_stride;
+   ctx->psn_phys = afu->ppmmio_phys + (ctx->pe * ctx->psn_size);
+   }
+
+   return 0;
+}
+
+/**
+ * ocxlflash_start_context() - start a kernel context
+ * @ctx_cookie:Adapter context to be started.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ocxlflash_start_context(void *ctx_cookie)
+{
+   struct ocxlflash_context *ctx = ctx_cookie;
+
+   return start_context(ctx);
+}
+
+/**
  * ocxlflash_set_master() - sets the context as master
  * @ctx_cookie:Adapter context to set as master.
  */
@@ -573,6 +611,7 @@ static void *ocxlflash_fops_get_context(struct file *file)
 const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
.module = THIS_MODULE,
.process_element= ocxlflash_process_element,
+   .start_context  = ocxlflash_start_context,
.set_master = ocxlflash_set_master,
.get_context= ocxlflash_get_context,
.dev_context_init   = ocxlflash_dev_context_init,
diff --git a/drivers/scsi/cxlflash/ocxl_hw.h b/drivers/scsi/cxlflash/ocxl_hw.h
index fbe9741..6912dd1 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.h
+++ b/drivers/scsi/cxlflash/ocxl_hw.h
@@ -40,4 +40,7 @@ struct ocxlflash_context {
struct address_space *mapping;  /* Mapping for pseudo filesystem */
bool master;/* Whether this is a master context */
int pe; /* Process element */
+
+   phys_addr_t psn_phys;   /* Process mapping */
+   u64 psn_size;   /* Process mapping size */
 };
-- 
2.1.0



[PATCH 11/38] cxlflash: Adapter context support for OpenCXL

2018-02-22 Thread Uma Krishnan
Add support to create and release the adapter contexts for OpenCXL and
provide means to specify certain contexts as a master.

The existing cxlflash core has a design requirement that each host will
have a single host context available by default. To satisfy this
requirement, one host adapter context is created when the hardware AFU is
initialized. This is returned by the get_context() fop.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 90 +
 drivers/scsi/cxlflash/ocxl_hw.h |  6 +++
 2 files changed, 96 insertions(+)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 677bc34..c5f5c81 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -18,6 +18,80 @@
 #include "ocxl_hw.h"
 
 /**
+ * ocxlflash_set_master() - sets the context as master
+ * @ctx_cookie:Adapter context to set as master.
+ */
+static void ocxlflash_set_master(void *ctx_cookie)
+{
+   struct ocxlflash_context *ctx = ctx_cookie;
+
+   ctx->master = true;
+}
+
+/**
+ * ocxlflash_get_context() - obtains the context associated with the host
+ * @pdev:  PCI device associated with the host.
+ * @afu_cookie:Hardware AFU associated with the host.
+ *
+ * Return: returns the pointer to host adapter context
+ */
+static void *ocxlflash_get_context(struct pci_dev *pdev, void *afu_cookie)
+{
+   struct ocxl_hw_afu *afu = afu_cookie;
+
+   return afu->ocxl_ctx;
+}
+
+/**
+ * ocxlflash_dev_context_init() - allocate and initialize an adapter context
+ * @pdev:  PCI device associated with the host.
+ * @afu_cookie:Hardware AFU associated with the host.
+ *
+ * Return: returns the adapter context on success, ERR_PTR on failure
+ */
+static void *ocxlflash_dev_context_init(struct pci_dev *pdev, void *afu_cookie)
+{
+   struct ocxl_hw_afu *afu = afu_cookie;
+   struct device *dev = afu->dev;
+   struct ocxlflash_context *ctx;
+   int rc;
+
+   ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+   if (unlikely(!ctx)) {
+   dev_err(dev, "%s: Context allocation failed\n", __func__);
+   rc = -ENOMEM;
+   goto err;
+   }
+
+   ctx->master = false;
+   ctx->hw_afu = afu;
+out:
+   return ctx;
+err:
+   ctx = ERR_PTR(rc);
+   goto out;
+}
+
+/**
+ * ocxlflash_release_context() - releases an adapter context
+ * @ctx_cookie:Adapter context to be released.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ocxlflash_release_context(void *ctx_cookie)
+{
+   struct ocxlflash_context *ctx = ctx_cookie;
+   int rc = 0;
+
+   if (!ctx)
+   goto out;
+
+   kfree(ctx);
+out:
+   return rc;
+}
+
+/**
  * ocxlflash_destroy_afu() - destroy the AFU structure
  * @afu_cookie:AFU to be freed.
  */
@@ -28,6 +102,7 @@ static void ocxlflash_destroy_afu(void *afu_cookie)
if (!afu)
return;
 
+   ocxlflash_release_context(afu->ocxl_ctx);
kfree(afu);
 }
 
@@ -127,6 +202,7 @@ static int ocxlflash_config_afu(struct pci_dev *pdev, 
struct ocxl_hw_afu *afu)
 static void *ocxlflash_create_afu(struct pci_dev *pdev)
 {
struct device *dev = >dev;
+   struct ocxlflash_context *ctx;
struct ocxl_hw_afu *afu;
int rc;
 
@@ -152,6 +228,16 @@ static void *ocxlflash_create_afu(struct pci_dev *pdev)
__func__, rc);
goto err1;
}
+
+   ctx = ocxlflash_dev_context_init(pdev, afu);
+   if (IS_ERR(ctx)) {
+   rc = PTR_ERR(ctx);
+   dev_err(dev, "%s: ocxlflash_dev_context_init failed rc=%d\n",
+   __func__, rc);
+   goto err1;
+   }
+
+   afu->ocxl_ctx = ctx;
 out:
return afu;
 err1:
@@ -163,6 +249,10 @@ static void *ocxlflash_create_afu(struct pci_dev *pdev)
 /* Backend ops to ocxlflash services */
 const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
.module = THIS_MODULE,
+   .set_master = ocxlflash_set_master,
+   .get_context= ocxlflash_get_context,
+   .dev_context_init   = ocxlflash_dev_context_init,
+   .release_context= ocxlflash_release_context,
.create_afu = ocxlflash_create_afu,
.destroy_afu= ocxlflash_destroy_afu,
 };
diff --git a/drivers/scsi/cxlflash/ocxl_hw.h b/drivers/scsi/cxlflash/ocxl_hw.h
index a807656..f78e5c9 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.h
+++ b/drivers/scsi/cxlflash/ocxl_hw.h
@@ -14,6 +14,7 @@
 
 /* OpenCXL hardware AFU associated with the host */
 struct ocxl_hw_afu {
+   struct ocxlflash_context *ocxl_ctx; /* Host context */
struct pci_dev *pdev;   /* PCI device */
struct device *dev; /* Generic device */
 
@@ -27,3 +28,8 @@ struct ocxl_hw_afu {
 
int max_pasid;  /* 

[PATCH 15/38] cxlflash: Support image reload policy modification

2018-02-22 Thread Uma Krishnan
On a PERST, the AFU image can be reloaded or left intact. Provide means to
set this image reload policy.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 13 +
 drivers/scsi/cxlflash/ocxl_hw.h |  1 +
 2 files changed, 14 insertions(+)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 2dab547..6f78e71 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -252,6 +252,18 @@ static int ocxlflash_release_context(void *ctx_cookie)
 }
 
 /**
+ * ocxlflash_perst_reloads_same_image() - sets the image reload policy
+ * @afu_cookie:Hardware AFU associated with the host.
+ * @image: Whether to load the same image on PERST.
+ */
+static void ocxlflash_perst_reloads_same_image(void *afu_cookie, bool image)
+{
+   struct ocxl_hw_afu *afu = afu_cookie;
+
+   afu->perst_same_image = image;
+}
+
+/**
  * ocxlflash_destroy_afu() - destroy the AFU structure
  * @afu_cookie:AFU to be freed.
  */
@@ -493,6 +505,7 @@ const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
.get_context= ocxlflash_get_context,
.dev_context_init   = ocxlflash_dev_context_init,
.release_context= ocxlflash_release_context,
+   .perst_reloads_same_image = ocxlflash_perst_reloads_same_image,
.create_afu = ocxlflash_create_afu,
.destroy_afu= ocxlflash_destroy_afu,
.get_fd = ocxlflash_get_fd,
diff --git a/drivers/scsi/cxlflash/ocxl_hw.h b/drivers/scsi/cxlflash/ocxl_hw.h
index 7f234b1..6d6e323 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.h
+++ b/drivers/scsi/cxlflash/ocxl_hw.h
@@ -17,6 +17,7 @@ struct ocxl_hw_afu {
struct ocxlflash_context *ocxl_ctx; /* Host context */
struct pci_dev *pdev;   /* PCI device */
struct device *dev; /* Generic device */
+   bool perst_same_image;  /* Same image loaded on perst */
 
struct ocxl_fn_config fcfg; /* DVSEC config of the function */
struct ocxl_afu_config acfg;/* AFU configuration data */
-- 
2.1.0



[PATCH 09/38] cxlflash: Setup AFU acTag range

2018-02-22 Thread Uma Krishnan
The OpenCXL specification supports distributing acTags amongst different
AFUs and functions on the link. As cxlflash devices are expected to only
support a single AFU and function, the entire range that was assigned to
the function is also assigned to the AFU.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 13 +
 drivers/scsi/cxlflash/ocxl_hw.h |  2 ++
 2 files changed, 15 insertions(+)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 8e48480..3875ed4 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -89,6 +89,9 @@ static int ocxlflash_config_afu(struct pci_dev *pdev, struct 
ocxl_hw_afu *afu)
struct ocxl_afu_config *acfg = >acfg;
struct ocxl_fn_config *fcfg = >fcfg;
struct device *dev = >dev;
+   int count;
+   int base;
+   int pos;
int rc = 0;
 
/* Read AFU config at index 0 */
@@ -98,6 +101,16 @@ static int ocxlflash_config_afu(struct pci_dev *pdev, 
struct ocxl_hw_afu *afu)
__func__, rc);
goto out;
}
+
+   /* Only one AFU per function is supported, so actag_base is same */
+   base = afu->fn_actag_base;
+   count = min_t(int, acfg->actag_supported, afu->fn_actag_enabled);
+   pos = acfg->dvsec_afu_control_pos;
+
+   ocxl_config_set_afu_actag(pdev, pos, base, count);
+   dev_dbg(dev, "%s: acTag base=%d enabled=%d\n", __func__, base, count);
+   afu->afu_actag_base = base;
+   afu->afu_actag_enabled = count;
 out:
return rc;
 }
diff --git a/drivers/scsi/cxlflash/ocxl_hw.h b/drivers/scsi/cxlflash/ocxl_hw.h
index 29fd338..a0ef04c 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.h
+++ b/drivers/scsi/cxlflash/ocxl_hw.h
@@ -22,4 +22,6 @@ struct ocxl_hw_afu {
 
int fn_actag_base;  /* Function acTag base */
int fn_actag_enabled;   /* Function acTag number enabled */
+   int afu_actag_base; /* AFU acTag base */
+   int afu_actag_enabled;  /* AFU acTag number enabled */
 };
-- 
2.1.0



[PATCH 12/38] cxlflash: Use IDR to manage adapter contexts

2018-02-22 Thread Uma Krishnan
A range of PASIDs are used as identifiers for the adapter contexts. These
contexts may be destroyed and created randomly. Use an IDR to keep track
of contexts that are in use and assign a unique identifier to new ones.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 20 ++--
 drivers/scsi/cxlflash/ocxl_hw.h |  2 ++
 2 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index c5f5c81..30db79d 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -12,6 +12,8 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#include 
+
 #include 
 
 #include "backend.h"
@@ -60,14 +62,25 @@ static void *ocxlflash_dev_context_init(struct pci_dev 
*pdev, void *afu_cookie)
if (unlikely(!ctx)) {
dev_err(dev, "%s: Context allocation failed\n", __func__);
rc = -ENOMEM;
-   goto err;
+   goto err1;
+   }
+
+   idr_preload(GFP_KERNEL);
+   rc = idr_alloc(>idr, ctx, 0, afu->max_pasid, GFP_NOWAIT);
+   idr_preload_end();
+   if (unlikely(rc < 0)) {
+   dev_err(dev, "%s: idr_alloc failed rc=%d\n", __func__, rc);
+   goto err2;
}
 
+   ctx->pe = rc;
ctx->master = false;
ctx->hw_afu = afu;
 out:
return ctx;
-err:
+err2:
+   kfree(ctx);
+err1:
ctx = ERR_PTR(rc);
goto out;
 }
@@ -86,6 +99,7 @@ static int ocxlflash_release_context(void *ctx_cookie)
if (!ctx)
goto out;
 
+   idr_remove(>hw_afu->idr, ctx->pe);
kfree(ctx);
 out:
return rc;
@@ -103,6 +117,7 @@ static void ocxlflash_destroy_afu(void *afu_cookie)
return;
 
ocxlflash_release_context(afu->ocxl_ctx);
+   idr_destroy(>idr);
kfree(afu);
 }
 
@@ -237,6 +252,7 @@ static void *ocxlflash_create_afu(struct pci_dev *pdev)
goto err1;
}
 
+   idr_init(>idr);
afu->ocxl_ctx = ctx;
 out:
return afu;
diff --git a/drivers/scsi/cxlflash/ocxl_hw.h b/drivers/scsi/cxlflash/ocxl_hw.h
index f78e5c9..49d5d08 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.h
+++ b/drivers/scsi/cxlflash/ocxl_hw.h
@@ -26,10 +26,12 @@ struct ocxl_hw_afu {
int afu_actag_base; /* AFU acTag base */
int afu_actag_enabled;  /* AFU acTag number enabled */
 
+   struct idr idr; /* IDR to manage contexts */
int max_pasid;  /* Maximum number of contexts */
 };
 
 struct ocxlflash_context {
struct ocxl_hw_afu *hw_afu; /* HW AFU back pointer */
bool master;/* Whether this is a master context */
+   int pe; /* Process element */
 };
-- 
2.1.0



[PATCH 10/38] cxlflash: Setup AFU PASID

2018-02-22 Thread Uma Krishnan
Per the OpenCXL specification, the maximum PASID supported by the AFU is
indicated by a field within the configuration space. Similar to acTags,
implementations can choose to use any sub-range of PASID within their
assigned range. For cxlflash, the entire range is used.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 3 +++
 drivers/scsi/cxlflash/ocxl_hw.h | 2 ++
 2 files changed, 5 insertions(+)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 3875ed4..677bc34 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -111,6 +111,9 @@ static int ocxlflash_config_afu(struct pci_dev *pdev, 
struct ocxl_hw_afu *afu)
dev_dbg(dev, "%s: acTag base=%d enabled=%d\n", __func__, base, count);
afu->afu_actag_base = base;
afu->afu_actag_enabled = count;
+   afu->max_pasid = 1 << acfg->pasid_supported_log;
+
+   ocxl_config_set_afu_pasid(pdev, pos, 0, acfg->pasid_supported_log);
 out:
return rc;
 }
diff --git a/drivers/scsi/cxlflash/ocxl_hw.h b/drivers/scsi/cxlflash/ocxl_hw.h
index a0ef04c..a807656 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.h
+++ b/drivers/scsi/cxlflash/ocxl_hw.h
@@ -24,4 +24,6 @@ struct ocxl_hw_afu {
int fn_actag_enabled;   /* Function acTag number enabled */
int afu_actag_base; /* AFU acTag base */
int afu_actag_enabled;  /* AFU acTag number enabled */
+
+   int max_pasid;  /* Maximum number of contexts */
 };
-- 
2.1.0



[PATCH 16/38] cxlflash: MMIO map the AFU

2018-02-22 Thread Uma Krishnan
When the AFU is configured, the global and per process MMIO regions
are presented by the configuration space. Save these regions and
map the global MMIO region that is used to access all of the control
and provisioning data in the AFU.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 74 -
 drivers/scsi/cxlflash/ocxl_hw.h |  4 +++
 2 files changed, 77 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 6f78e71..824d789 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -264,6 +264,18 @@ static void ocxlflash_perst_reloads_same_image(void 
*afu_cookie, bool image)
 }
 
 /**
+ * ocxlflash_unconfig_afu() - unconfigure the AFU
+ * @afu: AFU associated with the host.
+ */
+static void ocxlflash_unconfig_afu(struct ocxl_hw_afu *afu)
+{
+   if (afu->gmmio_virt) {
+   iounmap(afu->gmmio_virt);
+   afu->gmmio_virt = NULL;
+   }
+}
+
+/**
  * ocxlflash_destroy_afu() - destroy the AFU structure
  * @afu_cookie:AFU to be freed.
  */
@@ -276,6 +288,7 @@ static void ocxlflash_destroy_afu(void *afu_cookie)
 
ocxlflash_release_context(afu->ocxl_ctx);
idr_destroy(>idr);
+   ocxlflash_unconfig_afu(afu);
kfree(afu);
 }
 
@@ -324,6 +337,56 @@ static int ocxlflash_config_fn(struct pci_dev *pdev, 
struct ocxl_hw_afu *afu)
 }
 
 /**
+ * ocxlflash_map_mmio() - map the AFU MMIO space
+ * @afu: AFU associated with the host.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ocxlflash_map_mmio(struct ocxl_hw_afu *afu)
+{
+   struct ocxl_afu_config *acfg = >acfg;
+   struct pci_dev *pdev = afu->pdev;
+   struct device *dev = afu->dev;
+   phys_addr_t gmmio, ppmmio;
+   int rc = 0;
+
+   rc = pci_request_region(pdev, acfg->global_mmio_bar, "ocxlflash");
+   if (unlikely(rc)) {
+   dev_err(dev, "%s: pci_request_region for global failed rc=%d\n",
+   __func__, rc);
+   goto out;
+   }
+   gmmio = pci_resource_start(pdev, acfg->global_mmio_bar);
+   gmmio += acfg->global_mmio_offset;
+
+   rc = pci_request_region(pdev, acfg->pp_mmio_bar, "ocxlflash");
+   if (unlikely(rc)) {
+   dev_err(dev, "%s: pci_request_region for pp bar failed rc=%d\n",
+   __func__, rc);
+   goto err1;
+   }
+   ppmmio = pci_resource_start(pdev, acfg->pp_mmio_bar);
+   ppmmio += acfg->pp_mmio_offset;
+
+   afu->gmmio_virt = ioremap(gmmio, acfg->global_mmio_size);
+   if (unlikely(!afu->gmmio_virt)) {
+   dev_err(dev, "%s: MMIO mapping failed\n", __func__);
+   rc = -ENOMEM;
+   goto err2;
+   }
+
+   afu->gmmio_phys = gmmio;
+   afu->ppmmio_phys = ppmmio;
+out:
+   return rc;
+err2:
+   pci_release_region(pdev, acfg->pp_mmio_bar);
+err1:
+   pci_release_region(pdev, acfg->global_mmio_bar);
+   goto out;
+}
+
+/**
  * ocxlflash_config_afu() - configure the host AFU
  * @pdev:  PCI device associated with the host.
  * @afu:   AFU associated with the host.
@@ -362,6 +425,13 @@ static int ocxlflash_config_afu(struct pci_dev *pdev, 
struct ocxl_hw_afu *afu)
afu->max_pasid = 1 << acfg->pasid_supported_log;
 
ocxl_config_set_afu_pasid(pdev, pos, 0, acfg->pasid_supported_log);
+
+   rc = ocxlflash_map_mmio(afu);
+   if (unlikely(rc)) {
+   dev_err(dev, "%s: ocxlflash_map_mmio failed rc=%d\n",
+   __func__, rc);
+   goto out;
+   }
 out:
return rc;
 }
@@ -407,13 +477,15 @@ static void *ocxlflash_create_afu(struct pci_dev *pdev)
rc = PTR_ERR(ctx);
dev_err(dev, "%s: ocxlflash_dev_context_init failed rc=%d\n",
__func__, rc);
-   goto err1;
+   goto err2;
}
 
idr_init(>idr);
afu->ocxl_ctx = ctx;
 out:
return afu;
+err2:
+   ocxlflash_unconfig_afu(afu);
 err1:
kfree(afu);
afu = NULL;
diff --git a/drivers/scsi/cxlflash/ocxl_hw.h b/drivers/scsi/cxlflash/ocxl_hw.h
index 6d6e323..fbe9741 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.h
+++ b/drivers/scsi/cxlflash/ocxl_hw.h
@@ -27,6 +27,10 @@ struct ocxl_hw_afu {
int afu_actag_base; /* AFU acTag base */
int afu_actag_enabled;  /* AFU acTag number enabled */
 
+   phys_addr_t ppmmio_phys;/* Per process MMIO space */
+   phys_addr_t gmmio_phys; /* Global AFU MMIO space */
+   void __iomem *gmmio_virt;   /* Global MMIO map */
+
struct idr idr; /* IDR to manage contexts */
int max_pasid;  /* Maximum number of contexts */
 };
-- 
2.1.0



[PATCH 13/38] cxlflash: Support adapter file descriptors for OpenCXL

2018-02-22 Thread Uma Krishnan
Allocate a file descriptor for an adapter context when requested. In order
to allocate inodes for the file descriptors, a pseudo filesystem is created
and used.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 200 
 drivers/scsi/cxlflash/ocxl_hw.h |   1 +
 2 files changed, 201 insertions(+)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 30db79d..ee3702d 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -12,13 +12,144 @@
  * 2 of the License, or (at your option) any later version.
  */
 
+#include 
 #include 
+#include 
+#include 
 
 #include 
 
 #include "backend.h"
 #include "ocxl_hw.h"
 
+/*
+ * Pseudo-filesystem to allocate inodes.
+ */
+
+#define OCXLFLASH_FS_MAGIC  0x1697698f
+
+static int ocxlflash_fs_cnt;
+static struct vfsmount *ocxlflash_vfs_mount;
+
+static const struct dentry_operations ocxlflash_fs_dops = {
+   .d_dname= simple_dname,
+};
+
+/*
+ * ocxlflash_fs_mount() - mount the pseudo-filesystem
+ * @fs_type:   File system type.
+ * @flags: Flags for the filesystem.
+ * @dev_name:  Device name associated with the filesystem.
+ * @data:  Data pointer.
+ *
+ * Return: pointer to the directory entry structure
+ */
+static struct dentry *ocxlflash_fs_mount(struct file_system_type *fs_type,
+int flags, const char *dev_name,
+void *data)
+{
+   return mount_pseudo(fs_type, "ocxlflash:", NULL, _fs_dops,
+   OCXLFLASH_FS_MAGIC);
+}
+
+static struct file_system_type ocxlflash_fs_type = {
+   .name   = "ocxlflash",
+   .owner  = THIS_MODULE,
+   .mount  = ocxlflash_fs_mount,
+   .kill_sb= kill_anon_super,
+};
+
+/*
+ * ocxlflash_release_mapping() - release the memory mapping
+ * @ctx:   Context whose mapping is to be released.
+ */
+static void ocxlflash_release_mapping(struct ocxlflash_context *ctx)
+{
+   if (ctx->mapping)
+   simple_release_fs(_vfs_mount, _fs_cnt);
+   ctx->mapping = NULL;
+}
+
+/*
+ * ocxlflash_getfile() - allocate pseudo filesystem, inode, and the file
+ * @dev:   Generic device of the host.
+ * @name:  Name of the pseudo filesystem.
+ * @fops:  File operations.
+ * @priv:  Private data.
+ * @flags: Flags for the file.
+ *
+ * Return: pointer to the file on success, ERR_PTR on failure
+ */
+static struct file *ocxlflash_getfile(struct device *dev, const char *name,
+ const struct file_operations *fops,
+ void *priv, int flags)
+{
+   struct qstr this;
+   struct path path;
+   struct file *file;
+   struct inode *inode = NULL;
+   int rc;
+
+   if (fops->owner && !try_module_get(fops->owner)) {
+   dev_err(dev, "%s: Owner does not exist\n", __func__);
+   rc = -ENOENT;
+   goto err1;
+   }
+
+   rc = simple_pin_fs(_fs_type, _vfs_mount,
+  _fs_cnt);
+   if (unlikely(rc < 0)) {
+   dev_err(dev, "%s: Cannot mount ocxlflash pseudofs rc=%d\n",
+   __func__, rc);
+   goto err2;
+   }
+
+   inode = alloc_anon_inode(ocxlflash_vfs_mount->mnt_sb);
+   if (IS_ERR(inode)) {
+   rc = PTR_ERR(inode);
+   dev_err(dev, "%s: alloc_anon_inode failed rc=%d\n",
+   __func__, rc);
+   goto err3;
+   }
+
+   this.name = name;
+   this.len = strlen(name);
+   this.hash = 0;
+   path.dentry = d_alloc_pseudo(ocxlflash_vfs_mount->mnt_sb, );
+   if (!path.dentry) {
+   dev_err(dev, "%s: d_alloc_pseudo failed\n", __func__);
+   rc = -ENOMEM;
+   goto err4;
+   }
+
+   path.mnt = mntget(ocxlflash_vfs_mount);
+   d_instantiate(path.dentry, inode);
+
+   file = alloc_file(, OPEN_FMODE(flags), fops);
+   if (IS_ERR(file)) {
+   rc = PTR_ERR(file);
+   dev_err(dev, "%s: alloc_file failed rc=%d\n",
+   __func__, rc);
+   goto err5;
+   }
+
+   file->f_flags = flags & (O_ACCMODE | O_NONBLOCK);
+   file->private_data = priv;
+out:
+   return file;
+err5:
+   path_put();
+err4:
+   iput(inode);
+err3:
+   simple_release_fs(_vfs_mount, _fs_cnt);
+err2:
+   module_put(fops->owner);
+err1:
+   file = ERR_PTR(rc);
+   goto out;
+}
+
 /**
  * ocxlflash_set_master() - sets the context as master
  * @ctx_cookie:Adapter context to set as master.
@@ -75,6 +206,7 @@ static void *ocxlflash_dev_context_init(struct pci_dev 
*pdev, void *afu_cookie)
 
ctx->pe = rc;
ctx->master = false;
+   ctx->mapping = NULL;
ctx->hw_afu = afu;
 out:
return ctx;
@@ -100,6 

[PATCH 08/38] cxlflash: Read host AFU configuration

2018-02-22 Thread Uma Krishnan
The host AFU configuration is read on the initialization path to identify
the features and configuration of the AFU. This data is cached for use in
later configuration steps.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 34 ++
 drivers/scsi/cxlflash/ocxl_hw.h |  1 +
 2 files changed, 35 insertions(+)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index add2803..8e48480 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -76,6 +76,33 @@ static int ocxlflash_config_fn(struct pci_dev *pdev, struct 
ocxl_hw_afu *afu)
 }
 
 /**
+ * ocxlflash_config_afu() - configure the host AFU
+ * @pdev:  PCI device associated with the host.
+ * @afu:   AFU associated with the host.
+ *
+ * Must be called _after_ host function configuration.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ocxlflash_config_afu(struct pci_dev *pdev, struct ocxl_hw_afu *afu)
+{
+   struct ocxl_afu_config *acfg = >acfg;
+   struct ocxl_fn_config *fcfg = >fcfg;
+   struct device *dev = >dev;
+   int rc = 0;
+
+   /* Read AFU config at index 0 */
+   rc = ocxl_config_read_afu(pdev, fcfg, acfg, 0);
+   if (unlikely(rc)) {
+   dev_err(dev, "%s: ocxl_config_read_afu failed rc=%d\n",
+   __func__, rc);
+   goto out;
+   }
+out:
+   return rc;
+}
+
+/**
  * ocxlflash_create_afu() - create the AFU for OpenCXL
  * @pdev:  PCI device associated with the host.
  *
@@ -102,6 +129,13 @@ static void *ocxlflash_create_afu(struct pci_dev *pdev)
__func__, rc);
goto err1;
}
+
+   rc = ocxlflash_config_afu(pdev, afu);
+   if (unlikely(rc)) {
+   dev_err(dev, "%s: AFU configuration failed rc=%d\n",
+   __func__, rc);
+   goto err1;
+   }
 out:
return afu;
 err1:
diff --git a/drivers/scsi/cxlflash/ocxl_hw.h b/drivers/scsi/cxlflash/ocxl_hw.h
index 8c0a172..29fd338 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.h
+++ b/drivers/scsi/cxlflash/ocxl_hw.h
@@ -18,6 +18,7 @@ struct ocxl_hw_afu {
struct device *dev; /* Generic device */
 
struct ocxl_fn_config fcfg; /* DVSEC config of the function */
+   struct ocxl_afu_config acfg;/* AFU configuration data */
 
int fn_actag_base;  /* Function acTag base */
int fn_actag_enabled;   /* Function acTag number enabled */
-- 
2.1.0



[PATCH 07/38] cxlflash: Setup function acTag range

2018-02-22 Thread Uma Krishnan
The OpenCXL specification supports distributing acTags amongst different
AFUs and functions on the link. The platform-specific acTag range for the
link is obtained using the OCXL provider services and then assigned to the
host function based on implementation. For cxlflash devices only a single
function per host is expected and thus the entire range is assigned.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 15 +++
 drivers/scsi/cxlflash/ocxl_hw.h |  3 +++
 2 files changed, 18 insertions(+)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index a349ec6..add2803 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -42,6 +42,7 @@ static int ocxlflash_config_fn(struct pci_dev *pdev, struct 
ocxl_hw_afu *afu)
 {
struct ocxl_fn_config *fcfg = >fcfg;
struct device *dev = >dev;
+   u16 base, enabled, supported;
int rc = 0;
 
/* Read DVSEC config of the function */
@@ -56,6 +57,20 @@ static int ocxlflash_config_fn(struct pci_dev *pdev, struct 
ocxl_hw_afu *afu)
if (fcfg->max_afu_index != 0)
dev_warn(dev, "%s: Unexpected AFU index value %d\n",
 __func__, fcfg->max_afu_index);
+
+   rc = ocxl_config_get_actag_info(pdev, , , );
+   if (unlikely(rc)) {
+   dev_err(dev, "%s: ocxl_config_get_actag_info failed rc=%d\n",
+   __func__, rc);
+   goto out;
+   }
+
+   afu->fn_actag_base = base;
+   afu->fn_actag_enabled = enabled;
+
+   ocxl_config_set_actag(pdev, fcfg->dvsec_function_pos, base, enabled);
+   dev_dbg(dev, "%s: Function acTag range base=%u enabled=%u\n",
+   __func__, base, enabled);
 out:
return rc;
 }
diff --git a/drivers/scsi/cxlflash/ocxl_hw.h b/drivers/scsi/cxlflash/ocxl_hw.h
index 9c1b5347..8c0a172 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.h
+++ b/drivers/scsi/cxlflash/ocxl_hw.h
@@ -18,4 +18,7 @@ struct ocxl_hw_afu {
struct device *dev; /* Generic device */
 
struct ocxl_fn_config fcfg; /* DVSEC config of the function */
+
+   int fn_actag_base;  /* Function acTag base */
+   int fn_actag_enabled;   /* Function acTag number enabled */
 };
-- 
2.1.0



[PATCH 05/38] cxlflash: Hardware AFU for OpenCXL

2018-02-22 Thread Uma Krishnan
When an adapter is initialized, transport specific configuration and MMIO
mapping details need to be saved. For CXL, this data is managed by the
underlying kernel module. To maintain a separation between the cxlflash
core and underlying transports, introduce a new structure to store data
specific to an OpenCXL AFU.

Initially only the pointers to underlying PCI and generic devices are
added to this new structure - it will be expanded further in future
commits. Services to create and destroy this hardware AFU are added and
integrated in the probe and exit paths of the driver.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/backend.h |  1 +
 drivers/scsi/cxlflash/cxl_hw.c  |  6 ++
 drivers/scsi/cxlflash/main.c|  9 +++--
 drivers/scsi/cxlflash/ocxl_hw.c | 40 
 drivers/scsi/cxlflash/ocxl_hw.h | 19 +++
 5 files changed, 73 insertions(+), 2 deletions(-)
 create mode 100644 drivers/scsi/cxlflash/ocxl_hw.h

diff --git a/drivers/scsi/cxlflash/backend.h b/drivers/scsi/cxlflash/backend.h
index a60f051..f675bcb 100644
--- a/drivers/scsi/cxlflash/backend.h
+++ b/drivers/scsi/cxlflash/backend.h
@@ -36,6 +36,7 @@ struct cxlflash_backend_ops {
int (*allocate_afu_irqs)(void *ctx_cookie, int num);
void (*free_afu_irqs)(void *ctx_cookie);
void * (*create_afu)(struct pci_dev *dev);
+   void (*destroy_afu)(void *afu_cookie);
struct file * (*get_fd)(void *ctx_cookie, struct file_operations *fops,
int *fd);
void * (*fops_get_context)(struct file *file);
diff --git a/drivers/scsi/cxlflash/cxl_hw.c b/drivers/scsi/cxlflash/cxl_hw.c
index db1cada..a1d6d12 100644
--- a/drivers/scsi/cxlflash/cxl_hw.c
+++ b/drivers/scsi/cxlflash/cxl_hw.c
@@ -110,6 +110,11 @@ static void *cxlflash_create_afu(struct pci_dev *dev)
return cxl_pci_to_afu(dev);
 }
 
+static void cxlflash_destroy_afu(void *afu)
+{
+   /* Dummy fop for cxl */
+}
+
 static struct file *cxlflash_get_fd(void *ctx_cookie,
struct file_operations *fops, int *fd)
 {
@@ -160,6 +165,7 @@ const struct cxlflash_backend_ops cxlflash_cxl_ops = {
.allocate_afu_irqs  = cxlflash_allocate_afu_irqs,
.free_afu_irqs  = cxlflash_free_afu_irqs,
.create_afu = cxlflash_create_afu,
+   .destroy_afu= cxlflash_destroy_afu,
.get_fd = cxlflash_get_fd,
.fops_get_context   = cxlflash_fops_get_context,
.start_work = cxlflash_start_work,
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index b83a55a..5d754d1 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -971,6 +971,7 @@ static void cxlflash_remove(struct pci_dev *pdev)
case INIT_STATE_AFU:
term_afu(cfg);
case INIT_STATE_PCI:
+   cfg->ops->destroy_afu(cfg->afu_cookie);
pci_disable_device(pdev);
case INIT_STATE_NONE:
free_mem(cfg);
@@ -3689,8 +3690,6 @@ static int cxlflash_probe(struct pci_dev *pdev,
 
pci_set_drvdata(pdev, cfg);
 
-   cfg->afu_cookie = cfg->ops->create_afu(pdev);
-
rc = init_pci(cfg);
if (rc) {
dev_err(dev, "%s: init_pci failed rc=%d\n", __func__, rc);
@@ -3698,6 +3697,12 @@ static int cxlflash_probe(struct pci_dev *pdev,
}
cfg->init_state = INIT_STATE_PCI;
 
+   cfg->afu_cookie = cfg->ops->create_afu(pdev);
+   if (unlikely(!cfg->afu_cookie)) {
+   dev_err(dev, "%s: create_afu failed\n", __func__);
+   goto out_remove;
+   }
+
rc = init_afu(cfg);
if (rc && !wq_has_sleeper(>reset_waitq)) {
dev_err(dev, "%s: init_afu failed rc=%d\n", __func__, rc);
diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 58a3182..667cf77 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -15,8 +15,48 @@
 #include 
 
 #include "backend.h"
+#include "ocxl_hw.h"
+
+/**
+ * ocxlflash_destroy_afu() - destroy the AFU structure
+ * @afu_cookie:AFU to be freed.
+ */
+static void ocxlflash_destroy_afu(void *afu_cookie)
+{
+   struct ocxl_hw_afu *afu = afu_cookie;
+
+   if (!afu)
+   return;
+
+   kfree(afu);
+}
+
+/**
+ * ocxlflash_create_afu() - create the AFU for OpenCXL
+ * @pdev:  PCI device associated with the host.
+ *
+ * Return: AFU on success, NULL on failure
+ */
+static void *ocxlflash_create_afu(struct pci_dev *pdev)
+{
+   struct device *dev = >dev;
+   struct ocxl_hw_afu *afu;
+
+   afu = kzalloc(sizeof(*afu), GFP_KERNEL);
+   if (unlikely(!afu)) {
+   dev_err(dev, "%s: HW AFU allocation failed\n", __func__);
+   goto out;
+   }
+
+   afu->pdev = pdev;
+   afu->dev = dev;
+out:
+   return afu;
+}

[PATCH 06/38] cxlflash: Read host function configuration

2018-02-22 Thread Uma Krishnan
Per the OpenCXL specification, the underlying host can have multiple AFUs
per function with each function supporting its own configuration. The host
function configuration is read on the initialization path to evaluate the
number of functions present and identify the features and configuration of
the functions present. This data is cached for use in later configuration
steps. Note that for the OCXL hardware supported by the cxlflash driver,
only one AFU per function is expected.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/ocxl_hw.c | 41 +
 drivers/scsi/cxlflash/ocxl_hw.h |  2 ++
 2 files changed, 43 insertions(+)

diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 667cf77..a349ec6 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -32,6 +32,35 @@ static void ocxlflash_destroy_afu(void *afu_cookie)
 }
 
 /**
+ * ocxlflash_config_fn() - configure the host function
+ * @pdev:  PCI device associated with the host.
+ * @afu:   AFU associated with the host.
+ *
+ * Return: 0 on success, -errno on failure
+ */
+static int ocxlflash_config_fn(struct pci_dev *pdev, struct ocxl_hw_afu *afu)
+{
+   struct ocxl_fn_config *fcfg = >fcfg;
+   struct device *dev = >dev;
+   int rc = 0;
+
+   /* Read DVSEC config of the function */
+   rc = ocxl_config_read_function(pdev, fcfg);
+   if (unlikely(rc)) {
+   dev_err(dev, "%s: ocxl_config_read_function failed rc=%d\n",
+   __func__, rc);
+   goto out;
+   }
+
+   /* Only one AFU per function is supported by ocxlflash */
+   if (fcfg->max_afu_index != 0)
+   dev_warn(dev, "%s: Unexpected AFU index value %d\n",
+__func__, fcfg->max_afu_index);
+out:
+   return rc;
+}
+
+/**
  * ocxlflash_create_afu() - create the AFU for OpenCXL
  * @pdev:  PCI device associated with the host.
  *
@@ -41,6 +70,7 @@ static void *ocxlflash_create_afu(struct pci_dev *pdev)
 {
struct device *dev = >dev;
struct ocxl_hw_afu *afu;
+   int rc;
 
afu = kzalloc(sizeof(*afu), GFP_KERNEL);
if (unlikely(!afu)) {
@@ -50,8 +80,19 @@ static void *ocxlflash_create_afu(struct pci_dev *pdev)
 
afu->pdev = pdev;
afu->dev = dev;
+
+   rc = ocxlflash_config_fn(pdev, afu);
+   if (unlikely(rc)) {
+   dev_err(dev, "%s: Function configuration failed rc=%d\n",
+   __func__, rc);
+   goto err1;
+   }
 out:
return afu;
+err1:
+   kfree(afu);
+   afu = NULL;
+   goto out;
 }
 
 /* Backend ops to ocxlflash services */
diff --git a/drivers/scsi/cxlflash/ocxl_hw.h b/drivers/scsi/cxlflash/ocxl_hw.h
index 57eb53b..9c1b5347 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.h
+++ b/drivers/scsi/cxlflash/ocxl_hw.h
@@ -16,4 +16,6 @@
 struct ocxl_hw_afu {
struct pci_dev *pdev;   /* PCI device */
struct device *dev; /* Generic device */
+
+   struct ocxl_fn_config fcfg; /* DVSEC config of the function */
 };
-- 
2.1.0



[PATCH 04/38] cxlflash: Introduce OpenCXL backend

2018-02-22 Thread Uma Krishnan
Add initial infrastructure to support a new cxlflash transport, OpenCXL.

Claim a dependency on OpenCXL (OCXL) and add a new file, ocxl_hw.c, which
will host the backend routines that are specific to OpenCXL.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/Kconfig   |  2 +-
 drivers/scsi/cxlflash/Makefile  |  2 +-
 drivers/scsi/cxlflash/backend.h |  1 +
 drivers/scsi/cxlflash/ocxl_hw.c | 22 ++
 4 files changed, 25 insertions(+), 2 deletions(-)
 create mode 100644 drivers/scsi/cxlflash/ocxl_hw.c

diff --git a/drivers/scsi/cxlflash/Kconfig b/drivers/scsi/cxlflash/Kconfig
index a011c5d..e2a3a1b 100644
--- a/drivers/scsi/cxlflash/Kconfig
+++ b/drivers/scsi/cxlflash/Kconfig
@@ -4,7 +4,7 @@
 
 config CXLFLASH
tristate "Support for IBM CAPI Flash"
-   depends on PCI && SCSI && CXL && EEH
+   depends on PCI && SCSI && CXL && OCXL && EEH
select IRQ_POLL
default m
help
diff --git a/drivers/scsi/cxlflash/Makefile b/drivers/scsi/cxlflash/Makefile
index 7ec3f6b..5124c68 100644
--- a/drivers/scsi/cxlflash/Makefile
+++ b/drivers/scsi/cxlflash/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_CXLFLASH) += cxlflash.o
-cxlflash-y += main.o superpipe.o lunmgt.o vlun.o cxl_hw.o
+cxlflash-y += main.o superpipe.o lunmgt.o vlun.o cxl_hw.o ocxl_hw.o
diff --git a/drivers/scsi/cxlflash/backend.h b/drivers/scsi/cxlflash/backend.h
index 7b72149..a60f051 100644
--- a/drivers/scsi/cxlflash/backend.h
+++ b/drivers/scsi/cxlflash/backend.h
@@ -13,6 +13,7 @@
  */
 
 extern const struct cxlflash_backend_ops cxlflash_cxl_ops;
+extern const struct cxlflash_backend_ops cxlflash_ocxl_ops;
 
 struct cxlflash_backend_ops {
struct module *module;
diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
new file mode 100644
index 000..58a3182
--- /dev/null
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -0,0 +1,22 @@
+/*
+ * CXL Flash Device Driver
+ *
+ * Written by: Matthew R. Ochs , IBM Corporation
+ * Uma Krishnan , IBM Corporation
+ *
+ * Copyright (C) 2018 IBM Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include 
+
+#include "backend.h"
+
+/* Backend ops to ocxlflash services */
+const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
+   .module = THIS_MODULE,
+};
-- 
2.1.0



[PATCH 02/38] cxlflash: Avoid clobbering context control register value

2018-02-22 Thread Uma Krishnan
From: "Matthew R. Ochs" 

The SISLite specification originally defined the context control
register with a single field of bits to represent the LISN and
also stipulated that the register reset value be 0. The cxlflash
driver took advantage of this when programming the LISN for the
master contexts via an unconditional write - no other bits were
preserved.

When unmap support was added, SISLite was updated to define bit
0 of the context control register as a way for the AFU to notify
the context owner that unmap operations were supported. Thus the
assumptions under which the register is setup changed and the
existing unconditional write is clobbering the unmap state for
master contexts. This is presently not an issue due to the order
in which the context control register is programmed in relation to
the unmap bit being queried but should be addressed to avoid a
future regression in the event this code is moved elsewhere.

To remedy this issue, preserve the bits when programming the LISN
field in the context control register. Since the LISN will now be
programmed using a read value, assert that the initial state of the
LISN field is as described in SISLite (0).

Signed-off-by: Matthew R. Ochs 
Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/main.c| 5 -
 drivers/scsi/cxlflash/sislite.h | 1 +
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 3d3e003..b83a55a 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -1303,7 +1303,10 @@ static void afu_err_intr_init(struct afu *afu)
for (i = 0; i < afu->num_hwqs; i++) {
hwq = get_hwq(afu, i);
 
-   writeq_be(SISL_MSI_SYNC_ERROR, >host_map->ctx_ctrl);
+   reg = readq_be(>host_map->ctx_ctrl);
+   WARN_ON((reg & SISL_CTX_CTRL_LISN_MASK) != 0);
+   reg |= SISL_MSI_SYNC_ERROR;
+   writeq_be(reg, >host_map->ctx_ctrl);
writeq_be(SISL_ISTATUS_MASK, >host_map->intr_mask);
}
 }
diff --git a/drivers/scsi/cxlflash/sislite.h b/drivers/scsi/cxlflash/sislite.h
index bedf1ce..d8940f1 100644
--- a/drivers/scsi/cxlflash/sislite.h
+++ b/drivers/scsi/cxlflash/sislite.h
@@ -284,6 +284,7 @@ struct sisl_host_map {
__be64 cmd_room;
__be64 ctx_ctrl;/* least significant byte or b56:63 is LISN# */
 #define SISL_CTX_CTRL_UNMAP_SECTOR 0x8000ULL /* b0 */
+#define SISL_CTX_CTRL_LISN_MASK(0xFFULL)
__be64 mbox_w;  /* restricted use */
__be64 sq_start;/* Submission Queue (R/W): write sequence and */
__be64 sq_end;  /* inclusion semantics are the same as RRQ*/
-- 
2.1.0



[PATCH 03/38] cxlflash: Add argument identifier names

2018-02-22 Thread Uma Krishnan
Checkpatch throws a warning when the argument identifier names are not
included in the function definitions.

To avoid these warnings, argument identifiers are added in the existing
function definitions.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/backend.h | 47 ++---
 drivers/scsi/cxlflash/common.h  |  4 ++--
 2 files changed, 27 insertions(+), 24 deletions(-)

diff --git a/drivers/scsi/cxlflash/backend.h b/drivers/scsi/cxlflash/backend.h
index 339e42b..7b72149 100644
--- a/drivers/scsi/cxlflash/backend.h
+++ b/drivers/scsi/cxlflash/backend.h
@@ -16,26 +16,29 @@ extern const struct cxlflash_backend_ops cxlflash_cxl_ops;
 
 struct cxlflash_backend_ops {
struct module *module;
-   void __iomem * (*psa_map)(void *);
-   void (*psa_unmap)(void __iomem *);
-   int (*process_element)(void *);
-   int (*map_afu_irq)(void *, int, irq_handler_t, void *, char *);
-   void (*unmap_afu_irq)(void *, int, void *);
-   int (*start_context)(void *);
-   int (*stop_context)(void *);
-   int (*afu_reset)(void *);
-   void (*set_master)(void *);
-   void * (*get_context)(struct pci_dev *, void *);
-   void * (*dev_context_init)(struct pci_dev *, void *);
-   int (*release_context)(void *);
-   void (*perst_reloads_same_image)(void *, bool);
-   ssize_t (*read_adapter_vpd)(struct pci_dev *, void *, size_t);
-   int (*allocate_afu_irqs)(void *, int);
-   void (*free_afu_irqs)(void *);
-   void * (*create_afu)(struct pci_dev *);
-   struct file * (*get_fd)(void *, struct file_operations *, int *);
-   void * (*fops_get_context)(struct file *);
-   int (*start_work)(void *, u64);
-   int (*fd_mmap)(struct file *, struct vm_area_struct *);
-   int (*fd_release)(struct inode *, struct file *);
+   void __iomem * (*psa_map)(void *ctx_cookie);
+   void (*psa_unmap)(void __iomem *addr);
+   int (*process_element)(void *ctx_cookie);
+   int (*map_afu_irq)(void *ctx_cookie, int num, irq_handler_t handler,
+  void *cookie, char *name);
+   void (*unmap_afu_irq)(void *ctx_cookie, int num, void *cookie);
+   int (*start_context)(void *ctx_cookie);
+   int (*stop_context)(void *ctx_cookie);
+   int (*afu_reset)(void *ctx_cookie);
+   void (*set_master)(void *ctx_cookie);
+   void * (*get_context)(struct pci_dev *dev, void *afu_cookie);
+   void * (*dev_context_init)(struct pci_dev *dev, void *afu_cookie);
+   int (*release_context)(void *ctx_cookie);
+   void (*perst_reloads_same_image)(void *afu_cookie, bool image);
+   ssize_t (*read_adapter_vpd)(struct pci_dev *dev, void *buf,
+   size_t count);
+   int (*allocate_afu_irqs)(void *ctx_cookie, int num);
+   void (*free_afu_irqs)(void *ctx_cookie);
+   void * (*create_afu)(struct pci_dev *dev);
+   struct file * (*get_fd)(void *ctx_cookie, struct file_operations *fops,
+   int *fd);
+   void * (*fops_get_context)(struct file *file);
+   int (*start_work)(void *ctx_cookie, u64 irqs);
+   int (*fd_mmap)(struct file *file, struct vm_area_struct *vm);
+   int (*fd_release)(struct inode *inode, struct file *file);
 };
diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h
index 5d7ca01..d7fccea 100644
--- a/drivers/scsi/cxlflash/common.h
+++ b/drivers/scsi/cxlflash/common.h
@@ -232,8 +232,8 @@ struct hwq {
 
 struct afu {
struct hwq hwqs[CXLFLASH_MAX_HWQS];
-   int (*send_cmd)(struct afu *, struct afu_cmd *);
-   int (*context_reset)(struct hwq *);
+   int (*send_cmd)(struct afu *afu, struct afu_cmd *cmd);
+   int (*context_reset)(struct hwq *hwq);
 
/* AFU HW */
struct cxlflash_afu_map __iomem *afu_map;   /* entire MMIO map */
-- 
2.1.0



[PATCH 01/38] cxlflash: Preserve number of interrupts for master contexts

2018-02-22 Thread Uma Krishnan
The number of interrupts requested for user contexts are stored in the
context specific structures and utilized to manage the interrupts. For the
master contexts, this number is only used once and therefore not saved.

To prepare for future commits where the number of interrupts will be
required in more than one place, preserve the value in the master context
structure.

Signed-off-by: Uma Krishnan 
---
 drivers/scsi/cxlflash/common.h |  1 +
 drivers/scsi/cxlflash/main.c   | 11 ---
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/cxlflash/common.h b/drivers/scsi/cxlflash/common.h
index 102fd26..5d7ca01 100644
--- a/drivers/scsi/cxlflash/common.h
+++ b/drivers/scsi/cxlflash/common.h
@@ -211,6 +211,7 @@ struct hwq {
struct sisl_ctrl_map __iomem *ctrl_map; /* MC control map */
ctx_hndl_t ctx_hndl;/* master's context handle */
u32 index;  /* Index of this hwq */
+   int num_irqs;   /* Numer of interrupts requested for context */
struct list_head pending_cmds;  /* Commands pending completion */
 
atomic_t hsq_credits;
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index d8fe7ab8..3d3e003 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -1911,7 +1911,7 @@ static enum undo_level init_intr(struct cxlflash_cfg *cfg,
int rc = 0;
enum undo_level level = UNDO_NOOP;
bool is_primary_hwq = (hwq->index == PRIMARY_HWQ);
-   int num_irqs = is_primary_hwq ? 3 : 2;
+   int num_irqs = hwq->num_irqs;
 
rc = cfg->ops->allocate_afu_irqs(ctx, num_irqs);
if (unlikely(rc)) {
@@ -1965,16 +1965,20 @@ static int init_mc(struct cxlflash_cfg *cfg, u32 index)
struct device *dev = >dev->dev;
struct hwq *hwq = get_hwq(cfg->afu, index);
int rc = 0;
+   int num_irqs;
enum undo_level level;
 
hwq->afu = cfg->afu;
hwq->index = index;
INIT_LIST_HEAD(>pending_cmds);
 
-   if (index == PRIMARY_HWQ)
+   if (index == PRIMARY_HWQ) {
ctx = cfg->ops->get_context(cfg->dev, cfg->afu_cookie);
-   else
+   num_irqs = 3;
+   } else {
ctx = cfg->ops->dev_context_init(cfg->dev, cfg->afu_cookie);
+   num_irqs = 2;
+   }
if (IS_ERR_OR_NULL(ctx)) {
rc = -ENOMEM;
goto err1;
@@ -1982,6 +1986,7 @@ static int init_mc(struct cxlflash_cfg *cfg, u32 index)
 
WARN_ON(hwq->ctx_cookie);
hwq->ctx_cookie = ctx;
+   hwq->num_irqs = num_irqs;
 
/* Set it up as a master with the CXL */
cfg->ops->set_master(ctx);
-- 
2.1.0



[PATCH 00/38] cxlflash: OpenCXL transport support

2018-02-22 Thread Uma Krishnan
This patch series adds OpenCXL support to the cxlflash driver. With
this support, new devices using the OpenCXL transport will be supported
by the cxlflash driver along with the existing CXL devices. An effort is
made to keep this transport specific function independent of the existing
core driver that communicates with the AFU.

The first three patches contain a minor fix and staging improvements.

This series is intended for 4.17 and is bisectable.

Matthew R. Ochs (1):
  cxlflash: Avoid clobbering context control register value

Uma Krishnan (37):
  cxlflash: Preserve number of interrupts for master contexts
  cxlflash: Add argument identifier names
  cxlflash: Introduce OpenCXL backend
  cxlflash: Hardware AFU for OpenCXL
  cxlflash: Read host function configuration
  cxlflash: Setup function acTag range
  cxlflash: Read host AFU configuration
  cxlflash: Setup AFU acTag range
  cxlflash: Setup AFU PASID
  cxlflash: Adapter context support for OpenCXL
  cxlflash: Use IDR to manage adapter contexts
  cxlflash: Support adapter file descriptors for OpenCXL
  cxlflash: Support adapter context discovery
  cxlflash: Support image reload policy modification
  cxlflash: MMIO map the AFU
  cxlflash: Support starting an adapter context
  cxlflash: Support process specific mappings
  cxlflash: Support AFU state toggling
  cxlflash: Support reading adapter VPD data
  cxlflash: Setup function OpenCXL link
  cxlflash: Setup OpenCXL transaction layer
  cxlflash: Support process element lifecycle
  cxlflash: Support AFU interrupt management
  cxlflash: Support AFU interrupt mapping and registration
  cxlflash: Support starting user contexts
  cxlflash: Support adapter context polling
  cxlflash: Support adapter context reading
  cxlflash: Support adapter context mmap and release
  cxlflash: Support file descriptor mapping
  cxlflash: Introduce object handle fop
  cxlflash: Setup LISNs for user contexts
  cxlflash: Setup LISNs for master contexts
  cxlflash: Update synchronous interrupt status bits
  cxlflash: Introduce OCXL context state machine
  cxlflash: Register for translation errors
  cxlflash: Support AFU reset
  cxlflash: Enable OpenCXL operations

 drivers/scsi/cxlflash/Kconfig |2 +-
 drivers/scsi/cxlflash/Makefile|2 +-
 drivers/scsi/cxlflash/backend.h   |   50 +-
 drivers/scsi/cxlflash/common.h|   10 +-
 drivers/scsi/cxlflash/cxl_hw.c|   13 +
 drivers/scsi/cxlflash/main.c  |   55 +-
 drivers/scsi/cxlflash/main.h  |1 +
 drivers/scsi/cxlflash/ocxl_hw.c   | 1428 +
 drivers/scsi/cxlflash/ocxl_hw.h   |   76 ++
 drivers/scsi/cxlflash/sislite.h   |   41 +-
 drivers/scsi/cxlflash/superpipe.c |   14 +
 11 files changed, 1644 insertions(+), 48 deletions(-)
 create mode 100644 drivers/scsi/cxlflash/ocxl_hw.c
 create mode 100644 drivers/scsi/cxlflash/ocxl_hw.h

-- 
2.1.0



[PATCH] libsas: Fix kernel-doc headers

2018-02-22 Thread Bart Van Assche
Avoid that building with W=1 causes the kernel-doc tool to complain
about function arguments that have not been documented in the libsas
kernel-doc headers. Avoid that the short description starts with a
hyphen by changing "--" into "-" in the first line of the kernel-doc
headers.

Signed-off-by: Bart Van Assche 
Cc: John Garry 
---

v2: addressed John Garry's feedback

 drivers/scsi/libsas/sas_ata.c  |  2 +-
 drivers/scsi/libsas/sas_discover.c | 13 +++--
 drivers/scsi/libsas/sas_expander.c | 29 +++--
 drivers/scsi/libsas/sas_init.c |  2 +-
 drivers/scsi/libsas/sas_port.c |  5 +++--
 5 files changed, 27 insertions(+), 24 deletions(-)

diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c
index 2b3637b40dde..0cc1567eacc1 100644
--- a/drivers/scsi/libsas/sas_ata.c
+++ b/drivers/scsi/libsas/sas_ata.c
@@ -709,7 +709,7 @@ void sas_resume_sata(struct asd_sas_port *port)
 }
 
 /**
- * sas_discover_sata -- discover an STP/SATA domain device
+ * sas_discover_sata - discover an STP/SATA domain device
  * @dev: pointer to struct domain_device of interest
  *
  * Devices directly attached to a HA port, have no parents.  All other
diff --git a/drivers/scsi/libsas/sas_discover.c 
b/drivers/scsi/libsas/sas_discover.c
index e4fd078e4175..a0fa7ef3a071 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -55,7 +55,7 @@ void sas_init_dev(struct domain_device *dev)
 /* -- Domain device discovery -- */
 
 /**
- * sas_get_port_device -- Discover devices which caused port creation
+ * sas_get_port_device - Discover devices which caused port creation
  * @port: pointer to struct sas_port of interest
  *
  * Devices directly attached to a HA port, have no parent.  This is
@@ -278,8 +278,8 @@ static void sas_resume_devices(struct work_struct *work)
 }
 
 /**
- * sas_discover_end_dev -- discover an end device (SSP, etc)
- * @end: pointer to domain device of interest
+ * sas_discover_end_dev - discover an end device (SSP, etc)
+ * @dev: pointer to domain device of interest
  *
  * See comment in sas_discover_sata().
  */
@@ -428,8 +428,8 @@ void sas_device_set_phy(struct domain_device *dev, struct 
sas_port *port)
 /* -- Discovery and Revalidation -- */
 
 /**
- * sas_discover_domain -- discover the domain
- * @port: port to the domain of interest
+ * sas_discover_domain - discover the domain
+ * @work: work structure embedded in port domain device.
  *
  * NOTE: this process _must_ quit (return) as soon as any connection
  * errors are encountered.  Connection recovery is done elsewhere.
@@ -572,7 +572,8 @@ int sas_discover_event(struct asd_sas_port *port, enum 
discover_event ev)
 }
 
 /**
- * sas_init_disc -- initialize the discovery struct in the port
+ * sas_init_disc - initialize the discovery struct in the port
+ * @disc: port discovery structure
  * @port: pointer to struct port
  *
  * Called when the ports are being initialized.
diff --git a/drivers/scsi/libsas/sas_expander.c 
b/drivers/scsi/libsas/sas_expander.c
index 6a4f8198b78e..8b7114348def 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -1170,9 +1170,9 @@ static int sas_check_level_subtractive_boundary(struct 
domain_device *dev)
return 0;
 }
 /**
- * sas_ex_discover_devices -- discover devices attached to this expander
- * dev: pointer to the expander domain device
- * single: if you want to do a single phy, else set to -1;
+ * sas_ex_discover_devices - discover devices attached to this expander
+ * @dev: pointer to the expander domain device
+ * @single: if you want to do a single phy, else set to -1;
  *
  * Configure this expander for use with its devices and register the
  * devices of this expander.
@@ -1528,10 +1528,11 @@ static int sas_configure_phy(struct domain_device *dev, 
int phy_id,
 }
 
 /**
- * sas_configure_parent -- configure routing table of parent
- * parent: parent expander
- * child: child expander
- * sas_addr: SAS port identifier of device directly attached to child
+ * sas_configure_parent - configure routing table of parent
+ * @parent: parent expander
+ * @child: child expander
+ * @sas_addr: SAS port identifier of device directly attached to child
+ * @include: whether or not to include @child in the expander routing table
  */
 static int sas_configure_parent(struct domain_device *parent,
struct domain_device *child,
@@ -1570,9 +1571,9 @@ static int sas_configure_parent(struct domain_device 
*parent,
 }
 
 /**
- * sas_configure_routing -- configure routing
- * dev: expander device
- * sas_addr: port identifier of device directly attached to the expander device
+ * sas_configure_routing - configure routing
+ * @dev: expander device
+ * @sas_addr: port identifier of device directly attached to the expander 
device
  */
 static int sas_configure_routing(struct domain_device *dev, 

Re: [PATCH] libsas: Fix kernel-doc headers

2018-02-22 Thread Bart Van Assche
On Wed, 2018-02-14 at 16:29 +, John Garry wrote:
> On 13/02/2018 17:49, Bart Van Assche wrote:
> > On 02/13/18 02:17, John Garry wrote:
> > > On 12/02/2018 18:45, Bart Van Assche wrote:
> > > > -/**
> > > > +/*
> > > >   * sas_configure_parent -- configure routing table of parent
> > > > - * parent: parent expander
> > > > - * child: child expander
> > > > - * sas_addr: SAS port identifier of device directly attached to child
> > > > + * @parent: parent expander
> > > > + * @child: child expander
> > > > + * @sas_addr: SAS port identifier of device directly attached to child
> > > 
> > > and no mention of @include here
> > 
> > Also for the 'include' argument, a suggestion of how to document it
> > would be welcome.
> 
> To be honest, I am not so fimilar with this specific part of the code.
> 
> As I see, the @include argument is to flag whether we want to setup or 
> tear down a routing for parent (upstream) expander device.

Thanks for the feedback. I will have a look at the SAS spec to see what the
meaning of this parameter is.

Bart.




[PATCH v2] Avoid that ATA error handling can trigger a kernel hang or oops

2018-02-22 Thread Bart Van Assche
Avoid that the recently introduced call_rcu() call in the SCSI core
triggers a double call_rcu() call.

Reported-by: Natanael Copa 
Reported-by: Damien Le Moal 
References: https://bugzilla.kernel.org/show_bug.cgi?id=198861
Fixes: 3bd6f43f5cb3 ("scsi: core: Ensure that the SCSI error handler gets woken 
up")
Signed-off-by: Bart Van Assche 
Cc: Natanael Copa 
Cc: Damien Le Moal 
Cc: Alexandre Oliva 
Cc: Pavel Tikhomirov 
Cc: Hannes Reinecke 
Cc: Johannes Thumshirn 
Cc: 
---
 drivers/scsi/hosts.c  | 3 ---
 drivers/scsi/scsi_error.c | 5 +++--
 drivers/scsi/scsi_lib.c   | 2 ++
 include/scsi/scsi_cmnd.h  | 3 +++
 include/scsi/scsi_host.h  | 2 --
 5 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index a0a7e4ff255c..7279d3d2e941 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -334,8 +334,6 @@ static void scsi_host_dev_release(struct device *dev)
if (shost->work_q)
destroy_workqueue(shost->work_q);
 
-   destroy_rcu_head(>rcu);
-
if (shost->shost_state == SHOST_CREATED) {
/*
 * Free the shost_dev device name here if scsi_host_alloc()
@@ -404,7 +402,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template 
*sht, int privsize)
INIT_LIST_HEAD(>starved_list);
init_waitqueue_head(>host_wait);
mutex_init(>scan_mutex);
-   init_rcu_head(>rcu);
 
index = ida_simple_get(_index_ida, 0, 0, GFP_KERNEL);
if (index < 0)
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 96f988a7efda..9b0242f84407 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -229,7 +229,8 @@ static void scsi_eh_reset(struct scsi_cmnd *scmd)
 
 static void scsi_eh_inc_host_failed(struct rcu_head *head)
 {
-   struct Scsi_Host *shost = container_of(head, typeof(*shost), rcu);
+   struct scsi_cmnd *scmd = container_of(head, typeof(*scmd), rcu);
+   struct Scsi_Host *shost = scmd->device->host;
unsigned long flags;
 
spin_lock_irqsave(shost->host_lock, flags);
@@ -265,7 +266,7 @@ void scsi_eh_scmd_add(struct scsi_cmnd *scmd)
 * Ensure that all tasks observe the host state change before the
 * host_failed change.
 */
-   call_rcu(>rcu, scsi_eh_inc_host_failed);
+   call_rcu(>rcu, scsi_eh_inc_host_failed);
 }
 
 /**
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index aea5a1ae318b..e1ca2160aa40 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -671,6 +671,7 @@ static bool scsi_end_request(struct request *req, 
blk_status_t error,
if (!blk_rq_is_scsi(req)) {
WARN_ON_ONCE(!(cmd->flags & SCMD_INITIALIZED));
cmd->flags &= ~SCMD_INITIALIZED;
+   destroy_rcu_head(>rcu);
}
 
if (req->mq_ctx) {
@@ -1151,6 +1152,7 @@ static void scsi_initialize_rq(struct request *rq)
struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq);
 
scsi_req_init(>req);
+   init_rcu_head(>rcu);
cmd->jiffies_at_alloc = jiffies;
cmd->retries = 0;
 }
diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h
index d8d4a902a88d..2280b2351739 100644
--- a/include/scsi/scsi_cmnd.h
+++ b/include/scsi/scsi_cmnd.h
@@ -68,6 +68,9 @@ struct scsi_cmnd {
struct list_head list;  /* scsi_cmnd participates in queue lists */
struct list_head eh_entry; /* entry for the host eh_cmd_q */
struct delayed_work abort_work;
+
+   struct rcu_head rcu;
+
int eh_eflags;  /* Used by error handlr */
 
/*
diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h
index 19317585ae48..7aedb6776b4f 100644
--- a/include/scsi/scsi_host.h
+++ b/include/scsi/scsi_host.h
@@ -577,8 +577,6 @@ struct Scsi_Host {
struct blk_mq_tag_set   tag_set;
};
 
-   struct rcu_head rcu;
-
atomic_t host_busy;/* commands actually active on 
low-level */
atomic_t host_blocked;
 
-- 
2.16.2



[GIT PULL] SCSI fixes for 4.16-rc2

2018-02-22 Thread James Bottomley
These are mostly fixes for problems with merge window code.  In
addition we have one doc update (alua) and two dead code removals
(aiclib and octogon) a spurious assignment removal (csiostor) and a
performance improvement for storvsc involving better interrupt
spreading and increasing the command per lun handling.

[fixup over previous pull to drop one of the storvsc patches]

The patch is available here:

git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git scsi-fixes

The short changelog is:

Andrew Vasquez (1):
  scsi: qedi: Fix truncation of CHAP name and secret

Bart Van Assche (3):
  scsi: qla2xxx: Fix a locking imbalance in qlt_24xx_handle_els()
  scsi: scsi_dh: Document alua_rtpg_queue() arguments
  scsi: qla2xxx: Avoid triggering undefined behavior in 
qla2x00_mbx_completion()

Chad Dupuis (1):
  scsi: bnx2fc: Fix check in SCSI completion handler for timed out request

Colin Ian King (1):
  scsi: csiostor: remove redundant assignment to pointer 'ln'

Corentin Labbe (2):
  scsi: Remove Makefile entry for oktagon files
  scsi: aic7xxx: remove aiclib.c

Dan Carpenter (2):
  scsi: mptfusion: Add bounds check in mptctl_hp_targetinfo()
  scsi: sym53c8xx_2: iterator underflow in sym_getsync()

Himanshu Madhani (1):
  scsi: qla2xxx: Fix incorrect handle for abort IOCB

Manish Rangankar (1):
  scsi: qla4xxx: skip error recovery in case of register disconnect.

Meelis Roos (1):
  scsi: aacraid: fix shutdown crash when init fails

Michael Kelley (EOSG) (1):
  scsi: storvsc: Increase cmd_per_lun for higher speed devices

Nilesh Javali (1):
  scsi: qedi: Cleanup local str variable

Quinn Tran (2):
  scsi: qla2xxx: Fix double free bug after firmware timeout
  scsi: qla2xxx: Fix memory corruption during hba reset test

Sujit Reddy Thumma (1):
  scsi: ufs: Enable quirk to ignore sending WRITE_SAME command

Tomas Henzl (1):
  scsi: mpt3sas: fix an out of bound write

Tyrel Datwyler (1):
  scsi: ibmvfc: fix misdefined reserved field in ibmvfc_fcp_rsp_info

And the diffstat:

 drivers/message/fusion/mptctl.c|  2 ++
 drivers/scsi/Makefile  |  1 -
 drivers/scsi/aacraid/linit.c   |  4 ++-
 drivers/scsi/aic7xxx/aiclib.c  | 34 --
 drivers/scsi/bnx2fc/bnx2fc_io.c|  1 +
 drivers/scsi/csiostor/csio_lnode.c |  2 +-
 drivers/scsi/device_handler/scsi_dh_alua.c |  5 +++
 drivers/scsi/ibmvscsi/ibmvfc.h |  2 +-
 drivers/scsi/mpt3sas/mpt3sas_base.c|  5 ++-
 drivers/scsi/qedi/qedi_main.c  | 55 ++
 drivers/scsi/qla2xxx/qla_init.c| 23 ++---
 drivers/scsi/qla2xxx/qla_iocb.c|  7 ++--
 drivers/scsi/qla2xxx/qla_isr.c |  6 ++--
 drivers/scsi/qla2xxx/qla_os.c  |  2 ++
 drivers/scsi/qla2xxx/qla_target.c  |  2 --
 drivers/scsi/qla4xxx/ql4_def.h |  2 ++
 drivers/scsi/qla4xxx/ql4_os.c  | 46 +
 drivers/scsi/storvsc_drv.c |  2 +-
 drivers/scsi/sym53c8xx_2/sym_hipd.c|  2 +-
 drivers/scsi/ufs/ufshcd.c  |  2 ++
 20 files changed, 107 insertions(+), 98 deletions(-)
 delete mode 100644 drivers/scsi/aic7xxx/aiclib.c

With full diff below.

James

---

diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c
index 8d12017b9893..4470630dd545 100644
--- a/drivers/message/fusion/mptctl.c
+++ b/drivers/message/fusion/mptctl.c
@@ -2687,6 +2687,8 @@ mptctl_hp_targetinfo(unsigned long arg)
__FILE__, __LINE__, iocnum);
return -ENODEV;
}
+   if (karg.hdr.id >= MPT_MAX_FC_DEVICES)
+   return -EINVAL;
dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_hp_targetinfo 
called.\n",
ioc->name));
 
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index fcfd28d2884c..de1b3fce936d 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -185,7 +185,6 @@ ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \
 CFLAGS_ncr53c8xx.o := $(ncr53c8xx-flags-y) $(ncr53c8xx-flags-m)
 zalon7xx-objs  := zalon.o ncr53c8xx.o
 NCR_Q720_mod-objs  := NCR_Q720.o ncr53c8xx.o
-oktagon_esp_mod-objs   := oktagon_esp.o oktagon_io.o
 
 # Files generated that shall be removed upon make clean
 clean-files := 53c700_d.h 53c700_u.h
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index ad6ec573cc87..b730e8edb8b3 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -1690,8 +1690,10 @@ static int aac_probe_one(struct pci_dev *pdev, const 
struct pci_device_id *id)
 *  Map in the registers from the adapter.
 */
aac->base_size = AAC_MIN_FOOTPRINT_SIZE;
-   if ((*aac_drivers[index].init)(aac))
+   if ((*aac_drivers[index].init)(aac)) {
+   error = -ENODEV;
goto out_unmap;
+   }
 

Re: [PATCH v2] scsi: qla2xxx: Use dma_pool_zalloc()

2018-02-22 Thread Himanshu Madhani


On Wed, 14 Feb 2018, 12:10pm, Souptick Joarder wrote:

> Use dma_pool_zalloc() instead of dma_pool_alloc + memset
> 
> Signed-off-by: Souptick Joarder 
> ---
> 
> v2: Remove extra line and comment
> 
>  drivers/scsi/qla2xxx/qla_bsg.c|  3 +--
>  drivers/scsi/qla2xxx/qla_iocb.c   | 10 ++
>  drivers/scsi/qla2xxx/qla_target.c |  7 +--
>  3 files changed, 4 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
> index e2d5d3c..c11a89b 100644
> --- a/drivers/scsi/qla2xxx/qla_bsg.c
> +++ b/drivers/scsi/qla2xxx/qla_bsg.c
> @@ -1035,7 +1035,7 @@
>   sg_copy_to_buffer(bsg_job->request_payload.sg_list,
>   bsg_job->request_payload.sg_cnt, fw_buf, data_len);
> 
> - mn = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL, _dma);
> + mn = dma_pool_zalloc(ha->s_dma_pool, GFP_KERNEL, _dma);
>   if (!mn) {
>   ql_log(ql_log_warn, vha, 0x7036,
>   "DMA alloc failed for fw buffer.\n");
> @@ -1046,7 +1046,6 @@
>   flag = bsg_request->rqst_data.h_vendor.vendor_cmd[1];
>   fw_ver = le32_to_cpu(*((uint32_t *)((uint32_t *)fw_buf + 2)));
> 
> - memset(mn, 0, sizeof(struct access_chip_84xx));
>   mn->entry_type = VERIFY_CHIP_IOCB_TYPE;
>   mn->entry_count = 1;
> 
> diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
> index 1b62e94..1796866 100644
> --- a/drivers/scsi/qla2xxx/qla_iocb.c
> +++ b/drivers/scsi/qla2xxx/qla_iocb.c
> @@ -1203,7 +1203,6 @@ struct fw_dif_context {
>   uint32_tdif_bytes;
>   uint8_t bundling = 1;
>   uint16_tblk_size;
> - uint8_t *clr_ptr;
>   struct crc_context  *crc_ctx_pkt = NULL;
>   struct qla_hw_data  *ha;
>   uint8_t additional_fcpcdb_len;
> @@ -1245,15 +1244,11 @@ struct fw_dif_context {
> 
>   /* Allocate CRC context from global pool */
>   crc_ctx_pkt = sp->u.scmd.ctx =
> - dma_pool_alloc(ha->dl_dma_pool, GFP_ATOMIC, _ctx_dma);
> + dma_pool_zalloc(ha->dl_dma_pool, GFP_ATOMIC, _ctx_dma);
> 
>   if (!crc_ctx_pkt)
>   goto crc_queuing_error;
> 
> - /* Zero out CTX area. */
> - clr_ptr = (uint8_t *)crc_ctx_pkt;
> - memset(clr_ptr, 0, sizeof(*crc_ctx_pkt));
> -
>   crc_ctx_pkt->crc_ctx_dma = crc_ctx_dma;
> 
>   sp->flags |= SRB_CRC_CTX_DMA_VALID;
> @@ -3067,7 +3062,7 @@ struct fw_dif_context {
>   }
> 
>   memset(ctx, 0, sizeof(struct ct6_dsd));
> - ctx->fcp_cmnd = dma_pool_alloc(ha->fcp_cmnd_dma_pool,
> + ctx->fcp_cmnd = dma_pool_zalloc(ha->fcp_cmnd_dma_pool,
>   GFP_ATOMIC, >fcp_cmnd_dma);
>   if (!ctx->fcp_cmnd) {
>   ql_log(ql_log_fatal, vha, 0x3011,
> @@ -3120,7 +3115,6 @@ struct fw_dif_context {
>   host_to_fcp_swap((uint8_t *)_pkt->lun, 
> sizeof(cmd_pkt->lun));
> 
>   /* build FCP_CMND IU */
> - memset(ctx->fcp_cmnd, 0, sizeof(struct fcp_cmnd));
>   int_to_scsilun(cmd->device->lun, >fcp_cmnd->lun);
>   ctx->fcp_cmnd->additional_cdb_len = additional_cdb_len;
> 
> diff --git a/drivers/scsi/qla2xxx/qla_target.c 
> b/drivers/scsi/qla2xxx/qla_target.c
> index fc89af8..3b52bcd 100644
> --- a/drivers/scsi/qla2xxx/qla_target.c
> +++ b/drivers/scsi/qla2xxx/qla_target.c
> @@ -2871,7 +2871,6 @@ static void qlt_24xx_init_ctio_to_isp(struct 
> ctio7_to_24xx *ctio,
>   uint32_tdata_bytes;
>   uint32_tdif_bytes;
>   uint8_t bundling = 1;
> - uint8_t *clr_ptr;
>   struct crc_context  *crc_ctx_pkt = NULL;
>   struct qla_hw_data  *ha;
>   struct ctio_crc2_to_fw  *pkt;
> @@ -3000,15 +2999,11 @@ static void qlt_24xx_init_ctio_to_isp(struct 
> ctio7_to_24xx *ctio,
> 
>   /* Allocate CRC context from global pool */
>   crc_ctx_pkt = cmd->ctx =
> - dma_pool_alloc(ha->dl_dma_pool, GFP_ATOMIC, _ctx_dma);
> + dma_pool_zalloc(ha->dl_dma_pool, GFP_ATOMIC, _ctx_dma);
> 
>   if (!crc_ctx_pkt)
>   goto crc_queuing_error;
> 
> - /* Zero out CTX area. */
> - clr_ptr = (uint8_t *)crc_ctx_pkt;
> - memset(clr_ptr, 0, sizeof(*crc_ctx_pkt));
> -
>   crc_ctx_pkt->crc_ctx_dma = crc_ctx_dma;
>   INIT_LIST_HEAD(_ctx_pkt->dsd_list);
> 
> --
> 1.9.1
> 
> 

Looks Good. 

Acked-by: Himanshu Madhani 

Thanks,
Himanshu


hpsa crashes on boot in 4.16-rc2-00062

2018-02-22 Thread Meelis Roos
This happens on a HP DL360 G6 with Smart Array 410i.

Will try to bisect.

IO completion timeout could be because of some IRQ toubles?

(sorry, the rest has scrolled away in ilo2 textcons)

[  242.655025] Call Trace:  
[  242.655077]  ? __schedule+0x1dd/0x5e0
[  242.655130]  schedule+0x23/0x70  
[  242.655182]  schedule_timeout+0xe1/0x290 
[  242.655236]  io_schedule_timeout+0x14/0x40   
[  242.655290]  wait_for_completion_io+0xa4/0x120   
[  242.655346]  ? wake_up_q+0x70/0x70   
[  242.655401]  hpsa_scsi_do_simple_cmd+0xa7/0xf0   
[  242.655456]  hpsa_scsi_do_simple_cmd_with_retry+0x4a/0x150   
[  242.655512]  hpsa_scsi_do_inquiry+0x5d/0xc0  
[  242.655567]  hpsa_scan_start+0xf67/0x1fa0
[  242.655621]  ? sched_clock_local+0x12/0x80   
[  242.655675]  ? sched_clock_local+0x12/0x80   
[  242.655729]  ? select_idle_sibling+0x21/0x3b0
[  242.655785]  ? do_scsi_scan_host+0x2d/0x90   
[  242.655839]  do_scsi_scan_host+0x2d/0x90 
[  242.655892]  do_scan_async+0x12/0x180
[  242.655945]  async_run_entry_fn+0x2c/0x140   
[  242.656002]  process_one_work+0x1a6/0x320
[  242.656062]  worker_thread+0x26/0x3c0
[  242.656115]  ? create_worker+0x190/0x190 
[  242.656170]  kthread+0x107/0x120 
[  242.656222]  ? kthread_create_worker_on_cpu+0x70/0x70
[  242.656278]  ret_from_fork+0x35/0x40  


-- 
Meelis Roos (mr...@linux.ee)


Re: [PATCH 3/3] qla2xxx: ensure async flags are reset correctly

2018-02-22 Thread Himanshu Madhani


On Thu, 22 Feb 2018, 12:49am, Hannes Reinecke wrote:

> The fcport flags FCF_ASYNC_ACTIVE and FCF_ASYNC_SENT are used
> to throttle the state machine, so we need to ensure to always
> set and unset them correctly. Not doing so will lead to the
> state machine getting confused and no login attempt into
> remote ports.
> 
> Cc: Quinn Tran 
> Cc: Himanshu Madhani 
> Fixes: 3dbec59bdf63 ("scsi: qla2xxx: Prevent multiple active discovery 
> commands per session")
> Signed-off-by: Hannes Reinecke 
> ---
>  drivers/scsi/qla2xxx/qla_gs.c   |  2 ++
>  drivers/scsi/qla2xxx/qla_init.c | 13 ++---
>  2 files changed, 12 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
> index e4d404c24506..3cb05c1bd7bf 100644
> --- a/drivers/scsi/qla2xxx/qla_gs.c
> +++ b/drivers/scsi/qla2xxx/qla_gs.c
> @@ -3177,6 +3177,7 @@ int qla24xx_async_gidpn(scsi_qla_host_t *vha, fc_port_t 
> *fcport)
>   sp->free(sp);
>   fcport->flags &= ~FCF_ASYNC_SENT;
>  done:
> + fcport->flags &= ~FCF_ASYNC_ACTIVE;
>   return rval;
>  }
>  
> @@ -3368,6 +3369,7 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t 
> *fcport)
>   sp->free(sp);
>   fcport->flags &= ~FCF_ASYNC_SENT;
>  done:
> + fcport->flags &= ~FCF_ASYNC_ACTIVE;
>   return rval;
>  }
>  
> diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
> index a19ed53ba6d9..df31c396d206 100644
> --- a/drivers/scsi/qla2xxx/qla_init.c
> +++ b/drivers/scsi/qla2xxx/qla_init.c
> @@ -228,6 +228,7 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t 
> *fcport,
>   sp->free(sp);
>   fcport->flags &= ~FCF_ASYNC_SENT;
>  done:
> + fcport->flags &= ~FCF_ASYNC_ACTIVE;
>   return rval;
>  }
>  
> @@ -280,7 +281,7 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t 
> *fcport)
>  done_free_sp:
>   sp->free(sp);
>  done:
> - fcport->flags &= ~FCF_ASYNC_SENT;
> + fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
>   return rval;
>  }
>  
> @@ -288,6 +289,7 @@ void
>  qla2x00_async_prlo_done(struct scsi_qla_host *vha, fc_port_t *fcport,
>  uint16_t *data)
>  {
> + fcport->flags &= ~FCF_ASYNC_ACTIVE;
>   /* Don't re-login in target mode */
>   if (!fcport->tgt_session)
>   qla2x00_mark_device_lost(vha, fcport, 1, 0);
> @@ -301,6 +303,7 @@ qla2x00_async_prlo_sp_done(void *s, int res)
>   struct srb_iocb *lio = >u.iocb_cmd;
>   struct scsi_qla_host *vha = sp->vha;
>  
> + sp->fcport->flags &= ~FCF_ASYNC_ACTIVE;
>   if (!test_bit(UNLOADING, >dpc_flags))
>   qla2x00_post_async_prlo_done_work(sp->fcport->vha, sp->fcport,
>   lio->u.logio.data);
> @@ -339,6 +342,7 @@ qla2x00_async_prlo(struct scsi_qla_host *vha, fc_port_t 
> *fcport)
>  done_free_sp:
>   sp->free(sp);
>  done:
> + fcport->flags &= ~FCF_ASYNC_ACTIVE;
>   return rval;
>  }
>  
> @@ -392,6 +396,8 @@ qla2x00_async_adisc_sp_done(void *ptr, int res)
>   "Async done-%s res %x %8phC\n",
>   sp->name, res, sp->fcport->port_name);
>  
> + sp->fcport->flags &= ~FCF_ASYNC_SENT;
> +
>   memset(, 0, sizeof(ea));
>   ea.event = FCME_ADISC_DONE;
>   ea.rc = res;
> @@ -442,7 +448,7 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t 
> *fcport,
>  done_free_sp:
>   sp->free(sp);
>  done:
> - fcport->flags &= ~FCF_ASYNC_SENT;
> + fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
>   qla2x00_post_async_adisc_work(vha, fcport, data);
>   return rval;
>  }
> @@ -1815,6 +1821,7 @@ qla2x00_async_logout_done(struct scsi_qla_host *vha, 
> fc_port_t *fcport,
>   qla2x00_mark_device_lost(vha, fcport, 1, 0);
>   qlt_logo_completion_handler(fcport, data[0]);
>   fcport->login_gen++;
> + fcport->flags &= ~FCF_ASYNC_ACTIVE;
>   return;
>  }
>  
> @@ -1822,6 +1829,7 @@ void
>  qla2x00_async_adisc_done(struct scsi_qla_host *vha, fc_port_t *fcport,
>  uint16_t *data)
>  {
> + fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
>   if (data[0] == MBS_COMMAND_COMPLETE) {
>   qla2x00_update_fcport(vha, fcport);
>  
> @@ -1829,7 +1837,6 @@ qla2x00_async_adisc_done(struct scsi_qla_host *vha, 
> fc_port_t *fcport,
>   }
>  
>   /* Retry login. */
> - fcport->flags &= ~FCF_ASYNC_SENT;
>   if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
>   set_bit(RELOGIN_NEEDED, >dpc_flags);
>   else
> 

Thanks for the patch. Looks good.

Acked-by: Himanshu Madhani 



Re: [PATCH 2/3] qla2xxx: do not check login_state if no loop id is assigned

2018-02-22 Thread Himanshu Madhani


On Thu, 22 Feb 2018, 12:49am, Hannes Reinecke wrote:

> When no loop id is assigned in qla24xx_fcport_handle_login()
> the login state needs to be ignored; it will get set later on
> in qla_chk_n2n_b4_login().
> 
> Cc: Quinn Tran 
> Cc: Himanshu Madhani 
> Fixes: 040036bb0bc1 ("scsi: qla2xxx: Delay loop id allocation at login")
> Signed-off-by: Hannes Reinecke 
> ---
>  drivers/scsi/qla2xxx/qla_init.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
> index 4dd897c2c2b1..a19ed53ba6d9 100644
> --- a/drivers/scsi/qla2xxx/qla_init.c
> +++ b/drivers/scsi/qla2xxx/qla_init.c
> @@ -1174,8 +1174,9 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host 
> *vha, fc_port_t *fcport)
>   if (fcport->scan_state != QLA_FCPORT_FOUND)
>   return 0;
>  
> - if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
> - (fcport->fw_login_state == DSC_LS_PRLI_PEND))
> + if ((fcport->loop_id != FC_NO_LOOP_ID) &&
> + ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
> +  (fcport->fw_login_state == DSC_LS_PRLI_PEND)))
>   return 0;
>  
>   if (fcport->fw_login_state == DSC_LS_PLOGI_COMP) {
> 

Good Catch. I had this patch in my queue for submission but you beat me to 
it. Looks good.

Acked-by: Himanshu Madhani 



Re: [PATCH 1/3] qla2xxx: Fixup locking for session deletion

2018-02-22 Thread Himanshu Madhani


On Thu, 22 Feb 2018, 12:49am, Hannes Reinecke wrote:

> Commit d8630bb95f46 ('Serialize session deletion by using work_lock') tries
> to fixup a deadlock when deleting sessions, but fails to take
> into account the locking rules. This patch resolves the situation
> by introducing a separate lock for processing the GNLIST response, and
> ensures that sess_lock is released before calling
> qlt_schedule_sess_delete().
> 
> Cc: Himanshu Madhani 
> Cc: Quinn Tran 
> Fixes: d8630bb95f46 ("scsi: qla2xxx: Serialize session deletion by using 
> work_lock")
> Signed-off-by: Hannes Reinecke 
> ---
>  drivers/scsi/qla2xxx/qla_def.h|  4 ++--
>  drivers/scsi/qla2xxx/qla_init.c   | 24 +++-
>  drivers/scsi/qla2xxx/qla_os.c |  7 ++-
>  drivers/scsi/qla2xxx/qla_target.c | 17 ++---
>  4 files changed, 29 insertions(+), 23 deletions(-)
> 
> diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
> index be7d6824581a..3ca4b6a5eddd 100644
> --- a/drivers/scsi/qla2xxx/qla_def.h
> +++ b/drivers/scsi/qla2xxx/qla_def.h
> @@ -261,9 +261,9 @@
>  struct name_list_extended {
>   struct get_name_list_extended *l;
>   dma_addr_t  ldma;
> - struct list_headfcports;/* protect by sess_list */
> + struct list_headfcports;
> + spinlock_t  fcports_lock;
>   u32 size;
> - u8  sent;
>  };
>  /*
>   * Timeout timer counts in seconds
> diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
> index 590aa904fdef..4dd897c2c2b1 100644
> --- a/drivers/scsi/qla2xxx/qla_init.c
> +++ b/drivers/scsi/qla2xxx/qla_init.c
> @@ -660,8 +660,7 @@ qla24xx_async_gnl_sp_done(void *s, int res)
>   (loop_id & 0x7fff));
>   }
>  
> - spin_lock_irqsave(>hw->tgt.sess_lock, flags);
> - vha->gnl.sent = 0;
> + spin_lock_irqsave(>gnl.fcports_lock, flags);
>  
>   INIT_LIST_HEAD();
>   fcport = tf = NULL;
> @@ -670,12 +669,16 @@ qla24xx_async_gnl_sp_done(void *s, int res)
>  
>   list_for_each_entry_safe(fcport, tf, , gnl_entry) {
>   list_del_init(>gnl_entry);
> + spin_lock(>hw->tgt.sess_lock);
>   fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
> + spin_unlock(>hw->tgt.sess_lock);
>   ea.fcport = fcport;
>  
>   qla2x00_fcport_event_handler(vha, );
>   }
> + spin_unlock_irqrestore(>gnl.fcports_lock, flags);
>  
> + spin_lock_irqsave(>hw->tgt.sess_lock, flags);
>   /* create new fcport if fw has knowledge of new sessions */
>   for (i = 0; i < n; i++) {
>   port_id_t id;
> @@ -727,18 +730,21 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, 
> fc_port_t *fcport)
>   ql_dbg(ql_dbg_disc, vha, 0x20d9,
>   "Async-gnlist WWPN %8phC \n", fcport->port_name);
>  
> - spin_lock_irqsave(>hw->tgt.sess_lock, flags);
> + spin_lock_irqsave(>gnl.fcports_lock, flags);
> + if (!list_empty(>gnl_entry)) {
> + spin_unlock_irqrestore(>gnl.fcports_lock, flags);
> + rval = QLA_SUCCESS;
> + goto done;
> + }
> +
> + spin_lock(>hw->tgt.sess_lock);
>   fcport->disc_state = DSC_GNL;
>   fcport->last_rscn_gen = fcport->rscn_gen;
>   fcport->last_login_gen = fcport->login_gen;
> + spin_unlock(>hw->tgt.sess_lock);
>  
>   list_add_tail(>gnl_entry, >gnl.fcports);
> - if (vha->gnl.sent) {
> - spin_unlock_irqrestore(>hw->tgt.sess_lock, flags);
> - return QLA_SUCCESS;
> - }
> - vha->gnl.sent = 1;
> - spin_unlock_irqrestore(>hw->tgt.sess_lock, flags);
> + spin_unlock_irqrestore(>gnl.fcports_lock, flags);
>  
>   sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
>   if (!sp)
> diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
> index 12ee6e02d146..dc2b188fdce1 100644
> --- a/drivers/scsi/qla2xxx/qla_os.c
> +++ b/drivers/scsi/qla2xxx/qla_os.c
> @@ -4575,6 +4575,7 @@ struct scsi_qla_host *qla2x00_create_host(struct 
> scsi_host_template *sht,
>  
>   spin_lock_init(>work_lock);
>   spin_lock_init(>cmd_list_lock);
> + spin_lock_init(>gnl.fcports_lock);
>   init_waitqueue_head(>fcport_waitQ);
>   init_waitqueue_head(>vref_waitq);
>  
> @@ -4875,6 +4876,8 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, 
> struct qla_work_evt *e)
>   }
>   qlt_plogi_ack_unref(vha, pla);
>   } else {
> + fc_port_t *dfcp = NULL;
> +
>   spin_lock_irqsave(>hw->tgt.sess_lock, flags);
>   tfcp = qla2x00_find_fcport_by_nportid(vha,
>   >u.new_sess.id, 1);
> @@ -4897,11 +4900,13 @@ void qla24xx_create_new_sess(struct scsi_qla_host 
> *vha, struct qla_work_evt *e)
>   

Re: [PATCH] Avoid that ATA error handling hangs

2018-02-22 Thread Natanael Copa
On Thu, 22 Feb 2018 03:53:19 +
Bart Van Assche  wrote:

> On Thu, 2018-02-22 at 02:23 +, Damien Le Moal wrote:
> > On Wed, 2018-02-21 at 09:23 -0800, Bart Van Assche wrote:  
> > > [ ... ]  
> > This does not compile.  
> 
> This patch depends on another patch that is not yet in Martin's tree. See also
> https://marc.info/?l=linux-scsi=151675130615597. I should have mentioned 
> this
> in the patch description.

I applied the two patches on top of 4.14.20 and it solves my problem[1]. I
think those two should be included in the 4.14.21 release.

Thanks!

-nc

[1]: https://bugzilla.kernel.org/show_bug.cgi?id=198861


[Bug 198861] Regression causes kernel OOPS and hang in SCSI error report

2018-02-22 Thread bugzilla-daemon
https://bugzilla.kernel.org/show_bug.cgi?id=198861

--- Comment #1 from nc...@alpinelinux.org ---
Those two patches fixes the issue:

https://patchwork.kernel.org/patch/10181165/
https://patchwork.kernel.org/patch/10233617/

-- 
You are receiving this mail because:
You are the assignee for the bug.


[PATCH v5 09/13] lpfc: Add embedded data pointers for enhanced performance

2018-02-22 Thread James Smart
The current driver isn't taking advantage of a performance hint whereby
the initial data buffer descriptor can be placed in the WQE as well as
the SGL.

Add the logic to detect support for the feature and to use it when
supported.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
Reviewed-by: Johannes Thumshirn 

---
v3:
  remove unneeded parens
  combined 6422 msg on 1 line
---
 drivers/scsi/lpfc/lpfc.h   |  2 ++
 drivers/scsi/lpfc/lpfc_hw4.h   |  3 +++
 drivers/scsi/lpfc/lpfc_init.c  | 20 
 drivers/scsi/lpfc/lpfc_nvme.c  | 18 ++
 drivers/scsi/lpfc/lpfc_nvmet.c | 24 
 drivers/scsi/lpfc/lpfc_scsi.c  |  8 ++--
 drivers/scsi/lpfc/lpfc_sli.c   | 25 +
 7 files changed, 94 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 7aad4a717f13..9136a59b1c5b 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -840,6 +840,8 @@ struct lpfc_hba {
 #define LPFC_ENABLE_FCP  1
 #define LPFC_ENABLE_NVME 2
 #define LPFC_ENABLE_BOTH 3
+   uint32_t nvme_embed_pbde;
+   uint32_t fcp_embed_pbde;
uint32_t io_channel_irqs;   /* number of irqs for io channels */
struct nvmet_fc_target_port *targetport;
lpfc_vpd_t vpd; /* vital product data */
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index be8227dfa086..ed5e870c58c3 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -4226,6 +4226,9 @@ struct wqe_common {
 #define wqe_irsp_SHIFT4
 #define wqe_irsp_MASK 0x0001
 #define wqe_irsp_WORD word11
+#define wqe_pbde_SHIFT5
+#define wqe_pbde_MASK 0x0001
+#define wqe_pbde_WORD word11
 #define wqe_sup_SHIFT 6
 #define wqe_sup_MASK  0x0001
 #define wqe_sup_WORD  word11
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index af92c3c681f7..ecb42cae71f2 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -10608,6 +10608,19 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, 
LPFC_MBOXQ_t *mboxq)
phba->cfg_enable_fc4_type = LPFC_ENABLE_FCP;
}
 
+   /* Only embed PBDE for if_type 6 */
+   if (bf_get(lpfc_sli_intf_if_type, >sli4_hba.sli_intf) ==
+   LPFC_SLI_INTF_IF_TYPE_6) {
+   phba->fcp_embed_pbde = 1;
+   phba->nvme_embed_pbde = 1;
+   }
+
+   /* PBDE support requires xib be set */
+   if (!bf_get(cfg_xib, mbx_sli4_parameters)) {
+   phba->fcp_embed_pbde = 0;
+   phba->nvme_embed_pbde = 0;
+   }
+
/*
 * To support Suppress Response feature we must satisfy 3 conditions.
 * lpfc_suppress_rsp module parameter must be set (default).
@@ -10639,6 +10652,13 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, 
LPFC_MBOXQ_t *mboxq)
else
phba->fcp_embed_io = 0;
 
+   lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_NVME,
+   "6422 XIB %d: FCP %d %d NVME %d %d %d\n",
+   bf_get(cfg_xib, mbx_sli4_parameters),
+   phba->fcp_embed_pbde, phba->fcp_embed_io,
+   phba->nvme_support, phba->nvme_embed_pbde,
+   phba->cfg_suppress_rsp);
+
if ((bf_get(cfg_cqpsize, mbx_sli4_parameters) & LPFC_CQ_16K_PAGE_SZ) &&
(bf_get(cfg_wqpsize, mbx_sli4_parameters) & LPFC_WQ_16K_PAGE_SZ) &&
(sli4_params->wqsize & LPFC_WQ_SZ128_SUPPORT))
diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index 3a103d0895a2..5a1a6e24a27f 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -1170,6 +1170,7 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport,
struct sli4_sge *sgl = lpfc_ncmd->nvme_sgl;
struct scatterlist *data_sg;
struct sli4_sge *first_data_sgl;
+   struct ulp_bde64 *bde;
dma_addr_t physaddr;
uint32_t num_bde = 0;
uint32_t dma_len;
@@ -1237,7 +1238,24 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport,
data_sg = sg_next(data_sg);
sgl++;
}
+   if (phba->nvme_embed_pbde) {
+   /* Use PBDE support for first SGL only, offset == 0 */
+   /* Words 13-15 */
+   bde = (struct ulp_bde64 *)
+   >words[13];
+   bde->addrLow = first_data_sgl->addr_lo;
+   bde->addrHigh = first_data_sgl->addr_hi;
+   bde->tus.f.bdeSize =
+   le32_to_cpu(first_data_sgl->sge_len);
+   bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
+   bde->tus.w = cpu_to_le32(bde->tus.w);
+  

[PATCH v5 12/13] lpfc: update driver version to 12.0.0.0

2018-02-22 Thread James Smart
Update the driver version to 12.0.0.0

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
Reviewed-by: Johannes Thumshirn 
---
 drivers/scsi/lpfc/lpfc_version.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h
index 4adbf07880a2..b1ae62a44aae 100644
--- a/drivers/scsi/lpfc/lpfc_version.h
+++ b/drivers/scsi/lpfc/lpfc_version.h
@@ -20,7 +20,7 @@
  * included with this package. *
  ***/
 
-#define LPFC_DRIVER_VERSION "11.4.0.7"
+#define LPFC_DRIVER_VERSION "12.0.0.0"
 #define LPFC_DRIVER_NAME   "lpfc"
 
 /* Used for SLI 2/3 */
-- 
2.13.1



[PATCH v5 04/13] lpfc: Add push-to-adapter support to sli4

2018-02-22 Thread James Smart
New if_type=6 adapters support an additional BAR that provides
apertures to allow direct WQE to adapter push support - termed
Direct Packet Push (DPP). WQ creation differs slightly to ask for
a WQ to be DPP-ized. When submitting a WQE to a DPP WQ, it is
submitted to the host memory for the WQ normally, but is also
written by the host cpu directly to a BAR aperture.  Write buffer
coalescing in hardware is (hopefully) turned on, enabling single
pci write operation support. The doorbell is thing rung to indicate
the WQE is available and was pushed to the aperture.

This patch:
- Updates the WQ Create commands for the DPP options
- Adds the bar mapping for if_type=6 DPP bar
- Adds the WQE pushing to the DDP aperture received from WQ create
- Adds a new module parameter to disable DPP operation if desired.
  Default is enabled.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 

---
v3:
  remove unnecessary parens
  use ioremap_wc() instead of set_memory_wc(). the wc property
is now set by default on the BAR. if direct push is disabled,
the BAR won't be used so it won't matter what is set on it.
Track cases where the ioremap_wc() may not succeed, leaving
bar pointer NULL. In this case, disable direct push.
  As some platforms will honor ioremap_wc() but not truly enable
wc, change default for direct push so enabled only on X86.
v4:
  revert to original patch version using set_memory_wc() as
  benchmarking and different platform testing says its the best
  option

v5:
  remove separate 64bit/32bit code - use writeq() always
---
 drivers/scsi/lpfc/lpfc.h  |   3 +-
 drivers/scsi/lpfc/lpfc_attr.c |  10 ++
 drivers/scsi/lpfc/lpfc_hw4.h  |  31 ++
 drivers/scsi/lpfc/lpfc_init.c |  18 
 drivers/scsi/lpfc/lpfc_sli.c  | 229 +++---
 drivers/scsi/lpfc/lpfc_sli4.h |  16 ++-
 6 files changed, 220 insertions(+), 87 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 9698b9635058..86ffb9756e65 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -840,7 +840,8 @@ struct lpfc_hba {
uint32_t cfg_enable_SmartSAN;
uint32_t cfg_enable_mds_diags;
uint32_t cfg_enable_fc4_type;
-   uint32_t cfg_enable_bbcr;   /*Enable BB Credit Recovery*/
+   uint32_t cfg_enable_bbcr;   /* Enable BB Credit Recovery */
+   uint32_t cfg_enable_dpp;/* Enable Direct Packet Push */
uint32_t cfg_xri_split;
 #define LPFC_ENABLE_FCP  1
 #define LPFC_ENABLE_NVME 2
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 7be4bdef4d42..32f17e19e123 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -5186,6 +5186,14 @@ LPFC_ATTR_R(enable_mds_diags, 0, 0, 1, "Enable MDS 
Diagnostics");
  */
 LPFC_BBCR_ATTR_RW(enable_bbcr, 1, 0, 1, "Enable BBC Recovery");
 
+/*
+ * lpfc_enable_dpp: Enable DPP on G7
+ *   0  = DPP on G7 disabled
+ *   1  = DPP on G7 enabled (default)
+ * Value range is [0,1]. Default value is 1.
+ */
+LPFC_ATTR_RW(enable_dpp, 1, 0, 1, "Enable Direct Packet Push");
+
 struct device_attribute *lpfc_hba_attrs[] = {
_attr_nvme_info,
_attr_bg_info,
@@ -5294,6 +5302,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
_attr_lpfc_xlane_supported,
_attr_lpfc_enable_mds_diags,
_attr_lpfc_enable_bbcr,
+   _attr_lpfc_enable_dpp,
NULL,
 };
 
@@ -6306,6 +6315,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
lpfc_fcp_io_channel_init(phba, lpfc_fcp_io_channel);
lpfc_nvme_io_channel_init(phba, lpfc_nvme_io_channel);
lpfc_enable_bbcr_init(phba, lpfc_enable_bbcr);
+   lpfc_enable_dpp_init(phba, lpfc_enable_dpp);
 
if (phba->sli_rev != LPFC_SLI_REV4) {
/* NVME only supported on SLI4 */
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index 93fd9fd10a0f..60ccff6fa8b0 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -1372,6 +1372,15 @@ struct lpfc_mbx_wq_create {
 #define lpfc_mbx_wq_create_page_size_MASK  0x00FF
 #define lpfc_mbx_wq_create_page_size_WORD  word1
 #define LPFC_WQ_PAGE_SIZE_4096 0x1
+#define lpfc_mbx_wq_create_dpp_req_SHIFT   15
+#define lpfc_mbx_wq_create_dpp_req_MASK0x0001
+#define lpfc_mbx_wq_create_dpp_req_WORDword1
+#define lpfc_mbx_wq_create_doe_SHIFT   14
+#define lpfc_mbx_wq_create_doe_MASK0x0001
+#define lpfc_mbx_wq_create_doe_WORDword1
+#define lpfc_mbx_wq_create_toe_SHIFT   13
+#define lpfc_mbx_wq_create_toe_MASK0x0001
+#define lpfc_mbx_wq_create_toe_WORDword1
 #define lpfc_mbx_wq_create_wqe_size_SHIFT  8
 #define lpfc_mbx_wq_create_wqe_size_MASK   0x000F
 #define lpfc_mbx_wq_create_wqe_size_WORD   word1
@@ -1400,6 +1409,28 @@ struct lpfc_mbx_wq_create {
 

[PATCH v5 10/13] lpfc: Fix nvme embedded io length on new hardware

2018-02-22 Thread James Smart
Newer hardware more strictly enforces buffer lenghts, causing an
mis-set value to be identified. Older hardware won't catch it.
The difference is benign on old hardware.

Set the right embedded buffer length for nvme ios.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
Reviewed-by: Johannes Thumshirn 
---
 drivers/scsi/lpfc/lpfc_nvme.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index 5a1a6e24a27f..c75958daf799 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -655,7 +655,7 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport,
 
/* Word 0-2 - NVME CMND IU (embedded payload) */
wqe->generic.bde.tus.f.bdeFlags = BUFF_TYPE_BDE_IMMED;
-   wqe->generic.bde.tus.f.bdeSize = 60;
+   wqe->generic.bde.tus.f.bdeSize = 56;
wqe->generic.bde.addrHigh = 0;
wqe->generic.bde.addrLow =  64;  /* Word 16 */
 
-- 
2.13.1



[PATCH v5 05/13] lpfc: Add PCI Ids for if_type=6 hardware

2018-02-22 Thread James Smart
Add PCI ids for the new G7 adapter

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
Reviewed-by: Johannes Thumshirn 

---
v3:
  Add default adapter id string for G7 adapter
---
 drivers/scsi/lpfc/lpfc_hw.h   | 1 +
 drivers/scsi/lpfc/lpfc_ids.h  | 2 ++
 drivers/scsi/lpfc/lpfc_init.c | 3 +++
 3 files changed, 6 insertions(+)

diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index bdc1f184f67a..d07d2fcbea34 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -1580,6 +1580,7 @@ struct lpfc_fdmi_reg_portattr {
 #define PCI_DEVICE_ID_LANCER_FCOE   0xe260
 #define PCI_DEVICE_ID_LANCER_FCOE_VF 0xe268
 #define PCI_DEVICE_ID_LANCER_G6_FC  0xe300
+#define PCI_DEVICE_ID_LANCER_G7_FC  0xf400
 #define PCI_DEVICE_ID_SAT_SMB   0xf011
 #define PCI_DEVICE_ID_SAT_MID   0xf015
 #define PCI_DEVICE_ID_RFLY  0xf095
diff --git a/drivers/scsi/lpfc/lpfc_ids.h b/drivers/scsi/lpfc/lpfc_ids.h
index 0ba3733eb36d..329c8d28869c 100644
--- a/drivers/scsi/lpfc/lpfc_ids.h
+++ b/drivers/scsi/lpfc/lpfc_ids.h
@@ -116,6 +116,8 @@ const struct pci_device_id lpfc_id_table[] = {
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_G6_FC,
PCI_ANY_ID, PCI_ANY_ID, },
+   {PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_LANCER_G7_FC,
+   PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SKYHAWK,
PCI_ANY_ID, PCI_ANY_ID, },
{PCI_VENDOR_ID_EMULEX, PCI_DEVICE_ID_SKYHAWK_VF,
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 5f0c63bb0a4d..2e723cdd2c1a 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -2473,6 +2473,9 @@ lpfc_get_hba_model_desc(struct lpfc_hba *phba, uint8_t 
*mdp, uint8_t *descp)
case PCI_DEVICE_ID_LANCER_G6_FC:
m = (typeof(m)){"LPe32000", "PCIe", "Fibre Channel Adapter"};
break;
+   case PCI_DEVICE_ID_LANCER_G7_FC:
+   m = (typeof(m)){"LPe36000", "PCIe", "Fibre Channel Adapter"};
+   break;
case PCI_DEVICE_ID_SKYHAWK:
case PCI_DEVICE_ID_SKYHAWK_VF:
oneConnect = 1;
-- 
2.13.1



[PATCH v5 06/13] lpfc: Add 64G link speed support

2018-02-22 Thread James Smart
The G7 adapter supports 64G link speeds. Add support to the driver.

In addition, a small cleanup to replace the odd bitmap logic with
a switch case.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
Reviewed-by: Johannes Thumshirn 

---
v2:
  address review comment of typo in define name. Define wasn't used
  anywhere yet.
v3:
  reformat printf_log 0469
---
 drivers/scsi/lpfc/lpfc.h | 14 +++--
 drivers/scsi/lpfc/lpfc_attr.c| 62 
 drivers/scsi/lpfc/lpfc_ct.c  |  5 
 drivers/scsi/lpfc/lpfc_els.c |  5 
 drivers/scsi/lpfc/lpfc_hbadisc.c |  1 +
 drivers/scsi/lpfc/lpfc_hw.h  | 12 
 drivers/scsi/lpfc/lpfc_hw4.h |  3 ++
 drivers/scsi/lpfc/lpfc_init.c| 17 +--
 drivers/scsi/lpfc/lpfc_mbox.c|  4 +++
 9 files changed, 93 insertions(+), 30 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 86ffb9756e65..7aad4a717f13 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -544,16 +544,10 @@ struct unsol_rcv_ct_ctx {
 #define LPFC_USER_LINK_SPEED_10G   10  /* 10 Gigabaud */
 #define LPFC_USER_LINK_SPEED_16G   16  /* 16 Gigabaud */
 #define LPFC_USER_LINK_SPEED_32G   32  /* 32 Gigabaud */
-#define LPFC_USER_LINK_SPEED_MAX   LPFC_USER_LINK_SPEED_32G
-#define LPFC_USER_LINK_SPEED_BITMAP  ((1ULL << LPFC_USER_LINK_SPEED_32G) | \
-(1 << LPFC_USER_LINK_SPEED_16G) | \
-(1 << LPFC_USER_LINK_SPEED_10G) | \
-(1 << LPFC_USER_LINK_SPEED_8G) | \
-(1 << LPFC_USER_LINK_SPEED_4G) | \
-(1 << LPFC_USER_LINK_SPEED_2G) | \
-(1 << LPFC_USER_LINK_SPEED_1G) | \
-(1 << LPFC_USER_LINK_SPEED_AUTO))
-#define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8, 10, 16, 32"
+#define LPFC_USER_LINK_SPEED_64G   64  /* 64 Gigabaud */
+#define LPFC_USER_LINK_SPEED_MAX   LPFC_USER_LINK_SPEED_64G
+
+#define LPFC_LINK_SPEED_STRING "0, 1, 2, 4, 8, 10, 16, 32, 64"
 
 enum nemb_type {
nemb_mse = 1,
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 32f17e19e123..14f6efcf8f0b 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -4115,23 +4115,32 @@ lpfc_link_speed_store(struct device *dev, struct 
device_attribute *attr,
((val == LPFC_USER_LINK_SPEED_8G) && !(phba->lmt & LMT_8Gb)) ||
((val == LPFC_USER_LINK_SPEED_10G) && !(phba->lmt & LMT_10Gb)) ||
((val == LPFC_USER_LINK_SPEED_16G) && !(phba->lmt & LMT_16Gb)) ||
-   ((val == LPFC_USER_LINK_SPEED_32G) && !(phba->lmt & LMT_32Gb))) {
+   ((val == LPFC_USER_LINK_SPEED_32G) && !(phba->lmt & LMT_32Gb)) ||
+   ((val == LPFC_USER_LINK_SPEED_64G) && !(phba->lmt & LMT_64Gb))) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"2879 lpfc_link_speed attribute cannot be set "
"to %d. Speed is not supported by this port.\n",
val);
return -EINVAL;
}
-   if (val == LPFC_USER_LINK_SPEED_16G &&
-phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
+   if (val >= LPFC_USER_LINK_SPEED_16G &&
+   phba->fc_topology == LPFC_TOPOLOGY_LOOP) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
"3112 lpfc_link_speed attribute cannot be set "
"to %d. Speed is not supported in loop mode.\n",
val);
return -EINVAL;
}
-   if ((val >= 0) && (val <= LPFC_USER_LINK_SPEED_MAX) &&
-   (LPFC_USER_LINK_SPEED_BITMAP & (1 << val))) {
+
+   switch (val) {
+   case LPFC_USER_LINK_SPEED_AUTO:
+   case LPFC_USER_LINK_SPEED_1G:
+   case LPFC_USER_LINK_SPEED_2G:
+   case LPFC_USER_LINK_SPEED_4G:
+   case LPFC_USER_LINK_SPEED_8G:
+   case LPFC_USER_LINK_SPEED_16G:
+   case LPFC_USER_LINK_SPEED_32G:
+   case LPFC_USER_LINK_SPEED_64G:
prev_val = phba->cfg_link_speed;
phba->cfg_link_speed = val;
if (nolip)
@@ -4141,13 +4150,18 @@ lpfc_link_speed_store(struct device *dev, struct 
device_attribute *attr,
if (err) {
phba->cfg_link_speed = prev_val;
return -EINVAL;
-   } else
-   return strlen(buf);
+   }
+   return strlen(buf);
+   default:
+   break;
}
+
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-   "0469 lpfc_link_speed attribute cannot be set to %d, "
-   "allowed values are 

[PATCH v5 00/13] lpfc new hardware patches for 12.0.0.0

2018-02-22 Thread James Smart
This patch set adds support for Broadcom's new G7 product that
supports G4G FC.

The patches were cut against the Martin's 4.17/scsi-queue tree.

v2:
 Address comments:
   patch 1, 2, 4, 7: patch description typos
   patch 6: typo on 256GBit speed define

v3:
 Add review tags
 Address comments:
   patch 4: parens, replace set_memory_wc by ioremap_wc
   patch 6: reformat strings
   patch 9: parens
   patch 13: patch title
 patch 5: add missing snippet for default id string
 patch 9, 11: log print condensed to line

v4:
 Add review tags
 patch4: revert to using set_memory_wc

v5:
 patch4: remove 64bit flag. use writeq() always

James Smart (13):
  lpfc: Rework lpfc to allow different sli4 cq and eq handlers
  lpfc: Rework sli4 doorbell infrastructure
  lpfc: Add SLI-4 if_type=6 support to the code base
  lpfc: Add push-to-adapter support to sli4
  lpfc: Add PCI Ids for if_type=6 hardware
  lpfc: Add 64G link speed support
  lpfc: Add if_type=6 support for cycling valid bits
  lpfc: Enable fw download on if_type=6 devices
  lpfc: Add embedded data pointers for enhanced performance
  lpfc: Fix nvme embedded io length on new hardware
  lpfc: Work around NVME cmd iu SGL type
  lpfc: update driver version to 12.0.0.0
  lpfc: Change Copyright of 12.0.0.0 modified files to 2018

 drivers/scsi/lpfc/lpfc.h |  20 +-
 drivers/scsi/lpfc/lpfc_attr.c|  86 +--
 drivers/scsi/lpfc/lpfc_bsg.c |   6 +-
 drivers/scsi/lpfc/lpfc_ct.c  |   7 +-
 drivers/scsi/lpfc/lpfc_debugfs.c |  22 +-
 drivers/scsi/lpfc/lpfc_debugfs.h |  13 +-
 drivers/scsi/lpfc/lpfc_els.c |   5 +
 drivers/scsi/lpfc/lpfc_hbadisc.c |   1 +
 drivers/scsi/lpfc/lpfc_hw.h  |  15 +-
 drivers/scsi/lpfc/lpfc_hw4.h | 115 -
 drivers/scsi/lpfc/lpfc_ids.h |   4 +-
 drivers/scsi/lpfc/lpfc_init.c| 247 +++---
 drivers/scsi/lpfc/lpfc_mbox.c|   4 +
 drivers/scsi/lpfc/lpfc_nvme.c|  69 +++--
 drivers/scsi/lpfc/lpfc_nvmet.c   |  24 ++
 drivers/scsi/lpfc/lpfc_scsi.c|   8 +-
 drivers/scsi/lpfc/lpfc_sli.c | 530 +--
 drivers/scsi/lpfc/lpfc_sli4.h|  30 ++-
 drivers/scsi/lpfc/lpfc_version.h |   2 +-
 19 files changed, 958 insertions(+), 250 deletions(-)

-- 
2.13.1



[PATCH v5 07/13] lpfc: Add if_type=6 support for cycling valid bits

2018-02-22 Thread James Smart
Traditional SLI4 required the driver to clear Valid bits on
EQEs and CQEs after consuming them.

The new if_type=6 hardware will cycle the value for what is
valid on each queue itteration. The driver no longer has to
touch the valid bits. This also means all the cpu cache
dirtying and perhaps flush/refill's done by the hardware
in accessing the EQ/CQ elements is eliminated.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
Reviewed-by: Johannes Thumshirn 
---
 drivers/scsi/lpfc/lpfc_hw4.h  | 18 --
 drivers/scsi/lpfc/lpfc_init.c | 11 +++
 drivers/scsi/lpfc/lpfc_sli.c  | 77 +++
 drivers/scsi/lpfc/lpfc_sli4.h |  3 ++
 4 files changed, 92 insertions(+), 17 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index 0c33510fe75c..dba724e1f5ee 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -1040,6 +1040,9 @@ struct eq_context {
 #define lpfc_eq_context_valid_SHIFT29
 #define lpfc_eq_context_valid_MASK 0x0001
 #define lpfc_eq_context_valid_WORD word0
+#define lpfc_eq_context_autovalid_SHIFT 28
+#define lpfc_eq_context_autovalid_MASK  0x0001
+#define lpfc_eq_context_autovalid_WORD  word0
uint32_t word1;
 #define lpfc_eq_context_count_SHIFT26
 #define lpfc_eq_context_count_MASK 0x0003
@@ -1173,6 +1176,9 @@ struct cq_context {
 #define LPFC_CQ_CNT_5120x1
 #define LPFC_CQ_CNT_1024   0x2
 #define LPFC_CQ_CNT_WORD7  0x3
+#define lpfc_cq_context_autovalid_SHIFT 15
+#define lpfc_cq_context_autovalid_MASK  0x0001
+#define lpfc_cq_context_autovalid_WORD  word0
uint32_t word1;
 #define lpfc_cq_eq_id_SHIFT22  /* Version 0 Only */
 #define lpfc_cq_eq_id_MASK 0x00FF
@@ -1231,9 +1237,9 @@ struct lpfc_mbx_cq_create_set {
 #define lpfc_mbx_cq_create_set_cqe_size_SHIFT  25
 #define lpfc_mbx_cq_create_set_cqe_size_MASK   0x0003
 #define lpfc_mbx_cq_create_set_cqe_size_WORD   word1
-#define lpfc_mbx_cq_create_set_auto_SHIFT  15
-#define lpfc_mbx_cq_create_set_auto_MASK   0x001
-#define lpfc_mbx_cq_create_set_auto_WORD   word1
+#define lpfc_mbx_cq_create_set_autovalid_SHIFT 15
+#define lpfc_mbx_cq_create_set_autovalid_MASK  0x001
+#define lpfc_mbx_cq_create_set_autovalid_WORD  word1
 #define lpfc_mbx_cq_create_set_nodelay_SHIFT   14
 #define lpfc_mbx_cq_create_set_nodelay_MASK0x0001
 #define lpfc_mbx_cq_create_set_nodelay_WORDword1
@@ -3288,6 +3294,9 @@ struct lpfc_sli4_parameters {
 #define cfg_sli_hint_2_MASK0x001f
 #define cfg_sli_hint_2_WORDword1
uint32_t word2;
+#define cfg_eqav_SHIFT 31
+#define cfg_eqav_MASK  0x0001
+#define cfg_eqav_WORD  word2
uint32_t word3;
uint32_t word4;
 #define cfg_cqv_SHIFT  14
@@ -3296,6 +3305,9 @@ struct lpfc_sli4_parameters {
 #define cfg_cqpsize_SHIFT  16
 #define cfg_cqpsize_MASK   0x00ff
 #define cfg_cqpsize_WORD   word4
+#define cfg_cqav_SHIFT 31
+#define cfg_cqav_MASK  0x0001
+#define cfg_cqav_WORD  word4
uint32_t word5;
uint32_t word6;
 #define cfg_mqv_SHIFT  14
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 576ab7ec7e9d..96a37e4e127d 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -8063,6 +8063,7 @@ lpfc_alloc_nvme_wq_cq(struct lpfc_hba *phba, int wqidx)
wqidx);
return 1;
}
+   qdesc->qe_valid = 1;
phba->sli4_hba.nvme_cq[wqidx] = qdesc;
 
qdesc = lpfc_sli4_queue_alloc(phba, LPFC_EXPANDED_PAGE_SIZE,
@@ -8100,6 +8101,7 @@ lpfc_alloc_fcp_wq_cq(struct lpfc_hba *phba, int wqidx)
"0499 Failed allocate fast-path FCP CQ (%d)\n", wqidx);
return 1;
}
+   qdesc->qe_valid = 1;
phba->sli4_hba.fcp_cq[wqidx] = qdesc;
 
/* Create Fast Path FCP WQs */
@@ -8293,6 +8295,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
"0497 Failed allocate EQ (%d)\n", idx);
goto out_error;
}
+   qdesc->qe_valid = 1;
phba->sli4_hba.hba_eq[idx] = qdesc;
}
 
@@ -8318,6 +8321,7 @@ lpfc_sli4_queue_create(struct lpfc_hba *phba)
"CQ Set (%d)\n", idx);
goto out_error;
}
+   qdesc->qe_valid = 1;
phba->sli4_hba.nvmet_cqset[idx] = qdesc;
}
}
@@ -8335,6 +8339,7 @@ 

[PATCH v5 11/13] lpfc: Work around NVME cmd iu SGL type

2018-02-22 Thread James Smart
The hardware offload for NVME commands was created when the
FC-NVME standard was setting SGL Descriptor Type to SGL Data
Block Descriptor (0h) and SGL Descriptor Sub Type to Address (0h).

A late change in NVMe-over-Fabrics obsoleted these values, creating
a transport SGL descriptor type with new values to go into these
fields.

For initial hardware support, in order to be compliant to the spec,
use host-supplied cmd IU buffers instead of the adapter generated
values. Later hardware will correct this.

Add a module parameter to override this offload disablement if looking
for lowest latency. This is reasonable as nothing in FC-NVME uses
the SQE SGL values.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
Reviewed-by: Johannes Thumshirn 

---
v3:
  msg 6422 combined on 1 line
---
 drivers/scsi/lpfc/lpfc.h  |  1 +
 drivers/scsi/lpfc/lpfc_attr.c | 14 
 drivers/scsi/lpfc/lpfc_hw4.h  |  1 +
 drivers/scsi/lpfc/lpfc_init.c |  4 ++--
 drivers/scsi/lpfc/lpfc_nvme.c | 51 ++-
 drivers/scsi/lpfc/lpfc_sli.c  | 15 +
 6 files changed, 69 insertions(+), 17 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index 9136a59b1c5b..6c0d351c0d0d 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -782,6 +782,7 @@ struct lpfc_hba {
uint32_t cfg_fcp_io_channel;
uint32_t cfg_suppress_rsp;
uint32_t cfg_nvme_oas;
+   uint32_t cfg_nvme_embed_cmd;
uint32_t cfg_nvme_io_channel;
uint32_t cfg_nvmet_mrq;
uint32_t cfg_enable_nvmet;
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 14f6efcf8f0b..46f6d97d21d6 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -5042,6 +5042,18 @@ LPFC_ATTR_RW(nvme_oas, 0, 0, 1,
 "Use OAS bit on NVME IOs");
 
 /*
+ * lpfc_nvme_embed_cmd: Use the oas bit when sending NVME/NVMET IOs
+ *
+ *  0  = Put NVME Command in SGL
+ *  1  = Embed NVME Command in WQE (unless G7)
+ *  2 =  Embed NVME Command in WQE (force)
+ *
+ * Value range is [0,2]. Default value is 1.
+ */
+LPFC_ATTR_RW(nvme_embed_cmd, 1, 0, 2,
+"Embed NVME Command in WQE");
+
+/*
  * lpfc_fcp_io_channel: Set the number of FCP IO channels the driver
  * will advertise it supports to the SCSI layer. This also will map to
  * the number of WQs the driver will create.
@@ -5282,6 +5294,7 @@ struct device_attribute *lpfc_hba_attrs[] = {
_attr_lpfc_task_mgmt_tmo,
_attr_lpfc_use_msi,
_attr_lpfc_nvme_oas,
+   _attr_lpfc_nvme_embed_cmd,
_attr_lpfc_auto_imax,
_attr_lpfc_fcp_imax,
_attr_lpfc_fcp_cpu_map,
@@ -6306,6 +6319,7 @@ lpfc_get_cfgparam(struct lpfc_hba *phba)
lpfc_enable_SmartSAN_init(phba, lpfc_enable_SmartSAN);
lpfc_use_msi_init(phba, lpfc_use_msi);
lpfc_nvme_oas_init(phba, lpfc_nvme_oas);
+   lpfc_nvme_embed_cmd_init(phba, lpfc_nvme_embed_cmd);
lpfc_auto_imax_init(phba, lpfc_auto_imax);
lpfc_fcp_imax_init(phba, lpfc_fcp_imax);
lpfc_fcp_cpu_map_init(phba, lpfc_fcp_cpu_map);
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index ed5e870c58c3..37c547b4bc78 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -2678,6 +2678,7 @@ struct lpfc_mbx_read_rev {
 #define lpfc_mbx_rd_rev_vpd_MASK   0x0001
 #define lpfc_mbx_rd_rev_vpd_WORD   word1
uint32_t first_hw_rev;
+#define LPFC_G7_ASIC_1 0xd
uint32_t second_hw_rev;
uint32_t word4_rsvd;
uint32_t third_hw_rev;
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index ecb42cae71f2..50bc6c6efa87 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -10653,11 +10653,11 @@ lpfc_get_sli4_parameters(struct lpfc_hba *phba, 
LPFC_MBOXQ_t *mboxq)
phba->fcp_embed_io = 0;
 
lpfc_printf_log(phba, KERN_INFO, LOG_INIT | LOG_NVME,
-   "6422 XIB %d: FCP %d %d NVME %d %d %d\n",
+   "6422 XIB %d: FCP %d %d NVME %d %d %d %d\n",
bf_get(cfg_xib, mbx_sli4_parameters),
phba->fcp_embed_pbde, phba->fcp_embed_io,
phba->nvme_support, phba->nvme_embed_pbde,
-   phba->cfg_suppress_rsp);
+   phba->cfg_nvme_embed_cmd, phba->cfg_suppress_rsp);
 
if ((bf_get(cfg_cqpsize, mbx_sli4_parameters) & LPFC_CQ_16K_PAGE_SZ) &&
(bf_get(cfg_wqpsize, mbx_sli4_parameters) & LPFC_WQ_16K_PAGE_SZ) &&
diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index c75958daf799..6ea6cc372647 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -617,11 +617,21 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport 

[PATCH v5 08/13] lpfc: Enable fw download on if_type=6 devices

2018-02-22 Thread James Smart
Current code is very explicit in what it allows to be downloaded.
The driver checking prevented G7 firmware download. The driver
checking is unnecessary as the device will validate what it receives.

Revise the firmware download interface checking.
Added a little debug support in case there is still a failure.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
Reviewed-by: Johannes Thumshirn 
---
 drivers/scsi/lpfc/lpfc_hw4.h  |  5 +
 drivers/scsi/lpfc/lpfc_init.c | 44 ++-
 drivers/scsi/lpfc/lpfc_sli.c  |  1 +
 3 files changed, 33 insertions(+), 17 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index dba724e1f5ee..be8227dfa086 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -2241,6 +2241,7 @@ struct lpfc_mbx_redisc_fcf_tbl {
  * command.
  */
 #define ADD_STATUS_OPERATION_ALREADY_ACTIVE0x67
+#define ADD_STATUS_FW_NOT_SUPPORTED0xEB
 
 struct lpfc_mbx_sli4_config {
struct mbox_header header;
@@ -4603,10 +4604,6 @@ union lpfc_wqe128 {
struct gen_req64_wqe gen_req;
 };
 
-#define LPFC_GROUP_OJECT_MAGIC_G5  0xfeaa0001
-#define LPFC_GROUP_OJECT_MAGIC_G6  0xfeaa0003
-#define LPFC_FILE_TYPE_GROUP   0xf7
-#define LPFC_FILE_ID_GROUP 0xa2
 struct lpfc_grp_hdr {
uint32_t size;
uint32_t magic_number;
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 96a37e4e127d..af92c3c681f7 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -11297,6 +11297,27 @@ lpfc_sli4_get_iocb_cnt(struct lpfc_hba *phba)
 }
 
 
+static void
+lpfc_log_write_firmware_error(struct lpfc_hba *phba, uint32_t offset,
+   uint32_t magic_number, uint32_t ftype, uint32_t fid, uint32_t fsize,
+   const struct firmware *fw)
+{
+   if (offset == ADD_STATUS_FW_NOT_SUPPORTED)
+   lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+   "3030 This firmware version is not supported on "
+   "this HBA model. Device:%x Magic:%x Type:%x "
+   "ID:%x Size %d %zd\n",
+   phba->pcidev->device, magic_number, ftype, fid,
+   fsize, fw->size);
+   else
+   lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+   "3022 FW Download failed. Device:%x Magic:%x Type:%x "
+   "ID:%x Size %d %zd\n",
+   phba->pcidev->device, magic_number, ftype, fid,
+   fsize, fw->size);
+}
+
+
 /**
  * lpfc_write_firmware - attempt to write a firmware image to the port
  * @fw: pointer to firmware image returned from request_firmware.
@@ -11324,20 +11345,10 @@ lpfc_write_firmware(const struct firmware *fw, void 
*context)
 
magic_number = be32_to_cpu(image->magic_number);
ftype = bf_get_be32(lpfc_grp_hdr_file_type, image);
-   fid = bf_get_be32(lpfc_grp_hdr_id, image),
+   fid = bf_get_be32(lpfc_grp_hdr_id, image);
fsize = be32_to_cpu(image->size);
 
INIT_LIST_HEAD(_buffer_list);
-   if ((magic_number != LPFC_GROUP_OJECT_MAGIC_G5 &&
-magic_number != LPFC_GROUP_OJECT_MAGIC_G6) ||
-   ftype != LPFC_FILE_TYPE_GROUP || fsize != fw->size) {
-   lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
-   "3022 Invalid FW image found. "
-   "Magic:%x Type:%x ID:%x Size %d %zd\n",
-   magic_number, ftype, fid, fsize, fw->size);
-   rc = -EINVAL;
-   goto release_out;
-   }
lpfc_decode_firmware_rev(phba, fwrev, 1);
if (strncmp(fwrev, image->revision, strnlen(image->revision, 16))) {
lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
@@ -11378,11 +11389,18 @@ lpfc_write_firmware(const struct firmware *fw, void 
*context)
}
rc = lpfc_wr_object(phba, _buffer_list,
(fw->size - offset), );
-   if (rc)
+   if (rc) {
+   lpfc_log_write_firmware_error(phba, offset,
+   magic_number, ftype, fid, fsize, fw);
goto release_out;
+   }
}
rc = offset;
-   }
+   } else
+   lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
+   "3029 Skipped Firmware update, Current "
+   "Version:%s New Version:%s\n",
+   fwrev, image->revision);
 
 release_out:
list_for_each_entry_safe(dmabuf, next, _buffer_list, list) {
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 

[PATCH v5 13/13] lpfc: Change Copyright of 12.0.0.0 modified files to 2018

2018-02-22 Thread James Smart
Updated Copyright in files updated as part of 12.0.0.0

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
Reviewed-by: Johannes Thumshirn 

---
v3:
  patch title
---
 drivers/scsi/lpfc/lpfc_bsg.c | 2 +-
 drivers/scsi/lpfc/lpfc_ct.c  | 2 +-
 drivers/scsi/lpfc/lpfc_debugfs.c | 2 +-
 drivers/scsi/lpfc/lpfc_debugfs.h | 2 +-
 drivers/scsi/lpfc/lpfc_hw.h  | 2 +-
 drivers/scsi/lpfc/lpfc_ids.h | 2 +-
 6 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index 8b33b652226b..0f174ca80f67 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -1,7 +1,7 @@
 /***
  * This file is part of the Emulex Linux Device Driver for *
  * Fibre Channel Host Bus Adapters.*
- * Copyright (C) 2017 Broadcom. All Rights Reserved. The term  *
+ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
  * “Broadcom” refers to Broadcom Limited and/or its subsidiaries.  *
  * Copyright (C) 2009-2015 Emulex.  All rights reserved.   *
  * EMULEX and SLI are trademarks of Emulex.*
diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index 03a7e13a049d..ebe8ac1b88e7 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -1,7 +1,7 @@
 /***
  * This file is part of the Emulex Linux Device Driver for *
  * Fibre Channel Host Bus Adapters.*
- * Copyright (C) 2017 Broadcom. All Rights Reserved. The term  *
+ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
  * “Broadcom” refers to Broadcom Limited and/or its subsidiaries.  *
  * Copyright (C) 2004-2016 Emulex.  All rights reserved.   *
  * EMULEX and SLI are trademarks of Emulex.*
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index 308303d501cf..fb0dc2aeed91 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -1,7 +1,7 @@
 /***
  * This file is part of the Emulex Linux Device Driver for *
  * Fibre Channel Host Bus Adapters.*
- * Copyright (C) 2017 Broadcom. All Rights Reserved. The term  *
+ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
  * “Broadcom” refers to Broadcom Limited and/or its subsidiaries.  *
  * Copyright (C) 2007-2015 Emulex.  All rights reserved.   *
  * EMULEX and SLI are trademarks of Emulex.*
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h
index 12fbf498a7ce..f32eaeb2225a 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.h
+++ b/drivers/scsi/lpfc/lpfc_debugfs.h
@@ -1,7 +1,7 @@
 /***
  * This file is part of the Emulex Linux Device Driver for *
  * Fibre Channel Host Bus Adapters.*
- * Copyright (C) 2017 Broadcom. All Rights Reserved. The term  *
+ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
  * “Broadcom” refers to Broadcom Limited and/or its subsidiaries.  *
  * Copyright (C) 2007-2011 Emulex.  All rights reserved.   *
  * EMULEX and SLI are trademarks of Emulex.*
diff --git a/drivers/scsi/lpfc/lpfc_hw.h b/drivers/scsi/lpfc/lpfc_hw.h
index cf83322cd4fe..08a3f1520159 100644
--- a/drivers/scsi/lpfc/lpfc_hw.h
+++ b/drivers/scsi/lpfc/lpfc_hw.h
@@ -1,7 +1,7 @@
 /***
  * This file is part of the Emulex Linux Device Driver for *
  * Fibre Channel Host Bus Adapters.*
- * Copyright (C) 2017 Broadcom. All Rights Reserved. The term  *
+ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
  * “Broadcom” refers to Broadcom Limited and/or its subsidiaries.  *
  * Copyright (C) 2004-2016 Emulex.  All rights reserved.   *
  * EMULEX and SLI are trademarks of Emulex.*
diff --git a/drivers/scsi/lpfc/lpfc_ids.h b/drivers/scsi/lpfc/lpfc_ids.h
index 329c8d28869c..07ee34017d88 100644
--- a/drivers/scsi/lpfc/lpfc_ids.h
+++ b/drivers/scsi/lpfc/lpfc_ids.h
@@ -1,7 +1,7 @@
 /***
  * This file is part of the Emulex Linux Device Driver for *
  * Fibre Channel Host Bus Adapters.*
- * Copyright (C) 2017 Broadcom. All Rights Reserved. The term  *
+ * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term *
  * “Broadcom” refers to Broadcom Limited and/or its subsidiaries.  *
  * Copyright (C) 

[PATCH v5 01/13] lpfc: Rework lpfc to allow different sli4 cq and eq handlers

2018-02-22 Thread James Smart
Up until now, an SLI-4 device had no variance in the way it handled
its EQs and CQs. With newer hardware, there are now differences in
doorbells and some differences in how entries are valid.

Prepare the code for new hardware by creating a sli4-based callout
table that can be set based on if_type.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
Reviewed-by: Johannes Thumshirn 
---
 drivers/scsi/lpfc/lpfc_init.c |  7 +
 drivers/scsi/lpfc/lpfc_sli.c  | 63 ++-
 drivers/scsi/lpfc/lpfc_sli4.h |  5 
 3 files changed, 44 insertions(+), 31 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 465d890220d5..e24dca2b3f2f 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -9540,6 +9540,13 @@ lpfc_sli4_pci_mem_setup(struct lpfc_hba *phba)
}
}
 
+   /* Set up the EQ/CQ register handeling functions now */
+   if (if_type <= LPFC_SLI_INTF_IF_TYPE_2) {
+   phba->sli4_hba.sli4_eq_clr_intr = lpfc_sli4_eq_clr_intr;
+   phba->sli4_hba.sli4_eq_release = lpfc_sli4_eq_release;
+   phba->sli4_hba.sli4_cq_release = lpfc_sli4_cq_release;
+   }
+
return 0;
 
 out_iounmap_all:
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index e97d080e9f65..f91caae6489a 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -299,7 +299,7 @@ lpfc_sli4_eq_get(struct lpfc_queue *q)
  * @q: The Event Queue to disable interrupts
  *
  **/
-static inline void
+inline void
 lpfc_sli4_eq_clr_intr(struct lpfc_queue *q)
 {
struct lpfc_register doorbell;
@@ -5302,41 +5302,42 @@ static void
 lpfc_sli4_arm_cqeq_intr(struct lpfc_hba *phba)
 {
int qidx;
+   struct lpfc_sli4_hba *sli4_hba = >sli4_hba;
 
-   lpfc_sli4_cq_release(phba->sli4_hba.mbx_cq, LPFC_QUEUE_REARM);
-   lpfc_sli4_cq_release(phba->sli4_hba.els_cq, LPFC_QUEUE_REARM);
-   if (phba->sli4_hba.nvmels_cq)
-   lpfc_sli4_cq_release(phba->sli4_hba.nvmels_cq,
+   sli4_hba->sli4_cq_release(sli4_hba->mbx_cq, LPFC_QUEUE_REARM);
+   sli4_hba->sli4_cq_release(sli4_hba->els_cq, LPFC_QUEUE_REARM);
+   if (sli4_hba->nvmels_cq)
+   sli4_hba->sli4_cq_release(sli4_hba->nvmels_cq,
LPFC_QUEUE_REARM);
 
-   if (phba->sli4_hba.fcp_cq)
+   if (sli4_hba->fcp_cq)
for (qidx = 0; qidx < phba->cfg_fcp_io_channel; qidx++)
-   lpfc_sli4_cq_release(phba->sli4_hba.fcp_cq[qidx],
+   sli4_hba->sli4_cq_release(sli4_hba->fcp_cq[qidx],
LPFC_QUEUE_REARM);
 
-   if (phba->sli4_hba.nvme_cq)
+   if (sli4_hba->nvme_cq)
for (qidx = 0; qidx < phba->cfg_nvme_io_channel; qidx++)
-   lpfc_sli4_cq_release(phba->sli4_hba.nvme_cq[qidx],
+   sli4_hba->sli4_cq_release(sli4_hba->nvme_cq[qidx],
LPFC_QUEUE_REARM);
 
if (phba->cfg_fof)
-   lpfc_sli4_cq_release(phba->sli4_hba.oas_cq, LPFC_QUEUE_REARM);
+   sli4_hba->sli4_cq_release(sli4_hba->oas_cq, LPFC_QUEUE_REARM);
 
-   if (phba->sli4_hba.hba_eq)
+   if (sli4_hba->hba_eq)
for (qidx = 0; qidx < phba->io_channel_irqs; qidx++)
-   lpfc_sli4_eq_release(phba->sli4_hba.hba_eq[qidx],
-   LPFC_QUEUE_REARM);
+   sli4_hba->sli4_eq_release(sli4_hba->hba_eq[qidx],
+   LPFC_QUEUE_REARM);
 
if (phba->nvmet_support) {
for (qidx = 0; qidx < phba->cfg_nvmet_mrq; qidx++) {
-   lpfc_sli4_cq_release(
-   phba->sli4_hba.nvmet_cqset[qidx],
+   sli4_hba->sli4_cq_release(
+   sli4_hba->nvmet_cqset[qidx],
LPFC_QUEUE_REARM);
}
}
 
if (phba->cfg_fof)
-   lpfc_sli4_eq_release(phba->sli4_hba.fof_eq, LPFC_QUEUE_REARM);
+   sli4_hba->sli4_eq_release(sli4_hba->fof_eq, LPFC_QUEUE_REARM);
 }
 
 /**
@@ -7270,7 +7271,7 @@ lpfc_sli4_mbox_completions_pending(struct lpfc_hba *phba)
 bool
 lpfc_sli4_process_missed_mbox_completions(struct lpfc_hba *phba)
 {
-
+   struct lpfc_sli4_hba *sli4_hba = >sli4_hba;
uint32_t eqidx;
struct lpfc_queue *fpeq = NULL;
struct lpfc_eqe *eqe;
@@ -7281,11 +7282,11 @@ lpfc_sli4_process_missed_mbox_completions(struct 
lpfc_hba *phba)
 
/* Find the eq associated with the mcq */
 
-   if (phba->sli4_hba.hba_eq)
+   if (sli4_hba->hba_eq)
for (eqidx = 0; eqidx < phba->io_channel_irqs; eqidx++)
-   

[PATCH v5 03/13] lpfc: Add SLI-4 if_type=6 support to the code base

2018-02-22 Thread James Smart
New hardware supports a SLI-4 interface, but with a new if_type
variant of 6.

If_type=6 has a different PCI BAR map, separate EQ/CQ doorbells,
and some changes in doorbell formats.

Add the changes for the if_type into headers, adapter initialization
and control flows. Add new eq and cq handlers.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
Reviewed-by: Johannes Thumshirn 
---
 drivers/scsi/lpfc/lpfc_bsg.c  |   4 +-
 drivers/scsi/lpfc/lpfc_hw4.h  |  54 ++-
 drivers/scsi/lpfc/lpfc_init.c | 120 +++---
 drivers/scsi/lpfc/lpfc_sli.c  | 120 --
 drivers/scsi/lpfc/lpfc_sli4.h |   3 ++
 5 files changed, 275 insertions(+), 26 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_bsg.c b/drivers/scsi/lpfc/lpfc_bsg.c
index d89816222b23..8b33b652226b 100644
--- a/drivers/scsi/lpfc/lpfc_bsg.c
+++ b/drivers/scsi/lpfc/lpfc_bsg.c
@@ -3867,7 +3867,7 @@ lpfc_bsg_sli_cfg_read_cmd_ext(struct lpfc_hba *phba, 
struct bsg_job *job,
"ext_buf_cnt:%d\n", ext_buf_cnt);
} else {
/* sanity check on interface type for support */
-   if (bf_get(lpfc_sli_intf_if_type, >sli4_hba.sli_intf) !=
+   if (bf_get(lpfc_sli_intf_if_type, >sli4_hba.sli_intf) <
LPFC_SLI_INTF_IF_TYPE_2) {
rc = -ENODEV;
goto job_error;
@@ -4053,7 +4053,7 @@ lpfc_bsg_sli_cfg_write_cmd_ext(struct lpfc_hba *phba, 
struct bsg_job *job,
"ext_buf_cnt:%d\n", ext_buf_cnt);
} else {
/* sanity check on interface type for support */
-   if (bf_get(lpfc_sli_intf_if_type, >sli4_hba.sli_intf) !=
+   if (bf_get(lpfc_sli_intf_if_type, >sli4_hba.sli_intf) <
LPFC_SLI_INTF_IF_TYPE_2)
return -ENODEV;
/* nemb_tp == nemb_hbd */
diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h
index 8685d26e6929..93fd9fd10a0f 100644
--- a/drivers/scsi/lpfc/lpfc_hw4.h
+++ b/drivers/scsi/lpfc/lpfc_hw4.h
@@ -84,6 +84,7 @@ struct lpfc_sli_intf {
 #define LPFC_SLI_INTF_IF_TYPE_00
 #define LPFC_SLI_INTF_IF_TYPE_11
 #define LPFC_SLI_INTF_IF_TYPE_22
+#define LPFC_SLI_INTF_IF_TYPE_66
 #define lpfc_sli_intf_sli_family_SHIFT 8
 #define lpfc_sli_intf_sli_family_MASK  0x000F
 #define lpfc_sli_intf_sli_family_WORD  word0
@@ -731,11 +732,13 @@ struct lpfc_register {
  * register sets depending on the UCNA Port's reported if_type
  * value.  For UCNA ports running SLI4 and if_type 0, they reside in
  * BAR4.  For UCNA ports running SLI4 and if_type 2, they reside in
- * BAR0.  The offsets are the same so the driver must account for
- * any base address difference.
+ * BAR0.  For FC ports running SLI4 and if_type 6, they reside in
+ * BAR2. The offsets and base address are different,  so the driver
+ * has to compute the register addresses accordingly
  */
 #define LPFC_ULP0_RQ_DOORBELL  0x00A0
 #define LPFC_ULP1_RQ_DOORBELL  0x00C0
+#define LPFC_IF6_RQ_DOORBELL   0x0080
 #define lpfc_rq_db_list_fm_num_posted_SHIFT24
 #define lpfc_rq_db_list_fm_num_posted_MASK 0x00FF
 #define lpfc_rq_db_list_fm_num_posted_WORD word0
@@ -770,6 +773,20 @@ struct lpfc_register {
 #define lpfc_wq_db_ring_fm_id_MASK  0x
 #define lpfc_wq_db_ring_fm_id_WORD  word0
 
+#define LPFC_IF6_WQ_DOORBELL   0x0040
+#define lpfc_if6_wq_db_list_fm_num_posted_SHIFT24
+#define lpfc_if6_wq_db_list_fm_num_posted_MASK 0x00FF
+#define lpfc_if6_wq_db_list_fm_num_posted_WORD word0
+#define lpfc_if6_wq_db_list_fm_dpp_SHIFT   23
+#define lpfc_if6_wq_db_list_fm_dpp_MASK0x0001
+#define lpfc_if6_wq_db_list_fm_dpp_WORDword0
+#define lpfc_if6_wq_db_list_fm_dpp_id_SHIFT16
+#define lpfc_if6_wq_db_list_fm_dpp_id_MASK 0x001F
+#define lpfc_if6_wq_db_list_fm_dpp_id_WORD word0
+#define lpfc_if6_wq_db_list_fm_id_SHIFT0
+#define lpfc_if6_wq_db_list_fm_id_MASK 0x
+#define lpfc_if6_wq_db_list_fm_id_WORD word0
+
 #define LPFC_EQCQ_DOORBELL 0x0120
 #define lpfc_eqcq_doorbell_se_SHIFT31
 #define lpfc_eqcq_doorbell_se_MASK 0x0001
@@ -805,6 +822,38 @@ struct lpfc_register {
 #define LPFC_CQID_HI_FIELD_SHIFT   10
 #define LPFC_EQID_HI_FIELD_SHIFT   9
 
+#define LPFC_IF6_CQ_DOORBELL   0x00C0
+#define lpfc_if6_cq_doorbell_se_SHIFT  31
+#define lpfc_if6_cq_doorbell_se_MASK   0x0001
+#define lpfc_if6_cq_doorbell_se_WORD   word0
+#define LPFC_IF6_CQ_SOLICIT_ENABLE_OFF 0
+#define LPFC_IF6_CQ_SOLICIT_ENABLE_ON  1
+#define lpfc_if6_cq_doorbell_arm_SHIFT   

[PATCH v5 02/13] lpfc: Rework sli4 doorbell infrastructure

2018-02-22 Thread James Smart
Up until now, all SLI-4 devices had the same doorbells at the same
bar locations. With newer hardware, there are now independent EQ and
CQ doorbells and the bar locations differ.

Prepare the code for new hardware by separating the eq/cq doorbell into
separate components. The components can be set based on if_type.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
Reviewed-by: Johannes Thumshirn 
---
 drivers/scsi/lpfc/lpfc_debugfs.c | 20 ++--
 drivers/scsi/lpfc/lpfc_debugfs.h | 11 ++-
 drivers/scsi/lpfc/lpfc_init.c|  9 ++---
 drivers/scsi/lpfc/lpfc_sli.c |  8 
 drivers/scsi/lpfc/lpfc_sli4.h|  3 ++-
 5 files changed, 32 insertions(+), 19 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index 17ea3bb04266..308303d501cf 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -3944,10 +3944,15 @@ lpfc_idiag_drbacc_read_reg(struct lpfc_hba *phba, char 
*pbuffer,
return 0;
 
switch (drbregid) {
-   case LPFC_DRB_EQCQ:
-   len += snprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len,
-   "EQCQ-DRB-REG: 0x%08x\n",
-   readl(phba->sli4_hba.EQCQDBregaddr));
+   case LPFC_DRB_EQ:
+   len += snprintf(pbuffer + len, LPFC_DRB_ACC_BUF_SIZE-len,
+   "EQ-DRB-REG: 0x%08x\n",
+   readl(phba->sli4_hba.EQDBregaddr));
+   break;
+   case LPFC_DRB_CQ:
+   len += snprintf(pbuffer + len, LPFC_DRB_ACC_BUF_SIZE - len,
+   "CQ-DRB-REG: 0x%08x\n",
+   readl(phba->sli4_hba.CQDBregaddr));
break;
case LPFC_DRB_MQ:
len += snprintf(pbuffer+len, LPFC_DRB_ACC_BUF_SIZE-len,
@@ -4086,8 +4091,11 @@ lpfc_idiag_drbacc_write(struct file *file, const char 
__user *buf,
idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_ST ||
idiag.cmd.opcode == LPFC_IDIAG_CMD_DRBACC_CL) {
switch (drb_reg_id) {
-   case LPFC_DRB_EQCQ:
-   drb_reg = phba->sli4_hba.EQCQDBregaddr;
+   case LPFC_DRB_EQ:
+   drb_reg = phba->sli4_hba.EQDBregaddr;
+   break;
+   case LPFC_DRB_CQ:
+   drb_reg = phba->sli4_hba.CQDBregaddr;
break;
case LPFC_DRB_MQ:
drb_reg = phba->sli4_hba.MQDBregaddr;
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.h b/drivers/scsi/lpfc/lpfc_debugfs.h
index c4edd87bfc65..12fbf498a7ce 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.h
+++ b/drivers/scsi/lpfc/lpfc_debugfs.h
@@ -126,12 +126,13 @@
 #define LPFC_DRB_ACC_WR_CMD_ARG 2
 #define LPFC_DRB_ACC_BUF_SIZE 256
 
-#define LPFC_DRB_EQCQ 1
-#define LPFC_DRB_MQ   2
-#define LPFC_DRB_WQ   3
-#define LPFC_DRB_RQ   4
+#define LPFC_DRB_EQ   1
+#define LPFC_DRB_CQ   2
+#define LPFC_DRB_MQ   3
+#define LPFC_DRB_WQ   4
+#define LPFC_DRB_RQ   5
 
-#define LPFC_DRB_MAX  4
+#define LPFC_DRB_MAX  5
 
 #define IDIAG_DRBACC_REGID_INDX 0
 #define IDIAG_DRBACC_VALUE_INDX 1
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index e24dca2b3f2f..b2cf8eb99008 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -7430,8 +7430,9 @@ lpfc_sli4_bar0_register_memmap(struct lpfc_hba *phba, 
uint32_t if_type)
phba->sli4_hba.WQDBregaddr =
phba->sli4_hba.conf_regs_memmap_p +
LPFC_ULP0_WQ_DOORBELL;
-   phba->sli4_hba.EQCQDBregaddr =
+   phba->sli4_hba.CQDBregaddr =
phba->sli4_hba.conf_regs_memmap_p + LPFC_EQCQ_DOORBELL;
+   phba->sli4_hba.EQDBregaddr = phba->sli4_hba.CQDBregaddr;
phba->sli4_hba.MQDBregaddr =
phba->sli4_hba.conf_regs_memmap_p + LPFC_MQ_DOORBELL;
phba->sli4_hba.BMBXregaddr =
@@ -7488,8 +7489,10 @@ lpfc_sli4_bar2_register_memmap(struct lpfc_hba *phba, 
uint32_t vf)
phba->sli4_hba.WQDBregaddr = (phba->sli4_hba.drbl_regs_memmap_p +
vf * LPFC_VFR_PAGE_SIZE +
LPFC_ULP0_WQ_DOORBELL);
-   phba->sli4_hba.EQCQDBregaddr = (phba->sli4_hba.drbl_regs_memmap_p +
-   vf * LPFC_VFR_PAGE_SIZE + LPFC_EQCQ_DOORBELL);
+   phba->sli4_hba.CQDBregaddr = (phba->sli4_hba.drbl_regs_memmap_p +
+   vf * LPFC_VFR_PAGE_SIZE +
+   LPFC_EQCQ_DOORBELL);
+   phba->sli4_hba.EQDBregaddr = phba->sli4_hba.CQDBregaddr;
phba->sli4_hba.MQDBregaddr = (phba->sli4_hba.drbl_regs_memmap_p +
vf * LPFC_VFR_PAGE_SIZE 

[PATCH 2/3] qla2xxx: do not check login_state if no loop id is assigned

2018-02-22 Thread Hannes Reinecke
When no loop id is assigned in qla24xx_fcport_handle_login()
the login state needs to be ignored; it will get set later on
in qla_chk_n2n_b4_login().

Cc: Quinn Tran 
Cc: Himanshu Madhani 
Fixes: 040036bb0bc1 ("scsi: qla2xxx: Delay loop id allocation at login")
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/qla2xxx/qla_init.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 4dd897c2c2b1..a19ed53ba6d9 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -1174,8 +1174,9 @@ int qla24xx_fcport_handle_login(struct scsi_qla_host 
*vha, fc_port_t *fcport)
if (fcport->scan_state != QLA_FCPORT_FOUND)
return 0;
 
-   if ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
-   (fcport->fw_login_state == DSC_LS_PRLI_PEND))
+   if ((fcport->loop_id != FC_NO_LOOP_ID) &&
+   ((fcport->fw_login_state == DSC_LS_PLOGI_PEND) ||
+(fcport->fw_login_state == DSC_LS_PRLI_PEND)))
return 0;
 
if (fcport->fw_login_state == DSC_LS_PLOGI_COMP) {
-- 
2.12.3



[PATCH 0/3] qla2xxx: driver fails to log into remote ports

2018-02-22 Thread Hannes Reinecke
Hi all,

with the latest updates the qla2xxx driver fails to log into remote
ports, whereas P2P connections continued to work.
After a lengthy debugging session I found that latest update has
several less-than-perfect patches, all of which contributing to
the failed (or, rather, not attempted) login.
With these patches the problem is no longer seen and the driver
behaves as expected.

As usual, comments and reviews are welcome.

Hannes Reinecke (3):
  qla2xxx: Fixup locking for session deletion
  qla2xxx: do not check login_state if no loop id is assigned
  qla2xxx: ensure async flags are reset correctly

 drivers/scsi/qla2xxx/qla_def.h|  4 ++--
 drivers/scsi/qla2xxx/qla_gs.c |  2 ++
 drivers/scsi/qla2xxx/qla_init.c   | 42 ++-
 drivers/scsi/qla2xxx/qla_os.c |  7 ++-
 drivers/scsi/qla2xxx/qla_target.c | 17 ++--
 5 files changed, 44 insertions(+), 28 deletions(-)

-- 
2.12.3



[PATCH 3/3] qla2xxx: ensure async flags are reset correctly

2018-02-22 Thread Hannes Reinecke
The fcport flags FCF_ASYNC_ACTIVE and FCF_ASYNC_SENT are used
to throttle the state machine, so we need to ensure to always
set and unset them correctly. Not doing so will lead to the
state machine getting confused and no login attempt into
remote ports.

Cc: Quinn Tran 
Cc: Himanshu Madhani 
Fixes: 3dbec59bdf63 ("scsi: qla2xxx: Prevent multiple active discovery commands 
per session")
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/qla2xxx/qla_gs.c   |  2 ++
 drivers/scsi/qla2xxx/qla_init.c | 13 ++---
 2 files changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
index e4d404c24506..3cb05c1bd7bf 100644
--- a/drivers/scsi/qla2xxx/qla_gs.c
+++ b/drivers/scsi/qla2xxx/qla_gs.c
@@ -3177,6 +3177,7 @@ int qla24xx_async_gidpn(scsi_qla_host_t *vha, fc_port_t 
*fcport)
sp->free(sp);
fcport->flags &= ~FCF_ASYNC_SENT;
 done:
+   fcport->flags &= ~FCF_ASYNC_ACTIVE;
return rval;
 }
 
@@ -3368,6 +3369,7 @@ int qla24xx_async_gpsc(scsi_qla_host_t *vha, fc_port_t 
*fcport)
sp->free(sp);
fcport->flags &= ~FCF_ASYNC_SENT;
 done:
+   fcport->flags &= ~FCF_ASYNC_ACTIVE;
return rval;
 }
 
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index a19ed53ba6d9..df31c396d206 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -228,6 +228,7 @@ qla2x00_async_login(struct scsi_qla_host *vha, fc_port_t 
*fcport,
sp->free(sp);
fcport->flags &= ~FCF_ASYNC_SENT;
 done:
+   fcport->flags &= ~FCF_ASYNC_ACTIVE;
return rval;
 }
 
@@ -280,7 +281,7 @@ qla2x00_async_logout(struct scsi_qla_host *vha, fc_port_t 
*fcport)
 done_free_sp:
sp->free(sp);
 done:
-   fcport->flags &= ~FCF_ASYNC_SENT;
+   fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
return rval;
 }
 
@@ -288,6 +289,7 @@ void
 qla2x00_async_prlo_done(struct scsi_qla_host *vha, fc_port_t *fcport,
 uint16_t *data)
 {
+   fcport->flags &= ~FCF_ASYNC_ACTIVE;
/* Don't re-login in target mode */
if (!fcport->tgt_session)
qla2x00_mark_device_lost(vha, fcport, 1, 0);
@@ -301,6 +303,7 @@ qla2x00_async_prlo_sp_done(void *s, int res)
struct srb_iocb *lio = >u.iocb_cmd;
struct scsi_qla_host *vha = sp->vha;
 
+   sp->fcport->flags &= ~FCF_ASYNC_ACTIVE;
if (!test_bit(UNLOADING, >dpc_flags))
qla2x00_post_async_prlo_done_work(sp->fcport->vha, sp->fcport,
lio->u.logio.data);
@@ -339,6 +342,7 @@ qla2x00_async_prlo(struct scsi_qla_host *vha, fc_port_t 
*fcport)
 done_free_sp:
sp->free(sp);
 done:
+   fcport->flags &= ~FCF_ASYNC_ACTIVE;
return rval;
 }
 
@@ -392,6 +396,8 @@ qla2x00_async_adisc_sp_done(void *ptr, int res)
"Async done-%s res %x %8phC\n",
sp->name, res, sp->fcport->port_name);
 
+   sp->fcport->flags &= ~FCF_ASYNC_SENT;
+
memset(, 0, sizeof(ea));
ea.event = FCME_ADISC_DONE;
ea.rc = res;
@@ -442,7 +448,7 @@ qla2x00_async_adisc(struct scsi_qla_host *vha, fc_port_t 
*fcport,
 done_free_sp:
sp->free(sp);
 done:
-   fcport->flags &= ~FCF_ASYNC_SENT;
+   fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
qla2x00_post_async_adisc_work(vha, fcport, data);
return rval;
 }
@@ -1815,6 +1821,7 @@ qla2x00_async_logout_done(struct scsi_qla_host *vha, 
fc_port_t *fcport,
qla2x00_mark_device_lost(vha, fcport, 1, 0);
qlt_logo_completion_handler(fcport, data[0]);
fcport->login_gen++;
+   fcport->flags &= ~FCF_ASYNC_ACTIVE;
return;
 }
 
@@ -1822,6 +1829,7 @@ void
 qla2x00_async_adisc_done(struct scsi_qla_host *vha, fc_port_t *fcport,
 uint16_t *data)
 {
+   fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
if (data[0] == MBS_COMMAND_COMPLETE) {
qla2x00_update_fcport(vha, fcport);
 
@@ -1829,7 +1837,6 @@ qla2x00_async_adisc_done(struct scsi_qla_host *vha, 
fc_port_t *fcport,
}
 
/* Retry login. */
-   fcport->flags &= ~FCF_ASYNC_SENT;
if (data[1] & QLA_LOGIO_LOGIN_RETRIED)
set_bit(RELOGIN_NEEDED, >dpc_flags);
else
-- 
2.12.3



[PATCH 1/3] qla2xxx: Fixup locking for session deletion

2018-02-22 Thread Hannes Reinecke
Commit d8630bb95f46 ('Serialize session deletion by using work_lock') tries
to fixup a deadlock when deleting sessions, but fails to take
into account the locking rules. This patch resolves the situation
by introducing a separate lock for processing the GNLIST response, and
ensures that sess_lock is released before calling
qlt_schedule_sess_delete().

Cc: Himanshu Madhani 
Cc: Quinn Tran 
Fixes: d8630bb95f46 ("scsi: qla2xxx: Serialize session deletion by using 
work_lock")
Signed-off-by: Hannes Reinecke 
---
 drivers/scsi/qla2xxx/qla_def.h|  4 ++--
 drivers/scsi/qla2xxx/qla_init.c   | 24 +++-
 drivers/scsi/qla2xxx/qla_os.c |  7 ++-
 drivers/scsi/qla2xxx/qla_target.c | 17 ++---
 4 files changed, 29 insertions(+), 23 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index be7d6824581a..3ca4b6a5eddd 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -261,9 +261,9 @@
 struct name_list_extended {
struct get_name_list_extended *l;
dma_addr_t  ldma;
-   struct list_headfcports;/* protect by sess_list */
+   struct list_headfcports;
+   spinlock_t  fcports_lock;
u32 size;
-   u8  sent;
 };
 /*
  * Timeout timer counts in seconds
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index 590aa904fdef..4dd897c2c2b1 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -660,8 +660,7 @@ qla24xx_async_gnl_sp_done(void *s, int res)
(loop_id & 0x7fff));
}
 
-   spin_lock_irqsave(>hw->tgt.sess_lock, flags);
-   vha->gnl.sent = 0;
+   spin_lock_irqsave(>gnl.fcports_lock, flags);
 
INIT_LIST_HEAD();
fcport = tf = NULL;
@@ -670,12 +669,16 @@ qla24xx_async_gnl_sp_done(void *s, int res)
 
list_for_each_entry_safe(fcport, tf, , gnl_entry) {
list_del_init(>gnl_entry);
+   spin_lock(>hw->tgt.sess_lock);
fcport->flags &= ~(FCF_ASYNC_SENT | FCF_ASYNC_ACTIVE);
+   spin_unlock(>hw->tgt.sess_lock);
ea.fcport = fcport;
 
qla2x00_fcport_event_handler(vha, );
}
+   spin_unlock_irqrestore(>gnl.fcports_lock, flags);
 
+   spin_lock_irqsave(>hw->tgt.sess_lock, flags);
/* create new fcport if fw has knowledge of new sessions */
for (i = 0; i < n; i++) {
port_id_t id;
@@ -727,18 +730,21 @@ int qla24xx_async_gnl(struct scsi_qla_host *vha, 
fc_port_t *fcport)
ql_dbg(ql_dbg_disc, vha, 0x20d9,
"Async-gnlist WWPN %8phC \n", fcport->port_name);
 
-   spin_lock_irqsave(>hw->tgt.sess_lock, flags);
+   spin_lock_irqsave(>gnl.fcports_lock, flags);
+   if (!list_empty(>gnl_entry)) {
+   spin_unlock_irqrestore(>gnl.fcports_lock, flags);
+   rval = QLA_SUCCESS;
+   goto done;
+   }
+
+   spin_lock(>hw->tgt.sess_lock);
fcport->disc_state = DSC_GNL;
fcport->last_rscn_gen = fcport->rscn_gen;
fcport->last_login_gen = fcport->login_gen;
+   spin_unlock(>hw->tgt.sess_lock);
 
list_add_tail(>gnl_entry, >gnl.fcports);
-   if (vha->gnl.sent) {
-   spin_unlock_irqrestore(>hw->tgt.sess_lock, flags);
-   return QLA_SUCCESS;
-   }
-   vha->gnl.sent = 1;
-   spin_unlock_irqrestore(>hw->tgt.sess_lock, flags);
+   spin_unlock_irqrestore(>gnl.fcports_lock, flags);
 
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp)
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 12ee6e02d146..dc2b188fdce1 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -4575,6 +4575,7 @@ struct scsi_qla_host *qla2x00_create_host(struct 
scsi_host_template *sht,
 
spin_lock_init(>work_lock);
spin_lock_init(>cmd_list_lock);
+   spin_lock_init(>gnl.fcports_lock);
init_waitqueue_head(>fcport_waitQ);
init_waitqueue_head(>vref_waitq);
 
@@ -4875,6 +4876,8 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, 
struct qla_work_evt *e)
}
qlt_plogi_ack_unref(vha, pla);
} else {
+   fc_port_t *dfcp = NULL;
+
spin_lock_irqsave(>hw->tgt.sess_lock, flags);
tfcp = qla2x00_find_fcport_by_nportid(vha,
>u.new_sess.id, 1);
@@ -4897,11 +4900,13 @@ void qla24xx_create_new_sess(struct scsi_qla_host *vha, 
struct qla_work_evt *e)
default:
fcport->login_pause = 1;
tfcp->conflict = fcport;
-