[PATCH] SCSI-aic94xx: Delete unnecessary checks before the function call "kmem_cache_destroy"

2015-11-16 Thread SF Markus Elfring
From: Markus Elfring 
Date: Tue, 17 Nov 2015 08:14:52 +0100

The kmem_cache_destroy() function tests whether its argument is NULL
and then returns immediately. Thus the test around the calls is not needed.

This issue was detected by using the Coccinelle software.

Signed-off-by: Markus Elfring 
---
 drivers/scsi/aic94xx/aic94xx_init.c | 7 ++-
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/aic94xx/aic94xx_init.c 
b/drivers/scsi/aic94xx/aic94xx_init.c
index 662b232..ab93049 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
+++ b/drivers/scsi/aic94xx/aic94xx_init.c
@@ -660,12 +660,9 @@ Err:
 
 static void asd_destroy_global_caches(void)
 {
-   if (asd_dma_token_cache)
-   kmem_cache_destroy(asd_dma_token_cache);
+   kmem_cache_destroy(asd_dma_token_cache);
asd_dma_token_cache = NULL;
-
-   if (asd_ascb_cache)
-   kmem_cache_destroy(asd_ascb_cache);
+   kmem_cache_destroy(asd_ascb_cache);
asd_ascb_cache = NULL;
 }
 
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH, resend] scsi: advansys: fix big-endian builds

2015-11-16 Thread Hannes Reinecke
On 11/16/2015 05:49 PM, Arnd Bergmann wrote:
> Building the advansys driver in a big-endian configuration such as
> ARM allmodconfig shows a warning:
> 
>  drivers/scsi/advansys.c: In function 'adv_build_req':
>  include/uapi/linux/byteorder/big_endian.h:32:26: warning: large integer 
> implicitly truncated to unsigned type [-Woverflow]
>   #define __cpu_to_le32(x) ((__force __le32)__swab32((x)))
>  drivers/scsi/advansys.c:7806:22: note: in expansion of macro 'cpu_to_le32'
>scsiqp->sense_len = cpu_to_le32(SCSI_SENSE_BUFFERSIZE);
> 
> It turns out that the commit that introduced this used the cpu_to_le32()
> incorrectly on an 8-bit field, which results in the sense_len to always
> be set to zero, as the SCSI_SENSE_BUFFERSIZE value gets moved to upper
> byte of the 32-bit intermediate.
> 
> This removes the cpu_to_le32() call to restore the original version.
> 
> I found this only by looking at the compiler output and have not done
> a full review for possible further endianess bugs in the same driver.
> 
> Signed-off-by: Arnd Bergmann 
> Fixes: 811ddc057aac ("advansys: use DMA-API for mapping sense buffer")
> Cc: sta...@vger.kernel.org # v4.2+
> ---
> Using wi...@linux.intel.com, as the address listed in MAINTAINERS
> failed:
> 
> Failed to transport message. Message sending failed since the following 
> recipients were rejected by the server: matt...@wil.cx (The server responded: 
> Requested action not taken: mailbox unavailable invalid DNS MX or A/ 
> resource record)
> 
> Geert found the same bug and submitted the same patch earlier:
> https://lkml.org/lkml/2015/6/24/89
> 
> Neither one has been reviewed or accepted so far. Can we get one of the
> two merged please?
> 
> diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
> index 4305178e4e01..1c1cd657c380 100644
> --- a/drivers/scsi/advansys.c
> +++ b/drivers/scsi/advansys.c
> @@ -7803,7 +7803,7 @@ adv_build_req(struct asc_board *boardp, struct 
> scsi_cmnd *scp,
>   return ASC_BUSY;
>   }
>   scsiqp->sense_addr = cpu_to_le32(sense_addr);
> - scsiqp->sense_len = cpu_to_le32(SCSI_SENSE_BUFFERSIZE);
> + scsiqp->sense_len = SCSI_SENSE_BUFFERSIZE;
>  
>   /* Build ADV_SCSI_REQ_Q */
>  
> 
Ho-hum. You are right.

Reviewed-by: Hannes Reinecke 

Cheers,

Hannes
-- 
Dr. Hannes ReineckezSeries & Storage
h...@suse.de   +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2] Separate target visibility from reaped state information

2015-11-16 Thread James Bottomley
On Mon, 2015-11-16 at 16:18 -0800, Bart Van Assche wrote:
> Instead of representing the states "visible in sysfs" and
> "has been removed from the target list" by a single state
> variable, use two variables to represent this information.
> 
> This patch avoids that SCSI device removal can trigger a
> soft lockup.
> 
> See also:
> * "scsi: restart list search after unlock in scsi_remove_target"
>   (commit 40998193560d).
> * "scsi_remove_target: fix softlockup regression on hot remove"
>   (commit bc3f02a795d3).

OK, could you justify this, please ... like with traces and things.

The theory on which

commit 40998193560dab6c3ce8d25f4fa58a23e252ef38
Author: Christoph Hellwig 
Date:   Mon Oct 19 16:35:46 2015 +0200

scsi: restart list search after unlock in scsi_remove_target

Was based is that the race you're claiming to be fixing no longer exists
because it was fixed by

commit f2495e228fce9f9cec84367547813cbb0d6db15a
Author: James Bottomley 
Date:   Tue Jan 21 07:01:41 2014 -0800

[SCSI] dual scan thread bug fix

If that isn't the case, we can fix it, but I'd like to see the evidence.

Thanks,

James


--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v5 02/11] phy: exynos-ufs: add UFS PHY driver for EXYNOS SoC

2015-11-16 Thread Kishon Vijay Abraham I
Hi,

On Monday 09 November 2015 10:56 AM, Alim Akhtar wrote:
> From: Seungwon Jeon 
> 
> This patch introduces Exynos UFS PHY driver. This driver
> supports to deal with phy calibration and power control
> according to UFS host driver's behavior.
> 
> Signed-off-by: Seungwon Jeon 
> Signed-off-by: Alim Akhtar 
> Cc: Kishon Vijay Abraham I 
> ---
>  drivers/phy/Kconfig|7 ++
>  drivers/phy/Makefile   |1 +
>  drivers/phy/phy-exynos-ufs.c   |  241 
> 
>  drivers/phy/phy-exynos-ufs.h   |   85 +
>  drivers/phy/phy-exynos7-ufs.h  |   89 +
>  include/linux/phy/phy-exynos-ufs.h |   85 +
>  6 files changed, 508 insertions(+)
>  create mode 100644 drivers/phy/phy-exynos-ufs.c
>  create mode 100644 drivers/phy/phy-exynos-ufs.h
>  create mode 100644 drivers/phy/phy-exynos7-ufs.h
>  create mode 100644 include/linux/phy/phy-exynos-ufs.h
> 
> diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig
> index 7eb5859dd035..7d38a92e0297 100644
> --- a/drivers/phy/Kconfig
> +++ b/drivers/phy/Kconfig
> @@ -389,4 +389,11 @@ config PHY_CYGNUS_PCIE
> Enable this to support the Broadcom Cygnus PCIe PHY.
> If unsure, say N.
>  
> +config PHY_EXYNOS_UFS
> + tristate "EXYNOS SoC series UFS PHY driver"
> + depends on OF && ARCH_EXYNOS || COMPILE_TEST
> + select GENERIC_PHY
> + help
> +   Support for UFS PHY on Samsung EXYNOS chipsets.
> +
>  endmenu
> diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile
> index 075db1a81aa5..9bec4d1a89e1 100644
> --- a/drivers/phy/Makefile
> +++ b/drivers/phy/Makefile
> @@ -10,6 +10,7 @@ obj-$(CONFIG_ARMADA375_USBCLUSTER_PHY)  += 
> phy-armada375-usb2.o
>  obj-$(CONFIG_BCM_KONA_USB2_PHY)  += phy-bcm-kona-usb2.o
>  obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO)+= phy-exynos-dp-video.o
>  obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO)  += phy-exynos-mipi-video.o
> +obj-$(CONFIG_PHY_EXYNOS_UFS) += phy-exynos-ufs.o
>  obj-$(CONFIG_PHY_LPC18XX_USB_OTG)+= phy-lpc18xx-usb-otg.o
>  obj-$(CONFIG_PHY_PXA_28NM_USB2)  += phy-pxa-28nm-usb2.o
>  obj-$(CONFIG_PHY_PXA_28NM_HSIC)  += phy-pxa-28nm-hsic.o
> diff --git a/drivers/phy/phy-exynos-ufs.c b/drivers/phy/phy-exynos-ufs.c
> new file mode 100644
> index ..cb1aeaa3d4eb
> --- /dev/null
> +++ b/drivers/phy/phy-exynos-ufs.c
> @@ -0,0 +1,241 @@
> +/*
> + * UFS PHY driver for Samsung EXYNOS SoC
> + *
> + * Copyright (C) 2015 Samsung Electronics Co., Ltd.
> + * Author: Seungwon Jeon 
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + */
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include "phy-exynos-ufs.h"
> +
> +#define for_each_phy_lane(phy, i) \
> + for (i = 0; i < (phy)->lane_cnt; i++)
> +#define for_each_phy_cfg(cfg) \
> + for (; (cfg)->id; (cfg)++)
> +
> +#define PHY_DEF_LANE_CNT 1
> +
> +static void exynos_ufs_phy_config(struct exynos_ufs_phy *phy,
> + const struct exynos_ufs_phy_cfg *cfg, u8 lane)
> +{
> + enum {LANE_0, LANE_1}; /* lane index */
> +
> + switch (lane) {
> + case LANE_0:
> + writel(cfg->val, (phy)->reg_pma + cfg->off_0);
> + break;
> + case LANE_1:
> + if (cfg->id == PHY_TRSV_BLK)
> + writel(cfg->val, (phy)->reg_pma + cfg->off_1);
> + break;
> + }
> +}
> +
> +static bool match_cfg_to_pwr_mode(u8 desc, u8 required_pwr)
> +{
> + if (IS_PWR_MODE_ANY(desc))
> + return true;
> +
> + if (IS_PWR_MODE_HS(required_pwr) && IS_PWR_MODE_HS_ANY(desc))
> + return true;
> +
> + if (COMP_PWR_MODE(required_pwr, desc))
> + return true;
> +
> + if (COMP_PWR_MODE_MD(required_pwr, desc) &&
> + COMP_PWR_MODE_GEAR(required_pwr, desc) &&
> + COMP_PWR_MODE_SER(required_pwr, desc))
> + return true;
> +
> + return false;
> +}
> +
> +int exynos_ufs_phy_calibrate(struct phy *phy,
> + enum phy_cfg_tag tag, u8 pwr)

This is similar to the first version of your patch without EXPORT_SYMBOL.

I think you have to create a new generic PHY_OPS for calibrate PHY while making
sure that it is as generic as possible (which means calibrate_phy shouldn't
have tag and pwr arguments or a strong justification as to why those arguments
are required in a generic API).
> +{
> + struct exynos_ufs_phy *ufs_phy = get_exynos_ufs_phy(phy);
> + struct exynos_ufs_phy_cfg **cfgs = ufs_phy->cfg;
> + const struct exynos_ufs_phy_cfg *cfg;
> + int i;
> +
> + if (unlikely(tag < CFG_PRE_INIT || tag >= CFG_TAG_MAX)) {
> + 

Re: [PATCH v5 00/11] exynos-ufs: add support for Exynos

2015-11-16 Thread Kishon Vijay Abraham I
Hi Alim,

On Monday 16 November 2015 06:31 AM, Alim Akhtar wrote:
> Hi Kishon,
> 
> Any more concern on the PHY part of this series?

Sorry for the late reply. Yes, I still have concerns. I'll comment on your 
patch.

Thanks
Kishon
> 
> Thanks!
> 
> On Mon, Nov 9, 2015 at 10:56 AM, Alim Akhtar  wrote:
>> This patch-set introduces UFS (Universal Flash Storage) host support
>> for Samsung Exynos SoC. Mostly, it consists of UFS PHY and host specific 
>> driver.
>> And it also contains some quirks handling for Exynos.
>>
>> NOTE: ** This series has a dependency on [4]. **
>>
>> -Changes since v4:
>> * Removed platform specific PHY ops as suggested by Kishon
>> * Rebased on the top of Yaniv Gardi's work [4]
>> * make use of newly introduce ufshcd_{get,set}_variant
>> * other small changes and improvements.
>> * rebased on the top of linux next-20151109
>>
>> -Changes since v3:
>> * Fixed compilation warrings as reported by "Kbuild Test Robot"[5].
>> * Restructure the driver to make it as a platform driver, rebased on top of 
>> [4].
>> * Addressed review comments from Arnd Bergmann[5].
>> * Other misc changes and improvements.
>>
>> -Changes since v2:
>> * Addressed review comments from Kishon[1] and Rob Herring [2]
>> * Splited ufs dt binding documetation from ufs driver patch
>>
>> -Changes since v1:
>> * Addressed review comments from Alexey[3] and various review comments from 
>> Amit.
>> * Updated email id of Seungwon as his samsung id is void now.
>> * Added ufs platform data
>>
>> [1]-> https://lkml.org/lkml/2015/9/18/29
>> [2]-> https://lkml.org/lkml/2015/9/21/668
>> [3]-> https://lkml.org/lkml/2015/8/23/124
>> [4]-> https://lkml.org/lkml/2015/10/28/271
>> [5]-> https://lkml.org/lkml/2015/10/1/402
>>
>> This patch set is tested on exynos7-espresso board.
>>
>>
>> Alim Akhtar (1):
>>   Documentation: samsung-phy: Add dt bindings for UFS
>>
>> Seungwon Jeon (10):
>>   phy: exynos-ufs: add UFS PHY driver for EXYNOS SoC
>>   scsi: ufs: add quirk to contain unconformable utrd field
>>   scsi: ufs: add quirk to fix mishandling utrlclr/utmrlclr
>>   scsi: ufs: add quirk not to allow reset of interrupt aggregation
>>   scsi: ufs: add quirk to enable host controller without hce
>>   scsi: ufs: add specific callback for nexus type
>>   scsi: ufs: add add specific callback for hibern8
>>   scsi: ufs: make ufshcd_config_pwr_mode of non-static func
>>   Documentation: devicetree: ufs: Add DT bindings for exynos UFS host
>> controller
>>   scsi: ufs-exynos: add UFS host support for Exynos SoCs
>>
>>  .../devicetree/bindings/phy/samsung-phy.txt|   22 +
>>  .../devicetree/bindings/ufs/ufs-exynos.txt |  104 ++
>>  drivers/phy/Kconfig|7 +
>>  drivers/phy/Makefile   |1 +
>>  drivers/phy/phy-exynos-ufs.c   |  241 
>>  drivers/phy/phy-exynos-ufs.h   |   85 ++
>>  drivers/phy/phy-exynos7-ufs.h  |   89 ++
>>  drivers/scsi/ufs/Kconfig   |   12 +
>>  drivers/scsi/ufs/Makefile  |1 +
>>  drivers/scsi/ufs/ufs-exynos-hw.c   |  131 ++
>>  drivers/scsi/ufs/ufs-exynos-hw.h   |   43 +
>>  drivers/scsi/ufs/ufs-exynos.c  | 1304 
>> 
>>  drivers/scsi/ufs/ufs-exynos.h  |  247 
>>  drivers/scsi/ufs/ufshcd.c  |  168 ++-
>>  drivers/scsi/ufs/ufshcd.h  |   54 +
>>  drivers/scsi/ufs/ufshci.h  |   26 +-
>>  drivers/scsi/ufs/unipro.h  |   47 +
>>  include/linux/phy/phy-exynos-ufs.h |   85 ++
>>  18 files changed, 2647 insertions(+), 20 deletions(-)
>>  create mode 100644 Documentation/devicetree/bindings/ufs/ufs-exynos.txt
>>  create mode 100644 drivers/phy/phy-exynos-ufs.c
>>  create mode 100644 drivers/phy/phy-exynos-ufs.h
>>  create mode 100644 drivers/phy/phy-exynos7-ufs.h
>>  create mode 100644 drivers/scsi/ufs/ufs-exynos-hw.c
>>  create mode 100644 drivers/scsi/ufs/ufs-exynos-hw.h
>>  create mode 100644 drivers/scsi/ufs/ufs-exynos.c
>>  create mode 100644 drivers/scsi/ufs/ufs-exynos.h
>>  create mode 100644 include/linux/phy/phy-exynos-ufs.h
>>
>> --
>> 1.7.10.4
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
>> the body of a message to majord...@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2] Separate target visibility from reaped state information

2015-11-16 Thread Bart Van Assche
Instead of representing the states "visible in sysfs" and
"has been removed from the target list" by a single state
variable, use two variables to represent this information.

This patch avoids that SCSI device removal can trigger a
soft lockup.

See also:
* "scsi: restart list search after unlock in scsi_remove_target"
  (commit 40998193560d).
* "scsi_remove_target: fix softlockup regression on hot remove"
  (commit bc3f02a795d3).

Signed-off-by: Bart Van Assche 
Cc: Christoph Hellwig 
Cc: Johannes Thumshirn 
Cc: Dan Williams 
Cc: stable 
---
 drivers/scsi/scsi_scan.c   | 31 +++
 drivers/scsi/scsi_sysfs.c  |  7 ---
 include/scsi/scsi_device.h |  9 ++---
 3 files changed, 9 insertions(+), 38 deletions(-)


Changes compared to v1:
- Renamed "visible" into "is_visible" for consistency with the rest of the
  SCSI initiator code.
- Removed the scsi_target_state since it is no longer used.

This patch has been tested on top of kernel v4.4-rc1 with the SRP initiator
driver.


diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 8324539..6accec3 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -314,7 +314,6 @@ static void scsi_target_destroy(struct scsi_target *starget)
struct Scsi_Host *shost = dev_to_shost(dev->parent);
unsigned long flags;
 
-   starget->state = STARGET_DEL;
transport_destroy_device(dev);
spin_lock_irqsave(shost->host_lock, flags);
if (shost->hostt->target_destroy)
@@ -379,19 +378,15 @@ static void scsi_target_reap_ref_release(struct kref 
*kref)
struct scsi_target *starget
= container_of(kref, struct scsi_target, reap_ref);
 
-   /*
-* if we get here and the target is still in the 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->is_visible) {
+   starget->is_visible = false;
transport_remove_device(&starget->dev);
device_del(&starget->dev);
}
scsi_target_destroy(starget);
 }
 
-static void scsi_target_reap_ref_put(struct scsi_target *starget)
+void scsi_target_reap(struct scsi_target *starget)
 {
kref_put(&starget->reap_ref, scsi_target_reap_ref_release);
 }
@@ -437,7 +432,6 @@ static struct scsi_target *scsi_alloc_target(struct device 
*parent,
starget->can_queue = 0;
INIT_LIST_HEAD(&starget->siblings);
INIT_LIST_HEAD(&starget->devices);
-   starget->state = STARGET_CREATED;
starget->scsi_level = SCSI_2;
starget->max_target_blocked = SCSI_DEFAULT_TARGET_BLOCKED;
  retry:
@@ -498,25 +492,6 @@ static struct scsi_target *scsi_alloc_target(struct device 
*parent,
 }
 
 /**
- * scsi_target_reap - check to see if target is in use and destroy if not
- * @starget: target to be checked
- *
- * This is used after removing a LUN or doing a last put of the target
- * it checks atomically that nothing is using the target and removes
- * it if so.
- */
-void scsi_target_reap(struct scsi_target *starget)
-{
-   /*
-* serious problem if this triggers: STARGET_DEL is only set in the if
-* the reap_ref drops to zero, so we're trying to do another final put
-* on an already released kref
-*/
-   BUG_ON(starget->state == STARGET_DEL);
-   scsi_target_reap_ref_put(starget);
-}
-
-/**
  * sanitize_inquiry_string - remove non-graphical chars from an INQUIRY result 
string
  * @s: INQUIRY result string to sanitize
  * @len: length of the string
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 8d23122..c5ea634 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -1000,7 +1000,7 @@ static int scsi_target_add(struct scsi_target *starget)
 {
int error;
 
-   if (starget->state != STARGET_CREATED)
+   if (starget->is_visible)
return 0;
 
error = device_add(&starget->dev);
@@ -1009,7 +1009,7 @@ static int scsi_target_add(struct scsi_target *starget)
return error;
}
transport_add_device(&starget->dev);
-   starget->state = STARGET_RUNNING;
+   starget->is_visible = true;
 
pm_runtime_set_active(&starget->dev);
pm_runtime_enable(&starget->dev);
@@ -1198,10 +1198,11 @@ void scsi_remove_target(struct device *dev)
 restart:
spin_lock_irqsave(shost->host_lock, flags);
list_for_each_entry(starget, &shost->__targets, siblings) {
-   if (starget->state == STARGET_DEL)
+   if (starget->reaped)
continue;
if (starget->dev.parent == dev || &starget->dev == dev) {
kref_get(&starget->reap_ref);
+   starget->reaped = true;
spin_unlock_irqrestore(shost->host_lo

[PATCH, RESEND] qla2xxx: Fix rwlock recursion

2015-11-16 Thread Bart Van Assche
This patch fixes the following kernel bug:

kernel:BUG: rwlock recursion on CPU#2, insmod/39333, 8803e998cb28
kernel: Call Trace:
kernel: [] dump_stack+0x48/0x64
kernel: [] rwlock_bug+0x67/0x70
kernel: [] do_raw_write_lock+0x8a/0xa0
kernel: [] _raw_write_lock_irqsave+0x63/0x80
kernel: [] qla82xx_rd_32+0xe8/0x140 [qla2xxx]
kernel: [] qla82xx_crb_win_lock+0x25/0x60 [qla2xxx]
kernel: [] qla82xx_wr_32+0xf6/0x150 [qla2xxx]
kernel: [] qla82xx_disable_intrs+0x50/0x80 [qla2xxx]
kernel: [] qla82xx_reset_chip+0x1a/0x20 [qla2xxx]
kernel: [] qla2x00_initialize_adapter+0x132/0x420 [qla2xxx]
kernel: [] qla82xx_rd_32+0xe8/0x140 [qla2xxx]
kernel: [] qla82xx_crb_win_lock+0x25/0x60 [qla2xxx]
kernel: [] qla82xx_wr_32+0xf6/0x150 [qla2xxx]
kernel: [] qla82xx_disable_intrs+0x50/0x80 [qla2xxx]
kernel: [] qla82xx_reset_chip+0x1a/0x20 [qla2xxx]
kernel: [] qla2x00_initialize_adapter+0x132/0x420 [qla2xxx]
kernel: [] qla2x00_probe_one+0xefe/0x2130 [qla2xxx]
kernel: [] local_pci_probe+0x4c/0xa0
kernel: [] pci_call_probe+0x83/0xa0
kernel: [] pci_device_probe+0x7f/0xb0
kernel: [] really_probe+0x133/0x390
kernel: [] driver_probe_device+0x59/0xd0
kernel: [] __driver_attach+0xa1/0xb0
kernel: [] bus_for_each_dev+0x8d/0xb0
kernel: [] driver_attach+0x1e/0x20
kernel: [] bus_add_driver+0x1d2/0x290
kernel: [] driver_register+0x60/0xe0
kernel: [] __pci_register_driver+0x64/0x70
kernel: [] qla2x00_module_init+0x1cb/0x21b [qla2xxx]
kernel: [] do_one_initcall+0xad/0x1c0
kernel: [] do_init_module+0x69/0x210
kernel: [] load_module+0x5cc/0x750
kernel: [] SyS_init_module+0x92/0xc0
kernel: [] entry_SYSCALL_64_fastpath+0x12/0x6f

Fixes: 8dfa4b5a9b44 ("qla2xxx: Fix sparse annotation")
Signed-off-by: Bart Van Assche 
Reported-by: Himanshu Madhani 
Tested-by: Himanshu Madhani 
Cc: Giridhar Malavali 
Cc: Xose Vazquez Perez 
Cc: stable  # v4.3+
---
 drivers/scsi/qla2xxx/qla_nx.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
index eb0cc54..b6b4cfd 100644
--- a/drivers/scsi/qla2xxx/qla_nx.c
+++ b/drivers/scsi/qla2xxx/qla_nx.c
@@ -433,7 +433,7 @@ qla82xx_pci_get_crb_addr_2M(struct qla_hw_data *ha, ulong 
off_in,
if (off_in < QLA82XX_PCI_CRBSPACE)
return -1;
 
-   *off_out = (void __iomem *)(off_in - QLA82XX_PCI_CRBSPACE);
+   off_in -= QLA82XX_PCI_CRBSPACE;
 
/* Try direct map */
m = &crb_128M_2M_map[CRB_BLK(off_in)].sub_block[CRB_SUBBLK(off_in)];
@@ -443,6 +443,7 @@ qla82xx_pci_get_crb_addr_2M(struct qla_hw_data *ha, ulong 
off_in,
return 0;
}
/* Not in direct map, use crb window */
+   *off_out = (void __iomem *)off_in;
return 1;
 }
 
