Re: [PATCH v3 14/23] scsi: hisi_sas: add v3 cq interrupt handler

2017-05-31 Thread Christoph Hellwig
> + case SAS_PROTOCOL_SSP:
> + {
> + unsigned char op = task->ssp_task.cmd->cmnd[0];
> +
> + if (op == READ_6 || op == WRITE_6 ||
> + op == READ_10 || op == WRITE_10 ||
> + op == READ_12 || op == WRITE_12 ||
> + op == READ_16 || op == WRITE_16)
> + return true;
> + break;
> + }

Wee. why do you care?  What about 32-byte CDs or things like Write Same?


Re: [PATCH v3 13/23] scsi: hisi_sas: add phy up/down/bcast and channel ISR

2017-05-31 Thread Christoph Hellwig
On Wed, May 31, 2017 at 10:33:05PM +0800, John Garry wrote:
> From: Xiang Chen 
> 
> Add code to initialise interrupts and add some interrupt handlers.
> 
> Signed-off-by: John Garry 
> Signed-off-by: Xiang Chen 
> ---
>  drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 281 
> +
>  1 file changed, 281 insertions(+)
> 
> diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
> b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
> index 9651658..49f14d2 100644
> --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
> +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
> @@ -173,6 +173,13 @@ enum {
>   HISI_SAS_PHY_INT_NR
>  };
>  
> +static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off)
> +{
> + void __iomem *regs = hisi_hba->regs + off;
> +
> + return readl(regs);
> +}
> +
>  static void hisi_sas_write32(struct hisi_hba *hisi_hba, u32 off, u32 val)
>  {
>   void __iomem *regs = hisi_hba->regs + off;
> @@ -397,6 +404,276 @@ static void sl_notify_v3_hw(struct hisi_hba *hisi_hba, 
> int phy_no)
>   hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL, sl_control);
>  }
>  
> +static int phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
> +{
> + int i, res = 0;
> + u32 context, port_id, link_rate, hard_phy_linkrate;
> + struct hisi_sas_phy *phy = _hba->phy[phy_no];
> + struct asd_sas_phy *sas_phy = >sas_phy;
> + struct device *dev = hisi_hba->dev;
> +
> + hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 1);
> +
> + port_id = hisi_sas_read32(hisi_hba, PHY_PORT_NUM_MA);
> + port_id = (port_id >> (4 * phy_no)) & 0xf;
> + link_rate = hisi_sas_read32(hisi_hba, PHY_CONN_RATE);
> + link_rate = (link_rate >> (phy_no * 4)) & 0xf;
> +
> + if (port_id == 0xf) {
> + dev_err(dev, "phyup: phy%d invalid portid\n", phy_no);
> + res = IRQ_NONE;
> + goto end;
> + }
> + sas_phy->linkrate = link_rate;
> + hard_phy_linkrate = hisi_sas_phy_read32(hisi_hba, phy_no,
> + HARD_PHY_LINKRATE);
> + phy->maximum_linkrate = hard_phy_linkrate & 0xf;
> + phy->minimum_linkrate = (hard_phy_linkrate >> 4) & 0xf;
> + phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA);
> +
> + /* Check for SATA dev */
> + context = hisi_sas_read32(hisi_hba, PHY_CONTEXT);
> + if (context & (1 << phy_no)) {
> + struct hisi_sas_initial_fis *initial_fis;
> + struct dev_to_host_fis *fis;
> + u8 attached_sas_addr[SAS_ADDR_SIZE] = {0};
> +
> + dev_info(dev, "phyup: phy%d link_rate=%d\n", phy_no, link_rate);
> + initial_fis = _hba->initial_fis[phy_no];
> + fis = _fis->fis;
> + sas_phy->oob_mode = SATA_OOB_MODE;
> + attached_sas_addr[0] = 0x50;
> + attached_sas_addr[7] = phy_no;
> + memcpy(sas_phy->attached_sas_addr,
> +attached_sas_addr,
> +SAS_ADDR_SIZE);
> + memcpy(sas_phy->frame_rcvd, fis,
> +sizeof(struct dev_to_host_fis));
> + phy->phy_type |= PORT_TYPE_SATA;
> + phy->identify.device_type = SAS_SATA_DEV;
> + phy->frame_rcvd_size = sizeof(struct dev_to_host_fis);
> + phy->identify.target_port_protocols = SAS_PROTOCOL_SATA;
> + } else {
> + u32 *frame_rcvd = (u32 *)sas_phy->frame_rcvd;
> + struct sas_identify_frame *id =
> + (struct sas_identify_frame *)frame_rcvd;
> +
> + dev_info(dev, "phyup: phy%d link_rate=%d\n", phy_no, link_rate);
> + for (i = 0; i < 6; i++) {
> + u32 idaf = hisi_sas_phy_read32(hisi_hba, phy_no,
> +RX_IDAF_DWORD0 + (i * 4));
> + frame_rcvd[i] = __swab32(idaf);
> + }
> + sas_phy->oob_mode = SAS_OOB_MODE;
> + memcpy(sas_phy->attached_sas_addr,
> +>sas_addr,
> +SAS_ADDR_SIZE);
> + phy->phy_type |= PORT_TYPE_SAS;
> + phy->identify.device_type = id->dev_type;
> + phy->frame_rcvd_size = sizeof(struct sas_identify_frame);
> + if (phy->identify.device_type == SAS_END_DEVICE)
> + phy->identify.target_port_protocols =
> + SAS_PROTOCOL_SSP;
> + else if (phy->identify.device_type != SAS_PHY_UNUSED)
> + phy->identify.target_port_protocols =
> + SAS_PROTOCOL_SMP;
> + }
> +
> + phy->port_id = port_id;
> + phy->phy_attached = 1;
> + queue_work(hisi_hba->wq, >phyup_ws);
> +
> +end:
> + hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
> +  CHL_INT0_SL_PHY_ENABLE_MSK);
> + hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 0);

[GIT PULL] target fixes for v4.12-rc4

2017-05-31 Thread Nicholas A. Bellinger
Hello Linus,

Here are the target-pending fixes for v4.12-rc4.  Please go ahead and
pull from:

  git://git.kernel.org/pub/scm/linux/kernel/git/nab/target-pending.git master

This includes:

  - ibmviscsis ABORT_TASK handling fixes that missed the v4.12 merge 
window. (Bryant Ly and Michael Cyr)
  - Re-add a target-core check enforcing WRITE overflow reject that was 
relaxed in v4.3, to avoid unsupported iscsi-target immediate data 
overflow. (nab)
  - Fix a target-core-user OOPs during device removal. (MNC + Bryant Ly)
  - Fix a long standing iscsi-target potential issue where kthread exit 
did not wait for kthread_should_stop(). (Jiang Yi)
  - Fix a iscsi-target v3.12.y regression OOPs involving initial login 
PDU processing during asynchronous TCP connection close. (MNC + nab)

This is a little larger than usual for an -rc4, primarily due to the
iscsi-target v3.12.y regression OOPs bug-fix.

However, it's an important patch as MNC + Hannes where both able to
trigger it using a reduced iscsi initiator login timeout combined with a
backend taking a long time to complete I/Os during iscsi login driven
session reinstatement.

Note the trailing two patches have a recent CommitDate, as the second to
last was updated today to include MNC's tested-by and reviewed-by tags.
The patches themselves has not changed though, and both have been run
through manual and automated regression testing from multiple parties
over the last 7 days.

Thank you,

--nab

Bryant G. Ly (2):
  ibmvscsis: Clear left-over abort_cmd pointers
  ibmvscsis: Fix the incorrect req_lim_delta

Jiang Yi (1):
  iscsi-target: Always wait for kthread_should_stop() before kthread
exit

Mike Christie (1):
  tcmu: fix crash during device removal

Nicholas Bellinger (2):
  target: Re-add check to reject control WRITEs with overflow data
  iscsi-target: Fix initial login PDU asynchronous socket close OOPs

 drivers/scsi/ibmvscsi_tgt/ibmvscsi_tgt.c  |  27 -
 drivers/target/iscsi/iscsi_target.c   |  30 -
 drivers/target/iscsi/iscsi_target_erl0.c  |   6 +-
 drivers/target/iscsi/iscsi_target_erl0.h  |   2 +-
 drivers/target/iscsi/iscsi_target_login.c |   4 +
 drivers/target/iscsi/iscsi_target_nego.c  | 194 --
 drivers/target/target_core_transport.c|  23 +++-
 drivers/target/target_core_user.c |  46 +--
 include/target/iscsi/iscsi_target_core.h  |   1 +
 9 files changed, 241 insertions(+), 92 deletions(-)



Re: [PATCH] megaraid: Fix a sleep-in-atomic bug

2017-05-31 Thread Jia-Ju Bai

On 05/31/2017 06:18 PM, Sumit Saxena wrote:

-Original Message-
From: Jia-Ju Bai [mailto:baijiaju1...@163.com]
Sent: Wednesday, May 31, 2017 8:27 AM
To: kashyap.de...@broadcom.com; sumit.sax...@broadcom.com;
shivasharan.srikanteshw...@broadcom.com; j...@linux.vnet.ibm.com;
martin.peter...@oracle.com
Cc: megaraidlinux@broadcom.com; linux-scsi@vger.kernel.org; linux-
ker...@vger.kernel.org; Jia-Ju Bai
Subject: [PATCH] megaraid: Fix a sleep-in-atomic bug

The driver may sleep under a spin lock, and the function call path is:
mraid_mm_attach_buf (acquire the lock by spin_lock_irqsave)
  pci_pool_alloc(GFP_KERNEL) -->  may sleep

To fix it, the "GFP_KERNEL" is replaced with "GFP_ATOMIC".

Signed-off-by: Jia-Ju Bai
---
drivers/scsi/megaraid/megaraid_mm.c |2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/megaraid/megaraid_mm.c
b/drivers/scsi/megaraid/megaraid_mm.c
index 4cf9ed9..c43afb8 100644
--- a/drivers/scsi/megaraid/megaraid_mm.c
+++ b/drivers/scsi/megaraid/megaraid_mm.c
@@ -574,7 +574,7 @@