-- 
2.1.4

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/2] qla2xxx: fix rwlock recursion

2015-11-16 Thread Xose Vazquez Perez
Bart Van Assche wrote:

> [PATCH] qla2xxx: Fix rwlock recursion
> 
> Fixes: 8dfa4b5a9b44 ("qla2xxx: Fix sparse annotation")
> Signed-off-by: Bart Van Assche 
> Reported-by: Himanshu Madhani 
> Cc: Giridhar Malavali 
> ---
>   drivers/scsi/qla2xxx/qla_nx.c | 3 ++-
>   1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
> index eb0cc54..b6b4cfd 100644
> --- a/drivers/scsi/qla2xxx/qla_nx.c
> +++ b/drivers/scsi/qla2xxx/qla_nx.c
> @@ -433,7 +433,7 @@ qla82xx_pci_get_crb_addr_2M(struct qla_hw_data *ha, 
> ulong off_in,
>   if (off_in < QLA82XX_PCI_CRBSPACE)
>   return -1;
> 
> - *off_out = (void __iomem *)(off_in - QLA82XX_PCI_CRBSPACE);
> + off_in -= QLA82XX_PCI_CRBSPACE;
> 
>   /* Try direct map */
>   m = &crb_128M_2M_map[CRB_BLK(off_in)].sub_block[CRB_SUBBLK(off_in)];
> @@ -443,6 +443,7 @@ qla82xx_pci_get_crb_addr_2M(struct qla_hw_data *ha, 
> ulong off_in,
>   return 0;
>   }
>   /* Not in direct map, use crb window */
> + *off_out = (void __iomem *)off_in;
>   return 1;
>   }
> 
> -- 
> 2.1.4

This patch is still pending or it was lost, could you please resend it ?

-thanks-
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCHv4 1/1] SCSI: hosts: update to use ida_simple for host_no management

2015-11-16 Thread Lee Duncan
On 11/16/2015 04:10 AM, Hannes Reinecke wrote:
> On 11/13/2015 10:54 PM, Martin K. Petersen wrote:
>>> "Lee" == Lee Duncan  writes:
>>
 Well, I'm a bit worried about the loss of a monotonically increasing
 host number from the debugging perspective.  Right now, if you look
 at any log, hostX always refers to one and only one incarnation
 throughout the system lifetime for any given value of X.
>>
>> That's a feature that I would absolutely hate to lose. I spend a huge
>> amount of time looking at system logs.
>>
> Right. Then have it enabled via a modprobe parameters.
> 
> We actually had customers running into a host_no overflow due to
> excessive host allocations and freeing done by iSCSI.
> 
> Cheers,
> 
> Hannes
> 

Martin: I will be glad to update the patch, creating a modprobe
parameter as suggested, if you find this acceptable.
-- 
Lee Duncan
SUSE Labs
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4 05/32] scsi: hisi_sas: scan device tree

2015-11-16 Thread kbuild test robot
Hi John,

[auto build test ERROR on scsi/for-next]
[also build test ERROR on v4.4-rc1 next-20151116]

url:
https://github.com/0day-ci/linux/commits/John-Garry/HiSilicon-SAS-driver/20151116-215304
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git for-next
config: i386-allmodconfig (attached as .config)
reproduce:
# save the attached .config to linux build tree
make ARCH=i386 

All errors (new ones prefixed by >>):

>> ERROR: "of_irq_count" undefined!

---
0-DAY kernel test infrastructureOpen Source Technology Center
https://lists.01.org/pipermail/kbuild-all   Intel Corporation


.config.gz
Description: Binary data


RE: [PATCH 3/9] IB: add a helper to safely drain a QP

2015-11-16 Thread Steve Wise


> -Original Message-
> From: linux-rdma-ow...@vger.kernel.org 
> [mailto:linux-rdma-ow...@vger.kernel.org] On Behalf Of Sagi Grimberg
> Sent: Monday, November 16, 2015 12:38 PM
> To: Steve Wise; 'Christoph Hellwig'; linux-r...@vger.kernel.org
> Cc: bart.vanass...@sandisk.com; ax...@fb.com; linux-scsi@vger.kernel.org; 
> linux-ker...@vger.kernel.org
> Subject: Re: [PATCH 3/9] IB: add a helper to safely drain a QP
> 
> 
> > After looking at the nes driver, I don't see any common way to support 
> > drain w/o some serious driver mods.  Since SRP is the
only
> > user, perhaps we can ignore iWARP for this function...
> 
> But iser/isert essentially does it too (and I think xprtrdma will have
> it soon)...
> 
> the modify_qp is invoked from rdma_disconnect() and we do post
> an 'empty' wr to wait for all the flushes to drain (see
> iser_conn_terminate).

That won't work for iWARP.  Is this code new?  I didn't see any errors that 
would result from this code when I tested iSER over
cxgb4 with the old iwarp support patches.   

Perhaps we need another way to do this?  Like a completion object in the QP 
that gets triggered when the SQ and RQ become empty
after a transition to ERROR (and CLOSING for iwarp).  Then a core service that 
just waits until the QP is empty.  Implementation of
this design would hit the providers though since only they know when the flush 
is completed.

Alternatively, I could enable post-while-in-error support in cxgb4 and ignore 
the spec in this regard.  But I'd rather not do that.
:)

Steve.

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH, resend] scsi: advansys: fix big-endian builds

2015-11-16 Thread Geert Uytterhoeven
On Mon, Nov 16, 2015 at 7:20 PM, Russell King - ARM Linux
 wrote:
> On Mon, Nov 16, 2015 at 05:49:23PM +0100, Arnd Bergmann wrote:
>> It turns out that the commit that introduced this used the cpu_to_le32()
>> incorrectly on an 8-bit field, which results in the sense_len to always
>> be set to zero, as the SCSI_SENSE_BUFFERSIZE value gets moved to upper
>> byte of the 32-bit intermediate.
>
> More people need to run the sparse checker with -D__CHECK_ENDIAN__ and
> have proper endian annotations?

Sure.

But in this case, it shows up as a normal compiler warning on all big endian
platforms.

Gr{oetje,eeting}s,

Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 3/9] IB: add a helper to safely drain a QP

2015-11-16 Thread Sagi Grimberg



After looking at the nes driver, I don't see any common way to support drain 
w/o some serious driver mods.  Since SRP is the only
user, perhaps we can ignore iWARP for this function...


But iser/isert essentially does it too (and I think xprtrdma will have
it soon)...

the modify_qp is invoked from rdma_disconnect() and we do post
an 'empty' wr to wait for all the flushes to drain (see
iser_conn_terminate).
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH, resend] scsi: advansys: fix big-endian builds

2015-11-16 Thread Christoph Hellwig
On Mon, Nov 16, 2015 at 06:20:31PM +, Russell King - ARM Linux wrote:
> On Mon, Nov 16, 2015 at 05:49:23PM +0100, Arnd Bergmann wrote:
> > It turns out that the commit that introduced this used the cpu_to_le32()
> > incorrectly on an 8-bit field, which results in the sense_len to always
> > be set to zero, as the SCSI_SENSE_BUFFERSIZE value gets moved to upper
> > byte of the 32-bit intermediate.
> 
> More people need to run the sparse checker with -D__CHECK_ENDIAN__ and
> have proper endian annotations?

Ho about enabling __CHECK_ENDIAN__ by default when running sparse at
least?
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


RE: [PATCH 3/9] IB: add a helper to safely drain a QP

2015-11-16 Thread Steve Wise


> -Original Message-
> From: Steve Wise [mailto:sw...@opengridcomputing.com]
> Sent: Monday, November 16, 2015 10:38 AM
> To: Sagi Grimberg; Christoph Hellwig; linux-r...@vger.kernel.org
> Cc: bart.vanass...@sandisk.com; ax...@fb.com; linux-scsi@vger.kernel.org; 
> linux-ker...@vger.kernel.org
> Subject: Re: [PATCH 3/9] IB: add a helper to safely drain a QP
> 
> On 11/15/2015 3:34 AM, Sagi Grimberg wrote:
> >
> >> +
> >> +struct ib_stop_cqe {
> >> +struct ib_cqecqe;
> >> +struct completion done;
> >> +};
> >> +
> >> +static void ib_stop_done(struct ib_cq *cq, struct ib_wc *wc)
> >> +{
> >> +struct ib_stop_cqe *stop =
> >> +container_of(wc->wr_cqe, struct ib_stop_cqe, cqe);
> >> +
> >> +complete(&stop->done);
> >> +}
> >> +
> >> +/*
> >> + * Change a queue pair into the error state and wait until all receive
> >> + * completions have been processed before destroying it. This avoids
> >> that
> >> + * the receive completion handler can access the queue pair while it is
> >> + * being destroyed.
> >> + */
> >> +void ib_drain_qp(struct ib_qp *qp)
> >> +{
> >> +struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR };
> >> +struct ib_stop_cqe stop = { };
> >> +struct ib_recv_wr wr, *bad_wr;
> >> +int ret;
> >> +
> >> +wr.wr_cqe = &stop.cqe;
> >> +stop.cqe.done = ib_stop_done;
> >> +init_completion(&stop.done);
> >> +
> >> +ret = ib_modify_qp(qp, &attr, IB_QP_STATE);
> >> +if (ret) {
> >> +WARN_ONCE(ret, "failed to drain QP: %d\n", ret);
> >> +return;
> >> +}
> >> +
> >> +ret = ib_post_recv(qp, &wr, &bad_wr);
> >> +if (ret) {
> >> +WARN_ONCE(ret, "failed to drain QP: %d\n", ret);
> >> +return;
> >> +}
> >> +
> >> +wait_for_completion(&stop.done);
> >> +}
> >
> > This is taken from srp, and srp drains using a recv wr due to a race
> > causing a use-after-free condition in srp which re-posts a recv buffer
> > in the recv completion handler. srp does not really care if there are
> > pending send flushes.
> >
> > I'm not sure if there are ordering rules for send/recv queues in
> > terms of flush completions, meaning that even if all recv flushes
> > were consumed maybe there are send flushes still pending.
> >
> > I think that for a general drain helper it would be useful to
> > make sure that both the recv _and_ send flushes were drained.
> >
> > So, something like:
> >
> > void ib_drain_qp(struct ib_qp *qp)
> > {
> > struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR };
> > struct ib_stop_cqe rstop, sstop;
> > struct ib_recv_wr rwr = {}, *bad_rwr;
> > struct ib_send_wr swr = {}, *bad_swr;
> > int ret;
> >
> > rwr.wr_cqe = &rstop.cqe;
> > rstop.cqe.done = ib_stop_done;
> > init_completion(&rstop.done);
> >
> > swr.wr_cqe = &sstop.cqe;
> > sstop.cqe.done = ib_stop_done;
> > init_completion(&sstop.done);
> >
> > ret = ib_modify_qp(qp, &attr, IB_QP_STATE);
> > if (ret) {
> > WARN_ONCE(ret, "failed to drain QP: %d\n", ret);
> > return;
> > }
> >
> > ret = ib_post_recv(qp, &rwr, &bad_rwr);
> > if (ret) {
> > WARN_ONCE(ret, "failed to drain recv queue: %d\n", ret);
> > return;
> > }
> >
> > ret = ib_post_send(qp, &swr, &bad_swr);
> > if (ret) {
> > WARN_ONCE(ret, "failed to drain send queue: %d\n", ret);
> > return;
> > }
> >
> > wait_for_completion(&rstop.done);
> > wait_for_completion(&sstop.done);
> > }
> >
> > Thoughts?
> 
> This won't work for iWARP as per my previous email.  But I will code
> something up that will.
> 
> Steve

After looking at the nes driver, I don't see any common way to support drain 
w/o some serious driver mods.  Since SRP is the only
user, perhaps we can ignore iWARP for this function...

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH, resend] scsi: advansys: fix big-endian builds

2015-11-16 Thread Russell King - ARM Linux
On Mon, Nov 16, 2015 at 05:49:23PM +0100, Arnd Bergmann wrote:
> It turns out that the commit that introduced this used the cpu_to_le32()
> incorrectly on an 8-bit field, which results in the sense_len to always
> be set to zero, as the SCSI_SENSE_BUFFERSIZE value gets moved to upper
> byte of the 32-bit intermediate.

More people need to run the sparse checker with -D__CHECK_ENDIAN__ and
have proper endian annotations?

-- 
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/2] Restart list search after unlock in scsi_remove_target

2015-11-16 Thread Christoph Hellwig
Bart, can you resend your patch on top of 4.4-rc1?  I think we really
need it so we should get it into 4.4 and backport it to -stable.
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] ib_srp: initialize dma_length in srp_map_idb

2015-11-16 Thread Bart Van Assche

On 11/16/2015 09:22 AM, Christoph Hellwig wrote:

the code in this area changed enough since 4.3 that it won't easily
apply.  But a backport would still be very useful!


In that case:

Reviewed-by: Bart Van Assche 
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v4 03/32] scsi: hisi_sas: add initial bare main driver

2015-11-16 Thread kbuild test robot
Hi John,

[auto build test ERROR on scsi/for-next]
[also build test ERROR on v4.4-rc1 next-20151116]

url:
https://github.com/0day-ci/linux/commits/John-Garry/HiSilicon-SAS-driver/20151116-215304
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git for-next
config: i386-randconfig-s0-11162304 (attached as .config)
reproduce:
# save the attached .config to linux build tree
make ARCH=i386 

All error/warnings (new ones prefixed by >>):

warning: (SCSI_HISI_SAS && TCM_IBLOCK) selects BLK_DEV_INTEGRITY which has 
unmet direct dependencies (BLOCK)
warning: (SCSI_HISI_SAS) selects SCSI_SAS_LIBSAS which has unmet direct 
dependencies (SCSI)
   block/bio-integrity.c: In function 'bio_integrity_alloc':
>> block/bio-integrity.c:50:26: error: dereferencing pointer to incomplete type 
>> 'struct bio'
 struct bio_set *bs = bio->bi_pool;
 ^
>> block/bio-integrity.c:51:22: error: 'BIO_POOL_NONE' undeclared (first use in 
>> this function)
 unsigned long idx = BIO_POOL_NONE;
 ^
   block/bio-integrity.c:51:22: note: each undeclared identifier is reported 
only once for each function it appears in
   In file included from include/uapi/linux/stddef.h:1:0,
from include/linux/stddef.h:4,
from include/uapi/linux/posix_types.h:4,
from include/uapi/linux/types.h:13,
from include/linux/types.h:5,
from include/uapi/linux/capability.h:16,
from include/linux/capability.h:15,
from include/linux/sched.h:15,
from include/linux/blkdev.h:4,
from block/bio-integrity.c:23:
>> block/bio-integrity.c:54:16: error: dereferencing pointer to incomplete type 
>> 'struct bio_set'
 if (!bs || !bs->bio_integrity_pool) {
   ^
   include/linux/compiler.h:147:28: note: in definition of macro '__trace_if'
 if (__builtin_constant_p((cond)) ? !!(cond) :   \
   ^
>> block/bio-integrity.c:54:2: note: in expansion of macro 'if'
 if (!bs || !bs->bio_integrity_pool) {
 ^
>> block/bio-integrity.c:55:24: error: invalid application of 'sizeof' to 
>> incomplete type 'struct bio_integrity_payload'
  bip = kmalloc(sizeof(struct bio_integrity_payload) +
   ^
   In file included from arch/x86/include/asm/string.h:2:0,
from include/linux/string.h:17,
from include/linux/dynamic_debug.h:111,
from include/linux/printk.h:277,
from include/linux/kernel.h:13,
from include/linux/sched.h:17,
from include/linux/blkdev.h:4,
from block/bio-integrity.c:23:
>> block/bio-integrity.c:66:24: error: dereferencing pointer to incomplete type 
>> 'struct bio_integrity_payload'
 memset(bip, 0, sizeof(*bip));
   ^
   arch/x86/include/asm/string_32.h:325:52: note: in definition of macro 
'memset'
#define memset(s, c, count) __builtin_memset(s, c, count)
   ^
>> block/bio-integrity.c:69:18: error: implicit declaration of function 
>> 'bvec_alloc' [-Werror=implicit-function-declaration]
  bip->bip_vec = bvec_alloc(gfp_mask, nr_vecs, &idx,
 ^
>> block/bio-integrity.c:73:23: error: implicit declaration of function 
>> 'bvec_nr_vecs' [-Werror=implicit-function-declaration]
  bip->bip_max_vcnt = bvec_nr_vecs(idx);
  ^
   block/bio-integrity.c: In function 'bio_integrity_free':
>> block/bio-integrity.c:100:38: error: implicit declaration of function 
>> 'bio_integrity' [-Werror=implicit-function-declaration]
 struct bio_integrity_payload *bip = bio_integrity(bio);
 ^
>> block/bio-integrity.c:100:38: warning: initialization makes pointer from 
>> integer without a cast [-Wint-conversion]
   In file included from include/uapi/linux/stddef.h:1:0,
from include/linux/stddef.h:4,
from include/uapi/linux/posix_types.h:4,
from include/uapi/linux/types.h:13,
from include/linux/types.h:5,
from include/uapi/linux/capability.h:16,
from include/linux/capability.h:15,
from include/linux/sched.h:15,
from include/linux/blkdev.h:4,
from block/bio-integrity.c:23:
>> block/bio-integrity.c:103:23: error: 'BIP_BLOCK_INTEGRITY' undeclared (first 
>> use in this funct

Re: [PATCH] ib_srp: initialize dma_length in srp_map_idb

2015-11-16 Thread Christoph Hellwig
Hi Bart,

the code in this area changed enough since 4.3 that it won't easily
apply.  But a backport would still be very useful!
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/1] iscsi: fix regression caused by session lock patch

2015-11-16 Thread Michael Christie

> On Nov 15, 2015, at 4:10 AM, Or Gerlitz  wrote:
> 
> On Fri, Nov 13, 2015 at 6:51 PM, Mike Christie  wrote:
>> On 11/13/2015 09:06 AM, Or Gerlitz wrote:
 The patch has caused multiple regressions, did not even compile when
> sent to me, and was poorly reviewed and I have not heard from you guys
> in a week. Given the issues the patch has had and the current time, I do
> not feel comfortable with it anymore. I want to re-review it and fix it
> up when there is more time.
>>> Mike (Hi),
>>> 
>>> It's a complex patch that touches all the iscsi transports, and yes,
>>> when it was send to you the 1st time, there was build error on one of
>>> the offload transports (bad! but happens) and yes, as you pointed, one
>>> static checker fix + one bug fix for it went upstream after this has
>>> been merged, happens too.
>> 
>> A patch should not cause this many issues.
>> 
>>> What makes you say it was poorly reviewed?
>> 
>> I just did not do a good job at looking at the patch. I should have
>> caught all of these issues.
>> 
>> - The bnx2i cleanup_task bug should have been obvious, especially for me
>> because I had commented about the back lock and the abort path.
>> 
>> - This oops, was so basic. Incorrect locking around a linked list being
>> accessed from 2 threads is really one of those 1st year kernel
>> programmer things.
> 
> Mike, Chris
> 
> After the locking change, adding a task to any of the connection
> mgmtqueue, cmdqueue, or requeue lists is under the session forward lock.
> 
> Removing tasks from any of these lists in iscsi_data_xmit is under
> the session forward lock and **before** calling down to the transport
> to handle the task.
> 
> The iscsi_complete_task helper was added by Mike's commit
> 3bbaaad95fd38ded "[SCSI] libiscsi: handle cleanup task races"
> and is indeed typically called under the backward lock && has this section
> 
> +   if (!list_empty(&task->running))
> +   list_del_init(&task->running);
> 
> which per my reading of the code never comes into play, can you comment?


I had sent this to Sagi and your mellanox email the other day:


> The bug occurs when a target completes a command while we are still
> processing it. If we are doing a WRITE and the iscsi_task
> is on the cmdqueue because we are handling a R2T. The target shouldn't
> send a Check Condition at this time, but some do. If that happens, then
> iscsi_queuecommand could be adding a new task to the cmdqueue, while the
> recv path is handling the CC for the task with the outsanding R2T.  The
> recv path iscsi_complete_task call sees that task it on the cmdqueue and
> deletes it from the list at the same time iscsi_queuecommand is adding a new
> task.
> 
> This should not happen per the iscsi spec. There is some wording about
> waiting to finish the sequence in progress, but targets goof this up.




--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] ib_srp: initialize dma_length in srp_map_idb

2015-11-16 Thread Bart Van Assche

On 11/15/2015 09:59 AM, Christoph Hellwig wrote:

Without this sg_dma_len will return 0 on architectures tha have
the dma_length field.

Signed-off-by: Christoph Hellwig 
---
  drivers/infiniband/ulp/srp/ib_srp.c | 3 +++
  1 file changed, 3 insertions(+)

diff --git a/drivers/infiniband/ulp/srp/ib_srp.c 
b/drivers/infiniband/ulp/srp/ib_srp.c
index 32f7962..445c0a6 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -1520,6 +1520,9 @@ static int srp_map_idb(struct srp_rdma_ch *ch, struct 
srp_request *req,
state.sg_nents = 1;
sg_set_buf(idb_sg, req->indirect_desc, idb_len);
idb_sg->dma_address = req->indirect_dma_addr; /* hack! */
+#ifdef CONFIG_NEED_SG_DMA_LENGTH
+   idb_sg->dma_length = idb_sg->length;/* hack^2 */
+#endif
ret = srp_map_finish_fr(&state, ch);
if (ret < 0)
return ret;



Hello Christoph,

How about adding "Cc: stable" to this patch such that it not only will 
be integrated in kernel v4.4 but also in kernel v4.3.1 or later ?


Thanks,

Bart.
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH, resend] scsi: advansys: fix big-endian builds

2015-11-16 Thread Arnd Bergmann
Building the advansys driver in a big-endian configuration such as
ARM allmodconfig shows a warning:

 drivers/scsi/advansys.c: In function 'adv_build_req':
 include/uapi/linux/byteorder/big_endian.h:32:26: warning: large integer 
implicitly truncated to unsigned type [-Woverflow]
  #define __cpu_to_le32(x) ((__force __le32)__swab32((x)))
 drivers/scsi/advansys.c:7806:22: note: in expansion of macro 'cpu_to_le32'
   scsiqp->sense_len = cpu_to_le32(SCSI_SENSE_BUFFERSIZE);

It turns out that the commit that introduced this used the cpu_to_le32()
incorrectly on an 8-bit field, which results in the sense_len to always
be set to zero, as the SCSI_SENSE_BUFFERSIZE value gets moved to upper
byte of the 32-bit intermediate.

This removes the cpu_to_le32() call to restore the original version.

I found this only by looking at the compiler output and have not done
a full review for possible further endianess bugs in the same driver.

Signed-off-by: Arnd Bergmann 
Fixes: 811ddc057aac ("advansys: use DMA-API for mapping sense buffer")
Cc: sta...@vger.kernel.org # v4.2+
---
Using wi...@linux.intel.com, as the address listed in MAINTAINERS
failed:

Failed to transport message. Message sending failed since the following 
recipients were rejected by the server: matt...@wil.cx (The server responded: 
Requested action not taken: mailbox unavailable invalid DNS MX or A/ 
resource record)

Geert found the same bug and submitted the same patch earlier:
https://lkml.org/lkml/2015/6/24/89

Neither one has been reviewed or accepted so far. Can we get one of the
two merged please?

diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 4305178e4e01..1c1cd657c380 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -7803,7 +7803,7 @@ adv_build_req(struct asc_board *boardp, struct scsi_cmnd 
*scp,
return ASC_BUSY;
}
scsiqp->sense_addr = cpu_to_le32(sense_addr);
-   scsiqp->sense_len = cpu_to_le32(SCSI_SENSE_BUFFERSIZE);
+   scsiqp->sense_len = SCSI_SENSE_BUFFERSIZE;
 
/* Build ADV_SCSI_REQ_Q */
 
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 3/9] IB: add a helper to safely drain a QP

2015-11-16 Thread Steve Wise

On 11/15/2015 3:34 AM, Sagi Grimberg wrote:



+
+struct ib_stop_cqe {
+struct ib_cqecqe;
+struct completion done;
+};
+
+static void ib_stop_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+struct ib_stop_cqe *stop =
+container_of(wc->wr_cqe, struct ib_stop_cqe, cqe);
+
+complete(&stop->done);
+}
+
+/*
+ * Change a queue pair into the error state and wait until all receive
+ * completions have been processed before destroying it. This avoids 
that

+ * the receive completion handler can access the queue pair while it is
+ * being destroyed.
+ */
+void ib_drain_qp(struct ib_qp *qp)
+{
+struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR };
+struct ib_stop_cqe stop = { };
+struct ib_recv_wr wr, *bad_wr;
+int ret;
+
+wr.wr_cqe = &stop.cqe;
+stop.cqe.done = ib_stop_done;
+init_completion(&stop.done);
+
+ret = ib_modify_qp(qp, &attr, IB_QP_STATE);
+if (ret) {
+WARN_ONCE(ret, "failed to drain QP: %d\n", ret);
+return;
+}
+
+ret = ib_post_recv(qp, &wr, &bad_wr);
+if (ret) {
+WARN_ONCE(ret, "failed to drain QP: %d\n", ret);
+return;
+}
+
+wait_for_completion(&stop.done);
+}


This is taken from srp, and srp drains using a recv wr due to a race
causing a use-after-free condition in srp which re-posts a recv buffer
in the recv completion handler. srp does not really care if there are
pending send flushes.

I'm not sure if there are ordering rules for send/recv queues in
terms of flush completions, meaning that even if all recv flushes
were consumed maybe there are send flushes still pending.

I think that for a general drain helper it would be useful to
make sure that both the recv _and_ send flushes were drained.

So, something like:

void ib_drain_qp(struct ib_qp *qp)
{
struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR };
struct ib_stop_cqe rstop, sstop;
struct ib_recv_wr rwr = {}, *bad_rwr;
struct ib_send_wr swr = {}, *bad_swr;
int ret;

rwr.wr_cqe = &rstop.cqe;
rstop.cqe.done = ib_stop_done;
init_completion(&rstop.done);

swr.wr_cqe = &sstop.cqe;
sstop.cqe.done = ib_stop_done;
init_completion(&sstop.done);

ret = ib_modify_qp(qp, &attr, IB_QP_STATE);
if (ret) {
WARN_ONCE(ret, "failed to drain QP: %d\n", ret);
return;
}

ret = ib_post_recv(qp, &rwr, &bad_rwr);
if (ret) {
WARN_ONCE(ret, "failed to drain recv queue: %d\n", ret);
return;
}

ret = ib_post_send(qp, &swr, &bad_swr);
if (ret) {
WARN_ONCE(ret, "failed to drain send queue: %d\n", ret);
return;
}

wait_for_completion(&rstop.done);
wait_for_completion(&sstop.done);
}

Thoughts?


This won't work for iWARP as per my previous email.  But I will code 
something up that will.


Steve
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH for-next 05/10] iser: Have initiator and target to share protocol structures and definitions

2015-11-16 Thread Sagi Grimberg
The iser RDMA_CM negotiation protocol is shared by
the initiator and the target, so have a shared header
for the defines and structure. Move relevant items from
the initiator and target headers.

Signed-off-by: Sagi Grimberg 
Signed-off-by: Jenny Derzhavetz 
Cc: linux-scsi 
---
 drivers/infiniband/ulp/iser/iscsi_iser.h |  41 ++
 drivers/infiniband/ulp/iser/iser_initiator.c |   6 +-
 drivers/infiniband/ulp/iser/iser_verbs.c |   7 +-
 drivers/infiniband/ulp/isert/ib_isert.c  |  22 +++---
 drivers/infiniband/ulp/isert/ib_isert.h  |   6 +-
 include/scsi/iser.h  | 109 +++
 6 files changed, 135 insertions(+), 56 deletions(-)
 create mode 100644 include/scsi/iser.h

diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h 
b/drivers/infiniband/ulp/iser/iscsi_iser.h
index fb7fa7aa113c..096d5234bbea 100644
--- a/drivers/infiniband/ulp/iser/iscsi_iser.h
+++ b/drivers/infiniband/ulp/iser/iscsi_iser.h
@@ -48,6 +48,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include 
 #include 
@@ -154,43 +155,11 @@
 #define ISER_WC_BATCH_COUNT   16
 #define ISER_SIGNAL_CMD_COUNT 32
 
-#define ISER_VER   0x10
-#define ISER_WSV   0x08
-#define ISER_RSV   0x04
-
 #define ISER_FASTREG_LI_WRID   0xULL
 #define ISER_BEACON_WRID   0xfffeULL
 
-/**
- * struct iser_hdr - iSER header
- *
- * @flags:flags support (zbva, remote_inv)
- * @rsvd: reserved
- * @write_stag:   write rkey
- * @write_va: write virtual address
- * @reaf_stag:read rkey
- * @read_va:  read virtual address
- */
-struct iser_hdr {
-   u8  flags;
-   u8  rsvd[3];
-   __be32  write_stag;
-   __be64  write_va;
-   __be32  read_stag;
-   __be64  read_va;
-} __attribute__((packed));
-
-
-#define ISER_ZBVA_NOT_SUPPORTED0x80
-#define ISER_SEND_W_INV_NOT_SUPPORTED  0x40
-
-struct iser_cm_hdr {
-   u8  flags;
-   u8  rsvd[3];
-} __packed;
-
-/* Constant PDU lengths calculations */
-#define ISER_HEADERS_LEN  (sizeof(struct iser_hdr) + sizeof(struct iscsi_hdr))
+/*Constant PDU lengths calculations */
+#define ISER_HEADERS_LEN   (sizeof(struct iser_ctrl) + sizeof(struct 
iscsi_hdr))
 
 #define ISER_RECV_DATA_SEG_LEN 128
 #define ISER_RX_PAYLOAD_SIZE   (ISER_HEADERS_LEN + ISER_RECV_DATA_SEG_LEN)
@@ -287,7 +256,7 @@ enum iser_desc_type {
  * @sig_attrs: Signature attributes
  */
 struct iser_tx_desc {
-   struct iser_hdr  iser_header;
+   struct iser_ctrl iser_header;
struct iscsi_hdr iscsi_header;
enum   iser_desc_typetype;
u64  dma_addr;
@@ -318,7 +287,7 @@ struct iser_tx_desc {
  * @pad:   for sense data TODO: Modify to maximum sense length 
supported
  */
 struct iser_rx_desc {
-   struct iser_hdr  iser_header;
+   struct iser_ctrl iser_header;
struct iscsi_hdr iscsi_header;
char data[ISER_RECV_DATA_SEG_LEN];
u64  dma_addr;
diff --git a/drivers/infiniband/ulp/iser/iser_initiator.c 
b/drivers/infiniband/ulp/iser/iser_initiator.c
index 07bf26427ee7..6a968e350c14 100644
--- a/drivers/infiniband/ulp/iser/iser_initiator.c
+++ b/drivers/infiniband/ulp/iser/iser_initiator.c
@@ -51,7 +51,7 @@ static int iser_prepare_read_cmd(struct iscsi_task *task)
struct iscsi_iser_task *iser_task = task->dd_data;
struct iser_mem_reg *mem_reg;
int err;
-   struct iser_hdr *hdr = &iser_task->desc.iser_header;
+   struct iser_ctrl *hdr = &iser_task->desc.iser_header;
struct iser_data_buf *buf_in = &iser_task->data[ISER_DIR_IN];
 
err = iser_dma_map_task_data(iser_task,
@@ -104,7 +104,7 @@ iser_prepare_write_cmd(struct iscsi_task *task,
struct iscsi_iser_task *iser_task = task->dd_data;
struct iser_mem_reg *mem_reg;
int err;
-   struct iser_hdr *hdr = &iser_task->desc.iser_header;
+   struct iser_ctrl *hdr = &iser_task->desc.iser_header;
struct iser_data_buf *buf_out = &iser_task->data[ISER_DIR_OUT];
struct ib_sge *tx_dsg = &iser_task->desc.tx_sg[1];
 
@@ -167,7 +167,7 @@ static void iser_create_send_desc(struct iser_conn  
*iser_conn,
ib_dma_sync_single_for_cpu(device->ib_device,
tx_desc->dma_addr, ISER_HEADERS_LEN, DMA_TO_DEVICE);
 
-   memset(&tx_desc->iser_header, 0, sizeof(struct iser_hdr));
+   memset(&tx_desc->iser_header, 0, sizeof(struct iser_ctrl));
tx_desc->iser_header.flags = ISER_VER;
tx_desc->num_sge = 1;
 }
diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c 
b/drivers/infiniband/ulp/iser/iser_verbs.c
index 09121e774d14..74161a566852 100644
--- a/drivers/infiniband/ulp/iser/iser_verbs.c
+++ b/drivers/infiniband/ulp/iser/iser_verbs.c
@@ -847,10 +847,9 @@

Re: [PATCH v4 02/32] devicetree: bindings: scsi: HiSi SAS

2015-11-16 Thread Rob Herring
On Mon, Nov 16, 2015 at 09:05:48PM +0800, John Garry wrote:
> Add devicetree bindings for HiSilicon SAS driver.
> 
> Signed-off-by: John Garry 
> Signed-off-by: Zhangfei Gao 

Acked-by: Rob Herring 

> ---
>  .../devicetree/bindings/scsi/hisilicon-sas.txt | 69 
> ++
>  1 file changed, 69 insertions(+)
>  create mode 100644 Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
> 
> diff --git a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt 
> b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
> new file mode 100644
> index 000..f67e761
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
> @@ -0,0 +1,69 @@
> +* HiSilicon SAS controller
> +
> +The HiSilicon SAS controller supports SAS/SATA.
> +
> +Main node required properties:
> +  - compatible : value should be as follows:
> + (a) "hisilicon,hip05-sas-v1" for v1 hw in hip05 chipset
> +  - sas-addr : array of 8 bytes for host SAS address
> +  - reg : Address and length of the SAS register
> +  - hisilicon,sas-syscon: phandle of syscon used for sas control
> +  - ctrl-reset-reg : offset to controller reset register in ctrl reg
> +  - ctrl-reset-sts-reg : offset to controller reset status register in ctrl 
> reg
> +  - ctrl-clock-ena-reg : offset to controller clock enable register in ctrl 
> reg
> +  - queue-count : number of delivery and completion queues in the controller
> +  - phy-count : number of phys accessible by the controller
> +  - interrupts : Interrupts for phys, completion queues, and fatal
> + sources; the interrupts are ordered in 3 groups, as follows:
> + - Phy interrupts
> + - Completion queue interrupts
> + - Fatal interrupts
> + Phy interrupts : Each phy has 3 interrupt sources:
> + - broadcast
> + - phyup
> + - abnormal
> + The phy interrupts are ordered into groups of 3 per phy
> + (broadcast, phyup, and abnormal) in increasing order.
> + Completion queue interrupts : each completion queue has 1
> + interrupt source.
> + The interrupts are ordered in increasing order.
> + Fatal interrupts : the fatal interrupts are ordered as follows:
> + - ECC
> + - AXI bus
> +
> +Example:
> + sas0: sas@c100 {
> + compatible = "hisilicon,hip05-sas-v1";
> + sas-addr = [50 01 88 20 16 00 00 0a];
> + reg = <0x0 0xc100 0x0 0x1>;
> + hisilicon,sas-syscon = <&pcie_sas>;
> + ctrl-reset-reg = <0xa60>;
> + ctrl-reset-sts-reg = <0x5a30>;
> + ctrl-clock-ena-reg = <0x338>;
> + queue-count = <32>;
> + phy-count = <8>;
> + dma-coherent;
> + interrupt-parent = <&mbigen_dsa>;
> + interrupts =<259 4>,<263 4>,<264 4>,/* phy0 */
> + <269 4>,<273 4>,<274 4>,/* phy1 */
> + <279 4>,<283 4>,<284 4>,/* phy2 */
> + <289 4>,<293 4>,<294 4>,/* phy3 */
> + <299 4>,<303 4>,<304 4>,/* phy4 */
> + <309 4>,<313 4>,<314 4>,/* phy5 */
> + <319 4>,<323 4>,<324 4>,/* phy6 */
> + <329 4>,<333 4>,<334 4>,/* phy7 */
> + <336 1>,<337 1>,<338 1>,/* cq0-2 */
> + <339 1>,<340 1>,<341 1>,/* cq3-5 */
> + <342 1>,<343 1>,<344 1>,/* cq6-8 */
> + <345 1>,<346 1>,<347 1>,/* cq9-11 */
> + <348 1>,<349 1>,<350 1>,/* cq12-14 */
> + <351 1>,<352 1>,<353 1>,/* cq15-17 */
> + <354 1>,<355 1>,<356 1>,/* cq18-20 */
> + <357 1>,<358 1>,<359 1>,/* cq21-23 */
> + <360 1>,<361 1>,<362 1>,/* cq24-26 */
> + <363 1>,<364 1>,<365 1>,/* cq27-29 */
> + <366 1>,<367 1>/* cq30-31 */
> + <376 4>,/* fatal ecc */
> + <381 4>;/* fatal axi */
> + status = "disabled";
> + };
> -- 
> 1.9.1
> 
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 18/32] scsi: hisi_sas: add v1 hardware register definitions

2015-11-16 Thread John Garry
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 389 +
 1 file changed, 389 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index e9aebce..9fe89bb 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -12,10 +12,399 @@
 #include "hisi_sas.h"
 #define DRV_NAME "hisi_sas_v1_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 BROKEN_MSG_ADDR_LO 0x18
+#define BROKEN_MSG_ADDR_HI 0x1c
+#define PHY_CONTEXT0x20
+#define PHY_STATE  0x24
+#define PHY_PORT_NUM_MA0x28
+#define PORT_STATE 0x2c
+#define PHY_CONN_RATE  0x30
+#define HGC_TRANS_TASK_CNT_LIMIT   0x38
+#define AXI_AHB_CLK_CFG0x3c
+#define HGC_SAS_TXFAIL_RETRY_CTRL  0x84
+#define HGC_GET_ITV_TIME   0x90
+#define DEVICE_MSG_WORK_MODE   0x94
+#define I_T_NEXUS_LOSS_TIME0xa0
+#define BUS_INACTIVE_LIMIT_TIME0xa8
+#define REJECT_TO_OPEN_LIMIT_TIME  0xac
+#define CFG_AGING_TIME 0xbc
+#define CFG_AGING_TIME_ITCT_REL_OFF0
+#define CFG_AGING_TIME_ITCT_REL_MSK(0x1 << CFG_AGING_TIME_ITCT_REL_OFF)
+#define HGC_DFX_CFG2   0xc0
+#define FIS_LIST_BADDR_L   0xc4
+#define CFG_1US_TIMER_TRSH 0xcc
+#define CFG_SAS_CONFIG 0xd4
+#define HGC_IOST_ECC_ADDR  0x140
+#define HGC_IOST_ECC_ADDR_BAD_OFF  16
+#define HGC_IOST_ECC_ADDR_BAD_MSK  (0x3ff << HGC_IOST_ECC_ADDR_BAD_OFF)
+#define HGC_DQ_ECC_ADDR0x144
+#define HGC_DQ_ECC_ADDR_BAD_OFF16
+#define HGC_DQ_ECC_ADDR_BAD_MSK(0xfff << 
HGC_DQ_ECC_ADDR_BAD_OFF)
+#define HGC_INVLD_DQE_INFO 0x148
+#define HGC_INVLD_DQE_INFO_DQ_OFF  0
+#define HGC_INVLD_DQE_INFO_DQ_MSK  (0x << HGC_INVLD_DQE_INFO_DQ_OFF)
+#define HGC_INVLD_DQE_INFO_TYPE_OFF16
+#define HGC_INVLD_DQE_INFO_TYPE_MSK(0x1 << HGC_INVLD_DQE_INFO_TYPE_OFF)
+#define HGC_INVLD_DQE_INFO_FORCE_OFF   17
+#define HGC_INVLD_DQE_INFO_FORCE_MSK   (0x1 << HGC_INVLD_DQE_INFO_FORCE_OFF)
+#define HGC_INVLD_DQE_INFO_PHY_OFF 18
+#define HGC_INVLD_DQE_INFO_PHY_MSK (0x1 << HGC_INVLD_DQE_INFO_PHY_OFF)
+#define HGC_INVLD_DQE_INFO_ABORT_OFF   19
+#define HGC_INVLD_DQE_INFO_ABORT_MSK   (0x1 << HGC_INVLD_DQE_INFO_ABORT_OFF)
+#define HGC_INVLD_DQE_INFO_IPTT_OF_OFF 20
+#define HGC_INVLD_DQE_INFO_IPTT_OF_MSK (0x1 << HGC_INVLD_DQE_INFO_IPTT_OF_OFF)
+#define HGC_INVLD_DQE_INFO_SSP_ERR_OFF 21
+#define HGC_INVLD_DQE_INFO_SSP_ERR_MSK (0x1 << HGC_INVLD_DQE_INFO_SSP_ERR_OFF)
+#define HGC_INVLD_DQE_INFO_OFL_OFF 22
+#define HGC_INVLD_DQE_INFO_OFL_MSK (0x1 << HGC_INVLD_DQE_INFO_OFL_OFF)
+#define HGC_ITCT_ECC_ADDR  0x150
+#define HGC_ITCT_ECC_ADDR_BAD_OFF  16
+#define HGC_ITCT_ECC_ADDR_BAD_MSK  (0x3ff << HGC_ITCT_ECC_ADDR_BAD_OFF)
+#define HGC_AXI_FIFO_ERR_INFO  0x154
+#define INT_COAL_EN0x1bc
+#define OQ_INT_COAL_TIME   0x1c0
+#define OQ_INT_COAL_CNT0x1c4
+#define ENT_INT_COAL_TIME  0x1c8
+#define ENT_INT_COAL_CNT   0x1cc
+#define OQ_INT_SRC 0x1d0
+#define OQ_INT_SRC_MSK 0x1d4
+#define ENT_INT_SRC1   0x1d8
+#define ENT_INT_SRC2   0x1dc
+#define ENT_INT_SRC2_DQ_CFG_ERR_OFF25
+#define ENT_INT_SRC2_DQ_CFG_ERR_MSK(0x1 << ENT_INT_SRC2_DQ_CFG_ERR_OFF)
+#define ENT_INT_SRC2_CQ_CFG_ERR_OFF27
+#define ENT_INT_SRC2_CQ_CFG_ERR_MSK(0x1 << ENT_INT_SRC2_CQ_CFG_ERR_OFF)
+#define ENT_INT_SRC2_AXI_WRONG_INT_OFF 28
+#define ENT_INT_SRC2_AXI_WRONG_INT_MSK (0x1 << ENT_INT_SRC2_AXI_WRONG_INT_OFF)
+#define ENT_INT_SRC2_AXI_OVERLF_INT_OFF29
+#define ENT_INT_SRC2_AXI_OVERLF_INT_MSK(0x1 << 
ENT_INT_SRC2_AXI_OVERLF_INT_OFF)
+#define ENT_INT_SRC_MSK1   0x1e0
+#define ENT_INT_SRC_MSK2   0x1e4
+#define SAS_ECC_INTR   0x1e8
+#define SAS_ECC_INTR_DQ_ECC1B_OFF  0
+#define SAS_ECC_INTR_DQ_ECC1B_MSK  (0x1 << SAS_ECC_INTR_DQ_ECC1B_OFF)
+#define SAS_ECC_INTR_DQ_ECCBAD_OFF 1
+#define SAS_ECC_INTR_DQ_ECCBAD_MSK (0x1 << SAS_ECC_INTR_DQ_ECCBAD_OFF)
+#define SAS_ECC_INTR_IOST_ECC1B_OFF2
+#define SAS_ECC_INTR_IOST_ECC1B_MSK(0x1 << SAS_ECC_INTR_IOST_ECC1B_OFF)
+#define SAS_ECC_INTR_IOST_ECCBAD_OFF   3
+#define SAS_ECC_INTR_IOST_ECCBAD_MSK   (0x1 << SAS_ECC_INTR_IOST_ECCBAD_OFF)
+#define SAS_ECC_INTR_ITCT_ECC1B_OFF4
+#define SAS_ECC_INTR_ITCT_ECC1B_MSK(0x1 << SAS_ECC_INTR_ITCT_ECC1B_OFF)
+#define SAS_ECC_INTR_I

[PATCH v4 28/32] scsi: hisi_sas: add scan finished and start

2015-11-16 Thread John Garry
Add functions for scsi host template scan_finished
and scan_start methods

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

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index f34f73b..15adeca 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -156,6 +156,7 @@ struct hisi_hba {
u8 sas_addr[SAS_ADDR_SIZE];
 
int n_phy;
+   int scan_finished;
spinlock_t lock;
 
struct timer_list timer;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 406ffa0..63ebaf3 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -403,6 +403,29 @@ static int hisi_sas_dev_found(struct domain_device *device)
return 0;
 }
 
+static void hisi_sas_scan_start(struct Scsi_Host *shost)
+{
+   struct hisi_hba *hisi_hba = shost_priv(shost);
+   int i;
+
+   for (i = 0; i < hisi_hba->n_phy; ++i)
+   hisi_sas_bytes_dmaed(hisi_hba, i);
+
+   hisi_hba->scan_finished = 1;
+}
+
+static int hisi_sas_scan_finished(struct Scsi_Host *shost, unsigned long time)
+{
+   struct hisi_hba *hisi_hba = shost_priv(shost);
+   struct sas_ha_struct *sha = &hisi_hba->sha;
+
+   if (hisi_hba->scan_finished == 0)
+   return 0;
+
+   sas_drain_work(sha);
+   return 1;
+}
+
 static void hisi_sas_phyup_work(struct work_struct *work)
 {
struct hisi_sas_phy *phy =
@@ -587,6 +610,8 @@ static struct scsi_host_template hisi_sas_sht = {
.queuecommand   = sas_queuecommand,
.target_alloc   = sas_target_alloc,
.slave_configure= sas_slave_configure,
+   .scan_finished  = hisi_sas_scan_finished,
+   .scan_start = hisi_sas_scan_start,
.change_queue_depth = sas_change_queue_depth,
.bios_param = sas_bios_param,
.can_queue  = 1,
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 29/32] scsi: hisi_sas: add tmf methods

2015-11-16 Thread John Garry
Add function methods for tmf's.

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_main.c | 309 ++
 1 file changed, 309 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 63ebaf3..4ee90eb 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -553,6 +553,309 @@ static int hisi_sas_queue_command(struct sas_task *task, 
gfp_t gfp_flags)
 }
 
 
+static void hisi_sas_task_done(struct sas_task *task)
+{
+   if (!del_timer(&task->slow_task->timer))
+   return;
+   complete(&task->slow_task->completion);
+}
+
+static void hisi_sas_tmf_timedout(unsigned long data)
+{
+   struct sas_task *task = (struct sas_task *)data;
+
+   task->task_state_flags |= SAS_TASK_STATE_ABORTED;
+   complete(&task->slow_task->completion);
+}
+
+#define TASK_TIMEOUT 20
+#define TASK_RETRY 3
+static int hisi_sas_exec_internal_tmf_task(struct domain_device *device,
+  void *parameter, u32 para_len,
+  struct hisi_sas_tmf_task *tmf)
+{
+   struct hisi_sas_device *sas_dev = device->lldd_dev;
+   struct hisi_hba *hisi_hba = sas_dev->hisi_hba;
+   struct device *dev = &hisi_hba->pdev->dev;
+   struct sas_task *task;
+   int res, retry;
+
+   for (retry = 0; retry < TASK_RETRY; retry++) {
+   task = sas_alloc_slow_task(GFP_KERNEL);
+   if (!task)
+   return -ENOMEM;
+
+   task->dev = device;
+   task->task_proto = device->tproto;
+
+   memcpy(&task->ssp_task, parameter, para_len);
+   task->task_done = hisi_sas_task_done;
+
+   task->slow_task->timer.data = (unsigned long) task;
+   task->slow_task->timer.function = hisi_sas_tmf_timedout;
+   task->slow_task->timer.expires = jiffies + TASK_TIMEOUT*HZ;
+   add_timer(&task->slow_task->timer);
+
+   res = hisi_sas_task_exec(task, GFP_KERNEL, 1, tmf);
+
+   if (res) {
+   del_timer(&task->slow_task->timer);
+   dev_err(dev, "abort tmf: executing internal task 
failed: %d\n",
+   res);
+   goto ex_err;
+   }
+
+   wait_for_completion(&task->slow_task->completion);
+   res = TMF_RESP_FUNC_FAILED;
+   /* Even TMF timed out, return direct. */
+   if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) {
+   if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) {
+   dev_err(dev, "abort tmf: TMF task[%d] 
timeout\n",
+   tmf->tag_of_task_to_be_managed);
+   if (task->lldd_task) {
+   struct hisi_sas_slot *slot =
+   task->lldd_task;
+
+   hisi_sas_slot_task_free(hisi_hba,
+   task, slot);
+   }
+
+   goto ex_err;
+   }
+   }
+
+   if (task->task_status.resp == SAS_TASK_COMPLETE &&
+   task->task_status.stat == SAM_STAT_GOOD) {
+   res = TMF_RESP_FUNC_COMPLETE;
+   break;
+   }
+
+   if (task->task_status.resp == SAS_TASK_COMPLETE &&
+ task->task_status.stat == SAS_DATA_UNDERRUN) {
+   /* no error, but return the number of bytes of
+* underrun
+*/
+   dev_warn(dev, "abort tmf: task to dev %016llx "
+"resp: 0x%x sts 0x%x underrun\n",
+SAS_ADDR(device->sas_addr),
+task->task_status.resp,
+task->task_status.stat);
+   res = task->task_status.residual;
+   break;
+   }
+
+   if (task->task_status.resp == SAS_TASK_COMPLETE &&
+   task->task_status.stat == SAS_DATA_OVERRUN) {
+   dev_warn(dev, "abort tmf: blocked task error\n");
+   res = -EMSGSIZE;
+   break;
+   }
+
+   dev_warn(dev, "abort tmf: task to dev "
+"%016llx resp: 0x%x status 0x%x\n",
+SAS_ADDR(device->sas_addr), task->task_status.resp,
+task->task_status.stat);
+   sas_free_task(task);
+   task = NULL;
+   }
+ex_err:
+   WARN_ON(retry == TASK_RETRY);
+   sas_free_task(task);
+   return res;
+}
+

[PATCH v4 31/32] scsi: hisi_sas: add fatal irq handler

2015-11-16 Thread John Garry
Add handlers for fatal interrupts

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 119 +
 1 file changed, 119 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index a95259c..e29b7c7 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -1573,6 +1573,93 @@ static irqreturn_t cq_interrupt_v1_hw(int irq, void *p)
return IRQ_HANDLED;
 }
 