kioc->pool_index = right_pool;
kioc->free_buf   = 1;
-   kioc->buf_vaddr  = pci_pool_alloc(pool->handle, GFP_KERNEL,
+   kioc->buf_vaddr  = pci_pool_alloc(pool->handle, GFP_ATOMIC,
>buf_paddr);
spin_unlock_irqrestore(>lock, flags);

This is very old driver and reached EOL. Did you face any issue because of
this bug or discover this through code review?
Anyways patch looks good to me.

Acked-by: Sumit Saxena


--
1.7.9.5


Hi,

This bug is found by a static analysis tool and my code review.

Jia-Ju Bai




Re: [PATCH 1/1] scsi: scsi_debug: Avoid PI being disabled when TGPS is enabled

2017-05-31 Thread Martin K. Petersen

Ewan,

> Code is correct.
>
> s/TGPS/TPGS in the subject line and in one place in the patch
> description.

Also fixed the original, incorrect comment in the code that begat the
patch description typo. Thanks!

Applied to 4.12/scsi-fixes.

-- 
Martin K. Petersen  Oracle Linux Engineering


Re: [PATCH] scsi: lpfc: fix spelling mistake "entrys" -> "entries"

2017-05-31 Thread Martin K. Petersen

Colin,

> Trivial fix to spelling mistake in debugfs message

Applied to 4.13/scsi-queue. Thanks!

-- 
Martin K. Petersen  Oracle Linux Engineering


Re: [PATCH] qla2xxx: Fix extraneous ref on sp's after adapter break

2017-05-31 Thread Martin K. Petersen

Bill,

> Hung task timeouts can result if a qlogic board breaks unexpectedly
> while running I/O. These tasks become hung because command srb
> reference counts are not going to zero, hence the affected srbs and
> commands do not get freed. This fix accounts for this extra reference
> in the srbs in the case of a board failure.

Applied to 4.12/scsi-fixes, thanks!

-- 
Martin K. Petersen  Oracle Linux Engineering


Re: [PATCH] scsi: lpfc: Avoid NULL pointer dereference in lpfc_els_abort()

2017-05-31 Thread Martin K. Petersen

Guilherme,

> We might have a NULL pring in lpfc_els_abort(), for example on error
> recovery path, since queues are destroyed during error recovery
> mechanism.
>
> In this case, we should just drop the abort since the queues will be
> recreated anyway. This patch just verifies for NULL pointer and stop
> the abortion of the queue in case of a NULL pring.
>
> Also, this patch converts return type of lpfc_els_abort() from int to
> void, since it's not checked anywhere.

Applied to 4.12/scsi-fixes. Thanks!

-- 
Martin K. Petersen  Oracle Linux Engineering


Re: [PATCH] scsi: lpfc: prevent potential null pointer dereference

2017-05-31 Thread Martin K. Petersen

Gustavo A.,

> Null check at line 966: if (ndlp) {, implies that ndlp might be NULL.
> Functions lpfc_nlp_set_state() and lpfc_issue_els_prli() dereference
> pointer ndlp. Include these function calls inside the IF block that
> tests pointer ndlp.

Applied to 4.12/scsi-fixes. Thank you!

-- 
Martin K. Petersen  Oracle Linux Engineering


Re: [PATCH] lpfc: nvmet_fc: fix format string

2017-05-31 Thread Martin K. Petersen

Arnd,

> The lpfc_nvmeio_data() tracing helper always takes a format string and
> three additional arguments. The latest caller has a format string with
> only two integer arguments, causing this harmless warning:

Applied to 4.12/scsi-fixes. Thank you!

-- 
Martin K. Petersen  Oracle Linux Engineering


Linux kernel 4.9.25: signed integer overflow in drivers/scsi/scsicam.c:173:29

2017-05-31 Thread Alice Ferrazzi

Hello scsi maintainer,

I would like to report a signed integer overflow in 
drivers/scsi/scsicam.c:173:29 
reported on the Gentoo bug reporting system. 
https://bugs.gentoo.org/show_bug.cgi?id=617820

The problem looks present ,at least , in the Linux kernel 4.9.25
regards,

Alice Ferrazzi
Gentoo kernel project leader


signature.asc
Description: PGP signature


Re: [PATCH v3 3/9] blk-mq: use the introduced blk_mq_unquiesce_queue()

2017-05-31 Thread Ming Lei
On Wed, May 31, 2017 at 03:21:41PM +, Bart Van Assche wrote:
> On Wed, 2017-05-31 at 20:37 +0800, Ming Lei wrote:
> > diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
> > index 99e16ac479e3..ffcf05765e2b 100644
> > --- a/drivers/scsi/scsi_lib.c
> > +++ b/drivers/scsi/scsi_lib.c
> > @@ -3031,7 +3031,10 @@ scsi_internal_device_unblock(struct scsi_device 
> > *sdev,
> > return -EINVAL;
> >  
> > if (q->mq_ops) {
> > -   blk_mq_start_stopped_hw_queues(q, false);
> > +   if (blk_queue_quiesced(q))
> > +   blk_mq_unquiesce_queue(q);
> > +   else
> > +   blk_mq_start_stopped_hw_queues(q, false);
> > } else {
> > spin_lock_irqsave(q->queue_lock, flags);
> > blk_start_queue(q);
> 
> As I commented on v2, this change is really wrong. All what's needed here is
> a call to blk_mq_unquiesce_queue() and nothing else. Adding a call to
> blk_mq_start_stopped_hw_queues() is wrong because it makes it impossible to
> use the STOPPED flag in the SCSI core to make the block layer core stop 
> calling
> .queue_rq() if a SCSI LLD returns "busy".

I am not sure if I understand your idea, could you explain a bit why it is 
wrong?

Let's see the function of scsi_internal_device_block():

if (q->mq_ops) {
if (wait)
blk_mq_quiesce_queue(q);
else
blk_mq_stop_hw_queues(q);
}

So the queue may be put into quiesced if 'wait' is true, or it is
stopped if 'wait' is false.

And this patch just makes the two SCSI APIs symmetrical.

Since we will not stop queue in blk_mq_quiesce_queue() later,
I have to unquiese one queue only if it is quiesced.

So suppose the queue is put into stopped in scsi_internal_device_block(),
do we expect not to restart it in scsi_internal_device_unblock() via
blk_mq_unquiesce_queue()?

Thanks,
Ming


Hello Dear Greetings from the Almighty God

2017-05-31 Thread elvir cerrato
Hello dear greetings to you from the almighty God  , my name is Mrs
Elvir Cerrato from Honduras  i am 45 years old , i ma a dying woman
who have decided to donate what i have to the churches , mosque ,
motherless homes , less privilege and the poor through you i was
diagonsed for cancer two years ago but recently my health condition is
getting worst by the day ,i have been toched by God to use what he has
given me to put a smile on the faces of the poor the needy and the
less privilege through you i have asked God to show me a trusted
person that will help me and do this humannitarian work because if i
die now the money will not used well and the security company where i
deposited the money will confiscate the money because no one knows
about the fund  and i will never be a happy woman in the spirit world
because i made a promise to God that i will donate all he has given me
to charity organization , the doctor told me that i have less than 30
days to live, at the moment I cannot take any telephone calls right
now due to the doctors instructions  and my health status also I need
you to contact the security company where i deposited my( $3,500,000)
with  your full name home address  where you will like them to ship
this trunk box to  and your mobile number and i will instruct them to
make the delivery of my money to you by quoting my personal reference
number:( Jlk/Wds/95773/50015/GwrI/3196 )and I have also notified  them
that I am willing that amount to you for a good, effective and prudent
work. I know I don't know you but I have been directed to do this by
God please let me know as soon as you contact the security compmay ok
here is the security company's email address
(speedex.deliveryandvaultcomp...@mail.ru)


Re: [PATCH] iscsi-target: Fix initial login PDU asynchronous socket close OOPs

2017-05-31 Thread Nicholas A. Bellinger
On Wed, 2017-05-31 at 15:28 -0500, Mike Christie wrote:
> On 05/30/2017 11:58 PM, Nicholas A. Bellinger wrote:
> > Hey MNC,
> > 
> > On Fri, 2017-05-26 at 22:14 -0500, Mike Christie wrote:
> >> Thanks for the patch.



> >> The patch fixes the crash for me. However, is there a possible
> >> regression where if the initiator attempts new relogins we could run out
> >> of memory? With the old code, we would free the login attempts resources
> >> at this time, but with the new code the initiator will send more login
> >> attempts and so we just keep allocating more memory for each attempt
> >> until we run out or the login is finally able to complete.
> > 
> > AFAICT, no. For the two cases in question:
> > 
> >  - Initial login request PDU processing done within iscsi_np kthread
> > context in iscsi_target_start_negotiation(), and
> >  - subsequent login request PDU processing done by delayed work-queue
> > kthread context in iscsi_target_do_login_rx() 
> > 
> > this patch doesn't change how aggressively connection cleanup happens
> > for failed login attempts in the face of new connection login attempts
> > for either case.
> > 
> > For the first case when iscsi_np process context invokes
> > iscsi_target_start_negotiation() -> iscsi_target_do_login() ->
> > iscsi_check_for_session_reinstatement() to wait for backend I/O to
> > complete, it still blocks other new connections from being accepted on
> > the specific iscsi_np process context.
> > 
> > This patch doesn't change this behavior.
> > 
> > What it does change is when the host closes the connection and
> > iscsi_target_sk_state_change() gets invoked, iscsi_np process context
> > waits for iscsi_check_for_session_reinstatement() to complete before
> > releasing the connection resources.
> > 
> > However since iscsi_np process context is blocked, new connections won't
> > be accepted until the new connection forcing session reinstatement
> > finishes waiting for outstanding backend I/O to complete.
> 
> I was seeing this. My original mail asked about iscsi login resources
> incorrectly, but like you said we do not get that far. I get a giant
> backlog (1 connection request per 5 seconds that we waited) of tcp level
> connection requests and drops. When the wait is done I get a flood of
> "iSCSI Login negotiation failed" due to the target handling all those
> now stale requests/drops.

Ah, I see what you mean.  The TCP backlog = 256 default can fill up when
a small host side login timeout is used while iscsi_np is blocked
waiting for session reinstatement to complete.

> 
> If we do not care about the memory use at the network level for this
> case (it seems like a little and reconnects are not aggressive), then
> patch works ok for me. I am guessing it gets nasty to handle, so maybe
> not worth it to handle right now? 

Yeah, since it's a issue separate from root cause here, getting this
merged first makes sense.

> I tried to do it in my patch which is why it got all crazy with the 
> waits/wakeups :)
> 

One option to consider is to immediately queue into delayed work-queue
context from iscsi_target_start_negotiation() instead of doing the
iscsi_target_do_login() and session reinstatement from iscsi_np context.

Just taking a quick look, this seems like it would be a pretty
straight-forward change..

> Thanks, and you can add a tested-by or reviewed-by from me.

Great, thanks MNC.

Will send out a PULL request for -rc4 shortly.



Re: [PATCH v2 11/17] qla2xxx: Turn on FW option for exchange check

2017-05-31 Thread Bart Van Assche
On Tue, 2017-05-30 at 10:54 -0700, Himanshu Madhani wrote:
> - ctio->u.status1.flags = (atio->u.isp24.attr << 9) |
> - cpu_to_le16(CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS);
> + temp = (atio->u.isp24.attr << 9)|
> + CTIO7_FLAGS_STATUS_MODE_1 | CTIO7_FLAGS_SEND_STATUS;
> + ctio->u.status1.flags = cpu_to_le16(temp);

This patch not only includes the functional changes explained in the patch
description but also several changes that do not change any functionality
like the above. Please keep functional and non-functional changes separate
for future patch submissions.

Thanks,

Bart.

Re: [PATCH v2 06/17] tcm_qla2xxx: Do not allow aborted cmd to advance.

2017-05-31 Thread Bart Van Assche
On Tue, 2017-05-30 at 10:54 -0700, Himanshu Madhani wrote:
> From: Quinn Tran 
> 
> In case of hardware queue full, commands can loop between
> TCM stack and tcm_qla2xx shim layers for retry. While command
> is waiting for retry, task mgmt can get ahead and abort the
> cmmand that encountered queue full condition. Fix this by
> dropping the command, if task mgmt has already started the
> command free process.

Although I think this is a check that should be performed by the target core
instead of each target driver:

Reviewed-by: Bart Van Assche 

Re: [PATCH v2 05/17] qla2xxx: Fix path recovery

2017-05-31 Thread Bart Van Assche
On Tue, 2017-05-30 at 10:54 -0700, Himanshu Madhani wrote:
> From: Quinn Tran 
> 
> If the port is moved/changed, current code would trigger
> a deletion. If the port is already deleted, then do relogin.

Reviewed-by: Bart Van Assche 

Re: [PATCH 20/25] qla2xxx: Remove redundant code

2017-05-31 Thread Tran, Quinn
Bart,

Will make available in the next upstream, once it has a chance to go through 
our internal test cycle. 

Regards,
Quinn Tran

-Original Message-
From: Bart Van Assche 
Date: Wednesday, May 31, 2017 at 4:41 PM
To: "Tran, Quinn" , Nicholas Bellinger 

Cc: "linux-scsi@vger.kernel.org" , 
"james.bottom...@hansenpartnership.com" 
, "Madhani, Himanshu" 
, "martin.peter...@oracle.com" 

Subject: Re: [PATCH 20/25] qla2xxx: Remove redundant code

On Mon, 2017-05-22 at 22:14 +, Tran, Quinn wrote:
> 
> I think an initiator could get
> really confused if it receives two responses for the same exchange.
> 
> QT:  I do see the window youʼre describing in the 
qlt_try_to_dequeue_unknown_atios().
> Will have to follow up with another patch.   This patch is not meant for 
this window
> youʼve just identify.

Hello Quinn,

Has that patch been included in v2 of this series or will that patch 
perhaps be
made available later?

Thanks,

Bart.



Re: [PATCH v2 03/17] qla2xxx: Retain loop test for fwdump length exceeding buffer length

2017-05-31 Thread Bart Van Assche
On Tue, 2017-05-30 at 10:54 -0700, Himanshu Madhani wrote:
> From: Joe Carnuccio 

Reviewed-by: Bart Van Assche 

Re: [PATCH v2 02/17] qla2xxx: Replace usage of spin_lock with spin_lock_irqsave

2017-05-31 Thread Bart Van Assche
On Tue, 2017-05-30 at 10:54 -0700, Himanshu Madhani wrote:
> From: Quinn Tran 
> 
> Convert usage of spin_lock to spin_lock_irqsave because qla2xxx driver
> accesses all the data structures in an interrupt context.

Did you perhaps mean "*can* access all data structures in interrupt context"?

Anyway:

Reviewed-by: Bart Van Assche 

Re: [PATCH v2 01/17] qla2xxx: Allow ABTS RX, RIDA on ATIOQ for ISP83XX/27XX

2017-05-31 Thread Bart Van Assche
On Tue, 2017-05-30 at 10:54 -0700, Himanshu Madhani wrote:
> From: Quinn Tran 
> 
> Driver added mechanism to move ABTS/PUREX/RIDA mailbox to
> ATIO queue as part of commit id 41dc529a4602ac737020f423f84686a81de38e6d
> ("qla2xxx: Improve RSCN handling in driver").
> 
> This patch addes a check to only allow ABTS/PURX/RIDA
> to be moved to ATIO Queue for ISP83XX and ISP27XX.

Did you perhaps mean "adds" instead of "adds"? Anyway:

Reviewed-by: Bart Van Assche 



Re: [PATCH 20/25] qla2xxx: Remove redundant code

2017-05-31 Thread Bart Van Assche
On Mon, 2017-05-22 at 22:14 +, Tran, Quinn wrote:
> 
> I think an initiator could get
> really confused if it receives two responses for the same exchange.
> 
> QT:  I do see the window you’re describing in the 
> qlt_try_to_dequeue_unknown_atios().
> Will have to follow up with another patch.   This patch is not meant for this 
> window
> you’ve just identify.

Hello Quinn,

Has that patch been included in v2 of this series or will that patch perhaps be
made available later?

Thanks,

Bart.

Re: [PATCH v2 15/17] qla2xxx: Accelerate SCSI BUSY status generation in target mode

2017-05-31 Thread Bart Van Assche
On Tue, 2017-05-30 at 10:54 -0700, Himanshu Madhani wrote:
> + /* FW perform Exchang validation */

Did you perhaps intend "exchange" instead of "Exchang"? Please fix this if you
repost this patch.

Thanks,

Bart.

Re: [PATCH v2 13/17] qla2xxx: Remove redundant code

2017-05-31 Thread Bart Van Assche
On Tue, 2017-05-30 at 10:54 -0700, Himanshu Madhani wrote:
> The reason for hard coding LUN ID to 0 is that, from the FC
> protocol perspective, ABTS does not have any knowledge of
> LUN ID. So, there is no reason for qla2xxx driver to
> manufacture the LUN ID.

Sorry but I think this is completely wrong. Are you aware that
target_submit_tmr() performs an exact match on the LUN specified as the fourth
argument? This patch will cause ABTS requests to be ignored that apply to
commands that have been submitted to another LUN than LUN 0.

Please note that I had proposed a better approach three months ago on the
target-devel mailing list and that I'm still waiting for someone from Cavium to
review these patches:
* [PATCH v6 09/33] target: Make it possible to specify I_T nexus for SCSI
  abort (http://www.spinics.net/lists/target-devel/msg14534.html).
* [PATCH v6 10/33] tcm_qla2xxx: Let the target core look up the LUN of the
  aborted cmd (http://www.spinics.net/lists/target-devel/msg14563.html).

Bart.

Re: [PATCH v2 12/17] qla2xxx: Add ql2xiniexchg parameter

2017-05-31 Thread Bart Van Assche
On Tue, 2017-05-30 at 10:54 -0700, Himanshu Madhani wrote:
> -   "For Dual Mode (qlini_mode=dual), this parameter determines "
> -   "the percentage of exchanges/cmds FW will allocate resources "
> -   "for Target mode.");
> + "For Dual Mode (qlini_mode=dual), this parameter determines "
> + "the percentage of exchanges/cmds FW will allocate resources "
> + "for Target mode.");

Hello Himanshu and Quinn,

There are several pointless changes in this patch series like the above
that changes indentation from 7 spaces to five spaces. Please leave such
changes out from future patch submissions.

Thanks,

Bart.

Re: [PATCH v2 08/17] qla2xxx: Convert 32-bit LUN usage to 64-bit

2017-05-31 Thread Bart Van Assche
On Tue, 2017-05-30 at 10:54 -0700, Himanshu Madhani wrote:
> From: Quinn Tran 

Reviewed-by: Bart Van Assche 



Re: [PATCH v2 04/17] qla2xxx: Include Exchange offload/Extended Login into FW dump

2017-05-31 Thread Bart Van Assche
On Tue, 2017-05-30 at 10:54 -0700, Himanshu Madhani wrote:
>  static inline void *
> +qla25xx_copy_exlogin(struct qla_hw_data *ha, void *ptr, uint32_t 
> **last_chain)
> +{
> + struct qla2xxx_offld_chain *c = ptr;
> +
> + if (!ha->exlogin_buf)
> + return ptr;
> +
> + *last_chain = >type;
> +
> + c->type = htonl(DUMP_CHAIN_EXLOGIN);
> + c->chain_size = htonl(sizeof(struct qla2xxx_offld_chain) +
> + ha->exlogin_size);
> + c->size = htonl(ha->exlogin_size);

Since this is not networking code, why is this code using htonl() instead of 
cpu_to_be32()?

> + c->addr_l = htonl(LSD(ha->exlogin_buf_dma));
> + c->addr_h = htonl(MSD(ha->exlogin_buf_dma));

Please use cpu_to_be64() instead of this weird construct.

> + uint32_t addr_l;
> + uint32_t addr_h;

Please declare this as a single 64-bit variable instead of using this weird
split into two 32-bit variables.

Thanks,

Bart.

Re: [PATCH] qla2xxx: Fix extraneous ref on sp's after adapter break

2017-05-31 Thread Madhani, Himanshu

> On May 25, 2017, at 12:26 PM, Bill Kuzeja  wrote:
> 
> Hung task timeouts can result if a qlogic board breaks unexpectedly while
> running I/O. These tasks become hung because command srb reference counts
> are not going to zero, hence the affected srbs and commands do not get 
> freed. This fix accounts for this extra reference in the srbs in the case 
> of a board failure. 
> 
> Fixes: a465537ad1a4 ("qla2xxx: Disable the adapter and skip error recovery in 
> case of register disconnect")
> Signed-off-by: Bill Kuzeja 
> ---
> 
> I encountered this hang during by adapter break testing (on Stratus
> hardware, we need to survive adapter breaks). I noticed that we wait
> indefinitely for several commands which all have outstanding
> references to them, but which have all followed this code path:
> 
> qla2x00_abort_all_cmds
>   qla2xxx_eh_abort
>   Exit early because qla2x00_isp_reg_stat is non-zero.
> 
> Note that before calling qla2xxx_eh_abort from this path, we do an extra
> sp_get(sp), which takes out another reference on the current sp. If we
> do not early exit immediately from qla2xxx_eh_abort, we'll get rid of this
> extra reference through the abort - which is the normal case.
> 
> However, if we exit immediately, this extra sp_get is never dereferenced.
> Each one of the commands flowing through this code will be stuck forever,
> resulting in hung tasks.
> 
> This early exit in qla2xxx_eh_abort was introduced by this commit:
> 
> commit a465537ad1a4 ("qla2xxx: Disable the adapter and skip error recovery in 
> case of register disconnect.")
> 
> The solution for this is somewhat tricky because qla2xxx_eh_abort can be
> invoked from the scsi error handler as well as qla2x00_abort_all_cmds.
> I originally thought of having qla2xxx_eh_abort remove the extra reference
> before early exiting, but not knowing the context of its invocation,
> this seemed dangerous.
> 
> Alternatively we could also just remove the early exit case from
> qla2xxx_eh_abort, but the aforementioned commit was put in for a reason, so 
> that doesn't seem correct either.
> 
> The right thing to do seems to be putting the fix in qla2x00_abort_all_cmds,
> checking the conditions we where we have exited early from qla2xxx_eh_abort
> before removing the extra reference.
> 
> ---
> drivers/scsi/qla2xxx/qla_os.c | 7 +--
> 1 file changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
> index 1c79579..1a93365 100644
> --- a/drivers/scsi/qla2xxx/qla_os.c
> +++ b/drivers/scsi/qla2xxx/qla_os.c
> @@ -1632,7 +1632,7 @@ uint32_t qla2x00_isp_reg_stat(struct qla_hw_data *ha)
> void
> qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
> {
> - int que, cnt;
> + int que, cnt, status;
>   unsigned long flags;
>   srb_t *sp;
>   struct qla_hw_data *ha = vha->hw;
> @@ -1662,8 +1662,12 @@ uint32_t qla2x00_isp_reg_stat(struct qla_hw_data *ha)
>*/
>   sp_get(sp);
>   
> spin_unlock_irqrestore(>hardware_lock, flags);
> - qla2xxx_eh_abort(GET_CMD_SP(sp));
> + status = 
> qla2xxx_eh_abort(GET_CMD_SP(sp));
>   spin_lock_irqsave(>hardware_lock, 
> flags);
> + /* Get rid of extra reference if 
> immediate exit
> +  * from ql2xxx_eh_abort */
> + if (status == FAILED && 
> (qla2x00_isp_reg_stat(ha)))
> + atomic_dec(>ref_count);
>   }
>   req->outstanding_cmds[cnt] = NULL;
>   sp->done(sp, res);
> -- 
> 1.8.3.1
> 

Looks Good. 

Acked-by: Himanshu Madhani 

Thanks,
- Himanshu



Re: [PATCH] iscsi-target: Fix initial login PDU asynchronous socket close OOPs

2017-05-31 Thread Mike Christie
On 05/30/2017 11:58 PM, Nicholas A. Bellinger wrote:
> Hey MNC,
> 
> On Fri, 2017-05-26 at 22:14 -0500, Mike Christie wrote:
>> Thanks for the patch.
>>
> 
> Btw, after running DATERA's internal longevity and scale tests across
> ~20 racks on v4.1.y with this patch over the long weekend, there haven't
> been any additional regressions.
> 
>> On 05/26/2017 12:32 AM, Nicholas A. Bellinger wrote:
>>>  
>>> -   state = iscsi_target_sk_state_check(sk);
>>> -   write_unlock_bh(>sk_callback_lock);
>>> -
>>> -   pr_debug("iscsi_target_sk_state_change: state: %d\n", state);
>>> +   orig_state_change(sk);
>>>  
>>> -   if (!state) {
>>> -   pr_debug("iscsi_target_sk_state_change got failed state\n");
>>> -   schedule_delayed_work(>login_cleanup_work, 0);
>>
>> I think login_cleanup_work is no longer used so you can also remove it
>> and its code.
> 
> Yep, since this needs to goto stable, I left that part out for now..
> 
> Will take care of that post -rc4.
> 
>>
>> The patch fixes the crash for me. However, is there a possible
>> regression where if the initiator attempts new relogins we could run out
>> of memory? With the old code, we would free the login attempts resources
>> at this time, but with the new code the initiator will send more login
>> attempts and so we just keep allocating more memory for each attempt
>> until we run out or the login is finally able to complete.
> 
> AFAICT, no. For the two cases in question:
> 
>  - Initial login request PDU processing done within iscsi_np kthread
> context in iscsi_target_start_negotiation(), and
>  - subsequent login request PDU processing done by delayed work-queue
> kthread context in iscsi_target_do_login_rx() 
> 
> this patch doesn't change how aggressively connection cleanup happens
> for failed login attempts in the face of new connection login attempts
> for either case.
> 
> For the first case when iscsi_np process context invokes
> iscsi_target_start_negotiation() -> iscsi_target_do_login() ->
> iscsi_check_for_session_reinstatement() to wait for backend I/O to
> complete, it still blocks other new connections from being accepted on
> the specific iscsi_np process context.
> 
> This patch doesn't change this behavior.
> 
> What it does change is when the host closes the connection and
> iscsi_target_sk_state_change() gets invoked, iscsi_np process context
> waits for iscsi_check_for_session_reinstatement() to complete before
> releasing the connection resources.
> 
> However since iscsi_np process context is blocked, new connections won't
> be accepted until the new connection forcing session reinstatement
> finishes waiting for outstanding backend I/O to complete.

I was seeing this. My original mail asked about iscsi login resources
incorrectly, but like you said we do not get that far. I get a giant
backlog (1 connection request per 5 seconds that we waited) of tcp level
connection requests and drops. When the wait is done I get a flood of
"iSCSI Login negotiation failed" due to the target handling all those
now stale requests/drops.

If we do not care about the memory use at the network level for this
case (it seems like a little and reconnects are not aggressive), then
patch works ok for me. I am guessing it gets nasty to handle, so maybe
not worth it to handle right now? I tried to do it in my patch which is
why it got all crazy with the waits/wakeups :)

Thanks, and you can add a tested-by or reviewed-by from me.


Re: [PATCH] scsi: lpfc: Fix crash on PCI hotplug remove path

2017-05-31 Thread James Smart
Actually, I think we solved this in a better manner in this patch in the 
11.4.0.0 patch set:
  PATCH 10/15] lpfc: Fix crash on powering off BFS VM with passthrough 
device

  http://marc.info/?l=linux-scsi=149621070910290=2

See if the above patch fixes your error.

-- james



On 5/29/2017 4:11 PM, James Smart wrote:

looks good

Signed-off-by: James Smart  

-- james



On 5/28/2017 2:45 PM, Guilherme G. Piccoli wrote:

During a PCI hotplug remove event we could have a NULL pointer
dereference on lpfc_sli_abort_iocb(), if pring is NULL. This
patch adds a check for this case and is able to circumvent the
failure and continue the hotplug remove process with success.

This issue was introduced after the driver refactor made on
commit 895427bd012c ("scsi: lpfc: NVME Initiator: Base modifications").

Fixes: 895427bd012c ("scsi: lpfc: NVME Initiator: Base modifications")
Reported-by: Naresh Bannoth 
Signed-off-by: Guilherme G. Piccoli 
---
This patch was rebased against Martin's 4.12/scsi-fixes.








Re: [PATCH 1/1] scsi: scsi_debug: Avoid PI being disabled when TGPS is enabled

2017-05-31 Thread Ewan D. Milne
On Fri, 2017-05-26 at 12:59 -0400, Martin K. Petersen wrote:
> It was not possible to enable both T10 PI and TGPS because they share
> the same byte in the INQUIRY response. Logically OR the TPGS value
> instead of using assignment.
> 
> Reported-by: Ritika Srivastava 
> Signed-off-by: Martin K. Petersen 
> ---
>  drivers/scsi/scsi_debug.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
> index 17249c3650fe..b945d187873f 100644
> --- a/drivers/scsi/scsi_debug.c
> +++ b/drivers/scsi/scsi_debug.c
> @@ -1404,7 +1404,7 @@ static int resp_inquiry(struct scsi_cmnd *scp, struct 
> sdebug_dev_info *devip)
>   arr[4] = SDEBUG_LONG_INQ_SZ - 5;
>   arr[5] = (int)have_dif_prot;/* PROTECT bit */
>   if (sdebug_vpd_use_hostno == 0)
> - arr[5] = 0x10; /* claim: implicit TGPS */
> + arr[5] |= 0x10; /* claim: implicit TGPS */
>   arr[6] = 0x10; /* claim: MultiP */
>   /* arr[6] |= 0x40; ... claim: EncServ (enclosure services) */
>   arr[7] = 0xa; /* claim: LINKED + CMDQUE */

Code is correct.

s/TGPS/TPGS in the subject line and in one place in the patch description.

Reviewed-by: Ewan D. Milne 




Re: [PATCH v3 3/9] blk-mq: use the introduced blk_mq_unquiesce_queue()

2017-05-31 Thread Bart Van Assche
On Wed, 2017-05-31 at 20:37 +0800, Ming Lei wrote:
> diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
> index 99e16ac479e3..ffcf05765e2b 100644
> --- a/drivers/scsi/scsi_lib.c
> +++ b/drivers/scsi/scsi_lib.c
> @@ -3031,7 +3031,10 @@ scsi_internal_device_unblock(struct scsi_device *sdev,
>   return -EINVAL;
>  
>   if (q->mq_ops) {
> - blk_mq_start_stopped_hw_queues(q, false);
> + if (blk_queue_quiesced(q))
> + blk_mq_unquiesce_queue(q);
> + else
> + blk_mq_start_stopped_hw_queues(q, false);
>   } else {
>   spin_lock_irqsave(q->queue_lock, flags);
>   blk_start_queue(q);

As I commented on v2, this change is really wrong. All what's needed here is
a call to blk_mq_unquiesce_queue() and nothing else. Adding a call to
blk_mq_start_stopped_hw_queues() is wrong because it makes it impossible to
use the STOPPED flag in the SCSI core to make the block layer core stop calling
.queue_rq() if a SCSI LLD returns "busy".

Bart.

Re: [PATCH 1/1] scsi: scsi_debug: Avoid PI being disabled when TGPS is enabled

2017-05-31 Thread Bart Van Assche
On Fri, 2017-05-26 at 12:59 -0400, Martin K. Petersen wrote:
> It was not possible to enable both T10 PI and TGPS because they share
> the same byte in the INQUIRY response. Logically OR the TPGS value
> instead of using assignment.

Reviewed-by: Bart Van Assche 

[PATCH] scsi: Add STARGET_CREATE_REMOVE state to scsi_target_state

2017-05-31 Thread Ewan D. Milne
From: "Ewan D. Milne" 

The addition of the STARGET_REMOVE state had the side effect of
introducing a race condition that can cause a crash.

scsi_target_reap_ref_release() checks the starget->state to
see if it still in STARGET_CREATED, and if so, skips calling
transport_remove_device() and device_del(), because the starget->state
is only set to STARGET_RUNNING after scsi_target_add() has called
device_add() and transport_add_device().

However, if an rport loss occurs while a target is being scanned,
it can happen that scsi_remove_target() will be called while the
starget is still in the STARGET_CREATED state.  In this case, the
starget->state will be set to STARGET_REMOVE, and as a result,
scsi_target_reap_ref_release() will take the wrong path.  The end
result is a panic:

[ 1255.356653] Oops:  [#1] SMP
[ 1255.360154] Modules linked in: x86_pkg_temp_thermal kvm_intel kvm irqbypass 
crc32c_intel
[ 1255.393234] CPU: 5 PID: 149 Comm: kworker/u96:4 Tainted: GW   
4.11.0+ #8
[ 1255.401879] Hardware name: Dell Inc. PowerEdge R320/08VT7V, BIOS 2.0.22 
11/19/2013
[ 1255.410327] Workqueue: scsi_wq_6 fc_scsi_scan_rport [scsi_transport_fc]
[ 1255.417720] task: 88060ca8c8c0 task.stack: c900048a8000
[ 1255.424331] RIP: 0010:kernfs_find_ns+0x13/0xc0
[ 1255.429287] RSP: 0018:c900048abbf0 EFLAGS: 00010246
[ 1255.435123] RAX:  RBX:  RCX: 
[ 1255.443083] RDX:  RSI: 8188d659 RDI: 
[ 1255.451043] RBP: c900048abc10 R08:  R09: 012433fe0025
[ 1255.459005] R10: 25e5a4b5 R11: 25e5a4b5 R12: 8188d659
[ 1255.466972] R13:  R14: 8805f55e5088 R15: 
[ 1255.474931] FS:  () GS:880616b4() 
knlGS:
[ 1255.483959] CS:  0010 DS:  ES:  CR0: 80050033
[ 1255.490370] CR2: 0068 CR3: 01c09000 CR4: 000406e0
[ 1255.498332] Call Trace:
[ 1255.501058]  kernfs_find_and_get_ns+0x31/0x60
[ 1255.505916]  sysfs_unmerge_group+0x1d/0x60
[ 1255.510498]  dpm_sysfs_remove+0x22/0x60
[ 1255.514783]  device_del+0xf4/0x2e0
[ 1255.518577]  ? device_remove_file+0x19/0x20
[ 1255.523241]  attribute_container_class_device_del+0x1a/0x20
[ 1255.529457]  transport_remove_classdev+0x4e/0x60
[ 1255.534607]  ? transport_add_class_device+0x40/0x40
[ 1255.540046]  attribute_container_device_trigger+0xb0/0xc0
[ 1255.546069]  transport_remove_device+0x15/0x20
[ 1255.551025]  scsi_target_reap_ref_release+0x25/0x40
[ 1255.556467]  scsi_target_reap+0x2e/0x40
[ 1255.560744]  __scsi_scan_target+0xaa/0x5b0
[ 1255.565312]  scsi_scan_target+0xec/0x100
[ 1255.569689]  fc_scsi_scan_rport+0xb1/0xc0 [scsi_transport_fc]
[ 1255.576099]  process_one_work+0x14b/0x390
[ 1255.580569]  worker_thread+0x4b/0x390
[ 1255.584651]  kthread+0x109/0x140
[ 1255.588251]  ? rescuer_thread+0x330/0x330
[ 1255.592730]  ? kthread_park+0x60/0x60
[ 1255.596815]  ret_from_fork+0x29/0x40
[ 1255.600801] Code: 24 08 48 83 42 40 01 5b 41 5c 5d c3 66 66 66 2e 0f 1f 84 
00 00 00 00 00 66 66 66 66 90 
[ 1255.621876] RIP: kernfs_find_ns+0x13/0xc0 RSP: c900048abbf0
[ 1255.628479] CR2: 0068
[ 1255.632756] ---[ end trace 34a69ba0477d036f ]---

Fix this by adding another scsi_target state STARGET_CREATED_REMOVE
to distinguish this case.

Fixes: f05795d3d771 ("scsi: Add intermediate STARGET_REMOVE state to 
scsi_target_state")
Reported-by: David Jeffery 
Signed-off-by: Ewan D. Milne 
Cc: sta...@vger.kernel.org
---
 drivers/scsi/scsi_scan.c   | 5 +++--
 drivers/scsi/scsi_sysfs.c  | 8 ++--
 include/scsi/scsi_device.h | 1 +
 3 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 6f7128f..27a6d3c 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -384,11 +384,12 @@ static void scsi_target_reap_ref_release(struct kref 
*kref)
= container_of(kref, struct scsi_target, reap_ref);
 
/*
-* if we get here and the target is still in the CREATED state that
+* if we get here and the target is still in a CREATED state that
 * means it was allocated but never made visible (because a scan
 * turned up no LUNs), so don't call device_del() on it.
 */
-   if (starget->state != STARGET_CREATED) {
+   if ((starget->state != STARGET_CREATED) &&
+   (starget->state != STARGET_CREATED_REMOVE)) {
transport_remove_device(>dev);
device_del(>dev);
}
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 82dfe07..3a6f557 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -1370,11 +1370,15 @@ void scsi_remove_target(struct device *dev)
spin_lock_irqsave(shost->host_lock, flags);
list_for_each_entry(starget, >__targets, siblings) {
   

[PATCH v3 4/5] tcmu: Make dev_config configurable

2017-05-31 Thread Bryant G. Ly
This allows for userspace to change the device path after
it has been created. Thus giving the user the ability to change
the path. The use case for this is to allow for virtual optical
to have media change.

v3 - Fix kree spelling error to kfree

Signed-off-by: Bryant G. Ly 
---
 drivers/target/target_core_user.c | 41 +++
 1 file changed, 41 insertions(+)

diff --git a/drivers/target/target_core_user.c 
b/drivers/target/target_core_user.c
index a4cf678..eea4630 100644
--- a/drivers/target/target_core_user.c
+++ b/drivers/target/target_core_user.c
@@ -1577,6 +1577,46 @@ static ssize_t tcmu_cmd_time_out_store(struct 
config_item *item, const char *pag
 }
 CONFIGFS_ATTR(tcmu_, cmd_time_out);
 
+static ssize_t tcmu_dev_path_show(struct config_item *item, char *page)
+{
+   struct se_dev_attrib *da = container_of(to_config_group(item),
+   struct se_dev_attrib, da_group);
+   struct tcmu_dev *udev = TCMU_DEV(da->da_dev);
+
+   return snprintf(page, PAGE_SIZE, "%s\n", udev->dev_config);
+}
+
+static ssize_t tcmu_dev_path_store(struct config_item *item, const char *page,
+  size_t count)
+{
+   struct se_dev_attrib *da = container_of(to_config_group(item),
+   struct se_dev_attrib, da_group);
+   struct tcmu_dev *udev = TCMU_DEV(da->da_dev);
+   char *copy = NULL;
+   int ret;
+
+   copy = kstrdup(page, GFP_KERNEL);
+   if (!copy) {
+   kfree(copy);
+   return -EINVAL;
+   }
+   strcpy(udev->dev_config, copy);
+
+   /* Check if device has been configured before */
+   if (tcmu_dev_configured(udev)) {
+   ret = tcmu_netlink_event(TCMU_CMD_RECONFIG_DEVICE,
+udev->uio_info.name,
+udev->uio_info.uio_dev->minor);
+   if (ret) {
+   pr_err("Unable to reconfigure device\n");
+   return ret;
+   }
+   }
+
+   return count;
+}
+CONFIGFS_ATTR(tcmu_, dev_path);
+
 static ssize_t tcmu_dev_size_show(struct config_item *item, char *page)
 {
struct se_dev_attrib *da = container_of(to_config_group(item),
@@ -1655,6 +1695,7 @@ CONFIGFS_ATTR(tcmu_, emulate_write_cache);
 
 struct configfs_attribute *tcmu_attrib_attrs[] = {
_attr_cmd_time_out,
+   _attr_dev_path,
_attr_dev_size,
_attr_emulate_write_cache,
NULL,
-- 
2.5.4 (Apple Git-61)



[PATCH v3 02/23] scsi: hisi_sas: define hisi_sas_device.device_id as int

2017-05-31 Thread John Garry
Currently hisi_sas_device.device_id is a u64. This can create a
problem in selecting the queue for a device, in that this code
does a 64b division on device id. For some 32b systems, 64b division
is slow and the lib reference must be explicitly included.

The device id does not need to be 64b in size, so, as a solution,
just make as an int.

Also, struct hisi_sas_device elements are re-ordered to improve
packing efficiency.

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h  |  8 
 drivers/scsi/hisi_sas/hisi_sas_main.c | 10 +-
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 4e28f32..b4e96fa9 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -107,15 +107,15 @@ struct hisi_sas_dq {
 };
 
 struct hisi_sas_device {
-   enum sas_device_typedev_type;
struct hisi_hba *hisi_hba;
struct domain_device*sas_device;
+   struct list_headlist;
u64 attached_phy;
-   u64 device_id;
atomic64_t running_req;
-   struct list_headlist;
-   u8 dev_status;
+   enum sas_device_typedev_type;
+   int device_id;
int sata_idx;
+   u8 dev_status;
 };
 
 struct hisi_sas_slot {
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 3605d28..54e0cf2 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -209,7 +209,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct 
hisi_hba *hisi_hba,
 
if (DEV_IS_GONE(sas_dev)) {
if (sas_dev)
-   dev_info(dev, "task prep: device %llu not ready\n",
+   dev_info(dev, "task prep: device %d not ready\n",
 sas_dev->device_id);
else
dev_info(dev, "task prep: device %016llx not ready\n",
@@ -627,9 +627,9 @@ static void hisi_sas_dev_gone(struct domain_device *device)
struct hisi_sas_device *sas_dev = device->lldd_dev;
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
struct device *dev = _hba->pdev->dev;
-   u64 dev_id = sas_dev->device_id;
+   int dev_id = sas_dev->device_id;
 
-   dev_info(dev, "found dev[%lld:%x] is gone\n",
+   dev_info(dev, "found dev[%d:%x] is gone\n",
 sas_dev->device_id, sas_dev->dev_type);
 
hisi_sas_internal_task_abort(hisi_hba, device,
@@ -1082,7 +1082,7 @@ static int hisi_sas_lu_reset(struct domain_device 
*device, u8 *lun)
}
 out:
if (rc != TMF_RESP_FUNC_COMPLETE)
-   dev_err(dev, "lu_reset: for device[%llx]:rc= %d\n",
+   dev_err(dev, "lu_reset: for device[%d]:rc= %d\n",
 sas_dev->device_id, rc);
return rc;
 }
@@ -1129,7 +1129,7 @@ static int hisi_sas_query_task(struct sas_task *task)
 }
 
 static int
-hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, u64 device_id,
+hisi_sas_internal_abort_task_exec(struct hisi_hba *hisi_hba, int device_id,
  struct sas_task *task, int abort_flag,
  int task_tag)
 {
-- 
1.9.1



[PATCH v3 03/23] scsi: hisi_sas: optimise the usage of hisi_hba.lock

2017-05-31 Thread John Garry
From: Xiang Chen 

Currently hisi_hba.lock is locked to deliver and receive a
command to/from any hw queue. This causes much
contention at high data-rates.

To boost performance, lock on a per queue basis for
sending and receiving commands to/from hw.

Certain critical regions still need to be locked in the delivery
and completion stages with hisi_hba.lock.

New element hisi_sas_device.dq is added to store the delivery
queue for a device, so it does not need to be needlessly
re-calculated for every task.

Signed-off-by: Xiang Chen 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |  9 ++---
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 61 +++---
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 23 +
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 34 +--
 4 files changed, 71 insertions(+), 56 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index b4e96fa9..68ba7bd 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -102,6 +102,8 @@ struct hisi_sas_cq {
 
 struct hisi_sas_dq {
struct hisi_hba *hisi_hba;
+   struct hisi_sas_slot*slot_prep;
+   spinlock_t lock;
int wr_point;
int id;
 };
@@ -109,6 +111,7 @@ struct hisi_sas_dq {
 struct hisi_sas_device {
struct hisi_hba *hisi_hba;
struct domain_device*sas_device;
+   struct hisi_sas_dq  *dq;
struct list_headlist;
u64 attached_phy;
atomic64_t running_req;
@@ -154,9 +157,8 @@ struct hisi_sas_hw {
struct domain_device *device);
struct hisi_sas_device *(*alloc_dev)(struct domain_device *device);
void (*sl_notify)(struct hisi_hba *hisi_hba, int phy_no);
-   int (*get_free_slot)(struct hisi_hba *hisi_hba, u32 dev_id,
-   int *q, int *s);
-   void (*start_delivery)(struct hisi_hba *hisi_hba);
+   int (*get_free_slot)(struct hisi_hba *hisi_hba, struct hisi_sas_dq *dq);
+   void (*start_delivery)(struct hisi_sas_dq *dq);
int (*prep_ssp)(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot, int is_tmf,
struct hisi_sas_tmf_task *tmf);
@@ -217,7 +219,6 @@ struct hisi_hba {
struct hisi_sas_port port[HISI_SAS_MAX_PHYS];
 
int queue_count;
-   struct hisi_sas_slot*slot_prep;
 
struct dma_pool *sge_page_pool;
struct hisi_sas_device  devices[HISI_SAS_MAX_DEVICES];
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 54e0cf2..b247220 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -179,10 +179,11 @@ static void hisi_sas_slot_abort(struct work_struct *work)
task->task_done(task);
 }
 
-static int hisi_sas_task_prep(struct sas_task *task, struct hisi_hba *hisi_hba,
- int is_tmf, struct hisi_sas_tmf_task *tmf,
- int *pass)
+static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq
+   *dq, int is_tmf, struct hisi_sas_tmf_task *tmf,
+   int *pass)
 {
+   struct hisi_hba *hisi_hba = dq->hisi_hba;
struct domain_device *device = task->dev;
struct hisi_sas_device *sas_dev = device->lldd_dev;
struct hisi_sas_port *port;
@@ -240,18 +241,24 @@ static int hisi_sas_task_prep(struct sas_task *task, 
struct hisi_hba *hisi_hba,
} else
n_elem = task->num_scatter;
 
+   spin_lock_irqsave(_hba->lock, flags);
if (hisi_hba->hw->slot_index_alloc)
rc = hisi_hba->hw->slot_index_alloc(hisi_hba, _idx,
device);
else
rc = hisi_sas_slot_index_alloc(hisi_hba, _idx);
-   if (rc)
+   if (rc) {
+   spin_unlock_irqrestore(_hba->lock, flags);
goto err_out;
-   rc = hisi_hba->hw->get_free_slot(hisi_hba, sas_dev->device_id,
-   _queue, _queue_slot);
+   }
+   spin_unlock_irqrestore(_hba->lock, flags);
+
+   rc = hisi_hba->hw->get_free_slot(hisi_hba, dq);
if (rc)
goto err_out_tag;
 
+   dlvry_queue = dq->id;
+   dlvry_queue_slot = dq->wr_point;
slot = _hba->slot_info[slot_idx];
memset(slot, 0, sizeof(struct hisi_sas_slot));
 
@@ -316,7 +323,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct 
hisi_hba *hisi_hba,
task->task_state_flags |= SAS_TASK_AT_INITIATOR;
spin_unlock_irqrestore(>task_state_lock, flags);
 
-   hisi_hba->slot_prep = slot;
+   dq->slot_prep = slot;
 
atomic64_inc(_dev->running_req);
++(*pass);
@@ -354,19 +361,22 @@ static int hisi_sas_task_exec(struct 

[PATCH v3 06/23] scsi: hisi_sas: relocate get_ncq_tag_v2_hw()

2017-05-31 Thread John Garry
From: Xiang Chen 

Relocate get_ncq_tag_v2_hw() to a common location, as
future hw versions will require it.
Also rename with "hisi_sas_" prefix for consistency.

Signed-off-by: Xiang Chen 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |  1 +
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 15 +++
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 16 +---
 3 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index f2d69cd..439b1f2 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -360,6 +360,7 @@ struct hisi_sas_command_table_ssp {
 extern struct hisi_sas_port *to_hisi_sas_port(struct asd_sas_port *sas_port);
 extern void hisi_sas_sata_done(struct sas_task *task,
struct hisi_sas_slot *slot);
+extern int hisi_sas_get_ncq_tag(struct sas_task *task, u32 *tag);
 extern int hisi_sas_probe(struct platform_device *pdev,
  const struct hisi_sas_hw *ops);
 extern int hisi_sas_remove(struct platform_device *pdev);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 88ace7c..32962d3 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -103,6 +103,21 @@ void hisi_sas_sata_done(struct sas_task *task,
 }
 EXPORT_SYMBOL_GPL(hisi_sas_sata_done);
 
+int hisi_sas_get_ncq_tag(struct sas_task *task, u32 *tag)
+{
+   struct ata_queued_cmd *qc = task->uldd_task;
+
+   if (qc) {
+   if (qc->tf.command == ATA_CMD_FPDMA_WRITE ||
+   qc->tf.command == ATA_CMD_FPDMA_READ) {
+   *tag = qc->tag;
+   return 1;
+   }
+   }
+   return 0;
+}
+EXPORT_SYMBOL_GPL(hisi_sas_get_ncq_tag);
+
 static struct hisi_hba *dev_to_hisi_hba(struct domain_device *device)
 {
return device->port->ha->lldd_ha;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index fdd7019..9cc5435 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -2332,20 +2332,6 @@ static void slot_err_v2_hw(struct hisi_hba *hisi_hba,
return sts;
 }
 
-static int get_ncq_tag_v2_hw(struct sas_task *task, u32 *tag)
-{
-   struct ata_queued_cmd *qc = task->uldd_task;
-
-   if (qc) {
-   if (qc->tf.command == ATA_CMD_FPDMA_WRITE ||
-   qc->tf.command == ATA_CMD_FPDMA_READ) {
-   *tag = qc->tag;
-   return 1;
-   }
-   }
-   return 0;
-}
-
 static int prep_ata_v2_hw(struct hisi_hba *hisi_hba,
  struct hisi_sas_slot *slot)
 {
@@ -2393,7 +2379,7 @@ static int prep_ata_v2_hw(struct hisi_hba *hisi_hba,
hdr->dw1 = cpu_to_le32(dw1);
 
/* dw2 */
-   if (task->ata_task.use_ncq && get_ncq_tag_v2_hw(task, _tag)) {
+   if (task->ata_task.use_ncq && hisi_sas_get_ncq_tag(task, _tag)) {
task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3);
dw2 |= hdr_tag << CMD_HDR_NCQ_TAG_OFF;
}
-- 
1.9.1



[PATCH v3 04/23] scsi: hisi_sas: relocate get_ata_protocol()

2017-05-31 Thread John Garry
From: Xiang Chen 

Relocate get_ata_protocol() to a common location, as future
hw versions will require it.
Also rename with "hisi_sas_" prefix for consistency.

Signed-off-by: Xiang Chen 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |  1 +
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 65 +
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 67 +-
 3 files changed, 68 insertions(+), 65 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 68ba7bd..8ed1199 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -356,6 +356,7 @@ struct hisi_sas_command_table_ssp {
struct hisi_sas_command_table_stp stp;
 };
 
+extern u8 hisi_sas_get_ata_protocol(u8 cmd, int direction);
 extern struct hisi_sas_port *to_hisi_sas_port(struct asd_sas_port *sas_port);
 extern int hisi_sas_probe(struct platform_device *pdev,
  const struct hisi_sas_hw *ops);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index b247220..f71590c 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -15,6 +15,12 @@
 #define DEV_IS_GONE(dev) \
((!dev) || (dev->dev_type == SAS_PHY_UNUSED))
 
+#define SATA_PROTOCOL_NONDATA  0x1
+#define SATA_PROTOCOL_PIO  0x2
+#define SATA_PROTOCOL_DMA  0x4
+#define SATA_PROTOCOL_FPDMA0x8
+#define SATA_PROTOCOL_ATAPI0x10
+
 static int hisi_sas_debug_issue_ssp_tmf(struct domain_device *device,
u8 *lun, struct hisi_sas_tmf_task *tmf);
 static int
@@ -23,6 +29,65 @@ static int hisi_sas_debug_issue_ssp_tmf(struct domain_device 
*device,
 int abort_flag, int tag);
 static int hisi_sas_softreset_ata_disk(struct domain_device *device);
 
+u8 hisi_sas_get_ata_protocol(u8 cmd, int direction)
+{
+   switch (cmd) {
+   case ATA_CMD_FPDMA_WRITE:
+   case ATA_CMD_FPDMA_READ:
+   case ATA_CMD_FPDMA_RECV:
+   case ATA_CMD_FPDMA_SEND:
+   case ATA_CMD_NCQ_NON_DATA:
+   return SATA_PROTOCOL_FPDMA;
+
+   case ATA_CMD_DOWNLOAD_MICRO:
+   case ATA_CMD_ID_ATA:
+   case ATA_CMD_PMP_READ:
+   case ATA_CMD_READ_LOG_EXT:
+   case ATA_CMD_PIO_READ:
+   case ATA_CMD_PIO_READ_EXT:
+   case ATA_CMD_PMP_WRITE:
+   case ATA_CMD_WRITE_LOG_EXT:
+   case ATA_CMD_PIO_WRITE:
+   case ATA_CMD_PIO_WRITE_EXT:
+   return SATA_PROTOCOL_PIO;
+
+   case ATA_CMD_DSM:
+   case ATA_CMD_DOWNLOAD_MICRO_DMA:
+   case ATA_CMD_PMP_READ_DMA:
+   case ATA_CMD_PMP_WRITE_DMA:
+   case ATA_CMD_READ:
+   case ATA_CMD_READ_EXT:
+   case ATA_CMD_READ_LOG_DMA_EXT:
+   case ATA_CMD_READ_STREAM_DMA_EXT:
+   case ATA_CMD_TRUSTED_RCV_DMA:
+   case ATA_CMD_TRUSTED_SND_DMA:
+   case ATA_CMD_WRITE:
+   case ATA_CMD_WRITE_EXT:
+   case ATA_CMD_WRITE_FUA_EXT:
+   case ATA_CMD_WRITE_QUEUED:
+   case ATA_CMD_WRITE_LOG_DMA_EXT:
+   case ATA_CMD_WRITE_STREAM_DMA_EXT:
+   return SATA_PROTOCOL_DMA;
+
+   case ATA_CMD_CHK_POWER:
+   case ATA_CMD_DEV_RESET:
+   case ATA_CMD_EDD:
+   case ATA_CMD_FLUSH:
+   case ATA_CMD_FLUSH_EXT:
+   case ATA_CMD_VERIFY:
+   case ATA_CMD_VERIFY_EXT:
+   case ATA_CMD_SET_FEATURES:
+   case ATA_CMD_STANDBY:
+   case ATA_CMD_STANDBYNOW1:
+   return SATA_PROTOCOL_NONDATA;
+   default:
+   if (direction == DMA_NONE)
+   return SATA_PROTOCOL_NONDATA;
+   return SATA_PROTOCOL_PIO;
+   }
+}
+EXPORT_SYMBOL_GPL(hisi_sas_get_ata_protocol);
+
 static struct hisi_hba *dev_to_hisi_hba(struct domain_device *device)
 {
return device->port->ha->lldd_ha;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 2607aac..d9314c4 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -554,12 +554,6 @@ enum {
 #define DIR_TO_DEVICE 2
 #define DIR_RESERVED 3
 
-#define SATA_PROTOCOL_NONDATA  0x1
-#define SATA_PROTOCOL_PIO  0x2
-#define SATA_PROTOCOL_DMA  0x4
-#define SATA_PROTOCOL_FPDMA0x8
-#define SATA_PROTOCOL_ATAPI0x10
-
 #define ERR_ON_TX_PHASE(err_phase) (err_phase == 0x2 || \
err_phase == 0x4 || err_phase == 0x8 ||\
err_phase == 0x6 || err_phase == 0xa)
@@ -2352,64 +2346,6 @@ static void slot_err_v2_hw(struct hisi_hba *hisi_hba,
return sts;
 }
 
-static u8 get_ata_protocol(u8 cmd, int direction)
-{
-   switch (cmd) {
-   case ATA_CMD_FPDMA_WRITE:
-   case ATA_CMD_FPDMA_READ:
-   case ATA_CMD_FPDMA_RECV:
-   case ATA_CMD_FPDMA_SEND:
-   case ATA_CMD_NCQ_NON_DATA:
- 

[PATCH v3 07/23] scsi: hisi_sas: add pci_dev in hisi_hba struct

2017-05-31 Thread John Garry
Since hip08 SAS controller is based on pci device, add hisi_hba.pci_dev
for hip08 (will be v3), and also rename hisi_hba.pdev to .platform_dev
for clarity.

In addition, for common code which wants to reference the controller
device struct, add hisi_hba.dev, and change the common code to use
it.

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |  6 -
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 36 ++--
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 28 +++---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 44 +-
 4 files changed, 59 insertions(+), 55 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 439b1f2..7b63656 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -190,7 +191,10 @@ struct hisi_hba {
/* This must be the first element, used by SHOST_TO_SAS_HA */
struct sas_ha_struct *p;
 
-   struct platform_device *pdev;
+   struct platform_device *platform_dev;
+   struct pci_dev *pci_dev;
+   struct device *dev;
+
void __iomem *regs;
struct regmap *ctrl;
u32 ctrl_reset_reg;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 32962d3..eefab13 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -174,7 +174,7 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, 
struct sas_task *task,
 {
 
if (task) {
-   struct device *dev = _hba->pdev->dev;
+   struct device *dev = hisi_hba->dev;
struct domain_device *device = task->dev;
struct hisi_sas_device *sas_dev = device->lldd_dev;
 
@@ -251,7 +251,7 @@ static void hisi_sas_slot_abort(struct work_struct *work)
struct scsi_cmnd *cmnd = task->uldd_task;
struct hisi_sas_tmf_task tmf_task;
struct scsi_lun lun;
-   struct device *dev = _hba->pdev->dev;
+   struct device *dev = hisi_hba->dev;
int tag = abort_slot->idx;
unsigned long flags;
 
@@ -285,7 +285,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct 
hisi_sas_dq
struct hisi_sas_slot *slot;
struct hisi_sas_cmd_hdr *cmd_hdr_base;
struct asd_sas_port *sas_port = device->port;
-   struct device *dev = _hba->pdev->dev;
+   struct device *dev = hisi_hba->dev;
int dlvry_queue_slot, dlvry_queue, n_elem = 0, rc, slot_idx;
unsigned long flags;
 
@@ -455,7 +455,7 @@ static int hisi_sas_task_exec(struct sas_task *task, gfp_t 
gfp_flags,
u32 pass = 0;
unsigned long flags;
struct hisi_hba *hisi_hba = dev_to_hisi_hba(task->dev);
-   struct device *dev = _hba->pdev->dev;
+   struct device *dev = hisi_hba->dev;
struct domain_device *device = task->dev;
struct hisi_sas_device *sas_dev = device->lldd_dev;
struct hisi_sas_dq *dq = sas_dev->dq;
@@ -550,7 +550,7 @@ static int hisi_sas_dev_found(struct domain_device *device)
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
struct domain_device *parent_dev = device->parent;
struct hisi_sas_device *sas_dev;
-   struct device *dev = _hba->pdev->dev;
+   struct device *dev = hisi_hba->dev;
 
if (hisi_hba->hw->alloc_dev)
sas_dev = hisi_hba->hw->alloc_dev(device);
@@ -735,7 +735,7 @@ static void hisi_sas_dev_gone(struct domain_device *device)
 {
struct hisi_sas_device *sas_dev = device->lldd_dev;
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
-   struct device *dev = _hba->pdev->dev;
+   struct device *dev = hisi_hba->dev;
int dev_id = sas_dev->device_id;
 
dev_info(dev, "found dev[%d:%x] is gone\n",
@@ -818,7 +818,7 @@ static int hisi_sas_exec_internal_tmf_task(struct 
domain_device *device,
 {
struct hisi_sas_device *sas_dev = device->lldd_dev;
struct hisi_hba *hisi_hba = sas_dev->hisi_hba;
-   struct device *dev = _hba->pdev->dev;
+   struct device *dev = hisi_hba->dev;
struct sas_task *task;
int res, retry;
 
@@ -935,7 +935,7 @@ static int hisi_sas_softreset_ata_disk(struct domain_device 
*device)
struct ata_link *link;
int rc = TMF_RESP_FUNC_FAILED;
struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
-   struct device *dev = _hba->pdev->dev;
+   struct device *dev = hisi_hba->dev;
int s = sizeof(struct host_to_dev_fis);
unsigned long flags;
 
@@ -993,7 +993,7 @@ static int hisi_sas_controller_reset(struct hisi_hba 
*hisi_hba)
return -1;
 
if (!test_and_set_bit(HISI_SAS_RESET_BIT, _hba->flags)) {
-   struct device *dev = _hba->pdev->dev;
+

[PATCH v3 08/23] scsi: hisi_sas: create hisi_sas_get_fw_info()

2017-05-31 Thread John Garry
Move the functionality to retrieve the fw info into
a dedicated device type-agnostic function,
hisi_sas_get_fw_info().

The reasoning is that this function will be required
for future pci-based platforms.

Also add some debug logs for failure.

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h  |   1 +
 drivers/scsi/hisi_sas/hisi_sas_main.c | 107 ++
 2 files changed, 71 insertions(+), 37 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 7b63656..480f9ae 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -365,6 +365,7 @@ struct hisi_sas_command_table_ssp {
 extern void hisi_sas_sata_done(struct sas_task *task,
struct hisi_sas_slot *slot);
 extern int hisi_sas_get_ncq_tag(struct sas_task *task, u32 *tag);
+extern int hisi_sas_get_fw_info(struct hisi_hba *hisi_hba);
 extern int hisi_sas_probe(struct platform_device *pdev,
  const struct hisi_sas_hw *ops);
 extern int hisi_sas_remove(struct platform_device *pdev);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index eefab13..5979ab6 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1731,66 +1731,99 @@ static void hisi_sas_rst_work_handler(struct 
work_struct *work)
hisi_sas_controller_reset(hisi_hba);
 }
 
-static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
- const struct hisi_sas_hw *hw)
+int hisi_sas_get_fw_info(struct hisi_hba *hisi_hba)
 {
-   struct resource *res;
-   struct Scsi_Host *shost;
-   struct hisi_hba *hisi_hba;
-   struct device *dev = >dev;
-   struct device_node *np = pdev->dev.of_node;
+   struct device *dev = hisi_hba->dev;
+   struct platform_device *pdev = hisi_hba->platform_dev;
+   struct device_node *np = pdev ? pdev->dev.of_node : NULL;
struct clk *refclk;
 
-   shost = scsi_host_alloc(_sas_sht, sizeof(*hisi_hba));
-   if (!shost) {
-   dev_err(dev, "scsi host alloc failed\n");
-   return NULL;
-   }
-   hisi_hba = shost_priv(shost);
-
-   INIT_WORK(_hba->rst_work, hisi_sas_rst_work_handler);
-   hisi_hba->hw = hw;
-   hisi_hba->platform_dev = pdev;
-   hisi_hba->dev = dev;
-   hisi_hba->shost = shost;
-   SHOST_TO_SAS_HA(shost) = _hba->sha;
-
-   init_timer(_hba->timer);
-
if (device_property_read_u8_array(dev, "sas-addr", hisi_hba->sas_addr,
- SAS_ADDR_SIZE))
-   goto err_out;
+ SAS_ADDR_SIZE)) {
+   dev_err(dev, "could not get property sas-addr\n");
+   return -ENOENT;
+   }
 
if (np) {
+   /*
+* These properties are only required for platform device-based
+* controller with DT firmware.
+*/
hisi_hba->ctrl = syscon_regmap_lookup_by_phandle(np,
"hisilicon,sas-syscon");
-   if (IS_ERR(hisi_hba->ctrl))
-   goto err_out;
+   if (IS_ERR(hisi_hba->ctrl)) {
+   dev_err(dev, "could not get syscon\n");
+   return -ENOENT;
+   }
 
if (device_property_read_u32(dev, "ctrl-reset-reg",
-_hba->ctrl_reset_reg))
-   goto err_out;
+_hba->ctrl_reset_reg)) {
+   dev_err(dev,
+   "could not get property ctrl-reset-reg\n");
+   return -ENOENT;
+   }
 
if (device_property_read_u32(dev, "ctrl-reset-sts-reg",
-_hba->ctrl_reset_sts_reg))
-   goto err_out;
+_hba->ctrl_reset_sts_reg)) {
+   dev_err(dev,
+   "could not get property ctrl-reset-sts-reg\n");
+   return -ENOENT;
+   }
 
if (device_property_read_u32(dev, "ctrl-clock-ena-reg",
-_hba->ctrl_clock_ena_reg))
-   goto err_out;
+_hba->ctrl_clock_ena_reg)) {
+   dev_err(dev,
+   "could not get property ctrl-clock-ena-reg\n");
+   return -ENOENT;
+   }
}
 
-   refclk = devm_clk_get(>dev, NULL);
+   refclk = devm_clk_get(dev, NULL);
if (IS_ERR(refclk))
dev_dbg(dev, "no ref clk property\n");
else

[PATCH v3 01/23] scsi: hisi_sas: fix timeout check in hisi_sas_internal_task_abort()

2017-05-31 Thread John Garry
From: Xiang Chen 

We need to check for timeout before task status, or the task will be
mistook as completed internal abort command.
Also add protection for sas_task.task_state_flags in
hisi_sas_tmf_timedout().

Signed-off-by: Xiang Chen 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_main.c | 25 +
 1 file changed, 17 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index f720d3c..3605d28 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -691,8 +691,13 @@ static void hisi_sas_task_done(struct sas_task *task)
 static void hisi_sas_tmf_timedout(unsigned long data)
 {
struct sas_task *task = (struct sas_task *)data;
+   unsigned long flags;
+
+   spin_lock_irqsave(>task_state_lock, flags);
+   if (!(task->task_state_flags & SAS_TASK_STATE_DONE))
+   task->task_state_flags |= SAS_TASK_STATE_ABORTED;
+   spin_unlock_irqrestore(>task_state_lock, flags);
 
-   task->task_state_flags |= SAS_TASK_STATE_ABORTED;
complete(>slow_task->completion);
 }
 
@@ -1247,6 +1252,17 @@ static int hisi_sas_query_task(struct sas_task *task)
wait_for_completion(>slow_task->completion);
res = TMF_RESP_FUNC_FAILED;
 
+   /* Internal abort timed out */
+   if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
+   if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
+   struct hisi_sas_slot *slot = task->lldd_task;
+
+   if (slot)
+   slot->task = NULL;
+   dev_err(dev, "internal task abort: timeout.\n");
+   }
+   }
+
if (task->task_status.resp == SAS_TASK_COMPLETE &&
task->task_status.stat == TMF_RESP_FUNC_COMPLETE) {
res = TMF_RESP_FUNC_COMPLETE;
@@ -1259,13 +1275,6 @@ static int hisi_sas_query_task(struct sas_task *task)
goto exit;
}
 
-   /* Internal abort timed out */
-   if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
-   if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
-   dev_err(dev, "internal task abort: timeout.\n");
-   }
-   }
-
 exit:
dev_dbg(dev, "internal task abort: task to dev %016llx task=%p "
"resp: 0x%x sts 0x%x\n",
-- 
1.9.1



[PATCH v3 09/23] scsi: hisi_sas: add skeleton v3 hw driver

2017-05-31 Thread John Garry
Add skeleton driver for v3 hw in hisi_sas_v3_hw.c

File hisi_sas_v3_hw.c will serve 2 purposes:
- probing and initialisation of the controller based on pci device
- hw layer for v3-based controllers

The controller design is quite similar to v2 hw in hip07.

However key differences include:
-All v2 hw bugs are fixed (hopefully), so workarounds are not
required
-support for device deregistration
-some interrupt modifications
-configurable max device support

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/Kconfig  | 10 +++-
 drivers/scsi/hisi_sas/Makefile |  1 +
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 47 ++
 3 files changed, 57 insertions(+), 1 deletion(-)
 create mode 100644 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c

diff --git a/drivers/scsi/hisi_sas/Kconfig b/drivers/scsi/hisi_sas/Kconfig
index 975dbf0..a5ca080 100644
--- a/drivers/scsi/hisi_sas/Kconfig
+++ b/drivers/scsi/hisi_sas/Kconfig
@@ -6,4 +6,12 @@ config SCSI_HISI_SAS
select BLK_DEV_INTEGRITY
depends on ATA
help
-   This driver supports HiSilicon's SAS HBA
+   This driver supports HiSilicon's SAS HBA, including support 
based
+   on platform device
+
+config SCSI_HISI_SAS_PCI
+   tristate "HiSilicon SAS on PCI bus"
+   depends on SCSI_HISI_SAS
+   depends on PCI
+   help
+   This driver supports HiSilicon's SAS HBA based on PCI device
diff --git a/drivers/scsi/hisi_sas/Makefile b/drivers/scsi/hisi_sas/Makefile
index c6d3a1b..24623f2 100644
--- a/drivers/scsi/hisi_sas/Makefile
+++ b/drivers/scsi/hisi_sas/Makefile
@@ -1,2 +1,3 @@
 obj-$(CONFIG_SCSI_HISI_SAS)+= hisi_sas_main.o
 obj-$(CONFIG_SCSI_HISI_SAS)+= hisi_sas_v1_hw.o hisi_sas_v2_hw.o
+obj-$(CONFIG_SCSI_HISI_SAS_PCI)+= hisi_sas_v3_hw.o
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
new file mode 100644
index 000..cf72577
--- /dev/null
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2017 Hisilicon Limited.
+ *
+ * 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 "hisi_sas.h"
+#define DRV_NAME "hisi_sas_v3_hw"
+
+static int
+hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+   return 0;
+}
+
+static void hisi_sas_v3_remove(struct pci_dev *pdev)
+{
+}
+
+enum {
+   /* instances of the controller */
+   hip08,
+};
+
+static const struct pci_device_id sas_v3_pci_table[] = {
+   { PCI_VDEVICE(HUAWEI, 0xa230), hip08 },
+   {}
+};
+
+static struct pci_driver sas_v3_pci_driver = {
+   .name   = DRV_NAME,
+   .id_table   = sas_v3_pci_table,
+   .probe  = hisi_sas_v3_probe,
+   .remove = hisi_sas_v3_remove,
+};
+
+module_pci_driver(sas_v3_pci_driver);
+
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("John Garry ");
+MODULE_DESCRIPTION("HISILICON SAS controller v3 hw driver based on pci 
device");
+MODULE_ALIAS("platform:" DRV_NAME);
-- 
1.9.1



[PATCH v3 05/23] scsi: hisi_sas: relocate sata_done_v2_hw()

2017-05-31 Thread John Garry
From: Xiang Chen 

Relocate get_ata_protocol() to a common location, as future hw
versions will require it.
Also rename with "hisi_sas_" prefix for consistency.

Signed-off-by: Xiang Chen 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |  2 ++
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 15 +++
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 18 ++
 3 files changed, 19 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 8ed1199..f2d69cd 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -358,6 +358,8 @@ struct hisi_sas_command_table_ssp {
 
 extern u8 hisi_sas_get_ata_protocol(u8 cmd, int direction);
 extern struct hisi_sas_port *to_hisi_sas_port(struct asd_sas_port *sas_port);
+extern void hisi_sas_sata_done(struct sas_task *task,
+   struct hisi_sas_slot *slot);
 extern int hisi_sas_probe(struct platform_device *pdev,
  const struct hisi_sas_hw *ops);
 extern int hisi_sas_remove(struct platform_device *pdev);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index f71590c..88ace7c 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -88,6 +88,21 @@ u8 hisi_sas_get_ata_protocol(u8 cmd, int direction)
 }
 EXPORT_SYMBOL_GPL(hisi_sas_get_ata_protocol);
 
+void hisi_sas_sata_done(struct sas_task *task,
+   struct hisi_sas_slot *slot)
+{
+   struct task_status_struct *ts = >task_status;
+   struct ata_task_resp *resp = (struct ata_task_resp *)ts->buf;
+   struct dev_to_host_fis *d2h = slot->status_buffer +
+ sizeof(struct hisi_sas_err_record);
+
+   resp->frame_len = sizeof(struct dev_to_host_fis);
+   memcpy(>ending_fis[0], d2h, sizeof(struct dev_to_host_fis));
+
+   ts->buf_valid_size = sizeof(*resp);
+}
+EXPORT_SYMBOL_GPL(hisi_sas_sata_done);
+
 static struct hisi_hba *dev_to_hisi_hba(struct domain_device *device)
 {
return device->port->ha->lldd_ha;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index d9314c4..fdd7019 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -1683,20 +1683,6 @@ static int prep_ssp_v2_hw(struct hisi_hba *hisi_hba,
return 0;
 }
 
-static void sata_done_v2_hw(struct hisi_hba *hisi_hba, struct sas_task *task,
-   struct hisi_sas_slot *slot)
-{
-   struct task_status_struct *ts = >task_status;
-   struct ata_task_resp *resp = (struct ata_task_resp *)ts->buf;
-   struct dev_to_host_fis *d2h = slot->status_buffer +
- sizeof(struct hisi_sas_err_record);
-
-   resp->frame_len = sizeof(struct dev_to_host_fis);
-   memcpy(>ending_fis[0], d2h, sizeof(struct dev_to_host_fis));
-
-   ts->buf_valid_size = sizeof(*resp);
-}
-
 #define TRANS_TX_ERR   0
 #define TRANS_RX_ERR   1
 #define DMA_TX_ERR 2
@@ -2189,7 +2175,7 @@ static void slot_err_v2_hw(struct hisi_hba *hisi_hba,
break;
}
}
-   sata_done_v2_hw(hisi_hba, task, slot);
+   hisi_sas_sata_done(task, slot);
}
break;
default:
@@ -2317,7 +2303,7 @@ static void slot_err_v2_hw(struct hisi_hba *hisi_hba,
case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
{
ts->stat = SAM_STAT_GOOD;
-   sata_done_v2_hw(hisi_hba, task, slot);
+   hisi_sas_sata_done(task, slot);
break;
}
default:
-- 
1.9.1



[PATCH v3 23/23] scsi: hisi_sas: modify internal abort dev flow for v3 hw

2017-05-31 Thread John Garry
From: Xiang Chen 

There is a change for abort dev for v3 hw: add registers to configure
unaborted iptt for a device, and then inform this to logic.

Signed-off-by: Xiang Chen 
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |  2 ++
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 15 +++
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 28 
 3 files changed, 45 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index d7545ff..cf2a593 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -182,6 +182,8 @@ struct hisi_sas_hw {
void (*free_device)(struct hisi_hba *hisi_hba,
struct hisi_sas_device *dev);
int (*get_wideport_bitmap)(struct hisi_hba *hisi_hba, int port_id);
+   void (*dereg_device)(struct hisi_hba *hisi_hba,
+   struct domain_device *device);
int (*soft_reset)(struct hisi_hba *hisi_hba);
int max_command_entries;
int complete_hdr_size;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index b90eb50..96a23af 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -763,6 +763,13 @@ static void hisi_sas_release_tasks(struct hisi_hba 
*hisi_hba)
}
 }
 
+static void hisi_sas_dereg_device(struct hisi_hba *hisi_hba,
+   struct domain_device *device)
+{
+   if (hisi_hba->hw->dereg_device)
+   hisi_hba->hw->dereg_device(hisi_hba, device);
+}
+
 static void hisi_sas_dev_gone(struct domain_device *device)
 {
struct hisi_sas_device *sas_dev = device->lldd_dev;
@@ -776,6 +783,8 @@ static void hisi_sas_dev_gone(struct domain_device *device)
hisi_sas_internal_task_abort(hisi_hba, device,
 HISI_SAS_INT_ABT_DEV, 0);
 
+   hisi_sas_dereg_device(hisi_hba, device);
+
hisi_hba->hw->free_device(hisi_hba, sas_dev);
device->lldd_dev = NULL;
memset(sas_dev, 0, sizeof(*sas_dev));
@@ -1107,6 +1116,7 @@ static int hisi_sas_abort_task(struct sas_task *task)
if (task->dev->dev_type == SAS_SATA_DEV) {
hisi_sas_internal_task_abort(hisi_hba, device,
 HISI_SAS_INT_ABT_DEV, 0);
+   hisi_sas_dereg_device(hisi_hba, device);
rc = hisi_sas_softreset_ata_disk(device);
}
} else if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SMP) {
@@ -1173,6 +1183,10 @@ static int hisi_sas_I_T_nexus_reset(struct domain_device 
*device)
return TMF_RESP_FUNC_FAILED;
sas_dev->dev_status = HISI_SAS_DEV_NORMAL;
 
+   hisi_sas_internal_task_abort(hisi_hba, device,
+   HISI_SAS_INT_ABT_DEV, 0);
+   hisi_sas_dereg_device(hisi_hba, device);
+
rc = hisi_sas_debug_I_T_nexus_reset(device);
 
if (rc == TMF_RESP_FUNC_COMPLETE) {
@@ -1200,6 +1214,7 @@ static int hisi_sas_lu_reset(struct domain_device 
*device, u8 *lun)
  HISI_SAS_INT_ABT_DEV, 0);
if (rc == TMF_RESP_FUNC_FAILED)
goto out;
+   hisi_sas_dereg_device(hisi_hba, device);
 
phy = sas_get_local_phy(device);
 
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 17f9ac9..63239ca 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -50,6 +50,10 @@
 #define CFG_ABT_SET_QUERY_IPTT 0xd4
 #define CFG_SET_ABORTED_IPTT_OFF   0
 #define CFG_SET_ABORTED_IPTT_MSK   (0xfff << CFG_SET_ABORTED_IPTT_OFF)
+#define CFG_SET_ABORTED_EN_OFF 12
+#define CFG_ABT_SET_IPTT_DONE  0xd8
+#define CFG_ABT_SET_IPTT_DONE_OFF  0
+#define HGC_IOMB_PROC1_STATUS  0x104
 #define CFG_1US_TIMER_TRSH 0xcc
 #define HGC_LM_DFX_STATUS2 0x128
 #define HGC_LM_DFX_STATUS2_IOSTLIST_OFF0
@@ -635,6 +639,29 @@ static void free_device_v3_hw(struct hisi_hba *hisi_hba,
}
 }
 
+static void dereg_device_v3_hw(struct hisi_hba *hisi_hba,
+   struct domain_device *device)
+{
+   struct hisi_sas_slot *slot, *slot2;
+   struct hisi_sas_device *sas_dev = device->lldd_dev;
+   u32 cfg_abt_set_query_iptt;
+
+   cfg_abt_set_query_iptt = hisi_sas_read32(hisi_hba,
+   CFG_ABT_SET_QUERY_IPTT);
+   list_for_each_entry_safe(slot, slot2, _dev->list, entry) {
+   cfg_abt_set_query_iptt &= ~CFG_SET_ABORTED_IPTT_MSK;
+   cfg_abt_set_query_iptt |= (1 << CFG_SET_ABORTED_EN_OFF) |
+   (slot->idx << CFG_SET_ABORTED_IPTT_OFF);
+   

[PATCH v3 21/23] scsi: hisi_sas: Add v3 code to support ECC and AXI bus fatal error

2017-05-31 Thread John Garry
From: Xiang Chen 

For ECC 1bit error, logic can recover it, so we only print a warning.
For ECC multi-bit and AXI bus fatal error, we panic.

Note: once v3 hw controller reset support is added, the panic will
  be replaced by a controller reset, like v2 hw.

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 402 -
 1 file changed, 400 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index f71f1ba..3203221 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -51,7 +51,39 @@
 #define CFG_SET_ABORTED_IPTT_OFF   0
 #define CFG_SET_ABORTED_IPTT_MSK   (0xfff << CFG_SET_ABORTED_IPTT_OFF)
 #define CFG_1US_TIMER_TRSH 0xcc
+#define HGC_LM_DFX_STATUS2 0x128
+#define HGC_LM_DFX_STATUS2_IOSTLIST_OFF0
+#define HGC_LM_DFX_STATUS2_IOSTLIST_MSK(0xfff <<\
+   HGC_LM_DFX_STATUS2_IOSTLIST_OFF)
+#define HGC_LM_DFX_STATUS2_ITCTLIST_OFF12
+#define HGC_LM_DFX_STATUS2_ITCTLIST_MSK(0x7ff <<\
+   HGC_LM_DFX_STATUS2_ITCTLIST_OFF)
+#define HGC_CQE_ECC_ADDR   0x13c
+#define HGC_CQE_ECC_1B_ADDR_OFF0
+#define HGC_CQE_ECC_1B_ADDR_MSK(0x3f << 
HGC_CQE_ECC_1B_ADDR_OFF)
+#define HGC_CQE_ECC_MB_ADDR_OFF8
+#define HGC_CQE_ECC_MB_ADDR_MSK(0x3f << 
HGC_CQE_ECC_MB_ADDR_OFF)
+#define HGC_IOST_ECC_ADDR  0x140
+#define HGC_IOST_ECC_1B_ADDR_OFF   0
+#define HGC_IOST_ECC_1B_ADDR_MSK   (0x3ff << HGC_IOST_ECC_1B_ADDR_OFF)
+#define HGC_IOST_ECC_MB_ADDR_OFF   16
+#define HGC_IOST_ECC_MB_ADDR_MSK   (0x3ff << HGC_IOST_ECC_MB_ADDR_OFF)
+#define HGC_DQE_ECC_ADDR   0x144
+#define HGC_DQE_ECC_1B_ADDR_OFF0
+#define HGC_DQE_ECC_1B_ADDR_MSK(0xfff << 
HGC_DQE_ECC_1B_ADDR_OFF)
+#define HGC_DQE_ECC_MB_ADDR_OFF16
+#define HGC_DQE_ECC_MB_ADDR_MSK(0xfff << 
HGC_DQE_ECC_MB_ADDR_OFF)
 #define CHNL_INT_STATUS0x148
+#define HGC_ITCT_ECC_ADDR  0x150
+#define HGC_ITCT_ECC_1B_ADDR_OFF   0
+#define HGC_ITCT_ECC_1B_ADDR_MSK   (0x3ff << HGC_ITCT_ECC_1B_ADDR_OFF)
+#define HGC_ITCT_ECC_MB_ADDR_OFF   16
+#define HGC_ITCT_ECC_MB_ADDR_MSK   (0x3ff << HGC_ITCT_ECC_MB_ADDR_OFF)
+#define HGC_AXI_FIFO_ERR_INFO  0x154
+#define AXI_ERR_INFO_OFF   0
+#define AXI_ERR_INFO_MSK   (0xff << AXI_ERR_INFO_OFF)
+#define FIFO_ERR_INFO_OFF  8
+#define FIFO_ERR_INFO_MSK  (0xff << FIFO_ERR_INFO_OFF)
 #define INT_COAL_EN0x19c
 #define OQ_INT_COAL_TIME   0x1a0
 #define OQ_INT_COAL_CNT0x1a4
@@ -85,6 +117,26 @@
 #define ENT_INT_SRC_MSK3_ENT95_MSK_MSK (0x1 << ENT_INT_SRC_MSK3_ENT95_MSK_OFF)
 #define SAS_ECC_INTR   0x1e8
 #define SAS_ECC_INTR_MSK   0x1ec
+#define SAS_ECC_INTR_DQE_ECC_1B_OFF0
+#define SAS_ECC_INTR_DQE_ECC_MB_OFF1
+#define SAS_ECC_INTR_IOST_ECC_1B_OFF   2
+#define SAS_ECC_INTR_IOST_ECC_MB_OFF   3
+#define SAS_ECC_INTR_ITCT_ECC_MB_OFF   4
+#define SAS_ECC_INTR_ITCT_ECC_1B_OFF   5
+#define SAS_ECC_INTR_IOSTLIST_ECC_MB_OFF   6
+#define SAS_ECC_INTR_IOSTLIST_ECC_1B_OFF   7
+#define SAS_ECC_INTR_ITCTLIST_ECC_MB_OFF   8
+#define SAS_ECC_INTR_ITCTLIST_ECC_1B_OFF   9
+#define SAS_ECC_INTR_CQE_ECC_1B_OFF10
+#define SAS_ECC_INTR_CQE_ECC_MB_OFF11
+#define SAS_ECC_INTR_NCQ_MEM0_ECC_MB_OFF   12
+#define SAS_ECC_INTR_NCQ_MEM0_ECC_1B_OFF   13
+#define SAS_ECC_INTR_NCQ_MEM1_ECC_MB_OFF   14
+#define SAS_ECC_INTR_NCQ_MEM1_ECC_1B_OFF   15
+#define SAS_ECC_INTR_NCQ_MEM2_ECC_MB_OFF   16
+#define SAS_ECC_INTR_NCQ_MEM2_ECC_1B_OFF   17
+#define SAS_ECC_INTR_NCQ_MEM3_ECC_MB_OFF   18
+#define SAS_ECC_INTR_NCQ_MEM3_ECC_1B_OFF   19
 #define HGC_ERR_STAT_EN0x238
 #define DLVRY_Q_0_BASE_ADDR_LO 0x260
 #define DLVRY_Q_0_BASE_ADDR_HI 0x264
@@ -98,6 +150,20 @@
 #define COMPL_Q_0_DEPTH0x4e8
 #define COMPL_Q_0_WR_PTR   0x4ec
 #define COMPL_Q_0_RD_PTR   0x4f0
+#define HGC_RXM_DFX_STATUS14   0xae8
+#define HGC_RXM_DFX_STATUS14_MEM0_OFF  0
+#define HGC_RXM_DFX_STATUS14_MEM0_MSK  (0x1ff <<\
+   HGC_RXM_DFX_STATUS14_MEM0_OFF)
+#define HGC_RXM_DFX_STATUS14_MEM1_OFF  9
+#define HGC_RXM_DFX_STATUS14_MEM1_MSK  (0x1ff <<\
+   HGC_RXM_DFX_STATUS14_MEM1_OFF)
+#define HGC_RXM_DFX_STATUS14_MEM2_OFF  18
+#define HGC_RXM_DFX_STATUS14_MEM2_MSK  

[PATCH v3 18/23] scsi: hisi_sas: add v3 code for itct setup and free

2017-05-31 Thread John Garry
From: Xiang Chen 

Add code to itct setup and free for v3 hw.

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 114 +
 1 file changed, 114 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 613c625..720abd1c 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -24,6 +24,11 @@
 #define PHY_PORT_NUM_MA0x28
 #define PHY_CONN_RATE  0x30
 #define AXI_AHB_CLK_CFG0x3c
+#define ITCT_CLR   0x44
+#define ITCT_CLR_EN_OFF16
+#define ITCT_CLR_EN_MSK(0x1 << ITCT_CLR_EN_OFF)
+#define ITCT_DEV_OFF   0
+#define ITCT_DEV_MSK   (0x7ff << ITCT_DEV_OFF)
 #define AXI_USER1  0x48
 #define AXI_USER2  0x4c
 #define IO_SATA_BROKEN_MSG_ADDR_LO 0x58
@@ -226,6 +231,26 @@
 #define CMPLT_HDR_IO_IN_TARGET_OFF 17
 #define CMPLT_HDR_IO_IN_TARGET_MSK (0x1 << CMPLT_HDR_IO_IN_TARGET_OFF)
 
+/* ITCT header */
+/* qw0 */
+#define ITCT_HDR_DEV_TYPE_OFF  0
+#define ITCT_HDR_DEV_TYPE_MSK  (0x3 << ITCT_HDR_DEV_TYPE_OFF)
+#define ITCT_HDR_VALID_OFF 2
+#define ITCT_HDR_VALID_MSK (0x1 << ITCT_HDR_VALID_OFF)
+#define ITCT_HDR_MCR_OFF   5
+#define ITCT_HDR_MCR_MSK   (0xf << ITCT_HDR_MCR_OFF)
+#define ITCT_HDR_VLN_OFF   9
+#define ITCT_HDR_VLN_MSK   (0xf << ITCT_HDR_VLN_OFF)
+#define ITCT_HDR_SMP_TIMEOUT_OFF   16
+#define ITCT_HDR_AWT_CONTINUE_OFF  25
+#define ITCT_HDR_PORT_ID_OFF   28
+#define ITCT_HDR_PORT_ID_MSK   (0xf << ITCT_HDR_PORT_ID_OFF)
+/* qw2 */
+#define ITCT_HDR_INLT_OFF  0
+#define ITCT_HDR_INLT_MSK  (0xULL << ITCT_HDR_INLT_OFF)
+#define ITCT_HDR_RTOLT_OFF 48
+#define ITCT_HDR_RTOLT_MSK (0xULL << ITCT_HDR_RTOLT_OFF)
+
 struct hisi_sas_complete_v3_hdr {
__le32 dw0;
__le32 dw1;
@@ -444,6 +469,93 @@ static void config_id_frame_v3_hw(struct hisi_hba 
*hisi_hba, int phy_no)
__swab32(identify_buffer[5]));
 }
 
+static void setup_itct_v3_hw(struct hisi_hba *hisi_hba,
+struct hisi_sas_device *sas_dev)
+{
+   struct domain_device *device = sas_dev->sas_device;
+   struct device *dev = hisi_hba->dev;
+   u64 qw0, device_id = sas_dev->device_id;
+   struct hisi_sas_itct *itct = _hba->itct[device_id];
+   struct domain_device *parent_dev = device->parent;
+   struct asd_sas_port *sas_port = device->port;
+   struct hisi_sas_port *port = to_hisi_sas_port(sas_port);
+
+   memset(itct, 0, sizeof(*itct));
+
+   /* qw0 */
+   qw0 = 0;
+   switch (sas_dev->dev_type) {
+   case SAS_END_DEVICE:
+   case SAS_EDGE_EXPANDER_DEVICE:
+   case SAS_FANOUT_EXPANDER_DEVICE:
+   qw0 = HISI_SAS_DEV_TYPE_SSP << ITCT_HDR_DEV_TYPE_OFF;
+   break;
+   case SAS_SATA_DEV:
+   case SAS_SATA_PENDING:
+   if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type))
+   qw0 = HISI_SAS_DEV_TYPE_STP << ITCT_HDR_DEV_TYPE_OFF;
+   else
+   qw0 = HISI_SAS_DEV_TYPE_SATA << ITCT_HDR_DEV_TYPE_OFF;
+   break;
+   default:
+   dev_warn(dev, "setup itct: unsupported dev type (%d)\n",
+sas_dev->dev_type);
+   }
+
+   qw0 |= ((1 << ITCT_HDR_VALID_OFF) |
+   (device->linkrate << ITCT_HDR_MCR_OFF) |
+   (1 << ITCT_HDR_VLN_OFF) |
+   (0xfa << ITCT_HDR_SMP_TIMEOUT_OFF) |
+   (1 << ITCT_HDR_AWT_CONTINUE_OFF) |
+   (port->id << ITCT_HDR_PORT_ID_OFF));
+   itct->qw0 = cpu_to_le64(qw0);
+
+   /* qw1 */
+   memcpy(>sas_addr, device->sas_addr, SAS_ADDR_SIZE);
+   itct->sas_addr = __swab64(itct->sas_addr);
+
+   /* qw2 */
+   if (!dev_is_sata(device))
+   itct->qw2 = cpu_to_le64((5000ULL << ITCT_HDR_INLT_OFF) |
+   (0x1ULL << ITCT_HDR_RTOLT_OFF));
+}
+
+static void free_device_v3_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_device *sas_dev)
+{
+   u64 dev_id = sas_dev->device_id;
+   struct device *dev = hisi_hba->dev;
+   struct hisi_sas_itct *itct = _hba->itct[dev_id];
+   u32 reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
+
+   /* clear the itct interrupt state */
+   if (ENT_INT_SRC3_ITC_INT_MSK & reg_val)
+   hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
+ENT_INT_SRC3_ITC_INT_MSK);
+
+   /* clear the itct table*/
+   reg_val = hisi_sas_read32(hisi_hba, 

[PATCH v3 15/23] scsi: hisi_sas: add v3 code to send SSP frame

2017-05-31 Thread John Garry
From: Xiang Chen 

Add code to prepare SSP frame and deliver it to hardware.

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 208 +
 1 file changed, 208 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 4259047..7be3a53 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -157,6 +157,41 @@
 #define SL_RX_BCAST_CHK_MSK(PORT_BASE + 0x2c0)
 #define PHYCTRL_OOB_RESTART_MSK(PORT_BASE + 0x2c4)
 
+/* HW dma structures */
+/* Delivery queue header */
+/* dw0 */
+#define CMD_HDR_RESP_REPORT_OFF5
+#define CMD_HDR_RESP_REPORT_MSK(0x1 << CMD_HDR_RESP_REPORT_OFF)
+#define CMD_HDR_TLR_CTRL_OFF   6
+#define CMD_HDR_TLR_CTRL_MSK   (0x3 << CMD_HDR_TLR_CTRL_OFF)
+#define CMD_HDR_PORT_OFF   18
+#define CMD_HDR_PORT_MSK   (0xf << CMD_HDR_PORT_OFF)
+#define CMD_HDR_PRIORITY_OFF   27
+#define CMD_HDR_PRIORITY_MSK   (0x1 << CMD_HDR_PRIORITY_OFF)
+#define CMD_HDR_CMD_OFF29
+#define CMD_HDR_CMD_MSK(0x7 << CMD_HDR_CMD_OFF)
+/* dw1 */
+#define CMD_HDR_DIR_OFF5
+#define CMD_HDR_DIR_MSK(0x3 << CMD_HDR_DIR_OFF)
+#define CMD_HDR_VDTL_OFF   10
+#define CMD_HDR_VDTL_MSK   (0x1 << CMD_HDR_VDTL_OFF)
+#define CMD_HDR_FRAME_TYPE_OFF 11
+#define CMD_HDR_FRAME_TYPE_MSK (0x1f << CMD_HDR_FRAME_TYPE_OFF)
+#define CMD_HDR_DEV_ID_OFF 16
+#define CMD_HDR_DEV_ID_MSK (0x << CMD_HDR_DEV_ID_OFF)
+/* dw2 */
+#define CMD_HDR_CFL_OFF0
+#define CMD_HDR_CFL_MSK(0x1ff << CMD_HDR_CFL_OFF)
+#define CMD_HDR_MRFL_OFF   15
+#define CMD_HDR_MRFL_MSK   (0x1ff << CMD_HDR_MRFL_OFF)
+#define CMD_HDR_SG_MOD_OFF 24
+#define CMD_HDR_SG_MOD_MSK (0x3 << CMD_HDR_SG_MOD_OFF)
+/* dw6 */
+#define CMD_HDR_DIF_SGL_LEN_OFF0
+#define CMD_HDR_DIF_SGL_LEN_MSK(0x << 
CMD_HDR_DIF_SGL_LEN_OFF)
+#define CMD_HDR_DATA_SGL_LEN_OFF   16
+#define CMD_HDR_DATA_SGL_LEN_MSK   (0x << CMD_HDR_DATA_SGL_LEN_OFF)
+
 /* Completion header */
 /* dw0 */
 #define CMPLT_HDR_CMPLT_OFF0
@@ -201,6 +236,11 @@ enum {
HISI_SAS_PHY_INT_NR
 };
 
+#define DIR_NO_DATA 0
+#define DIR_TO_INI 1
+#define DIR_TO_DEVICE 2
+#define DIR_RESERVED 3
+
 static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off)
 {
void __iomem *regs = hisi_hba->regs + off;
@@ -208,6 +248,13 @@ static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 
off)
return readl(regs);
 }
 
+static u32 hisi_sas_read32_relaxed(struct hisi_hba *hisi_hba, u32 off)
+{
+   void __iomem *regs = hisi_hba->regs + off;
+
+   return readl_relaxed(regs);
+}
+
 static void hisi_sas_write32(struct hisi_hba *hisi_hba, u32 off, u32 val)
 {
void __iomem *regs = hisi_hba->regs + off;
@@ -432,6 +479,163 @@ static void sl_notify_v3_hw(struct hisi_hba *hisi_hba, 
int phy_no)
hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL, sl_control);
 }
 
+/**
+ * The callpath to this function and upto writing the write
+ * queue pointer should be safe from interruption.
+ */
+static int
+get_free_slot_v3_hw(struct hisi_hba *hisi_hba, struct hisi_sas_dq *dq)
+{
+   struct device *dev = hisi_hba->dev;
+   int queue = dq->id;
+   u32 r, w;
+
+   w = dq->wr_point;
+   r = hisi_sas_read32_relaxed(hisi_hba,
+   DLVRY_Q_0_RD_PTR + (queue * 0x14));
+   if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) {
+   dev_warn(dev, "full queue=%d r=%d w=%d\n\n",
+   queue, r, w);
+   return -EAGAIN;
+   }
+
+   return 0;
+}
+
+static void start_delivery_v3_hw(struct hisi_sas_dq *dq)
+{
+   struct hisi_hba *hisi_hba = dq->hisi_hba;
+   int dlvry_queue = dq->slot_prep->dlvry_queue;
+   int dlvry_queue_slot = dq->slot_prep->dlvry_queue_slot;
+
+   dq->wr_point = ++dlvry_queue_slot % HISI_SAS_QUEUE_SLOTS;
+   hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14),
+dq->wr_point);
+}
+
+static int prep_prd_sge_v3_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot,
+ struct hisi_sas_cmd_hdr *hdr,
+ struct scatterlist *scatter,
+ int n_elem)
+{
+   struct device *dev = hisi_hba->dev;
+   struct scatterlist *sg;
+   int i;
+
+   if (n_elem > HISI_SAS_SGE_PAGE_CNT) {
+   dev_err(dev, "prd err: n_elem(%d) > HISI_SAS_SGE_PAGE_CNT",
+   n_elem);
+   

[PATCH v3 16/23] scsi: hisi_sas: add v3 code to send SMP frame

2017-05-31 Thread John Garry
From: Xiang Chen 

Add code to prepare SMP frame.

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 74 ++
 1 file changed, 74 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 7be3a53..d4e4844 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -186,6 +186,9 @@
 #define CMD_HDR_MRFL_MSK   (0x1ff << CMD_HDR_MRFL_OFF)
 #define CMD_HDR_SG_MOD_OFF 24
 #define CMD_HDR_SG_MOD_MSK (0x3 << CMD_HDR_SG_MOD_OFF)
+/* dw3 */
+#define CMD_HDR_IPTT_OFF   0
+#define CMD_HDR_IPTT_MSK   (0x << CMD_HDR_IPTT_OFF)
 /* dw6 */
 #define CMD_HDR_DIF_SGL_LEN_OFF0
 #define CMD_HDR_DIF_SGL_LEN_MSK(0x << 
CMD_HDR_DIF_SGL_LEN_OFF)
@@ -636,6 +639,76 @@ static int prep_ssp_v3_hw(struct hisi_hba *hisi_hba,
return 0;
 }
 
+static int prep_smp_v3_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot)
+{
+   struct sas_task *task = slot->task;
+   struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
+   struct domain_device *device = task->dev;
+   struct device *dev = hisi_hba->dev;
+   struct hisi_sas_port *port = slot->port;
+   struct scatterlist *sg_req, *sg_resp;
+   struct hisi_sas_device *sas_dev = device->lldd_dev;
+   dma_addr_t req_dma_addr;
+   unsigned int req_len, resp_len;
+   int elem, rc;
+
+   /*
+* DMA-map SMP request, response buffers
+*/
+   /* req */
+   sg_req = >smp_task.smp_req;
+   elem = dma_map_sg(dev, sg_req, 1, DMA_TO_DEVICE);
+   if (!elem)
+   return -ENOMEM;
+   req_len = sg_dma_len(sg_req);
+   req_dma_addr = sg_dma_address(sg_req);
+
+   /* resp */
+   sg_resp = >smp_task.smp_resp;
+   elem = dma_map_sg(dev, sg_resp, 1, DMA_FROM_DEVICE);
+   if (!elem) {
+   rc = -ENOMEM;
+   goto err_out_req;
+   }
+   resp_len = sg_dma_len(sg_resp);
+   if ((req_len & 0x3) || (resp_len & 0x3)) {
+   rc = -EINVAL;
+   goto err_out_resp;
+   }
+
+   /* create header */
+   /* dw0 */
+   hdr->dw0 = cpu_to_le32((port->id << CMD_HDR_PORT_OFF) |
+  (1 << CMD_HDR_PRIORITY_OFF) | /* high pri */
+  (2 << CMD_HDR_CMD_OFF)); /* smp */
+
+   /* map itct entry */
+   hdr->dw1 = cpu_to_le32((sas_dev->device_id << CMD_HDR_DEV_ID_OFF) |
+  (1 << CMD_HDR_FRAME_TYPE_OFF) |
+  (DIR_NO_DATA << CMD_HDR_DIR_OFF));
+
+   /* dw2 */
+   hdr->dw2 = cpu_to_le32req_len - 4) / 4) << CMD_HDR_CFL_OFF) |
+  (HISI_SAS_MAX_SMP_RESP_SZ / 4 <<
+  CMD_HDR_MRFL_OFF));
+
+   hdr->transfer_tags = cpu_to_le32(slot->idx << CMD_HDR_IPTT_OFF);
+
+   hdr->cmd_table_addr = cpu_to_le64(req_dma_addr);
+   hdr->sts_buffer_addr = cpu_to_le64(slot->status_buffer_dma);
+
+   return 0;
+
+err_out_resp:
+   dma_unmap_sg(dev, >task->smp_task.smp_resp, 1,
+DMA_FROM_DEVICE);
+err_out_req:
+   dma_unmap_sg(dev, >task->smp_task.smp_req, 1,
+DMA_TO_DEVICE);
+   return rc;
+}
+
 static int phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
 {
int i, res = 0;
@@ -1230,6 +1303,7 @@ static int hisi_sas_v3_init(struct hisi_hba *hisi_hba)
.complete_hdr_size = sizeof(struct hisi_sas_complete_v3_hdr),
.sl_notify = sl_notify_v3_hw,
.prep_ssp = prep_ssp_v3_hw,
+   .prep_smp = prep_smp_v3_hw,
.get_free_slot = get_free_slot_v3_hw,
.start_delivery = start_delivery_v3_hw,
.slot_complete = slot_complete_v3_hw,
-- 
1.9.1



[PATCH v3 11/23] scsi: hisi_sas: add v3 hw init

2017-05-31 Thread John Garry
From: Xiang Chen 

Add code to initialise v3 hardware.

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 277 +
 1 file changed, 277 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 3e74225..da74ed8 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -11,7 +11,283 @@
 #include "hisi_sas.h"
 #define DRV_NAME "hisi_sas_v3_hw"
 
+/* global registers need init*/
+#define DLVRY_QUEUE_ENABLE 0x0
+#define IOST_BASE_ADDR_LO  0x8
+#define IOST_BASE_ADDR_HI  0xc
+#define ITCT_BASE_ADDR_LO  0x10
+#define ITCT_BASE_ADDR_HI  0x14
+#define IO_BROKEN_MSG_ADDR_LO  0x18
+#define IO_BROKEN_MSG_ADDR_HI  0x1c
+#define AXI_AHB_CLK_CFG0x3c
+#define AXI_USER1  0x48
+#define AXI_USER2  0x4c
+#define IO_SATA_BROKEN_MSG_ADDR_LO 0x58
+#define IO_SATA_BROKEN_MSG_ADDR_HI 0x5c
+#define SATA_INITI_D2H_STORE_ADDR_LO   0x60
+#define SATA_INITI_D2H_STORE_ADDR_HI   0x64
+#define CFG_MAX_TAG0x68
+#define HGC_SAS_TX_OPEN_FAIL_RETRY_CTRL0x84
+#define HGC_SAS_TXFAIL_RETRY_CTRL  0x88
+#define HGC_GET_ITV_TIME   0x90
+#define DEVICE_MSG_WORK_MODE   0x94
+#define OPENA_WT_CONTI_TIME0x9c
+#define I_T_NEXUS_LOSS_TIME0xa0
+#define MAX_CON_TIME_LIMIT_TIME0xa4
+#define BUS_INACTIVE_LIMIT_TIME0xa8
+#define REJECT_TO_OPEN_LIMIT_TIME  0xac
+#define CFG_AGING_TIME 0xbc
+#define HGC_DFX_CFG2   0xc0
+#define CFG_ABT_SET_QUERY_IPTT 0xd4
+#define CFG_SET_ABORTED_IPTT_OFF   0
+#define CFG_SET_ABORTED_IPTT_MSK   (0xfff << CFG_SET_ABORTED_IPTT_OFF)
+#define CFG_1US_TIMER_TRSH 0xcc
+#define INT_COAL_EN0x19c
+#define OQ_INT_COAL_TIME   0x1a0
+#define OQ_INT_COAL_CNT0x1a4
+#define ENT_INT_COAL_TIME  0x1a8
+#define ENT_INT_COAL_CNT   0x1ac
+#define OQ_INT_SRC 0x1b0
+#define OQ_INT_SRC_MSK 0x1b4
+#define ENT_INT_SRC1   0x1b8
+#define ENT_INT_SRC1_D2H_FIS_CH0_OFF   0
+#define ENT_INT_SRC1_D2H_FIS_CH0_MSK   (0x1 << ENT_INT_SRC1_D2H_FIS_CH0_OFF)
+#define ENT_INT_SRC1_D2H_FIS_CH1_OFF   8
+#define ENT_INT_SRC1_D2H_FIS_CH1_MSK   (0x1 << ENT_INT_SRC1_D2H_FIS_CH1_OFF)
+#define ENT_INT_SRC2   0x1bc
+#define ENT_INT_SRC3   0x1c0
+#define ENT_INT_SRC3_WP_DEPTH_OFF  8
+#define ENT_INT_SRC3_IPTT_SLOT_NOMATCH_OFF 9
+#define ENT_INT_SRC3_RP_DEPTH_OFF  10
+#define ENT_INT_SRC3_AXI_OFF   11
+#define ENT_INT_SRC3_FIFO_OFF  12
+#define ENT_INT_SRC3_LM_OFF14
+#define ENT_INT_SRC3_ITC_INT_OFF   15
+#define ENT_INT_SRC3_ITC_INT_MSK   (0x1 << ENT_INT_SRC3_ITC_INT_OFF)
+#define ENT_INT_SRC3_ABT_OFF   16
+#define ENT_INT_SRC_MSK1   0x1c4
+#define ENT_INT_SRC_MSK2   0x1c8
+#define ENT_INT_SRC_MSK3   0x1cc
+#define CHNL_PHYUPDOWN_INT_MSK 0x1d0
+#define CHNL_ENT_INT_MSK   0x1d4
+#define HGC_COM_INT_MSK0x1d8
+#define SAS_ECC_INTR   0x1e8
+#define SAS_ECC_INTR_MSK   0x1ec
+#define HGC_ERR_STAT_EN0x238
+#define DLVRY_Q_0_BASE_ADDR_LO 0x260
+#define DLVRY_Q_0_BASE_ADDR_HI 0x264
+#define DLVRY_Q_0_DEPTH0x268
+#define DLVRY_Q_0_WR_PTR   0x26c
+#define DLVRY_Q_0_RD_PTR   0x270
+#define HYPER_STREAM_ID_EN_CFG 0xc80
+#define OQ0_INT_SRC_MSK0xc90
+#define COMPL_Q_0_BASE_ADDR_LO 0x4e0
+#define COMPL_Q_0_BASE_ADDR_HI 0x4e4
+#define COMPL_Q_0_DEPTH0x4e8
+#define COMPL_Q_0_WR_PTR   0x4ec
+#define COMPL_Q_0_RD_PTR   0x4f0
+#define AWQOS_AWCACHE_CFG  0xc84
+#define ARQOS_ARCACHE_CFG  0xc88
+
+/* phy registers requiring init */
+#define PORT_BASE  (0x2000)
+#define PROG_PHY_LINK_RATE (PORT_BASE + 0x8)
+#define PHY_CTRL   (PORT_BASE + 0x14)
+#define PHY_CTRL_RESET_OFF 0
+#define PHY_CTRL_RESET_MSK (0x1 << PHY_CTRL_RESET_OFF)
+#define SL_CFG (PORT_BASE + 0x84)
+#define RXOP_CHECK_CFG_H   (PORT_BASE + 0xfc)
+#define SAS_SSP_CON_TIMER_CFG  (PORT_BASE + 0x134)
+#define SAS_SMP_CON_TIMER_CFG  (PORT_BASE + 0x138)
+#define SAS_STP_CON_TIMER_CFG  (PORT_BASE + 0x13c)
+#define CHL_INT0   (PORT_BASE + 0x1b4)
+#define 

[PATCH v3 10/23] scsi: hisi_sas: add initialisation for v3 pci-based controller

2017-05-31 Thread John Garry
Add the code to initialise the controller which is based on pci
device in hisi_sas_v3_hw.c

The core controller routines are still in hisi_sas_main.c; some
common initialisation functions are also exported from
hisi_sas_main.c

For pci-based controller, the device properties, like
phy count and sas address are read from the firmware,
same as platform device-based controller.

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |   6 ++
 drivers/scsi/hisi_sas/hisi_sas_main.c  |  18 ++--
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 155 +
 3 files changed, 173 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 480f9ae..5fe5a55 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -360,6 +360,12 @@ struct hisi_sas_command_table_ssp {
struct hisi_sas_command_table_stp stp;
 };
 
+extern struct scsi_transport_template *hisi_sas_stt;
+extern struct scsi_host_template *hisi_sas_sht;
+
+extern void hisi_sas_init_add(struct hisi_hba *hisi_hba);
+extern int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost);
+extern void hisi_sas_free(struct hisi_hba *hisi_hba);
 extern u8 hisi_sas_get_ata_protocol(u8 cmd, int direction);
 extern struct hisi_sas_port *to_hisi_sas_port(struct asd_sas_port *sas_port);
 extern void hisi_sas_sata_done(struct sas_task *task,
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 5979ab6..f5a73bd 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -1478,9 +1478,10 @@ void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, 
u32 old_state,
 }
 EXPORT_SYMBOL_GPL(hisi_sas_rescan_topology);
 
-static struct scsi_transport_template *hisi_sas_stt;
+struct scsi_transport_template *hisi_sas_stt;
+EXPORT_SYMBOL_GPL(hisi_sas_stt);
 
-static struct scsi_host_template hisi_sas_sht = {
+static struct scsi_host_template _hisi_sas_sht = {
.module = THIS_MODULE,
.name   = DRV_NAME,
.queuecommand   = sas_queuecommand,
@@ -1500,6 +1501,8 @@ void hisi_sas_rescan_topology(struct hisi_hba *hisi_hba, 
u32 old_state,
.target_destroy = sas_target_destroy,
.ioctl  = sas_ioctl,
 };
+struct scsi_host_template *hisi_sas_sht = &_hisi_sas_sht;
+EXPORT_SYMBOL_GPL(hisi_sas_sht);
 
 static struct sas_domain_function_template hisi_sas_transport_ops = {
.lldd_dev_found = hisi_sas_dev_found,
@@ -1547,7 +1550,7 @@ void hisi_sas_init_mem(struct hisi_hba *hisi_hba)
 }
 EXPORT_SYMBOL_GPL(hisi_sas_init_mem);
 
-static int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost)
+int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost)
 {
struct device *dev = hisi_hba->dev;
int i, s, max_command_entries = hisi_hba->hw->max_command_entries;
@@ -1666,8 +1669,9 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, 
struct Scsi_Host *shost)
 err_out:
return -ENOMEM;
 }
+EXPORT_SYMBOL_GPL(hisi_sas_alloc);
 
-static void hisi_sas_free(struct hisi_hba *hisi_hba)
+void hisi_sas_free(struct hisi_hba *hisi_hba)
 {
struct device *dev = hisi_hba->dev;
int i, s, max_command_entries = hisi_hba->hw->max_command_entries;
@@ -1722,6 +1726,7 @@ static void hisi_sas_free(struct hisi_hba *hisi_hba)
if (hisi_hba->wq)
destroy_workqueue(hisi_hba->wq);
 }
+EXPORT_SYMBOL_GPL(hisi_sas_free);
 
 static void hisi_sas_rst_work_handler(struct work_struct *work)
 {
@@ -1807,7 +1812,7 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct 
platform_device *pdev,
struct hisi_hba *hisi_hba;
struct device *dev = >dev;
 
-   shost = scsi_host_alloc(_sas_sht, sizeof(*hisi_hba));
+   shost = scsi_host_alloc(hisi_sas_sht, sizeof(*hisi_hba));
if (!shost) {
dev_err(dev, "scsi host alloc failed\n");
return NULL;
@@ -1849,7 +1854,7 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct 
platform_device *pdev,
return NULL;
 }
 
-static void hisi_sas_init_add(struct hisi_hba *hisi_hba)
+void hisi_sas_init_add(struct hisi_hba *hisi_hba)
 {
int i;
 
@@ -1858,6 +1863,7 @@ static void hisi_sas_init_add(struct hisi_hba *hisi_hba)
   hisi_hba->sas_addr,
   SAS_ADDR_SIZE);
 }
+EXPORT_SYMBOL_GPL(hisi_sas_init_add);
 
 int hisi_sas_probe(struct platform_device *pdev,
 const struct hisi_sas_hw *hw)
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index cf72577..3e74225 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -11,14 +11,169 @@
 #include "hisi_sas.h"
 #define DRV_NAME "hisi_sas_v3_hw"
 
+static const 

[PATCH v3 17/23] scsi: hisi_sas: add v3 code to send ATA frame

2017-05-31 Thread John Garry
From: Xiang Chen 

Add code to prepare ATA frame for v3 hw

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 106 +
 1 file changed, 106 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index d4e4844..613c625 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -171,8 +171,11 @@
 #define CMD_HDR_CMD_OFF29
 #define CMD_HDR_CMD_MSK(0x7 << CMD_HDR_CMD_OFF)
 /* dw1 */
+#define CMD_HDR_UNCON_CMD_OFF  3
 #define CMD_HDR_DIR_OFF5
 #define CMD_HDR_DIR_MSK(0x3 << CMD_HDR_DIR_OFF)
+#define CMD_HDR_RESET_OFF  7
+#define CMD_HDR_RESET_MSK  (0x1 << CMD_HDR_RESET_OFF)
 #define CMD_HDR_VDTL_OFF   10
 #define CMD_HDR_VDTL_MSK   (0x1 << CMD_HDR_VDTL_OFF)
 #define CMD_HDR_FRAME_TYPE_OFF 11
@@ -182,6 +185,8 @@
 /* dw2 */
 #define CMD_HDR_CFL_OFF0
 #define CMD_HDR_CFL_MSK(0x1ff << CMD_HDR_CFL_OFF)
+#define CMD_HDR_NCQ_TAG_OFF10
+#define CMD_HDR_NCQ_TAG_MSK(0x1f << CMD_HDR_NCQ_TAG_OFF)
 #define CMD_HDR_MRFL_OFF   15
 #define CMD_HDR_MRFL_MSK   (0x1ff << CMD_HDR_MRFL_OFF)
 #define CMD_HDR_SG_MOD_OFF 24
@@ -244,6 +249,11 @@ enum {
 #define DIR_TO_DEVICE 2
 #define DIR_RESERVED 3
 
+#define CMD_IS_UNCONSTRAINT(cmd) \
+   ((cmd == ATA_CMD_READ_LOG_EXT) || \
+   (cmd == ATA_CMD_READ_LOG_DMA_EXT) || \
+   (cmd == ATA_CMD_DEV_RESET))
+
 static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off)
 {
void __iomem *regs = hisi_hba->regs + off;
@@ -709,6 +719,101 @@ static int prep_smp_v3_hw(struct hisi_hba *hisi_hba,
return rc;
 }
 
+static int get_ncq_tag_v3_hw(struct sas_task *task, u32 *tag)
+{
+   struct ata_queued_cmd *qc = task->uldd_task;
+
+   if (qc) {
+   if (qc->tf.command == ATA_CMD_FPDMA_WRITE ||
+   qc->tf.command == ATA_CMD_FPDMA_READ) {
+   *tag = qc->tag;
+   return 1;
+   }
+   }
+   return 0;
+}
+
+static int prep_ata_v3_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot)
+{
+   struct sas_task *task = slot->task;
+   struct domain_device *device = task->dev;
+   struct domain_device *parent_dev = device->parent;
+   struct hisi_sas_device *sas_dev = device->lldd_dev;
+   struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
+   struct asd_sas_port *sas_port = device->port;
+   struct hisi_sas_port *port = to_hisi_sas_port(sas_port);
+   u8 *buf_cmd;
+   int has_data = 0, rc = 0, hdr_tag = 0;
+   u32 dw1 = 0, dw2 = 0;
+
+   hdr->dw0 = cpu_to_le32(port->id << CMD_HDR_PORT_OFF);
+   if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type))
+   hdr->dw0 |= cpu_to_le32(3 << CMD_HDR_CMD_OFF);
+   else
+   hdr->dw0 |= cpu_to_le32(4 << CMD_HDR_CMD_OFF);
+
+   switch (task->data_dir) {
+   case DMA_TO_DEVICE:
+   has_data = 1;
+   dw1 |= DIR_TO_DEVICE << CMD_HDR_DIR_OFF;
+   break;
+   case DMA_FROM_DEVICE:
+   has_data = 1;
+   dw1 |= DIR_TO_INI << CMD_HDR_DIR_OFF;
+   break;
+   default:
+   dw1 &= ~CMD_HDR_DIR_MSK;
+   }
+
+   if ((task->ata_task.fis.command == ATA_CMD_DEV_RESET) &&
+   (task->ata_task.fis.control & ATA_SRST))
+   dw1 |= 1 << CMD_HDR_RESET_OFF;
+
+   dw1 |= (hisi_sas_get_ata_protocol(
+   task->ata_task.fis.command, task->data_dir))
+   << CMD_HDR_FRAME_TYPE_OFF;
+   dw1 |= sas_dev->device_id << CMD_HDR_DEV_ID_OFF;
+
+   if (CMD_IS_UNCONSTRAINT(task->ata_task.fis.command))
+   dw1 |= 1 << CMD_HDR_UNCON_CMD_OFF;
+
+   hdr->dw1 = cpu_to_le32(dw1);
+
+   /* dw2 */
+   if (task->ata_task.use_ncq && get_ncq_tag_v3_hw(task, _tag)) {
+   task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3);
+   dw2 |= hdr_tag << CMD_HDR_NCQ_TAG_OFF;
+   }
+
+   dw2 |= (HISI_SAS_MAX_STP_RESP_SZ / 4) << CMD_HDR_CFL_OFF |
+   2 << CMD_HDR_SG_MOD_OFF;
+   hdr->dw2 = cpu_to_le32(dw2);
+
+   /* dw3 */
+   hdr->transfer_tags = cpu_to_le32(slot->idx);
+
+   if (has_data) {
+   rc = prep_prd_sge_v3_hw(hisi_hba, slot, hdr, task->scatter,
+   slot->n_elem);
+   if (rc)
+   return rc;
+   }
+
+   hdr->data_transfer_len = cpu_to_le32(task->total_xfer_len);
+   hdr->cmd_table_addr = cpu_to_le64(slot->command_table_dma);
+   

[PATCH v3 13/23] scsi: hisi_sas: add phy up/down/bcast and channel ISR

2017-05-31 Thread John Garry
From: Xiang Chen 

Add code to initialise interrupts and add some interrupt handlers.

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 281 +
 1 file changed, 281 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 9651658..49f14d2 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -173,6 +173,13 @@ enum {
HISI_SAS_PHY_INT_NR
 };
 
+static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off)
+{
+   void __iomem *regs = hisi_hba->regs + off;
+
+   return readl(regs);
+}
+
 static void hisi_sas_write32(struct hisi_hba *hisi_hba, u32 off, u32 val)
 {
void __iomem *regs = hisi_hba->regs + off;
@@ -397,6 +404,276 @@ static void sl_notify_v3_hw(struct hisi_hba *hisi_hba, 
int phy_no)
hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL, sl_control);
 }
 