+static irqreturn_t fatal_ecc_int_v1_hw(int irq, void *p)
+{
+   struct hisi_hba *hisi_hba = p;
+   struct device *dev = &hisi_hba->pdev->dev;
+   u32 ecc_int = hisi_sas_read32(hisi_hba, SAS_ECC_INTR);
+
+   if (ecc_int & SAS_ECC_INTR_DQ_ECC1B_MSK) {
+   u32 ecc_err = hisi_sas_read32(hisi_hba, HGC_ECC_ERR);
+
+   panic("%s: Fatal DQ 1b ECC interrupt (0x%x)\n",
+ dev_name(dev), ecc_err);
+   }
+
+   if (ecc_int & SAS_ECC_INTR_DQ_ECCBAD_MSK) {
+   u32 addr = (hisi_sas_read32(hisi_hba, HGC_DQ_ECC_ADDR) &
+   HGC_DQ_ECC_ADDR_BAD_MSK) >>
+   HGC_DQ_ECC_ADDR_BAD_OFF;
+
+   panic("%s: Fatal DQ RAM ECC interrupt @ 0x%08x\n",
+ dev_name(dev), addr);
+   }
+
+   if (ecc_int & SAS_ECC_INTR_IOST_ECC1B_MSK) {
+   u32 ecc_err = hisi_sas_read32(hisi_hba, HGC_ECC_ERR);
+
+   panic("%s: Fatal IOST 1b ECC interrupt (0x%x)\n",
+ dev_name(dev), ecc_err);
+   }
+
+   if (ecc_int & SAS_ECC_INTR_IOST_ECCBAD_MSK) {
+   u32 addr = (hisi_sas_read32(hisi_hba, HGC_IOST_ECC_ADDR) &
+   HGC_IOST_ECC_ADDR_BAD_MSK) >>
+   HGC_IOST_ECC_ADDR_BAD_OFF;
+
+   panic("%s: Fatal IOST RAM ECC interrupt @ 0x%08x\n",
+ dev_name(dev), addr);
+   }
+
+   if (ecc_int & SAS_ECC_INTR_ITCT_ECCBAD_MSK) {
+   u32 addr = (hisi_sas_read32(hisi_hba, HGC_ITCT_ECC_ADDR) &
+   HGC_ITCT_ECC_ADDR_BAD_MSK) >>
+   HGC_ITCT_ECC_ADDR_BAD_OFF;
+
+   panic("%s: Fatal TCT RAM ECC interrupt @ 0x%08x\n",
+ dev_name(dev), addr);
+   }
+
+   if (ecc_int & SAS_ECC_INTR_ITCT_ECC1B_MSK) {
+   u32 ecc_err = hisi_sas_read32(hisi_hba, HGC_ECC_ERR);
+
+   panic("%s: Fatal ITCT 1b ECC interrupt (0x%x)\n",
+ dev_name(dev), ecc_err);
+   }
+
+   hisi_sas_write32(hisi_hba, SAS_ECC_INTR, ecc_int | 0x3f);
+
+   return IRQ_HANDLED;
+}
+
+static irqreturn_t fatal_axi_int_v1_hw(int irq, void *p)
+{
+   struct hisi_hba *hisi_hba = p;
+   struct device *dev = &hisi_hba->pdev->dev;
+   u32 axi_int = hisi_sas_read32(hisi_hba, ENT_INT_SRC2);
+   u32 axi_info = hisi_sas_read32(hisi_hba, HGC_AXI_FIFO_ERR_INFO);
+
+   if (axi_int & ENT_INT_SRC2_DQ_CFG_ERR_MSK)
+   panic("%s: Fatal DQ_CFG_ERR interrupt (0x%x)\n",
+ dev_name(dev), axi_info);
+
+   if (axi_int & ENT_INT_SRC2_CQ_CFG_ERR_MSK)
+   panic("%s: Fatal CQ_CFG_ERR interrupt (0x%x)\n",
+ dev_name(dev), axi_info);
+
+   if (axi_int & ENT_INT_SRC2_AXI_WRONG_INT_MSK)
+   panic("%s: Fatal AXI_WRONG_INT interrupt (0x%x)\n",
+ dev_name(dev), axi_info);
+
+   if (axi_int & ENT_INT_SRC2_AXI_OVERLF_INT_MSK)
+   panic("%s: Fatal AXI_OVERLF_INT incorrect interrupt (0x%x)\n",
+ dev_name(dev), axi_info);
+
+   hisi_sas_write32(hisi_hba, ENT_INT_SRC2, axi_int | 0x3000);
+
+   return IRQ_HANDLED;
+}
+
 static const char phy_int_names[HISI_SAS_PHY_INT_NR][32] = {
{"Bcast"},
{"Phy Up"},
@@ -1580,12 +1667,22 @@ static const char 
phy_int_names[HISI_SAS_PHY_INT_NR][32] = {
 };
 
 static const char cq_int_name[32] = "cq";
+static const char fatal_int_name[HISI_SAS_FATAL_INT_NR][32] = {
+   "fatal ecc",
+   "fatal axi"
+};
+
 static irq_handler_t phy_interrupts[HISI_SAS_PHY_INT_NR] = {
int_bcast_v1_hw,
int_phyup_v1_hw,
int_abnormal_v1_hw
 };
 
+static irq_handler_t fatal_interrupts[HISI_SAS_MAX_QUEUES] = {
+   fatal_ecc_int_v1_hw,
+   fatal_axi_int_v1_hw
+};
+
 static int interrupt_init_v1_hw(struct hisi_hba *hisi_hba)
 {
struct device *dev = &hisi_hba->pdev->dev;
@@ -1646,6 +1743,28 @@ static int interrupt_init_v1_hw(struct hisi_hba 
*hisi_hba)
}
}
 
+   idx = (hisi_hba->n_phy * HISI_SAS_PHY_INT_NR) + hisi_hba->queue_count;
+   for (i = 0; i < HISI_SAS_FATAL_INT_NR; i++, idx++) {
+   irq = irq_of_parse_and_map(np, idx);
+   if (!irq) {
+   dev_err(dev, "irq init: could not map fatal interrupt 
%d\n",
+   idx);
+   return -

[PATCH v4 26/32] scsi: hisi_sas: add bcast interrupt handler

2015-11-16 Thread John Garry
This is for expander broadcast event.

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 31 +++
 1 file changed, 31 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index 1723dd4..ad50aed 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -1333,6 +1333,35 @@ end:
return res;
 }
 
+static irqreturn_t int_bcast_v1_hw(int irq, void *p)
+{
+   struct hisi_sas_phy *phy = p;
+   struct hisi_hba *hisi_hba = phy->hisi_hba;
+   struct asd_sas_phy *sas_phy = &phy->sas_phy;
+   struct sas_ha_struct *sha = &hisi_hba->sha;
+   struct device *dev = &hisi_hba->pdev->dev;
+   int phy_no = sas_phy->id;
+   u32 irq_value;
+   irqreturn_t res = IRQ_HANDLED;
+
+   irq_value = hisi_sas_phy_read32(hisi_hba, phy_no, CHL_INT2);
+
+   if (!(irq_value & CHL_INT2_SL_RX_BC_ACK_MSK)) {
+   dev_err(dev, "bcast: irq_value = %x not set enable bit",
+   irq_value);
+   res = IRQ_NONE;
+   goto end;
+   }
+
+   sha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+
+end:
+   hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT2,
+CHL_INT2_SL_RX_BC_ACK_MSK);
+
+   return res;
+}
+
 static irqreturn_t int_abnormal_v1_hw(int irq, void *p)
 {
struct hisi_sas_phy *phy = p;
@@ -1438,12 +1467,14 @@ static irqreturn_t cq_interrupt_v1_hw(int irq, void *p)
 }
 
 static const char phy_int_names[HISI_SAS_PHY_INT_NR][32] = {
+   {"Bcast"},
{"Phy Up"},
{"Abnormal"},
 };
 
 static const char cq_int_name[32] = "cq";
 static irq_handler_t phy_interrupts[HISI_SAS_PHY_INT_NR] = {
+   int_bcast_v1_hw,
int_phyup_v1_hw,
int_abnormal_v1_hw
 };
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 24/32] scsi: hisi_sas: add dev_found and dev_gone

2015-11-16 Thread John Garry
Add functions to deal with lldd_dev_found and lldd_dev_gone.

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   | 13 +
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 88 ++
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 41 
 3 files changed, 142 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index fe4055b..999f319 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -39,6 +39,7 @@
 
 #define HISI_SAS_NAME_LEN 32
 
+struct hisi_hba;
 
 enum {
PORT_TYPE_SAS = (1U << 1),
@@ -49,6 +50,13 @@ enum dev_status {
HISI_SAS_DEV_NORMAL,
HISI_SAS_DEV_EH,
 };
+
+enum hisi_sas_dev_type {
+   HISI_SAS_DEV_TYPE_STP = 0,
+   HISI_SAS_DEV_TYPE_SSP,
+   HISI_SAS_DEV_TYPE_SATA,
+};
+
 struct hisi_sas_phy {
struct hisi_hba *hisi_hba;
struct hisi_sas_port*port;
@@ -81,6 +89,9 @@ struct hisi_sas_cq {
 
 struct hisi_sas_device {
enum sas_device_typedev_type;
+   struct hisi_hba *hisi_hba;
+   struct domain_device*sas_device;
+   u64 attached_phy;
u64 device_id;
u64 running_req;
u8 dev_status;
@@ -113,6 +124,8 @@ struct hisi_sas_tmf_task {
 
 struct hisi_sas_hw {
int (*hw_init)(struct hisi_hba *hisi_hba);
+   void (*setup_itct)(struct hisi_hba *hisi_hba,
+  struct hisi_sas_device *device);
void (*sl_notify)(struct hisi_hba *hisi_hba, int phy_no);
int (*get_free_slot)(struct hisi_hba *hisi_hba, int *q, int *s);
void (*start_delivery)(struct hisi_hba *hisi_hba);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index ddbd2b71..d8af4c6 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -12,6 +12,9 @@
 #include "hisi_sas.h"
 #define DRV_NAME "hisi_sas"
 
+#define DEV_IS_EXPANDER(type) \
+   ((type == SAS_EDGE_EXPANDER_DEVICE) || \
+   (type == SAS_FANOUT_EXPANDER_DEVICE))
 
 #define DEV_IS_GONE(dev) \
((!dev) || (dev->dev_type == SAS_PHY_UNUSED))
@@ -325,6 +328,72 @@ static void hisi_sas_bytes_dmaed(struct hisi_hba 
*hisi_hba, int phy_no)
sas_ha->notify_port_event(sas_phy, PORTE_BYTES_DMAED);
 }
 
+static struct hisi_sas_device *hisi_sas_alloc_dev(struct domain_device *device)
+{
+   struct hisi_hba *hisi_hba = dev_to_hisi_hba(device);
+   struct hisi_sas_device *sas_dev = NULL;
+   int i;
+
+   spin_lock(&hisi_hba->lock);
+   for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
+   if (hisi_hba->devices[i].dev_type == SAS_PHY_UNUSED) {
+   hisi_hba->devices[i].device_id = i;
+   sas_dev = &hisi_hba->devices[i];
+   sas_dev->dev_status = HISI_SAS_DEV_NORMAL;
+   sas_dev->dev_type = device->dev_type;
+   sas_dev->hisi_hba = hisi_hba;
+   sas_dev->sas_device = device;
+   break;
+   }
+   }
+   spin_unlock(&hisi_hba->lock);
+
+   return sas_dev;
+}
+
+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 = &hisi_hba->pdev->dev;
+
+   sas_dev = hisi_sas_alloc_dev(device);
+   if (!sas_dev) {
+   dev_err(dev, "fail alloc dev: max support %d devices\n",
+   HISI_SAS_MAX_DEVICES);
+   return -EINVAL;
+   }
+
+   device->lldd_dev = sas_dev;
+   hisi_hba->hw->setup_itct(hisi_hba, sas_dev);
+
+   if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) {
+   int phy_no;
+   u8 phy_num = parent_dev->ex_dev.num_phys;
+   struct ex_phy *phy;
+
+   for (phy_no = 0; phy_no < phy_num; phy_no++) {
+   phy = &parent_dev->ex_dev.ex_phy[phy_no];
+   if (SAS_ADDR(phy->attached_sas_addr) ==
+   SAS_ADDR(device->sas_addr)) {
+   sas_dev->attached_phy = phy_no;
+   break;
+   }
+   }
+
+   if (phy_no == phy_num) {
+   dev_info(dev, "dev found: no attached "
+"dev:%016llx at ex:%016llx\n",
+SAS_ADDR(device->sas_addr),
+SAS_ADDR(parent_dev->sas_addr));
+   return -EINVAL;
+   }
+   }
+
+   return 0;
+}
+
 static void hisi_sas_phyup_work(struct work_struct *work)
 {
struct hisi_sas_phy *phy =
@@ -362,6 +431,23 @@ static void hisi_sas_phy_init(struct hisi_hba *hisi_hba, 
int phy_no)
INIT_WORK(&phy->phyup_ws, hi

[PATCH v4 03/32] scsi: hisi_sas: add initial bare main driver

2015-11-16 Thread John Garry
This patch adds the initial bare main driver for the
HiSilicon SAS HBA. This only introduces the changes to
build and load the main driver module.

The complete driver consists of the core main module and
also a module platform driver for driving the hw.

The HBA is a platform device.

Signed-off-by: John Garry 
Signed-off-by: Zhangfei Gao 
---
 drivers/scsi/Kconfig  |  1 +
 drivers/scsi/Makefile |  1 +
 drivers/scsi/hisi_sas/Kconfig |  6 +
 drivers/scsi/hisi_sas/Makefile|  1 +
 drivers/scsi/hisi_sas/hisi_sas.h  | 26 +
 drivers/scsi/hisi_sas/hisi_sas_main.c | 43 +++
 6 files changed, 78 insertions(+)
 create mode 100644 drivers/scsi/hisi_sas/Kconfig
 create mode 100644 drivers/scsi/hisi_sas/Makefile
 create mode 100644 drivers/scsi/hisi_sas/hisi_sas.h
 create mode 100644 drivers/scsi/hisi_sas/hisi_sas_main.c

diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 5f692ae..1a6a711 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1766,5 +1766,6 @@ source "drivers/scsi/pcmcia/Kconfig"
 source "drivers/scsi/device_handler/Kconfig"
 
 source "drivers/scsi/osd/Kconfig"
+source "drivers/scsi/hisi_sas/Kconfig"
 
 endmenu
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index c14bca4..862ab4e 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -157,6 +157,7 @@ obj-$(CONFIG_CHR_DEV_SCH)   += ch.o
 obj-$(CONFIG_SCSI_ENCLOSURE)   += ses.o
 
 obj-$(CONFIG_SCSI_OSD_INITIATOR) += osd/
+obj-$(CONFIG_SCSI_HISI_SAS) += hisi_sas/
 
 # This goes last, so that "real" scsi devices probe earlier
 obj-$(CONFIG_SCSI_DEBUG)   += scsi_debug.o
diff --git a/drivers/scsi/hisi_sas/Kconfig b/drivers/scsi/hisi_sas/Kconfig
new file mode 100644
index 000..37a0c71
--- /dev/null
+++ b/drivers/scsi/hisi_sas/Kconfig
@@ -0,0 +1,6 @@
+config SCSI_HISI_SAS
+   tristate "HiSilicon SAS"
+   select SCSI_SAS_LIBSAS
+   select BLK_DEV_INTEGRITY
+   help
+   This driver supports HiSilicon's SAS HBA
diff --git a/drivers/scsi/hisi_sas/Makefile b/drivers/scsi/hisi_sas/Makefile
new file mode 100644
index 000..d86b05e
--- /dev/null
+++ b/drivers/scsi/hisi_sas/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_SCSI_HISI_SAS)+= hisi_sas_main.o
diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
new file mode 100644
index 000..a5cec22
--- /dev/null
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015 Linaro Ltd.
+ * Copyright (c) 2015 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.
+ *
+ */
+
+#ifndef _HISI_SAS_H_
+#define _HISI_SAS_H_
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DRV_VERSION "v1.0"
+
+#endif
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
new file mode 100644
index 000..7201363
--- /dev/null
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 Linaro Ltd.
+ * Copyright (c) 2015 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"
+
+static struct scsi_transport_template *hisi_sas_stt;
+
+static struct sas_domain_function_template hisi_sas_transport_ops = {
+};
+
+static __init int hisi_sas_init(void)
+{
+   pr_info("hisi_sas: driver version %s\n", DRV_VERSION);
+
+   hisi_sas_stt = sas_domain_attach_transport(&hisi_sas_transport_ops);
+   if (!hisi_sas_stt)
+   return -ENOMEM;
+
+   return 0;
+}
+
+static __exit void hisi_sas_exit(void)
+{
+   sas_release_transport(hisi_sas_stt);
+}
+
+module_init(hisi_sas_init);
+module_exit(hisi_sas_exit);
+
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("John Garry ");
+MODULE_DESCRIPTION("HISILICON SAS controller driver");
+MODULE_ALIAS("platform:" DRV_NAME);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 23/32] scsi: hisi_sas: add cq interrupt handler

2015-11-16 Thread John Garry
Add cq interrupt handler and also slot error handler
function.

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |   9 +
 drivers/scsi/hisi_sas/hisi_sas_main.c  |  35 
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 345 +
 3 files changed, 389 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 72657eb..fe4055b 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -93,6 +93,8 @@ struct hisi_sas_slot {
u64 n_elem;
int dlvry_queue;
int dlvry_queue_slot;
+   int cmplt_queue;
+   int cmplt_queue_slot;
int idx;
void*cmd_hdr;
dma_addr_t cmd_hdr_dma;
@@ -117,6 +119,10 @@ struct hisi_sas_hw {
int (*prep_ssp)(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot, int is_tmf,
struct hisi_sas_tmf_task *tmf);
+   int (*slot_complete)(struct hisi_hba *hisi_hba,
+struct hisi_sas_slot *slot, int abort);
+   void (*free_device)(struct hisi_hba *hisi_hba,
+   struct hisi_sas_device *dev);
int complete_hdr_size;
 };
 
@@ -311,4 +317,7 @@ extern int hisi_sas_probe(struct platform_device *pdev,
  const struct hisi_sas_hw *ops);
 extern int hisi_sas_remove(struct platform_device *pdev);
 
+extern void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba,
+   struct sas_task *task,
+   struct hisi_sas_slot *slot);
 #endif
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 660ef6c..ddbd2b71 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -60,6 +60,41 @@ static void hisi_sas_slot_index_init(struct hisi_hba 
*hisi_hba)
for (i = 0; i < hisi_hba->slot_index_count; ++i)
hisi_sas_slot_index_clear(hisi_hba, i);
 }
+
+void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task,
+struct hisi_sas_slot *slot)
+{
+   struct device *dev = &hisi_hba->pdev->dev;
+
+   if (!slot->task)
+   return;
+
+   if (!sas_protocol_ata(task->task_proto))
+   if (slot->n_elem)
+   dma_unmap_sg(dev, task->scatter, slot->n_elem,
+task->data_dir);
+
+   if (slot->command_table)
+   dma_pool_free(hisi_hba->command_table_pool,
+ slot->command_table, slot->command_table_dma);
+
+   if (slot->status_buffer)
+   dma_pool_free(hisi_hba->status_buffer_pool,
+ slot->status_buffer, slot->status_buffer_dma);
+
+   if (slot->sge_page)
+   dma_pool_free(hisi_hba->sge_page_pool, slot->sge_page,
+ slot->sge_page_dma);
+
+   list_del_init(&slot->entry);
+   task->lldd_task = NULL;
+   slot->task = NULL;
+   slot->port = NULL;
+   hisi_sas_slot_index_free(hisi_hba, slot->idx);
+   memset(slot, 0, sizeof(*slot));
+}
+EXPORT_SYMBOL_GPL(hisi_sas_slot_task_free);
+
 static int hisi_sas_task_prep_ssp(struct hisi_hba *hisi_hba,
  struct hisi_sas_slot *slot, int is_tmf,
  struct hisi_sas_tmf_task *tmf)
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index 07b9750..6711c0a 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -498,6 +498,28 @@ static void init_id_frame_v1_hw(struct hisi_hba *hisi_hba)
config_id_frame_v1_hw(hisi_hba, i);
 }
 