+static int phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
+{
+   int i, res = 0;
+   u32 context, port_id, link_rate, hard_phy_linkrate;
+   struct hisi_sas_phy *phy = _hba->phy[phy_no];
+   struct asd_sas_phy *sas_phy = >sas_phy;
+   struct device *dev = hisi_hba->dev;
+
+   hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 1);
+
+   port_id = hisi_sas_read32(hisi_hba, PHY_PORT_NUM_MA);
+   port_id = (port_id >> (4 * phy_no)) & 0xf;
+   link_rate = hisi_sas_read32(hisi_hba, PHY_CONN_RATE);
+   link_rate = (link_rate >> (phy_no * 4)) & 0xf;
+
+   if (port_id == 0xf) {
+   dev_err(dev, "phyup: phy%d invalid portid\n", phy_no);
+   res = IRQ_NONE;
+   goto end;
+   }
+   sas_phy->linkrate = link_rate;
+   hard_phy_linkrate = hisi_sas_phy_read32(hisi_hba, phy_no,
+   HARD_PHY_LINKRATE);
+   phy->maximum_linkrate = hard_phy_linkrate & 0xf;
+   phy->minimum_linkrate = (hard_phy_linkrate >> 4) & 0xf;
+   phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA);
+
+   /* Check for SATA dev */
+   context = hisi_sas_read32(hisi_hba, PHY_CONTEXT);
+   if (context & (1 << phy_no)) {
+   struct hisi_sas_initial_fis *initial_fis;
+   struct dev_to_host_fis *fis;
+   u8 attached_sas_addr[SAS_ADDR_SIZE] = {0};
+
+   dev_info(dev, "phyup: phy%d link_rate=%d\n", phy_no, link_rate);
+   initial_fis = _hba->initial_fis[phy_no];
+   fis = _fis->fis;
+   sas_phy->oob_mode = SATA_OOB_MODE;
+   attached_sas_addr[0] = 0x50;
+   attached_sas_addr[7] = phy_no;
+   memcpy(sas_phy->attached_sas_addr,
+  attached_sas_addr,
+  SAS_ADDR_SIZE);
+   memcpy(sas_phy->frame_rcvd, fis,
+  sizeof(struct dev_to_host_fis));
+   phy->phy_type |= PORT_TYPE_SATA;
+   phy->identify.device_type = SAS_SATA_DEV;
+   phy->frame_rcvd_size = sizeof(struct dev_to_host_fis);
+   phy->identify.target_port_protocols = SAS_PROTOCOL_SATA;
+   } else {
+   u32 *frame_rcvd = (u32 *)sas_phy->frame_rcvd;
+   struct sas_identify_frame *id =
+   (struct sas_identify_frame *)frame_rcvd;
+
+   dev_info(dev, "phyup: phy%d link_rate=%d\n", phy_no, link_rate);
+   for (i = 0; i < 6; i++) {
+   u32 idaf = hisi_sas_phy_read32(hisi_hba, phy_no,
+  RX_IDAF_DWORD0 + (i * 4));
+   frame_rcvd[i] = __swab32(idaf);
+   }
+   sas_phy->oob_mode = SAS_OOB_MODE;
+   memcpy(sas_phy->attached_sas_addr,
+  >sas_addr,
+  SAS_ADDR_SIZE);
+   phy->phy_type |= PORT_TYPE_SAS;
+   phy->identify.device_type = id->dev_type;
+   phy->frame_rcvd_size = sizeof(struct sas_identify_frame);
+   if (phy->identify.device_type == SAS_END_DEVICE)
+   phy->identify.target_port_protocols =
+   SAS_PROTOCOL_SSP;
+   else if (phy->identify.device_type != SAS_PHY_UNUSED)
+   phy->identify.target_port_protocols =
+   SAS_PROTOCOL_SMP;
+   }
+
+   phy->port_id = port_id;
+   phy->phy_attached = 1;
+   queue_work(hisi_hba->wq, >phyup_ws);
+
+end:
+   hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
+CHL_INT0_SL_PHY_ENABLE_MSK);
+   hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 0);
+
+   return res;
+}
+
+static int phy_down_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
+{
+   int res = 0;
+   u32 phy_state, 

[PATCH v3 12/23] scsi: hisi_sas: add v3 hw PHY init

2017-05-31 Thread John Garry
From: Xiang Chen 

Add code to configure PHYs for v3 hw.

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 127 -
 1 file changed, 126 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index da74ed8..9651658 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -19,6 +19,10 @@
 #define ITCT_BASE_ADDR_HI  0x14
 #define IO_BROKEN_MSG_ADDR_LO  0x18
 #define IO_BROKEN_MSG_ADDR_HI  0x1c
+#define PHY_CONTEXT0x20
+#define PHY_STATE  0x24
+#define PHY_PORT_NUM_MA0x28
+#define PHY_CONN_RATE  0x30
 #define AXI_AHB_CLK_CFG0x3c
 #define AXI_USER1  0x48
 #define AXI_USER2  0x4c
@@ -42,6 +46,7 @@
 #define CFG_SET_ABORTED_IPTT_OFF   0
 #define CFG_SET_ABORTED_IPTT_MSK   (0xfff << CFG_SET_ABORTED_IPTT_OFF)
 #define CFG_1US_TIMER_TRSH 0xcc
+#define CHNL_INT_STATUS0x148
 #define INT_COAL_EN0x19c
 #define OQ_INT_COAL_TIME   0x1a0
 #define OQ_INT_COAL_CNT0x1a4
@@ -68,9 +73,11 @@
 #define ENT_INT_SRC_MSK1   0x1c4
 #define ENT_INT_SRC_MSK2   0x1c8
 #define ENT_INT_SRC_MSK3   0x1cc
+#define ENT_INT_SRC_MSK3_ENT95_MSK_OFF 31
 #define CHNL_PHYUPDOWN_INT_MSK 0x1d0
 #define CHNL_ENT_INT_MSK   0x1d4
 #define HGC_COM_INT_MSK0x1d8
+#define ENT_INT_SRC_MSK3_ENT95_MSK_MSK (0x1 << ENT_INT_SRC_MSK3_ENT95_MSK_OFF)
 #define SAS_ECC_INTR   0x1e8
 #define SAS_ECC_INTR_MSK   0x1ec
 #define HGC_ERR_STAT_EN0x238
@@ -91,11 +98,33 @@
 
 /* phy registers requiring init */
 #define PORT_BASE  (0x2000)
+#define PHY_CFG(PORT_BASE + 0x0)
+#define HARD_PHY_LINKRATE  (PORT_BASE + 0x4)
+#define PHY_CFG_ENA_OFF0
+#define PHY_CFG_ENA_MSK(0x1 << PHY_CFG_ENA_OFF)
+#define PHY_CFG_DC_OPT_OFF 2
+#define PHY_CFG_DC_OPT_MSK (0x1 << PHY_CFG_DC_OPT_OFF)
 #define PROG_PHY_LINK_RATE (PORT_BASE + 0x8)
 #define PHY_CTRL   (PORT_BASE + 0x14)
 #define PHY_CTRL_RESET_OFF 0
 #define PHY_CTRL_RESET_MSK (0x1 << PHY_CTRL_RESET_OFF)
 #define SL_CFG (PORT_BASE + 0x84)
+#define SL_CONTROL (PORT_BASE + 0x94)
+#define SL_CONTROL_NOTIFY_EN_OFF   0
+#define SL_CONTROL_NOTIFY_EN_MSK   (0x1 << SL_CONTROL_NOTIFY_EN_OFF)
+#define SL_CTA_OFF 17
+#define SL_CTA_MSK (0x1 << SL_CTA_OFF)
+#define TX_ID_DWORD0   (PORT_BASE + 0x9c)
+#define TX_ID_DWORD1   (PORT_BASE + 0xa0)
+#define TX_ID_DWORD2   (PORT_BASE + 0xa4)
+#define TX_ID_DWORD3   (PORT_BASE + 0xa8)
+#define TX_ID_DWORD4   (PORT_BASE + 0xaC)
+#define TX_ID_DWORD5   (PORT_BASE + 0xb0)
+#define TX_ID_DWORD6   (PORT_BASE + 0xb4)
+#define TXID_AUTO  (PORT_BASE + 0xb8)
+#define CT3_OFF1
+#define CT3_MSK(0x1 << CT3_OFF)
+#define RX_IDAF_DWORD0 (PORT_BASE + 0xc4)
 #define RXOP_CHECK_CFG_H   (PORT_BASE + 0xfc)
 #define SAS_SSP_CON_TIMER_CFG  (PORT_BASE + 0x134)
 #define SAS_SMP_CON_TIMER_CFG  (PORT_BASE + 0x138)
@@ -136,6 +165,13 @@ struct hisi_sas_complete_v3_hdr {
 };
 
 #define HISI_SAS_COMMAND_ENTRIES_V3_HW 4096
+#define HISI_SAS_MSI_COUNT_V3_HW 32
+
+enum {
+   HISI_SAS_PHY_PHY_UPDOWN,
+   HISI_SAS_PHY_CHNL_INT,
+   HISI_SAS_PHY_INT_NR
+};
 
 static void hisi_sas_write32(struct hisi_hba *hisi_hba, u32 off, u32 val)
 {
@@ -152,6 +188,14 @@ static void hisi_sas_phy_write32(struct hisi_hba 
*hisi_hba, int phy_no,
writel(val, regs);
 }
 
+static u32 hisi_sas_phy_read32(struct hisi_hba *hisi_hba,
+ int phy_no, u32 off)
+{
+   void __iomem *regs = hisi_hba->regs + (0x400 * phy_no) + off;
+
+   return readl(regs);
+}
+
 static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
 {
int i;
@@ -266,6 +310,45 @@ static void init_reg_v3_hw(struct hisi_hba *hisi_hba)
 upper_32_bits(hisi_hba->initial_fis_dma));
 }
 
+static void config_phy_opt_mode_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
+{
+   u32 cfg = hisi_sas_phy_read32(hisi_hba, phy_no, PHY_CFG);
+
+   cfg &= ~PHY_CFG_DC_OPT_MSK;
+   cfg |= 1 << PHY_CFG_DC_OPT_OFF;
+   hisi_sas_phy_write32(hisi_hba, phy_no, PHY_CFG, cfg);
+}
+

[PATCH v3 20/23] scsi: hisi_sas: add get_wideport_bitmap_v3_hw()

2017-05-31 Thread John Garry
From: Xiang Chen 

Add code for interface get_wideport_bitmap.

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 14 ++
 1 file changed, 14 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 7bb9d2a..f71f1ba 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -613,6 +613,18 @@ static void sl_notify_v3_hw(struct hisi_hba *hisi_hba, int 
phy_no)
hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL, sl_control);
 }
 