+
+static void free_device_v1_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_device *sas_dev)
+{
+   u64 dev_id = sas_dev->device_id;
+   struct hisi_sas_itct *itct = &hisi_hba->itct[dev_id];
+   u32 qw0, reg_val = hisi_sas_read32(hisi_hba, CFG_AGING_TIME);
+
+   reg_val |= CFG_AGING_TIME_ITCT_REL_MSK;
+   hisi_sas_write32(hisi_hba, CFG_AGING_TIME, reg_val);
+
+   /* free itct */
+   udelay(1);
+   reg_val = hisi_sas_read32(hisi_hba, CFG_AGING_TIME);
+   reg_val &= ~CFG_AGING_TIME_ITCT_REL_MSK;
+   hisi_sas_write32(hisi_hba, CFG_AGING_TIME, reg_val);
+
+   qw0 = cpu_to_le64(itct->qw0);
+   qw0 &= ~ITCT_HDR_VALID_MSK;
+   itct->qw0 = cpu_to_le64(qw0);
+}
+
 static int reset_hw_v1_hw(struct hisi_hba *hisi_hba)
 {
int i;
@@ -932,6 +954,253 @@ static int prep_ssp_v1_hw(struct hisi_hba *hisi_hba,
return 0;
 }
 
+/* by default, task resp is complete */
+static void slot_err_v1_hw(struct hisi_hba *hisi_hba,
+  struct sas_task *task,
+  struct hisi_sas_slot *slot)
+{
+   struct task_status_struct *ts = &task->t

[PATCH v4 30/32] scsi: hisi_sas: add control phy handler

2015-11-16 Thread John Garry
Add method for lldd_control_phy. Currently link rate
control and spinup hold is unsupported.

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |  3 +++
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 29 +
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 23 +++
 3 files changed, 55 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 15adeca..5b790c9 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -137,6 +137,9 @@ struct hisi_sas_hw {
struct hisi_sas_slot *slot);
int (*slot_complete)(struct hisi_hba *hisi_hba,
 struct hisi_sas_slot *slot, int abort);
+   void (*phy_enable)(struct hisi_hba *hisi_hba, int phy_no);
+   void (*phy_disable)(struct hisi_hba *hisi_hba, int phy_no);
+   void (*phy_hard_reset)(struct hisi_hba *hisi_hba, int phy_no);
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);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 4ee90eb..1377625 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -552,6 +552,34 @@ static int hisi_sas_queue_command(struct sas_task *task, 
gfp_t gfp_flags)
return hisi_sas_task_exec(task, gfp_flags, 0, NULL);
 }
 
+static int hisi_sas_control_phy(struct asd_sas_phy *sas_phy, enum phy_func 
func,
+   void *funcdata)
+{
+   struct sas_ha_struct *sas_ha = sas_phy->ha;
+   struct hisi_hba *hisi_hba = sas_ha->lldd_ha;
+   int phy_no = sas_phy->id;
+
+   switch (func) {
+   case PHY_FUNC_HARD_RESET:
+   hisi_hba->hw->phy_hard_reset(hisi_hba, phy_no);
+   break;
+
+   case PHY_FUNC_LINK_RESET:
+   hisi_hba->hw->phy_enable(hisi_hba, phy_no);
+   hisi_hba->hw->phy_hard_reset(hisi_hba, phy_no);
+   break;
+
+   case PHY_FUNC_DISABLE:
+   hisi_hba->hw->phy_disable(hisi_hba, phy_no);
+   break;
+
+   case PHY_FUNC_SET_LINK_RATE:
+   case PHY_FUNC_RELEASE_SPINUP_HOLD:
+   default:
+   return -EOPNOTSUPP;
+   }
+   return 0;
+}
 
 static void hisi_sas_task_done(struct sas_task *task)
 {
@@ -932,6 +960,7 @@ static struct sas_domain_function_template 
hisi_sas_transport_ops = {
.lldd_dev_found = hisi_sas_dev_found,
.lldd_dev_gone  = hisi_sas_dev_gone,
.lldd_execute_task  = hisi_sas_queue_command,
+   .lldd_control_phy   = hisi_sas_control_phy,
.lldd_abort_task= hisi_sas_abort_task,
.lldd_abort_task_set= hisi_sas_abort_task_set,
.lldd_clear_aca = hisi_sas_clear_aca,
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index 64b17a1..a95259c 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -764,6 +764,14 @@ static void enable_phy_v1_hw(struct hisi_hba *hisi_hba, 
int phy_no)
hisi_sas_phy_write32(hisi_hba, phy_no, PHY_CFG, cfg);
 }
 
+static void disable_phy_v1_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_v1_hw(struct hisi_hba *hisi_hba, int phy_no)
 {
config_id_frame_v1_hw(hisi_hba, phy_no);
@@ -772,6 +780,18 @@ static void start_phy_v1_hw(struct hisi_hba *hisi_hba, int 
phy_no)
enable_phy_v1_hw(hisi_hba, phy_no);
 }
 
+static void stop_phy_v1_hw(struct hisi_hba *hisi_hba, int phy_no)
+{
+   disable_phy_v1_hw(hisi_hba, phy_no);
+}
+
+static void phy_hard_reset_v1_hw(struct hisi_hba *hisi_hba, int phy_no)
+{
+   stop_phy_v1_hw(hisi_hba, phy_no);
+   msleep(100);
+   start_phy_v1_hw(hisi_hba, phy_no);
+}
+
 static void start_phys_v1_hw(unsigned long data)
 {
struct hisi_hba *hisi_hba = (struct hisi_hba *)data;
@@ -1687,6 +1707,9 @@ static const struct hisi_sas_hw hisi_sas_v1_hw = {
.get_free_slot = get_free_slot_v1_hw,
.start_delivery = start_delivery_v1_hw,
.slot_complete = slot_complete_v1_hw,
+   .phy_enable = enable_phy_v1_hw,
+   .phy_disable = disable_phy_v1_hw,
+   .phy_hard_reset = phy_hard_reset_v1_hw,
.get_wideport_bitmap = get_wideport_bitmap_v1_hw,
.complete_hdr_size = sizeof(struct hisi_sas_complete_v1_hdr),
 };
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 12/32] scsi: hisi_sas: set dev DMA mask

2015-11-16 Thread John Garry
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_main.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 8cd1b55..d7d9516 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -311,6 +311,14 @@ int hisi_sas_probe(struct platform_device *pdev,
sha = SHOST_TO_SAS_HA(shost);
hisi_hba = shost_priv(shost);
platform_set_drvdata(pdev, sha);
+
+   if (dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)) &&
+   dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32))) {
+   dev_err(dev, "No usable DMA addressing method\n");
+   rc = -EIO;
+   goto err_out_ha;
+   }
+
phy_nr = port_nr = hisi_hba->n_phy;
 
arr_phy = devm_kcalloc(dev, phy_nr, sizeof(void *), GFP_KERNEL);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 09/32] scsi: hisi_sas: add slot init code

2015-11-16 Thread John Garry
Add functionality to init slot indexing.

Slot indexing is for the host to track which slots
(or tags) are free and which are used.

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h  |  4 
 drivers/scsi/hisi_sas/hisi_sas_main.c | 23 +++
 2 files changed, 27 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 6d1b7d8..2cd6771 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -66,6 +66,10 @@ struct hisi_hba {
 
int n_phy;
 
+
+   int slot_index_count;
+   unsigned long *slot_index_tags;
+
/* SCSI/SAS glue */
struct sas_ha_struct sha;
struct Scsi_Host *shost;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index b96a2ab..d7e5b66 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -12,6 +12,21 @@
 #include "hisi_sas.h"
 #define DRV_NAME "hisi_sas"
 
+static void hisi_sas_slot_index_clear(struct hisi_hba *hisi_hba, int slot_idx)
+{
+   void *bitmap = hisi_hba->slot_index_tags;
+
+   clear_bit(slot_idx, bitmap);
+}
+
+static void hisi_sas_slot_index_init(struct hisi_hba *hisi_hba)
+{
+   int i;
+
+   for (i = 0; i < hisi_hba->slot_index_count; ++i)
+   hisi_sas_slot_index_clear(hisi_hba, i);
+}
+
 static struct scsi_transport_template *hisi_sas_stt;
 
 static struct scsi_host_template hisi_sas_sht = {
@@ -102,6 +117,12 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, 
struct Scsi_Host *shost)
 
memset(hisi_hba->breakpoint, 0, s);
 
+   hisi_hba->slot_index_count = HISI_SAS_COMMAND_ENTRIES;
+   s = hisi_hba->slot_index_count / sizeof(unsigned long);
+   hisi_hba->slot_index_tags = devm_kzalloc(dev, s, GFP_KERNEL);
+   if (!hisi_hba->slot_index_tags)
+   goto err_out;
+
hisi_hba->sge_page_pool = dma_pool_create("status_sge", dev,
sizeof(struct hisi_sas_sge_page), 16, 0);
if (!hisi_hba->sge_page_pool)
@@ -121,6 +142,8 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct 
Scsi_Host *shost)
goto err_out;
memset(hisi_hba->sata_breakpoint, 0, s);
 
+   hisi_sas_slot_index_init(hisi_hba);
+
return 0;
 err_out:
return -ENOMEM;
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 25/32] scsi: hisi_sas: add abnormal irq handler

2015-11-16 Thread John Garry
Add abnormal irq handler. This handler is concerned with
phy down event.
Also add port formed and port deformed handlers.

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |   2 +
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 118 +
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c |  70 +++
 3 files changed, 190 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 999f319..e5ee3c9 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -136,6 +136,7 @@ struct hisi_sas_hw {
 struct hisi_sas_slot *slot, int abort);
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);
int complete_hdr_size;
 };
 
@@ -330,6 +331,7 @@ extern int hisi_sas_probe(struct platform_device *pdev,
  const struct hisi_sas_hw *ops);
 extern int hisi_sas_remove(struct platform_device *pdev);
 
+extern void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy);
 extern void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba,
struct sas_task *task,
struct hisi_sas_slot *slot);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index d8af4c6..1797851 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -431,6 +431,72 @@ static void hisi_sas_phy_init(struct hisi_hba *hisi_hba, 
int phy_no)
INIT_WORK(&phy->phyup_ws, hisi_sas_phyup_work);
 }
 
+static void hisi_sas_port_notify_formed(struct asd_sas_phy *sas_phy)
+{
+   struct sas_ha_struct *sas_ha = sas_phy->ha;
+   struct hisi_hba *hisi_hba = sas_ha->lldd_ha;
+   struct hisi_sas_phy *phy = sas_phy->lldd_phy;
+   struct asd_sas_port *sas_port = sas_phy->port;
+   struct hisi_sas_port *port = &hisi_hba->port[sas_phy->id];
+   unsigned long flags;
+
+   if (!sas_port)
+   return;
+
+   spin_lock_irqsave(&hisi_hba->lock, flags);
+   port->port_attached = 1;
+   port->id = phy->port_id;
+   phy->port = port;
+   sas_port->lldd_port = port;
+   spin_unlock_irqrestore(&hisi_hba->lock, flags);
+}
+
+static void hisi_sas_do_release_task(struct hisi_hba *hisi_hba, int phy_no,
+struct domain_device *device)
+{
+   struct hisi_sas_phy *phy;
+   struct hisi_sas_port *port;
+   struct hisi_sas_slot *slot, *slot2;
+   struct device *dev = &hisi_hba->pdev->dev;
+
+   phy = &hisi_hba->phy[phy_no];
+   port = phy->port;
+   if (!port)
+   return;
+
+   list_for_each_entry_safe(slot, slot2, &port->list, entry) {
+   struct sas_task *task;
+
+   task = slot->task;
+   if (device && task->dev != device)
+   continue;
+
+   dev_info(dev, "Release slot [%d:%d], task [%p]:\n",
+slot->dlvry_queue, slot->dlvry_queue_slot, task);
+   hisi_hba->hw->slot_complete(hisi_hba, slot, 1);
+   }
+}
+
+static void hisi_sas_port_notify_deformed(struct asd_sas_phy *sas_phy)
+{
+   struct domain_device *device;
+   struct hisi_sas_phy *phy = sas_phy->lldd_phy;
+   struct asd_sas_port *sas_port = sas_phy->port;
+
+   list_for_each_entry(device, &sas_port->dev_list, dev_list_node)
+   hisi_sas_do_release_task(phy->hisi_hba, sas_phy->id, device);
+}
+
+static void hisi_sas_release_task(struct hisi_hba *hisi_hba,
+   struct domain_device *device)
+{
+   struct asd_sas_port *port = device->port;
+   struct asd_sas_phy *sas_phy;
+
+   list_for_each_entry(sas_phy, &port->phy_list, port_phy_el)
+   hisi_sas_do_release_task(hisi_hba, sas_phy->id, device);
+}
+
 static void hisi_sas_dev_gone(struct domain_device *device)
 {
struct hisi_sas_device *sas_dev = device->lldd_dev;
@@ -454,6 +520,56 @@ static int hisi_sas_queue_command(struct sas_task *task, 
gfp_t gfp_flags)
return hisi_sas_task_exec(task, gfp_flags, 0, NULL);
 }
 