+static int get_wideport_bitmap_v3_hw(struct hisi_hba *hisi_hba, int port_id)
+{
+   int i, bitmap = 0;
+   u32 phy_port_num_ma = hisi_sas_read32(hisi_hba, PHY_PORT_NUM_MA);
+
+   for (i = 0; i < hisi_hba->n_phy; i++)
+   if (((phy_port_num_ma >> (i * 4)) & 0xf) == port_id)
+   bitmap |= 1 << i;
+
+   return bitmap;
+}
+
 /**
  * The callpath to this function and upto writing the write
  * queue pointer should be safe from interruption.
@@ -1555,6 +1567,7 @@ static int hisi_sas_v3_init(struct hisi_hba *hisi_hba)
.hw_init = hisi_sas_v3_init,
.setup_itct = setup_itct_v3_hw,
.max_command_entries = HISI_SAS_COMMAND_ENTRIES_V3_HW,
+   .get_wideport_bitmap = get_wideport_bitmap_v3_hw,
.complete_hdr_size = sizeof(struct hisi_sas_complete_v3_hdr),
.free_device = free_device_v3_hw,
.sl_notify = sl_notify_v3_hw,
@@ -1730,6 +1743,7 @@ static void hisi_sas_v3_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
 }
 
+
 enum {
/* instances of the controller */
hip08,
-- 
1.9.1