+
+static void hisi_sas_port_formed(struct asd_sas_phy *sas_phy)
+{
+   hisi_sas_port_notify_formed(sas_phy);
+}
+
+static void hisi_sas_port_deformed(struct asd_sas_phy *sas_phy)
+{
+   hisi_sas_port_notify_deformed(sas_phy);
+}
+
+static void hisi_sas_phy_disconnected(struct hisi_sas_phy *phy)
+{
+   phy->phy_attached = 0;
+   phy->phy_type = 0;
+   phy->port = NULL;
+}
+
+void hisi_sas_phy_down(struct hisi_hba *hisi_hba, int phy_no, int rdy)
+{
+   struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
+   struct asd_sas_phy *sas_phy = &phy->sas_phy;
+   struct sas_ha_struct *sas_ha = &hisi_hba->sha;
+
+   if (rdy) {
+   /* Phy down but read

[PATCH v4 32/32] MAINTAINERS: add maintainer for HiSi SAS driver

2015-11-16 Thread John Garry
Add maintainer for HiSilicon SAS driver.

Signed-off-by: John Garry 
---
 MAINTAINERS | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/MAINTAINERS b/MAINTAINERS
index e9caa4b..c7081bd 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5035,6 +5035,13 @@ F:   include/uapi/linux/if_hippi.h
 F: net/802/hippi.c
 F: drivers/net/hippi/
 
+HISILICON SAS Controller
+M: John Garry 
+W: http://www.hisilicon.com
+S: Supported
+F: drivers/scsi/hisi_sas/
+F: Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
+
 HOST AP DRIVER
 M: Jouni Malinen 
 L: hos...@shmoo.com (subscribers-only)
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 20/32] scsi: hisi_sas: add v1 hw interrupt init

2015-11-16 Thread John Garry
Add code to interrupts, so now we can get a phy up
interrupt when a disk is connected.

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |   5 +
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 161 +
 2 files changed, 166 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index ba3bf5e..938fa75 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -38,6 +38,11 @@
 #define HISI_SAS_NAME_LEN 32
 
 
+enum {
+   PORT_TYPE_SAS = (1U << 1),
+   PORT_TYPE_SATA = (1U << 0),
+};
+
 enum dev_status {
HISI_SAS_DEV_NORMAL,
HISI_SAS_DEV_EH,
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index 9bfe1aa..3ea666f 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -728,6 +728,159 @@ static void phys_init_v1_hw(struct hisi_hba *hisi_hba)
mod_timer(timer, jiffies + HZ);
 }
 
+/* Interrupts */
+static irqreturn_t int_phyup_v1_hw(int irq_no, void *p)
+{
+   struct hisi_sas_phy *phy = p;
+   struct hisi_hba *hisi_hba = phy->hisi_hba;
+   struct device *dev = &hisi_hba->pdev->dev;
+   struct asd_sas_phy *sas_phy = &phy->sas_phy;
+   int i, phy_no = sas_phy->id;
+   u32 irq_value, context, port_id, link_rate;
+   u32 *frame_rcvd = (u32 *)sas_phy->frame_rcvd;
+   struct sas_identify_frame *id = (struct sas_identify_frame *)frame_rcvd;
+   irqreturn_t res = IRQ_HANDLED;
+
+   irq_value = hisi_sas_phy_read32(hisi_hba, phy_no, CHL_INT2);
+   if (!(irq_value & CHL_INT2_SL_PHY_ENA_MSK)) {
+   dev_dbg(dev, "phyup: irq_value = %x not set enable bit\n",
+   irq_value);
+   res = IRQ_NONE;
+   goto end;
+   }
+
+   context = hisi_sas_read32(hisi_hba, PHY_CONTEXT);
+   if (context & 1 << phy_no) {
+   dev_err(dev, "phyup: phy%d SATA attached equipment\n",
+   phy_no);
+   goto end;
+   }
+
+   port_id = (hisi_sas_read32(hisi_hba, PHY_PORT_NUM_MA) >> (4 * phy_no))
+ & 0xf;
+   if (port_id == 0xf) {
+   dev_err(dev, "phyup: phy%d invalid portid\n", phy_no);
+   res = IRQ_NONE;
+   goto end;
+   }
+
+   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);
+   }
+
+   /* Get the linkrate */
+   link_rate = hisi_sas_read32(hisi_hba, PHY_CONN_RATE);
+   link_rate = (link_rate >> (phy_no * 4)) & 0xf;
+   sas_phy->linkrate = link_rate;
+   sas_phy->oob_mode = SAS_OOB_MODE;
+   memcpy(sas_phy->attached_sas_addr,
+   &id->sas_addr, SAS_ADDR_SIZE);
+   dev_info(dev, "phyup: phy%d link_rate=%d\n",
+phy_no, link_rate);
+   phy->port_id = port_id;
+   phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA);
+   phy->phy_type |= PORT_TYPE_SAS;
+   phy->phy_attached = 1;
+   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;
+
+end:
+   hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT2,
+CHL_INT2_SL_PHY_ENA_MSK);
+
+   if (irq_value & CHL_INT2_SL_PHY_ENA_MSK) {
+   u32 chl_int0 = hisi_sas_phy_read32(hisi_hba, phy_no, CHL_INT0);
+
+   chl_int0 &= ~CHL_INT0_PHYCTRL_NOTRDY_MSK;
+   hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, chl_int0);
+   hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0_MSK, 0x3ce3ee);
+   }
+
+   return res;
+}
+static const char phy_int_names[HISI_SAS_PHY_INT_NR][32] = {
+   {"Phy Up"},
+};
+static irq_handler_t phy_interrupts[HISI_SAS_PHY_INT_NR] = {
+   int_phyup_v1_hw,
+};
+
+static int interrupt_init_v1_hw(struct hisi_hba *hisi_hba)
+{
+   struct device *dev = &hisi_hba->pdev->dev;
+   struct device_node *np = dev->of_node;
+   char *int_names = hisi_hba->int_names;
+   int i, j, irq, rc, idx;
+
+   if (!np)
+   return -ENOENT;
+
+   for (i = 0; i < hisi_hba->n_phy; i++) {
+   struct hisi_sas_phy *phy = &hisi_hba->phy[i];
+
+   idx = i * HISI_SAS_PHY_INT_NR;
+   for (j = 0; j < HISI_SAS_PHY_INT_NR; j++, idx++) {
+   irq = irq_of_parse_and_map(np, idx);
+   if (!irq) {
+   dev_err(dev,
+   "irq init: fail m

[PATCH v4 13/32] scsi: hisi_sas: add hisi_hba workqueue

2015-11-16 Thread John Garry
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h  | 1 +
 drivers/scsi/hisi_sas/hisi_sas_main.c | 8 
 2 files changed, 9 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index c50384f..62bc6f3 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -72,6 +72,7 @@ struct hisi_hba {
 
int n_phy;
 
+   struct workqueue_struct *wq;
 
int slot_index_count;
unsigned long *slot_index_tags;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index d7d9516..7f32c6b 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -150,6 +150,12 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, 
struct Scsi_Host *shost)
 
hisi_sas_slot_index_init(hisi_hba);
 
+   hisi_hba->wq = create_singlethread_workqueue(dev_name(dev));
+   if (!hisi_hba->wq) {
+   dev_err(dev, "sas_alloc: failed to create workqueue\n");
+   goto err_out;
+   }
+
return 0;
 err_out:
return -ENOMEM;
@@ -207,6 +213,8 @@ static void hisi_sas_free(struct hisi_hba *hisi_hba)
  hisi_hba->sata_breakpoint,
  hisi_hba->sata_breakpoint_dma);
 
+   if (hisi_hba->wq)
+   destroy_workqueue(hisi_hba->wq);
 }
 
 static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 19/32] scsi: hisi_sas: add v1 HW initialisation code

2015-11-16 Thread John Garry
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |   1 +
 drivers/scsi/hisi_sas/hisi_sas_main.c  |   4 +
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 337 +
 3 files changed, 342 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 72533ca..ba3bf5e 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -81,6 +81,7 @@ struct hisi_sas_slot {
 };
 
 struct hisi_sas_hw {
+   int (*hw_init)(struct hisi_hba *hisi_hba);
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 06b863c..6c13547 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -402,6 +402,10 @@ int hisi_sas_probe(struct platform_device *pdev,
 
hisi_sas_init_add(hisi_hba);
 
+   rc = hisi_hba->hw->hw_init(hisi_hba);
+   if (rc)
+   goto err_out_ha;
+
rc = scsi_add_host(shost, &pdev->dev);
if (rc)
goto err_out_ha;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index 9fe89bb..9bfe1aa 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -405,7 +405,344 @@ enum {
(HISI_SAS_PHY_MAX_INT_NR + HISI_SAS_CQ_MAX_INT_NR +\
HISI_SAS_FATAL_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;
+
+   writel(val, regs);
+}
+
+static void hisi_sas_phy_write32(struct hisi_hba *hisi_hba,
+   int phy_no, u32 off, u32 val)
+{
+   void __iomem *regs = hisi_hba->regs + (0x400 * phy_no) + off;
+
+   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 config_phy_opt_mode_v1_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);
+}
+
+static void config_tx_tfe_autoneg_v1_hw(struct hisi_hba *hisi_hba, int phy_no)
+{
+   u32 cfg = hisi_sas_phy_read32(hisi_hba, phy_no, PHY_CONFIG2);
+
+   cfg &= ~PHY_CONFIG2_FORCE_TXDEEMPH_MSK;
+   hisi_sas_phy_write32(hisi_hba, phy_no, PHY_CONFIG2, cfg);
+}
+
+static void config_id_frame_v1_hw(struct hisi_hba *hisi_hba, int phy_no)
+{
+   struct sas_identify_frame identify_frame;
+   u32 *identify_buffer;
+
+   memset(&identify_frame, 0, sizeof(identify_frame));
+   identify_frame.dev_type = SAS_END_DEVICE;
+   identify_frame.frame_type = 0;
+   identify_frame._un1 = 1;
+   identify_frame.initiator_bits = SAS_PROTOCOL_ALL;
+   identify_frame.target_bits = SAS_PROTOCOL_NONE;
+   memcpy(&identify_frame._un4_11[0], hisi_hba->sas_addr, SAS_ADDR_SIZE);
+   memcpy(&identify_frame.sas_addr[0], hisi_hba->sas_addr, SAS_ADDR_SIZE);
+   identify_frame.phy_id = phy_no;
+   identify_buffer = (u32 *)(&identify_frame);
+
+   hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD0,
+   __swab32(identify_buffer[0]));
+   hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD1,
+   identify_buffer[2]);
+   hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD2,
+   identify_buffer[1]);
+   hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD3,
+   identify_buffer[4]);
+   hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD4,
+   identify_buffer[3]);
+   hisi_sas_phy_write32(hisi_hba, phy_no, TX_ID_DWORD5,
+   __swab32(identify_buffer[5]));
+}
+
+static void init_id_frame_v1_hw(struct hisi_hba *hisi_hba)
+{
+   int i;
+
+   for (i = 0; i < hisi_hba->n_phy; i++)
+   config_id_frame_v1_hw(hisi_hba, i);
+}
+
+static int reset_hw_v1_hw(struct hisi_hba *hisi_hba)
+{
+   int i;
+   unsigned long end_time;
+   u32 val;
+   struct device *dev = &hisi_hba->pdev->dev;
+
+   for (i = 0; i < hisi_hba->n_phy; i++) {
+   u32 phy_ctrl = hisi_sas_phy_read32(hisi_hba, i, PHY_CTRL);
+
+   phy_ctrl |= PHY_CTRL_RESET_MSK;
+   hisi_sas_phy_write32(hisi_hba, i, PHY_CTRL, phy_ctrl);
+   }
+   msleep(1); /* It is safe to wait for 50us */
+
+   /* Ensure DMA tx & rx idle */
+   for (i = 0; i < hisi_hba->n_phy; i++) {
+   u32 dma_tx_status, dma_rx_status;
+
+  

[PATCH v4 21/32] scsi: hisi_sas: add path from phyup irq to SAS framework

2015-11-16 Thread John Garry
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |  2 ++
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 49 ++
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 15 +++
 3 files changed, 66 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 938fa75..837d139 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -53,6 +53,7 @@ struct hisi_sas_phy {
struct asd_sas_phy  sas_phy;
struct sas_identify identify;
struct timer_list   timer;
+   struct work_struct  phyup_ws;
u64 port_id; /* from hw */
u64 dev_sas_addr;
u64 phy_type;
@@ -87,6 +88,7 @@ struct hisi_sas_slot {
 
 struct hisi_sas_hw {
int (*hw_init)(struct hisi_hba *hisi_hba);
+   void (*sl_notify)(struct hisi_hba *hisi_hba, int phy_no);
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 6c13547..7bf6d2f 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -27,6 +27,53 @@ static void hisi_sas_slot_index_init(struct hisi_hba 
*hisi_hba)
hisi_sas_slot_index_clear(hisi_hba, i);
 }
 
+static void hisi_sas_bytes_dmaed(struct hisi_hba *hisi_hba, int phy_no)
+{
+   struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
+   struct asd_sas_phy *sas_phy = &phy->sas_phy;
+   struct sas_ha_struct *sas_ha;
+
+   if (!phy->phy_attached)
+   return;
+
+   sas_ha = &hisi_hba->sha;
+   sas_ha->notify_phy_event(sas_phy, PHYE_OOB_DONE);
+
+   if (sas_phy->phy) {
+   struct sas_phy *sphy = sas_phy->phy;
+
+   sphy->negotiated_linkrate = sas_phy->linkrate;
+   sphy->minimum_linkrate = phy->minimum_linkrate;
+   sphy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
+   sphy->maximum_linkrate = phy->maximum_linkrate;
+   }
+
+   if (phy->phy_type & PORT_TYPE_SAS) {
+   struct sas_identify_frame *id;
+
+   id = (struct sas_identify_frame *)phy->frame_rcvd;
+   id->dev_type = phy->identify.device_type;
+   id->initiator_bits = SAS_PROTOCOL_ALL;
+   id->target_bits = phy->identify.target_port_protocols;
+   } else if (phy->phy_type & PORT_TYPE_SATA) {
+   /*Nothing*/
+   }
+
+   sas_phy->frame_rcvd_size = phy->frame_rcvd_size;
+   sas_ha->notify_port_event(sas_phy, PORTE_BYTES_DMAED);
+}
+
+static void hisi_sas_phyup_work(struct work_struct *work)
+{
+   struct hisi_sas_phy *phy =
+   container_of(work, struct hisi_sas_phy, phyup_ws);
+   struct hisi_hba *hisi_hba = phy->hisi_hba;
+   struct asd_sas_phy *sas_phy = &phy->sas_phy;
+   int phy_no = sas_phy->id;
+
+   hisi_hba->hw->sl_notify(hisi_hba, phy_no); /* This requires a sleep */
+   hisi_sas_bytes_dmaed(hisi_hba, phy_no);
+}
 
 static void hisi_sas_phy_init(struct hisi_hba *hisi_hba, int phy_no)
 {
@@ -49,6 +96,8 @@ static void hisi_sas_phy_init(struct hisi_hba *hisi_hba, int 
phy_no)
sas_phy->frame_rcvd = &phy->frame_rcvd[0];
sas_phy->ha = (struct sas_ha_struct *)hisi_hba->shost->hostdata;
sas_phy->lldd_phy = phy;
+
+   INIT_WORK(&phy->phyup_ws, hisi_sas_phyup_work);
 }
 
 static struct scsi_transport_template *hisi_sas_stt;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index 3ea666f..4364279 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -728,6 +728,19 @@ static void phys_init_v1_hw(struct hisi_hba *hisi_hba)
mod_timer(timer, jiffies + HZ);
 }
 
+static void sl_notify_v1_hw(struct hisi_hba *hisi_hba, int phy_no)
+{
+   u32 sl_control;
+
+   sl_control = hisi_sas_phy_read32(hisi_hba, phy_no, SL_CONTROL);
+   sl_control |= SL_CONTROL_NOTIFY_EN_MSK;
+   hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL, sl_control);
+   msleep(1);
+   sl_control = hisi_sas_phy_read32(hisi_hba, phy_no, SL_CONTROL);
+   sl_control &= ~SL_CONTROL_NOTIFY_EN_MSK;
+   hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL, sl_control);
+}
+
 /* Interrupts */
 static irqreturn_t int_phyup_v1_hw(int irq_no, void *p)
 {
@@ -791,6 +804,7 @@ static irqreturn_t int_phyup_v1_hw(int irq_no, void *p)
else if (phy->identify.device_type != SAS_PHY_UNUSED)
phy->identify.target_port_protocols =
SAS_PROTOCOL_SMP;
+   queue_work(hisi_hba->wq, &phy->phyup_ws);
 
 end:
hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT2,
@@ -904,6 +918,7 @@ static int hisi_sas_v1_init(struct hisi_hba *hisi_hba)
 
 static const struct hisi_sas_hw hisi_sas_v1_hw = {
.hw_init = hisi_sas_v1_init,
+   .sl_notify = sl_notify_v1_hw,
.complete_hdr_

[PATCH v4 27/32] scsi: hisi_sas: add smp protocol support

2015-11-16 Thread John Garry
Add support for smp function, which allows devices
attached by expander to be controlled

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |  3 ++
 drivers/scsi/hisi_sas/hisi_sas_main.c  |  9 
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 88 ++
 3 files changed, 100 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index e5ee3c9..f34f73b 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -36,6 +36,7 @@
(((sizeof(union hisi_sas_command_table)+3)/4)*4)
 
 #define HISI_SAS_MAX_SSP_RESP_SZ (sizeof(struct ssp_frame_hdr) + 1024)
+#define HISI_SAS_MAX_SMP_RESP_SZ 1028
 
 #define HISI_SAS_NAME_LEN 32
 
@@ -132,6 +133,8 @@ struct hisi_sas_hw {
int (*prep_ssp)(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot, int is_tmf,
struct hisi_sas_tmf_task *tmf);
+   int (*prep_smp)(struct hisi_hba *hisi_hba,
+   struct hisi_sas_slot *slot);
int (*slot_complete)(struct hisi_hba *hisi_hba,
 struct hisi_sas_slot *slot, int abort);
void (*free_device)(struct hisi_hba *hisi_hba,
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 1797851..406ffa0 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -98,6 +98,12 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, 
struct sas_task *task,
 }
 EXPORT_SYMBOL_GPL(hisi_sas_slot_task_free);
 
+static int hisi_sas_task_prep_smp(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot)
+{
+   return hisi_hba->hw->prep_smp(hisi_hba, slot);
+}
+
 static int hisi_sas_task_prep_ssp(struct hisi_hba *hisi_hba,
  struct hisi_sas_slot *slot, int is_tmf,
  struct hisi_sas_tmf_task *tmf)
@@ -215,6 +221,9 @@ static int hisi_sas_task_prep(struct sas_task *task, struct 
hisi_hba *hisi_hba,
memset(slot->cmd_hdr, 0, sizeof(struct hisi_sas_cmd_hdr));
 
switch (task->task_proto) {
+   case SAS_PROTOCOL_SMP:
+   rc = hisi_sas_task_prep_smp(hisi_hba, slot);
+   break;
case SAS_PROTOCOL_SSP:
rc = hisi_sas_task_prep_ssp(hisi_hba, slot, is_tmf, tmf);
break;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index ad50aed..64b17a1 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -903,6 +903,74 @@ static int prep_prd_sge_v1_hw(struct hisi_hba *hisi_hba,
return 0;
 }
 
+static int prep_smp_v1_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->pdev->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 = &task->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 = &task->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 */
+  (1 << CMD_HDR_MODE_OFF) | /* ini mode */
+  (2 << CMD_HDR_CMD_OFF)); /* smp */
+
+   /* map itct entry */
+   hdr->dw1 = cpu_to_le32(sas_dev->device_id << CMD_HDR_DEVICE_ID_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, &slot->task->smp_task.smp_resp, 1,
+DMA_F

[PATCH v4 11/32] scsi: hisi_sas: add phy SAS ADDR initialization

2015-11-16 Thread John Garry
The SAS address for the HBA comes from the device tree.

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

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 315fe46..c50384f 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -39,6 +39,7 @@
 
 struct hisi_sas_phy {
struct asd_sas_phy  sas_phy;
+   u64 dev_sas_addr;
 };
 
 struct hisi_sas_port {
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index d10bf24..8cd1b55 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -281,6 +281,16 @@ err_out:
return NULL;
 }
 
+static void hisi_sas_init_add(struct hisi_hba *hisi_hba)
+{
+   int i;
+
+   for (i = 0; i < hisi_hba->n_phy; i++)
+   memcpy(&hisi_hba->phy[i].dev_sas_addr,
+  hisi_hba->sas_addr,
+  SAS_ADDR_SIZE);
+}
+
 int hisi_sas_probe(struct platform_device *pdev,
 const struct hisi_sas_hw *hw)
 {
@@ -334,6 +344,8 @@ int hisi_sas_probe(struct platform_device *pdev,
sha->sas_port[i] = &hisi_hba->port[i].sas_port;
}
 
+   hisi_sas_init_add(hisi_hba);
+
rc = scsi_add_host(shost, &pdev->dev);
if (rc)
goto err_out_ha;
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 02/32] devicetree: bindings: scsi: HiSi SAS

2015-11-16 Thread John Garry
Add devicetree bindings for HiSilicon SAS driver.

Signed-off-by: John Garry 
Signed-off-by: Zhangfei Gao 
---
 .../devicetree/bindings/scsi/hisilicon-sas.txt | 69 ++
 1 file changed, 69 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/scsi/hisilicon-sas.txt

diff --git a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt 
b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
new file mode 100644
index 000..f67e761
--- /dev/null
+++ b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
@@ -0,0 +1,69 @@
+* HiSilicon SAS controller
+
+The HiSilicon SAS controller supports SAS/SATA.
+
+Main node required properties:
+  - compatible : value should be as follows:
+   (a) "hisilicon,hip05-sas-v1" for v1 hw in hip05 chipset
+  - sas-addr : array of 8 bytes for host SAS address
+  - reg : Address and length of the SAS register
+  - hisilicon,sas-syscon: phandle of syscon used for sas control
+  - ctrl-reset-reg : offset to controller reset register in ctrl reg
+  - ctrl-reset-sts-reg : offset to controller reset status register in ctrl reg
+  - ctrl-clock-ena-reg : offset to controller clock enable register in ctrl reg
+  - queue-count : number of delivery and completion queues in the controller
+  - phy-count : number of phys accessible by the controller
+  - interrupts : Interrupts for phys, completion queues, and fatal
+   sources; the interrupts are ordered in 3 groups, as follows:
+   - Phy interrupts
+   - Completion queue interrupts
+   - Fatal interrupts
+   Phy interrupts : Each phy has 3 interrupt sources:
+   - broadcast
+   - phyup
+   - abnormal
+   The phy interrupts are ordered into groups of 3 per phy
+   (broadcast, phyup, and abnormal) in increasing order.
+   Completion queue interrupts : each completion queue has 1
+   interrupt source.
+   The interrupts are ordered in increasing order.
+   Fatal interrupts : the fatal interrupts are ordered as follows:
+   - ECC
+   - AXI bus
+
+Example:
+   sas0: sas@c100 {
+   compatible = "hisilicon,hip05-sas-v1";
+   sas-addr = [50 01 88 20 16 00 00 0a];
+   reg = <0x0 0xc100 0x0 0x1>;
+   hisilicon,sas-syscon = <&pcie_sas>;
+   ctrl-reset-reg = <0xa60>;
+   ctrl-reset-sts-reg = <0x5a30>;
+   ctrl-clock-ena-reg = <0x338>;
+   queue-count = <32>;
+   phy-count = <8>;
+   dma-coherent;
+   interrupt-parent = <&mbigen_dsa>;
+   interrupts =<259 4>,<263 4>,<264 4>,/* phy0 */
+   <269 4>,<273 4>,<274 4>,/* phy1 */
+   <279 4>,<283 4>,<284 4>,/* phy2 */
+   <289 4>,<293 4>,<294 4>,/* phy3 */
+   <299 4>,<303 4>,<304 4>,/* phy4 */
+   <309 4>,<313 4>,<314 4>,/* phy5 */
+   <319 4>,<323 4>,<324 4>,/* phy6 */
+   <329 4>,<333 4>,<334 4>,/* phy7 */
+   <336 1>,<337 1>,<338 1>,/* cq0-2 */
+   <339 1>,<340 1>,<341 1>,/* cq3-5 */
+   <342 1>,<343 1>,<344 1>,/* cq6-8 */
+   <345 1>,<346 1>,<347 1>,/* cq9-11 */
+   <348 1>,<349 1>,<350 1>,/* cq12-14 */
+   <351 1>,<352 1>,<353 1>,/* cq15-17 */
+   <354 1>,<355 1>,<356 1>,/* cq18-20 */
+   <357 1>,<358 1>,<359 1>,/* cq21-23 */
+   <360 1>,<361 1>,<362 1>,/* cq24-26 */
+   <363 1>,<364 1>,<365 1>,/* cq27-29 */
+   <366 1>,<367 1>/* cq30-31 */
+   <376 4>,/* fatal ecc */
+   <381 4>;/* fatal axi */
+   status = "disabled";
+   };
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 10/32] scsi: hisi_sas: add cq structure initialization

2015-11-16 Thread John Garry
Each completion queue has a structure. This is mainly for
passing to irq handler so we know which queue the irq occured
on.

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h  | 7 +++
 drivers/scsi/hisi_sas/hisi_sas_main.c | 6 ++
 2 files changed, 13 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 2cd6771..315fe46 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -45,6 +45,11 @@ struct hisi_sas_port {
struct asd_sas_port sas_port;
 };
 
+struct hisi_sas_cq {
+   struct hisi_hba *hisi_hba;
+   int id;
+};
+
 struct hisi_sas_slot {
 };
 
@@ -73,6 +78,8 @@ struct hisi_hba {
/* SCSI/SAS glue */
struct sas_ha_struct sha;
struct Scsi_Host *shost;
+
+   struct hisi_sas_cq cq[HISI_SAS_MAX_QUEUES];
struct hisi_sas_phy phy[HISI_SAS_MAX_PHYS];
struct hisi_sas_port port[HISI_SAS_MAX_PHYS];
 
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index d7e5b66..d10bf24 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -58,6 +58,12 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct 
Scsi_Host *shost)
struct device *dev = &pdev->dev;
 
for (i = 0; i < hisi_hba->queue_count; i++) {
+   struct hisi_sas_cq *cq = &hisi_hba->cq[i];
+
+   /* Completion queue structure */
+   cq->id = i;
+   cq->hisi_hba = hisi_hba;
+
/* Delivery queue */
s = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS;
hisi_hba->cmd_hdr[i] = dma_alloc_coherent(dev, s,
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 16/32] scsi: hisi_sas: add timer and spinlock init

2015-11-16 Thread John Garry
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h  | 2 ++
 drivers/scsi/hisi_sas/hisi_sas_main.c | 3 +++
 2 files changed, 5 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 3a2400e..3749c46 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -97,7 +97,9 @@ struct hisi_hba {
u8 sas_addr[SAS_ADDR_SIZE];
 
int n_phy;
+   spinlock_t lock;
 
+   struct timer_list timer;
struct workqueue_struct *wq;
 
int slot_index_count;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index bc41ce4..06b863c 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -81,6 +81,7 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct 
Scsi_Host *shost)
struct platform_device *pdev = hisi_hba->pdev;
struct device *dev = &pdev->dev;
 
+   spin_lock_init(&hisi_hba->lock);
for (i = 0; i < hisi_hba->n_phy; i++) {
hisi_sas_phy_init(hisi_hba, i);
hisi_hba->port[i].port_attached = 0;
@@ -275,6 +276,8 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct 
platform_device *pdev,
hisi_hba->shost = shost;
SHOST_TO_SAS_HA(shost) = &hisi_hba->sha;
 
+   init_timer(&hisi_hba->timer);
+
sas_addr_prop = of_find_property(np, "sas-addr", NULL);
if (!sas_addr_prop || (sas_addr_prop->length != SAS_ADDR_SIZE))
goto err_out;
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 04/32] scsi: hisi_sas: add scsi host registration

2015-11-16 Thread John Garry
Add functionality to register device as a scsi host.

The SAS domain transport ops are empty at this point.

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h  |  34 ++
 drivers/scsi/hisi_sas/hisi_sas_main.c | 116 ++
 2 files changed, 150 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index a5cec22..6f57fd1 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -23,4 +23,38 @@
 
 #define DRV_VERSION "v1.0"
 
+#define HISI_SAS_MAX_PHYS  9
+#define HISI_SAS_MAX_ITCT_ENTRIES 4096
+#define HISI_SAS_MAX_DEVICES HISI_SAS_MAX_ITCT_ENTRIES
+#define HISI_SAS_COMMAND_ENTRIES 8192
+
+struct hisi_sas_phy {
+   struct asd_sas_phy  sas_phy;
+};
+
+struct hisi_sas_port {
+   struct asd_sas_port sas_port;
+};
+
+struct hisi_sas_hw {
+};
+
+struct hisi_hba {
+   /* This must be the first element, used by SHOST_TO_SAS_HA */
+   struct sas_ha_struct *p;
+
+   struct platform_device *pdev;
+   u8 sas_addr[SAS_ADDR_SIZE];
+
+   int n_phy;
+
+   /* SCSI/SAS glue */
+   struct sas_ha_struct sha;
+   struct Scsi_Host *shost;
+   struct hisi_sas_phy phy[HISI_SAS_MAX_PHYS];
+   struct hisi_sas_port port[HISI_SAS_MAX_PHYS];
+   const struct hisi_sas_hw *hw;   /* Low level hw interface */
+};
+
+#define HISI_SAS_SGE_PAGE_CNT SCSI_MAX_SG_SEGMENTS
 #endif
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 7201363..4fd000e 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -14,9 +14,125 @@
 
 static struct scsi_transport_template *hisi_sas_stt;
 
+static struct scsi_host_template hisi_sas_sht = {
+   .module = THIS_MODULE,
+   .name   = DRV_NAME,
+   .queuecommand   = sas_queuecommand,
+   .target_alloc   = sas_target_alloc,
+   .slave_configure= sas_slave_configure,
+   .change_queue_depth = sas_change_queue_depth,
+   .bios_param = sas_bios_param,
+   .can_queue  = 1,
+   .this_id= -1,
+   .sg_tablesize   = SG_ALL,
+   .max_sectors= SCSI_DEFAULT_MAX_SECTORS,
+   .use_clustering = ENABLE_CLUSTERING,
+   .eh_device_reset_handler = sas_eh_device_reset_handler,
+   .eh_bus_reset_handler   = sas_eh_bus_reset_handler,
+   .target_destroy = sas_target_destroy,
+   .ioctl  = sas_ioctl,
+};
+
 static struct sas_domain_function_template hisi_sas_transport_ops = {
 };
 
+static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
+ const struct hisi_sas_hw *hw)
+{
+   struct Scsi_Host *shost;
+   struct hisi_hba *hisi_hba;
+   struct device *dev = &pdev->dev;
+
+   shost = scsi_host_alloc(&hisi_sas_sht, sizeof(*hisi_hba));
+   if (!shost)
+   goto err_out;
+   hisi_hba = shost_priv(shost);
+
+   hisi_hba->hw = hw;
+   hisi_hba->pdev = pdev;
+   hisi_hba->shost = shost;
+   SHOST_TO_SAS_HA(shost) = &hisi_hba->sha;
+
+   return shost;
+err_out:
+   dev_err(dev, "shost alloc failed\n");
+   return NULL;
+}
+
+int hisi_sas_probe(struct platform_device *pdev,
+const struct hisi_sas_hw *hw)
+{
+   struct Scsi_Host *shost;
+   struct hisi_hba *hisi_hba;
+   struct device *dev = &pdev->dev;
+   struct asd_sas_phy **arr_phy;
+   struct asd_sas_port **arr_port;
+   struct sas_ha_struct *sha;
+   int rc, phy_nr, port_nr, i;
+
+   shost = hisi_sas_shost_alloc(pdev, hw);
+   if (!shost) {
+   rc = -ENOMEM;
+   goto err_out_ha;
+   }
+
+   sha = SHOST_TO_SAS_HA(shost);
+   hisi_hba = shost_priv(shost);
+   platform_set_drvdata(pdev, sha);
+   hisi_hba->n_phy = HISI_SAS_MAX_PHYS;
+   phy_nr = port_nr = hisi_hba->n_phy;
+
+   arr_phy = devm_kcalloc(dev, phy_nr, sizeof(void *), GFP_KERNEL);
+   arr_port = devm_kcalloc(dev, port_nr, sizeof(void *), GFP_KERNEL);
+   if (!arr_phy || !arr_port)
+   return -ENOMEM;
+
+   sha->sas_phy = arr_phy;
+   sha->sas_port = arr_port;
+   sha->core.shost = shost;
+   sha->lldd_ha = hisi_hba;
+
+   shost->transportt = hisi_sas_stt;
+   shost->max_id = HISI_SAS_MAX_DEVICES;
+   shost->max_lun = ~0;
+   shost->max_channel = 1;
+   shost->max_cmd_len = 16;
+   shost->sg_tablesize = min_t(u16, SG_ALL, HISI_SAS_SGE_PAGE_CNT);
+   shost->can_queue = HISI_SAS_COMMAND_ENTRIES;
+   shost->cmd_per_lun = HISI_SAS_COMMAND_ENTRIES;
+
+   sha->sas_ha_name = DRV_NAME;
+   sha->dev = &hisi_hba->pdev->dev;
+   sha->lldd_module = THIS_MODULE;
+   sha->sas_addr = &hisi_hba->sas_addr[0];
+   sha->num_phys = hisi_hba->n_phy;
+

[PATCH v4 08/32] scsi: hisi_sas: add hisi_sas_remove

2015-11-16 Thread John Garry
This patch also includes relevant memory/pool
free'ing and sas/scsi host removal

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_main.c | 71 ++-
 1 file changed, 70 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 97f5368..b96a2ab 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -126,6 +126,59 @@ err_out:
return -ENOMEM;
 }
 
+static void hisi_sas_free(struct hisi_hba *hisi_hba)
+{
+   struct device *dev = &hisi_hba->pdev->dev;
+   int i, s;
+
+   for (i = 0; i < hisi_hba->queue_count; i++) {
+   s = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS;
+   if (hisi_hba->cmd_hdr[i])
+   dma_free_coherent(dev, s,
+ hisi_hba->cmd_hdr[i],
+ hisi_hba->cmd_hdr_dma[i]);
+
+   s = hisi_hba->hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS;
+   if (hisi_hba->complete_hdr[i])
+   dma_free_coherent(dev, s,
+ hisi_hba->complete_hdr[i],
+ hisi_hba->complete_hdr_dma[i]);
+   }
+
+   dma_pool_destroy(hisi_hba->status_buffer_pool);
+   dma_pool_destroy(hisi_hba->command_table_pool);
+   dma_pool_destroy(hisi_hba->sge_page_pool);
+
+   s = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct);
+   if (hisi_hba->itct)
+   dma_free_coherent(dev, s,
+ hisi_hba->itct, hisi_hba->itct_dma);
+
+   s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_iost);
+   if (hisi_hba->iost)
+   dma_free_coherent(dev, s,
+ hisi_hba->iost, hisi_hba->iost_dma);
+
+   s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_breakpoint);
+   if (hisi_hba->breakpoint)
+   dma_free_coherent(dev, s,
+ hisi_hba->breakpoint,
+ hisi_hba->breakpoint_dma);
+
+
+   s = sizeof(struct hisi_sas_initial_fis) * HISI_SAS_MAX_PHYS;
+   if (hisi_hba->initial_fis)
+   dma_free_coherent(dev, s,
+ hisi_hba->initial_fis,
+ hisi_hba->initial_fis_dma);
+
+   s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_breakpoint) * 2;
+   if (hisi_hba->sata_breakpoint)
+   dma_free_coherent(dev, s,
+ hisi_hba->sata_breakpoint,
+ hisi_hba->sata_breakpoint_dma);
+
+}
 
 static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
  const struct hisi_sas_hw *hw)