[PATCH v3 14/23] scsi: hisi_sas: add v3 cq interrupt handler

2017-05-31 Thread John Garry
From: Xiang Chen 

Add v3 cq interrupt handler slot_complete_v2_hw().

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |   1 +
 drivers/scsi/hisi_sas/hisi_sas_main.c  |  32 
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 331 +
 3 files changed, 364 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 5fe5a55..d7545ff 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -372,6 +372,7 @@ extern void hisi_sas_sata_done(struct sas_task *task,
struct hisi_sas_slot *slot);
 extern int hisi_sas_get_ncq_tag(struct sas_task *task, u32 *tag);
 extern int hisi_sas_get_fw_info(struct hisi_hba *hisi_hba);
+extern bool hisi_sas_is_rw_cmd(struct sas_task *task);
 extern int hisi_sas_probe(struct platform_device *pdev,
  const struct hisi_sas_hw *ops);
 extern int hisi_sas_remove(struct platform_device *pdev);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index f5a73bd..b90eb50 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -118,6 +118,38 @@ int hisi_sas_get_ncq_tag(struct sas_task *task, u32 *tag)
 }
 EXPORT_SYMBOL_GPL(hisi_sas_get_ncq_tag);
 
+bool hisi_sas_is_rw_cmd(struct sas_task *task)
+{
+   switch (task->task_proto) {
+   case SAS_PROTOCOL_SSP:
+   {
+   unsigned char op = task->ssp_task.cmd->cmnd[0];
+
+   if (op == READ_6 || op == WRITE_6 ||
+   op == READ_10 || op == WRITE_10 ||
+   op == READ_12 || op == WRITE_12 ||
+   op == READ_16 || op == WRITE_16)
+   return true;
+   break;
+   }
+   case SAS_PROTOCOL_SATA:
+   case SAS_PROTOCOL_STP:
+   case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
+   {
+   u32 cmd_proto = hisi_sas_get_ata_protocol(
+   task->ata_task.fis.command,
+   task->data_dir);
+   if (cmd_proto != SATA_PROTOCOL_NONDATA)
+   return true;
+   break;
+   }
+   default:
+   break;
+   }
+   return false;
+}
+EXPORT_SYMBOL_GPL(hisi_sas_is_rw_cmd);
+
 static struct hisi_hba *dev_to_hisi_hba(struct domain_device *device)
 {
return device->port->ha->lldd_ha;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 49f14d2..4259047 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -157,6 +157,32 @@
 #define SL_RX_BCAST_CHK_MSK(PORT_BASE + 0x2c0)
 #define PHYCTRL_OOB_RESTART_MSK(PORT_BASE + 0x2c4)
 
+/* Completion header */
+/* dw0 */
+#define CMPLT_HDR_CMPLT_OFF0
+#define CMPLT_HDR_CMPLT_MSK(0x3 << CMPLT_HDR_CMPLT_OFF)
+#define CMPLT_HDR_ERROR_PHASE_OFF   2
+#define CMPLT_HDR_ERROR_PHASE_MSK   (0xff << CMPLT_HDR_ERROR_PHASE_OFF)
+#define CMPLT_HDR_RSPNS_XFRD_OFF   10
+#define CMPLT_HDR_RSPNS_XFRD_MSK   (0x1 << CMPLT_HDR_RSPNS_XFRD_OFF)
+#define CMPLT_HDR_ERX_OFF  12
+#define CMPLT_HDR_ERX_MSK  (0x1 << CMPLT_HDR_ERX_OFF)
+#define CMPLT_HDR_ABORT_STAT_OFF   13
+#define CMPLT_HDR_ABORT_STAT_MSK   (0x7 << CMPLT_HDR_ABORT_STAT_OFF)
+/* abort_stat */
+#define STAT_IO_NOT_VALID  0x1
+#define STAT_IO_NO_DEVICE  0x2
+#define STAT_IO_COMPLETE   0x3
+#define STAT_IO_ABORTED0x4
+/* dw1 */
+#define CMPLT_HDR_IPTT_OFF 0
+#define CMPLT_HDR_IPTT_MSK (0x << CMPLT_HDR_IPTT_OFF)
+#define CMPLT_HDR_DEV_ID_OFF   16
+#define CMPLT_HDR_DEV_ID_MSK   (0x << CMPLT_HDR_DEV_ID_OFF)
+/* dw3 */
+#define CMPLT_HDR_IO_IN_TARGET_OFF 17
+#define CMPLT_HDR_IO_IN_TARGET_MSK (0x1 << CMPLT_HDR_IO_IN_TARGET_OFF)
+
 struct hisi_sas_complete_v3_hdr {
__le32 dw0;
__le32 dw1;
@@ -164,6 +190,8 @@ struct hisi_sas_complete_v3_hdr {
__le32 dw3;
 };
 
+#define IO_RX_DATA_LEN_UNDERFLOW_OFF   6
+#define IO_RX_DATA_LEN_UNDERFLOW_MSK   (1 << IO_RX_DATA_LEN_UNDERFLOW_OFF)
 #define HISI_SAS_COMMAND_ENTRIES_V3_HW 4096
 #define HISI_SAS_MSI_COUNT_V3_HW 32
 
@@ -625,6 +653,286 @@ static irqreturn_t int_chnl_int_v3_hw(int irq_no, void *p)
return IRQ_HANDLED;
 }
 
+static void slot_err_v3_hw(struct hisi_hba *hisi_hba,
+   struct sas_task *task,
+   struct hisi_sas_slot *slot)
+{
+   struct task_status_struct *ts = >task_status;
+   struct hisi_sas_complete_v3_hdr *complete_queue =
+   hisi_hba->complete_hdr[slot->cmplt_queue];
+   struct hisi_sas_complete_v3_hdr *complete_hdr 

[PATCH v3 19/23] scsi: hisi_sas: add v3 code to send internal abort command

2017-05-31 Thread John Garry
From: Xiang Chen 

Add code to prepare internal abort command.

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 38 ++
 1 file changed, 38 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 720abd1c..7bb9d2a 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -165,6 +165,10 @@
 /* HW dma structures */
 /* Delivery queue header */
 /* dw0 */
+#define CMD_HDR_ABORT_FLAG_OFF 0
+#define CMD_HDR_ABORT_FLAG_MSK (0x3 << CMD_HDR_ABORT_FLAG_OFF)
+#define CMD_HDR_ABORT_DEVICE_TYPE_OFF  2
+#define CMD_HDR_ABORT_DEVICE_TYPE_MSK  (0x1 << CMD_HDR_ABORT_DEVICE_TYPE_OFF)
 #define CMD_HDR_RESP_REPORT_OFF5
 #define CMD_HDR_RESP_REPORT_MSK(0x1 << CMD_HDR_RESP_REPORT_OFF)
 #define CMD_HDR_TLR_CTRL_OFF   6
@@ -204,6 +208,11 @@
 #define CMD_HDR_DIF_SGL_LEN_MSK(0x << 
CMD_HDR_DIF_SGL_LEN_OFF)
 #define CMD_HDR_DATA_SGL_LEN_OFF   16
 #define CMD_HDR_DATA_SGL_LEN_MSK   (0x << CMD_HDR_DATA_SGL_LEN_OFF)
+/* dw7 */
+#define CMD_HDR_ADDR_MODE_SEL_OFF  15
+#define CMD_HDR_ADDR_MODE_SEL_MSK  (1 << CMD_HDR_ADDR_MODE_SEL_OFF)
+#define CMD_HDR_ABORT_IPTT_OFF 16
+#define CMD_HDR_ABORT_IPTT_MSK (0x << CMD_HDR_ABORT_IPTT_OFF)
 
 /* Completion header */
 /* dw0 */
@@ -926,6 +935,34 @@ static int prep_ata_v3_hw(struct hisi_hba *hisi_hba,
return 0;
 }
 
+static int prep_abort_v3_hw(struct hisi_hba *hisi_hba,
+   struct hisi_sas_slot *slot,
+   int device_id, int abort_flag, int tag_to_abort)
+{
+   struct sas_task *task = slot->task;
+   struct domain_device *dev = task->dev;
+   struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
+   struct hisi_sas_port *port = slot->port;
+
+   /* dw0 */
+   hdr->dw0 = cpu_to_le32((5 << CMD_HDR_CMD_OFF) | /*abort*/
+  (port->id << CMD_HDR_PORT_OFF) |
+  ((dev_is_sata(dev) ? 1:0)
+   << CMD_HDR_ABORT_DEVICE_TYPE_OFF) |
+   (abort_flag
+<< CMD_HDR_ABORT_FLAG_OFF));
+
+   /* dw1 */
+   hdr->dw1 = cpu_to_le32(device_id
+   << CMD_HDR_DEV_ID_OFF);
+
+   /* dw7 */
+   hdr->dw7 = cpu_to_le32(tag_to_abort << CMD_HDR_ABORT_IPTT_OFF);
+   hdr->transfer_tags = cpu_to_le32(slot->idx);
+
+   return 0;
+}
+
 static int phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba)
 {
int i, res = 0;
@@ -1524,6 +1561,7 @@ static int hisi_sas_v3_init(struct hisi_hba *hisi_hba)
.prep_ssp = prep_ssp_v3_hw,
.prep_smp = prep_smp_v3_hw,
.prep_stp = prep_ata_v3_hw,
+   .prep_abort = prep_abort_v3_hw,
.get_free_slot = get_free_slot_v3_hw,
.start_delivery = start_delivery_v3_hw,
.slot_complete = slot_complete_v3_hw,
-- 
1.9.1



[PATCH v3 22/23] scsi: hisi_sas: add v3 code to fill some more hw function pointers

2017-05-31 Thread John Garry
From: Xiang Chen 

Add code to fill the interface of phy_hard_reset, phy_get_max_linkrate,
and phy enable/disable.

Signed-off-by: John Garry 
Signed-off-by: Xiang Chen 
---
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 40 +-
 1 file changed, 39 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
index 3203221..17f9ac9 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c
@@ -195,6 +195,8 @@
 #define TXID_AUTO  (PORT_BASE + 0xb8)
 #define CT3_OFF1
 #define CT3_MSK(0x1 << CT3_OFF)
+#define TX_HARDRST_OFF  2
+#define TX_HARDRST_MSK  (0x1 << TX_HARDRST_OFF)
 #define RX_IDAF_DWORD0 (PORT_BASE + 0xc4)
 #define RXOP_CHECK_CFG_H   (PORT_BASE + 0xfc)
 #define SAS_SSP_CON_TIMER_CFG  (PORT_BASE + 0x134)
@@ -648,6 +650,14 @@ static void enable_phy_v3_hw(struct hisi_hba *hisi_hba, 
int phy_no)
hisi_sas_phy_write32(hisi_hba, phy_no, PHY_CFG, cfg);
 }
 
+static void disable_phy_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
+{
+   u32 cfg = hisi_sas_phy_read32(hisi_hba, phy_no, PHY_CFG);
+
+   cfg &= ~PHY_CFG_ENA_MSK;
+   hisi_sas_phy_write32(hisi_hba, phy_no, PHY_CFG, cfg);
+}
+
 static void start_phy_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
 {
config_id_frame_v3_hw(hisi_hba, phy_no);
@@ -655,6 +665,11 @@ static void start_phy_v3_hw(struct hisi_hba *hisi_hba, int 
phy_no)
enable_phy_v3_hw(hisi_hba, phy_no);
 }
 
+static void stop_phy_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
+{
+   disable_phy_v3_hw(hisi_hba, phy_no);
+}
+
 static void start_phys_v3_hw(struct hisi_hba *hisi_hba)
 {
int i;
@@ -663,6 +678,26 @@ static void start_phys_v3_hw(struct hisi_hba *hisi_hba)
start_phy_v3_hw(hisi_hba, i);
 }
 
+static void phy_hard_reset_v3_hw(struct hisi_hba *hisi_hba, int phy_no)
+{
+   struct hisi_sas_phy *phy = _hba->phy[phy_no];
+   u32 txid_auto;
+
+   stop_phy_v3_hw(hisi_hba, phy_no);
+   if (phy->identify.device_type == SAS_END_DEVICE) {
+   txid_auto = hisi_sas_phy_read32(hisi_hba, phy_no, TXID_AUTO);
+   hisi_sas_phy_write32(hisi_hba, phy_no, TXID_AUTO,
+   txid_auto | TX_HARDRST_MSK);
+   }
+   msleep(100);
+   start_phy_v3_hw(hisi_hba, phy_no);
+}
+
+enum sas_linkrate phy_get_max_linkrate_v3_hw(void)
+{
+   return SAS_LINK_RATE_12_0_GBPS;
+}
+
 static void phys_init_v3_hw(struct hisi_hba *hisi_hba)
 {
start_phys_v3_hw(hisi_hba);
@@ -1977,6 +2012,10 @@ static int hisi_sas_v3_init(struct hisi_hba *hisi_hba)
.start_delivery = start_delivery_v3_hw,
.slot_complete = slot_complete_v3_hw,
.phys_init = phys_init_v3_hw,
+   .phy_enable = enable_phy_v3_hw,
+   .phy_disable = disable_phy_v3_hw,
+   .phy_hard_reset = phy_hard_reset_v3_hw,
+   .phy_get_max_linkrate = phy_get_max_linkrate_v3_hw,
 };
 
 static struct Scsi_Host *
@@ -2141,7 +2180,6 @@ static void hisi_sas_v3_remove(struct pci_dev *pdev)
pci_disable_device(pdev);
 }
 