@@ -188,8 +241,10 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct 
platform_device *pdev,
if (IS_ERR(hisi_hba->ctrl))
goto err_out;
 
-   if (hisi_sas_alloc(hisi_hba, shost))
+   if (hisi_sas_alloc(hisi_hba, shost)) {
+   hisi_sas_free(hisi_hba);
goto err_out;
+   }
 
return shost;
 err_out:
@@ -270,6 +325,20 @@ err_out_ha:
 }
 EXPORT_SYMBOL_GPL(hisi_sas_probe);
 
+int hisi_sas_remove(struct platform_device *pdev)
+{
+   struct sas_ha_struct *sha = platform_get_drvdata(pdev);
+   struct hisi_hba *hisi_hba = sha->lldd_ha;
+
+   scsi_remove_host(sha->core.shost);
+   sas_unregister_ha(sha);
+   sas_remove_host(sha->core.shost);
+
+   hisi_sas_free(hisi_hba);
+   return 0;
+}
+EXPORT_SYMBOL_GPL(hisi_sas_remove);
+
 static __init int hisi_sas_init(void)
 {
pr_info("hisi_sas: driver version %s\n", DRV_VERSION);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 07/32] scsi: hisi_sas: allocate memories and create pools

2015-11-16 Thread John Garry
Allocate DMA and non-DMA memories for the controller. Also
create DMA pools.

These include:
- Delivery queues
- Completion queues
- Command status buffer
- Command table
- ITCT (For device context)
- Host slot info
- IO status
- Breakpoint
- host slot indexing
- SG data
- FIS
- interrupts names

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h  | 30 +++
 drivers/scsi/hisi_sas/hisi_sas_main.c | 94 +++
 2 files changed, 124 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 19d40b7..6d1b7d8 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -24,10 +24,17 @@
 #define DRV_VERSION "v1.0"
 
 #define HISI_SAS_MAX_PHYS  9
+#define HISI_SAS_MAX_QUEUES32
+#define HISI_SAS_QUEUE_SLOTS 512
 #define HISI_SAS_MAX_ITCT_ENTRIES 4096
 #define HISI_SAS_MAX_DEVICES HISI_SAS_MAX_ITCT_ENTRIES
 #define HISI_SAS_COMMAND_ENTRIES 8192
 
+#define HISI_SAS_STATUS_BUF_SZ \
+   (sizeof(struct hisi_sas_err_record) + 1024)
+#define HISI_SAS_COMMAND_TABLE_SZ \
+   (((sizeof(union hisi_sas_command_table)+3)/4)*4)
+
 #define HISI_SAS_NAME_LEN 32
 
 struct hisi_sas_phy {
@@ -38,7 +45,11 @@ struct hisi_sas_port {
struct asd_sas_port sas_port;
 };
 
+struct hisi_sas_slot {
+};
+
 struct hisi_sas_hw {
+   int complete_hdr_size;
 };
 
 struct hisi_hba {
@@ -63,6 +74,25 @@ struct hisi_hba {
 
int queue_count;
char*int_names;
+
+   struct dma_pool *sge_page_pool;
+   struct dma_pool *command_table_pool;
+   struct dma_pool *status_buffer_pool;
+   struct hisi_sas_cmd_hdr *cmd_hdr[HISI_SAS_MAX_QUEUES];
+   dma_addr_t cmd_hdr_dma[HISI_SAS_MAX_QUEUES];
+   void *complete_hdr[HISI_SAS_MAX_QUEUES];
+   dma_addr_t complete_hdr_dma[HISI_SAS_MAX_QUEUES];
+   struct hisi_sas_initial_fis *initial_fis;
+   dma_addr_t initial_fis_dma;
+   struct hisi_sas_itct *itct;
+   dma_addr_t itct_dma;
+   struct hisi_sas_iost *iost;
+   dma_addr_t iost_dma;
+   struct hisi_sas_breakpoint *breakpoint;
+   dma_addr_t breakpoint_dma;
+   struct hisi_sas_breakpoint *sata_breakpoint;
+   dma_addr_t sata_breakpoint_dma;
+   struct hisi_sas_slot*slot_info;
const struct hisi_sas_hw *hw;   /* Low level hw interface */
 };
 
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 4fc5a6c..97f5368 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -36,6 +36,97 @@ static struct scsi_host_template hisi_sas_sht = {
 static struct sas_domain_function_template hisi_sas_transport_ops = {
 };
 
+static int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct Scsi_Host *shost)
+{
+   int i, s;
+   struct platform_device *pdev = hisi_hba->pdev;
+   struct device *dev = &pdev->dev;
+
+   for (i = 0; i < hisi_hba->queue_count; i++) {
+   /* Delivery queue */
+   s = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS;
+   hisi_hba->cmd_hdr[i] = dma_alloc_coherent(dev, s,
+   &hisi_hba->cmd_hdr_dma[i], GFP_KERNEL);
+   if (!hisi_hba->cmd_hdr[i])
+   goto err_out;
+   memset(hisi_hba->cmd_hdr[i], 0, s);
+
+   /* Completion queue */
+   s = hisi_hba->hw->complete_hdr_size * HISI_SAS_QUEUE_SLOTS;
+   hisi_hba->complete_hdr[i] = dma_alloc_coherent(dev, s,
+   &hisi_hba->complete_hdr_dma[i], GFP_KERNEL);
+   if (!hisi_hba->complete_hdr[i])
+   goto err_out;
+   memset(hisi_hba->complete_hdr[i], 0, s);
+   }
+
+   s = HISI_SAS_STATUS_BUF_SZ;
+   hisi_hba->status_buffer_pool = dma_pool_create("status_buffer",
+  dev, s, 16, 0);
+   if (!hisi_hba->status_buffer_pool)
+   goto err_out;
+
+   s = HISI_SAS_COMMAND_TABLE_SZ;
+   hisi_hba->command_table_pool = dma_pool_create("command_table",
+  dev, s, 16, 0);
+   if (!hisi_hba->command_table_pool)
+   goto err_out;
+
+   s = HISI_SAS_MAX_ITCT_ENTRIES * sizeof(struct hisi_sas_itct);
+   hisi_hba->itct = dma_alloc_coherent(dev, s, &hisi_hba->itct_dma,
+   GFP_KERNEL);
+   if (!hisi_hba->itct)
+   goto err_out;
+
+   memset(hisi_hba->itct, 0, s);
+
+   hisi_hba->slot_info = devm_kcalloc(dev, HISI_SAS_COMMAND_ENTRIES,
+  sizeof(struct hisi_sas_slot),
+  GFP_KERNEL);
+   if (!hisi_hba->slot_info)
+   goto err_out;
+
+   s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_iost);
+   hisi_hba->iost = dma_alloc_

[PATCH v4 15/32] scsi: hisi_sas: add phy and port init

2015-11-16 Thread John Garry
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h  | 15 +++
 drivers/scsi/hisi_sas/hisi_sas_main.c | 31 +++
 2 files changed, 46 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 5ac5a82..3a2400e 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -43,12 +43,27 @@ enum dev_status {
HISI_SAS_DEV_EH,
 };
 struct hisi_sas_phy {
+   struct hisi_hba *hisi_hba;
+   struct hisi_sas_port*port;
struct asd_sas_phy  sas_phy;
+   struct sas_identify identify;
+   struct timer_list   timer;
+   u64 port_id; /* from hw */
u64 dev_sas_addr;
+   u64 phy_type;
+   u64 frame_rcvd_size;
+   u8  frame_rcvd[32];
+   u8  phy_attached;
+   u8  reserved[3];
+   enum sas_linkrate   minimum_linkrate;
+   enum sas_linkrate   maximum_linkrate;
 };
 
 struct hisi_sas_port {
struct asd_sas_port sas_port;
+   u8  port_attached;
+   u8  id; /* from hw */
+   struct list_headlist;
 };
 
 struct hisi_sas_cq {
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 2d4..bc41ce4 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -27,6 +27,30 @@ static void hisi_sas_slot_index_init(struct hisi_hba 
*hisi_hba)
hisi_sas_slot_index_clear(hisi_hba, i);
 }
 
+
+static void hisi_sas_phy_init(struct hisi_hba *hisi_hba, int phy_no)
+{
+   struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no];
+   struct asd_sas_phy *sas_phy = &phy->sas_phy;
+
+   phy->hisi_hba = hisi_hba;
+   phy->port = NULL;
+   init_timer(&phy->timer);
+   sas_phy->enabled = (phy_no < hisi_hba->n_phy) ? 1 : 0;
+   sas_phy->class = SAS;
+   sas_phy->iproto = SAS_PROTOCOL_ALL;
+   sas_phy->tproto = 0;
+   sas_phy->type = PHY_TYPE_PHYSICAL;
+   sas_phy->role = PHY_ROLE_INITIATOR;
+   sas_phy->oob_mode = OOB_NOT_CONNECTED;
+   sas_phy->linkrate = SAS_LINK_RATE_UNKNOWN;
+   sas_phy->id = phy_no;
+   sas_phy->sas_addr = &hisi_hba->sas_addr[0];
+   sas_phy->frame_rcvd = &phy->frame_rcvd[0];
+   sas_phy->ha = (struct sas_ha_struct *)hisi_hba->shost->hostdata;
+   sas_phy->lldd_phy = phy;
+}
+
 static struct scsi_transport_template *hisi_sas_stt;
 
 static struct scsi_host_template hisi_sas_sht = {
@@ -57,6 +81,13 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct 
Scsi_Host *shost)
struct platform_device *pdev = hisi_hba->pdev;
struct device *dev = &pdev->dev;
 
+   for (i = 0; i < hisi_hba->n_phy; i++) {
+   hisi_sas_phy_init(hisi_hba, i);
+   hisi_hba->port[i].port_attached = 0;
+   hisi_hba->port[i].id = -1;
+   INIT_LIST_HEAD(&hisi_hba->port[i].list);
+   }
+
for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
hisi_hba->devices[i].dev_type = SAS_PHY_UNUSED;
hisi_hba->devices[i].device_id = i;
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 06/32] scsi: hisi_sas: add HW DMA structures

2015-11-16 Thread John Garry
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h | 131 +++
 1 file changed, 131 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 87f4b61..19d40b7 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -66,5 +66,136 @@ struct hisi_hba {
const struct hisi_sas_hw *hw;   /* Low level hw interface */
 };
 
+/* Generic HW DMA host memory structures */
+/* Delivery queue header */
+struct hisi_sas_cmd_hdr {
+   /* dw0 */
+   __le32 dw0;
+
+   /* dw1 */
+   __le32 dw1;
+
+   /* dw2 */
+   __le32 dw2;
+
+   /* dw3 */
+   __le32 transfer_tags;
+
+   /* dw4 */
+   __le32 data_transfer_len;
+
+   /* dw5 */
+   __le32 first_burst_num;
+
+   /* dw6 */
+   __le32 sg_len;
+
+   /* dw7 */
+   __le32 dw7;
+
+   /* dw8-9 */
+   __le64 cmd_table_addr;
+
+   /* dw10-11 */
+   __le64 sts_buffer_addr;
+
+   /* dw12-13 */
+   __le64 prd_table_addr;
+
+   /* dw14-15 */
+   __le64 dif_prd_table_addr;
+};
+
+struct hisi_sas_itct {
+   __le64 qw0;
+   __le64 sas_addr;
+   __le64 qw2;
+   __le64 qw3;
+   __le64 qw4;
+   __le64 qw_sata_ncq0_3;
+   __le64 qw_sata_ncq7_4;
+   __le64 qw_sata_ncq11_8;
+   __le64 qw_sata_ncq15_12;
+   __le64 qw_sata_ncq19_16;
+   __le64 qw_sata_ncq23_20;
+   __le64 qw_sata_ncq27_24;
+   __le64 qw_sata_ncq31_28;
+   __le64 qw_non_ncq_iptt;
+   __le64 qw_rsvd0;
+   __le64 qw_rsvd1;
+};
+
+struct hisi_sas_iost {
+   __le64 qw0;
+   __le64 qw1;
+   __le64 qw2;
+   __le64 qw3;
+};
+
+struct hisi_sas_err_record {
+   /* dw0 */
+   __le32 dma_err_type;
+
+   /* dw1 */
+   __le32 trans_tx_fail_type;
+
+   /* dw2 */
+   __le32 trans_rx_fail_type;
+
+   /* dw3 */
+   u32 rsvd;
+};
+
+struct hisi_sas_initial_fis {
+   struct hisi_sas_err_record err_record;
+   struct dev_to_host_fis fis;
+   u32 rsvd[3];
+};
+
+struct hisi_sas_breakpoint {
+   u8  data[128];  /*io128 byte*/
+};
+
+struct hisi_sas_sge {
+   __le64 addr;
+   __le32 page_ctrl_0;
+   __le32 page_ctrl_1;
+   __le32 data_len;
+   __le32 data_off;
+};
+
+struct hisi_sas_command_table_smp {
+   u8 bytes[44];
+};
+
+struct hisi_sas_command_table_stp {
+   struct  host_to_dev_fis command_fis;
+   u8  dummy[12];
+   u8  atapi_cdb[ATAPI_CDB_LEN];
+};
+
 #define HISI_SAS_SGE_PAGE_CNT SCSI_MAX_SG_SEGMENTS
+struct hisi_sas_sge_page {
+   struct hisi_sas_sge sge[HISI_SAS_SGE_PAGE_CNT];
+};
+
+struct hisi_sas_command_table_ssp {
+   struct ssp_frame_hdr hdr;
+   union {
+   struct {
+   struct ssp_command_iu task;
+   u32 prot[6];
+   };
+   struct ssp_tmf_iu ssp_task;
+   struct xfer_rdy_iu xfer_rdy;
+   struct ssp_response_iu ssp_res;
+   } u;
+};
+
+union hisi_sas_command_table {
+   struct hisi_sas_command_table_ssp ssp;
+   struct hisi_sas_command_table_smp smp;
+   struct hisi_sas_command_table_stp stp;
+};
+
 #endif
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 17/32] scsi: hisi_sas: add v1 hw module init

2015-11-16 Thread John Garry
Add module init code for v1 hw.

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/Makefile |  1 +
 drivers/scsi/hisi_sas/hisi_sas.h   |  3 ++
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 53 ++
 3 files changed, 57 insertions(+)
 create mode 100644 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c

diff --git a/drivers/scsi/hisi_sas/Makefile b/drivers/scsi/hisi_sas/Makefile
index d86b05e..3e70eae 100644
--- a/drivers/scsi/hisi_sas/Makefile
+++ b/drivers/scsi/hisi_sas/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_SCSI_HISI_SAS)+= hisi_sas_main.o
+obj-$(CONFIG_SCSI_HISI_SAS)+= hisi_sas_v1_hw.o
diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 3749c46..72533ca 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -269,5 +269,8 @@ union hisi_sas_command_table {
struct hisi_sas_command_table_smp smp;
struct hisi_sas_command_table_stp stp;
 };
+extern int hisi_sas_probe(struct platform_device *pdev,
+ const struct hisi_sas_hw *ops);
+extern int hisi_sas_remove(struct platform_device *pdev);
 
 #endif
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
new file mode 100644
index 000..e9aebce
--- /dev/null
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015 Linaro Ltd.
+ * Copyright (c) 2015 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_v1_hw"
+
+
+struct hisi_sas_complete_v1_hdr {
+   __le32 data;
+};
+static const struct hisi_sas_hw hisi_sas_v1_hw = {
+   .complete_hdr_size = sizeof(struct hisi_sas_complete_v1_hdr),
+};
+
+static int hisi_sas_v1_probe(struct platform_device *pdev)
+{
+   return hisi_sas_probe(pdev, &hisi_sas_v1_hw);
+}
+
+static int hisi_sas_v1_remove(struct platform_device *pdev)
+{
+   return hisi_sas_remove(pdev);
+}
+
+static const struct of_device_id sas_v1_of_match[] = {
+   { .compatible = "hisilicon,hip05-sas-v1",},
+   {},
+};
+MODULE_DEVICE_TABLE(of, sas_v1_of_match);
+
+static struct platform_driver hisi_sas_v1_driver = {
+   .probe = hisi_sas_v1_probe,
+   .remove = hisi_sas_v1_remove,
+   .driver = {
+   .name = DRV_NAME,
+   .of_match_table = sas_v1_of_match,
+   },
+};
+
+module_platform_driver(hisi_sas_v1_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("John Garry ");
+MODULE_DESCRIPTION("HISILICON SAS controller v1 hw driver");
+MODULE_ALIAS("platform:" DRV_NAME);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 05/32] scsi: hisi_sas: scan device tree

2015-11-16 Thread John Garry
Scan the device tree for all properties. Also
do this:
- do ioremap for SAS registers
- allocate memory for interrupt names

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h  | 10 
 drivers/scsi/hisi_sas/hisi_sas_main.c | 45 ++-
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 6f57fd1..87f4b61 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -28,6 +28,8 @@
 #define HISI_SAS_MAX_DEVICES HISI_SAS_MAX_ITCT_ENTRIES
 #define HISI_SAS_COMMAND_ENTRIES 8192
 
+#define HISI_SAS_NAME_LEN 32
+
 struct hisi_sas_phy {
struct asd_sas_phy  sas_phy;
 };