-
 enum {
/* instances of the controller */
hip08,
-- 
1.9.1



[PATCH v3 00/23] hisi_sas: hip08 support

2017-05-31 Thread John Garry
This patchset adds support for the HiSilicon SAS controller
in the hip08 chipset.

The key difference compared to earlier chipsets is that the
controller is an integrated PCI endpoint in hip08.
As such, the controller is a pci device (not a platform device,
like v2 hw in hip07).

The driver is refactored so it can support both platform and 
pci device-based controllers.

New hw layer file hisi_sas_v3_hw.c is added for v3 hw
support, which also includes pci device proving and
initialisation. 

Common functionality is still in hisi_sas_main.c, along with
platform device probing and initialization.

As for the patches, (ignoring #1-3) the first few
reorganise some functions from v2 hw.c into main.c, as they
are required for v3 hw. Then support is added for pci
device-based controller in subsequent patches.
And then hip08 support is added in the final patches.

Differences to v2 series:
- Add patch to change hisi_sas_device.device_id size
- Add device dq pointer
- Remove hisi_sas_v3_hw prototype in v3 driver
- Add explicit comment in hisi_sas_get_fw_info()

Differences to v1 series:
- Addressed Arnd's comments, including:
 - read sas address from device node DSD under PCI host
bridge
 - add comment in fatal axi error patch commit log regarding
controller reset
 - eliminate hisi_sas_pci_init.c, and move functionality into
hisi_sas_v3_hw.c, eliminating one layer of indirection

John Garry (5):
  scsi: hisi_sas: define hisi_sas_device.device_id as int
  scsi: hisi_sas: add pci_dev in hisi_hba struct
  scsi: hisi_sas: create hisi_sas_get_fw_info()
  scsi: hisi_sas: add skeleton v3 hw driver
  scsi: hisi_sas: add initialisation for v3 pci-based controller

Xiang Chen (18):
  scsi: hisi_sas: fix timeout check in hisi_sas_internal_task_abort()
  scsi: hisi_sas: optimise the usage of hisi_hba.lock
  scsi: hisi_sas: relocate get_ata_protocol()
  scsi: hisi_sas: relocate sata_done_v2_hw()
  scsi: hisi_sas: relocate get_ncq_tag_v2_hw()
  scsi: hisi_sas: add v3 hw init
  scsi: hisi_sas: add v3 hw PHY init
  scsi: hisi_sas: add phy up/down/bcast and channel ISR
  scsi: hisi_sas: add v3 cq interrupt handler
  scsi: hisi_sas: add v3 code to send SSP frame
  scsi: hisi_sas: add v3 code to send SMP frame
  scsi: hisi_sas: add v3 code to send ATA frame
  scsi: hisi_sas: add v3 code for itct setup and free
  scsi: hisi_sas: add v3 code to send internal abort command
  scsi: hisi_sas: add get_wideport_bitmap_v3_hw()
  scsi: hisi_sas: Add v3 code to support ECC and AXI bus fatal error
  scsi: hisi_sas: add v3 code to fill some more hw function pointers
  scsi: hisi_sas: modify internal abort dev flow for v3 hw

 drivers/scsi/hisi_sas/Kconfig  |   10 +-
 drivers/scsi/hisi_sas/Makefile |1 +
 drivers/scsi/hisi_sas/hisi_sas.h   |   37 +-
 drivers/scsi/hisi_sas/hisi_sas_main.c  |  393 --
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c |   51 +-
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c |  179 +--
 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 2234 
 7 files changed, 2640 insertions(+), 265 deletions(-)
 create mode 100644 drivers/scsi/hisi_sas/hisi_sas_v3_hw.c

-- 
1.9.1



[PATCH V2 12/15] qedf: Move some prints to a debug level so they do not print when no debugging is enabled.

2017-05-31 Thread Dupuis, Chad
Signed-off-by: Chad Dupuis 
---
 drivers/scsi/qedf/qedf_main.c | 13 -
 1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c
index 45c741b..4b688d6 100644
--- a/drivers/scsi/qedf/qedf_main.c
+++ b/drivers/scsi/qedf/qedf_main.c
@@ -442,7 +442,8 @@ static void qedf_link_update(void *dev, struct 
qed_link_output *link)
qedf_update_link_speed(qedf, link);
 
if (atomic_read(>dcbx) == QEDF_DCBX_DONE) {
-   QEDF_ERR(&(qedf->dbg_ctx), "DCBx done.\n");
+   QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_DISC,
+"DCBx done.\n");
if (atomic_read(>link_down_tmo_valid) > 0)
queue_delayed_work(qedf->link_update_wq,
>link_recovery, 0);
@@ -2155,14 +2156,15 @@ static void qedf_recv_frame(struct qedf_ctx *qedf,
}
 
if (ntoh24(_mac[3]) != ntoh24(fh->fh_d_id)) {
-   QEDF_ERR(&(qedf->dbg_ctx), "FC frame d_id mismatch with MAC 
%pM.\n",
-   dest_mac);
+   QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2,
+   "FC frame d_id mismatch with MAC %pM.\n", dest_mac);
return;
}
 
if (qedf->ctlr.state) {
if (!ether_addr_equal(mac, qedf->ctlr.dest_addr)) {
-   QEDF_ERR(&(qedf->dbg_ctx), "Wrong source address 
mac:%pM dest_addr:%pM.\n",
+   QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2,
+   "Wrong source address: mac:%pM dest_addr:%pM.\n",
mac, qedf->ctlr.dest_addr);
kfree_skb(skb);
return;
@@ -2177,7 +2179,8 @@ static void qedf_recv_frame(struct qedf_ctx *qedf,
 * empty then this is not addressed to our port so simply drop it.
 */
if (lport->port_id != ntoh24(fh->fh_d_id) && !vn_port) {
-   QEDF_ERR(&(qedf->dbg_ctx), "Dropping frame due to destination 
mismatch: lport->port_id=%x fh->d_id=%x.\n",
+   QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2,
+   "Dropping frame due to destination mismatch: 
lport->port_id=%x fh->d_id=%x.\n",
lport->port_id, ntoh24(fh->fh_d_id));
kfree_skb(skb);
return;
-- 
1.8.5.6



[PATCH V2 14/15] qedf: Add change_queue_depth member to scsi_host_template().

2017-05-31 Thread Dupuis, Chad
Add the change_queue_depth member to our SCSI host template so the queue
depth of devices attached to qedf can be changed dynamically.

Signed-off-by: Chad Dupuis 
---
 drivers/scsi/qedf/qedf_main.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c
index 27a9e26..ff32865 100644
--- a/drivers/scsi/qedf/qedf_main.c
+++ b/drivers/scsi/qedf/qedf_main.c
@@ -722,6 +722,7 @@ static int qedf_slave_configure(struct scsi_device *sdev)
.dma_boundary = QED_HW_DMA_BOUNDARY,
.sg_tablesize = QEDF_MAX_BDS_PER_CMD,
.can_queue = FCOE_PARAMS_NUM_TASKS,
+   .change_queue_depth = scsi_change_queue_depth,
 };
 
 static int qedf_get_paged_crc_eof(struct sk_buff *skb, int tlen)
-- 
1.8.5.6



[PATCH V2 15/15] qedf: Update version number to 8.18.22.0.

2017-05-31 Thread Dupuis, Chad
Signed-off-by: Chad Dupuis 
---
 drivers/scsi/qedf/qedf_version.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/qedf/qedf_version.h b/drivers/scsi/qedf/qedf_version.h
index d46c487..6fa4420 100644
--- a/drivers/scsi/qedf/qedf_version.h
+++ b/drivers/scsi/qedf/qedf_version.h
@@ -7,9 +7,9 @@
  *  this source tree.
  */
 
-#define QEDF_VERSION   "8.10.7.0"
+#define QEDF_VERSION   "8.18.22.0"
 #define QEDF_DRIVER_MAJOR_VER  8
-#define QEDF_DRIVER_MINOR_VER  10
-#define QEDF_DRIVER_REV_VER7
+#define QEDF_DRIVER_MINOR_VER  18
+#define QEDF_DRIVER_REV_VER22
 #define QEDF_DRIVER_ENG_VER0
 
-- 
1.8.5.6



[PATCH V2 13/15] qedf: Change cmd_per_lun in scsi_host_template to 32 to increase performance.

2017-05-31 Thread Dupuis, Chad
Increase the default number of commands that the driver tells the
SCSI mid-layer it can do to increase the default performance of the
driver.

Signed-off-by: Chad Dupuis 
---
 drivers/scsi/qedf/qedf_main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c
index 4b688d6..27a9e26 100644
--- a/drivers/scsi/qedf/qedf_main.c
+++ b/drivers/scsi/qedf/qedf_main.c
@@ -708,7 +708,7 @@ static int qedf_slave_configure(struct scsi_device *sdev)
.module = THIS_MODULE,
.name   = QEDF_MODULE_NAME,
.this_id= -1,
-   .cmd_per_lun= 3,
+   .cmd_per_lun= 32,
.use_clustering = ENABLE_CLUSTERING,
.max_sectors= 0x,
.queuecommand   = qedf_queuecommand,
-- 
1.8.5.6



[PATCH V2 10/15] qedf: Add non-offload receive filters.

2017-05-31 Thread Dupuis, Chad
Drop invalid or unexpected FCoE frames that come into the non-offload path
since the FCoE firmware would not do the filtering for us.

Signed-off-by: Chad Dupuis 
---
 drivers/scsi/qedf/qedf_main.c | 43 +++
 1 file changed, 43 insertions(+)

diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c
index d762b9f..45c741b 100644
--- a/drivers/scsi/qedf/qedf_main.c
+++ b/drivers/scsi/qedf/qedf_main.c
@@ -2087,6 +2087,8 @@ static void qedf_recv_frame(struct qedf_ctx *qedf,
u8 *dest_mac = NULL;
struct fcoe_hdr *hp;
struct qedf_rport *fcport;
+   struct fc_lport *vn_port;
+   u32 f_ctl;
 
lport = qedf->lport;
if (lport == NULL || lport->state == LPORT_ST_DISABLED) {
@@ -2123,6 +2125,10 @@ static void qedf_recv_frame(struct qedf_ctx *qedf,
 
fh = fc_frame_header_get(fp);
 
+   /*
+* Invalid frame filters.
+*/
+
if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA &&
fh->fh_type == FC_TYPE_FCP) {
/* Drop FCP data. We dont this in L2 path */
@@ -2148,6 +2154,43 @@ static void qedf_recv_frame(struct qedf_ctx *qedf,
return;
}
 
+   if (ntoh24(_mac[3]) != ntoh24(fh->fh_d_id)) {
+   QEDF_ERR(&(qedf->dbg_ctx), "FC frame d_id mismatch with MAC 
%pM.\n",
+   dest_mac);
+   return;
+   }
+
+   if (qedf->ctlr.state) {
+   if (!ether_addr_equal(mac, qedf->ctlr.dest_addr)) {
+   QEDF_ERR(&(qedf->dbg_ctx), "Wrong source address 
mac:%pM dest_addr:%pM.\n",
+   mac, qedf->ctlr.dest_addr);
+   kfree_skb(skb);
+   return;
+   }
+   }
+
+   vn_port = fc_vport_id_lookup(lport, ntoh24(fh->fh_d_id));
+
+   /*
+* If the destination ID from the frame header does not match what we
+* have on record for lport and the search for a NPIV port came up
+* empty then this is not addressed to our port so simply drop it.
+*/
+   if (lport->port_id != ntoh24(fh->fh_d_id) && !vn_port) {
+   QEDF_ERR(&(qedf->dbg_ctx), "Dropping frame due to destination 
mismatch: lport->port_id=%x fh->d_id=%x.\n",
+   lport->port_id, ntoh24(fh->fh_d_id));
+   kfree_skb(skb);
+   return;
+   }
+
+   f_ctl = ntoh24(fh->fh_f_ctl);
+   if ((fh->fh_type == FC_TYPE_BLS) && (f_ctl & FC_FC_SEQ_CTX) &&
+   (f_ctl & FC_FC_EX_CTX)) {
+   /* Drop incoming ABTS response that has both SEQ/EX CTX set */
+   kfree_skb(skb);
+   return;
+   }
+
/*
 * If a connection is uploading, drop incoming FCoE frames as there
 * is a small window where we could try to return a frame while libfc
-- 
1.8.5.6



[PATCH V2 08/15] qedf: Use same logic for SCSI host reset and FC lip_reset.

2017-05-31 Thread Dupuis, Chad
We should be using the same logic to do a soft reset of the FCoE function
whether it is initiated via sg_reset or the fc_host issue_lip attribute.
Refactor the host reset and fcoe reset handlers to use the preferred logic
which is currently contained in qedf_eh_host_reset().

Signed-off-by: Chad Dupuis 
---
 drivers/scsi/qedf/qedf_main.c | 39 +++
 1 file changed, 23 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c
index d08793e..99d8822 100644
--- a/drivers/scsi/qedf/qedf_main.c
+++ b/drivers/scsi/qedf/qedf_main.c
@@ -640,27 +640,17 @@ void qedf_wait_for_upload(struct qedf_ctx *qedf)
}
 }
 
-/* Reset the host by gracefully logging out and then logging back in */
-static int qedf_eh_host_reset(struct scsi_cmnd *sc_cmd)
+/* Performs soft reset of qedf_ctx by simulating a link down/up */
+static void qedf_ctx_soft_reset(struct fc_lport *lport)
 {
-   struct fc_lport *lport;
struct qedf_ctx *qedf;
 
-   lport = shost_priv(sc_cmd->device->host);
-
if (lport->vport) {
QEDF_ERR(NULL, "Cannot issue host reset on NPIV port.\n");
-   return SUCCESS;
+   return;
}
 
-   qedf = (struct qedf_ctx *)lport_priv(lport);
-
-   if (atomic_read(>link_state) == QEDF_LINK_DOWN ||
-   test_bit(QEDF_UNLOADING, >flags) ||
-   test_bit(QEDF_DBG_STOP_IO, >flags))
-   return FAILED;
-
-   QEDF_ERR(&(qedf->dbg_ctx), "HOST RESET Issued...");
+   qedf = lport_priv(lport);
 
/* For host reset, essentially do a soft link up/down */
atomic_set(>link_state, QEDF_LINK_DOWN);
@@ -672,6 +662,24 @@ static int qedf_eh_host_reset(struct scsi_cmnd *sc_cmd)
qedf->vlan_id  = 0;
queue_delayed_work(qedf->link_update_wq, >link_update,
0);
+}
+
+/* Reset the host by gracefully logging out and then logging back in */
+static int qedf_eh_host_reset(struct scsi_cmnd *sc_cmd)
+{
+   struct fc_lport *lport;
+   struct qedf_ctx *qedf;
+
+   lport = shost_priv(sc_cmd->device->host);
+   qedf = lport_priv(lport);
+
+   if (atomic_read(>link_state) == QEDF_LINK_DOWN ||
+   test_bit(QEDF_UNLOADING, >flags))
+   return FAILED;
+
+   QEDF_ERR(&(qedf->dbg_ctx), "HOST RESET Issued...");
+
+   qedf_ctx_soft_reset(lport);
 
return SUCCESS;
 }
@@ -1669,8 +1677,7 @@ static int qedf_fcoe_reset(struct Scsi_Host *shost)
 {
struct fc_lport *lport = shost_priv(shost);
 
-   fc_fabric_logoff(lport);
-   fc_fabric_login(lport);
+   qedf_ctx_soft_reset(lport);
return 0;
 }
 
-- 
1.8.5.6



[PATCH V2 05/15] qedf: Check that fcport is offloaded before dereferencing pointers in initiate_abts|cleanup.

2017-05-31 Thread Dupuis, Chad
If an fcport is not offloaded then the members of the qedf_rport struct
are undefined which may cause a system crash.

Signed-off-by: Chad Dupuis 
---
 drivers/scsi/qedf/qedf_io.c | 22 --
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/qedf/qedf_io.c b/drivers/scsi/qedf/qedf_io.c
index ca9097b..db16004 100644
--- a/drivers/scsi/qedf/qedf_io.c
+++ b/drivers/scsi/qedf/qedf_io.c
@@ -1476,8 +1476,8 @@ int qedf_initiate_abts(struct qedf_ioreq *io_req, bool 
return_scsi_cmd_on_abts)
 {
struct fc_lport *lport;
struct qedf_rport *fcport = io_req->fcport;
-   struct fc_rport_priv *rdata = fcport->rdata;
-   struct qedf_ctx *qedf = fcport->qedf;
+   struct fc_rport_priv *rdata;
+   struct qedf_ctx *qedf;
u16 xid;
u32 r_a_tov = 0;
int rc = 0;
@@ -1485,15 +1485,18 @@ int qedf_initiate_abts(struct qedf_ioreq *io_req, bool 
return_scsi_cmd_on_abts)
struct fcoe_wqe *sqe;
u16 sqe_idx;
 
-   r_a_tov = rdata->r_a_tov;
-   lport = qedf->lport;
-
+   /* Sanity check qedf_rport before dereferencing any pointers */
if (!test_bit(QEDF_RPORT_SESSION_READY, >flags)) {
-   QEDF_ERR(&(qedf->dbg_ctx), "tgt not offloaded\n");
+   QEDF_ERR(NULL, "tgt not offloaded\n");
rc = 1;
goto abts_err;
}
 
+   rdata = fcport->rdata;
+   r_a_tov = rdata->r_a_tov;
+   qedf = fcport->qedf;
+   lport = qedf->lport;
+
if (lport->state != LPORT_ST_READY || !(lport->link_up)) {
QEDF_ERR(&(qedf->dbg_ctx), "link is not ready\n");
rc = 1;
@@ -1729,6 +1732,13 @@ int qedf_initiate_cleanup(struct qedf_ioreq *io_req,
return SUCCESS;
}
 
+   /* Sanity check qedf_rport before dereferencing any pointers */
+   if (!test_bit(QEDF_RPORT_SESSION_READY, >flags)) {
+   QEDF_ERR(NULL, "tgt not offloaded\n");
+   rc = 1;
+   return SUCCESS;
+   }
+
qedf = fcport->qedf;
if (!qedf) {
QEDF_ERR(NULL, "qedf is NULL.\n");
-- 
1.8.5.6



[PATCH V2 09/15] qedf: Add bus_reset No-op.

2017-05-31 Thread Dupuis, Chad
We need to add a bus reset no-op as without it some of the LUNs attached to a
vport may go offline when the error handler escalates to host reset due to not
having a bus reset handler in the driver. What happens is we escalate to host
reset which does a soft link down/link up to reset the adapter. However with
multiple vports attached it's been observed that if the vports do log back into
the target within 5 seconds, the SCSI layer offlines the devices most likely
due to a TUR timing out to verify that the device is online. Adding a bus
reset handler will cause the TUR to be sent after the bus reset handler where
the devices will still be online if the bus reset is initiated by sg_reset
(which is the case in the test that was failing). The bus reset will succeed
and not needlessly bring the device offline/online.

Signed-off-by: Chad Dupuis 
---
 drivers/scsi/qedf/qedf_main.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c
index 99d8822..d762b9f 100644
--- a/drivers/scsi/qedf/qedf_main.c
+++ b/drivers/scsi/qedf/qedf_main.c
@@ -628,6 +628,16 @@ static int qedf_eh_device_reset(struct scsi_cmnd *sc_cmd)
return qedf_initiate_tmf(sc_cmd, FCP_TMF_LUN_RESET);
 }
 
+static int qedf_eh_bus_reset(struct scsi_cmnd *sc_cmd)
+{
+   QEDF_ERR(NULL, "BUS RESET Issued...\n");
+   /*
+* Essentially a no-op but return SUCCESS to prevent
+* unnecessary escalation to the host reset handler.
+*/
+   return SUCCESS;
+}
+
 void qedf_wait_for_upload(struct qedf_ctx *qedf)
 {
while (1) {
@@ -705,6 +715,7 @@ static int qedf_slave_configure(struct scsi_device *sdev)
.eh_abort_handler   = qedf_eh_abort,
.eh_device_reset_handler = qedf_eh_device_reset, /* lun reset */
.eh_target_reset_handler = qedf_eh_target_reset, /* target reset */
+   .eh_bus_reset_handler = qedf_eh_bus_reset,
.eh_host_reset_handler  = qedf_eh_host_reset,
.slave_configure= qedf_slave_configure,
.dma_boundary = QED_HW_DMA_BOUNDARY,
-- 
1.8.5.6



[PATCH V2 06/15] qedf: Add fka_period SCSI host attribute to show fip keep alive period.

2017-05-31 Thread Dupuis, Chad
Expose this information for interested applications.

Signed-off-by: Chad Dupuis 
---
 drivers/scsi/qedf/qedf_attr.c | 57 ---
 1 file changed, 38 insertions(+), 19 deletions(-)

diff --git a/drivers/scsi/qedf/qedf_attr.c b/drivers/scsi/qedf/qedf_attr.c
index 1349f8a..fa67276 100644
--- a/drivers/scsi/qedf/qedf_attr.c
+++ b/drivers/scsi/qedf/qedf_attr.c
@@ -8,6 +8,25 @@
  */
 #include "qedf.h"
 
+inline bool qedf_is_vport(struct qedf_ctx *qedf)
+{
+   return qedf->lport->vport != NULL;
+}
+
+/* Get base qedf for physical port from vport */
+static struct qedf_ctx *qedf_get_base_qedf(struct qedf_ctx *qedf)
+{
+   struct fc_lport *lport;
+   struct fc_lport *base_lport;
+
+   if (!(qedf_is_vport(qedf)))
+   return NULL;
+
+   lport = qedf->lport;
+   base_lport = shost_priv(vport_to_shost(lport->vport));
+   return lport_priv(base_lport);
+}
+
 static ssize_t
 qedf_fcoe_mac_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -26,34 +45,34 @@
return scnprintf(buf, PAGE_SIZE, "%pM\n", fcoe_mac);
 }
 
+static ssize_t
+qedf_fka_period_show(struct device *dev,
+   struct device_attribute *attr, char *buf)
+{
+   struct fc_lport *lport = shost_priv(class_to_shost(dev));
+   struct qedf_ctx *qedf = lport_priv(lport);
+   int fka_period = -1;
+
+   if (qedf_is_vport(qedf))
+   qedf = qedf_get_base_qedf(qedf);
+
+   if (qedf->ctlr.sel_fcf)
+   fka_period = qedf->ctlr.sel_fcf->fka_period;
+
+   return scnprintf(buf, PAGE_SIZE, "%d\n", fka_period);
+}
+
 static DEVICE_ATTR(fcoe_mac, S_IRUGO, qedf_fcoe_mac_show, NULL);
+static DEVICE_ATTR(fka_period, S_IRUGO, qedf_fka_period_show, NULL);
 
 struct device_attribute *qedf_host_attrs[] = {
_attr_fcoe_mac,
+   _attr_fka_period,
NULL,
 };
 
 extern const struct qed_fcoe_ops *qed_ops;
 
-inline bool qedf_is_vport(struct qedf_ctx *qedf)
-{
-   return (!(qedf->lport->vport == NULL));
-}
-
-/* Get base qedf for physical port from vport */
-static struct qedf_ctx *qedf_get_base_qedf(struct qedf_ctx *qedf)
-{
-   struct fc_lport *lport;
-   struct fc_lport *base_lport;
-
-   if (!(qedf_is_vport(qedf)))
-   return NULL;
-
-   lport = qedf->lport;
-   base_lport = shost_priv(vport_to_shost(lport->vport));
-   return (struct qedf_ctx *)(lport_priv(base_lport));
-}
-
 void qedf_capture_grc_dump(struct qedf_ctx *qedf)
 {
struct qedf_ctx *base_qedf;
-- 
1.8.5.6



[PATCH V2 11/15] qedf: Fixup unnecessary parantheses around test_bit operations.

2017-05-31 Thread Dupuis, Chad
Signed-off-by: Chad Dupuis 
---
 drivers/scsi/qedf/qedf_els.c | 6 +++---
 drivers/scsi/qedf/qedf_io.c  | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/qedf/qedf_els.c b/drivers/scsi/qedf/qedf_els.c
index e197fd6..78d9f1c 100644
--- a/drivers/scsi/qedf/qedf_els.c
+++ b/drivers/scsi/qedf/qedf_els.c
@@ -44,7 +44,7 @@ static int qedf_initiate_els(struct qedf_rport *fcport, 
unsigned int op,
goto els_err;
}
 
-   if (!(test_bit(QEDF_RPORT_SESSION_READY, >flags))) {
+   if (!test_bit(QEDF_RPORT_SESSION_READY, >flags)) {
QEDF_ERR(&(qedf->dbg_ctx), "els 0x%x: fcport not ready\n", op);
rc = -EINVAL;
goto els_err;
@@ -225,7 +225,7 @@ int qedf_send_rrq(struct qedf_ioreq *aborted_io_req)
fcport = aborted_io_req->fcport;
 
/* Check that fcport is still offloaded */
-   if (!(test_bit(QEDF_RPORT_SESSION_READY, >flags))) {
+   if (!test_bit(QEDF_RPORT_SESSION_READY, >flags)) {
QEDF_ERR(NULL, "fcport is no longer offloaded.\n");
return -EINVAL;
}
@@ -550,7 +550,7 @@ static int qedf_send_srr(struct qedf_ioreq *orig_io_req, 
u32 offset, u8 r_ctl)
fcport = orig_io_req->fcport;
 
/* Check that fcport is still offloaded */
-   if (!(test_bit(QEDF_RPORT_SESSION_READY, >flags))) {
+   if (!test_bit(QEDF_RPORT_SESSION_READY, >flags)) {
QEDF_ERR(NULL, "fcport is no longer offloaded.\n");
return -EINVAL;
}
diff --git a/drivers/scsi/qedf/qedf_io.c b/drivers/scsi/qedf/qedf_io.c
index db16004..ea37c78 100644
--- a/drivers/scsi/qedf/qedf_io.c
+++ b/drivers/scsi/qedf/qedf_io.c
@@ -1847,7 +1847,7 @@ static int qedf_execute_tmf(struct qedf_rport *fcport, 
struct scsi_cmnd *sc_cmd,
return FAILED;
}
 
-   if (!(test_bit(QEDF_RPORT_SESSION_READY, >flags))) {
+   if (!test_bit(QEDF_RPORT_SESSION_READY, >flags)) {
QEDF_ERR(&(qedf->dbg_ctx), "fcport not offloaded\n");
rc = FAILED;
return FAILED;
-- 
1.8.5.6



[PATCH V2 04/15] qedf: Look at all descriptors when processing a clear virtual link.

2017-05-31 Thread Dupuis, Chad
If there are multiple descriptors for a particular type in a clear virtual
link we receive, we will not process it correctly but rather take the last
value. This can cause us not to not flap the virtual link as the value from
the descriptors that we compare against the our stored FCF or fc_lport values
may not match.

Change this to do a comparison when processing the each descriptor instead of at
the end and then set a bool if we need to do the reset.

Signed-off-by: Chad Dupuis 
---
 drivers/scsi/qedf/qedf_fip.c | 20 +---
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/drivers/scsi/qedf/qedf_fip.c b/drivers/scsi/qedf/qedf_fip.c
index 2dfb817..64b04f2 100644
--- a/drivers/scsi/qedf/qedf_fip.c
+++ b/drivers/scsi/qedf/qedf_fip.c
@@ -156,10 +156,9 @@ void qedf_fip_recv(struct qedf_ctx *qedf, struct sk_buff 
*skb)
struct fip_wwn_desc *wp;
struct fip_vn_desc *vp;
size_t rlen, dlen;
-   uint32_t cvl_port_id;
-   __u8 cvl_mac[ETH_ALEN];
u16 op;
u8 sub;
+   bool do_reset = false;
 
eth_hdr = (struct ethhdr *)skb_mac_header(skb);
fiph = (struct fip_header *) ((void *)skb->data + 2 * ETH_ALEN + 2);
@@ -190,8 +189,6 @@ void qedf_fip_recv(struct qedf_ctx *qedf, struct sk_buff 
*skb)
return;
}
 
-   cvl_port_id = 0;
-   memset(cvl_mac, 0, ETH_ALEN);
/*
 * We need to loop through the CVL descriptors to determine
 * if we want to reset the fcoe link
@@ -205,7 +202,9 @@ void qedf_fip_recv(struct qedf_ctx *qedf, struct sk_buff 
*skb)
mp = (struct fip_mac_desc *)desc;
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2,
"fd_mac=%pM\n", mp->fd_mac);
-   ether_addr_copy(cvl_mac, mp->fd_mac);
+   if (ether_addr_equal(mp->fd_mac,
+   qedf->ctlr.sel_fcf->fcf_mac))
+   do_reset = true;
break;
case FIP_DT_NAME:
wp = (struct fip_wwn_desc *)desc;
@@ -217,7 +216,9 @@ void qedf_fip_recv(struct qedf_ctx *qedf, struct sk_buff 
*skb)
vp = (struct fip_vn_desc *)desc;
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2,
"fd_fc_id=%x.\n", ntoh24(vp->fd_fc_id));
-   cvl_port_id = ntoh24(vp->fd_fc_id);
+   if (ntoh24(vp->fd_fc_id) ==
+   qedf->lport->port_id)
+   do_reset = true;
break;
default:
/* Ignore anything else */
@@ -228,11 +229,8 @@ void qedf_fip_recv(struct qedf_ctx *qedf, struct sk_buff 
*skb)
}
 
QEDF_INFO(&(qedf->dbg_ctx), QEDF_LOG_LL2,
-   "cvl_port_id=%06x cvl_mac=%pM.\n", cvl_port_id,
-   cvl_mac);
-   if (cvl_port_id == qedf->lport->port_id &&
-   ether_addr_equal(cvl_mac,
-   qedf->ctlr.sel_fcf->fcf_mac)) {
+   "do_reset=%d.\n", do_reset);
+   if (do_reset) {
fcoe_ctlr_link_down(>ctlr);
qedf_wait_for_upload(qedf);
fcoe_ctlr_link_up(>ctlr);
-- 
1.8.5.6



[PATCH V2 03/15] qedf: Honor qed_ops->common->set_fp_int() return code.

2017-05-31 Thread Dupuis, Chad
We need to check the return code the set_fp_int() callback in case we were
not allocated any fastpath interrupts or there was an error setting up the
fastpath interrupts from the qed perspective.

Signed-off-by: Chad Dupuis 
---
 drivers/scsi/qedf/qedf_main.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c
index 9457665..884103b 100644
--- a/drivers/scsi/qedf/qedf_main.c
+++ b/drivers/scsi/qedf/qedf_main.c
@@ -2035,6 +2035,8 @@ static int qedf_setup_int(struct qedf_ctx *qedf)
 * Learn interrupt configuration
 */
rc = qed_ops->common->set_fp_int(qedf->cdev, num_online_cpus());
+   if (rc <= 0)
+   return 0;
 
rc  = qed_ops->common->get_fp_int(qedf->cdev, >int_info);
if (rc)
-- 
1.8.5.6



[PATCH V2 00/15] qedf: Update driver to version 8.18.22.0.

2017-05-31 Thread Dupuis, Chad
Hi Martin,

Please apply the following patches to the scsi tree at your earliest 
convenience.

Thanks,
Chad

Change from V1 -> V2:

- Use fc_host attributes directly instead of using fc_host_* macros when 
setting FDMI attributes
- Fix typos in patch descriptions
- Implement suggested code refactoring for fka_period sysfs attribute
- Keep newly introduced error message strings on one line

Dupuis, Chad (15):
  qedf: Enable basic FDMI information.
  qedf: Update copyright to 2017.
  qedf: Honor qed_ops->common->set_fp_int() return code.
  qedf: Look at all descriptors when processing a clear virtual link.
  qedf: Check that fcport is offloaded before dereferencing pointers in
initiate_abts|cleanup.
  qedf: Add fka_period SCSI host attribute to show fip keep alive
period.
  qedf: Set qed logging level to QED_LEVEL_NOTICE.
  qedf: Use same logic for SCSI host reset and FC lip_reset.
  qedf: Add bus_reset No-op.
  qedf: Add non-offload receive filters.
  qedf: Fixup unnecessary parantheses around test_bit operations.
  qedf: Move some prints to a debug level so they do not print when no
debugging is enabled.
  qedf: Change cmd_per_lun in scsi_host_template to 32 to increase
performance.
  qedf: Add change_queue_depth member to scsi_host_template().
  qedf: Update version number to 8.18.22.0.

 drivers/scsi/qedf/drv_fcoe_fw_funcs.c |   2 +-
 drivers/scsi/qedf/drv_fcoe_fw_funcs.h |   2 +-
 drivers/scsi/qedf/drv_scsi_fw_funcs.c |   2 +-
 drivers/scsi/qedf/drv_scsi_fw_funcs.h |   2 +-
 drivers/scsi/qedf/qedf.h  |   2 +-
 drivers/scsi/qedf/qedf_attr.c |  59 +++-
 drivers/scsi/qedf/qedf_dbg.h  |   2 +-
 drivers/scsi/qedf/qedf_debugfs.c  |   2 +-
 drivers/scsi/qedf/qedf_els.c  |   8 +-
 drivers/scsi/qedf/qedf_fip.c  |  22 +++--
 drivers/scsi/qedf/qedf_hsi.h  |   2 +-
 drivers/scsi/qedf/qedf_io.c   |  26 --
 drivers/scsi/qedf/qedf_main.c | 163 +-
 drivers/scsi/qedf/qedf_version.h  |   8 +-
 14 files changed, 226 insertions(+), 76 deletions(-)

-- 
1.8.5.6



[PATCH V2 07/15] qedf: Set qed logging level to QED_LEVEL_NOTICE.

2017-05-31 Thread Dupuis, Chad
Reduce the logging level we set for qed messages pertaining to this PCI
function so that unnecessary messages are not printed in the kernel
message log.

Signed-off-by: Chad Dupuis 
---
 drivers/scsi/qedf/qedf_main.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c
index 884103b..d08793e 100644
--- a/drivers/scsi/qedf/qedf_main.c
+++ b/drivers/scsi/qedf/qedf_main.c
@@ -95,7 +95,7 @@
 MODULE_PARM_DESC(dp_module, " bit flags control for verbose printk passed "
"qed module during probe.");
 
-static uint qedf_dp_level;
+static uint qedf_dp_level = QED_LEVEL_NOTICE;
 module_param_named(dp_level, qedf_dp_level, uint, S_IRUGO);
 MODULE_PARM_DESC(dp_level, " printk verbosity control passed to qed module  "
"during probe (0-3: 0 more verbose).");
-- 
1.8.5.6



[PATCH V2 01/15] qedf: Enable basic FDMI information.

2017-05-31 Thread Dupuis, Chad
For libfc to register FDMI attributes we need to do two things:

- Set the appropriate fc_host attributes that libfc will use to form the
  FDMI registration commands
- Set lport->fdmi_enabled to 1

Signed-off-by: Chad Dupuis 
---
 drivers/scsi/qedf/qedf_main.c | 56 +++
 1 file changed, 56 insertions(+)

diff --git a/drivers/scsi/qedf/qedf_main.c b/drivers/scsi/qedf/qedf_main.c
index cceddd9..8d0a999 100644
--- a/drivers/scsi/qedf/qedf_main.c
+++ b/drivers/scsi/qedf/qedf_main.c
@@ -22,6 +22,7 @@
 #include 
 #include 
 #include "qedf.h"
+#include 
 
 const struct qed_fcoe_ops *qed_ops;
 
@@ -1334,6 +1335,59 @@ static void qedf_fcoe_ctlr_setup(struct qedf_ctx *qedf)
ether_addr_copy(qedf->ctlr.ctl_src_addr, qedf->mac);
 }
 
+static void qedf_setup_fdmi(struct qedf_ctx *qedf)
+{
+   struct fc_lport *lport = qedf->lport;
+   struct fc_host_attrs *fc_host = shost_to_fc_host(lport->host);
+   u8 buf[8];
+   int i, pos;
+
+   /*
+* fdmi_enabled needs to be set for libfc to execute FDMI registration.
+*/
+   lport->fdmi_enabled = 1;
+
+   /*
+* Setup the necessary fc_host attributes to that will be used to fill
+* in the FDMI information.
+*/
+
+   /* Get the PCI-e Device Serial Number Capability */
+   pos = pci_find_ext_capability(qedf->pdev, PCI_EXT_CAP_ID_DSN);
+   if (pos) {
+   pos += 4;
+   for (i = 0; i < 8; i++)
+   pci_read_config_byte(qedf->pdev, pos + i, [i]);
+
+   snprintf(fc_host->serial_number,
+   sizeof(fc_host->serial_number),
+   "%02X%02X%02X%02X%02X%02X%02X%02X",
+   buf[7], buf[6], buf[5], buf[4],
+   buf[3], buf[2], buf[1], buf[0]);
+   } else
+   snprintf(fc_host->serial_number,
+   sizeof(fc_host->serial_number), "Unknown");
+
+   snprintf(fc_host->manufacturer,
+   sizeof(fc_host->manufacturer), "%s", "Cavium Inc.");
+
+   snprintf(fc_host->model, sizeof(fc_host->model), "%s", "QL41000");
+
+   snprintf(fc_host->model_description, sizeof(fc_host->model_description),
+   "%s", "QLogic FastLinQ QL41000 Series 10/25/40/50GGbE Controller"
+   "(FCoE)");
+
+   snprintf(fc_host->hardware_version, sizeof(fc_host->hardware_version),
+   "Rev %d", qedf->pdev->revision);
+
+   snprintf(fc_host->driver_version, sizeof(fc_host->driver_version),
+   "%s", QEDF_VERSION);
+
+   snprintf(fc_host->firmware_version, sizeof(fc_host->firmware_version),
+   "%d.%d.%d.%d", FW_MAJOR_VERSION, FW_MINOR_VERSION,
+   FW_REVISION_VERSION, FW_ENGINEERING_VERSION);
+}
+
 static int qedf_lport_setup(struct qedf_ctx *qedf)
 {
struct fc_lport *lport = qedf->lport;
@@ -1377,6 +1431,8 @@ static int qedf_lport_setup(struct qedf_ctx *qedf)
snprintf(fc_host_symbolic_name(lport->host), 256,
"QLogic %s v%s", QEDF_MODULE_NAME, QEDF_VERSION);
 
+   qedf_setup_fdmi(qedf);
+
return 0;
 }
 
-- 
1.8.5.6



[PATCH V2 02/15] qedf: Update copyright to 2017.

2017-05-31 Thread Dupuis, Chad
Signed-off-by: Chad Dupuis 
---
 drivers/scsi/qedf/drv_fcoe_fw_funcs.c | 2 +-
 drivers/scsi/qedf/drv_fcoe_fw_funcs.h | 2 +-
 drivers/scsi/qedf/drv_scsi_fw_funcs.c | 2 +-
 drivers/scsi/qedf/drv_scsi_fw_funcs.h | 2 +-
 drivers/scsi/qedf/qedf.h  | 2 +-
 drivers/scsi/qedf/qedf_attr.c | 2 +-
 drivers/scsi/qedf/qedf_dbg.h  | 2 +-
 drivers/scsi/qedf/qedf_debugfs.c  | 2 +-
 drivers/scsi/qedf/qedf_els.c  | 2 +-
 drivers/scsi/qedf/qedf_fip.c  | 2 +-
 drivers/scsi/qedf/qedf_hsi.h  | 2 +-
 drivers/scsi/qedf/qedf_io.c   | 2 +-
 drivers/scsi/qedf/qedf_main.c | 2 +-
 drivers/scsi/qedf/qedf_version.h  | 2 +-
 14 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/qedf/drv_fcoe_fw_funcs.c 
b/drivers/scsi/qedf/drv_fcoe_fw_funcs.c
index 8c65e3b..7d91e53 100644
--- a/drivers/scsi/qedf/drv_fcoe_fw_funcs.c
+++ b/drivers/scsi/qedf/drv_fcoe_fw_funcs.c
@@ -1,5 +1,5 @@
 /* QLogic FCoE Offload Driver
- * Copyright (c) 2016 Cavium Inc.
+ * Copyright (c) 2016-2017 Cavium Inc.
  *
  * This software is available under the terms of the GNU General Public License
  * (GPL) Version 2, available from the file COPYING in the main directory of
diff --git a/drivers/scsi/qedf/drv_fcoe_fw_funcs.h 
b/drivers/scsi/qedf/drv_fcoe_fw_funcs.h
index 617529b..f9c50fa 100644
--- a/drivers/scsi/qedf/drv_fcoe_fw_funcs.h
+++ b/drivers/scsi/qedf/drv_fcoe_fw_funcs.h
@@ -1,5 +1,5 @@
 /* QLogic FCoE Offload Driver
- * Copyright (c) 2016 Cavium Inc.
+ * Copyright (c) 2016-2017 Cavium Inc.
  *
  * This software is available under the terms of the GNU General Public License
  * (GPL) Version 2, available from the file COPYING in the main directory of
diff --git a/drivers/scsi/qedf/drv_scsi_fw_funcs.c 
b/drivers/scsi/qedf/drv_scsi_fw_funcs.c
index 11e0cc0..5d5095e 100644
--- a/drivers/scsi/qedf/drv_scsi_fw_funcs.c
+++ b/drivers/scsi/qedf/drv_scsi_fw_funcs.c
@@ -1,5 +1,5 @@
 /* QLogic FCoE Offload Driver
- * Copyright (c) 2016 Cavium Inc.
+ * Copyright (c) 2016-2017 Cavium Inc.
  *
  * This software is available under the terms of the GNU General Public License
  * (GPL) Version 2, available from the file COPYING in the main directory of
diff --git a/drivers/scsi/qedf/drv_scsi_fw_funcs.h 
b/drivers/scsi/qedf/drv_scsi_fw_funcs.h
index 9cb4541..8fbe6e4 100644
--- a/drivers/scsi/qedf/drv_scsi_fw_funcs.h
+++ b/drivers/scsi/qedf/drv_scsi_fw_funcs.h
@@ -1,5 +1,5 @@
 /* QLogic FCoE Offload Driver
- * Copyright (c) 2016 Cavium Inc.
+ * Copyright (c) 2016-2017 Cavium Inc.
  *
  * This software is available under the terms of the GNU General Public License
  * (GPL) Version 2, available from the file COPYING in the main directory of
diff --git a/drivers/scsi/qedf/qedf.h b/drivers/scsi/qedf/qedf.h
index 40aeb6b..a5b89b0 100644
--- a/drivers/scsi/qedf/qedf.h
+++ b/drivers/scsi/qedf/qedf.h
@@ -1,6 +1,6 @@
 /*
  *  QLogic FCoE Offload Driver
- *  Copyright (c) 2016 Cavium Inc.
+ *  Copyright (c) 2016-2017 Cavium Inc.
  *
  *  This software is available under the terms of the GNU General Public 
License
  *  (GPL) Version 2, available from the file COPYING in the main directory of
diff --git a/drivers/scsi/qedf/qedf_attr.c b/drivers/scsi/qedf/qedf_attr.c
index 4772061..1349f8a 100644
--- a/drivers/scsi/qedf/qedf_attr.c
+++ b/drivers/scsi/qedf/qedf_attr.c
@@ -1,6 +1,6 @@
 /*
  *  QLogic FCoE Offload Driver
- *  Copyright (c) 2016 Cavium Inc.
+ *  Copyright (c) 2016-2017 Cavium Inc.
  *
  *  This software is available under the terms of the GNU General Public 
License
  *  (GPL) Version 2, available from the file COPYING in the main directory of
diff --git a/drivers/scsi/qedf/qedf_dbg.h b/drivers/scsi/qedf/qedf_dbg.h
index 7d173f48..50083ca 100644
--- a/drivers/scsi/qedf/qedf_dbg.h
+++ b/drivers/scsi/qedf/qedf_dbg.h
@@ -1,6 +1,6 @@
 /*
  *  QLogic FCoE Offload Driver
- *  Copyright (c) 2016 Cavium Inc.
+ *  Copyright (c) 2016-2017 Cavium Inc.
  *
  *  This software is available under the terms of the GNU General Public 
License
  *  (GPL) Version 2, available from the file COPYING in the main directory of
diff --git a/drivers/scsi/qedf/qedf_debugfs.c b/drivers/scsi/qedf/qedf_debugfs.c
index 00a1d64..2b1ef30 100644
--- a/drivers/scsi/qedf/qedf_debugfs.c
+++ b/drivers/scsi/qedf/qedf_debugfs.c
@@ -1,6 +1,6 @@
 /*
  *  QLogic FCoE Offload Driver
- *  Copyright (c) 2016 QLogic Corporation
+ *  Copyright (c) 2016-2017 QLogic Corporation
  *
  *  This software is available under the terms of the GNU General Public 
License
  *  (GPL) Version 2, available from the file COPYING in the main directory of
diff --git a/drivers/scsi/qedf/qedf_els.c b/drivers/scsi/qedf/qedf_els.c
index c505d41..e197fd6 100644
--- a/drivers/scsi/qedf/qedf_els.c
+++ b/drivers/scsi/qedf/qedf_els.c
@@ -1,6 +1,6 @@
 /*
  *  QLogic FCoE Offload Driver
- *  Copyright (c) 2016 Cavium Inc.
+ *  Copyright (c) 2016-2017 Cavium Inc.
  *
  *  This software is available under the terms of the GNU General 

[PATCH v3 3/9] blk-mq: use the introduced blk_mq_unquiesce_queue()

2017-05-31 Thread Ming Lei
blk_mq_unquiesce_queue() is used for unquiescing the
queue explicitly, so replace blk_mq_start_stopped_hw_queues()
with it.

Cc: linux-n...@lists.infradead.org
Cc: linux-scsi@vger.kernel.org
Cc: dm-de...@redhat.com
Signed-off-by: Ming Lei 
---
 drivers/md/dm-rq.c   | 2 +-
 drivers/nvme/host/core.c | 2 +-
 drivers/scsi/scsi_lib.c  | 5 -
 3 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/md/dm-rq.c b/drivers/md/dm-rq.c
index b639fa7246ee..ea4029de077f 100644
--- a/drivers/md/dm-rq.c
+++ b/drivers/md/dm-rq.c
@@ -71,7 +71,7 @@ static void dm_old_start_queue(struct request_queue *q)
 
 static void dm_mq_start_queue(struct request_queue *q)
 {
-   blk_mq_start_stopped_hw_queues(q, true);
+   blk_mq_unquiesce_queue(q);
blk_mq_kick_requeue_list(q);
 }
 
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index a60926410438..c3f189e54d10 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -2526,7 +2526,7 @@ void nvme_start_queues(struct nvme_ctrl *ctrl)
 
mutex_lock(>namespaces_mutex);
list_for_each_entry(ns, >namespaces, list) {
-   blk_mq_start_stopped_hw_queues(ns->queue, true);
+   blk_mq_unquiesce_queue(ns->queue);
blk_mq_kick_requeue_list(ns->queue);
}
mutex_unlock(>namespaces_mutex);
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 99e16ac479e3..ffcf05765e2b 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -3031,7 +3031,10 @@ scsi_internal_device_unblock(struct scsi_device *sdev,
return -EINVAL;
 
if (q->mq_ops) {
-   blk_mq_start_stopped_hw_queues(q, false);
+   if (blk_queue_quiesced(q))
+   blk_mq_unquiesce_queue(q);
+   else
+   blk_mq_start_stopped_hw_queues(q, false);
} else {
spin_lock_irqsave(q->queue_lock, flags);
blk_start_queue(q);
-- 
2.9.4



RE: [PATCH] megaraid: Fix a sleep-in-atomic bug

2017-05-31 Thread Sumit Saxena
>-Original Message-
>From: Jia-Ju Bai [mailto:baijiaju1...@163.com]
>Sent: Wednesday, May 31, 2017 8:27 AM
>To: kashyap.de...@broadcom.com; sumit.sax...@broadcom.com;
>shivasharan.srikanteshw...@broadcom.com; j...@linux.vnet.ibm.com;
>martin.peter...@oracle.com
>Cc: megaraidlinux@broadcom.com; linux-scsi@vger.kernel.org; linux-
>ker...@vger.kernel.org; Jia-Ju Bai
>Subject: [PATCH] megaraid: Fix a sleep-in-atomic bug
>
>The driver may sleep under a spin lock, and the function call path is:
>mraid_mm_attach_buf (acquire the lock by spin_lock_irqsave)
>  pci_pool_alloc(GFP_KERNEL) --> may sleep
>
>To fix it, the "GFP_KERNEL" is replaced with "GFP_ATOMIC".
>
>Signed-off-by: Jia-Ju Bai 
>---
> drivers/scsi/megaraid/megaraid_mm.c |2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
>diff --git a/drivers/scsi/megaraid/megaraid_mm.c
>b/drivers/scsi/megaraid/megaraid_mm.c
>index 4cf9ed9..c43afb8 100644
>--- a/drivers/scsi/megaraid/megaraid_mm.c
>+++ b/drivers/scsi/megaraid/megaraid_mm.c
>@@ -574,7 +574,7 @@
>
>   kioc->pool_index= right_pool;
>   kioc->free_buf  = 1;
>-  kioc->buf_vaddr = pci_pool_alloc(pool->handle, GFP_KERNEL,
>+  kioc->buf_vaddr = pci_pool_alloc(pool->handle, GFP_ATOMIC,
>   >buf_paddr);
>   spin_unlock_irqrestore(>lock, flags);

This is very old driver and reached EOL. Did you face any issue because of
this bug or discover this through code review?
Anyways patch looks good to me.

Acked-by: Sumit Saxena 

>
>--
>1.7.9.5
>


Re: [PATCH 0/3] libfc: fix potential timer list corruption

2017-05-31 Thread Johannes Thumshirn
On 05/30/2017 05:14 PM, Hannes Reinecke wrote:
> Hi all,
> 
> we've seen reports for a crash with an invalid timer_list->function,
> which turned out to be an unsafe usage of libfc discovery callbacks.
> This patchset fixes up the problem
> 
> As usual, comments and reviews are welcome.

The patches look good themselves, but I'd prefer a *why* in the commit
message. For instance in patch 1 you have:

"Move 'pending' and 'requested' setting out of fc_disc_gpn_fc_req()
into the calling function.

No functional change."

But why do you need to move the 'pending' and 'requested' settings?

With an a bit more verbose changelog

Acked-by: Johannes Thumshirn 

for the whole series

-- 
Johannes Thumshirn  Storage
jthumsh...@suse.de+49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850


SCSI controller with CDB-16 (Was: sym53c8xx and Large disk (DCB-16))

2017-05-31 Thread Alexander Voropay
Hello, linux-scsi!

I've re replaced sym53c8xx SCSI controller with
Adaptec ASC-29320ALP (chip AIC-7901).
- Ultra320 bus does not work physically, too many errors.
- Ultra160 bus works relable, no errors.

Unfortunately Adaptec does not work with CDB-16 too :(

scsi11 : Adaptec AIC79XX PCI-X SCSI HBA DRIVER, Rev 3.0

aic7901: Ultra320 Wide Channel A, SCSI Id=7, PCI-X 101-133MHz, 512 SCBs
scsi 11:0:0:0: Direct-Access IFT  A24U-G2421-1 347R PQ: 0 ANSI: 5
scsi target11:0:0: asynchronous
scsi11:A:0:0: Tagged Queuing enabled.  Depth 4
scsi target11:0:0: Beginning Domain Validation
scsi target11:0:0: wide asynchronous
scsi target11:0:0: FAST-80 WIDE SCSI 160.0 MB/s DT (12.5 ns, offset 127)
scsi target11:0:0: Ending Domain Validation
sd 11:0:0:0: [sde] Very big device. Trying to use READ CAPACITY(16).
sd 11:0:0:0: [sde] READ CAPACITY(16) failed
sd 11:0:0:0: [sde]  Result: hostbyte=DID_ABORT driverbyte=DRIVER_OK
sd 11:0:0:0: [sde] Sense not available.
sd 11:0:0:0: [sde] Using 0x as device size
sd 11:0:0:0: [sde] 4294967296 512-byte logical blocks: (2.19 TB/2.00 TiB)
sd 11:0:0:0: [sde] Write Protect is off
sd 11:0:0:0: [sde] Mode Sense: 9b 00 00 08
sd 11:0:0:0: [sde] Write cache: enabled, read cache: enabled, doesn't
support DPO or FUA
sd 11:0:0:0: [sde] Very big device. Trying to use READ CAPACITY(16).
sd 11:0:0:0: [sde] READ CAPACITY(16) failed
sd 11:0:0:0: [sde]  Result: hostbyte=DID_ABORT driverbyte=DRIVER_OK
sd 11:0:0:0: [sde] Sense not available.
sd 11:0:0:0: [sde] Using 0x as device size
sd 11:0:0:0: Attached scsi generic sg5 type 0
sde: unknown partition table
sd 11:0:0:0: [sde] Very big device. Trying to use READ CAPACITY(16).
sd 11:0:0:0: [sde] READ CAPACITY(16) failed
sd 11:0:0:0: [sde]  Result: hostbyte=DID_ABORT driverbyte=DRIVER_OK
sd 11:0:0:0: [sde] Sense not available.
sd 11:0:0:0: [sde] Using 0x as device size
sd 11:0:0:0: [sde] Attached SCSI disk


CAN ANYONE PLEASE recommend a working Ultra320 SCSI controller
with CDB-16 support ?


2017-04-27 18:33 GMT+03:00 Alexander Voropay :
> Hi!
>
> I have a nasty bug with ‘sym53c8xx_2’ SCSI driver. I’m trying to
> attach a large (>2Tb) storage to this controller but it does not work.
> Seems nobody tested such combination before...
>
>
> My SCSI controller is noname OEM for Intel, PCI-X card with SYN53C1010 chip.
> Storage: Infortrend A24U-G2421-1 (upto 24 SATA disks to Ulra-320 SCSI 
> channel).
> I have 11x1Tb  RAID5 as one large disk with 10Tb in size.
> My Linux is RHEL 6, kernel "kernel-2.6.32-696.1.1.el6.x86_64".
>
> Physical SCSI link is OK, full Ultra-160, no physical/parity errors
> e.t.c. BUT IT DOES NOT WORK due to a software error.
>
> As it is known, Linux’s ‘sd’ uses CDB-16 command set for large SCSI
> disks. On the other hand ‘sym53c8xx_2’ driver “Utilizes SCRIPTS
> Load/Store command” and “Handles Phase Mismatch from SCRIPTS”. Seems
> there is a software error between driver and “sd”. As a result ALL
> disk operations are damn slow and gives a phase error in the “dmesg”:
> sd 4:0:0:0: phase change 2-7 16@37a9af60 resid=10.
> sd 4:0:0:0: phase change 2-7 16@37a9af60 resid=10.
> sd 4:0:0:0: phase change 2-7 16@37a9af60 resid=10.
> e.t.c.
>
> Another problem: “sd” incorrectly determines a disk size. Note a
> “phase change” errors after and before “capacity change”. As a result
> “sd” switches to CDB-10 and maximum disk size limited by 2Tb
>
> sym53c8xx : 05:01.0: PCI INT A disabled
> sym53c8xx : 05:01.0: PCI INT A -> GSI 24 (level, low) -> IRQ 24
> sym0: <1010-66> rev 0x1 at pci : 05:01.0 irq 24
> sym0: Symbios NVRAM, ID 7, Fast-80, LVD, parity checking
> sym0: open drain IRQ line driver, using on-chip SRAM
> sym0: using LOAD/STORE-based firmware.
> sym0: handling phase mismatch from SCRIPTS.
> sym0: SCSI BUS has been reset.
> scsi4 : sym-2.2.3
> scsi 4:0:0:0: Direct-Access IFT  A24U-G2421-1 347R PQ: 0 ANSI: 5
> scsi target4:0:0: tagged command queuing enabled, command queue depth 16.
> scsi target4:0:0: Beginning Domain Validation
> scsi target4:0:0: FAST-80 WIDE SCSI 160.0 MB/s DT (12.5 ns, offset 62)
> scsi target4:0:0: Ending Domain Validation
> sd 4:0:0:0: phase change 2-7 16@37a9af60 resid=10.
> sd 4:0:0:0: [sde] 4294967296 512-byte logical blocks: (2.19 TB/2.00 TiB)
> sd 4:0:0:0: [sde] Write Protect is off
> sd 4:0:0:0: [sde] Mode Sense: 9b 00 00 08
> sd 4:0:0:0: [sde] Write cache: enabled, read cache: enabled, doesn't
> support DPO or FUA
> sd 4:0:0:0: phase change 2-7 16@37a9af60 resid=10.
> sd 4:0:0:0: Attached scsi generic sg5 type 0
> sd 4:0:0:0: [sde] 19529912320 512-byte logical blocks: (9.99 TB/9.09 TiB)
> sde: detected capacity change from 219902322 to 315107840
> sde: unknown partition table
> sd 4:0:0:0: phase change 2-7 16@37a9af60 resid=10.
> sd 4:0:0:0: [sde] 4294967296 512-byte logical blocks: (2.19 TB/2.00 TiB)
> sd 4:0:0:0: [sde] Attached SCSI disk
>
> As a result ‘parted’ does not work too, it hangs on 

[PATCH 09/15] lpfc: Fix return value of board_mode store routine in case of online failure

2017-05-31 Thread James Smart
On hbacmd reset failure, observing wrong string "nline" in
kernel log.

On failure, non negative value (1) is returned from sysfs store
routine. It is interpreted as count by kernel and store routine
is called again with the remaining characters as input.

Fix: Return negative error code (-EIO) in case of failure.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_attr.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index eb33473cbc62..8eee39de15f7 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -1351,6 +1351,8 @@ lpfc_board_mode_store(struct device *dev, struct 
device_attribute *attr,
goto board_mode_out;
}
wait_for_completion(_compl);
+   if (status)
+   status = -EIO;
} else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0)
status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
else if (strncmp(buf, "warm", sizeof("warm") - 1) == 0)
-- 
2.11.0



[PATCH 00/15] lpfc updates for 11.4.0.0

2017-05-31 Thread James Smart
This patch set provides a number of bug fixes, code cleanups, and error
handling in lpfc.

The patches were cut against the Martin's 4.12/scsi-fixes tree.
There are no outside dependencies. The patches should merge via
Martin's tree. 

James Smart (15):
  lpfc: Add nvme initiator devloss support
  lpfc: Fix transition nvme-i rport handling to nport only.
  lpfc: Fix nvme port role handling in sysfs and debugfs handlers.
  lpfc: Add changes to assist in NVMET debugging
  lpfc: Fix Lun Priority level shown as NA
  lpfc: Fix nvmet node ref count handling
  lpfc: Fix Port going offline after multiple resets.
  lpfc: Fix counters so outstandng NVME IO count is accurate
  lpfc: Fix return value of board_mode store routine in case of online
failure
  lpfc: Fix crash on powering off BFS VM with passthrough device
  lpfc: Fix System panic after loading the driver
  lpfc: Null pointer dereference when log_verbose is set to 0x
  lpfc: Fix PRLI retry handling when target rejects it.
  lpfc: Fix vports not logging into target
  lpfc: update to revision to 11.4.0.0

 drivers/scsi/lpfc/lpfc.h |  20 ++--
 drivers/scsi/lpfc/lpfc_attr.c|  74 --
 drivers/scsi/lpfc/lpfc_ct.c  |  31 +++---
 drivers/scsi/lpfc/lpfc_debugfs.c |  72 --
 drivers/scsi/lpfc/lpfc_els.c |  17 +++-
 drivers/scsi/lpfc/lpfc_hbadisc.c |  14 +--
 drivers/scsi/lpfc/lpfc_init.c|  21 +++-
 drivers/scsi/lpfc/lpfc_nvme.c| 178 -
 drivers/scsi/lpfc/lpfc_nvme.h|   2 -
 drivers/scsi/lpfc/lpfc_nvmet.c   | 208 +++
 drivers/scsi/lpfc/lpfc_nvmet.h   |  14 +--
 drivers/scsi/lpfc/lpfc_scsi.c|  19 +++-
 drivers/scsi/lpfc/lpfc_sli.c |  19 +++-
 drivers/scsi/lpfc/lpfc_sli4.h|   4 +-
 drivers/scsi/lpfc/lpfc_version.h |   2 +-
 15 files changed, 398 insertions(+), 297 deletions(-)

-- 
2.11.0



[PATCH 07/15] lpfc: Fix Port going offline after multiple resets.

2017-05-31 Thread James Smart
Observing lpfc port down after issuing hbacmd reset command

Failure in posting SGL buffers. If there is only one SGL buffer
and rrq is valid for its XRI, we are rightly returning NULL but
not adding the buffer back to the SGL list. So, number of buffers
become less than total count and repost fails during reset.

Add SGL buffer back to list before returning NULL.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_sli.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index d6b184839bc2..e81fa7d4deb5 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -968,6 +968,7 @@ __lpfc_sli_get_els_sglq(struct lpfc_hba *phba, struct 
lpfc_iocbq *piocbq)
list_remove_head(lpfc_els_sgl_list, sglq,
struct lpfc_sglq, list);
if (sglq == start_sglq) {
+   list_add_tail(>list, lpfc_els_sgl_list);
sglq = NULL;
break;
} else
-- 
2.11.0



[PATCH 15/15] lpfc: update to revision to 11.4.0.0

2017-05-31 Thread James Smart
Set lpfc driver revision to 11.4.0.0

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 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 c2653244221c..067c9e8a4b2d 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.2.0.14"
+#define LPFC_DRIVER_VERSION "11.4.0.0"
 #define LPFC_DRIVER_NAME   "lpfc"
 
 /* Used for SLI 2/3 */
-- 
2.11.0



[PATCH 10/15] lpfc: Fix crash on powering off BFS VM with passthrough device

2017-05-31 Thread James Smart
Null pointer dereference when BFS VM is powered off

The driver incorrectly uses sli3_ring on SLI-4 adapters

Use the correct ring structure based on sli_rev

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_sli.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index e81fa7d4deb5..c4ceef69bd6b 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -10951,6 +10951,7 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct 
lpfc_sli_ring *pring,
struct lpfc_hba *phba = vport->phba;
struct lpfc_iocbq *iocbq;
struct lpfc_iocbq *abtsiocb;
+   struct lpfc_sli_ring *pring_s4;
IOCB_t *cmd = NULL;
int errcnt = 0, ret_val = 0;
int i;
@@ -11004,8 +11005,15 @@ lpfc_sli_abort_iocb(struct lpfc_vport *vport, struct 
lpfc_sli_ring *pring,
 
/* Setup callback routine and issue the command. */
abtsiocb->iocb_cmpl = lpfc_sli_abort_fcp_cmpl;
-   ret_val = lpfc_sli_issue_iocb(phba, pring->ringno,
- abtsiocb, 0);
+   if (phba->sli_rev == LPFC_SLI_REV4) {
+   pring_s4 = lpfc_sli4_calc_ring(phba, iocbq);
+   if (!pring_s4)
+   continue;
+   ret_val = lpfc_sli_issue_iocb(phba, pring_s4->ringno,
+ abtsiocb, 0);
+   } else
+   ret_val = lpfc_sli_issue_iocb(phba, pring->ringno,
+ abtsiocb, 0);
if (ret_val == IOCB_ERROR) {
lpfc_sli_release_iocbq(phba, abtsiocb);
errcnt++;
-- 
2.11.0



[PATCH 04/15] lpfc: Add changes to assist in NVMET debugging

2017-05-31 Thread James Smart
Inconsistent error messages and context state checks

Context state sanity checks were not accurate or
inconsistent in the code paths.

Separated LS context states from FCP.
Added and modified context state sanity checks.
Use context state to determine if a sol or unsol ABORT is needed.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_nvmet.c | 208 -
 drivers/scsi/lpfc/lpfc_nvmet.h |  14 +--
 2 files changed, 151 insertions(+), 71 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c
index f94294b77b7b..e062c317e2f6 100644
--- a/drivers/scsi/lpfc/lpfc_nvmet.c
+++ b/drivers/scsi/lpfc/lpfc_nvmet.c
@@ -112,6 +112,15 @@ lpfc_nvmet_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct 
lpfc_iocbq *cmdwqe,
 
status = bf_get(lpfc_wcqe_c_status, wcqe);
result = wcqe->parameter;
+   ctxp = cmdwqe->context2;
+
+   if (ctxp->state != LPFC_NVMET_STE_LS_RSP || ctxp->entry_cnt != 2) {
+   lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+   "6410 NVMET LS cmpl state mismatch IO x%x: "
+   "%d %d\n",
+   ctxp->oxid, ctxp->state, ctxp->entry_cnt);
+   }
+
if (!phba->targetport)
goto out;
 
@@ -123,15 +132,14 @@ lpfc_nvmet_xmt_ls_rsp_cmp(struct lpfc_hba *phba, struct 
lpfc_iocbq *cmdwqe,
atomic_inc(>xmt_ls_rsp_cmpl);
 
 out:
-   ctxp = cmdwqe->context2;
rsp = >ctx.ls_req;
 
lpfc_nvmeio_data(phba, "NVMET LS  CMPL: xri x%x stat x%x result x%x\n",
 ctxp->oxid, status, result);
 
lpfc_printf_log(phba, KERN_INFO, LOG_NVME_DISC,
-   "6038 %s: Entrypoint: ctx %p status %x/%x\n", __func__,
-   ctxp, status, result);
+   "6038 NVMET LS rsp cmpl: %d %d oxid x%x\n",
+   status, result, ctxp->oxid);
 
lpfc_nlp_put(cmdwqe->context1);
cmdwqe->context2 = NULL;
@@ -173,6 +181,12 @@ lpfc_nvmet_ctxbuf_post(struct lpfc_hba *phba, struct 
lpfc_nvmet_ctxbuf *ctx_buf)
ctxp->txrdy = NULL;
ctxp->txrdy_phys = 0;
}
+
+   if (ctxp->state == LPFC_NVMET_STE_FREE) {
+   lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+   "6411 NVMET free, already free IO x%x: %d %d\n",
+   ctxp->oxid, ctxp->state, ctxp->entry_cnt);
+   }
ctxp->state = LPFC_NVMET_STE_FREE;
 
spin_lock_irqsave(>sli4_hba.nvmet_io_wait_lock, iflag);
@@ -580,8 +594,17 @@ lpfc_nvmet_xmt_ls_rsp(struct nvmet_fc_target_port *tgtport,
int rc;
 
lpfc_printf_log(phba, KERN_INFO, LOG_NVME_DISC,
-   "6023 %s: Entrypoint ctx %p %p\n", __func__,
-   ctxp, tgtport);
+   "6023 NVMET LS rsp oxid x%x\n", ctxp->oxid);
+
+   if ((ctxp->state != LPFC_NVMET_STE_LS_RCV) ||
+   (ctxp->entry_cnt != 1)) {
+   lpfc_printf_log(phba, KERN_ERR, LOG_NVME_IOERR,
+   "6412 NVMET LS rsp state mismatch "
+   "oxid x%x: %d %d\n",
+   ctxp->oxid, ctxp->state, ctxp->entry_cnt);
+   }
+   ctxp->state = LPFC_NVMET_STE_LS_RSP;
+   ctxp->entry_cnt++;
 
nvmewqeq = lpfc_nvmet_prep_ls_wqe(phba, ctxp, rsp->rspdma,
  rsp->rsplen);
@@ -751,15 +774,14 @@ lpfc_nvmet_xmt_fcp_abort(struct nvmet_fc_target_port 
*tgtport,
unsigned long flags;
 
lpfc_printf_log(phba, KERN_INFO, LOG_NVME_ABTS,
-   "6103 Abort op: oxri x%x flg x%x cnt %d\n",
-   ctxp->oxid, ctxp->flag, ctxp->entry_cnt);
+   "6103 NVMET Abort op: oxri x%x flg x%x ste %d\n",
+   ctxp->oxid, ctxp->flag, ctxp->state);
 
-   lpfc_nvmeio_data(phba, "NVMET FCP ABRT: "
-"xri x%x flg x%x cnt x%x\n",
-ctxp->oxid, ctxp->flag, ctxp->entry_cnt);
+   lpfc_nvmeio_data(phba, "NVMET FCP ABRT: xri x%x flg x%x ste x%x\n",
+ctxp->oxid, ctxp->flag, ctxp->state);
 
atomic_inc(_nvmep->xmt_fcp_abort);
-   ctxp->entry_cnt++;
+
spin_lock_irqsave(>ctxlock, flags);
 
/* Since iaab/iaar are NOT set, we need to check
@@ -770,12 +792,17 @@ lpfc_nvmet_xmt_fcp_abort(struct nvmet_fc_target_port 
*tgtport,
return;
}
ctxp->flag |= LPFC_NVMET_ABORT_OP;
-   if (ctxp->flag & LPFC_NVMET_IO_INP)
-   lpfc_nvmet_sol_fcp_issue_abort(phba, ctxp, ctxp->sid,
-  ctxp->oxid);
-   else
+
+   /* An state of LPFC_NVMET_STE_RCV means we have just received
+* the NVME command and have not started 

[PATCH 13/15] lpfc: Fix PRLI retry handling when target rejects it.

2017-05-31 Thread James Smart
The nvmet driver was rejecting the initiator's PRLI because
its reg_rpi for the PLOGI was still outstanding.  The initiator
would resend the PRLI without delay and get the same answer.
The PRLI retries would exhaust causing the nvme initiator to
set the nvmet ndlp to UNMAPPED.

The driver's lpfc_els_retry handler did not have a policy for an
LS_RJT with explanation CMD_IN_PROGRESS for PRLI or NVME_PRLI.
This caused the delay to remain at 0 but retry set 1.

Fix: When the ELS response is LS_RJT, TPC and the command was PRLI
or NVME_PRLI, just set the delay to 1000 mS to get a 1 second
delay on the PRLI retry.  This was enough to allow the REG_RPI to
complete at the target.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_els.c | 17 ++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index 8e532b39ae93..a140318d6159 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -3332,6 +3332,19 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq 
*cmdiocb,
 */
switch (stat.un.b.lsRjtRsnCode) {
case LSRJT_UNABLE_TPC:
+   /* The driver has a VALID PLOGI but the rport has
+* rejected the PRLI - can't do it now.  Delay
+* for 1 second and try again - don't care about
+* the explanation.
+*/
+   if (cmd == ELS_CMD_PRLI || cmd == ELS_CMD_NVMEPRLI) {
+   delay = 1000;
+   maxretry = lpfc_max_els_tries + 1;
+   retry = 1;
+   break;
+   }
+
+   /* Legacy bug fix code for targets with PLOGI delays. */
if (stat.un.b.lsRjtRsnCodeExp ==
LSEXP_CMD_IN_PROGRESS) {
if (cmd == ELS_CMD_PLOGI) {
@@ -3350,9 +3363,7 @@ lpfc_els_retry(struct lpfc_hba *phba, struct lpfc_iocbq 
*cmdiocb,
retry = 1;
break;
}
-   if ((cmd == ELS_CMD_PLOGI) ||
-   (cmd == ELS_CMD_PRLI) ||
-   (cmd == ELS_CMD_NVMEPRLI)) {
+   if (cmd == ELS_CMD_PLOGI) {
delay = 1000;
maxretry = lpfc_max_els_tries + 1;
retry = 1;
-- 
2.11.0



[PATCH 14/15] lpfc: Fix vports not logging into target

2017-05-31 Thread James Smart
vports cannot login to target.

For vports, lpfc_nodelist is allocated for targets only on
completion of GFF_ID command. Driver checks if lpfc_nodelist
exists for target before sending GFF_ID. So, GFF_ID and
PLOGI are not sent.

As mentioned by the comment in lpfc_prep_node_fc4type() routine,
do not send GFF_ID only if this NPortID is previously identified
as FCP target. Send GFF_ID if it is a newly identified remote
port from GID_FT response.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_ct.c | 31 ++-
 1 file changed, 14 insertions(+), 17 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c
index f2cd19c6c2df..2853a6d352f8 100644
--- a/drivers/scsi/lpfc/lpfc_ct.c
+++ b/drivers/scsi/lpfc/lpfc_ct.c
@@ -503,26 +503,23 @@ lpfc_prep_node_fc4type(struct lpfc_vport *vport, uint32_t 
Did, uint8_t fc4_type)
Did, vport->fc_flag, vport->fc_rscn_id_cnt);
 
/*
-* This NPortID was previously a FCP target,
+* This NPortID was previously a FCP/NVMe target,
 * Don't even bother to send GFF_ID.
 */
ndlp = lpfc_findnode_did(vport, Did);
-   if (ndlp && NLP_CHK_NODE_ACT(ndlp))
-   ndlp->nlp_fc4_type = fc4_type;
-
-   if (ndlp && NLP_CHK_NODE_ACT(ndlp)) {
-   ndlp->nlp_fc4_type = fc4_type;
-
-   if (ndlp->nlp_type & NLP_FCP_TARGET)
-   lpfc_setup_disc_node(vport, Did);
-
-   else if (lpfc_ns_cmd(vport, SLI_CTNS_GFF_ID,
-   0, Did) == 0)
-   vport->num_disc_nodes++;
-
-   else
-   lpfc_setup_disc_node(vport, Did);
-   }
+   if (ndlp && NLP_CHK_NODE_ACT(ndlp) &&
+   (ndlp->nlp_type &
+   (NLP_FCP_TARGET | NLP_NVME_TARGET))) {
+   if (fc4_type == FC_TYPE_FCP)
+   ndlp->nlp_fc4_type |= NLP_FC4_FCP;
+   if (fc4_type == FC_TYPE_NVME)
+   ndlp->nlp_fc4_type |= NLP_FC4_NVME;
+   lpfc_setup_disc_node(vport, Did);
+   } else if (lpfc_ns_cmd(vport, SLI_CTNS_GFF_ID,
+  0, Did) == 0)
+   vport->num_disc_nodes++;
+   else
+   lpfc_setup_disc_node(vport, Did);
} else {
lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_CT,
"Skip2 GID_FTrsp: did:x%x flg:x%x cnt:%d",
-- 
2.11.0



[PATCH 06/15] lpfc: Fix nvmet node ref count handling

2017-05-31 Thread James Smart
When unloading the driver, the NVMET driver would wait
the full 30 seconds for its UNMAPPED initiator node to
get removed before continuing with the unload process.
NVMEI worked correctly.

For each rport put into UNMAPPED or MAPPED state by NVMET,
the driver puts a reference on the NDLP.  The difference is
that NVMEI has a unregister call for its rports and the extra
reference is removed in the unregister process.  For NVMET,
the driver has to remove the reference explicitly when dropping
out of UNMAPPED or MAPPED because there is no unregister call.

Add a call to lpfc_nlp_put on the ndlp when NVMET and the old
state was UNMAPPED or MAPPED.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_hbadisc.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 055fedd761ea..db2d0e692ddf 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -4167,14 +4167,14 @@ lpfc_nlp_state_cleanup(struct lpfc_vport *vport, struct 
lpfc_nodelist *ndlp,
lpfc_unregister_remote_port(ndlp);
}
 
-   /* Notify the NVME transport of this rport's loss on the
-* Initiator.  For NVME Target, should upcall transport
-* in the else clause when API available.
-*/
if (ndlp->nlp_fc4_type & NLP_FC4_NVME) {
vport->phba->nport_event_cnt++;
if (vport->phba->nvmet_support == 0)
+   /* Start devloss */
lpfc_nvme_unregister_port(vport, ndlp);
+   else
+   /* NVMET has no upcall. */
+   lpfc_nlp_put(ndlp);
}
}
 
-- 
2.11.0



[PATCH 01/15] lpfc: Add nvme initiator devloss support

2017-05-31 Thread James Smart
Add nvme initiator devloss support

The existing implementation was based on no devloss behavior
in the transport (e.g. immediate teardown) so code didn't
properly handle delayed nvme rport device unregister calls.
In addition, the driver was not correctly cycling the rport
port role for each register-unregister-reregister process.

This patch does the following:
Rework the code to properly handle rport device unregister
calls and potential re-allocation of the remoteport structure
if the port comes back in under dev_loss_tmo.

Correct code that was incorrectly cycling the rport
port role for each register-unregister-reregister process.

Prep the code to enable calling the nvme_fc transport api
to dynamically update dev_loss_tmo when the scsi sysfs interface
changes it.

Memset the rpinfo structure in the registration call to enforce
"accept nvme transport defaults" in the registration call.  Driver
parameters do influence the dev_loss_tmo transport setting
dynamically.

Simplifies the register function: the driver was incorrectly
searching its local rport list to determine resume or new semantics,
which is not valid as the transport already handles this.  The rport
was resumed if the rport handed back matches the ndlp->nrport pointer.
Otherwise, devloss fired and the ndlp's nrport is NULL.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_attr.c |   7 ++-
 drivers/scsi/lpfc/lpfc_nvme.c | 141 --
 2 files changed, 57 insertions(+), 91 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index bb2d9e238225..37f258fcf6d4 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -3198,9 +3198,12 @@ lpfc_update_rport_devloss_tmo(struct lpfc_vport *vport)
 
shost = lpfc_shost_from_vport(vport);
spin_lock_irq(shost->host_lock);
-   list_for_each_entry(ndlp, >fc_nodes, nlp_listp)
-   if (NLP_CHK_NODE_ACT(ndlp) && ndlp->rport)
+   list_for_each_entry(ndlp, >fc_nodes, nlp_listp) {
+   if (!NLP_CHK_NODE_ACT(ndlp))
+   continue;
+   if (ndlp->rport)
ndlp->rport->dev_loss_tmo = vport->cfg_devloss_tmo;
+   }
spin_unlock_irq(shost->host_lock);
 }
 
diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index 8008c8205fb6..70675fd7d884 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -186,13 +186,13 @@ lpfc_nvme_remoteport_delete(struct nvme_fc_remote_port 
*remoteport)
 
/* Remove this rport from the lport's list - memory is owned by the
 * transport. Remove the ndlp reference for the NVME transport before
-* calling state machine to remove the node, this is devloss = 0
-* semantics.
+* calling state machine to remove the node.
 */
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC,
"6146 remoteport delete complete %p\n",
remoteport);
list_del(>list);
+   ndlp->nrport = NULL;
lpfc_nlp_put(ndlp);
 
  rport_err:
@@ -1466,7 +1466,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port 
*pnvme_lport,
 
/* The remote node has to be ready to send an abort. */
if ((ndlp->nlp_state != NLP_STE_MAPPED_NODE) &&
-   !(ndlp->nlp_type & NLP_NVME_TARGET)) {
+   (ndlp->nlp_type & NLP_NVME_TARGET)) {
lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_ABTS,
 "6048 rport %p, DID x%06x not ready for "
 "IO. State x%x, Type x%x\n",
@@ -2340,69 +2340,44 @@ lpfc_nvme_register_port(struct lpfc_vport *vport, 
struct lpfc_nodelist *ndlp)
localport = vport->localport;
lport = (struct lpfc_nvme_lport *)localport->private;
 
-   if (ndlp->nlp_type & (NLP_NVME_TARGET | NLP_NVME_INITIATOR)) {
-
-   /* The driver isn't expecting the rport wwn to change
-* but it might get a different DID on a different
-* fabric.
+   /* NVME rports are not preserved across devloss.
+* Just register this instance.  Note, rpinfo->dev_loss_tmo
+* is left 0 to indicate accept transport defaults.  The
+* driver communicates port role capabilities consistent
+* with the PRLI response data.
+*/
+   memset(, 0, sizeof(struct nvme_fc_port_info));
+   rpinfo.port_id = ndlp->nlp_DID;
+   if (ndlp->nlp_type & NLP_NVME_TARGET)
+   rpinfo.port_role |= FC_PORT_ROLE_NVME_TARGET;
+   if (ndlp->nlp_type & NLP_NVME_INITIATOR)
+   rpinfo.port_role |= FC_PORT_ROLE_NVME_INITIATOR;
+
+   if (ndlp->nlp_type & NLP_NVME_DISCOVERY)
+   rpinfo.port_role |= FC_PORT_ROLE_NVME_DISCOVERY;
+
+   rpinfo.port_name = wwn_to_u64(ndlp->nlp_portname.u.wwn);
+   

[PATCH 02/15] lpfc: Fix transition nvme-i rport handling to nport only.

2017-05-31 Thread James Smart
As the devloss API was implemented in the
nvmei driver, an evaluation of the nvme transport
and the lpfc driver showed dual management of the
rports.  This creates a bug possibility when the
thread count and SAN size increases.

The nvmei driver code was based on a very
early transport and was not revisited until the
devloss API was introduced.

Remove the listhead in the driver's rport
data structure and the listhead in the driver's
lport data structure.  Remove all rport_list
traversal.  Convert the driver to use the
nrport (nvme rport) pointer that is now NULL
or nonNULL depending on a devloss action.  Convert
debugfs and nvme_info in sysfs to use the fc_nodes
list in the vport.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_attr.c| 11 ++-
 drivers/scsi/lpfc/lpfc_debugfs.c | 10 +-
 drivers/scsi/lpfc/lpfc_nvme.c| 18 --
 drivers/scsi/lpfc/lpfc_nvme.h|  2 --
 4 files changed, 11 insertions(+), 30 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 37f258fcf6d4..6d9b83cd82a2 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -148,8 +148,7 @@ lpfc_nvme_info_show(struct device *dev, struct 
device_attribute *attr,
struct lpfc_hba   *phba = vport->phba;
struct lpfc_nvmet_tgtport *tgtp;
struct nvme_fc_local_port *localport;
-   struct lpfc_nvme_lport *lport;
-   struct lpfc_nvme_rport *rport;
+   struct lpfc_nodelist *ndlp;
struct nvme_fc_remote_port *nrport;
char *statep;
int len = 0;
@@ -265,7 +264,6 @@ lpfc_nvme_info_show(struct device *dev, struct 
device_attribute *attr,
len = snprintf(buf, PAGE_SIZE, "NVME Initiator Enabled\n");
 
spin_lock_irq(shost->host_lock);
-   lport = (struct lpfc_nvme_lport *)localport->private;
 
/* Port state is only one of two values for now. */
if (localport->port_id)
@@ -281,9 +279,12 @@ lpfc_nvme_info_show(struct device *dev, struct 
device_attribute *attr,
wwn_to_u64(vport->fc_nodename.u.wwn),
localport->port_id, statep);
 
-   list_for_each_entry(rport, >rport_list, list) {
+   list_for_each_entry(ndlp, >fc_nodes, nlp_listp) {
+   if (!ndlp->nrport)
+   continue;
+
/* local short-hand pointer. */
-   nrport = rport->remoteport;
+   nrport = ndlp->nrport->remoteport;
 
/* Port state is only one of two values for now. */
switch (nrport->port_state) {
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index 4bcb92c844ca..d71bda24b08e 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -550,8 +550,6 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char 
*buf, int size)
struct lpfc_nodelist *ndlp;
unsigned char *statep;
struct nvme_fc_local_port *localport;
-   struct lpfc_nvme_lport *lport;
-   struct lpfc_nvme_rport *rport;
struct lpfc_nvmet_tgtport *tgtp;
struct nvme_fc_remote_port *nrport;
 
@@ -660,7 +658,6 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char 
*buf, int size)
goto out_exit;
 
spin_lock_irq(shost->host_lock);
-   lport = (struct lpfc_nvme_lport *)localport->private;
 
/* Port state is only one of two values for now. */
if (localport->port_id)
@@ -673,9 +670,12 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char 
*buf, int size)
localport->port_id, statep);
 
len += snprintf(buf + len, size - len, "\tRport List:\n");
-   list_for_each_entry(rport, >rport_list, list) {
+   list_for_each_entry(ndlp, >fc_nodes, nlp_listp) {
/* local short-hand pointer. */
-   nrport = rport->remoteport;
+   if (!ndlp->nrport)
+   continue;
+
+   nrport = ndlp->nrport->remoteport;
 
/* Port state is only one of two values for now. */
switch (nrport->port_state) {
diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index 70675fd7d884..ede42411e57b 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -191,7 +191,6 @@ lpfc_nvme_remoteport_delete(struct nvme_fc_remote_port 
*remoteport)
lpfc_printf_vlog(vport, KERN_INFO, LOG_NVME_DISC,
"6146 remoteport delete complete %p\n",
remoteport);
-   list_del(>list);
ndlp->nrport = NULL;
lpfc_nlp_put(ndlp);
 
@@ -2208,7 +2207,6 @@ lpfc_nvme_create_localport(struct lpfc_vport *vport)
lport = (struct lpfc_nvme_lport *)localport->private;
vport->localport = localport;
lport->vport = vport;
-

[PATCH 12/15] lpfc: Null pointer dereference when log_verbose is set to 0xffffffff

2017-05-31 Thread James Smart
Kernel panic when log_verbose is set to 0x

phba->pport is dereferenced before it is initialized

Fix: Do not dereference phba->pport if it is NULL

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_sli.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index c4ceef69bd6b..fb4c708ae747 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -7513,7 +7513,8 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, 
LPFC_MBOXQ_t *pmbox,
"(%d):0308 Mbox cmd issue - BUSY Data: "
"x%x x%x x%x x%x\n",
pmbox->vport ? pmbox->vport->vpi : 0xff,
-   mbx->mbxCommand, phba->pport->port_state,
+   mbx->mbxCommand,
+   phba->pport ? phba->pport->port_state : 0xff,
psli->sli_flag, flag);
 
psli->slistat.mbox_busy++;
@@ -7565,7 +7566,8 @@ lpfc_sli_issue_mbox_s3(struct lpfc_hba *phba, 
LPFC_MBOXQ_t *pmbox,
"(%d):0309 Mailbox cmd x%x issue Data: x%x x%x "
"x%x\n",
pmbox->vport ? pmbox->vport->vpi : 0,
-   mbx->mbxCommand, phba->pport->port_state,
+   mbx->mbxCommand,
+   phba->pport ? phba->pport->port_state : 0xff,
psli->sli_flag, flag);
 
if (mbx->mbxCommand != MBX_HEARTBEAT) {
-- 
2.11.0



[PATCH 08/15] lpfc: Fix counters so outstandng NVME IO count is accurate

2017-05-31 Thread James Smart
NVME FC counters don't reflect actual results

Since counters are not atomic, or protected by a lock,
the values often get screwed up.

Make them atomic, like NVMET.
Fix up sysfs and debugfs display accordingly
Added Outstanding IOs to stats display

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc.h | 20 ++--
 drivers/scsi/lpfc/lpfc_attr.c| 32 +---
 drivers/scsi/lpfc/lpfc_debugfs.c | 30 +-
 drivers/scsi/lpfc/lpfc_init.c| 10 ++
 drivers/scsi/lpfc/lpfc_nvme.c| 19 +--
 drivers/scsi/lpfc/lpfc_scsi.c| 19 ++-
 6 files changed, 89 insertions(+), 41 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc.h b/drivers/scsi/lpfc/lpfc.h
index f2c0ba6ced78..a9d73728a68c 100644
--- a/drivers/scsi/lpfc/lpfc.h
+++ b/drivers/scsi/lpfc/lpfc.h
@@ -913,16 +913,16 @@ struct lpfc_hba {
/*
 * stat  counters
 */
-   uint64_t fc4ScsiInputRequests;
-   uint64_t fc4ScsiOutputRequests;
-   uint64_t fc4ScsiControlRequests;
-   uint64_t fc4ScsiIoCmpls;
-   uint64_t fc4NvmeInputRequests;
-   uint64_t fc4NvmeOutputRequests;
-   uint64_t fc4NvmeControlRequests;
-   uint64_t fc4NvmeIoCmpls;
-   uint64_t fc4NvmeLsRequests;
-   uint64_t fc4NvmeLsCmpls;
+   atomic_t fc4ScsiInputRequests;
+   atomic_t fc4ScsiOutputRequests;
+   atomic_t fc4ScsiControlRequests;
+   atomic_t fc4ScsiIoCmpls;
+   atomic_t fc4NvmeInputRequests;
+   atomic_t fc4NvmeOutputRequests;
+   atomic_t fc4NvmeControlRequests;
+   atomic_t fc4NvmeIoCmpls;
+   atomic_t fc4NvmeLsRequests;
+   atomic_t fc4NvmeLsCmpls;
 
uint64_t bg_guard_err_cnt;
uint64_t bg_apptag_err_cnt;
diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 200a614bb540..eb33473cbc62 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -150,6 +150,7 @@ lpfc_nvme_info_show(struct device *dev, struct 
device_attribute *attr,
struct nvme_fc_local_port *localport;
struct lpfc_nodelist *ndlp;
struct nvme_fc_remote_port *nrport;
+   uint64_t data1, data2, data3, tot;
char *statep;
int len = 0;
 
@@ -244,11 +245,18 @@ lpfc_nvme_info_show(struct device *dev, struct 
device_attribute *attr,
atomic_read(>xmt_abort_rsp),
atomic_read(>xmt_abort_rsp_error));
 
+   spin_lock(>sli4_hba.nvmet_io_lock);
+   tot = phba->sli4_hba.nvmet_xri_cnt -
+   phba->sli4_hba.nvmet_ctx_cnt;
+   spin_unlock(>sli4_hba.nvmet_io_lock);
+
len += snprintf(buf + len, PAGE_SIZE - len,
-   "IO_CTX: %08x outstanding %08x total %x",
+   "IO_CTX: %08x  WAIT: cur %08x tot %08x\n"
+   "CTX Outstanding %08llx\n",
phba->sli4_hba.nvmet_ctx_cnt,
phba->sli4_hba.nvmet_io_wait_cnt,
-   phba->sli4_hba.nvmet_io_wait_total);
+   phba->sli4_hba.nvmet_io_wait_total,
+   tot);
 
len +=  snprintf(buf+len, PAGE_SIZE-len, "\n");
return len;
@@ -337,19 +345,21 @@ lpfc_nvme_info_show(struct device *dev, struct 
device_attribute *attr,
 
len += snprintf(buf + len, PAGE_SIZE - len, "\nNVME Statistics\n");
len += snprintf(buf+len, PAGE_SIZE-len,
-   "LS: Xmt %016llx Cmpl %016llx\n",
-   phba->fc4NvmeLsRequests,
-   phba->fc4NvmeLsCmpls);
-
+   "LS: Xmt %016x Cmpl %016x\n",
+   atomic_read(>fc4NvmeLsRequests),
+   atomic_read(>fc4NvmeLsCmpls));
+
+   tot = atomic_read(>fc4NvmeIoCmpls);
+   data1 = atomic_read(>fc4NvmeInputRequests);
+   data2 = atomic_read(>fc4NvmeOutputRequests);
+   data3 = atomic_read(>fc4NvmeControlRequests);
len += snprintf(buf+len, PAGE_SIZE-len,
"FCP: Rd %016llx Wr %016llx IO %016llx\n",
-   phba->fc4NvmeInputRequests,
-   phba->fc4NvmeOutputRequests,
-   phba->fc4NvmeControlRequests);
+   data1, data2, data3);
 
len += snprintf(buf+len, PAGE_SIZE-len,
-   "Cmpl %016llx\n", phba->fc4NvmeIoCmpls);
-
+   "Cmpl %016llx Outstanding %016llx\n",
+   tot, (data1 + data2 + data3) - tot);
return len;
 }
 
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index dd8598bc50f3..6089690fb345 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ 

[PATCH 11/15] lpfc: Fix System panic after loading the driver

2017-05-31 Thread James Smart
System panic with general protection fault during driver load

The driver uses a static array sli4_hba.handler_name
to store the irq handler names. If the io_channel_irqs
exceeds the pre-allocated size (32+1), then the driver
will overwrite other fields of sli4_hba.

Fix: Dynamically allocate handler_name.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_init.c | 11 ++-
 drivers/scsi/lpfc/lpfc_sli4.h |  4 ++--
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 3064f0768033..a825806036c3 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -9665,6 +9665,7 @@ static int
 lpfc_sli4_enable_msix(struct lpfc_hba *phba)
 {
int vectors, rc, index;
+   char *name;
 
/* Set up MSI-X multi-message vectors */
vectors = phba->io_channel_irqs;
@@ -9683,9 +9684,9 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba)
 
/* Assign MSI-X vectors to interrupt handlers */
for (index = 0; index < vectors; index++) {
-   memset(>sli4_hba.handler_name[index], 0, 16);
-   snprintf((char *)>sli4_hba.handler_name[index],
-LPFC_SLI4_HANDLER_NAME_SZ,
+   name = phba->sli4_hba.hba_eq_hdl[index].handler_name;
+   memset(name, 0, LPFC_SLI4_HANDLER_NAME_SZ);
+   snprintf(name, LPFC_SLI4_HANDLER_NAME_SZ,
 LPFC_DRIVER_HANDLER_NAME"%d", index);
 
phba->sli4_hba.hba_eq_hdl[index].idx = index;
@@ -9694,12 +9695,12 @@ lpfc_sli4_enable_msix(struct lpfc_hba *phba)
if (phba->cfg_fof && (index == (vectors - 1)))
rc = request_irq(pci_irq_vector(phba->pcidev, index),
 _sli4_fof_intr_handler, 0,
-(char *)>sli4_hba.handler_name[index],
+name,
 >sli4_hba.hba_eq_hdl[index]);
else
rc = request_irq(pci_irq_vector(phba->pcidev, index),
 _sli4_hba_intr_handler, 0,
-(char *)>sli4_hba.handler_name[index],
+name,
 >sli4_hba.hba_eq_hdl[index]);
if (rc) {
lpfc_printf_log(phba, KERN_WARNING, LOG_INIT,
diff --git a/drivers/scsi/lpfc/lpfc_sli4.h b/drivers/scsi/lpfc/lpfc_sli4.h
index cf863db27700..28b75e08e044 100644
--- a/drivers/scsi/lpfc/lpfc_sli4.h
+++ b/drivers/scsi/lpfc/lpfc_sli4.h
@@ -407,8 +407,10 @@ struct lpfc_max_cfg_param {
 
 struct lpfc_hba;
 /* SLI4 HBA multi-fcp queue handler struct */
+#define LPFC_SLI4_HANDLER_NAME_SZ  16
 struct lpfc_hba_eq_hdl {
uint32_t idx;
+   char handler_name[LPFC_SLI4_HANDLER_NAME_SZ];
struct lpfc_hba *phba;
atomic_t hba_eq_in_use;
struct cpumask *cpumask;
@@ -480,7 +482,6 @@ struct lpfc_sli4_lnk_info {
 
 #define LPFC_SLI4_HANDLER_CNT  (LPFC_HBA_IO_CHAN_MAX+ \
 LPFC_FOF_IO_CHAN_NUM)
-#define LPFC_SLI4_HANDLER_NAME_SZ  16
 
 /* Used for IRQ vector to CPU mapping */
 struct lpfc_vector_map_info {
@@ -548,7 +549,6 @@ struct lpfc_sli4_hba {
uint32_t ue_to_rp;
struct lpfc_register sli_intf;
struct lpfc_pc_sli4_params pc_sli4_params;
-   uint8_t handler_name[LPFC_SLI4_HANDLER_CNT][LPFC_SLI4_HANDLER_NAME_SZ];
struct lpfc_hba_eq_hdl *hba_eq_hdl; /* HBA per-WQ handle */
 
/* Pointers to the constructed SLI4 queues */
-- 
2.11.0



[PATCH 05/15] lpfc: Fix Lun Priority level shown as NA

2017-05-31 Thread James Smart
Lun Priority level shown as NA

Remote port is not getting registered for nameserver and fdmi.
Due to which dfc SendCTPassThru cmd is failing.

Made changes to register the remote port for both.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_hbadisc.c | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c
index 3ffcd9215ca8..055fedd761ea 100644
--- a/drivers/scsi/lpfc/lpfc_hbadisc.c
+++ b/drivers/scsi/lpfc/lpfc_hbadisc.c
@@ -4182,8 +4182,10 @@ lpfc_nlp_state_cleanup(struct lpfc_vport *vport, struct 
lpfc_nodelist *ndlp,
 
if (new_state ==  NLP_STE_MAPPED_NODE ||
new_state == NLP_STE_UNMAPPED_NODE) {
-   if ((ndlp->nlp_fc4_type & NLP_FC4_FCP) ||
-   (ndlp->nlp_DID == Fabric_DID)) {
+   if (ndlp->nlp_fc4_type & NLP_FC4_FCP ||
+   ndlp->nlp_DID == Fabric_DID ||
+   ndlp->nlp_DID == NameServer_DID ||
+   ndlp->nlp_DID == FDMI_DID) {
vport->phba->nport_event_cnt++;
/*
 * Tell the fc transport about the port, if we haven't
-- 
2.11.0



[PATCH 03/15] lpfc: Fix nvme port role handling in sysfs and debugfs handlers.

2017-05-31 Thread James Smart
While debugging Devloss and recovery, debugfs and sysfs
were found to not show the NVME port roles consistently.

The port role FC_PORT_ROLE_NVME_DISCOVERY was added with
the devloss bringup and the other issues were just oversight.

Add NVME Target and DISCSRVC to debugfs nodeinfo and sysfs
nvme info handlers. The full port role was added to the NVME
data only not the generic nodelist.

Signed-off-by: Dick Kennedy 
Signed-off-by: James Smart 
---
 drivers/scsi/lpfc/lpfc_attr.c| 22 ++
 drivers/scsi/lpfc/lpfc_debugfs.c | 32 ++--
 2 files changed, 28 insertions(+), 26 deletions(-)

diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c
index 6d9b83cd82a2..200a614bb540 100644
--- a/drivers/scsi/lpfc/lpfc_attr.c
+++ b/drivers/scsi/lpfc/lpfc_attr.c
@@ -312,25 +312,23 @@ lpfc_nvme_info_show(struct device *dev, struct 
device_attribute *attr,
len += snprintf(buf + len, PAGE_SIZE - len, "DID x%06x ",
nrport->port_id);
 
-   switch (nrport->port_role) {
-   case FC_PORT_ROLE_NVME_INITIATOR:
+   /* An NVME rport can have multiple roles. */
+   if (nrport->port_role & FC_PORT_ROLE_NVME_INITIATOR)
len +=  snprintf(buf + len, PAGE_SIZE - len,
 "INITIATOR ");
-   break;
-   case FC_PORT_ROLE_NVME_TARGET:
+   if (nrport->port_role & FC_PORT_ROLE_NVME_TARGET)
len +=  snprintf(buf + len, PAGE_SIZE - len,
 "TARGET ");
-   break;
-   case FC_PORT_ROLE_NVME_DISCOVERY:
+   if (nrport->port_role & FC_PORT_ROLE_NVME_DISCOVERY)
len +=  snprintf(buf + len, PAGE_SIZE - len,
-"DISCOVERY ");
-   break;
-   default:
+"DISCSRVC ");
+   if (nrport->port_role & ~(FC_PORT_ROLE_NVME_INITIATOR |
+ FC_PORT_ROLE_NVME_TARGET |
+ FC_PORT_ROLE_NVME_DISCOVERY))
len +=  snprintf(buf + len, PAGE_SIZE - len,
-"UNKNOWN_ROLE x%x",
+"UNKNOWN ROLE x%x",
 nrport->port_role);
-   break;
-   }
+
len +=  snprintf(buf + len, PAGE_SIZE - len, "%s  ", statep);
/* Terminate the string. */
len +=  snprintf(buf + len, PAGE_SIZE - len, "\n");
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index d71bda24b08e..dd8598bc50f3 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -621,6 +621,13 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char 
*buf, int size)
ndlp->nlp_sid);
if (ndlp->nlp_type & NLP_FCP_INITIATOR)
len += snprintf(buf+len, size-len, "FCP_INITIATOR ");
+   if (ndlp->nlp_type & NLP_NVME_TARGET)
+   len += snprintf(buf + len,
+   size - len, "NVME_TGT sid:%d ",
+   NLP_NO_SID);
+   if (ndlp->nlp_type & NLP_NVME_INITIATOR)
+   len += snprintf(buf + len,
+   size - len, "NVME_INITIATOR ");
len += snprintf(buf+len, size-len, "usgmap:%x ",
ndlp->nlp_usg_map);
len += snprintf(buf+len, size-len, "refcnt:%x",
@@ -698,26 +705,23 @@ lpfc_debugfs_nodelist_data(struct lpfc_vport *vport, char 
*buf, int size)
nrport->port_name);
len += snprintf(buf + len, size - len, "WWNN x%llx ",
nrport->node_name);
-   switch (nrport->port_role) {
-   case FC_PORT_ROLE_NVME_INITIATOR:
+
+   /* An NVME rport can have multiple roles. */
+   if (nrport->port_role & FC_PORT_ROLE_NVME_INITIATOR)
len +=  snprintf(buf + len, size - len,
-"NVME INITIATOR ");
-   break;
-   case FC_PORT_ROLE_NVME_TARGET:
+"INITIATOR ");
+   if (nrport->port_role & FC_PORT_ROLE_NVME_TARGET)
len +=  snprintf(buf + len, size - len,
-"NVME TARGET ");
-   break;
-   case FC_PORT_ROLE_NVME_DISCOVERY:
+"TARGET ");
+   if (nrport->port_role &