@@ -44,6 +46,11 @@ struct hisi_hba {
struct sas_ha_struct *p;
 
struct platform_device *pdev;
+   void __iomem *regs;
+   struct regmap *ctrl;
+   u32 ctrl_reset_reg;
+   u32 ctrl_reset_sts_reg;
+   u32 ctrl_clock_ena_reg;
u8 sas_addr[SAS_ADDR_SIZE];
 
int n_phy;
@@ -53,6 +60,9 @@ struct hisi_hba {
struct Scsi_Host *shost;
struct hisi_sas_phy phy[HISI_SAS_MAX_PHYS];
struct hisi_sas_port port[HISI_SAS_MAX_PHYS];
+
+   int queue_count;
+   char*int_names;
const struct hisi_sas_hw *hw;   /* Low level hw interface */
 };
 
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 4fd000e..4fc5a6c 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -39,9 +39,13 @@ static struct sas_domain_function_template 
hisi_sas_transport_ops = {
 static struct Scsi_Host *hisi_sas_shost_alloc(struct platform_device *pdev,
  const struct hisi_sas_hw *hw)
 {
+   struct resource *res;
struct Scsi_Host *shost;
struct hisi_hba *hisi_hba;
struct device *dev = &pdev->dev;
+   struct device_node *np = pdev->dev.of_node;
+   struct property *sas_addr_prop;
+   int num;
 
shost = scsi_host_alloc(&hisi_sas_sht, sizeof(*hisi_hba));
if (!shost)
@@ -53,6 +57,46 @@ static struct Scsi_Host *hisi_sas_shost_alloc(struct 
platform_device *pdev,
hisi_hba->shost = shost;
SHOST_TO_SAS_HA(shost) = &hisi_hba->sha;
 
+   sas_addr_prop = of_find_property(np, "sas-addr", NULL);
+   if (!sas_addr_prop || (sas_addr_prop->length != SAS_ADDR_SIZE))
+   goto err_out;
+   memcpy(hisi_hba->sas_addr, sas_addr_prop->value, SAS_ADDR_SIZE);
+
+   if (of_property_read_u32(np, "ctrl-reset-reg",
+&hisi_hba->ctrl_reset_reg))
+   goto err_out;
+
+   if (of_property_read_u32(np, "ctrl-reset-sts-reg",
+&hisi_hba->ctrl_reset_sts_reg))
+   goto err_out;
+
+   if (of_property_read_u32(np, "ctrl-clock-ena-reg",
+&hisi_hba->ctrl_clock_ena_reg))
+   goto err_out;
+
+   if (of_property_read_u32(np, "phy-count", &hisi_hba->n_phy))
+   goto err_out;
+
+   if (of_property_read_u32(np, "queue-count", &hisi_hba->queue_count))
+   goto err_out;
+
+   num = of_irq_count(np);
+   hisi_hba->int_names = devm_kcalloc(dev, num,
+  HISI_SAS_NAME_LEN,
+  GFP_KERNEL);
+   if (!hisi_hba->int_names)
+   goto err_out;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   hisi_hba->regs = devm_ioremap_resource(dev, res);
+   if (IS_ERR(hisi_hba->regs))
+   goto err_out;
+
+   hisi_hba->ctrl = syscon_regmap_lookup_by_phandle(
+   np, "hisilicon,sas-syscon");
+   if (IS_ERR(hisi_hba->ctrl))
+   goto err_out;
+
return shost;
 err_out:
dev_err(dev, "shost alloc failed\n");
@@ -79,7 +123,6 @@ int hisi_sas_probe(struct platform_device *pdev,
sha = SHOST_TO_SAS_HA(shost);
hisi_hba = shost_priv(shost);
platform_set_drvdata(pdev, sha);
-   hisi_hba->n_phy = HISI_SAS_MAX_PHYS;
phy_nr = port_nr = hisi_hba->n_phy;
 
arr_phy = devm_kcalloc(dev, phy_nr, sizeof(void *), GFP_KERNEL);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 14/32] scsi: hisi_sas: add hisi sas device type

2015-11-16 Thread John Garry
Include initialisation.

Signed-off-by: John Garry 

Conflicts:
drivers/scsi/hisi_sas/hisi_sas_main.c
---
 drivers/scsi/hisi_sas/hisi_sas.h  | 12 
 drivers/scsi/hisi_sas/hisi_sas_main.c |  6 ++
 2 files changed, 18 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 62bc6f3..5ac5a82 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -37,6 +37,11 @@
 
 #define HISI_SAS_NAME_LEN 32
 
+
+enum dev_status {
+   HISI_SAS_DEV_NORMAL,
+   HISI_SAS_DEV_EH,
+};
 struct hisi_sas_phy {
struct asd_sas_phy  sas_phy;
u64 dev_sas_addr;
@@ -51,6 +56,12 @@ struct hisi_sas_cq {
int id;
 };
 
+struct hisi_sas_device {
+   enum sas_device_typedev_type;
+   u64 device_id;
+   u8 dev_status;
+};
+
 struct hisi_sas_slot {
 };
 
@@ -89,6 +100,7 @@ struct hisi_hba {
char*int_names;
 
struct dma_pool *sge_page_pool;
+   struct hisi_sas_device  devices[HISI_SAS_MAX_DEVICES];
struct dma_pool *command_table_pool;
struct dma_pool *status_buffer_pool;
struct hisi_sas_cmd_hdr *cmd_hdr[HISI_SAS_MAX_QUEUES];
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 7f32c6b..2d4 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -57,6 +57,12 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, struct 
Scsi_Host *shost)
struct platform_device *pdev = hisi_hba->pdev;
struct device *dev = &pdev->dev;
 
+   for (i = 0; i < HISI_SAS_MAX_DEVICES; i++) {
+   hisi_hba->devices[i].dev_type = SAS_PHY_UNUSED;
+   hisi_hba->devices[i].device_id = i;
+   hisi_hba->devices[i].dev_status = HISI_SAS_DEV_NORMAL;
+   }
+
for (i = 0; i < hisi_hba->queue_count; i++) {
struct hisi_sas_cq *cq = &hisi_hba->cq[i];
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v4 22/32] scsi: hisi_sas: add ssp command function

2015-11-16 Thread John Garry
Add path to send ssp command to HW

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |  30 +
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 234 +
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 194 +++
 3 files changed, 458 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 837d139..72657eb 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -35,6 +35,8 @@
 #define HISI_SAS_COMMAND_TABLE_SZ \
(((sizeof(union hisi_sas_command_table)+3)/4)*4)
 
+#define HISI_SAS_MAX_SSP_RESP_SZ (sizeof(struct ssp_frame_hdr) + 1024)
+
 #define HISI_SAS_NAME_LEN 32
 
 
@@ -80,15 +82,41 @@ struct hisi_sas_cq {
 struct hisi_sas_device {
enum sas_device_typedev_type;
u64 device_id;
+   u64 running_req;
u8 dev_status;
 };
 
 struct hisi_sas_slot {
+   struct list_head entry;
+   struct sas_task *task;
+   struct hisi_sas_port*port;
+   u64 n_elem;
+   int dlvry_queue;
+   int dlvry_queue_slot;
+   int idx;
+   void*cmd_hdr;
+   dma_addr_t cmd_hdr_dma;
+   void*status_buffer;
+   dma_addr_t status_buffer_dma;
+   void *command_table;
+   dma_addr_t command_table_dma;
+   struct hisi_sas_sge_page *sge_page;
+   dma_addr_t sge_page_dma;
+};
+
+struct hisi_sas_tmf_task {
+   u8 tmf;
+   u16 tag_of_task_to_be_managed;
 };
 
 struct hisi_sas_hw {
int (*hw_init)(struct hisi_hba *hisi_hba);
void (*sl_notify)(struct hisi_hba *hisi_hba, int phy_no);
+   int (*get_free_slot)(struct hisi_hba *hisi_hba, int *q, int *s);
+   void (*start_delivery)(struct hisi_hba *hisi_hba);
+   int (*prep_ssp)(struct hisi_hba *hisi_hba,
+   struct hisi_sas_slot *slot, int is_tmf,
+   struct hisi_sas_tmf_task *tmf);
int complete_hdr_size;
 };
 
@@ -122,7 +150,9 @@ struct hisi_hba {
struct hisi_sas_port port[HISI_SAS_MAX_PHYS];
 
int queue_count;
+   int queue;
char*int_names;
+   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 7bf6d2f..660ef6c 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -12,6 +12,15 @@
 #include "hisi_sas.h"
 #define DRV_NAME "hisi_sas"
 
+
+#define DEV_IS_GONE(dev) \
+   ((!dev) || (dev->dev_type == SAS_PHY_UNUSED))
+
+static struct hisi_hba *dev_to_hisi_hba(struct domain_device *device)
+{
+   return device->port->ha->lldd_ha;
+}
+
 static void hisi_sas_slot_index_clear(struct hisi_hba *hisi_hba, int slot_idx)
 {
void *bitmap = hisi_hba->slot_index_tags;
@@ -19,6 +28,31 @@ static void hisi_sas_slot_index_clear(struct hisi_hba 
*hisi_hba, int slot_idx)
clear_bit(slot_idx, bitmap);
 }
 
+static void hisi_sas_slot_index_free(struct hisi_hba *hisi_hba, int slot_idx)
+{
+   hisi_sas_slot_index_clear(hisi_hba, slot_idx);
+}
+
+static void hisi_sas_slot_index_set(struct hisi_hba *hisi_hba, int slot_idx)
+{
+   void *bitmap = hisi_hba->slot_index_tags;
+
+   set_bit(slot_idx, bitmap);
+}
+
+static int hisi_sas_slot_index_alloc(struct hisi_hba *hisi_hba, int *slot_idx)
+{
+   unsigned int index;
+   void *bitmap = hisi_hba->slot_index_tags;
+
+   index = find_first_zero_bit(bitmap, hisi_hba->slot_index_count);
+   if (index >= hisi_hba->slot_index_count)
+   return -SAS_QUEUE_FULL;
+   hisi_sas_slot_index_set(hisi_hba, index);
+   *slot_idx = index;
+   return 0;
+}
+
 static void hisi_sas_slot_index_init(struct hisi_hba *hisi_hba)
 {
int i;
@@ -26,6 +60,199 @@ static void hisi_sas_slot_index_init(struct hisi_hba 
*hisi_hba)
for (i = 0; i < hisi_hba->slot_index_count; ++i)
hisi_sas_slot_index_clear(hisi_hba, i);
 }
+static int hisi_sas_task_prep_ssp(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot, int is_tmf,
+ struct hisi_sas_tmf_task *tmf)
+{
+   return hisi_hba->hw->prep_ssp(hisi_hba, slot, is_tmf, tmf);
+}
+
+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)
+{
+   struct domain_device *device = task->dev;
+   struct hisi_sas_device *sas_dev = device->lldd_dev;
+   struct hisi_sas_port *port;
+   struct hisi_sas_slot *slot;
+   struct hisi_sas_cmd_hdr *cmd_hdr_base;
+   struct device *dev = &hisi_hba->pdev->dev;
+   int dlvry_queue_slot, dlvry_queue, n_elem = 0, rc, slot_idx;
+
+   if (!device->port) {
+   struct task_status_str

[PATCH v4 01/32] [SCSI] sas: centralise ssp frame information units

2015-11-16 Thread John Garry
The xfer_rdy, command, and task frame's iu structures
are not available in , but only aic94xx
driver folder.
Add them to include/scsi/sas.h

Signed-off-by: John Garry 
---
 drivers/scsi/aic94xx/aic94xx_sas.h | 49 -
 include/scsi/sas.h | 74 ++
 2 files changed, 80 insertions(+), 43 deletions(-)

diff --git a/drivers/scsi/aic94xx/aic94xx_sas.h 
b/drivers/scsi/aic94xx/aic94xx_sas.h
index 912e6b7..101072c 100644
--- a/drivers/scsi/aic94xx/aic94xx_sas.h
+++ b/drivers/scsi/aic94xx/aic94xx_sas.h
@@ -327,46 +327,9 @@ struct scb_header {
 
 #define LUN_SIZE8
 
-/* See SAS spec, task IU
- */
-struct ssp_task_iu {
-   u8 lun[LUN_SIZE]; /* BE */
-   u16_r_a;
-   u8 tmf;
-   u8 _r_b;
-   __be16 tag;   /* BE */
-   u8 _r_c[14];
-} __attribute__ ((packed));
-
-/* See SAS spec, command IU
- */
-struct ssp_command_iu {
-   u8 lun[LUN_SIZE];
-   u8 _r_a;
-   u8 efb_prio_attr; /* enable first burst, task prio & attr */
-#define EFB_MASK0x80
-#define TASK_PRIO_MASK 0x78
-#define TASK_ATTR_MASK  0x07
-
-   u8_r_b;
-   u8 add_cdb_len;   /* in dwords, since bit 0,1 are reserved */
-   union {
-   u8 cdb[16];
-   struct {
-   __le64 long_cdb_addr; /* bus address, LE */
-   __le32 long_cdb_size; /* LE */
-   u8 _r_c[3];
-   u8 eol_ds;/* eol:6,6, ds:5,4 */
-   } long_cdb;   /* sequencer extension */
-   };
-} __attribute__ ((packed));
-
-struct xfer_rdy_iu {
-   __be32 requested_offset;  /* BE */
-   __be32 write_data_len;/* BE */
-   __be32 _r_a;
-} __attribute__ ((packed));
-
+#define EFB_MASK0x80
+#define TASK_PRIO_MASK  0x78
+#define TASK_ATTR_MASK  0x07
 /* -- SCB tasks -- */
 
 /* This is both ssp_task and long_ssp_task
@@ -511,7 +474,7 @@ struct abort_task {
u8 proto_conn_rate;
__le32 _r_a;
struct ssp_frame_hdr ssp_frame;
-   struct ssp_task_iu ssp_task;
+   struct ssp_tmf_iu ssp_task;
__le16 sister_scb;
__le16 conn_handle;
u8 flags; /* ovrd_itnl_timer:3,3, suspend_data_trans:2,2 */
@@ -549,7 +512,7 @@ struct clear_nexus {
u8 _r_b[3];
u8 conn_mask;
u8 _r_c[19];
-   struct ssp_task_iu ssp_task; /* LUN and TAG */
+   struct ssp_tmf_iu ssp_task; /* LUN and TAG */
__le16 _r_d;
__le16 conn_handle;
__le64 _r_e;
@@ -562,7 +525,7 @@ struct initiate_ssp_tmf {
u8 proto_conn_rate;
__le32 _r_a;
struct ssp_frame_hdr ssp_frame;
-   struct ssp_task_iu ssp_task;
+   struct ssp_tmf_iu ssp_task;
__le16 sister_scb;
__le16 conn_handle;
u8 flags; /* itnl override and suspend data tx */
diff --git a/include/scsi/sas.h b/include/scsi/sas.h
index 0d2607d..42a84ef 100644
--- a/include/scsi/sas.h
+++ b/include/scsi/sas.h
@@ -344,6 +344,43 @@ struct ssp_response_iu {
u8 sense_data[0];
 } __attribute__ ((packed));
 
+struct ssp_command_iu {
+   u8 lun[8];
+   u8 _r_a;
+
+   union {
+   struct {
+   u8  attr:3;
+   u8  prio:4;
+   u8  efb:1;
+   };
+   u8 efb_prio_attr;
+   };
+
+   u8_r_b;
+
+   u8_r_c:2;
+   u8add_cdb_len:6;
+
+   u8cdb[16];
+   u8add_cdb[0];
+} __attribute__ ((packed));
+
+struct xfer_rdy_iu {
+   __be32 requested_offset;
+   __be32 write_data_len;
+   __be32 _r_a;
+} __attribute__ ((packed));
+
+struct ssp_tmf_iu {
+   u8 lun[8];
+   u16_r_a;
+   u8 tmf;
+   u8 _r_b;
+   __be16 tag;
+   u8 _r_c[14];
+} __attribute__ ((packed));
+
 /* -- SMP -- */
 
 struct report_general_resp {
@@ -538,6 +575,43 @@ struct ssp_response_iu {
u8 sense_data[0];
 } __attribute__ ((packed));
 
+struct ssp_command_iu {
+   u8 lun[8];
+   u8 _r_a;
+
+   union {
+   struct {
+   u8  efb:1;
+   u8  prio:4;
+   u8  attr:3;
+   };
+   u8 efb_prio_attr;
+   };
+
+   u8_r_b;
+
+   u8add_cdb_len:6;
+   u8_r_c:2;
+
+   u8cdb[16];
+   u8add_cdb[0];
+} __attribute__ ((packed));
+
+struct xfer_rdy_iu {
+   __be32 requested_offset;
+   __be32 write_data_len;
+   __be32 _r_a;
+} __attribute__ ((packed));
+
+struct ssp_tmf_iu {
+   u8 lun[8];
+   u16_r_a;
+   u8 tmf;
+   u8 _r_b;
+   __be16 tag;
+   u8 _r_c[14];
+} __attribute__ ((packed));
+
 /* -- SMP -- */
 
 struct

[PATCH v4 00/32] HiSilicon SAS driver

2015-11-16 Thread John Garry
This is the driver patchset for the HiSilicon SAS driver. The driver
is a platform driver.

The driver will support multiple revisions of HW. Currently only "v1"
HW is supported.

The driver uses libsas framework within the SCSI framework.

The v1 HW supports SSP and SMP, but not STP/SATA.

Differences to v3:
- update dt bindings for syscon property
- change SAS and SCSI deregister order
- remove unused phy struct elements

Differences to v2:
- update device tree bindings
- remove while loops when evaluating hba struct
- remove _lo and _hi DMA struct fields
- revised spinlock usage
- fix error handling for when CMPLT_HDR_ERR_RCRD_XFRD set
- general coding style and cosmetic fixes

Differences to v1:
- re-arch driver into main module and hw-specific driver module
- allocate hisi_hba in scsi_host_alloc
- use of_irq_count get irq count - depends on [1]
- use syscon to handle ctrl reg access
- get SAS address from device tree
- do not set cmd_per_lun to 1
- remove remove controller id
- use static wq in phy struct
- process control phy in caller context
- fix port->port_attached issue for rmmod

[1] http://www.spinics.net/lists/arm-kernel/msg452833.html

John Garry (32):
  [SCSI] sas: centralise ssp frame information units
  devicetree: bindings: scsi: HiSi SAS
  scsi: hisi_sas: add initial bare main driver
  scsi: hisi_sas: add scsi host registration
  scsi: hisi_sas: scan device tree
  scsi: hisi_sas: add HW DMA structures
  scsi: hisi_sas: allocate memories and create pools
  scsi: hisi_sas: add hisi_sas_remove
  scsi: hisi_sas: add slot init code
  scsi: hisi_sas: add cq structure initialization
  scsi: hisi_sas: add phy SAS ADDR initialization
  scsi: hisi_sas: set dev DMA mask
  scsi: hisi_sas: add hisi_hba workqueue
  scsi: hisi_sas: add hisi sas device type
  scsi: hisi_sas: add phy and port init
  scsi: hisi_sas: add timer and spinlock init
  scsi: hisi_sas: add v1 hw module init
  scsi: hisi_sas: add v1 hardware register definitions
  scsi: hisi_sas: add v1 HW initialisation code
  scsi: hisi_sas: add v1 hw interrupt init
  scsi: hisi_sas: add path from phyup irq to SAS framework
  scsi: hisi_sas: add ssp command function
  scsi: hisi_sas: add cq interrupt handler
  scsi: hisi_sas: add dev_found and dev_gone
  scsi: hisi_sas: add abnormal irq handler
  scsi: hisi_sas: add bcast interrupt handler
  scsi: hisi_sas: add smp protocol support
  scsi: hisi_sas: add scan finished and start
  scsi: hisi_sas: add tmf methods
  scsi: hisi_sas: add control phy handler
  scsi: hisi_sas: add fatal irq handler
  MAINTAINERS: add maintainer for HiSi SAS driver

 .../devicetree/bindings/scsi/hisilicon-sas.txt |   69 +
 MAINTAINERS|7 +
 drivers/scsi/Kconfig   |1 +
 drivers/scsi/Makefile  |1 +
 drivers/scsi/aic94xx/aic94xx_sas.h |   49 +-
 drivers/scsi/hisi_sas/Kconfig  |6 +
 drivers/scsi/hisi_sas/Makefile |2 +
 drivers/scsi/hisi_sas/hisi_sas.h   |  345 
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 1362 ++
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 1866 
 include/scsi/sas.h |   74 +
 11 files changed, 3739 insertions(+), 43 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
 create mode 100644 drivers/scsi/hisi_sas/Kconfig
 create mode 100644 drivers/scsi/hisi_sas/Makefile
 create mode 100644 drivers/scsi/hisi_sas/hisi_sas.h
 create mode 100644 drivers/scsi/hisi_sas/hisi_sas_main.c
 create mode 100644 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c

-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCHv4 1/1] SCSI: hosts: update to use ida_simple for host_no management

2015-11-16 Thread Hannes Reinecke
On 11/13/2015 10:54 PM, Martin K. Petersen wrote:
>> "Lee" == Lee Duncan  writes:
> 
>>> Well, I'm a bit worried about the loss of a monotonically increasing
>>> host number from the debugging perspective.  Right now, if you look
>>> at any log, hostX always refers to one and only one incarnation
>>> throughout the system lifetime for any given value of X.
> 
> That's a feature that I would absolutely hate to lose. I spend a huge
> amount of time looking at system logs.
> 
Right. Then have it enabled via a modprobe parameters.

We actually had customers running into a host_no overflow due to
excessive host allocations and freeing done by iSCSI.

Cheers,

Hannes
-- 
Dr. Hannes ReineckezSeries & Storage
h...@suse.de   +49 911 74053 688
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: F. Imendörffer, J. Smithard, J. Guild, D. Upmanyu, G. Norton
HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/2] iscsi-target: Fix rx_login_comp hang after login failure

2015-11-16 Thread Sagi Grimberg



On 15/11/2015 02:21, Nicholas A. Bellinger wrote:

From: Nicholas Bellinger 

This patch addresses a case where iscsi_target_do_tx_login_io()
fails sending the last login response PDU, after the RX/TX
threads have already been started.

The case centers around iscsi_target_rx_thread() not invoking
allow_signal(SIGINT) before the send_sig(SIGINT, ...) occurs
from the failure path, resulting in RX thread hanging
indefinately on iscsi_conn->rx_login_comp.

Note this bug is a regression introduced by:

   commit e54198657b65625085834847ab6271087323ffea
   Author: Nicholas Bellinger 
   Date:   Wed Jul 22 23:14:19 2015 -0700

   iscsi-target: Fix iscsit_start_kthreads failure OOPs

To address this bug, complete ->rx_login_complete for good
measure in the failure path, and immediately return from
RX thread context if connection state did not actually reach
full feature phase (TARG_CONN_STATE_LOGGED_IN).


Hey Nic,

Will it make better sense to start the rx/tx threads after
the login was completed (i.e. the conn is in state
TARG_CONN_STATE_LOGGED_IN) instead?

Sagi.
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] ib_srp: initialize dma_length in srp_map_idb

2015-11-16 Thread Sagi Grimberg



On 15/11/2015 23:10, Or Gerlitz wrote:

On Sun, Nov 15, 2015, Sagi Grimberg  wrote:

On 15/11/2015 19:59, Christoph Hellwig wrote:



Without this sg_dma_len will return 0 on architectures tha have
the dma_length field.


and what wrong with that?


Because it's not length 0. It's because I did a (documented) hack
with the new memory registration API. I hope we can fix it soon.



Christoph, probably typo here? "tha" needs to be "that"


Signed-off-by: Christoph Hellwig 
---
   drivers/infiniband/ulp/srp/ib_srp.c | 3 +++
   1 file changed, 3 insertions(+)

diff --git a/drivers/infiniband/ulp/srp/ib_srp.c
b/drivers/infiniband/ulp/srp/ib_srp.c
index 32f7962..445c0a6 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -1520,6 +1520,9 @@ static int srp_map_idb(struct srp_rdma_ch *ch,
struct srp_request *req,
 state.sg_nents = 1;
 sg_set_buf(idb_sg, req->indirect_desc, idb_len);
 idb_sg->dma_address = req->indirect_dma_addr; /* hack! */
+#ifdef CONFIG_NEED_SG_DMA_LENGTH
+   idb_sg->dma_length = idb_sg->length;  /* hack^2 */
+#endif



:)

We should really get this properly map/unmap per IO at some point.
Probably do it in both code paths...


Sagi, can you please elaborate a little further on the problem, srpt
WA,


It's srp initiator. This falls in the case where srp sends an indirect
buffer descriptor to the target (which is registered). For this
descriptor it uses a pre-dma-mapped buffer, so in order to fit it into
the new memory registration scheme (which works on SG lists), I hacked
a single entry SG and used the pre-dma-mapped address. What was missing
is the dma_length setting (because we didn't dma mapped the SG).

The proper fix is doing correct map/unmap per IO.


what do we do in isert and what is the proposed not WA solution?


iser does not have indirect buffer descriptors, only a single rkey
(per-direction).
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] SCSI-libfc: Delete an unnecessary check before the function call "kmem_cache_destroy"

2015-11-16 Thread SF Markus Elfring
From: Markus Elfring 
Date: Mon, 16 Nov 2015 09:39:12 +0100

The kmem_cache_destroy() function tests whether its argument is NULL
and then returns immediately. Thus the test around the call is not needed.

This issue was detected by using the Coccinelle software.

Signed-off-by: Markus Elfring 
---
 drivers/scsi/libfc/fc_fcp.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 5121272..d377514 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -2216,8 +2216,7 @@ int fc_setup_fcp(void)
 
 void fc_destroy_fcp(void)
 {
-   if (scsi_pkt_cachep)
-   kmem_cache_destroy(scsi_pkt_cachep);
+   kmem_cache_destroy(scsi_pkt_cachep);
 }
 
 /**
-- 
2.6.2

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html