[PATCH] ncr5380: Don't re-enter NCR5380_select() when aborting a command

2016-01-25 Thread Finn Thain
Fixes: 707d62b37fbb ("ncr5380: Fix EH during arbitration and selection")
Signed-off-by: Finn Thain 

---
 drivers/scsi/NCR5380.c   |2 +-
 drivers/scsi/atari_NCR5380.c |2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

Index: linux/drivers/scsi/NCR5380.c
===
--- linux.orig/drivers/scsi/NCR5380.c   2016-01-26 13:31:10.0 +1100
+++ linux/drivers/scsi/NCR5380.c2016-01-26 13:31:10.0 +1100
@@ -2337,7 +2337,7 @@ static int NCR5380_abort(struct scsi_cmn
dsprintk(NDEBUG_ABORT, instance,
 "abort: removed %p from disconnected list\n", cmd);
cmd->result = DID_ERROR << 16;
-   if (!hostdata->connected)
+   if (!hostdata->connected && !hostdata->selecting)
NCR5380_select(instance, cmd);
if (hostdata->connected != cmd) {
complete_cmd(instance, cmd);
Index: linux/drivers/scsi/atari_NCR5380.c
===
--- linux.orig/drivers/scsi/atari_NCR5380.c 2016-01-26 13:31:10.0 
+1100
+++ linux/drivers/scsi/atari_NCR5380.c  2016-01-26 13:31:10.0 +1100
@@ -2532,7 +2532,7 @@ static int NCR5380_abort(struct scsi_cmn
dsprintk(NDEBUG_ABORT, instance,
 "abort: removed %p from disconnected list\n", cmd);
cmd->result = DID_ERROR << 16;
-   if (!hostdata->connected)
+   if (!hostdata->connected && !hostdata->selecting)
NCR5380_select(instance, cmd);
if (hostdata->connected != cmd) {
complete_cmd(instance, cmd);


--
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] ncr5380: Correctly clear command pointers and lists after bus reset

2016-01-25 Thread Finn Thain
Commands subject to exception handling have to be returned to the scsi
mid-layer. Make sure that the various command pointers and command lists
in the low-level driver are correctly cleansed of the affected commands.

This fixes bugs that I accidentally introduced in commit 62717f537e1b
("ncr5380: Implement new eh_bus_reset_handler") such as the removal of
INIT_LIST_HEAD for the 'autosense' and 'disconnected' command lists, and
the possible NULL pointer dereference in NCR5380_bus_reset() that was
reported by Dan Carpenter.

hostdata->sensing may also point to an affected command so this pointer
also has to be cleared. The abort handler calls complete_cmd() to take
care of this; have the bus reset handler do the same.

The issue queue may also contain an affected command. If so, remove it.
This also follows the abort handler logic.

Reported-by: Dan Carpenter 
Fixes: 62717f537e1b ("ncr5380: Implement new eh_bus_reset_handler")
Signed-off-by: Finn Thain 

---
 drivers/scsi/NCR5380.c   |   19 ---
 drivers/scsi/atari_NCR5380.c |   19 ---
 2 files changed, 24 insertions(+), 14 deletions(-)

Index: linux/drivers/scsi/NCR5380.c
===
--- linux.orig/drivers/scsi/NCR5380.c   2016-01-26 13:31:10.0 +1100
+++ linux/drivers/scsi/NCR5380.c2016-01-26 13:31:11.0 +1100
@@ -2450,7 +2450,16 @@ static int NCR5380_bus_reset(struct scsi
 * commands!
 */
 
-   hostdata->selecting = NULL;
+   if (list_del_cmd(>unissued, cmd)) {
+   cmd->result = DID_RESET << 16;
+   cmd->scsi_done(cmd);
+   }
+
+   if (hostdata->selecting) {
+   hostdata->selecting->result = DID_RESET << 16;
+   complete_cmd(instance, hostdata->selecting);
+   hostdata->selecting = NULL;
+   }
 
list_for_each_entry(ncmd, >disconnected, list) {
struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
@@ -2458,6 +2467,7 @@ static int NCR5380_bus_reset(struct scsi
set_host_byte(cmd, DID_RESET);
cmd->scsi_done(cmd);
}
+   INIT_LIST_HEAD(>disconnected);
 
list_for_each_entry(ncmd, >autosense, list) {
struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
@@ -2465,6 +2475,7 @@ static int NCR5380_bus_reset(struct scsi
set_host_byte(cmd, DID_RESET);
cmd->scsi_done(cmd);
}
+   INIT_LIST_HEAD(>autosense);
 
if (hostdata->connected) {
set_host_byte(hostdata->connected, DID_RESET);
@@ -2472,12 +2483,6 @@ static int NCR5380_bus_reset(struct scsi
hostdata->connected = NULL;
}
 
-   if (hostdata->sensing) {
-   set_host_byte(hostdata->connected, DID_RESET);
-   complete_cmd(instance, hostdata->sensing);
-   hostdata->sensing = NULL;
-   }
-
for (i = 0; i < 8; ++i)
hostdata->busy[i] = 0;
 #ifdef REAL_DMA
Index: linux/drivers/scsi/atari_NCR5380.c
===
--- linux.orig/drivers/scsi/atari_NCR5380.c 2016-01-26 13:31:10.0 
+1100
+++ linux/drivers/scsi/atari_NCR5380.c  2016-01-26 13:31:11.0 +1100
@@ -2646,7 +2646,16 @@ static int NCR5380_bus_reset(struct scsi
 * commands!
 */
 
-   hostdata->selecting = NULL;
+   if (list_del_cmd(>unissued, cmd)) {
+   cmd->result = DID_RESET << 16;
+   cmd->scsi_done(cmd);
+   }
+
+   if (hostdata->selecting) {
+   hostdata->selecting->result = DID_RESET << 16;
+   complete_cmd(instance, hostdata->selecting);
+   hostdata->selecting = NULL;
+   }
 
list_for_each_entry(ncmd, >disconnected, list) {
struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
@@ -2654,6 +2663,7 @@ static int NCR5380_bus_reset(struct scsi
set_host_byte(cmd, DID_RESET);
cmd->scsi_done(cmd);
}
+   INIT_LIST_HEAD(>disconnected);
 
list_for_each_entry(ncmd, >autosense, list) {
struct scsi_cmnd *cmd = NCR5380_to_scmd(ncmd);
@@ -2661,6 +2671,7 @@ static int NCR5380_bus_reset(struct scsi
set_host_byte(cmd, DID_RESET);
cmd->scsi_done(cmd);
}
+   INIT_LIST_HEAD(>autosense);
 
if (hostdata->connected) {
set_host_byte(hostdata->connected, DID_RESET);
@@ -2668,12 +2679,6 @@ static int NCR5380_bus_reset(struct scsi
hostdata->connected = NULL;
}
 
-   if (hostdata->sensing) {
-   set_host_byte(hostdata->connected, DID_RESET);
-   complete_cmd(instance, hostdata->sensing);
-   hostdata->sensing = NULL;
-   }
-
 #ifdef SUPPORT_TAGS
free_all_tags(hostdata);
 #endif


--
To unsubscribe from this 

Re: [PATCH v2 01/23] devicetree: bindings: hisi_sas: add v2 HW bindings

2016-01-25 Thread Rob Herring
On Tue, Jan 26, 2016 at 01:21:50AM +0800, j00310691 wrote:
> From: John Garry 
> 
> Add the dt bindings for HiSi SAS controller v2 HW.
> 
> The main difference in the controller from dt perspective
> is interrupts. The v2 controller does not have dedicated
> fatal and broadcast interrupts - they are multiplexed on
> the channel interrupt.
> 
> Each SAS v2 controller can issue upto 64 commands
> (or connection requests) on the system bus without waiting
> for a response - this is know as am-max-transmissions.
> In hip06, sas controller #1 has a limitation that it has to
> limit am-max-transmissions to 32 - this limitation is due
> to chip system bus design. It is not anticipated that any
> future chip incorporating v2 controller will have such a
> limitation.
> 
> Signed-off-by: John Garry 
> ---
>  .../devicetree/bindings/scsi/hisilicon-sas.txt  | 21 
> -
>  1 file changed, 20 insertions(+), 1 deletion(-)

Acked-by: Rob Herring 
--
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 34/78] atari_NCR5380: Use arbitration timeout

2016-01-25 Thread Michael Schmitz
Hi Geert,

On Mon, Jan 25, 2016 at 9:05 PM, Geert Uytterhoeven
 wrote:

>>> Perhaps this is an ARAnyM quirk?
>
>> The MR_ARBITRATE bit should remain set until the driver clears it (or the
>> reset logic clears it). But it looks like aranym simply discards writes to
>> the mode register, such that reads always return 0.
>>
>> Compare
>>   http://sourceforge.net/p/aranym/code/ci/master/tree/src/ncr5380.cpp
>> with the MAME/MESS emulated device
>>   https://github.com/mamedev/mame/blob/master/src/devices/machine/ncr5380.cpp
>>
>> I don't know what the Hatari emulator does.
>>
>> In principle I think that Linux drivers should not carry workarounds for
>> emulators.
>
> Please consider ARAnyM is the current m68k workhorse, so it would be
> nice to handle this someway.
>
> Alternatively, we need to fix ARAnyM, or can make the creation of the
> atari_scsi platform device conditional on not running under ARAnyM.

Should be possible based on the machine cookie, unless that gets
munged by kernel startup code.

(Making the 5380 emulation a bit more complete such as in the MAME
source snippet would be my preference, too)

Cheers,

  Michael


>
> Thanks!
>
> 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


[PATCH v2 13/23] hisi_sas: add v2 phy down handler

2016-01-25 Thread j00310691
From: John Garry 

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

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index a7b83bd..35ce7b6 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -628,6 +628,29 @@ static void sl_notify_v2_hw(struct hisi_hba *hisi_hba, int 
phy_no)
hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL, sl_control);
 }
 
+static int get_wideport_bitmap_v2_hw(struct hisi_hba *hisi_hba, int port_id)
+{
+   int i, bitmap = 0;
+   u32 phy_port_num_ma = hisi_sas_read32(hisi_hba, PHY_PORT_NUM_MA);
+   u32 phy_state = hisi_sas_read32(hisi_hba, PHY_STATE);
+
+   for (i = 0; i < (hisi_hba->n_phy < 9 ? hisi_hba->n_phy : 8); i++)
+   if (phy_state & 1 << i)
+   if (((phy_port_num_ma >> (i * 4)) & 0xf) == port_id)
+   bitmap |= 1 << i;
+
+   if (hisi_hba->n_phy == 9) {
+   u32 port_state = hisi_sas_read32(hisi_hba, PORT_STATE);
+
+   if (phy_state & 1 << 8)
+   if (((port_state & PORT_STATE_PHY8_PORT_NUM_MSK) >>
+PORT_STATE_PHY8_PORT_NUM_OFF) == port_id)
+   bitmap |= 1 << 9;
+   }
+
+   return bitmap;
+}
+
 static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
 {
int i, res = 0;
@@ -705,6 +728,25 @@ end:
return res;
 }
 
+static int phy_down_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
+{
+   int res = 0;
+   u32 phy_cfg, phy_state;
+
+   hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 1);
+
+   phy_cfg = hisi_sas_phy_read32(hisi_hba, phy_no, PHY_CFG);
+
+   phy_state = hisi_sas_read32(hisi_hba, PHY_STATE);
+
+   hisi_sas_phy_down(hisi_hba, phy_no, (phy_state & 1 << phy_no) ? 1 : 0);
+
+   hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, CHL_INT0_NOT_RDY_MSK);
+   hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 0);
+
+   return res;
+}
+
 static irqreturn_t int_phy_updown_v2_hw(int irq_no, void *p)
 {
struct hisi_hba *hisi_hba = p;
@@ -726,6 +768,12 @@ static irqreturn_t int_phy_updown_v2_hw(int irq_no, void 
*p)
goto end;
}
 
+   if (irq_value & CHL_INT0_NOT_RDY_MSK)
+   /* phy down */
+   if (phy_down_v2_hw(phy_no, hisi_hba)) {
+   res = IRQ_NONE;
+   goto end;
+   }
}
irq_msk >>= 1;
phy_no++;
@@ -796,6 +844,7 @@ static int hisi_sas_v2_init(struct hisi_hba *hisi_hba)
 static const struct hisi_sas_hw hisi_sas_v2_hw = {
.hw_init = hisi_sas_v2_init,
.sl_notify = sl_notify_v2_hw,
+   .get_wideport_bitmap = get_wideport_bitmap_v2_hw,
.max_command_entries = HISI_SAS_COMMAND_ENTRIES_V2_HW,
.complete_hdr_size = sizeof(struct hisi_sas_complete_v2_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 v2 02/23] hisi_sas: relocate DEV_IS_EXPANDER

2016-01-25 Thread j00310691
From: John Garry 

Relocate DEV_IS_EXPANDER to hisi_sas.h as
it will be required for v2 hw support.

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

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 5af2e41..21eb2bb 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -37,6 +37,10 @@
 #define HISI_SAS_MAX_SSP_RESP_SZ (sizeof(struct ssp_frame_hdr) + 1024)
 #define HISI_SAS_MAX_SMP_RESP_SZ 1028
 
+#define DEV_IS_EXPANDER(type) \
+   ((type == SAS_EDGE_EXPANDER_DEVICE) || \
+   (type == SAS_FANOUT_EXPANDER_DEVICE))
+
 struct hisi_hba;
 
 enum {
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 99b1950..7689939 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -12,10 +12,6 @@
 #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))
 
-- 
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 v2 10/23] hisi_sas: add init_id_frame_v2_hw()

2016-01-25 Thread j00310691
From: John Garry 

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

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index da9c375..6f05333 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -288,6 +288,44 @@ static u32 hisi_sas_phy_read32(struct hisi_hba *hisi_hba,
return readl(regs);
 }
 
+static void config_id_frame_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
+{
+   struct sas_identify_frame identify_frame;
+   u32 *identify_buffer;
+
+   memset(_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(_frame._un4_11[0], hisi_hba->sas_addr, SAS_ADDR_SIZE);
+   memcpy(_frame.sas_addr[0], hisi_hba->sas_addr, SAS_ADDR_SIZE);
+   identify_frame.phy_id = phy_no;
+   identify_buffer = (u32 *)(_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_v2_hw(struct hisi_hba *hisi_hba)
+{
+   int i;
+
+   for (i = 0; i < hisi_hba->n_phy; i++)
+   config_id_frame_v2_hw(hisi_hba, i);
+}
+
 static int reset_hw_v2_hw(struct hisi_hba *hisi_hba)
 {
int i, reset_val;
@@ -520,6 +558,8 @@ static int hw_init_v2_hw(struct hisi_hba *hisi_hba)
msleep(100);
init_reg_v2_hw(hisi_hba);
 
+   init_id_frame_v2_hw(hisi_hba);
+
return 0;
 }
 
-- 
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: [PATCH v2] mptlan: add checks for dma mapping errors

2016-01-25 Thread Tomas Henzl
On 23.1.2016 01:41, Alexey Khoroshilov wrote:
> mpt_lan_sdu_send() and mpt_lan_post_receive_buckets() do not check
> if mapping dma memory succeed.
> The patch adds the checks and failure handling.
>
> Found by Linux Driver Verification project (linuxtesting.org).
>
> Signed-off-by: Alexey Khoroshilov 
> ---
>  drivers/message/fusion/mptlan.c | 14 ++
>  1 file changed, 14 insertions(+)
>
> diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
> index cbe96072a6cc..3b6c8a755713 100644
> --- a/drivers/message/fusion/mptlan.c
> +++ b/drivers/message/fusion/mptlan.c
> @@ -734,6 +734,12 @@ mpt_lan_sdu_send (struct sk_buff *skb, struct net_device 
> *dev)
>  
>  dma = pci_map_single(mpt_dev->pcidev, skb->data, skb->len,
>PCI_DMA_TODEVICE);
> + if (pci_dma_mapping_error(mpt_dev->pcidev, dma)) {
> + netif_stop_queue(dev);

Hi Alexey,
isn't a mpt_put_msg_frame needed here ?
and a similar de-alloc in next chunk too?
-tms

> +
> + printk (KERN_ERR "%s: dma mapping failed\n", __func__);
> + return NETDEV_TX_BUSY;
> + }
>  
>   priv->SendCtl[ctx].skb = skb;
>   priv->SendCtl[ctx].dma = dma;
> @@ -1232,6 +1238,14 @@ mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv)
>  
>   dma = pci_map_single(mpt_dev->pcidev, skb->data,
>len, PCI_DMA_FROMDEVICE);
> + if (pci_dma_mapping_error(mpt_dev->pcidev, 
> dma)) {
> + printk (KERN_WARNING
> + MYNAM "/%s: dma mapping 
> failed\n",
> + __func__);
> + 
> priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = ctx;
> + 
> spin_unlock_irqrestore(>rxfidx_lock, flags);
> + break;
> + }
>  
>   priv->RcvCtl[ctx].skb = skb;
>   priv->RcvCtl[ctx].dma = dma;

--
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 04/23] hisi_sas: reduce max itct entries

2016-01-25 Thread j00310691
From: John Garry 

Since v2 hw only supports 2048 itct entries,
as opposed to 4096 for v1 hw, set the max itct
entries to the lower of the two.

It is not anticipated that any device with v1
will ever require to connect > 2048 devices.

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 5ed5cf1..7c05eb3 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -25,7 +25,7 @@
 #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_ITCT_ENTRIES 2048
 #define HISI_SAS_MAX_DEVICES HISI_SAS_MAX_ITCT_ENTRIES
 
 #define HISI_SAS_STATUS_BUF_SZ \
-- 
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 v2 18/23] hisi_sas: add v2 code to send smp command

2016-01-25 Thread j00310691
From: John Garry 

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

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index ab6ea25..2c6a753 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -744,6 +744,76 @@ static int prep_prd_sge_v2_hw(struct hisi_hba *hisi_hba,
return 0;
 }
 
+static int prep_smp_v2_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 = _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 = >smp_task.smp_req;
+   elem = dma_map_sg(dev, sg_req, 1, DMA_TO_DEVICE);
+   if (!elem)
+   return -ENOMEM;
+   req_len = sg_dma_len(sg_req);
+   req_dma_addr = sg_dma_address(sg_req);
+
+   /* resp */
+   sg_resp = >smp_task.smp_resp;
+   elem = dma_map_sg(dev, sg_resp, 1, DMA_FROM_DEVICE);
+   if (!elem) {
+   rc = -ENOMEM;
+   goto err_out_req;
+   }
+   resp_len = sg_dma_len(sg_resp);
+   if ((req_len & 0x3) || (resp_len & 0x3)) {
+   rc = -EINVAL;
+   goto err_out_resp;
+   }
+
+   /* create header */
+   /* dw0 */
+   hdr->dw0 = cpu_to_le32((port->id << CMD_HDR_PORT_OFF) |
+  (1 << CMD_HDR_PRIORITY_OFF) | /* high pri */
+  (2 << CMD_HDR_CMD_OFF)); /* smp */
+
+   /* map itct entry */
+   hdr->dw1 = cpu_to_le32((sas_dev->device_id << CMD_HDR_DEV_ID_OFF) |
+  (1 << CMD_HDR_FRAME_TYPE_OFF) |
+  (DIR_NO_DATA << CMD_HDR_DIR_OFF));
+
+   /* dw2 */
+   hdr->dw2 = cpu_to_le32req_len - 4) / 4) << CMD_HDR_CFL_OFF) |
+  (HISI_SAS_MAX_SMP_RESP_SZ / 4 <<
+  CMD_HDR_MRFL_OFF));
+
+   hdr->transfer_tags = cpu_to_le32(slot->idx << CMD_HDR_IPTT_OFF);
+
+   hdr->cmd_table_addr = cpu_to_le64(req_dma_addr);
+   hdr->sts_buffer_addr = cpu_to_le64(slot->status_buffer_dma);
+
+   return 0;
+
+err_out_resp:
+   dma_unmap_sg(dev, >task->smp_task.smp_resp, 1,
+DMA_FROM_DEVICE);
+err_out_req:
+   dma_unmap_sg(dev, >task->smp_task.smp_req, 1,
+DMA_TO_DEVICE);
+   return rc;
+}
+
 static int prep_ssp_v2_hw(struct hisi_hba *hisi_hba,
  struct hisi_sas_slot *slot, int is_tmf,
  struct hisi_sas_tmf_task *tmf)
@@ -1395,6 +1465,7 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = {
.hw_init = hisi_sas_v2_init,
.sl_notify = sl_notify_v2_hw,
.get_wideport_bitmap = get_wideport_bitmap_v2_hw,
+   .prep_smp = prep_smp_v2_hw,
.prep_ssp = prep_ssp_v2_hw,
.get_free_slot = get_free_slot_v2_hw,
.start_delivery = start_delivery_v2_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 v2 19/23] hisi_sas: add v2 code for itct setup and free

2016-01-25 Thread j00310691
From: John Garry 

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

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 2c6a753..8b51acf 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -353,6 +353,96 @@ static void init_id_frame_v2_hw(struct hisi_hba *hisi_hba)
config_id_frame_v2_hw(hisi_hba, i);
 }
 
+static void setup_itct_v2_hw(struct hisi_hba *hisi_hba,
+struct hisi_sas_device *sas_dev)
+{
+   struct domain_device *device = sas_dev->sas_device;
+   struct device *dev = _hba->pdev->dev;
+   u64 qw0, device_id = sas_dev->device_id;
+   struct hisi_sas_itct *itct = _hba->itct[device_id];
+   struct domain_device *parent_dev = device->parent;
+   struct hisi_sas_port *port = device->port->lldd_port;
+
+   memset(itct, 0, sizeof(*itct));
+
+   /* qw0 */
+   qw0 = 0;
+   switch (sas_dev->dev_type) {
+   case SAS_END_DEVICE:
+   case SAS_EDGE_EXPANDER_DEVICE:
+   case SAS_FANOUT_EXPANDER_DEVICE:
+   qw0 = HISI_SAS_DEV_TYPE_SSP << ITCT_HDR_DEV_TYPE_OFF;
+   break;
+   case SAS_SATA_DEV:
+   if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type))
+   qw0 = HISI_SAS_DEV_TYPE_STP << ITCT_HDR_DEV_TYPE_OFF;
+   else
+   qw0 = HISI_SAS_DEV_TYPE_SATA << ITCT_HDR_DEV_TYPE_OFF;
+   break;
+   default:
+   dev_warn(dev, "setup itct: unsupported dev type (%d)\n",
+sas_dev->dev_type);
+   }
+
+   qw0 |= ((1 << ITCT_HDR_VALID_OFF) |
+   (device->max_linkrate << ITCT_HDR_MCR_OFF) |
+   (1 << ITCT_HDR_VLN_OFF) |
+   (port->id << ITCT_HDR_PORT_ID_OFF));
+   itct->qw0 = cpu_to_le64(qw0);
+
+   /* qw1 */
+   memcpy(>sas_addr, device->sas_addr, SAS_ADDR_SIZE);
+   itct->sas_addr = __swab64(itct->sas_addr);
+
+   /* qw2 */
+   itct->qw2 = cpu_to_le64((500ULL << ITCT_HDR_INLT_OFF) |
+   (0xff00ULL << ITCT_HDR_BITLT_OFF) |
+   (0xff00ULL << ITCT_HDR_MCTLT_OFF) |
+   (0xff00ULL << ITCT_HDR_RTOLT_OFF));
+}
+
+static void free_device_v2_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_device *sas_dev)
+{
+   u64 qw0, dev_id = sas_dev->device_id;
+   struct device *dev = _hba->pdev->dev;
+   struct hisi_sas_itct *itct = _hba->itct[dev_id];
+   u32 reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
+   int i;
+
+   /* clear the itct interrupt state */
+   if (ENT_INT_SRC3_ITC_INT_MSK & reg_val)
+   hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
+ENT_INT_SRC3_ITC_INT_MSK);
+
+   /* clear the itct int*/
+   for (i = 0; i < 2; i++) {
+   /* clear the itct table*/
+   reg_val = hisi_sas_read32(hisi_hba, ITCT_CLR);
+   reg_val |= ITCT_CLR_EN_MSK | (dev_id & ITCT_DEV_MSK);
+   hisi_sas_write32(hisi_hba, ITCT_CLR, reg_val);
+
+   udelay(10);
+   reg_val = hisi_sas_read32(hisi_hba, ENT_INT_SRC3);
+   if (ENT_INT_SRC3_ITC_INT_MSK & reg_val) {
+   dev_dbg(dev, "got clear ITCT done interrupt\n");
+
+   /* invalid the itct state*/
+   qw0 = cpu_to_le64(itct->qw0);
+   qw0 &= ~(1 << ITCT_HDR_VALID_OFF);
+   hisi_sas_write32(hisi_hba, ENT_INT_SRC3,
+ENT_INT_SRC3_ITC_INT_MSK);
+   hisi_hba->devices[dev_id].dev_type = SAS_PHY_UNUSED;
+   hisi_hba->devices[dev_id].dev_status = 
HISI_SAS_DEV_NORMAL;
+
+   /* clear the itct */
+   hisi_sas_write32(hisi_hba, ITCT_CLR, 0);
+   dev_dbg(dev, "clear ITCT ok\n");
+   break;
+   }
+   }
+}
+
 static int reset_hw_v2_hw(struct hisi_hba *hisi_hba)
 {
int i, reset_val;
@@ -1463,8 +1553,10 @@ static int hisi_sas_v2_init(struct hisi_hba *hisi_hba)
 
 static const struct hisi_sas_hw hisi_sas_v2_hw = {
.hw_init = hisi_sas_v2_init,
+   .setup_itct = setup_itct_v2_hw,
.sl_notify = sl_notify_v2_hw,
.get_wideport_bitmap = get_wideport_bitmap_v2_hw,
+   .free_device = free_device_v2_hw,
.prep_smp = prep_smp_v2_hw,
.prep_ssp = prep_ssp_v2_hw,
.get_free_slot = get_free_slot_v2_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 v2 07/23] hisi_sas: add bare v2 hw driver

2016-01-25 Thread j00310691
From: John Garry 

Just add enough to build and init the module.

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/Makefile |  2 +-
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 48 ++
 2 files changed, 49 insertions(+), 1 deletion(-)
 create mode 100644 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c

diff --git a/drivers/scsi/hisi_sas/Makefile b/drivers/scsi/hisi_sas/Makefile
index 3e70eae..c6d3a1b 100644
--- a/drivers/scsi/hisi_sas/Makefile
+++ b/drivers/scsi/hisi_sas/Makefile
@@ -1,2 +1,2 @@
 obj-$(CONFIG_SCSI_HISI_SAS)+= hisi_sas_main.o
-obj-$(CONFIG_SCSI_HISI_SAS)+= hisi_sas_v1_hw.o
+obj-$(CONFIG_SCSI_HISI_SAS)+= hisi_sas_v1_hw.o hisi_sas_v2_hw.o
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
new file mode 100644
index 000..0f7f2af
--- /dev/null
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016 Linaro Ltd.
+ * Copyright (c) 2016 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_v2_hw"
+
+static const struct hisi_sas_hw hisi_sas_v2_hw = {
+};
+
+static int hisi_sas_v2_probe(struct platform_device *pdev)
+{
+   return hisi_sas_probe(pdev, _sas_v2_hw);
+}
+
+static int hisi_sas_v2_remove(struct platform_device *pdev)
+{
+   return hisi_sas_remove(pdev);
+}
+
+static const struct of_device_id sas_v2_of_match[] = {
+   { .compatible = "hisilicon,hip06-sas-v2",},
+   {},
+};
+MODULE_DEVICE_TABLE(of, sas_v2_of_match);
+
+static struct platform_driver hisi_sas_v2_driver = {
+   .probe = hisi_sas_v2_probe,
+   .remove = hisi_sas_v2_remove,
+   .driver = {
+   .name = DRV_NAME,
+   .of_match_table = sas_v2_of_match,
+   },
+};
+
+module_platform_driver(hisi_sas_v2_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("John Garry ");
+MODULE_DESCRIPTION("HISILICON SAS controller v2 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


Re: [PATCH-v2 11/12] xen-scsiback: Convert to percpu_ida tag allocation

2016-01-25 Thread Juergen Gross
On 25/01/16 09:11, Nicholas A. Bellinger wrote:
> From: Nicholas Bellinger 
> 
> Cc: Juergen Gross 
> Cc: Hannes Reinecke 
> Cc: David Vrabel 
> Signed-off-by: Nicholas Bellinger 

Could you please rebase to current version? The patch won't apply.


Juergen
--
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 00/23] HiSilicon SAS v2 hw support

2016-01-25 Thread John Garry
I'll re-send this patchset with my real name. I had my user name set to 
my company ID in my terminal.


I did send a trail patchset to myself, but my mail client autochanged 
the ID to my real name so I never detected.


John

--
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] mptlan: add checks for dma mapping errors

2016-01-25 Thread Alexey Khoroshilov
On 25.01.2016 16:36, Tomas Henzl wrote:
> On 23.1.2016 01:41, Alexey Khoroshilov wrote:
>> mpt_lan_sdu_send() and mpt_lan_post_receive_buckets() do not check
>> if mapping dma memory succeed.
>> The patch adds the checks and failure handling.
>>
>> Found by Linux Driver Verification project (linuxtesting.org).
>>
>> Signed-off-by: Alexey Khoroshilov 
>> ---
>>  drivers/message/fusion/mptlan.c | 14 ++
>>  1 file changed, 14 insertions(+)
>>
>> diff --git a/drivers/message/fusion/mptlan.c 
>> b/drivers/message/fusion/mptlan.c
>> index cbe96072a6cc..3b6c8a755713 100644
>> --- a/drivers/message/fusion/mptlan.c
>> +++ b/drivers/message/fusion/mptlan.c
>> @@ -734,6 +734,12 @@ mpt_lan_sdu_send (struct sk_buff *skb, struct 
>> net_device *dev)
>>  
>>  dma = pci_map_single(mpt_dev->pcidev, skb->data, skb->len,
>>   PCI_DMA_TODEVICE);
>> +if (pci_dma_mapping_error(mpt_dev->pcidev, dma)) {
>> +netif_stop_queue(dev);
> 
> Hi Alexey,
> isn't a mpt_put_msg_frame needed here ?
> and a similar de-alloc in next chunk too?
> -tms

Hi Tomas,

You are right, thank you!
I'll resend the patch.

--
Alexey

--
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 08/23] hisi_sas: add v2 register definitions

2016-01-25 Thread j00310691
From: John Garry 

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

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 0f7f2af..31e4fdc 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -12,6 +12,243 @@
 #include "hisi_sas.h"
 #define DRV_NAME "hisi_sas_v2_hw"
 
+/* global registers need init*/
+#define DLVRY_QUEUE_ENABLE 0x0
+#define IOST_BASE_ADDR_LO  0x8
+#define IOST_BASE_ADDR_HI  0xc
+#define ITCT_BASE_ADDR_LO  0x10
+#define ITCT_BASE_ADDR_HI  0x14
+#define IO_BROKEN_MSG_ADDR_LO  0x18
+#define IO_BROKEN_MSG_ADDR_HI  0x1c
+#define PHY_CONTEXT0x20
+#define PHY_STATE  0x24
+#define PHY_PORT_NUM_MA0x28
+#define PORT_STATE 0x2c
+#define PORT_STATE_PHY8_PORT_NUM_OFF   16
+#define PORT_STATE_PHY8_PORT_NUM_MSK   (0xf << PORT_STATE_PHY8_PORT_NUM_OFF)
+#define PORT_STATE_PHY8_CONN_RATE_OFF  20
+#define PORT_STATE_PHY8_CONN_RATE_MSK  (0xf << PORT_STATE_PHY8_CONN_RATE_OFF)
+#define PHY_CONN_RATE  0x30
+#define HGC_TRANS_TASK_CNT_LIMIT   0x38
+#define AXI_AHB_CLK_CFG0x3c
+#define ITCT_CLR   0x44
+#define ITCT_CLR_EN_OFF16
+#define ITCT_CLR_EN_MSK(0x1 << ITCT_CLR_EN_OFF)
+#define ITCT_DEV_OFF   0
+#define ITCT_DEV_MSK   (0x7ff << ITCT_DEV_OFF)
+#define AXI_USER1  0x48
+#define AXI_USER2  0x4c
+#define IO_SATA_BROKEN_MSG_ADDR_LO 0x58
+#define IO_SATA_BROKEN_MSG_ADDR_HI 0x5c
+#define SATA_INITI_D2H_STORE_ADDR_LO   0x60
+#define SATA_INITI_D2H_STORE_ADDR_HI   0x64
+#define HGC_SAS_TX_OPEN_FAIL_RETRY_CTRL0x84
+#define HGC_SAS_TXFAIL_RETRY_CTRL  0x88
+#define HGC_GET_ITV_TIME   0x90
+#define DEVICE_MSG_WORK_MODE   0x94
+#define OPENA_WT_CONTI_TIME0x9c
+#define I_T_NEXUS_LOSS_TIME0xa0
+#define MAX_CON_TIME_LIMIT_TIME0xa4
+#define BUS_INACTIVE_LIMIT_TIME0xa8
+#define REJECT_TO_OPEN_LIMIT_TIME  0xac
+#define CFG_AGING_TIME 0xbc
+#define HGC_DFX_CFG2   0xc0
+#define HGC_IOMB_PROC1_STATUS  0x104
+#define CFG_1US_TIMER_TRSH 0xcc
+#define HGC_INVLD_DQE_INFO 0x148
+#define HGC_INVLD_DQE_INFO_FB_CH0_OFF  9
+#define HGC_INVLD_DQE_INFO_FB_CH0_MSK  (0x1 << HGC_INVLD_DQE_INFO_FB_CH0_OFF)
+#define HGC_INVLD_DQE_INFO_FB_CH3_OFF  18
+#define INT_COAL_EN0x19c
+#define OQ_INT_COAL_TIME   0x1a0
+#define OQ_INT_COAL_CNT0x1a4
+#define ENT_INT_COAL_TIME  0x1a8
+#define ENT_INT_COAL_CNT   0x1ac
+#define OQ_INT_SRC 0x1b0
+#define OQ_INT_SRC_MSK 0x1b4
+#define ENT_INT_SRC1   0x1b8
+#define ENT_INT_SRC1_D2H_FIS_CH0_OFF   0
+#define ENT_INT_SRC1_D2H_FIS_CH0_MSK   (0x1 << ENT_INT_SRC1_D2H_FIS_CH0_OFF)
+#define ENT_INT_SRC1_D2H_FIS_CH1_OFF   8
+#define ENT_INT_SRC1_D2H_FIS_CH1_MSK   (0x1 << ENT_INT_SRC1_D2H_FIS_CH1_OFF)
+#define ENT_INT_SRC2   0x1bc
+#define ENT_INT_SRC3   0x1c0
+#define ENT_INT_SRC3_ITC_INT_OFF   15
+#define ENT_INT_SRC3_ITC_INT_MSK   (0x1 << ENT_INT_SRC3_ITC_INT_OFF)
+#define ENT_INT_SRC_MSK1   0x1c4
+#define ENT_INT_SRC_MSK2   0x1c8
+#define ENT_INT_SRC_MSK3   0x1cc
+#define ENT_INT_SRC_MSK3_ENT95_MSK_OFF 31
+#define ENT_INT_SRC_MSK3_ENT95_MSK_MSK (0x1 << ENT_INT_SRC_MSK3_ENT95_MSK_OFF)
+#define SAS_ECC_INTR_MSK   0x1ec
+#define HGC_ERR_STAT_EN0x238
+#define DLVRY_Q_0_BASE_ADDR_LO 0x260
+#define DLVRY_Q_0_BASE_ADDR_HI 0x264
+#define DLVRY_Q_0_DEPTH0x268
+#define DLVRY_Q_0_WR_PTR   0x26c
+#define DLVRY_Q_0_RD_PTR   0x270
+#define HYPER_STREAM_ID_EN_CFG 0xc80
+#define OQ0_INT_SRC_MSK0xc90
+#define COMPL_Q_0_BASE_ADDR_LO 0x4e0
+#define COMPL_Q_0_BASE_ADDR_HI 0x4e4
+#define COMPL_Q_0_DEPTH0x4e8
+#define COMPL_Q_0_WR_PTR   0x4ec
+#define COMPL_Q_0_RD_PTR   0x4f0
+
+/* phy registers need init */
+#define PORT_BASE  (0x2000)
+
+#define PHY_CFG(PORT_BASE + 0x0)
+#define HARD_PHY_LINKRATE  (PORT_BASE + 0x4)
+#define PHY_CFG_ENA_OFF0
+#define PHY_CFG_ENA_MSK(0x1 << PHY_CFG_ENA_OFF)
+#define PHY_CFG_DC_OPT_OFF 2
+#define PHY_CFG_DC_OPT_MSK (0x1 << PHY_CFG_DC_OPT_OFF)
+#define 

[PATCH v2 09/23] hisi_sas: add v2 hw init

2016-01-25 Thread j00310691
From: John Garry 

Add code to initialise the hardware.

Support is also added to deal with the
"am-max-transmissions" (amt) limitation in hip06
controller #1. This is how many connection requests
we can send on the system bus before waiting for a
response.
Due to chip bus design, controller #1 is limited to
32 amt, while, by design, a controller supports 64.
The default value for the nibbles in the relevant
registers is 0x40; these need to be programmed with
0x20.

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

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 31e4fdc..da9c375 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -249,7 +249,295 @@
 #define ITCT_HDR_RTOLT_OFF 48
 #define ITCT_HDR_RTOLT_MSK (0xULL << ITCT_HDR_RTOLT_OFF)
 
+struct hisi_sas_complete_v2_hdr {
+   __le32 dw0;
+   __le32 dw1;
+   __le32 act;
+   __le32 dw3;
+};
+
+#define HISI_SAS_COMMAND_ENTRIES_V2_HW 4096
+
+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 int reset_hw_v2_hw(struct hisi_hba *hisi_hba)
+{
+   int i, reset_val;
+   u32 val;
+   unsigned long end_time;
+   struct device *dev = _hba->pdev->dev;
+
+   /* The mask needs to be set depending on the number of phys */
+   if (hisi_hba->n_phy == 9)
+   reset_val = 0x1f;
+   else
+   reset_val = 0x7;
+
+   /* Disable all of the DQ */
+   for (i = 0; i < HISI_SAS_MAX_QUEUES; i++)
+   hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0);
+
+   /* Disable all of the PHYs */
+   for (i = 0; i < hisi_hba->n_phy; i++) {
+   u32 phy_cfg = hisi_sas_phy_read32(hisi_hba, i, PHY_CFG);
+
+   phy_cfg &= ~PHY_CTRL_RESET_MSK;
+   hisi_sas_phy_write32(hisi_hba, i, PHY_CFG, phy_cfg);
+   }
+   udelay(50);
+
+   /* Ensure DMA tx & rx idle */
+   for (i = 0; i < hisi_hba->n_phy; i++) {
+   u32 dma_tx_status, dma_rx_status;
+
+   end_time = jiffies + msecs_to_jiffies(1000);
+
+   while (1) {
+   dma_tx_status = hisi_sas_phy_read32(hisi_hba, i,
+   DMA_TX_STATUS);
+   dma_rx_status = hisi_sas_phy_read32(hisi_hba, i,
+   DMA_RX_STATUS);
+
+   if (!(dma_tx_status & DMA_TX_STATUS_BUSY_MSK) &&
+   !(dma_rx_status & DMA_RX_STATUS_BUSY_MSK))
+   break;
+
+   msleep(20);
+   if (time_after(jiffies, end_time))
+   return -EIO;
+   }
+   }
+
+   /* Ensure axi bus idle */
+   end_time = jiffies + msecs_to_jiffies(1000);
+   while (1) {
+   u32 axi_status =
+   hisi_sas_read32(hisi_hba, AXI_CFG);
+
+   if (axi_status == 0)
+   break;
+
+   msleep(20);
+   if (time_after(jiffies, end_time))
+   return -EIO;
+   }
+
+   /* reset and disable clock*/
+   regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_reset_reg,
+   reset_val);
+   regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_clock_ena_reg + 4,
+   reset_val);
+   msleep(1);
+   regmap_read(hisi_hba->ctrl, hisi_hba->ctrl_reset_sts_reg, );
+   if (reset_val != (val & reset_val)) {
+   dev_err(dev, "SAS reset fail.\n");
+   return -EIO;
+   }
+
+   /* De-reset and enable clock*/
+   regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_reset_reg + 4,
+   reset_val);
+   regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_clock_ena_reg,
+   reset_val);
+   msleep(1);
+   regmap_read(hisi_hba->ctrl, hisi_hba->ctrl_reset_sts_reg,
+   );
+   if (val & reset_val) {
+   dev_err(dev, "SAS de-reset fail.\n");

[PATCH v2 23/23] hisi_sas: update driver version to 1.1

2016-01-25 Thread j00310691
From: John Garry 

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index f00b55b..9f08c0c 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -21,7 +21,7 @@
 #include 
 #include 
 
-#define DRV_VERSION "v1.0"
+#define DRV_VERSION "v1.1"
 
 #define HISI_SAS_MAX_PHYS  9
 #define HISI_SAS_MAX_QUEUES32
-- 
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 v2 20/23] hisi_sas: add v2 path to send ATA command

2016-01-25 Thread j00310691
From: John Garry 

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |   4 +
 drivers/scsi/hisi_sas/hisi_sas_main.c  |   8 ++
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 162 +
 3 files changed, 174 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index b2e4b26..f00b55b 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #define DRV_VERSION "v1.0"
@@ -35,6 +36,7 @@
 
 #define HISI_SAS_MAX_SSP_RESP_SZ (sizeof(struct ssp_frame_hdr) + 1024)
 #define HISI_SAS_MAX_SMP_RESP_SZ 1028
+#define HISI_SAS_MAX_STP_RESP_SZ 28
 
 #define DEV_IS_EXPANDER(type) \
((type == SAS_EDGE_EXPANDER_DEVICE) || \
@@ -135,6 +137,8 @@ struct hisi_sas_hw {
struct hisi_sas_tmf_task *tmf);
int (*prep_smp)(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot);
+   int (*prep_stp)(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 (*phy_enable)(struct hisi_hba *hisi_hba, int phy_no);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index c48df6d..406b515 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -107,6 +107,12 @@ static int hisi_sas_task_prep_ssp(struct hisi_hba 
*hisi_hba,
return hisi_hba->hw->prep_ssp(hisi_hba, slot, is_tmf, tmf);
 }
 
+static int hisi_sas_task_prep_ata(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot)
+{
+   return hisi_hba->hw->prep_stp(hisi_hba, slot);
+}
+
 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)
@@ -230,6 +236,8 @@ static int hisi_sas_task_prep(struct sas_task *task, struct 
hisi_hba *hisi_hba,
case SAS_PROTOCOL_SATA:
case SAS_PROTOCOL_STP:
case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
+   rc = hisi_sas_task_prep_ata(hisi_hba, slot);
+   break;
default:
dev_err(dev, "task prep: unknown/unsupported proto (0x%x)\n",
task->task_proto);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 8b51acf..cea0b36 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -269,6 +269,12 @@ enum {
 #define DIR_TO_DEVICE 2
 #define DIR_RESERVED 3
 
+#define SATA_PROTOCOL_NONDATA  0x1
+#define SATA_PROTOCOL_PIO  0x2
+#define SATA_PROTOCOL_DMA  0x4
+#define SATA_PROTOCOL_FPDMA0x8
+#define SATA_PROTOCOL_ATAPI0x10
+
 static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off)
 {
void __iomem *regs = hisi_hba->regs + off;
@@ -994,6 +1000,19 @@ static int prep_ssp_v2_hw(struct hisi_hba *hisi_hba,
return 0;
 }
 
+static void sata_done_v2_hw(struct hisi_hba *hisi_hba, struct sas_task *task,
+   struct hisi_sas_slot *slot)
+{
+   struct task_status_struct *ts = >task_status;
+   struct ata_task_resp *resp = (struct ata_task_resp *)ts->buf;
+   struct dev_to_host_fis *d2h = slot->status_buffer +
+ sizeof(struct hisi_sas_err_record);
+
+   resp->frame_len = sizeof(struct dev_to_host_fis);
+   memcpy(>ending_fis[0], d2h, sizeof(struct dev_to_host_fis));
+
+   ts->buf_valid_size = sizeof(*resp);
+}
 static int
 slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot,
int abort)
@@ -1070,6 +1089,11 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct 
hisi_sas_slot *slot,
case SAS_PROTOCOL_SATA:
case SAS_PROTOCOL_STP:
case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
+   {
+   ts->stat = SAM_STAT_GOOD;
+   sata_done_v2_hw(hisi_hba, task, slot);
+   break;
+   }
default:
ts->stat = SAM_STAT_CHECK_CONDITION;
break;
@@ -1094,6 +1118,143 @@ out:
return sts;
 }
 
+static u8 get_ata_protocol(u8 cmd, int direction)
+{
+   switch (cmd) {
+   case ATA_CMD_FPDMA_WRITE:
+   case ATA_CMD_FPDMA_READ:
+   return SATA_PROTOCOL_FPDMA;
+
+   case ATA_CMD_ID_ATA:
+   case ATA_CMD_PMP_READ:
+   case ATA_CMD_READ_LOG_EXT:
+   case ATA_CMD_PIO_READ:
+   case ATA_CMD_PIO_READ_EXT:
+   case ATA_CMD_PMP_WRITE:
+   case ATA_CMD_WRITE_LOG_EXT:
+   case ATA_CMD_PIO_WRITE:
+   case ATA_CMD_PIO_WRITE_EXT:
+   return SATA_PROTOCOL_PIO;
+
+   case 

[PATCH v2 15/23] hisi_sas: add v2 SATA interrupt handler

2016-01-25 Thread j00310691
From: John Garry 

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

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 5af2069..c4a887c 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -861,6 +861,86 @@ static irqreturn_t int_chnl_int_v2_hw(int irq_no, void *p)
return IRQ_HANDLED;
 }
 
+static irqreturn_t sata_int_v2_hw(int irq_no, void *p)
+{
+   struct hisi_sas_phy *phy = p;
+   struct hisi_hba *hisi_hba = phy->hisi_hba;
+   struct asd_sas_phy *sas_phy = >sas_phy;
+   struct device *dev = _hba->pdev->dev;
+   struct  hisi_sas_initial_fis *initial_fis;
+   struct dev_to_host_fis *fis;
+   u32 ent_tmp, ent_msk, ent_int, port_id, link_rate, hard_phy_linkrate;
+   irqreturn_t res = IRQ_HANDLED;
+   u8 attached_sas_addr[SAS_ADDR_SIZE] = {0};
+   int phy_no;
+
+   phy_no = sas_phy->id;
+   initial_fis = _hba->initial_fis[phy_no];
+   fis = _fis->fis;
+
+   ent_msk = hisi_sas_read32(hisi_hba, ENT_INT_SRC_MSK1);
+   hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, ent_msk | 1 << phy_no);
+
+   ent_int = hisi_sas_read32(hisi_hba, ENT_INT_SRC1);
+   ent_tmp = ent_int;
+   ent_int >>= ENT_INT_SRC1_D2H_FIS_CH1_OFF * (phy_no % 4);
+   if ((ent_int & ENT_INT_SRC1_D2H_FIS_CH0_MSK) == 0) {
+   dev_warn(dev, "sata int: phy%d did not receive FIS\n", phy_no);
+   hisi_sas_write32(hisi_hba, ENT_INT_SRC1, ent_tmp);
+   hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, ent_msk);
+   res = IRQ_NONE;
+   goto end;
+   }
+
+   if (unlikely(phy_no == 8)) {
+   u32 port_state = hisi_sas_read32(hisi_hba, PORT_STATE);
+
+   port_id = (port_state & PORT_STATE_PHY8_PORT_NUM_MSK) >>
+ PORT_STATE_PHY8_PORT_NUM_OFF;
+   link_rate = (port_state & PORT_STATE_PHY8_CONN_RATE_MSK) >>
+   PORT_STATE_PHY8_CONN_RATE_OFF;
+   } else {
+   port_id = hisi_sas_read32(hisi_hba, PHY_PORT_NUM_MA);
+   port_id = (port_id >> (4 * phy_no)) & 0xf;
+   link_rate = hisi_sas_read32(hisi_hba, PHY_CONN_RATE);
+   link_rate = (link_rate >> (phy_no * 4)) & 0xf;
+   }
+
+   if (port_id == 0xf) {
+   dev_err(dev, "sata int: phy%d invalid portid\n", phy_no);
+   res = IRQ_NONE;
+   goto end;
+   }
+
+   sas_phy->linkrate = link_rate;
+   hard_phy_linkrate = hisi_sas_phy_read32(hisi_hba, phy_no,
+   HARD_PHY_LINKRATE);
+   phy->maximum_linkrate = hard_phy_linkrate & 0xf;
+   phy->minimum_linkrate = (hard_phy_linkrate >> 4) & 0xf;
+
+   sas_phy->oob_mode = SATA_OOB_MODE;
+   /* Make up some unique SAS address */
+   attached_sas_addr[0] = 0x50;
+   attached_sas_addr[7] = phy_no;
+   memcpy(sas_phy->attached_sas_addr, attached_sas_addr, SAS_ADDR_SIZE);
+   memcpy(sas_phy->frame_rcvd, fis, sizeof(struct dev_to_host_fis));
+   dev_info(dev, "sata int phyup: phy%d link_rate=%d\n", phy_no, 
link_rate);
+   phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA);
+   phy->port_id = port_id;
+   phy->phy_type |= PORT_TYPE_SATA;
+   phy->phy_attached = 1;
+   phy->identify.device_type = SAS_SATA_DEV;
+   phy->frame_rcvd_size = sizeof(struct dev_to_host_fis);
+   phy->identify.target_port_protocols = SAS_PROTOCOL_SATA;
+   queue_work(hisi_hba->wq, >phyup_ws);
+
+end:
+   hisi_sas_write32(hisi_hba, ENT_INT_SRC1, ent_tmp);
+   hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, ent_msk);
+
+   return res;
+}
+
 static irq_handler_t phy_interrupts[HISI_SAS_PHY_INT_NR] = {
int_phy_updown_v2_hw,
int_chnl_int_v2_hw,
@@ -900,6 +980,26 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba)
}
}
 
+   for (i = 0; i < hisi_hba->n_phy; i++) {
+   struct hisi_sas_phy *phy = _hba->phy[i];
+   int idx = i + 72; /* First SATA interrupt is irq72 */
+
+   irq = irq_map[idx];
+   if (!irq) {
+   dev_err(dev, "irq init: fail map phy interrupt %d\n",
+   idx);
+   return -ENOENT;
+   }
+
+   rc = devm_request_irq(dev, irq, sata_int_v2_hw, 0,
+ DRV_NAME " sata", phy);
+   if (rc) {
+   dev_err(dev, "irq init: could not request "
+   "sata interrupt %d, rc=%d\n",
+   irq, rc);
+   return -ENOENT;
+   }
+   }
return 0;
 }
 
-- 
1.9.1

--
To unsubscribe from this list: 

[PATCH v2 16/23] hisi_sas: add v2 cq interrupt handler

2016-01-25 Thread j00310691
From: John Garry 

Also include slot_complete_v2_hw handler

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

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index c4a887c..099bc13 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -652,6 +652,106 @@ static int get_wideport_bitmap_v2_hw(struct hisi_hba 
*hisi_hba, int port_id)
return bitmap;
 }
 
+static int
+slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot,
+   int abort)
+{
+   struct sas_task *task = slot->task;
+   struct hisi_sas_device *sas_dev;
+   struct device *dev = _hba->pdev->dev;
+   struct task_status_struct *ts;
+   struct domain_device *device;
+   enum exec_status sts;
+   struct hisi_sas_complete_v2_hdr *complete_queue =
+   hisi_hba->complete_hdr[slot->cmplt_queue];
+   struct hisi_sas_complete_v2_hdr *complete_hdr =
+   _queue[slot->cmplt_queue_slot];
+
+   if (unlikely(!task || !task->lldd_task || !task->dev))
+   return -EINVAL;
+
+   ts = >task_status;
+   device = task->dev;
+   sas_dev = device->lldd_dev;
+
+   task->task_state_flags &=
+   ~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR);
+   task->task_state_flags |= SAS_TASK_STATE_DONE;
+
+   memset(ts, 0, sizeof(*ts));
+   ts->resp = SAS_TASK_COMPLETE;
+
+   if (unlikely(!sas_dev || abort)) {
+   if (!sas_dev)
+   dev_dbg(dev, "slot complete: port has not device\n");
+   ts->stat = SAS_PHY_DOWN;
+   goto out;
+   }
+
+   if ((complete_hdr->dw0 & CMPLT_HDR_ERX_MSK) &&
+   (!(complete_hdr->dw0 & CMPLT_HDR_RSPNS_XFRD_MSK))) {
+   dev_dbg(dev, "%s slot %d has error info 0x%x\n",
+   __func__, slot->cmplt_queue_slot,
+   complete_hdr->dw0 & CMPLT_HDR_ERX_MSK);
+
+   goto out;
+   }
+
+   switch (task->task_proto) {
+   case SAS_PROTOCOL_SSP:
+   {
+   struct ssp_response_iu *iu = slot->status_buffer +
+   sizeof(struct hisi_sas_err_record);
+
+   sas_ssp_task_response(dev, task, iu);
+   break;
+   }
+   case SAS_PROTOCOL_SMP:
+   {
+   struct scatterlist *sg_resp = >smp_task.smp_resp;
+   void *to;
+
+   ts->stat = SAM_STAT_GOOD;
+   to = kmap_atomic(sg_page(sg_resp));
+
+   dma_unmap_sg(dev, >smp_task.smp_resp, 1,
+DMA_FROM_DEVICE);
+   dma_unmap_sg(dev, >smp_task.smp_req, 1,
+DMA_TO_DEVICE);
+   memcpy(to + sg_resp->offset,
+  slot->status_buffer +
+  sizeof(struct hisi_sas_err_record),
+  sg_dma_len(sg_resp));
+   kunmap_atomic(to);
+   break;
+   }
+   case SAS_PROTOCOL_SATA:
+   case SAS_PROTOCOL_STP:
+   case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
+   default:
+   ts->stat = SAM_STAT_CHECK_CONDITION;
+   break;
+   }
+
+   if (!slot->port->port_attached) {
+   dev_err(dev, "slot complete: port %d has removed\n",
+   slot->port->sas_port.id);
+   ts->stat = SAS_PHY_DOWN;
+   }
+
+out:
+   if (sas_dev && sas_dev->running_req)
+   sas_dev->running_req--;
+
+   hisi_sas_slot_task_free(hisi_hba, task, slot);
+   sts = ts->stat;
+
+   if (task->task_done)
+   task->task_done(task);
+
+   return sts;
+}
+
 static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
 {
int i, res = 0;
@@ -861,6 +961,74 @@ static irqreturn_t int_chnl_int_v2_hw(int irq_no, void *p)
return IRQ_HANDLED;
 }
 
+static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p)
+{
+   struct hisi_sas_cq *cq = p;
+   struct hisi_hba *hisi_hba = cq->hisi_hba;
+   struct hisi_sas_slot *slot;
+   struct hisi_sas_itct *itct;
+   struct hisi_sas_complete_v2_hdr *complete_queue;
+   u32 irq_value, rd_point, wr_point, dev_id;
+   int queue = cq->id;
+
+   complete_queue = hisi_hba->complete_hdr[queue];
+   irq_value = hisi_sas_read32(hisi_hba, OQ_INT_SRC);
+
+   hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue);
+
+   rd_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_RD_PTR +
+  (0x14 * queue));
+   wr_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_WR_PTR +
+  (0x14 * queue));
+
+   while (rd_point != wr_point) {
+   struct hisi_sas_complete_v2_hdr *complete_hdr;
+   int iptt;
+

[PATCH v2 21/23] hisi_sas: add v2 slot error handler

2016-01-25 Thread j00310691
From: John Garry 

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

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index cea0b36..481aff9 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -256,12 +256,165 @@ struct hisi_sas_complete_v2_hdr {
__le32 dw3;
 };
 
+struct hisi_sas_err_record_v2 {
+   /* dw0 */
+   __le32 trans_tx_fail_type;
+
+   /* dw1 */
+   __le32 trans_rx_fail_type;
+
+   /* dw2 */
+   __le16 dma_tx_err_type;
+   __le16 sipc_rx_err_type;
+
+   /* dw3 */
+   __le32 dma_rx_err_type;
+};
+
 enum {
HISI_SAS_PHY_PHY_UPDOWN,
HISI_SAS_PHY_CHNL_INT,
HISI_SAS_PHY_INT_NR
 };
 
+enum {
+   TRANS_TX_FAIL_BASE = 0x0, /* dw0 */
+   TRANS_RX_FAIL_BASE = 0x100, /* dw1 */
+   DMA_TX_ERR_BASE = 0x200, /* dw2 bit 15-0 */
+   SIPC_RX_ERR_BASE = 0x300, /* dw2 bit 31-16*/
+   DMA_RX_ERR_BASE = 0x400, /* dw3 */
+
+   /* trans tx*/
+   TRANS_TX_OPEN_FAIL_WITH_IT_NEXUS_LOSS = TRANS_TX_FAIL_BASE, /* 0x0 */
+   TRANS_TX_ERR_PHY_NOT_ENABLE, /* 0x1 */
+   TRANS_TX_OPEN_CNX_ERR_WRONG_DESTINATION, /* 0x2 */
+   TRANS_TX_OPEN_CNX_ERR_ZONE_VIOLATION, /* 0x3 */
+   TRANS_TX_OPEN_CNX_ERR_BY_OTHER, /* 0x4 */
+   RESERVED0, /* 0x5 */
+   TRANS_TX_OPEN_CNX_ERR_AIP_TIMEOUT, /* 0x6 */
+   TRANS_TX_OPEN_CNX_ERR_STP_RESOURCES_BUSY, /* 0x7 */
+   TRANS_TX_OPEN_CNX_ERR_PROTOCOL_NOT_SUPPORTED, /* 0x8 */
+   TRANS_TX_OPEN_CNX_ERR_CONNECTION_RATE_NOT_SUPPORTED, /* 0x9 */
+   TRANS_TX_OPEN_CNX_ERR_BAD_DESTINATION, /* 0xa */
+   TRANS_TX_OPEN_CNX_ERR_BREAK_RCVD, /* 0xb */
+   TRANS_TX_OPEN_CNX_ERR_LOW_PHY_POWER, /* 0xc */
+   TRANS_TX_OPEN_CNX_ERR_PATHWAY_BLOCKED, /* 0xd */
+   TRANS_TX_OPEN_CNX_ERR_OPEN_TIMEOUT, /* 0xe */
+   TRANS_TX_OPEN_CNX_ERR_NO_DESTINATION, /* 0xf */
+   TRANS_TX_OPEN_RETRY_ERR_THRESHOLD_REACHED, /* 0x10 */
+   TRANS_TX_ERR_FRAME_TXED, /* 0x11 */
+   TRANS_TX_ERR_WITH_BREAK_TIMEOUT, /* 0x12 */
+   TRANS_TX_ERR_WITH_BREAK_REQUEST, /* 0x13 */
+   TRANS_TX_ERR_WITH_BREAK_RECEVIED, /* 0x14 */
+   TRANS_TX_ERR_WITH_CLOSE_TIMEOUT, /* 0x15 */
+   TRANS_TX_ERR_WITH_CLOSE_NORMAL, /* 0x16 for ssp*/
+   TRANS_TX_ERR_WITH_CLOSE_PHYDISALE, /* 0x17 */
+   TRANS_TX_ERR_WITH_CLOSE_DWS_TIMEOUT, /* 0x18 */
+   TRANS_TX_ERR_WITH_CLOSE_COMINIT, /* 0x19 */
+   TRANS_TX_ERR_WITH_NAK_RECEVIED, /* 0x1a for ssp*/
+   TRANS_TX_ERR_WITH_ACK_NAK_TIMEOUT, /* 0x1b for ssp*/
+   /*IO_TX_ERR_WITH_R_ERR_RECEVIED, [> 0x1b for sata/stp<] */
+   TRANS_TX_ERR_WITH_CREDIT_TIMEOUT, /* 0x1c for ssp */
+   /*IO_RX_ERR_WITH_SATA_DEVICE_LOST 0x1c for sata/stp */
+   TRANS_TX_ERR_WITH_IPTT_CONFLICT, /* 0x1d for ssp/smp */
+   TRANS_TX_ERR_WITH_OPEN_BY_DES_OR_OTHERS, /* 0x1e */
+   /*IO_TX_ERR_WITH_SYNC_RXD, [> 0x1e <] for sata/stp */
+   TRANS_TX_ERR_WITH_WAIT_RECV_TIMEOUT, /* 0x1f for sata/stp */
+
+   /* trans rx */
+   TRANS_RX_ERR_WITH_RXFRAME_CRC_ERR = TRANS_RX_FAIL_BASE, /* 0x100 */
+   TRANS_RX_ERR_WITH_RXFIS_8B10B_DISP_ERR, /* 0x101 for sata/stp */
+   TRANS_RX_ERR_WITH_RXFRAME_HAVE_ERRPRM, /* 0x102 for ssp/smp */
+   /*IO_ERR_WITH_RXFIS_8B10B_CODE_ERR, [> 0x102 <] for sata/stp */
+   TRANS_RX_ERR_WITH_RXFIS_DECODE_ERROR, /* 0x103 for sata/stp */
+   TRANS_RX_ERR_WITH_RXFIS_CRC_ERR, /* 0x104 for sata/stp */
+   TRANS_RX_ERR_WITH_RXFRAME_LENGTH_OVERRUN, /* 0x105 for smp */
+   /*IO_ERR_WITH_RXFIS_TX SYNCP, [> 0x105 <] for sata/stp */
+   TRANS_RX_ERR_WITH_RXFIS_RX_SYNCP, /* 0x106 for sata/stp*/
+   TRANS_RX_ERR_WITH_LINK_BUF_OVERRUN, /* 0x107 */
+   TRANS_RX_ERR_WITH_BREAK_TIMEOUT, /* 0x108 */
+   TRANS_RX_ERR_WITH_BREAK_REQUEST, /* 0x109 */
+   TRANS_RX_ERR_WITH_BREAK_RECEVIED, /* 0x10a */
+   RESERVED1, /* 0x10b */
+   TRANS_RX_ERR_WITH_CLOSE_NORMAL, /* 0x10c */
+   TRANS_RX_ERR_WITH_CLOSE_PHY_DISABLE, /* 0x10d */
+   TRANS_RX_ERR_WITH_CLOSE_DWS_TIMEOUT, /* 0x10e */
+   TRANS_RX_ERR_WITH_CLOSE_COMINIT, /* 0x10f */
+   TRANS_RX_ERR_WITH_DATA_LEN0, /* 0x110 for ssp/smp */
+   TRANS_RX_ERR_WITH_BAD_HASH, /* 0x111 for ssp */
+   /*IO_RX_ERR_WITH_FIS_TOO_SHORT, [> 0x111 <] for sata/stp */
+   TRANS_RX_XRDY_WLEN_ZERO_ERR, /* 0x112 for ssp*/
+   /*IO_RX_ERR_WITH_FIS_TOO_LONG, [> 0x112 <] for sata/stp */
+   TRANS_RX_SSP_FRM_LEN_ERR, /* 0x113 for ssp */
+   /*IO_RX_ERR_WITH_SATA_DEVICE_LOST, [> 0x113 <] for sata */
+   RESERVED2, /* 0x114 */
+   RESERVED3, /* 0x115 */
+   RESERVED4, /* 0x116 */
+   RESERVED5, /* 0x117 */
+   TRANS_RX_ERR_WITH_BAD_FRM_TYPE, /* 0x118 */
+   TRANS_RX_SMP_FRM_LEN_ERR, /* 0x119 */
+   TRANS_RX_SMP_RESP_TIMEOUT_ERR, /* 0x11a */
+   

[PATCH v2 11/23] hisi_sas: add v2 phy init code

2016-01-25 Thread j00310691
From: John Garry 

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

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 6f05333..1990d65 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -288,6 +288,15 @@ static u32 hisi_sas_phy_read32(struct hisi_hba *hisi_hba,
return readl(regs);
 }
 
+static void config_phy_opt_mode_v2_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_id_frame_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
 {
struct sas_identify_frame identify_frame;
@@ -563,6 +572,44 @@ static int hw_init_v2_hw(struct hisi_hba *hisi_hba)
return 0;
 }
 
+static void enable_phy_v2_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_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
+{
+   config_id_frame_v2_hw(hisi_hba, phy_no);
+   config_phy_opt_mode_v2_hw(hisi_hba, phy_no);
+   enable_phy_v2_hw(hisi_hba, phy_no);
+}
+
+static void start_phys_v2_hw(unsigned long data)
+{
+   struct hisi_hba *hisi_hba = (struct hisi_hba *)data;
+   int i;
+
+   for (i = 0; i < hisi_hba->n_phy; i++)
+   start_phy_v2_hw(hisi_hba, i);
+}
+
+static void phys_init_v2_hw(struct hisi_hba *hisi_hba)
+{
+   int i;
+   struct timer_list *timer = _hba->timer;
+
+   for (i = 0; i < hisi_hba->n_phy; i++) {
+   hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0x6a);
+   hisi_sas_phy_read32(hisi_hba, i, CHL_INT2_MSK);
+   }
+
+   setup_timer(timer, start_phys_v2_hw, (unsigned long)hisi_hba);
+   mod_timer(timer, jiffies + HZ);
+}
+
 static int hisi_sas_v2_init(struct hisi_hba *hisi_hba)
 {
int rc;
@@ -571,6 +618,8 @@ static int hisi_sas_v2_init(struct hisi_hba *hisi_hba)
if (rc)
return rc;
 
+   phys_init_v2_hw(hisi_hba);
+
return 0;
 }
 
-- 
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 v2 17/23] hisi_sas: add v2 path to send ssp frame

2016-01-25 Thread j00310691
From: John Garry 

Include code to prep ssp frame and deliver
to hardware.

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

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 099bc13..ab6ea25 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -264,6 +264,11 @@ enum {
 
 #define HISI_SAS_COMMAND_ENTRIES_V2_HW 4096
 
+#define DIR_NO_DATA 0
+#define DIR_TO_INI 1
+#define DIR_TO_DEVICE 2
+#define DIR_RESERVED 3
+
 static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off)
 {
void __iomem *regs = hisi_hba->regs + off;
@@ -271,6 +276,13 @@ static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 
off)
return readl(regs);
 }
 
+static u32 hisi_sas_read32_relaxed(struct hisi_hba *hisi_hba, u32 off)
+{
+   void __iomem *regs = hisi_hba->regs + off;
+
+   return readl_relaxed(regs);
+}
+
 static void hisi_sas_write32(struct hisi_hba *hisi_hba, u32 off, u32 val)
 {
void __iomem *regs = hisi_hba->regs + off;
@@ -652,6 +664,176 @@ static int get_wideport_bitmap_v2_hw(struct hisi_hba 
*hisi_hba, int port_id)
return bitmap;
 }
 
+/**
+ * This function allocates across all queues to load balance.
+ * Slots are allocated from queues in a round-robin fashion.
+ *
+ * The callpath to this function and upto writing the write
+ * queue pointer should be safe from interruption.
+ */
+static int get_free_slot_v2_hw(struct hisi_hba *hisi_hba, int *q, int *s)
+{
+   struct device *dev = _hba->pdev->dev;
+   u32 r, w;
+   int queue = hisi_hba->queue;
+
+   while (1) {
+   w = hisi_sas_read32_relaxed(hisi_hba,
+   DLVRY_Q_0_WR_PTR + (queue * 0x14));
+   r = hisi_sas_read32_relaxed(hisi_hba,
+   DLVRY_Q_0_RD_PTR + (queue * 0x14));
+   if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) {
+   queue = (queue + 1) % hisi_hba->queue_count;
+   if (queue == hisi_hba->queue) {
+   dev_warn(dev, "could not find free slot\n");
+   return -EAGAIN;
+   }
+   continue;
+   }
+   break;
+   }
+   hisi_hba->queue = (queue + 1) % hisi_hba->queue_count;
+   *q = queue;
+   *s = w;
+   return 0;
+}
+
+static void start_delivery_v2_hw(struct hisi_hba *hisi_hba)
+{
+   int dlvry_queue = hisi_hba->slot_prep->dlvry_queue;
+   int dlvry_queue_slot = hisi_hba->slot_prep->dlvry_queue_slot;
+
+   hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14),
+++dlvry_queue_slot % HISI_SAS_QUEUE_SLOTS);
+}
+
+static int prep_prd_sge_v2_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot,
+ struct hisi_sas_cmd_hdr *hdr,
+ struct scatterlist *scatter,
+ int n_elem)
+{
+   struct device *dev = _hba->pdev->dev;
+   struct scatterlist *sg;
+   int i;
+
+   if (n_elem > HISI_SAS_SGE_PAGE_CNT) {
+   dev_err(dev, "prd err: n_elem(%d) > HISI_SAS_SGE_PAGE_CNT",
+   n_elem);
+   return -EINVAL;
+   }
+
+   slot->sge_page = dma_pool_alloc(hisi_hba->sge_page_pool, GFP_ATOMIC,
+   >sge_page_dma);
+   if (!slot->sge_page)
+   return -ENOMEM;
+
+   for_each_sg(scatter, sg, n_elem, i) {
+   struct hisi_sas_sge *entry = >sge_page->sge[i];
+
+   entry->addr = cpu_to_le64(sg_dma_address(sg));
+   entry->page_ctrl_0 = entry->page_ctrl_1 = 0;
+   entry->data_len = cpu_to_le32(sg_dma_len(sg));
+   entry->data_off = 0;
+   }
+
+   hdr->prd_table_addr = cpu_to_le64(slot->sge_page_dma);
+
+   hdr->sg_len = cpu_to_le32(n_elem << CMD_HDR_DATA_SGL_LEN_OFF);
+
+   return 0;
+}
+
+static int prep_ssp_v2_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot, int is_tmf,
+ struct hisi_sas_tmf_task *tmf)
+{
+   struct sas_task *task = slot->task;
+   struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
+   struct domain_device *device = task->dev;
+   struct hisi_sas_device *sas_dev = device->lldd_dev;
+   struct hisi_sas_port *port = slot->port;
+   struct sas_ssp_task *ssp_task = >ssp_task;
+   struct scsi_cmnd *scsi_cmnd = ssp_task->cmd;
+   int has_data = 0, rc, priority = is_tmf;
+   u8 *buf_cmd;
+   u32 dw1 = 0, dw2 = 0;
+
+   hdr->dw0 = cpu_to_le32((1 << CMD_HDR_RESP_REPORT_OFF) |
+  (2 << CMD_HDR_TLR_CTRL_OFF) |
+  

[PATCH v2 00/23] HiSilicon SAS v2 hw support

2016-01-25 Thread j00310691
From: John Garry 

This patchset introduces support for the HiSi SAS v2 hw.
The major difference between v1 and v2 hw is support
for SATA/STP.

Known limitation:
- We cannot connect a SATA disk through an expander
  which enables DMA setup auto-activate, as our controller
  does not support this feature. Directly connecting
  a SATA disk to the HBA is ok.

Differences to v1:
- Update dt bindings, specificially for am-max-transmissions
- some small SATA fixes
- minor formatting changes

John Garry (23):
  devicetree: bindings: hisi_sas: add v2 HW bindings
  hisi_sas: relocate DEV_IS_EXPANDER
  hisi_sas: set max commands as configurable
  hisi_sas: reduce max itct entries
  hisi_sas: add hisi_sas_err_record_v1
  hisi_sas: rename some fields in hisi_sas_itct
  hisi_sas: add bare v2 hw driver
  hisi_sas: add v2 register definitions
  hisi_sas: add v2 hw init
  hisi_sas: add init_id_frame_v2_hw()
  hisi_sas: add v2 phy init code
  hisi_sas: add v2 int init and phy up handler
  hisi_sas: add v2 phy down handler
  hisi_sas: add v2 channel interrupt handler
  hisi_sas: add v2 SATA interrupt handler
  hisi_sas: add v2 cq interrupt handler
  hisi_sas: add v2 path to send ssp frame
  hisi_sas: add v2 code to send smp command
  hisi_sas: add v2 code for itct setup and free
  hisi_sas: add v2 path to send ATA command
  hisi_sas: add v2 slot error handler
  hisi_sas: add v2 tmf functions
  hisi_sas: update driver version to 1.1

 .../devicetree/bindings/scsi/hisilicon-sas.txt |   21 +-
 drivers/scsi/hisi_sas/Kconfig  |1 +
 drivers/scsi/hisi_sas/Makefile |2 +-
 drivers/scsi/hisi_sas/hisi_sas.h   |   39 +-
 drivers/scsi/hisi_sas/hisi_sas_main.c  |   36 +-
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c |   20 +-
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 2205 
 7 files changed, 2278 insertions(+), 46 deletions(-)
 create mode 100644 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c

Reviewed-by: Hannes Reinecke 
-- 
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 v2 01/23] devicetree: bindings: hisi_sas: add v2 HW bindings

2016-01-25 Thread j00310691
From: John Garry 

Add the dt bindings for HiSi SAS controller v2 HW.

The main difference in the controller from dt perspective
is interrupts. The v2 controller does not have dedicated
fatal and broadcast interrupts - they are multiplexed on
the channel interrupt.

Each SAS v2 controller can issue upto 64 commands
(or connection requests) on the system bus without waiting
for a response - this is know as am-max-transmissions.
In hip06, sas controller #1 has a limitation that it has to
limit am-max-transmissions to 32 - this limitation is due
to chip system bus design. It is not anticipated that any
future chip incorporating v2 controller will have such a
limitation.

Signed-off-by: John Garry 
---
 .../devicetree/bindings/scsi/hisilicon-sas.txt  | 21 -
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt 
b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
index f67e761..f3da463 100644
--- a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
+++ b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
@@ -5,6 +5,7 @@ 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
+   (b) "hisilicon,hip06-sas-v2" for v2 hw in hip06 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
@@ -13,7 +14,7 @@ Main node required properties:
   - 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
+  - interrupts : For v1 hw: Interrupts for phys, completion queues, and fatal
sources; the interrupts are ordered in 3 groups, as follows:
- Phy interrupts
- Completion queue interrupts
@@ -30,6 +31,24 @@ Main node required properties:
Fatal interrupts : the fatal interrupts are ordered as follows:
- ECC
- AXI bus
+   For v2 hw: Interrupts for phys, Sata, and completion queues;
+   the interrupts are ordered in 3 groups, as follows:
+   - Phy interrupts
+   - Sata interrupts
+   - Completion queue interrupts
+   Phy interrupts : Each controller has 2 phy interrupts:
+   - phy up/down
+   - channel interrupt
+   Sata interrupts : Each phy on the controller has 1 Sata
+   interrupt. The interrupts are ordered in increasing
+   order.
+   Completion queue interrupts : each completion queue has 1
+   interrupt source. The interrupts are ordered in
+   increasing order.
+
+Optional main node properties:
+ - hip06-sas-v2-quirk-amt : when set, indicates that the v2 controller has the
+   "am-max-transmissions" limitation.
 
 Example:
sas0: sas@c100 {
-- 
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 v2 12/23] hisi_sas: add v2 int init and phy up handler

2016-01-25 Thread j00310691
From: John Garry 

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

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 1990d65..a7b83bd 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -256,6 +256,11 @@ struct hisi_sas_complete_v2_hdr {
__le32 dw3;
 };
 
+enum {
+   HISI_SAS_PHY_PHY_UPDOWN,
+   HISI_SAS_PHY_INT_NR
+};
+
 #define HISI_SAS_COMMAND_ENTRIES_V2_HW 4096
 
 static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off)
@@ -610,6 +615,167 @@ static void phys_init_v2_hw(struct hisi_hba *hisi_hba)
mod_timer(timer, jiffies + HZ);
 }
 
+static void sl_notify_v2_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);
+}
+
+static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
+{
+   int i, res = 0;
+   u32 context, port_id, link_rate, hard_phy_linkrate;
+   struct hisi_sas_phy *phy = _hba->phy[phy_no];
+   struct asd_sas_phy *sas_phy = >sas_phy;
+   struct device *dev = _hba->pdev->dev;
+   u32 *frame_rcvd = (u32 *)sas_phy->frame_rcvd;
+   struct sas_identify_frame *id = (struct sas_identify_frame *)frame_rcvd;
+
+   hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 1);
+
+   /* Check for SATA dev */
+   context = hisi_sas_read32(hisi_hba, PHY_CONTEXT);
+   if (context & (1 << phy_no))
+   goto end;
+
+   if (phy_no == 8) {
+   u32 port_state = hisi_sas_read32(hisi_hba, PORT_STATE);
+
+   port_id = (port_state & PORT_STATE_PHY8_PORT_NUM_MSK) >>
+ PORT_STATE_PHY8_PORT_NUM_OFF;
+   link_rate = (port_state & PORT_STATE_PHY8_CONN_RATE_MSK) >>
+   PORT_STATE_PHY8_CONN_RATE_OFF;
+   } else {
+   port_id = hisi_sas_read32(hisi_hba, PHY_PORT_NUM_MA);
+   port_id = (port_id >> (4 * phy_no)) & 0xf;
+   link_rate = hisi_sas_read32(hisi_hba, PHY_CONN_RATE);
+   link_rate = (link_rate >> (phy_no * 4)) & 0xf;
+   }
+
+   if (port_id == 0xf) {
+   dev_err(dev, "phyup: phy%d invalid portid\n", phy_no);
+   res = IRQ_NONE;
+   goto end;
+   }
+
+   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 linkrates */
+   link_rate = hisi_sas_read32(hisi_hba, PHY_CONN_RATE);
+   link_rate = (link_rate >> (phy_no * 4)) & 0xf;
+   sas_phy->linkrate = link_rate;
+   hard_phy_linkrate = hisi_sas_phy_read32(hisi_hba, phy_no,
+   HARD_PHY_LINKRATE);
+   phy->maximum_linkrate = hard_phy_linkrate & 0xf;
+   phy->minimum_linkrate = (hard_phy_linkrate >> 4) & 0xf;
+
+   sas_phy->oob_mode = SAS_OOB_MODE;
+   memcpy(sas_phy->attached_sas_addr, >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;
+   queue_work(hisi_hba->wq, >phyup_ws);
+
+end:
+   hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
+CHL_INT0_SL_PHY_ENABLE_MSK);
+   hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 0);
+
+   return res;
+}
+
+static irqreturn_t int_phy_updown_v2_hw(int irq_no, void *p)
+{
+   struct hisi_hba *hisi_hba = p;
+   u32 irq_msk;
+   int phy_no = 0;
+   irqreturn_t res = IRQ_HANDLED;
+
+   irq_msk = (hisi_sas_read32(hisi_hba, HGC_INVLD_DQE_INFO)
+  >> HGC_INVLD_DQE_INFO_FB_CH0_OFF) & 0x1ff;
+   while (irq_msk) {
+   if (irq_msk  & 1) {
+   u32 irq_value = hisi_sas_phy_read32(hisi_hba, phy_no,
+  

[PATCH v2 22/23] hisi_sas: add v2 tmf functions

2016-01-25 Thread j00310691
From: John Garry 

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

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 481aff9..58e1956 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -847,6 +847,14 @@ static void enable_phy_v2_hw(struct hisi_hba *hisi_hba, 
int phy_no)
hisi_sas_phy_write32(hisi_hba, phy_no, PHY_CFG, cfg);
 }
 
+static void disable_phy_v2_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_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
 {
config_id_frame_v2_hw(hisi_hba, phy_no);
@@ -854,6 +862,18 @@ static void start_phy_v2_hw(struct hisi_hba *hisi_hba, int 
phy_no)
enable_phy_v2_hw(hisi_hba, phy_no);
 }
 
+static void stop_phy_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
+{
+   disable_phy_v2_hw(hisi_hba, phy_no);
+}
+
+static void phy_hard_reset_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
+{
+   stop_phy_v2_hw(hisi_hba, phy_no);
+   msleep(100);
+   start_phy_v2_hw(hisi_hba, phy_no);
+}
+
 static void start_phys_v2_hw(unsigned long data)
 {
struct hisi_hba *hisi_hba = (struct hisi_hba *)data;
@@ -2145,6 +2165,9 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = {
.get_free_slot = get_free_slot_v2_hw,
.start_delivery = start_delivery_v2_hw,
.slot_complete = slot_complete_v2_hw,
+   .phy_enable = enable_phy_v2_hw,
+   .phy_disable = disable_phy_v2_hw,
+   .phy_hard_reset = phy_hard_reset_v2_hw,
.max_command_entries = HISI_SAS_COMMAND_ENTRIES_V2_HW,
.complete_hdr_size = sizeof(struct hisi_sas_complete_v2_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 v2 05/23] hisi_sas: add hisi_sas_err_record_v1

2016-01-25 Thread j00310691
From: John Garry 

Since the error record structure is different for
v2 hw, make hisi_sas_err_record opaque and add
hisi_sas_err_record_v1.

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

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 7c05eb3..e5a58c5 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -270,17 +270,7 @@ struct hisi_sas_iost {
 };
 
 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;
+   u32 data[4];
 };
 
 struct hisi_sas_initial_fis {
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index 9bbcf6d..87a0622 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -288,6 +288,20 @@ struct hisi_sas_complete_v1_hdr {
__le32 data;
 };
 
+struct hisi_sas_err_record_v1 {
+   /* dw0 */
+   __le32 dma_err_type;
+
+   /* dw1 */
+   __le32 trans_tx_fail_type;
+
+   /* dw2 */
+   __le32 trans_rx_fail_type;
+
+   /* dw3 */
+   u32 rsvd;
+};
+
 enum {
HISI_SAS_PHY_BCAST_ACK = 0,
HISI_SAS_PHY_SL_PHY_ENABLED,
@@ -1098,7 +1112,7 @@ static void slot_err_v1_hw(struct hisi_hba *hisi_hba,
   struct hisi_sas_slot *slot)
 {
struct task_status_struct *ts = >task_status;
-   struct hisi_sas_err_record *err_record = slot->status_buffer;
+   struct hisi_sas_err_record_v1 *err_record = slot->status_buffer;
struct device *dev = _hba->pdev->dev;
 
switch (task->task_proto) {
@@ -1222,7 +1236,6 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba,
struct domain_device *device;
enum exec_status sts;
struct hisi_sas_complete_v1_hdr *complete_queue =
-   (struct hisi_sas_complete_v1_hdr *)
hisi_hba->complete_hdr[slot->cmplt_queue];
struct hisi_sas_complete_v1_hdr *complete_hdr;
u32 cmplt_hdr_data;
-- 
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 v2 06/23] hisi_sas: rename some fields in hisi_sas_itct

2016-01-25 Thread j00310691
From: John Garry 

Since hisi_sas_itct format is different between v1
and v2 hw, give more general names for some fields.

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h | 13 +
 1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index e5a58c5..b2e4b26 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -248,18 +248,7 @@ struct hisi_sas_itct {
__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;
+   __le64 qw4_15[12];
 };
 
 struct hisi_sas_iost {
-- 
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 v2 03/23] hisi_sas: set max commands as configurable

2016-01-25 Thread j00310691
From: John Garry 

Since v2 hardware permits different numbers of
commands to v1, set this as configurable in
hisi_sas_hw.

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |  2 +-
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 24 
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c |  3 +++
 3 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 21eb2bb..5ed5cf1 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -27,7 +27,6 @@
 #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)
@@ -144,6 +143,7 @@ struct hisi_sas_hw {
void (*free_device)(struct hisi_hba *hisi_hba,
struct hisi_sas_device *dev);
int (*get_wideport_bitmap)(struct hisi_hba *hisi_hba, int port_id);
+   int max_command_entries;
int complete_hdr_size;
 };
 
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 7689939..c48df6d 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -973,9 +973,9 @@ 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 = >dev;
+   int i, s, max_command_entries = hisi_hba->hw->max_command_entries;
 
spin_lock_init(_hba->lock);
for (i = 0; i < hisi_hba->n_phy; i++) {
@@ -1035,13 +1035,13 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, 
struct Scsi_Host *shost)
 
memset(hisi_hba->itct, 0, s);
 
-   hisi_hba->slot_info = devm_kcalloc(dev, HISI_SAS_COMMAND_ENTRIES,
+   hisi_hba->slot_info = devm_kcalloc(dev, max_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);
+   s = max_command_entries * sizeof(struct hisi_sas_iost);
hisi_hba->iost = dma_alloc_coherent(dev, s, _hba->iost_dma,
GFP_KERNEL);
if (!hisi_hba->iost)
@@ -1049,7 +1049,7 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, 
struct Scsi_Host *shost)
 
memset(hisi_hba->iost, 0, s);
 
-   s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_breakpoint);
+   s = max_command_entries * sizeof(struct hisi_sas_breakpoint);
hisi_hba->breakpoint = dma_alloc_coherent(dev, s,
_hba->breakpoint_dma, GFP_KERNEL);
if (!hisi_hba->breakpoint)
@@ -1057,7 +1057,7 @@ 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;
+   hisi_hba->slot_index_count = max_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)
@@ -1075,7 +1075,7 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, 
struct Scsi_Host *shost)
goto err_out;
memset(hisi_hba->initial_fis, 0, s);
 
-   s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_breakpoint) * 2;
+   s = max_command_entries * sizeof(struct hisi_sas_breakpoint) * 2;
hisi_hba->sata_breakpoint = dma_alloc_coherent(dev, s,
_hba->sata_breakpoint_dma, GFP_KERNEL);
if (!hisi_hba->sata_breakpoint)
@@ -1098,7 +1098,7 @@ err_out:
 static void hisi_sas_free(struct hisi_hba *hisi_hba)
 {
struct device *dev = _hba->pdev->dev;
-   int i, s;
+   int i, s, max_command_entries = hisi_hba->hw->max_command_entries;
 
for (i = 0; i < hisi_hba->queue_count; i++) {
s = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS;
@@ -1123,12 +1123,12 @@ static void hisi_sas_free(struct hisi_hba *hisi_hba)
dma_free_coherent(dev, s,
  hisi_hba->itct, hisi_hba->itct_dma);
 
-   s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_iost);
+   s = max_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);
+   s = max_command_entries * sizeof(struct hisi_sas_breakpoint);
if 

[RESEND PATCH v2 13/23] hisi_sas: add v2 phy down handler

2016-01-25 Thread John Garry
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 49 ++
 1 file changed, 49 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index a7b83bd..35ce7b6 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -628,6 +628,29 @@ static void sl_notify_v2_hw(struct hisi_hba *hisi_hba, int 
phy_no)
hisi_sas_phy_write32(hisi_hba, phy_no, SL_CONTROL, sl_control);
 }
 
+static int get_wideport_bitmap_v2_hw(struct hisi_hba *hisi_hba, int port_id)
+{
+   int i, bitmap = 0;
+   u32 phy_port_num_ma = hisi_sas_read32(hisi_hba, PHY_PORT_NUM_MA);
+   u32 phy_state = hisi_sas_read32(hisi_hba, PHY_STATE);
+
+   for (i = 0; i < (hisi_hba->n_phy < 9 ? hisi_hba->n_phy : 8); i++)
+   if (phy_state & 1 << i)
+   if (((phy_port_num_ma >> (i * 4)) & 0xf) == port_id)
+   bitmap |= 1 << i;
+
+   if (hisi_hba->n_phy == 9) {
+   u32 port_state = hisi_sas_read32(hisi_hba, PORT_STATE);
+
+   if (phy_state & 1 << 8)
+   if (((port_state & PORT_STATE_PHY8_PORT_NUM_MSK) >>
+PORT_STATE_PHY8_PORT_NUM_OFF) == port_id)
+   bitmap |= 1 << 9;
+   }
+
+   return bitmap;
+}
+
 static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
 {
int i, res = 0;
@@ -705,6 +728,25 @@ end:
return res;
 }
 
+static int phy_down_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
+{
+   int res = 0;
+   u32 phy_cfg, phy_state;
+
+   hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 1);
+
+   phy_cfg = hisi_sas_phy_read32(hisi_hba, phy_no, PHY_CFG);
+
+   phy_state = hisi_sas_read32(hisi_hba, PHY_STATE);
+
+   hisi_sas_phy_down(hisi_hba, phy_no, (phy_state & 1 << phy_no) ? 1 : 0);
+
+   hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0, CHL_INT0_NOT_RDY_MSK);
+   hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_NOT_RDY_MSK, 0);
+
+   return res;
+}
+
 static irqreturn_t int_phy_updown_v2_hw(int irq_no, void *p)
 {
struct hisi_hba *hisi_hba = p;
@@ -726,6 +768,12 @@ static irqreturn_t int_phy_updown_v2_hw(int irq_no, void 
*p)
goto end;
}
 
+   if (irq_value & CHL_INT0_NOT_RDY_MSK)
+   /* phy down */
+   if (phy_down_v2_hw(phy_no, hisi_hba)) {
+   res = IRQ_NONE;
+   goto end;
+   }
}
irq_msk >>= 1;
phy_no++;
@@ -796,6 +844,7 @@ static int hisi_sas_v2_init(struct hisi_hba *hisi_hba)
 static const struct hisi_sas_hw hisi_sas_v2_hw = {
.hw_init = hisi_sas_v2_init,
.sl_notify = sl_notify_v2_hw,
+   .get_wideport_bitmap = get_wideport_bitmap_v2_hw,
.max_command_entries = HISI_SAS_COMMAND_ENTRIES_V2_HW,
.complete_hdr_size = sizeof(struct hisi_sas_complete_v2_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


[RESEND PATCH v2 05/23] hisi_sas: add hisi_sas_err_record_v1

2016-01-25 Thread John Garry
Since the error record structure is different for
v2 hw, make hisi_sas_err_record opaque and add
hisi_sas_err_record_v1.

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

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 7c05eb3..e5a58c5 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -270,17 +270,7 @@ struct hisi_sas_iost {
 };
 
 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;
+   u32 data[4];
 };
 
 struct hisi_sas_initial_fis {
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index 9bbcf6d..87a0622 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -288,6 +288,20 @@ struct hisi_sas_complete_v1_hdr {
__le32 data;
 };
 
+struct hisi_sas_err_record_v1 {
+   /* dw0 */
+   __le32 dma_err_type;
+
+   /* dw1 */
+   __le32 trans_tx_fail_type;
+
+   /* dw2 */
+   __le32 trans_rx_fail_type;
+
+   /* dw3 */
+   u32 rsvd;
+};
+
 enum {
HISI_SAS_PHY_BCAST_ACK = 0,
HISI_SAS_PHY_SL_PHY_ENABLED,
@@ -1098,7 +1112,7 @@ static void slot_err_v1_hw(struct hisi_hba *hisi_hba,
   struct hisi_sas_slot *slot)
 {
struct task_status_struct *ts = >task_status;
-   struct hisi_sas_err_record *err_record = slot->status_buffer;
+   struct hisi_sas_err_record_v1 *err_record = slot->status_buffer;
struct device *dev = _hba->pdev->dev;
 
switch (task->task_proto) {
@@ -1222,7 +1236,6 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba,
struct domain_device *device;
enum exec_status sts;
struct hisi_sas_complete_v1_hdr *complete_queue =
-   (struct hisi_sas_complete_v1_hdr *)
hisi_hba->complete_hdr[slot->cmplt_queue];
struct hisi_sas_complete_v1_hdr *complete_hdr;
u32 cmplt_hdr_data;
-- 
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


[RESEND PATCH v2 16/23] hisi_sas: add v2 cq interrupt handler

2016-01-25 Thread John Garry
Also include slot_complete_v2_hw handler

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

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index c4a887c..099bc13 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -652,6 +652,106 @@ static int get_wideport_bitmap_v2_hw(struct hisi_hba 
*hisi_hba, int port_id)
return bitmap;
 }
 
+static int
+slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot,
+   int abort)
+{
+   struct sas_task *task = slot->task;
+   struct hisi_sas_device *sas_dev;
+   struct device *dev = _hba->pdev->dev;
+   struct task_status_struct *ts;
+   struct domain_device *device;
+   enum exec_status sts;
+   struct hisi_sas_complete_v2_hdr *complete_queue =
+   hisi_hba->complete_hdr[slot->cmplt_queue];
+   struct hisi_sas_complete_v2_hdr *complete_hdr =
+   _queue[slot->cmplt_queue_slot];
+
+   if (unlikely(!task || !task->lldd_task || !task->dev))
+   return -EINVAL;
+
+   ts = >task_status;
+   device = task->dev;
+   sas_dev = device->lldd_dev;
+
+   task->task_state_flags &=
+   ~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR);
+   task->task_state_flags |= SAS_TASK_STATE_DONE;
+
+   memset(ts, 0, sizeof(*ts));
+   ts->resp = SAS_TASK_COMPLETE;
+
+   if (unlikely(!sas_dev || abort)) {
+   if (!sas_dev)
+   dev_dbg(dev, "slot complete: port has not device\n");
+   ts->stat = SAS_PHY_DOWN;
+   goto out;
+   }
+
+   if ((complete_hdr->dw0 & CMPLT_HDR_ERX_MSK) &&
+   (!(complete_hdr->dw0 & CMPLT_HDR_RSPNS_XFRD_MSK))) {
+   dev_dbg(dev, "%s slot %d has error info 0x%x\n",
+   __func__, slot->cmplt_queue_slot,
+   complete_hdr->dw0 & CMPLT_HDR_ERX_MSK);
+
+   goto out;
+   }
+
+   switch (task->task_proto) {
+   case SAS_PROTOCOL_SSP:
+   {
+   struct ssp_response_iu *iu = slot->status_buffer +
+   sizeof(struct hisi_sas_err_record);
+
+   sas_ssp_task_response(dev, task, iu);
+   break;
+   }
+   case SAS_PROTOCOL_SMP:
+   {
+   struct scatterlist *sg_resp = >smp_task.smp_resp;
+   void *to;
+
+   ts->stat = SAM_STAT_GOOD;
+   to = kmap_atomic(sg_page(sg_resp));
+
+   dma_unmap_sg(dev, >smp_task.smp_resp, 1,
+DMA_FROM_DEVICE);
+   dma_unmap_sg(dev, >smp_task.smp_req, 1,
+DMA_TO_DEVICE);
+   memcpy(to + sg_resp->offset,
+  slot->status_buffer +
+  sizeof(struct hisi_sas_err_record),
+  sg_dma_len(sg_resp));
+   kunmap_atomic(to);
+   break;
+   }
+   case SAS_PROTOCOL_SATA:
+   case SAS_PROTOCOL_STP:
+   case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
+   default:
+   ts->stat = SAM_STAT_CHECK_CONDITION;
+   break;
+   }
+
+   if (!slot->port->port_attached) {
+   dev_err(dev, "slot complete: port %d has removed\n",
+   slot->port->sas_port.id);
+   ts->stat = SAS_PHY_DOWN;
+   }
+
+out:
+   if (sas_dev && sas_dev->running_req)
+   sas_dev->running_req--;
+
+   hisi_sas_slot_task_free(hisi_hba, task, slot);
+   sts = ts->stat;
+
+   if (task->task_done)
+   task->task_done(task);
+
+   return sts;
+}
+
 static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
 {
int i, res = 0;
@@ -861,6 +961,74 @@ static irqreturn_t int_chnl_int_v2_hw(int irq_no, void *p)
return IRQ_HANDLED;
 }
 
+static irqreturn_t cq_interrupt_v2_hw(int irq_no, void *p)
+{
+   struct hisi_sas_cq *cq = p;
+   struct hisi_hba *hisi_hba = cq->hisi_hba;
+   struct hisi_sas_slot *slot;
+   struct hisi_sas_itct *itct;
+   struct hisi_sas_complete_v2_hdr *complete_queue;
+   u32 irq_value, rd_point, wr_point, dev_id;
+   int queue = cq->id;
+
+   complete_queue = hisi_hba->complete_hdr[queue];
+   irq_value = hisi_sas_read32(hisi_hba, OQ_INT_SRC);
+
+   hisi_sas_write32(hisi_hba, OQ_INT_SRC, 1 << queue);
+
+   rd_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_RD_PTR +
+  (0x14 * queue));
+   wr_point = hisi_sas_read32(hisi_hba, COMPL_Q_0_WR_PTR +
+  (0x14 * queue));
+
+   while (rd_point != wr_point) {
+   struct hisi_sas_complete_v2_hdr *complete_hdr;
+   int iptt;
+
+   complete_hdr = 

[RESEND PATCH v2 18/23] hisi_sas: add v2 code to send smp command

2016-01-25 Thread John Garry
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 71 ++
 1 file changed, 71 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index ab6ea25..2c6a753 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -744,6 +744,76 @@ static int prep_prd_sge_v2_hw(struct hisi_hba *hisi_hba,
return 0;
 }
 
+static int prep_smp_v2_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 = _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 = >smp_task.smp_req;
+   elem = dma_map_sg(dev, sg_req, 1, DMA_TO_DEVICE);
+   if (!elem)
+   return -ENOMEM;
+   req_len = sg_dma_len(sg_req);
+   req_dma_addr = sg_dma_address(sg_req);
+
+   /* resp */
+   sg_resp = >smp_task.smp_resp;
+   elem = dma_map_sg(dev, sg_resp, 1, DMA_FROM_DEVICE);
+   if (!elem) {
+   rc = -ENOMEM;
+   goto err_out_req;
+   }
+   resp_len = sg_dma_len(sg_resp);
+   if ((req_len & 0x3) || (resp_len & 0x3)) {
+   rc = -EINVAL;
+   goto err_out_resp;
+   }
+
+   /* create header */
+   /* dw0 */
+   hdr->dw0 = cpu_to_le32((port->id << CMD_HDR_PORT_OFF) |
+  (1 << CMD_HDR_PRIORITY_OFF) | /* high pri */
+  (2 << CMD_HDR_CMD_OFF)); /* smp */
+
+   /* map itct entry */
+   hdr->dw1 = cpu_to_le32((sas_dev->device_id << CMD_HDR_DEV_ID_OFF) |
+  (1 << CMD_HDR_FRAME_TYPE_OFF) |
+  (DIR_NO_DATA << CMD_HDR_DIR_OFF));
+
+   /* dw2 */
+   hdr->dw2 = cpu_to_le32req_len - 4) / 4) << CMD_HDR_CFL_OFF) |
+  (HISI_SAS_MAX_SMP_RESP_SZ / 4 <<
+  CMD_HDR_MRFL_OFF));
+
+   hdr->transfer_tags = cpu_to_le32(slot->idx << CMD_HDR_IPTT_OFF);
+
+   hdr->cmd_table_addr = cpu_to_le64(req_dma_addr);
+   hdr->sts_buffer_addr = cpu_to_le64(slot->status_buffer_dma);
+
+   return 0;
+
+err_out_resp:
+   dma_unmap_sg(dev, >task->smp_task.smp_resp, 1,
+DMA_FROM_DEVICE);
+err_out_req:
+   dma_unmap_sg(dev, >task->smp_task.smp_req, 1,
+DMA_TO_DEVICE);
+   return rc;
+}
+
 static int prep_ssp_v2_hw(struct hisi_hba *hisi_hba,
  struct hisi_sas_slot *slot, int is_tmf,
  struct hisi_sas_tmf_task *tmf)
@@ -1395,6 +1465,7 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = {
.hw_init = hisi_sas_v2_init,
.sl_notify = sl_notify_v2_hw,
.get_wideport_bitmap = get_wideport_bitmap_v2_hw,
+   .prep_smp = prep_smp_v2_hw,
.prep_ssp = prep_ssp_v2_hw,
.get_free_slot = get_free_slot_v2_hw,
.start_delivery = start_delivery_v2_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


[RESEND PATCH v2 03/23] hisi_sas: set max commands as configurable

2016-01-25 Thread John Garry
Since v2 hardware permits different numbers of
commands to v1, set this as configurable in
hisi_sas_hw.

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |  2 +-
 drivers/scsi/hisi_sas/hisi_sas_main.c  | 24 
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c |  3 +++
 3 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 21eb2bb..5ed5cf1 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -27,7 +27,6 @@
 #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)
@@ -144,6 +143,7 @@ struct hisi_sas_hw {
void (*free_device)(struct hisi_hba *hisi_hba,
struct hisi_sas_device *dev);
int (*get_wideport_bitmap)(struct hisi_hba *hisi_hba, int port_id);
+   int max_command_entries;
int complete_hdr_size;
 };
 
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 7689939..c48df6d 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -973,9 +973,9 @@ 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 = >dev;
+   int i, s, max_command_entries = hisi_hba->hw->max_command_entries;
 
spin_lock_init(_hba->lock);
for (i = 0; i < hisi_hba->n_phy; i++) {
@@ -1035,13 +1035,13 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, 
struct Scsi_Host *shost)
 
memset(hisi_hba->itct, 0, s);
 
-   hisi_hba->slot_info = devm_kcalloc(dev, HISI_SAS_COMMAND_ENTRIES,
+   hisi_hba->slot_info = devm_kcalloc(dev, max_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);
+   s = max_command_entries * sizeof(struct hisi_sas_iost);
hisi_hba->iost = dma_alloc_coherent(dev, s, _hba->iost_dma,
GFP_KERNEL);
if (!hisi_hba->iost)
@@ -1049,7 +1049,7 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, 
struct Scsi_Host *shost)
 
memset(hisi_hba->iost, 0, s);
 
-   s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_breakpoint);
+   s = max_command_entries * sizeof(struct hisi_sas_breakpoint);
hisi_hba->breakpoint = dma_alloc_coherent(dev, s,
_hba->breakpoint_dma, GFP_KERNEL);
if (!hisi_hba->breakpoint)
@@ -1057,7 +1057,7 @@ 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;
+   hisi_hba->slot_index_count = max_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)
@@ -1075,7 +1075,7 @@ static int hisi_sas_alloc(struct hisi_hba *hisi_hba, 
struct Scsi_Host *shost)
goto err_out;
memset(hisi_hba->initial_fis, 0, s);
 
-   s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_breakpoint) * 2;
+   s = max_command_entries * sizeof(struct hisi_sas_breakpoint) * 2;
hisi_hba->sata_breakpoint = dma_alloc_coherent(dev, s,
_hba->sata_breakpoint_dma, GFP_KERNEL);
if (!hisi_hba->sata_breakpoint)
@@ -1098,7 +1098,7 @@ err_out:
 static void hisi_sas_free(struct hisi_hba *hisi_hba)
 {
struct device *dev = _hba->pdev->dev;
-   int i, s;
+   int i, s, max_command_entries = hisi_hba->hw->max_command_entries;
 
for (i = 0; i < hisi_hba->queue_count; i++) {
s = sizeof(struct hisi_sas_cmd_hdr) * HISI_SAS_QUEUE_SLOTS;
@@ -1123,12 +1123,12 @@ static void hisi_sas_free(struct hisi_hba *hisi_hba)
dma_free_coherent(dev, s,
  hisi_hba->itct, hisi_hba->itct_dma);
 
-   s = HISI_SAS_COMMAND_ENTRIES * sizeof(struct hisi_sas_iost);
+   s = max_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);
+   s = max_command_entries * sizeof(struct hisi_sas_breakpoint);
if (hisi_hba->breakpoint)

[RESEND PATCH v2 20/23] hisi_sas: add v2 path to send ATA command

2016-01-25 Thread John Garry
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h   |   4 +
 drivers/scsi/hisi_sas/hisi_sas_main.c  |   8 ++
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 162 +
 3 files changed, 174 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index b2e4b26..f00b55b 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #define DRV_VERSION "v1.0"
@@ -35,6 +36,7 @@
 
 #define HISI_SAS_MAX_SSP_RESP_SZ (sizeof(struct ssp_frame_hdr) + 1024)
 #define HISI_SAS_MAX_SMP_RESP_SZ 1028
+#define HISI_SAS_MAX_STP_RESP_SZ 28
 
 #define DEV_IS_EXPANDER(type) \
((type == SAS_EDGE_EXPANDER_DEVICE) || \
@@ -135,6 +137,8 @@ struct hisi_sas_hw {
struct hisi_sas_tmf_task *tmf);
int (*prep_smp)(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot);
+   int (*prep_stp)(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 (*phy_enable)(struct hisi_hba *hisi_hba, int phy_no);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index c48df6d..406b515 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -107,6 +107,12 @@ static int hisi_sas_task_prep_ssp(struct hisi_hba 
*hisi_hba,
return hisi_hba->hw->prep_ssp(hisi_hba, slot, is_tmf, tmf);
 }
 
+static int hisi_sas_task_prep_ata(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot)
+{
+   return hisi_hba->hw->prep_stp(hisi_hba, slot);
+}
+
 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)
@@ -230,6 +236,8 @@ static int hisi_sas_task_prep(struct sas_task *task, struct 
hisi_hba *hisi_hba,
case SAS_PROTOCOL_SATA:
case SAS_PROTOCOL_STP:
case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
+   rc = hisi_sas_task_prep_ata(hisi_hba, slot);
+   break;
default:
dev_err(dev, "task prep: unknown/unsupported proto (0x%x)\n",
task->task_proto);
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 8b51acf..cea0b36 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -269,6 +269,12 @@ enum {
 #define DIR_TO_DEVICE 2
 #define DIR_RESERVED 3
 
+#define SATA_PROTOCOL_NONDATA  0x1
+#define SATA_PROTOCOL_PIO  0x2
+#define SATA_PROTOCOL_DMA  0x4
+#define SATA_PROTOCOL_FPDMA0x8
+#define SATA_PROTOCOL_ATAPI0x10
+
 static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off)
 {
void __iomem *regs = hisi_hba->regs + off;
@@ -994,6 +1000,19 @@ static int prep_ssp_v2_hw(struct hisi_hba *hisi_hba,
return 0;
 }
 
+static void sata_done_v2_hw(struct hisi_hba *hisi_hba, struct sas_task *task,
+   struct hisi_sas_slot *slot)
+{
+   struct task_status_struct *ts = >task_status;
+   struct ata_task_resp *resp = (struct ata_task_resp *)ts->buf;
+   struct dev_to_host_fis *d2h = slot->status_buffer +
+ sizeof(struct hisi_sas_err_record);
+
+   resp->frame_len = sizeof(struct dev_to_host_fis);
+   memcpy(>ending_fis[0], d2h, sizeof(struct dev_to_host_fis));
+
+   ts->buf_valid_size = sizeof(*resp);
+}
 static int
 slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct hisi_sas_slot *slot,
int abort)
@@ -1070,6 +1089,11 @@ slot_complete_v2_hw(struct hisi_hba *hisi_hba, struct 
hisi_sas_slot *slot,
case SAS_PROTOCOL_SATA:
case SAS_PROTOCOL_STP:
case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
+   {
+   ts->stat = SAM_STAT_GOOD;
+   sata_done_v2_hw(hisi_hba, task, slot);
+   break;
+   }
default:
ts->stat = SAM_STAT_CHECK_CONDITION;
break;
@@ -1094,6 +1118,143 @@ out:
return sts;
 }
 
+static u8 get_ata_protocol(u8 cmd, int direction)
+{
+   switch (cmd) {
+   case ATA_CMD_FPDMA_WRITE:
+   case ATA_CMD_FPDMA_READ:
+   return SATA_PROTOCOL_FPDMA;
+
+   case ATA_CMD_ID_ATA:
+   case ATA_CMD_PMP_READ:
+   case ATA_CMD_READ_LOG_EXT:
+   case ATA_CMD_PIO_READ:
+   case ATA_CMD_PIO_READ_EXT:
+   case ATA_CMD_PMP_WRITE:
+   case ATA_CMD_WRITE_LOG_EXT:
+   case ATA_CMD_PIO_WRITE:
+   case ATA_CMD_PIO_WRITE_EXT:
+   return SATA_PROTOCOL_PIO;
+
+   case ATA_CMD_READ:
+   case ATA_CMD_READ_EXT:
+  

[PATCH v3] mptlan: add checks for dma mapping errors

2016-01-25 Thread Alexey Khoroshilov
mpt_lan_sdu_send() and mpt_lan_post_receive_buckets() do not check
if mapping dma memory succeed.
The patch adds the checks and failure handling.

v3: Fix resource deallocation (reported by Tomas Henzl).

Found by Linux Driver Verification project (linuxtesting.org).

Signed-off-by: Alexey Khoroshilov 
---
 drivers/message/fusion/mptlan.c | 16 
 1 file changed, 16 insertions(+)

diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c
index cbe96072a6cc..e9b83fc7be35 100644
--- a/drivers/message/fusion/mptlan.c
+++ b/drivers/message/fusion/mptlan.c
@@ -734,6 +734,13 @@ mpt_lan_sdu_send (struct sk_buff *skb, struct net_device 
*dev)
 
 dma = pci_map_single(mpt_dev->pcidev, skb->data, skb->len,
 PCI_DMA_TODEVICE);
+   if (pci_dma_mapping_error(mpt_dev->pcidev, dma)) {
+   mpt_put_msg_frame(LanCtx, mpt_dev, mf);
+   netif_stop_queue(dev);
+
+   printk (KERN_ERR "%s: dma mapping failed\n", __func__);
+   return NETDEV_TX_BUSY;
+   }
 
priv->SendCtl[ctx].skb = skb;
priv->SendCtl[ctx].dma = dma;
@@ -1232,6 +1239,15 @@ mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv)
 
dma = pci_map_single(mpt_dev->pcidev, skb->data,
 len, PCI_DMA_FROMDEVICE);
+   if (pci_dma_mapping_error(mpt_dev->pcidev, 
dma)) {
+   printk (KERN_WARNING
+   MYNAM "/%s: dma mapping 
failed\n",
+   __func__);
+   dev_kfree_skb(skb);
+   
priv->mpt_rxfidx[++priv->mpt_rxfidx_tail] = ctx;
+   
spin_unlock_irqrestore(>rxfidx_lock, flags);
+   break;
+   }
 
priv->RcvCtl[ctx].skb = skb;
priv->RcvCtl[ctx].dma = dma;
-- 
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


[RESEND PATCH v2 06/23] hisi_sas: rename some fields in hisi_sas_itct

2016-01-25 Thread John Garry
Since hisi_sas_itct format is different between v1
and v2 hw, give more general names for some fields.

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h | 13 +
 1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index e5a58c5..b2e4b26 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -248,18 +248,7 @@ struct hisi_sas_itct {
__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;
+   __le64 qw4_15[12];
 };
 
 struct hisi_sas_iost {
-- 
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


[RESEND PATCH v2 21/23] hisi_sas: add v2 slot error handler

2016-01-25 Thread John Garry
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 421 +
 1 file changed, 421 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index cea0b36..481aff9 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -256,12 +256,165 @@ struct hisi_sas_complete_v2_hdr {
__le32 dw3;
 };
 
+struct hisi_sas_err_record_v2 {
+   /* dw0 */
+   __le32 trans_tx_fail_type;
+
+   /* dw1 */
+   __le32 trans_rx_fail_type;
+
+   /* dw2 */
+   __le16 dma_tx_err_type;
+   __le16 sipc_rx_err_type;
+
+   /* dw3 */
+   __le32 dma_rx_err_type;
+};
+
 enum {
HISI_SAS_PHY_PHY_UPDOWN,
HISI_SAS_PHY_CHNL_INT,
HISI_SAS_PHY_INT_NR
 };
 
+enum {
+   TRANS_TX_FAIL_BASE = 0x0, /* dw0 */
+   TRANS_RX_FAIL_BASE = 0x100, /* dw1 */
+   DMA_TX_ERR_BASE = 0x200, /* dw2 bit 15-0 */
+   SIPC_RX_ERR_BASE = 0x300, /* dw2 bit 31-16*/
+   DMA_RX_ERR_BASE = 0x400, /* dw3 */
+
+   /* trans tx*/
+   TRANS_TX_OPEN_FAIL_WITH_IT_NEXUS_LOSS = TRANS_TX_FAIL_BASE, /* 0x0 */
+   TRANS_TX_ERR_PHY_NOT_ENABLE, /* 0x1 */
+   TRANS_TX_OPEN_CNX_ERR_WRONG_DESTINATION, /* 0x2 */
+   TRANS_TX_OPEN_CNX_ERR_ZONE_VIOLATION, /* 0x3 */
+   TRANS_TX_OPEN_CNX_ERR_BY_OTHER, /* 0x4 */
+   RESERVED0, /* 0x5 */
+   TRANS_TX_OPEN_CNX_ERR_AIP_TIMEOUT, /* 0x6 */
+   TRANS_TX_OPEN_CNX_ERR_STP_RESOURCES_BUSY, /* 0x7 */
+   TRANS_TX_OPEN_CNX_ERR_PROTOCOL_NOT_SUPPORTED, /* 0x8 */
+   TRANS_TX_OPEN_CNX_ERR_CONNECTION_RATE_NOT_SUPPORTED, /* 0x9 */
+   TRANS_TX_OPEN_CNX_ERR_BAD_DESTINATION, /* 0xa */
+   TRANS_TX_OPEN_CNX_ERR_BREAK_RCVD, /* 0xb */
+   TRANS_TX_OPEN_CNX_ERR_LOW_PHY_POWER, /* 0xc */
+   TRANS_TX_OPEN_CNX_ERR_PATHWAY_BLOCKED, /* 0xd */
+   TRANS_TX_OPEN_CNX_ERR_OPEN_TIMEOUT, /* 0xe */
+   TRANS_TX_OPEN_CNX_ERR_NO_DESTINATION, /* 0xf */
+   TRANS_TX_OPEN_RETRY_ERR_THRESHOLD_REACHED, /* 0x10 */
+   TRANS_TX_ERR_FRAME_TXED, /* 0x11 */
+   TRANS_TX_ERR_WITH_BREAK_TIMEOUT, /* 0x12 */
+   TRANS_TX_ERR_WITH_BREAK_REQUEST, /* 0x13 */
+   TRANS_TX_ERR_WITH_BREAK_RECEVIED, /* 0x14 */
+   TRANS_TX_ERR_WITH_CLOSE_TIMEOUT, /* 0x15 */
+   TRANS_TX_ERR_WITH_CLOSE_NORMAL, /* 0x16 for ssp*/
+   TRANS_TX_ERR_WITH_CLOSE_PHYDISALE, /* 0x17 */
+   TRANS_TX_ERR_WITH_CLOSE_DWS_TIMEOUT, /* 0x18 */
+   TRANS_TX_ERR_WITH_CLOSE_COMINIT, /* 0x19 */
+   TRANS_TX_ERR_WITH_NAK_RECEVIED, /* 0x1a for ssp*/
+   TRANS_TX_ERR_WITH_ACK_NAK_TIMEOUT, /* 0x1b for ssp*/
+   /*IO_TX_ERR_WITH_R_ERR_RECEVIED, [> 0x1b for sata/stp<] */
+   TRANS_TX_ERR_WITH_CREDIT_TIMEOUT, /* 0x1c for ssp */
+   /*IO_RX_ERR_WITH_SATA_DEVICE_LOST 0x1c for sata/stp */
+   TRANS_TX_ERR_WITH_IPTT_CONFLICT, /* 0x1d for ssp/smp */
+   TRANS_TX_ERR_WITH_OPEN_BY_DES_OR_OTHERS, /* 0x1e */
+   /*IO_TX_ERR_WITH_SYNC_RXD, [> 0x1e <] for sata/stp */
+   TRANS_TX_ERR_WITH_WAIT_RECV_TIMEOUT, /* 0x1f for sata/stp */
+
+   /* trans rx */
+   TRANS_RX_ERR_WITH_RXFRAME_CRC_ERR = TRANS_RX_FAIL_BASE, /* 0x100 */
+   TRANS_RX_ERR_WITH_RXFIS_8B10B_DISP_ERR, /* 0x101 for sata/stp */
+   TRANS_RX_ERR_WITH_RXFRAME_HAVE_ERRPRM, /* 0x102 for ssp/smp */
+   /*IO_ERR_WITH_RXFIS_8B10B_CODE_ERR, [> 0x102 <] for sata/stp */
+   TRANS_RX_ERR_WITH_RXFIS_DECODE_ERROR, /* 0x103 for sata/stp */
+   TRANS_RX_ERR_WITH_RXFIS_CRC_ERR, /* 0x104 for sata/stp */
+   TRANS_RX_ERR_WITH_RXFRAME_LENGTH_OVERRUN, /* 0x105 for smp */
+   /*IO_ERR_WITH_RXFIS_TX SYNCP, [> 0x105 <] for sata/stp */
+   TRANS_RX_ERR_WITH_RXFIS_RX_SYNCP, /* 0x106 for sata/stp*/
+   TRANS_RX_ERR_WITH_LINK_BUF_OVERRUN, /* 0x107 */
+   TRANS_RX_ERR_WITH_BREAK_TIMEOUT, /* 0x108 */
+   TRANS_RX_ERR_WITH_BREAK_REQUEST, /* 0x109 */
+   TRANS_RX_ERR_WITH_BREAK_RECEVIED, /* 0x10a */
+   RESERVED1, /* 0x10b */
+   TRANS_RX_ERR_WITH_CLOSE_NORMAL, /* 0x10c */
+   TRANS_RX_ERR_WITH_CLOSE_PHY_DISABLE, /* 0x10d */
+   TRANS_RX_ERR_WITH_CLOSE_DWS_TIMEOUT, /* 0x10e */
+   TRANS_RX_ERR_WITH_CLOSE_COMINIT, /* 0x10f */
+   TRANS_RX_ERR_WITH_DATA_LEN0, /* 0x110 for ssp/smp */
+   TRANS_RX_ERR_WITH_BAD_HASH, /* 0x111 for ssp */
+   /*IO_RX_ERR_WITH_FIS_TOO_SHORT, [> 0x111 <] for sata/stp */
+   TRANS_RX_XRDY_WLEN_ZERO_ERR, /* 0x112 for ssp*/
+   /*IO_RX_ERR_WITH_FIS_TOO_LONG, [> 0x112 <] for sata/stp */
+   TRANS_RX_SSP_FRM_LEN_ERR, /* 0x113 for ssp */
+   /*IO_RX_ERR_WITH_SATA_DEVICE_LOST, [> 0x113 <] for sata */
+   RESERVED2, /* 0x114 */
+   RESERVED3, /* 0x115 */
+   RESERVED4, /* 0x116 */
+   RESERVED5, /* 0x117 */
+   TRANS_RX_ERR_WITH_BAD_FRM_TYPE, /* 0x118 */
+   TRANS_RX_SMP_FRM_LEN_ERR, /* 0x119 */
+   TRANS_RX_SMP_RESP_TIMEOUT_ERR, /* 0x11a */
+   RESERVED6, /* 0x11b */
+   RESERVED7, 

[RESEND PATCH v2 11/23] hisi_sas: add v2 phy init code

2016-01-25 Thread John Garry
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 49 ++
 1 file changed, 49 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 6f05333..1990d65 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -288,6 +288,15 @@ static u32 hisi_sas_phy_read32(struct hisi_hba *hisi_hba,
return readl(regs);
 }
 
+static void config_phy_opt_mode_v2_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_id_frame_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
 {
struct sas_identify_frame identify_frame;
@@ -563,6 +572,44 @@ static int hw_init_v2_hw(struct hisi_hba *hisi_hba)
return 0;
 }
 
+static void enable_phy_v2_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_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
+{
+   config_id_frame_v2_hw(hisi_hba, phy_no);
+   config_phy_opt_mode_v2_hw(hisi_hba, phy_no);
+   enable_phy_v2_hw(hisi_hba, phy_no);
+}
+
+static void start_phys_v2_hw(unsigned long data)
+{
+   struct hisi_hba *hisi_hba = (struct hisi_hba *)data;
+   int i;
+
+   for (i = 0; i < hisi_hba->n_phy; i++)
+   start_phy_v2_hw(hisi_hba, i);
+}
+
+static void phys_init_v2_hw(struct hisi_hba *hisi_hba)
+{
+   int i;
+   struct timer_list *timer = _hba->timer;
+
+   for (i = 0; i < hisi_hba->n_phy; i++) {
+   hisi_sas_phy_write32(hisi_hba, i, CHL_INT2_MSK, 0x6a);
+   hisi_sas_phy_read32(hisi_hba, i, CHL_INT2_MSK);
+   }
+
+   setup_timer(timer, start_phys_v2_hw, (unsigned long)hisi_hba);
+   mod_timer(timer, jiffies + HZ);
+}
+
 static int hisi_sas_v2_init(struct hisi_hba *hisi_hba)
 {
int rc;
@@ -571,6 +618,8 @@ static int hisi_sas_v2_init(struct hisi_hba *hisi_hba)
if (rc)
return rc;
 
+   phys_init_v2_hw(hisi_hba);
+
return 0;
 }
 
-- 
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


[RESEND PATCH v2 10/23] hisi_sas: add init_id_frame_v2_hw()

2016-01-25 Thread John Garry
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 40 ++
 1 file changed, 40 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index da9c375..6f05333 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -288,6 +288,44 @@ static u32 hisi_sas_phy_read32(struct hisi_hba *hisi_hba,
return readl(regs);
 }
 
+static void config_id_frame_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
+{
+   struct sas_identify_frame identify_frame;
+   u32 *identify_buffer;
+
+   memset(_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(_frame._un4_11[0], hisi_hba->sas_addr, SAS_ADDR_SIZE);
+   memcpy(_frame.sas_addr[0], hisi_hba->sas_addr, SAS_ADDR_SIZE);
+   identify_frame.phy_id = phy_no;
+   identify_buffer = (u32 *)(_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_v2_hw(struct hisi_hba *hisi_hba)
+{
+   int i;
+
+   for (i = 0; i < hisi_hba->n_phy; i++)
+   config_id_frame_v2_hw(hisi_hba, i);
+}
+
 static int reset_hw_v2_hw(struct hisi_hba *hisi_hba)
 {
int i, reset_val;
@@ -520,6 +558,8 @@ static int hw_init_v2_hw(struct hisi_hba *hisi_hba)
msleep(100);
init_reg_v2_hw(hisi_hba);
 
+   init_id_frame_v2_hw(hisi_hba);
+
return 0;
 }
 
-- 
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


[RESEND PATCH v2 04/23] hisi_sas: reduce max itct entries

2016-01-25 Thread John Garry
Since v2 hw only supports 2048 itct entries,
as opposed to 4096 for v1 hw, set the max itct
entries to the lower of the two.

It is not anticipated that any device with v1
will ever require to connect > 2048 devices.

Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 5ed5cf1..7c05eb3 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -25,7 +25,7 @@
 #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_ITCT_ENTRIES 2048
 #define HISI_SAS_MAX_DEVICES HISI_SAS_MAX_ITCT_ENTRIES
 
 #define HISI_SAS_STATUS_BUF_SZ \
-- 
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


[RESEND PATCH v2 02/23] hisi_sas: relocate DEV_IS_EXPANDER

2016-01-25 Thread John Garry
Relocate DEV_IS_EXPANDER to hisi_sas.h as
it will be required for v2 hw support.

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

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 5af2e41..21eb2bb 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -37,6 +37,10 @@
 #define HISI_SAS_MAX_SSP_RESP_SZ (sizeof(struct ssp_frame_hdr) + 1024)
 #define HISI_SAS_MAX_SMP_RESP_SZ 1028
 
+#define DEV_IS_EXPANDER(type) \
+   ((type == SAS_EDGE_EXPANDER_DEVICE) || \
+   (type == SAS_FANOUT_EXPANDER_DEVICE))
+
 struct hisi_hba;
 
 enum {
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 99b1950..7689939 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -12,10 +12,6 @@
 #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))
 
-- 
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


[RESEND PATCH v2 12/23] hisi_sas: add v2 int init and phy up handler

2016-01-25 Thread John Garry
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 171 +
 1 file changed, 171 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 1990d65..a7b83bd 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -256,6 +256,11 @@ struct hisi_sas_complete_v2_hdr {
__le32 dw3;
 };
 
+enum {
+   HISI_SAS_PHY_PHY_UPDOWN,
+   HISI_SAS_PHY_INT_NR
+};
+
 #define HISI_SAS_COMMAND_ENTRIES_V2_HW 4096
 
 static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off)
@@ -610,6 +615,167 @@ static void phys_init_v2_hw(struct hisi_hba *hisi_hba)
mod_timer(timer, jiffies + HZ);
 }
 
+static void sl_notify_v2_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);
+}
+
+static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
+{
+   int i, res = 0;
+   u32 context, port_id, link_rate, hard_phy_linkrate;
+   struct hisi_sas_phy *phy = _hba->phy[phy_no];
+   struct asd_sas_phy *sas_phy = >sas_phy;
+   struct device *dev = _hba->pdev->dev;
+   u32 *frame_rcvd = (u32 *)sas_phy->frame_rcvd;
+   struct sas_identify_frame *id = (struct sas_identify_frame *)frame_rcvd;
+
+   hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 1);
+
+   /* Check for SATA dev */
+   context = hisi_sas_read32(hisi_hba, PHY_CONTEXT);
+   if (context & (1 << phy_no))
+   goto end;
+
+   if (phy_no == 8) {
+   u32 port_state = hisi_sas_read32(hisi_hba, PORT_STATE);
+
+   port_id = (port_state & PORT_STATE_PHY8_PORT_NUM_MSK) >>
+ PORT_STATE_PHY8_PORT_NUM_OFF;
+   link_rate = (port_state & PORT_STATE_PHY8_CONN_RATE_MSK) >>
+   PORT_STATE_PHY8_CONN_RATE_OFF;
+   } else {
+   port_id = hisi_sas_read32(hisi_hba, PHY_PORT_NUM_MA);
+   port_id = (port_id >> (4 * phy_no)) & 0xf;
+   link_rate = hisi_sas_read32(hisi_hba, PHY_CONN_RATE);
+   link_rate = (link_rate >> (phy_no * 4)) & 0xf;
+   }
+
+   if (port_id == 0xf) {
+   dev_err(dev, "phyup: phy%d invalid portid\n", phy_no);
+   res = IRQ_NONE;
+   goto end;
+   }
+
+   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 linkrates */
+   link_rate = hisi_sas_read32(hisi_hba, PHY_CONN_RATE);
+   link_rate = (link_rate >> (phy_no * 4)) & 0xf;
+   sas_phy->linkrate = link_rate;
+   hard_phy_linkrate = hisi_sas_phy_read32(hisi_hba, phy_no,
+   HARD_PHY_LINKRATE);
+   phy->maximum_linkrate = hard_phy_linkrate & 0xf;
+   phy->minimum_linkrate = (hard_phy_linkrate >> 4) & 0xf;
+
+   sas_phy->oob_mode = SAS_OOB_MODE;
+   memcpy(sas_phy->attached_sas_addr, >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;
+   queue_work(hisi_hba->wq, >phyup_ws);
+
+end:
+   hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
+CHL_INT0_SL_PHY_ENABLE_MSK);
+   hisi_sas_phy_write32(hisi_hba, phy_no, PHYCTRL_PHY_ENA_MSK, 0);
+
+   return res;
+}
+
+static irqreturn_t int_phy_updown_v2_hw(int irq_no, void *p)
+{
+   struct hisi_hba *hisi_hba = p;
+   u32 irq_msk;
+   int phy_no = 0;
+   irqreturn_t res = IRQ_HANDLED;
+
+   irq_msk = (hisi_sas_read32(hisi_hba, HGC_INVLD_DQE_INFO)
+  >> HGC_INVLD_DQE_INFO_FB_CH0_OFF) & 0x1ff;
+   while (irq_msk) {
+   if (irq_msk  & 1) {
+   u32 irq_value = hisi_sas_phy_read32(hisi_hba, phy_no,
+

[RESEND PATCH v2 08/23] hisi_sas: add v2 register definitions

2016-01-25 Thread John Garry
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 237 +
 1 file changed, 237 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 0f7f2af..31e4fdc 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -12,6 +12,243 @@
 #include "hisi_sas.h"
 #define DRV_NAME "hisi_sas_v2_hw"
 
+/* global registers need init*/
+#define DLVRY_QUEUE_ENABLE 0x0
+#define IOST_BASE_ADDR_LO  0x8
+#define IOST_BASE_ADDR_HI  0xc
+#define ITCT_BASE_ADDR_LO  0x10
+#define ITCT_BASE_ADDR_HI  0x14
+#define IO_BROKEN_MSG_ADDR_LO  0x18
+#define IO_BROKEN_MSG_ADDR_HI  0x1c
+#define PHY_CONTEXT0x20
+#define PHY_STATE  0x24
+#define PHY_PORT_NUM_MA0x28
+#define PORT_STATE 0x2c
+#define PORT_STATE_PHY8_PORT_NUM_OFF   16
+#define PORT_STATE_PHY8_PORT_NUM_MSK   (0xf << PORT_STATE_PHY8_PORT_NUM_OFF)
+#define PORT_STATE_PHY8_CONN_RATE_OFF  20
+#define PORT_STATE_PHY8_CONN_RATE_MSK  (0xf << PORT_STATE_PHY8_CONN_RATE_OFF)
+#define PHY_CONN_RATE  0x30
+#define HGC_TRANS_TASK_CNT_LIMIT   0x38
+#define AXI_AHB_CLK_CFG0x3c
+#define ITCT_CLR   0x44
+#define ITCT_CLR_EN_OFF16
+#define ITCT_CLR_EN_MSK(0x1 << ITCT_CLR_EN_OFF)
+#define ITCT_DEV_OFF   0
+#define ITCT_DEV_MSK   (0x7ff << ITCT_DEV_OFF)
+#define AXI_USER1  0x48
+#define AXI_USER2  0x4c
+#define IO_SATA_BROKEN_MSG_ADDR_LO 0x58
+#define IO_SATA_BROKEN_MSG_ADDR_HI 0x5c
+#define SATA_INITI_D2H_STORE_ADDR_LO   0x60
+#define SATA_INITI_D2H_STORE_ADDR_HI   0x64
+#define HGC_SAS_TX_OPEN_FAIL_RETRY_CTRL0x84
+#define HGC_SAS_TXFAIL_RETRY_CTRL  0x88
+#define HGC_GET_ITV_TIME   0x90
+#define DEVICE_MSG_WORK_MODE   0x94
+#define OPENA_WT_CONTI_TIME0x9c
+#define I_T_NEXUS_LOSS_TIME0xa0
+#define MAX_CON_TIME_LIMIT_TIME0xa4
+#define BUS_INACTIVE_LIMIT_TIME0xa8
+#define REJECT_TO_OPEN_LIMIT_TIME  0xac
+#define CFG_AGING_TIME 0xbc
+#define HGC_DFX_CFG2   0xc0
+#define HGC_IOMB_PROC1_STATUS  0x104
+#define CFG_1US_TIMER_TRSH 0xcc
+#define HGC_INVLD_DQE_INFO 0x148
+#define HGC_INVLD_DQE_INFO_FB_CH0_OFF  9
+#define HGC_INVLD_DQE_INFO_FB_CH0_MSK  (0x1 << HGC_INVLD_DQE_INFO_FB_CH0_OFF)
+#define HGC_INVLD_DQE_INFO_FB_CH3_OFF  18
+#define INT_COAL_EN0x19c
+#define OQ_INT_COAL_TIME   0x1a0
+#define OQ_INT_COAL_CNT0x1a4
+#define ENT_INT_COAL_TIME  0x1a8
+#define ENT_INT_COAL_CNT   0x1ac
+#define OQ_INT_SRC 0x1b0
+#define OQ_INT_SRC_MSK 0x1b4
+#define ENT_INT_SRC1   0x1b8
+#define ENT_INT_SRC1_D2H_FIS_CH0_OFF   0
+#define ENT_INT_SRC1_D2H_FIS_CH0_MSK   (0x1 << ENT_INT_SRC1_D2H_FIS_CH0_OFF)
+#define ENT_INT_SRC1_D2H_FIS_CH1_OFF   8
+#define ENT_INT_SRC1_D2H_FIS_CH1_MSK   (0x1 << ENT_INT_SRC1_D2H_FIS_CH1_OFF)
+#define ENT_INT_SRC2   0x1bc
+#define ENT_INT_SRC3   0x1c0
+#define ENT_INT_SRC3_ITC_INT_OFF   15
+#define ENT_INT_SRC3_ITC_INT_MSK   (0x1 << ENT_INT_SRC3_ITC_INT_OFF)
+#define ENT_INT_SRC_MSK1   0x1c4
+#define ENT_INT_SRC_MSK2   0x1c8
+#define ENT_INT_SRC_MSK3   0x1cc
+#define ENT_INT_SRC_MSK3_ENT95_MSK_OFF 31
+#define ENT_INT_SRC_MSK3_ENT95_MSK_MSK (0x1 << ENT_INT_SRC_MSK3_ENT95_MSK_OFF)
+#define SAS_ECC_INTR_MSK   0x1ec
+#define HGC_ERR_STAT_EN0x238
+#define DLVRY_Q_0_BASE_ADDR_LO 0x260
+#define DLVRY_Q_0_BASE_ADDR_HI 0x264
+#define DLVRY_Q_0_DEPTH0x268
+#define DLVRY_Q_0_WR_PTR   0x26c
+#define DLVRY_Q_0_RD_PTR   0x270
+#define HYPER_STREAM_ID_EN_CFG 0xc80
+#define OQ0_INT_SRC_MSK0xc90
+#define COMPL_Q_0_BASE_ADDR_LO 0x4e0
+#define COMPL_Q_0_BASE_ADDR_HI 0x4e4
+#define COMPL_Q_0_DEPTH0x4e8
+#define COMPL_Q_0_WR_PTR   0x4ec
+#define COMPL_Q_0_RD_PTR   0x4f0
+
+/* phy registers need init */
+#define PORT_BASE  (0x2000)
+
+#define PHY_CFG(PORT_BASE + 0x0)
+#define HARD_PHY_LINKRATE  (PORT_BASE + 0x4)
+#define PHY_CFG_ENA_OFF0
+#define PHY_CFG_ENA_MSK(0x1 << PHY_CFG_ENA_OFF)
+#define PHY_CFG_DC_OPT_OFF 2
+#define PHY_CFG_DC_OPT_MSK (0x1 << PHY_CFG_DC_OPT_OFF)
+#define PROG_PHY_LINK_RATE (PORT_BASE + 

[RESEND PATCH v2 01/23] devicetree: bindings: hisi_sas: add v2 HW bindings

2016-01-25 Thread John Garry
Add the dt bindings for HiSi SAS controller v2 HW.

The main difference in the controller from dt perspective
is interrupts. The v2 controller does not have dedicated
fatal and broadcast interrupts - they are multiplexed on
the channel interrupt.

Each SAS v2 controller can issue upto 64 commands
(or connection requests) on the system bus without waiting
for a response - this is know as am-max-transmissions.
In hip06, sas controller #1 has a limitation that it has to
limit am-max-transmissions to 32 - this limitation is due
to chip system bus design. It is not anticipated that any
future chip incorporating v2 controller will have such a
limitation.

Signed-off-by: John Garry 
---
 .../devicetree/bindings/scsi/hisilicon-sas.txt  | 21 -
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt 
b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
index f67e761..f3da463 100644
--- a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
+++ b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt
@@ -5,6 +5,7 @@ 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
+   (b) "hisilicon,hip06-sas-v2" for v2 hw in hip06 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
@@ -13,7 +14,7 @@ Main node required properties:
   - 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
+  - interrupts : For v1 hw: Interrupts for phys, completion queues, and fatal
sources; the interrupts are ordered in 3 groups, as follows:
- Phy interrupts
- Completion queue interrupts
@@ -30,6 +31,24 @@ Main node required properties:
Fatal interrupts : the fatal interrupts are ordered as follows:
- ECC
- AXI bus
+   For v2 hw: Interrupts for phys, Sata, and completion queues;
+   the interrupts are ordered in 3 groups, as follows:
+   - Phy interrupts
+   - Sata interrupts
+   - Completion queue interrupts
+   Phy interrupts : Each controller has 2 phy interrupts:
+   - phy up/down
+   - channel interrupt
+   Sata interrupts : Each phy on the controller has 1 Sata
+   interrupt. The interrupts are ordered in increasing
+   order.
+   Completion queue interrupts : each completion queue has 1
+   interrupt source. The interrupts are ordered in
+   increasing order.
+
+Optional main node properties:
+ - hip06-sas-v2-quirk-amt : when set, indicates that the v2 controller has the
+   "am-max-transmissions" limitation.
 
 Example:
sas0: sas@c100 {
-- 
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


[RESEND PATCH v2 14/23] hisi_sas: add v2 channel interrupt handler

2016-01-25 Thread John Garry
This also includes broadcast handler. Unlike v1 hw,
broadcast does not have its own dedicated interrupt.

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

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 35ce7b6..5af2069 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -258,6 +258,7 @@ struct hisi_sas_complete_v2_hdr {
 
 enum {
HISI_SAS_PHY_PHY_UPDOWN,
+   HISI_SAS_PHY_CHNL_INT,
HISI_SAS_PHY_INT_NR
 };
 
@@ -783,8 +784,86 @@ end:
return res;
 }
 
+static void phy_bcast_v2_hw(int phy_no, struct hisi_hba *hisi_hba)
+{
+   struct hisi_sas_phy *phy = _hba->phy[phy_no];
+   struct asd_sas_phy *sas_phy = >sas_phy;
+   struct sas_ha_struct *sas_ha = _hba->sha;
+   unsigned long flags;
+
+   hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 1);
+
+   spin_lock_irqsave(_hba->lock, flags);
+   sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
+   spin_unlock_irqrestore(_hba->lock, flags);
+
+   hisi_sas_phy_write32(hisi_hba, phy_no, CHL_INT0,
+CHL_INT0_SL_RX_BCST_ACK_MSK);
+   hisi_sas_phy_write32(hisi_hba, phy_no, SL_RX_BCAST_CHK_MSK, 0);
+}
+
+static irqreturn_t int_chnl_int_v2_hw(int irq_no, void *p)
+{
+   struct hisi_hba *hisi_hba = p;
+   struct device *dev = _hba->pdev->dev;
+   u32 ent_msk, ent_tmp, irq_msk;
+   int phy_no = 0;
+
+   ent_msk = hisi_sas_read32(hisi_hba, ENT_INT_SRC_MSK3);
+   ent_tmp = ent_msk;
+   ent_msk |= ENT_INT_SRC_MSK3_ENT95_MSK_MSK;
+   hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, ent_msk);
+
+   irq_msk = (hisi_sas_read32(hisi_hba, HGC_INVLD_DQE_INFO) >>
+   HGC_INVLD_DQE_INFO_FB_CH3_OFF) & 0x1ff;
+
+   while (irq_msk) {
+   if (irq_msk & (1 << phy_no)) {
+   u32 irq_value0 = hisi_sas_phy_read32(hisi_hba, phy_no,
+CHL_INT0);
+   u32 irq_value1 = hisi_sas_phy_read32(hisi_hba, phy_no,
+CHL_INT1);
+   u32 irq_value2 = hisi_sas_phy_read32(hisi_hba, phy_no,
+CHL_INT2);
+
+   if (irq_value1) {
+   if (irq_value1 & (CHL_INT1_DMAC_RX_ECC_ERR_MSK |
+ CHL_INT1_DMAC_TX_ECC_ERR_MSK))
+   panic("%s: DMAC RX/TX ecc bad error! 
(0x%x)",
+   dev_name(dev), irq_value1);
+
+   hisi_sas_phy_write32(hisi_hba, phy_no,
+CHL_INT1, irq_value1);
+   }
+
+   if (irq_value2)
+   hisi_sas_phy_write32(hisi_hba, phy_no,
+CHL_INT2, irq_value2);
+
+
+   if (irq_value0) {
+   if (irq_value0 & CHL_INT0_SL_RX_BCST_ACK_MSK)
+   phy_bcast_v2_hw(phy_no, hisi_hba);
+
+   hisi_sas_phy_write32(hisi_hba, phy_no,
+   CHL_INT0, irq_value0
+   & (~CHL_INT0_HOTPLUG_TOUT_MSK)
+   & (~CHL_INT0_SL_PHY_ENABLE_MSK)
+   & (~CHL_INT0_NOT_RDY_MSK));
+   }
+   }
+   irq_msk &= ~(1 << phy_no);
+   phy_no++;
+   }
+
+   hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK3, ent_tmp);
+
+   return IRQ_HANDLED;
+}
+
 static irq_handler_t phy_interrupts[HISI_SAS_PHY_INT_NR] = {
int_phy_updown_v2_hw,
+   int_chnl_int_v2_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


[RESEND PATCH v2 23/23] hisi_sas: update driver version to 1.1

2016-01-25 Thread John Garry
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index f00b55b..9f08c0c 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -21,7 +21,7 @@
 #include 
 #include 
 
-#define DRV_VERSION "v1.0"
+#define DRV_VERSION "v1.1"
 
 #define HISI_SAS_MAX_PHYS  9
 #define HISI_SAS_MAX_QUEUES32
-- 
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


[RESEND PATCH v2 00/23] HiSilicon SAS v2 hw support

2016-01-25 Thread John Garry
This patchset introduces support for the HiSi SAS v2 hw.
The major difference between v1 and v2 hw is support
for SATA/STP.

Known limitation:
- We cannot connect a SATA disk through an expander
  which enables DMA setup auto-activate, as our controller
  does not support this feature. Directly connecting
  a SATA disk to the HBA is ok.

Differences to v1:
- Update dt bindings, specificially for am-max-transmissions
- some small SATA fixes
- minor formatting changes

John Garry (23):
  devicetree: bindings: hisi_sas: add v2 HW bindings
  hisi_sas: relocate DEV_IS_EXPANDER
  hisi_sas: set max commands as configurable
  hisi_sas: reduce max itct entries
  hisi_sas: add hisi_sas_err_record_v1
  hisi_sas: rename some fields in hisi_sas_itct
  hisi_sas: add bare v2 hw driver
  hisi_sas: add v2 register definitions
  hisi_sas: add v2 hw init
  hisi_sas: add init_id_frame_v2_hw()
  hisi_sas: add v2 phy init code
  hisi_sas: add v2 int init and phy up handler
  hisi_sas: add v2 phy down handler
  hisi_sas: add v2 channel interrupt handler
  hisi_sas: add v2 SATA interrupt handler
  hisi_sas: add v2 cq interrupt handler
  hisi_sas: add v2 path to send ssp frame
  hisi_sas: add v2 code to send smp command
  hisi_sas: add v2 code for itct setup and free
  hisi_sas: add v2 path to send ATA command
  hisi_sas: add v2 slot error handler
  hisi_sas: add v2 tmf functions
  hisi_sas: update driver version to 1.1

 .../devicetree/bindings/scsi/hisilicon-sas.txt |   21 +-
 drivers/scsi/hisi_sas/Makefile |2 +-
 drivers/scsi/hisi_sas/hisi_sas.h   |   39 +-
 drivers/scsi/hisi_sas/hisi_sas_main.c  |   36 +-
 drivers/scsi/hisi_sas/hisi_sas_v1_hw.c |   20 +-
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 2205 
 6 files changed, 2277 insertions(+), 46 deletions(-)
 create mode 100644 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c

Reviewed-by: Hannes Reinecke 
-- 
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: [Y2038] [PATCH, RESEND 2] qla2xxx: Remove use of 'struct timeval'

2016-01-25 Thread Himanshu Madhani
Hi Arnd, 



On 1/22/16, 7:12 AM, "linux-scsi-ow...@vger.kernel.org on behalf of Arnd
Bergmann" 
wrote:

>On Friday 22 January 2016 15:28:32 Arnd Bergmann wrote:
>> struct register_host_info stores a 64-bit UTC system time timestamp.
>> This patch removes the use of 'struct timeval' to obtain that timestamp
>> as its tv_sec value will overflow on 32-bit systems in year 2038 beyond.
>> The patch uses ktime_get_real_seconds() which returns a 64-bit seconds
>>value.
>> 
>> Signed-off-by: Tina Ruchandani 
>> Reviewed-by: Johannes Thumshirn 
>> Signed-off-by: Arnd Bergmann 
>> 
>
>
>
>I was missing
>
>From: Tina Ruchandani 
>
>If anyone is going to pick this up, let me know whether you will fix
>it up yourself or if I should resend.

Please resend the patch and add Acked-by: Himanshu Madhani


>--
>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

Thanks,
- Himanshu

<>

Re: [PATCH v4 34/78] atari_NCR5380: Use arbitration timeout

2016-01-25 Thread Andreas Schwab
Geert Uytterhoeven  writes:

> Alternatively, we need to fix ARAnyM, or can make the creation of the
> atari_scsi platform device conditional on not running under ARAnyM.

Given the ncr5380 emulation in ARAnyM is just a stub, making it less a
stub would be preferred.

Andreas.

-- 
Andreas Schwab, sch...@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."
--
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


[RESEND PATCH v2 09/23] hisi_sas: add v2 hw init

2016-01-25 Thread John Garry
Add code to initialise the hardware.

Support is also added to deal with the
"am-max-transmissions" (amt) limitation in hip06
controller #1. This is how many connection requests
we can send on the system bus before waiting for a
response.
Due to chip bus design, controller #1 is limited to
32 amt, while, by design, a controller supports 64.
The default value for the nibbles in the relevant
registers is 0x40; these need to be programmed with
0x20.

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

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 31e4fdc..da9c375 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -249,7 +249,295 @@
 #define ITCT_HDR_RTOLT_OFF 48
 #define ITCT_HDR_RTOLT_MSK (0xULL << ITCT_HDR_RTOLT_OFF)
 
+struct hisi_sas_complete_v2_hdr {
+   __le32 dw0;
+   __le32 dw1;
+   __le32 act;
+   __le32 dw3;
+};
+
+#define HISI_SAS_COMMAND_ENTRIES_V2_HW 4096
+
+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 int reset_hw_v2_hw(struct hisi_hba *hisi_hba)
+{
+   int i, reset_val;
+   u32 val;
+   unsigned long end_time;
+   struct device *dev = _hba->pdev->dev;
+
+   /* The mask needs to be set depending on the number of phys */
+   if (hisi_hba->n_phy == 9)
+   reset_val = 0x1f;
+   else
+   reset_val = 0x7;
+
+   /* Disable all of the DQ */
+   for (i = 0; i < HISI_SAS_MAX_QUEUES; i++)
+   hisi_sas_write32(hisi_hba, DLVRY_QUEUE_ENABLE, 0);
+
+   /* Disable all of the PHYs */
+   for (i = 0; i < hisi_hba->n_phy; i++) {
+   u32 phy_cfg = hisi_sas_phy_read32(hisi_hba, i, PHY_CFG);
+
+   phy_cfg &= ~PHY_CTRL_RESET_MSK;
+   hisi_sas_phy_write32(hisi_hba, i, PHY_CFG, phy_cfg);
+   }
+   udelay(50);
+
+   /* Ensure DMA tx & rx idle */
+   for (i = 0; i < hisi_hba->n_phy; i++) {
+   u32 dma_tx_status, dma_rx_status;
+
+   end_time = jiffies + msecs_to_jiffies(1000);
+
+   while (1) {
+   dma_tx_status = hisi_sas_phy_read32(hisi_hba, i,
+   DMA_TX_STATUS);
+   dma_rx_status = hisi_sas_phy_read32(hisi_hba, i,
+   DMA_RX_STATUS);
+
+   if (!(dma_tx_status & DMA_TX_STATUS_BUSY_MSK) &&
+   !(dma_rx_status & DMA_RX_STATUS_BUSY_MSK))
+   break;
+
+   msleep(20);
+   if (time_after(jiffies, end_time))
+   return -EIO;
+   }
+   }
+
+   /* Ensure axi bus idle */
+   end_time = jiffies + msecs_to_jiffies(1000);
+   while (1) {
+   u32 axi_status =
+   hisi_sas_read32(hisi_hba, AXI_CFG);
+
+   if (axi_status == 0)
+   break;
+
+   msleep(20);
+   if (time_after(jiffies, end_time))
+   return -EIO;
+   }
+
+   /* reset and disable clock*/
+   regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_reset_reg,
+   reset_val);
+   regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_clock_ena_reg + 4,
+   reset_val);
+   msleep(1);
+   regmap_read(hisi_hba->ctrl, hisi_hba->ctrl_reset_sts_reg, );
+   if (reset_val != (val & reset_val)) {
+   dev_err(dev, "SAS reset fail.\n");
+   return -EIO;
+   }
+
+   /* De-reset and enable clock*/
+   regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_reset_reg + 4,
+   reset_val);
+   regmap_write(hisi_hba->ctrl, hisi_hba->ctrl_clock_ena_reg,
+   reset_val);
+   msleep(1);
+   regmap_read(hisi_hba->ctrl, hisi_hba->ctrl_reset_sts_reg,
+   );
+   if (val & reset_val) {
+   dev_err(dev, "SAS de-reset fail.\n");
+   return -EIO;
+   }
+

[RESEND PATCH v2 17/23] hisi_sas: add v2 path to send ssp frame

2016-01-25 Thread John Garry
Include code to prep ssp frame and deliver
to hardware.

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

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 099bc13..ab6ea25 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -264,6 +264,11 @@ enum {
 
 #define HISI_SAS_COMMAND_ENTRIES_V2_HW 4096
 
+#define DIR_NO_DATA 0
+#define DIR_TO_INI 1
+#define DIR_TO_DEVICE 2
+#define DIR_RESERVED 3
+
 static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 off)
 {
void __iomem *regs = hisi_hba->regs + off;
@@ -271,6 +276,13 @@ static u32 hisi_sas_read32(struct hisi_hba *hisi_hba, u32 
off)
return readl(regs);
 }
 
+static u32 hisi_sas_read32_relaxed(struct hisi_hba *hisi_hba, u32 off)
+{
+   void __iomem *regs = hisi_hba->regs + off;
+
+   return readl_relaxed(regs);
+}
+
 static void hisi_sas_write32(struct hisi_hba *hisi_hba, u32 off, u32 val)
 {
void __iomem *regs = hisi_hba->regs + off;
@@ -652,6 +664,176 @@ static int get_wideport_bitmap_v2_hw(struct hisi_hba 
*hisi_hba, int port_id)
return bitmap;
 }
 
+/**
+ * This function allocates across all queues to load balance.
+ * Slots are allocated from queues in a round-robin fashion.
+ *
+ * The callpath to this function and upto writing the write
+ * queue pointer should be safe from interruption.
+ */
+static int get_free_slot_v2_hw(struct hisi_hba *hisi_hba, int *q, int *s)
+{
+   struct device *dev = _hba->pdev->dev;
+   u32 r, w;
+   int queue = hisi_hba->queue;
+
+   while (1) {
+   w = hisi_sas_read32_relaxed(hisi_hba,
+   DLVRY_Q_0_WR_PTR + (queue * 0x14));
+   r = hisi_sas_read32_relaxed(hisi_hba,
+   DLVRY_Q_0_RD_PTR + (queue * 0x14));
+   if (r == (w+1) % HISI_SAS_QUEUE_SLOTS) {
+   queue = (queue + 1) % hisi_hba->queue_count;
+   if (queue == hisi_hba->queue) {
+   dev_warn(dev, "could not find free slot\n");
+   return -EAGAIN;
+   }
+   continue;
+   }
+   break;
+   }
+   hisi_hba->queue = (queue + 1) % hisi_hba->queue_count;
+   *q = queue;
+   *s = w;
+   return 0;
+}
+
+static void start_delivery_v2_hw(struct hisi_hba *hisi_hba)
+{
+   int dlvry_queue = hisi_hba->slot_prep->dlvry_queue;
+   int dlvry_queue_slot = hisi_hba->slot_prep->dlvry_queue_slot;
+
+   hisi_sas_write32(hisi_hba, DLVRY_Q_0_WR_PTR + (dlvry_queue * 0x14),
+++dlvry_queue_slot % HISI_SAS_QUEUE_SLOTS);
+}
+
+static int prep_prd_sge_v2_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot,
+ struct hisi_sas_cmd_hdr *hdr,
+ struct scatterlist *scatter,
+ int n_elem)
+{
+   struct device *dev = _hba->pdev->dev;
+   struct scatterlist *sg;
+   int i;
+
+   if (n_elem > HISI_SAS_SGE_PAGE_CNT) {
+   dev_err(dev, "prd err: n_elem(%d) > HISI_SAS_SGE_PAGE_CNT",
+   n_elem);
+   return -EINVAL;
+   }
+
+   slot->sge_page = dma_pool_alloc(hisi_hba->sge_page_pool, GFP_ATOMIC,
+   >sge_page_dma);
+   if (!slot->sge_page)
+   return -ENOMEM;
+
+   for_each_sg(scatter, sg, n_elem, i) {
+   struct hisi_sas_sge *entry = >sge_page->sge[i];
+
+   entry->addr = cpu_to_le64(sg_dma_address(sg));
+   entry->page_ctrl_0 = entry->page_ctrl_1 = 0;
+   entry->data_len = cpu_to_le32(sg_dma_len(sg));
+   entry->data_off = 0;
+   }
+
+   hdr->prd_table_addr = cpu_to_le64(slot->sge_page_dma);
+
+   hdr->sg_len = cpu_to_le32(n_elem << CMD_HDR_DATA_SGL_LEN_OFF);
+
+   return 0;
+}
+
+static int prep_ssp_v2_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot, int is_tmf,
+ struct hisi_sas_tmf_task *tmf)
+{
+   struct sas_task *task = slot->task;
+   struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
+   struct domain_device *device = task->dev;
+   struct hisi_sas_device *sas_dev = device->lldd_dev;
+   struct hisi_sas_port *port = slot->port;
+   struct sas_ssp_task *ssp_task = >ssp_task;
+   struct scsi_cmnd *scsi_cmnd = ssp_task->cmd;
+   int has_data = 0, rc, priority = is_tmf;
+   u8 *buf_cmd;
+   u32 dw1 = 0, dw2 = 0;
+
+   hdr->dw0 = cpu_to_le32((1 << CMD_HDR_RESP_REPORT_OFF) |
+  (2 << CMD_HDR_TLR_CTRL_OFF) |
+  (port->id << CMD_HDR_PORT_OFF) |
+

[RESEND PATCH v2 22/23] hisi_sas: add v2 tmf functions

2016-01-25 Thread John Garry
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 481aff9..58e1956 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -847,6 +847,14 @@ static void enable_phy_v2_hw(struct hisi_hba *hisi_hba, 
int phy_no)
hisi_sas_phy_write32(hisi_hba, phy_no, PHY_CFG, cfg);
 }
 
+static void disable_phy_v2_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_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
 {
config_id_frame_v2_hw(hisi_hba, phy_no);
@@ -854,6 +862,18 @@ static void start_phy_v2_hw(struct hisi_hba *hisi_hba, int 
phy_no)
enable_phy_v2_hw(hisi_hba, phy_no);
 }
 
+static void stop_phy_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
+{
+   disable_phy_v2_hw(hisi_hba, phy_no);
+}
+
+static void phy_hard_reset_v2_hw(struct hisi_hba *hisi_hba, int phy_no)
+{
+   stop_phy_v2_hw(hisi_hba, phy_no);
+   msleep(100);
+   start_phy_v2_hw(hisi_hba, phy_no);
+}
+
 static void start_phys_v2_hw(unsigned long data)
 {
struct hisi_hba *hisi_hba = (struct hisi_hba *)data;
@@ -2145,6 +2165,9 @@ static const struct hisi_sas_hw hisi_sas_v2_hw = {
.get_free_slot = get_free_slot_v2_hw,
.start_delivery = start_delivery_v2_hw,
.slot_complete = slot_complete_v2_hw,
+   .phy_enable = enable_phy_v2_hw,
+   .phy_disable = disable_phy_v2_hw,
+   .phy_hard_reset = phy_hard_reset_v2_hw,
.max_command_entries = HISI_SAS_COMMAND_ENTRIES_V2_HW,
.complete_hdr_size = sizeof(struct hisi_sas_complete_v2_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


[RESEND PATCH v2 15/23] hisi_sas: add v2 SATA interrupt handler

2016-01-25 Thread John Garry
Signed-off-by: John Garry 
---
 drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 100 +
 1 file changed, 100 insertions(+)

diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
index 5af2069..c4a887c 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c
@@ -861,6 +861,86 @@ static irqreturn_t int_chnl_int_v2_hw(int irq_no, void *p)
return IRQ_HANDLED;
 }
 
+static irqreturn_t sata_int_v2_hw(int irq_no, void *p)
+{
+   struct hisi_sas_phy *phy = p;
+   struct hisi_hba *hisi_hba = phy->hisi_hba;
+   struct asd_sas_phy *sas_phy = >sas_phy;
+   struct device *dev = _hba->pdev->dev;
+   struct  hisi_sas_initial_fis *initial_fis;
+   struct dev_to_host_fis *fis;
+   u32 ent_tmp, ent_msk, ent_int, port_id, link_rate, hard_phy_linkrate;
+   irqreturn_t res = IRQ_HANDLED;
+   u8 attached_sas_addr[SAS_ADDR_SIZE] = {0};
+   int phy_no;
+
+   phy_no = sas_phy->id;
+   initial_fis = _hba->initial_fis[phy_no];
+   fis = _fis->fis;
+
+   ent_msk = hisi_sas_read32(hisi_hba, ENT_INT_SRC_MSK1);
+   hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, ent_msk | 1 << phy_no);
+
+   ent_int = hisi_sas_read32(hisi_hba, ENT_INT_SRC1);
+   ent_tmp = ent_int;
+   ent_int >>= ENT_INT_SRC1_D2H_FIS_CH1_OFF * (phy_no % 4);
+   if ((ent_int & ENT_INT_SRC1_D2H_FIS_CH0_MSK) == 0) {
+   dev_warn(dev, "sata int: phy%d did not receive FIS\n", phy_no);
+   hisi_sas_write32(hisi_hba, ENT_INT_SRC1, ent_tmp);
+   hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, ent_msk);
+   res = IRQ_NONE;
+   goto end;
+   }
+
+   if (unlikely(phy_no == 8)) {
+   u32 port_state = hisi_sas_read32(hisi_hba, PORT_STATE);
+
+   port_id = (port_state & PORT_STATE_PHY8_PORT_NUM_MSK) >>
+ PORT_STATE_PHY8_PORT_NUM_OFF;
+   link_rate = (port_state & PORT_STATE_PHY8_CONN_RATE_MSK) >>
+   PORT_STATE_PHY8_CONN_RATE_OFF;
+   } else {
+   port_id = hisi_sas_read32(hisi_hba, PHY_PORT_NUM_MA);
+   port_id = (port_id >> (4 * phy_no)) & 0xf;
+   link_rate = hisi_sas_read32(hisi_hba, PHY_CONN_RATE);
+   link_rate = (link_rate >> (phy_no * 4)) & 0xf;
+   }
+
+   if (port_id == 0xf) {
+   dev_err(dev, "sata int: phy%d invalid portid\n", phy_no);
+   res = IRQ_NONE;
+   goto end;
+   }
+
+   sas_phy->linkrate = link_rate;
+   hard_phy_linkrate = hisi_sas_phy_read32(hisi_hba, phy_no,
+   HARD_PHY_LINKRATE);
+   phy->maximum_linkrate = hard_phy_linkrate & 0xf;
+   phy->minimum_linkrate = (hard_phy_linkrate >> 4) & 0xf;
+
+   sas_phy->oob_mode = SATA_OOB_MODE;
+   /* Make up some unique SAS address */
+   attached_sas_addr[0] = 0x50;
+   attached_sas_addr[7] = phy_no;
+   memcpy(sas_phy->attached_sas_addr, attached_sas_addr, SAS_ADDR_SIZE);
+   memcpy(sas_phy->frame_rcvd, fis, sizeof(struct dev_to_host_fis));
+   dev_info(dev, "sata int phyup: phy%d link_rate=%d\n", phy_no, 
link_rate);
+   phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA);
+   phy->port_id = port_id;
+   phy->phy_type |= PORT_TYPE_SATA;
+   phy->phy_attached = 1;
+   phy->identify.device_type = SAS_SATA_DEV;
+   phy->frame_rcvd_size = sizeof(struct dev_to_host_fis);
+   phy->identify.target_port_protocols = SAS_PROTOCOL_SATA;
+   queue_work(hisi_hba->wq, >phyup_ws);
+
+end:
+   hisi_sas_write32(hisi_hba, ENT_INT_SRC1, ent_tmp);
+   hisi_sas_write32(hisi_hba, ENT_INT_SRC_MSK1, ent_msk);
+
+   return res;
+}
+
 static irq_handler_t phy_interrupts[HISI_SAS_PHY_INT_NR] = {
int_phy_updown_v2_hw,
int_chnl_int_v2_hw,
@@ -900,6 +980,26 @@ static int interrupt_init_v2_hw(struct hisi_hba *hisi_hba)
}
}
 
+   for (i = 0; i < hisi_hba->n_phy; i++) {
+   struct hisi_sas_phy *phy = _hba->phy[i];
+   int idx = i + 72; /* First SATA interrupt is irq72 */
+
+   irq = irq_map[idx];
+   if (!irq) {
+   dev_err(dev, "irq init: fail map phy interrupt %d\n",
+   idx);
+   return -ENOENT;
+   }
+
+   rc = devm_request_irq(dev, irq, sata_int_v2_hw, 0,
+ DRV_NAME " sata", phy);
+   if (rc) {
+   dev_err(dev, "irq init: could not request "
+   "sata interrupt %d, rc=%d\n",
+   irq, rc);
+   return -ENOENT;
+   }
+   }
return 0;
 }
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in

[PATCH, RESEND 3] qla2xxx: Remove use of 'struct timeval'

2016-01-25 Thread Arnd Bergmann
From: Tina Ruchandani 

struct register_host_info stores a 64-bit UTC system time timestamp.
This patch removes the use of 'struct timeval' to obtain that timestamp
as its tv_sec value will overflow on 32-bit systems in year 2038 beyond.
The patch uses ktime_get_real_seconds() which returns a 64-bit seconds value.

Signed-off-by: Tina Ruchandani 
Reviewed-by: Johannes Thumshirn 
Acked-by: Himanshu Madhani 
Signed-off-by: Arnd Bergmann 
---
Resent with correct author field and added Ack

diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c
index b5029e543b91..15dff7099955 100644
--- a/drivers/scsi/qla2xxx/qla_mr.c
+++ b/drivers/scsi/qla2xxx/qla_mr.c
@@ -6,6 +6,7 @@
  */
 #include "qla_def.h"
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -1812,7 +1813,6 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, 
uint16_t fx_type)
struct host_system_info *phost_info;
struct register_host_info *preg_hsi;
struct new_utsname *p_sysid = NULL;
-   struct timeval tv;
 
sp = qla2x00_get_sp(vha, fcport, GFP_KERNEL);
if (!sp)
@@ -1886,8 +1886,7 @@ qlafx00_fx_disc(scsi_qla_host_t *vha, fc_port_t *fcport, 
uint16_t fx_type)
p_sysid->domainname, DOMNAME_LENGTH);
strncpy(phost_info->hostdriver,
QLA2XXX_VERSION, VERSION_LENGTH);
-   do_gettimeofday();
-   preg_hsi->utc = (uint64_t)tv.tv_sec;
+   preg_hsi->utc = (uint64_t)ktime_get_real_seconds();
ql_dbg(ql_dbg_init, vha, 0x0149,
"ISP%04X: Host registration with firmware\n",
ha->pdev->device);

--
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 03/22] scsi: Fix dependencies for !HAS_IOMEM and !HAS_DMA archs

2016-01-25 Thread Richard Weinberger
Not every arch has io or DMA memory.
So, unbreak the build by fixing the dependencies.

Signed-off-by: Richard Weinberger 
---
 drivers/scsi/hisi_sas/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/scsi/hisi_sas/Kconfig b/drivers/scsi/hisi_sas/Kconfig
index 37a0c71..f9157f4 100644
--- a/drivers/scsi/hisi_sas/Kconfig
+++ b/drivers/scsi/hisi_sas/Kconfig
@@ -2,5 +2,6 @@ config SCSI_HISI_SAS
tristate "HiSilicon SAS"
select SCSI_SAS_LIBSAS
select BLK_DEV_INTEGRITY
+   depends on HAS_IOMEM && HAS_DMA
help
This driver supports HiSilicon's SAS HBA
-- 
1.8.4.5

--
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 34/78] atari_NCR5380: Use arbitration timeout

2016-01-25 Thread Finn Thain

On Mon, 25 Jan 2016, Geert Uytterhoeven wrote:

> > In principle I think that Linux drivers should not carry workarounds 
> > for emulators.
> 
> Please consider ARAnyM is the current m68k workhorse, so it would be 
> nice to handle this someway.

AFAICT atari_scsi on aranym never did anything useful. Those aranym users 
who need to run Linux 4.5 can set CONFIG_ATARI_SCSI=n or blacklist the 
atari_scsi module (up until aranym can be patched).

> 
> Alternatively, we need to fix ARAnyM,

I'll look into writing a patch for the emulator after I've finished 
testing the exception handling fixes for the driver.

> or can make the creation of the atari_scsi platform device conditional 
> on not running under ARAnyM.

Fixing the emulator is the only sensible approach. If S operating systems 
have to carry workarounds for B emulator bugs, the cost is (at least) 
proportional to S * B.

-- 
--
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 34/78] atari_NCR5380: Use arbitration timeout

2016-01-25 Thread Geert Uytterhoeven
Hi Finn,

On Mon, Jan 25, 2016 at 3:45 AM, Finn Thain  wrote:
> On Sun, 24 Jan 2016, Geert Uytterhoeven wrote:
>> On Sun, Jan 3, 2016 at 6:05 AM, Finn Thain  
>> wrote:
>> > Allow target selection to fail with a timeout instead of waiting in
>> > infinite loops. This gets rid of the unused NCR_TIMEOUT macro, it is more
>> > defensive and has proved helpful in debugging.
>> >
>> > Signed-off-by: Finn Thain 
>> > Reviewed-by: Hannes Reinecke 
>> > Tested-by: Ondrej Zary 
>> > Tested-by: Michael Schmitz 
>>
>> This patch (commit 55500d9b08295e3b6016b53879dea1cb7787f1b0) causes a hang
>> on ARAnyM with atari_defconfig after:
>>
>> scsi host0: Atari native SCSI, io_port 0x0, n_io_port 0, base 0x0,
>> irq 15, can_queue 8, cmd_per_lun 1, sg_tablesize 0, this_id 7, flags {
>> }, options { REAL_DMA SUPPORT_TAGS }
>> blk_queue_max_segments: set to minimum 1
>>
>> > --- linux.orig/drivers/scsi/atari_NCR5380.c 2016-01-03 
>> > 16:03:43.0 +1100
>> > +++ linux/drivers/scsi/atari_NCR5380.c  2016-01-03 16:03:44.0 +1100
>> > @@ -1436,42 +1437,28 @@ static int NCR5380_select(struct Scsi_Ho
>> > NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);
>> > NCR5380_write(MODE_REG, MR_ARBITRATE);
>> >
>> > -   local_irq_restore(flags);
>> > +   /* The chip now waits for BUS FREE phase. Then after the 800 ns
>> > +* Bus Free Delay, arbitration will begin.
>> > +*/
>> >
>> > -   /* Wait for arbitration logic to complete */
>> > -#if defined(NCR_TIMEOUT)
>> > -   {
>> > -   unsigned long timeout = jiffies + 2*NCR_TIMEOUT;
>> > -
>> > -   while (!(NCR5380_read(INITIATOR_COMMAND_REG) & 
>> > ICR_ARBITRATION_PROGRESS) &&
>> > -  time_before(jiffies, timeout) && 
>> > !hostdata->connected)
>> > -   ;
>> > -   if (time_after_eq(jiffies, timeout)) {
>> > -   printk("scsi : arbitration timeout at %d\n", 
>> > __LINE__);
>> > +   local_irq_restore(flags);
>> > +   timeout = jiffies + HZ;
>> > +   while (1) {
>> > +   if (time_is_before_jiffies(timeout)) {
>> > NCR5380_write(MODE_REG, MR_BASE);
>> > -   NCR5380_write(SELECT_ENABLE_REG, 
>> > hostdata->id_mask);
>> > +   shost_printk(KERN_ERR, instance,
>> > +"select: arbitration timeout\n");
>> > return -1;
>> > }
>> > +   if (!(NCR5380_read(MODE_REG) & MR_ARBITRATE)) {
>>
>> This newly added check always triggers, causing an infinite loop calling
>> NCR5380_select().
>
> If you bisected and got a failure here, it would not be surprising because
> some of the remaining patches fix bugs in the exception handlers.
>
> But if you test the entire patch series and get a hang (after waiting for
> the command to timeout and abort etc) it could be caused by a known bug in
> the abort handler. I will be sending a patch for that.

Yes, this was bisected. The issue was originally noticed after merging in
upstream, though.

Awaiting your patch for testing...

>> Perhaps this is an ARAnyM quirk?
>
> I'd say this is an ARAnyM bug. atari_scsi has been tested on an actual
> Atari Falcon, hence Michael's tested-by tag.
>
>> If not, does it trigger (on some hardware) with drivers/scsi/NCR5380.c,
>> too?
>
> For the arbitration and selection phases, there is no difference between
> NCR5380.c and atari_NCR5380.c. That's one of the benefits of my patches.
>
> That means this code was tested on silicon from NCR (53C400), Symbios
> Logic (53C400A), AMD (Am85C80), Domex Technology Corp (DTC-536, DTC-436)
> and LOGIC Devices (L5380).

> The MR_ARBITRATE bit should remain set until the driver clears it (or the
> reset logic clears it). But it looks like aranym simply discards writes to
> the mode register, such that reads always return 0.
>
> Compare
>   http://sourceforge.net/p/aranym/code/ci/master/tree/src/ncr5380.cpp
> with the MAME/MESS emulated device
>   https://github.com/mamedev/mame/blob/master/src/devices/machine/ncr5380.cpp
>
> I don't know what the Hatari emulator does.
>
> In principle I think that Linux drivers should not carry workarounds for
> emulators.

Please consider ARAnyM is the current m68k workhorse, so it would be
nice to handle this someway.

Alternatively, we need to fix ARAnyM, or can make the creation of the
atari_scsi platform device conditional on not running under ARAnyM.

Thanks!

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.

[PATCH-v2 08/12] sbp-target: Convert to TARGET_SCF_ACK_KREF I/O krefs

2016-01-25 Thread Nicholas A. Bellinger
From: Nicholas Bellinger 

Cc: Chris Boot 
Cc: Christoph Hellwig 
Cc: Hannes Reinecke 
Signed-off-by: Nicholas Bellinger 
---
 drivers/target/sbp/sbp_target.c | 30 --
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c
index 756e87f..251d532 100644
--- a/drivers/target/sbp/sbp_target.c
+++ b/drivers/target/sbp/sbp_target.c
@@ -893,7 +893,6 @@ static void tgt_agent_process_work(struct work_struct *work)
STATUS_BLOCK_SBP_STATUS(
SBP_STATUS_REQ_TYPE_NOTSUPP));
sbp_send_status(req);
-   sbp_free_request(req);
return;
case 3: /* Dummy ORB */
req->status.status |= cpu_to_be32(
@@ -904,7 +903,6 @@ static void tgt_agent_process_work(struct work_struct *work)
STATUS_BLOCK_SBP_STATUS(
SBP_STATUS_DUMMY_ORB_COMPLETE));
sbp_send_status(req);
-   sbp_free_request(req);
return;
default:
BUG();
@@ -988,7 +986,6 @@ static void tgt_agent_fetch_work(struct work_struct *work)
spin_unlock_bh(>lock);
 
sbp_send_status(req);
-   sbp_free_request(req);
return;
}
 
@@ -1235,7 +1232,7 @@ static void sbp_handle_command(struct sbp_target_request 
*req)
req->se_cmd.tag = req->orb_pointer;
if (target_submit_cmd(>se_cmd, sess->se_sess, req->cmd_buf,
  req->sense_buf, unpacked_lun, data_length,
- TCM_SIMPLE_TAG, data_dir, 0))
+ TCM_SIMPLE_TAG, data_dir, TARGET_SCF_ACK_KREF))
goto err;
 
return;
@@ -1247,7 +1244,6 @@ err:
STATUS_BLOCK_LEN(1) |
STATUS_BLOCK_SBP_STATUS(SBP_STATUS_UNSPECIFIED_ERROR));
sbp_send_status(req);
-   sbp_free_request(req);
 }
 
 /*
@@ -1346,22 +1342,29 @@ static int sbp_rw_data(struct sbp_target_request *req)
 
 static int sbp_send_status(struct sbp_target_request *req)
 {
-   int ret, length;
+   int rc, ret = 0, length;
struct sbp_login_descriptor *login = req->login;
 
length = (((be32_to_cpu(req->status.status) >> 24) & 0x07) + 1) * 4;
 
-   ret = sbp_run_request_transaction(req, TCODE_WRITE_BLOCK_REQUEST,
+   rc = sbp_run_request_transaction(req, TCODE_WRITE_BLOCK_REQUEST,
login->status_fifo_addr, >status, length);
-   if (ret != RCODE_COMPLETE) {
-   pr_debug("sbp_send_status: write failed: 0x%x\n", ret);
-   return -EIO;
+   if (rc != RCODE_COMPLETE) {
+   pr_debug("sbp_send_status: write failed: 0x%x\n", rc);
+   ret = -EIO;
+   goto put_ref;
}
 
pr_debug("sbp_send_status: status write complete for ORB: 0x%llx\n",
req->orb_pointer);
-
-   return 0;
+   /*
+* Drop the extra ACK_KREF reference taken by target_submit_cmd()
+* ahead of sbp_check_stop_free() -> transport_generic_free_cmd()
+* final se_cmd->cmd_kref put.
+*/
+put_ref:
+   target_put_sess_cmd(>se_cmd);
+   return ret;
 }
 
 static void sbp_sense_mangle(struct sbp_target_request *req)
@@ -1826,8 +1829,7 @@ static int sbp_check_stop_free(struct se_cmd *se_cmd)
struct sbp_target_request *req = container_of(se_cmd,
struct sbp_target_request, se_cmd);
 
-   transport_generic_free_cmd(>se_cmd, 0);
-   return 1;
+   return transport_generic_free_cmd(>se_cmd, 0);
 }
 
 static int sbp_count_se_tpg_luns(struct se_portal_group *tpg)
-- 
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-v2 09/12] usb-gadget/tcm: Conversion to percpu_ida tag pre-allocation

2016-01-25 Thread Nicholas A. Bellinger
From: Nicholas Bellinger 

Cc: Sebastian Andrzej Siewior 
Cc: Andrzej Pietrasiewicz 
Signed-off-by: Nicholas Bellinger 
---
 drivers/usb/gadget/function/f_tcm.c | 95 ++---
 1 file changed, 56 insertions(+), 39 deletions(-)

diff --git a/drivers/usb/gadget/function/f_tcm.c 
b/drivers/usb/gadget/function/f_tcm.c
index 2e8b91d..8773572 100644
--- a/drivers/usb/gadget/function/f_tcm.c
+++ b/drivers/usb/gadget/function/f_tcm.c
@@ -1073,39 +1073,65 @@ out:
usbg_cleanup_cmd(cmd);
 }
 
+static struct usbg_cmd *usbg_get_cmd(struct f_uas *fu,
+   struct tcm_usbg_nexus *tv_nexus, u32 scsi_tag)
+{
+   struct se_session *se_sess = tv_nexus->tvn_se_sess;
+   struct usbg_cmd *cmd;
+   int tag;
+
+   tag = percpu_ida_alloc(_sess->sess_tag_pool, GFP_ATOMIC);
+   if (tag < 0)
+   return ERR_PTR(-ENOMEM);
+
+   cmd = &((struct usbg_cmd *)se_sess->sess_cmd_map)[tag];
+   cmd->se_cmd.map_tag = tag;
+   cmd->se_cmd.tag = cmd->tag = scsi_tag;
+   cmd->fu = fu;
+
+   return cmd;
+}
+
+static void usbg_release_cmd(struct se_cmd *);
+
 static int usbg_submit_command(struct f_uas *fu,
void *cmdbuf, unsigned int len)
 {
struct command_iu *cmd_iu = cmdbuf;
struct usbg_cmd *cmd;
-   struct usbg_tpg *tpg;
-   struct tcm_usbg_nexus *tv_nexus;
+   struct usbg_tpg *tpg = fu->tpg;
+   struct tcm_usbg_nexus *tv_nexus = tpg->tpg_nexus;
u32 cmd_len;
+   u16 scsi_tag;
 
if (cmd_iu->iu_id != IU_ID_COMMAND) {
pr_err("Unsupported type %d\n", cmd_iu->iu_id);
return -EINVAL;
}
 
-   cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
-   if (!cmd)
-   return -ENOMEM;
+   tv_nexus = tpg->tpg_nexus;
+   if (!tv_nexus) {
+   pr_err("Missing nexus, ignoring command\n");
+   return -EINVAL;
+   }
 
-   cmd->fu = fu;
+   cmd_len = (cmd_iu->len & ~0x3) + 16;
+   if (cmd_len > USBG_MAX_CMD)
+   return -EINVAL;
+
+   scsi_tag = be16_to_cpup(_iu->tag);
+   cmd = usbg_get_cmd(fu, tv_nexus, scsi_tag);
+   if (IS_ERR(cmd)) {
+   pr_err("usbg_get_cmd failed\n");
+   return -ENOMEM;
+   }
 
/* XXX until I figure out why I can't free in on complete */
kref_init(>ref);
kref_get(>ref);
 
-   tpg = fu->tpg;
-   cmd_len = (cmd_iu->len & ~0x3) + 16;
-   if (cmd_len > USBG_MAX_CMD)
-   goto err;
-
memcpy(cmd->cmd_buf, cmd_iu->cdb, cmd_len);
 
-   cmd->tag = be16_to_cpup(_iu->tag);
-   cmd->se_cmd.tag = cmd->tag;
if (fu->flags & USBG_USE_STREAMS) {
if (cmd->tag > UASP_SS_EP_COMP_NUM_STREAMS)
goto err;
@@ -1117,12 +1143,6 @@ static int usbg_submit_command(struct f_uas *fu,
cmd->stream = >stream[0];
}
 
-   tv_nexus = tpg->tpg_nexus;
-   if (!tv_nexus) {
-   pr_err("Missing nexus, ignoring command\n");
-   goto err;
-   }
-
switch (cmd_iu->prio_attr & 0x7) {
case UAS_HEAD_TAG:
cmd->prio_attr = TCM_HEAD_TAG;
@@ -1148,7 +1168,7 @@ static int usbg_submit_command(struct f_uas *fu,
 
return 0;
 err:
-   kfree(cmd);
+   usbg_release_cmd(>se_cmd);
return -EINVAL;
 }
 
@@ -1190,7 +1210,7 @@ static int bot_submit_command(struct f_uas *fu,
 {
struct bulk_cb_wrap *cbw = cmdbuf;
struct usbg_cmd *cmd;
-   struct usbg_tpg *tpg;
+   struct usbg_tpg *tpg = fu->tpg;
struct tcm_usbg_nexus *tv_nexus;
u32 cmd_len;
 
@@ -1207,28 +1227,25 @@ static int bot_submit_command(struct f_uas *fu,
if (cmd_len < 1 || cmd_len > 16)
return -EINVAL;
 
-   cmd = kzalloc(sizeof(*cmd), GFP_ATOMIC);
-   if (!cmd)
-   return -ENOMEM;
+   tv_nexus = tpg->tpg_nexus;
+   if (!tv_nexus) {
+   pr_err("Missing nexus, ignoring command\n");
+   return -ENODEV;
+   }
 
-   cmd->fu = fu;
+   cmd = usbg_get_cmd(fu, tv_nexus, cbw->Tag);
+   if (IS_ERR(cmd)) {
+   pr_err("usbg_get_cmd failed\n");
+   return -ENOMEM;
+   }
 
/* XXX until I figure out why I can't free in on complete */
kref_init(>ref);
kref_get(>ref);
 
-   tpg = fu->tpg;
-
memcpy(cmd->cmd_buf, cbw->CDB, cmd_len);
 
cmd->bot_tag = cbw->Tag;
-
-   tv_nexus = tpg->tpg_nexus;
-   if (!tv_nexus) {
-   pr_err("Missing nexus, ignoring command\n");
-   goto err;
-   }
-
cmd->prio_attr = TCM_SIMPLE_TAG;
cmd->unpacked_lun = cbw->Lun;
cmd->is_read = cbw->Flags & US_BULK_FLAG_IN ? 1 : 0;
@@ -1239,9 +1256,6 @@ static int bot_submit_command(struct f_uas *fu,

[PATCH-v2 04/12] tcm_qla2xxx: Convert to target_alloc_session usage

2016-01-25 Thread Nicholas A. Bellinger
From: Nicholas Bellinger 

Cc: Himanshu Madhani 
Cc: Quinn Tran 
Signed-off-by: Nicholas Bellinger 
---
 drivers/scsi/qla2xxx/qla_target.c  |  8 +---
 drivers/scsi/qla2xxx/qla_target.h  |  2 +-
 drivers/scsi/qla2xxx/tcm_qla2xxx.c | 79 +++---
 3 files changed, 43 insertions(+), 46 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_target.c 
b/drivers/scsi/qla2xxx/qla_target.c
index 2c71305..a2da314 100644
--- a/drivers/scsi/qla2xxx/qla_target.c
+++ b/drivers/scsi/qla2xxx/qla_target.c
@@ -879,7 +879,6 @@ static struct qla_tgt_sess *qlt_create_sess(
struct qla_hw_data *ha = vha->hw;
struct qla_tgt_sess *sess;
unsigned long flags;
-   unsigned char be_sid[3];
 
/* Check to avoid double sessions */
spin_lock_irqsave(>tgt.sess_lock, flags);
@@ -948,17 +947,14 @@ static struct qla_tgt_sess *qlt_create_sess(
"Adding sess %p to tgt %p via ->check_initiator_node_acl()\n",
sess, vha->vha_tgt.qla_tgt);
 
-   be_sid[0] = sess->s_id.b.domain;
-   be_sid[1] = sess->s_id.b.area;
-   be_sid[2] = sess->s_id.b.al_pa;
/*
 * Determine if this fc_port->port_name is allowed to access
 * target mode using explict NodeACLs+MappedLUNs, or using
 * TPG demo mode.  If this is successful a target mode FC nexus
 * is created.
 */
-   if (ha->tgt.tgt_ops->check_initiator_node_acl(vha,
-   >port_name[0], sess, _sid[0], fcport->loop_id) < 0) {
+   if (ha->tgt.tgt_ops->check_initiator_node_acl(vha, 
>port_name[0],
+ sess)) {
kfree(sess);
return NULL;
}
diff --git a/drivers/scsi/qla2xxx/qla_target.h 
b/drivers/scsi/qla2xxx/qla_target.h
index 71b2865..409bd5f 100644
--- a/drivers/scsi/qla2xxx/qla_target.h
+++ b/drivers/scsi/qla2xxx/qla_target.h
@@ -731,7 +731,7 @@ struct qla_tgt_func_tmpl {
void (*free_session)(struct qla_tgt_sess *);
 
int (*check_initiator_node_acl)(struct scsi_qla_host *, unsigned char *,
-   void *, uint8_t *, uint16_t);
+   struct qla_tgt_sess *);
void (*update_sess)(struct qla_tgt_sess *, port_id_t, uint16_t, bool);
struct qla_tgt_sess *(*find_sess_by_loop_id)(struct scsi_qla_host *,
const uint16_t);
diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c 
b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
index b44f397..bf73c6f 100644
--- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c
+++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c
@@ -1336,6 +1336,39 @@ static void tcm_qla2xxx_free_session(struct qla_tgt_sess 
*sess)
transport_deregister_session(sess->se_sess);
 }
 
+static int tcm_qla2xxx_session_cb(struct se_portal_group *se_tpg,
+ struct se_session *se_sess, void *p)
+{
+   struct tcm_qla2xxx_tpg *tpg = container_of(se_tpg,
+   struct tcm_qla2xxx_tpg, se_tpg);
+   struct tcm_qla2xxx_lport *lport = tpg->lport;
+   struct qla_hw_data *ha = lport->qla_vha->hw;
+   struct se_node_acl *se_nacl = se_sess->se_node_acl;
+   struct tcm_qla2xxx_nacl *nacl = container_of(se_nacl,
+   struct tcm_qla2xxx_nacl, se_node_acl);
+   struct qla_tgt_sess *qlat_sess = p;
+   uint16_t loop_id = qlat_sess->loop_id;
+   unsigned long flags;
+   unsigned char be_sid[3];
+
+   be_sid[0] = qlat_sess->s_id.b.domain;
+   be_sid[1] = qlat_sess->s_id.b.area;
+   be_sid[2] = qlat_sess->s_id.b.al_pa;
+
+   /*
+* And now setup se_nacl and session pointers into HW lport internal
+* mappings for fabric S_ID and LOOP_ID.
+*/
+   spin_lock_irqsave(>tgt.sess_lock, flags);
+   tcm_qla2xxx_set_sess_by_s_id(lport, se_nacl, nacl,
+se_sess, qlat_sess, be_sid);
+   tcm_qla2xxx_set_sess_by_loop_id(lport, se_nacl, nacl,
+   se_sess, qlat_sess, loop_id);
+   spin_unlock_irqrestore(>tgt.sess_lock, flags);
+
+   return 0;
+}
+
 /*
  * Called via qlt_create_sess():ha->qla2x_tmpl->check_initiator_node_acl()
  * to locate struct se_node_acl
@@ -1343,20 +1376,13 @@ static void tcm_qla2xxx_free_session(struct 
qla_tgt_sess *sess)
 static int tcm_qla2xxx_check_initiator_node_acl(
scsi_qla_host_t *vha,
unsigned char *fc_wwpn,
-   void *qla_tgt_sess,
-   uint8_t *s_id,
-   uint16_t loop_id)
+   struct qla_tgt_sess *qlat_sess)
 {
struct qla_hw_data *ha = vha->hw;
struct tcm_qla2xxx_lport *lport;
struct tcm_qla2xxx_tpg *tpg;
-   struct tcm_qla2xxx_nacl *nacl;
-   struct se_portal_group *se_tpg;
-   struct se_node_acl *se_nacl;
struct se_session *se_sess;
-   struct 

[PATCH-v2 06/12] ib_srpt: Convert to target_alloc_session usage

2016-01-25 Thread Nicholas A. Bellinger
From: Nicholas Bellinger 

Cc: Vu Pham 
Cc: Sagi Grimberg 
Signed-off-by: Nicholas Bellinger 
---
 drivers/infiniband/ulp/srpt/ib_srpt.c | 23 ++-
 1 file changed, 6 insertions(+), 17 deletions(-)

diff --git a/drivers/infiniband/ulp/srpt/ib_srpt.c 
b/drivers/infiniband/ulp/srpt/ib_srpt.c
index bc5470c..5a35c1f 100644
--- a/drivers/infiniband/ulp/srpt/ib_srpt.c
+++ b/drivers/infiniband/ulp/srpt/ib_srpt.c
@@ -2387,7 +2387,6 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
struct srp_login_rej *rej;
struct ib_cm_rep_param *rep_param;
struct srpt_rdma_ch *ch, *tmp_ch;
-   struct se_node_acl *se_acl;
u32 it_iu_len;
int i, ret = 0;
unsigned char *p;
@@ -2553,19 +2552,12 @@ static int srpt_cm_req_recv(struct ib_cm_id *cm_id,
pr_debug("registering session %s\n", ch->sess_name);
p = >sess_name[0];
 
-   ch->sess = transport_init_session(TARGET_PROT_NORMAL);
-   if (IS_ERR(ch->sess)) {
-   rej->reason = cpu_to_be32(
-   SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
-   pr_debug("Failed to create session\n");
-   goto destroy_ib;
-   }
-
 try_again:
-   se_acl = core_tpg_get_initiator_node_acl(>port_tpg_1, p);
-   if (!se_acl) {
+   ch->sess = target_alloc_session(>port_tpg_1, 0, 0,
+   TARGET_PROT_NORMAL, p, ch, NULL);
+   if (IS_ERR(ch->sess)) {
pr_info("Rejected login because no ACL has been"
-   " configured yet for initiator %s.\n", ch->sess_name);
+   " configured yet for initiator %s.\n", p);
/*
 * XXX: Hack to retry of ch->i_port_id without leading '0x'
 */
@@ -2573,14 +2565,11 @@ try_again:
p += 2;
goto try_again;
}
-   rej->reason = cpu_to_be32(
+   rej->reason = cpu_to_be32((PTR_ERR(ch->sess) == -ENOMEM) ?
+   SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES :
SRP_LOGIN_REJ_CHANNEL_LIMIT_REACHED);
-   transport_free_session(ch->sess);
goto destroy_ib;
}
-   ch->sess->se_node_acl = se_acl;
-
-   transport_register_session(>port_tpg_1, se_acl, ch->sess, ch);
 
pr_debug("Establish connection sess=%p name=%s cm_id=%p\n", ch->sess,
 ch->sess_name, ch->cm_id);
-- 
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-v2 11/12] xen-scsiback: Convert to percpu_ida tag allocation

2016-01-25 Thread Nicholas A. Bellinger
From: Nicholas Bellinger 

Cc: Juergen Gross 
Cc: Hannes Reinecke 
Cc: David Vrabel 
Signed-off-by: Nicholas Bellinger 
---
 drivers/xen/xen-scsiback.c | 163 -
 1 file changed, 87 insertions(+), 76 deletions(-)

diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c
index 594f8a7..640fb22 100644
--- a/drivers/xen/xen-scsiback.c
+++ b/drivers/xen/xen-scsiback.c
@@ -190,7 +190,6 @@ module_param_named(max_buffer_pages, 
scsiback_max_buffer_pages, int, 0644);
 MODULE_PARM_DESC(max_buffer_pages,
 "Maximum number of free pages to keep in backend buffer");
 
-static struct kmem_cache *scsiback_cachep;
 static DEFINE_SPINLOCK(free_pages_lock);
 static int free_pages_num;
 static LIST_HEAD(scsiback_free_pages);
@@ -322,7 +321,8 @@ static void scsiback_free_translation_entry(struct kref 
*kref)
 }
 
 static void scsiback_do_resp_with_sense(char *sense_buffer, int32_t result,
-   uint32_t resid, struct vscsibk_pend *pending_req)
+   uint32_t resid, struct vscsibk_pend *pending_req,
+   uint16_t rqid)
 {
struct vscsiif_response *ring_res;
struct vscsibk_info *info = pending_req->info;
@@ -337,7 +337,7 @@ static void scsiback_do_resp_with_sense(char *sense_buffer, 
int32_t result,
info->ring.rsp_prod_pvt++;
 
ring_res->rslt   = result;
-   ring_res->rqid   = pending_req->rqid;
+   ring_res->rqid   = rqid;
 
if (sense_buffer != NULL &&
scsi_normalize_sense(sense_buffer, VSCSIIF_SENSE_BUFFERSIZE,
@@ -358,7 +358,7 @@ static void scsiback_do_resp_with_sense(char *sense_buffer, 
int32_t result,
if (notify)
notify_remote_via_irq(info->irq);
 
-   if (pending_req->v2p)
+   if (pending_req && pending_req->v2p)
kref_put(_req->v2p->kref,
 scsiback_free_translation_entry);
 }
@@ -378,7 +378,8 @@ static void scsiback_cmd_done(struct vscsibk_pend 
*pending_req)
scsiback_print_status(sense_buffer, errors, pending_req);
 
scsiback_fast_flush_area(pending_req);
-   scsiback_do_resp_with_sense(sense_buffer, errors, resid, pending_req);
+   scsiback_do_resp_with_sense(sense_buffer, errors, resid, pending_req,
+   pending_req->rqid);
scsiback_put(info);
 }
 
@@ -616,15 +617,15 @@ static void scsiback_device_action(struct vscsibk_pend 
*pending_req,
err = (se_cmd->se_tmr_req->response == TMR_FUNCTION_COMPLETE) ?
SUCCESS : FAILED;
 
-out:
-   if (tmr) {
-   transport_generic_free_cmd(_req->se_cmd, 1);
+   scsiback_do_resp_with_sense(NULL, err, 0, pending_req,
+   pending_req->rqid);
+   transport_generic_free_cmd(_req->se_cmd, 1);
+   return;
+err:
+   if (tmr)
kfree(tmr);
-   }
-
-   scsiback_do_resp_with_sense(NULL, err, 0, pending_req);
-
-   kmem_cache_free(scsiback_cachep, pending_req);
+   scsiback_do_resp_with_sense(NULL, err, 0, pending_req,
+   pending_req->rqid);
 }
 
 /*
@@ -653,15 +654,53 @@ out:
return entry;
 }
 
-static int prepare_pending_reqs(struct vscsibk_info *info,
-   struct vscsiif_request *ring_req,
-   struct vscsibk_pend *pending_req)
+static struct vscsibk_pend *scsiback_get_pend_req(struct vscsiif_back_ring 
*ring,
+   struct v2p_entry *v2p)
+{
+   struct scsiback_tpg *tpg = v2p->tpg;
+   struct scsiback_nexus *nexus = tpg->tpg_nexus;
+   struct se_session *se_sess = nexus->tvn_se_sess;
+   struct vscsibk_pend *req;
+   int tag, i;
+
+   tag = percpu_ida_alloc(_sess->sess_tag_pool, TASK_RUNNING);
+   if (tag < 0) {
+   pr_err("Unable to obtain tag for vscsiif_request\n");
+   return ERR_PTR(-ENOMEM);
+   }
+
+   req = &((struct vscsibk_pend *)se_sess->sess_cmd_map)[tag];
+   memset(req, 0, sizeof(*req));
+   req->se_cmd.map_tag = tag;
+
+   for (i = 0; i < VSCSI_MAX_GRANTS; i++)
+   req->grant_handles[i] = SCSIBACK_INVALID_HANDLE;
+
+   return req;
+}
+
+static struct vscsibk_pend *prepare_pending_reqs(struct vscsibk_info *info,
+   struct vscsiif_back_ring *ring,
+   struct vscsiif_request *ring_req)
 {
+   struct vscsibk_pend *pending_req;
struct v2p_entry *v2p;
struct ids_tuple vir;
 
-   pending_req->rqid   = ring_req->rqid;
-   pending_req->info   = info;
+   /* request range check from frontend */
+   if ((ring_req->sc_data_direction != DMA_BIDIRECTIONAL) &&
+   (ring_req->sc_data_direction != DMA_TO_DEVICE) &&
+   (ring_req->sc_data_direction 

[PATCH-v2 12/12] xen-scsiback: Convert to TARGET_SCF_ACK_KREF I/O krefs

2016-01-25 Thread Nicholas A. Bellinger
From: Nicholas Bellinger 

Cc: Juergen Gross 
Cc: Hannes Reinecke 
Cc: David Vrabel 
Signed-off-by: Nicholas Bellinger 
---
 drivers/xen/xen-scsiback.c | 53 +++---
 1 file changed, 26 insertions(+), 27 deletions(-)

diff --git a/drivers/xen/xen-scsiback.c b/drivers/xen/xen-scsiback.c
index 640fb22..a10e5f1 100644
--- a/drivers/xen/xen-scsiback.c
+++ b/drivers/xen/xen-scsiback.c
@@ -381,6 +381,12 @@ static void scsiback_cmd_done(struct vscsibk_pend 
*pending_req)
scsiback_do_resp_with_sense(sense_buffer, errors, resid, pending_req,
pending_req->rqid);
scsiback_put(info);
+   /*
+* Drop the extra KREF_ACK reference taken by 
target_submit_cmd_map_sgls()
+* ahead of scsiback_check_stop_free() ->  transport_generic_free_cmd()
+* final se_cmd->cmd_kref put.
+*/
+   target_put_sess_cmd(_req->se_cmd);
 }
 
 static void scsiback_cmd_exec(struct vscsibk_pend *pending_req)
@@ -398,7 +404,7 @@ static void scsiback_cmd_exec(struct vscsibk_pend 
*pending_req)
rc = target_submit_cmd_map_sgls(se_cmd, sess, pending_req->cmnd,
pending_req->sense_buffer, pending_req->v2p->lun,
pending_req->data_len, 0,
-   pending_req->sc_data_direction, 0,
+   pending_req->sc_data_direction, TARGET_SCF_ACK_KREF,
pending_req->sgl, pending_req->n_sg,
NULL, 0, NULL, 0);
if (rc < 0) {
@@ -587,31 +593,28 @@ static void scsiback_disconnect(struct vscsibk_info *info)
 static void scsiback_device_action(struct vscsibk_pend *pending_req,
enum tcm_tmreq_table act, int tag)
 {
-   int rc, err = FAILED;
struct scsiback_tpg *tpg = pending_req->v2p->tpg;
+   struct scsiback_nexus *nexus = tpg->tpg_nexus;
struct se_cmd *se_cmd = _req->se_cmd;
struct scsiback_tmr *tmr;
+   u64 unpacked_lun = pending_req->v2p->lun;
+   int rc, err = FAILED;
 
tmr = kzalloc(sizeof(struct scsiback_tmr), GFP_KERNEL);
-   if (!tmr)
-   goto out;
+   if (!tmr) {
+   target_put_sess_cmd(se_cmd);
+   goto err;
+   }
 
init_waitqueue_head(>tmr_wait);
 
-   transport_init_se_cmd(se_cmd, tpg->se_tpg.se_tpg_tfo,
-   tpg->tpg_nexus->tvn_se_sess, 0, DMA_NONE, TCM_SIMPLE_TAG,
-   _req->sense_buffer[0]);
-
-   rc = core_tmr_alloc_req(se_cmd, tmr, act, GFP_KERNEL);
-   if (rc < 0)
-   goto out;
-
-   se_cmd->se_tmr_req->ref_task_tag = tag;
+   rc = target_submit_tmr(_req->se_cmd, nexus->tvn_se_sess,
+  _req->sense_buffer[0],
+  unpacked_lun, tmr, act, GFP_KERNEL,
+  tag, TARGET_SCF_ACK_KREF);
+   if (rc)
+   goto err;
 
-   if (transport_lookup_tmr_lun(se_cmd, pending_req->v2p->lun) < 0)
-   goto out;
-
-   transport_generic_handle_tmr(se_cmd);
wait_event(tmr->tmr_wait, atomic_read(>tmr_complete));
 
err = (se_cmd->se_tmr_req->response == TMR_FUNCTION_COMPLETE) ?
@@ -1368,16 +1371,7 @@ static u32 scsiback_tpg_get_inst_index(struct 
se_portal_group *se_tpg)
 
 static int scsiback_check_stop_free(struct se_cmd *se_cmd)
 {
-   /*
-* Do not release struct se_cmd's containing a valid TMR pointer.
-* These will be released directly in scsiback_device_action()
-* with transport_generic_free_cmd().
-*/
-   if (se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)
-   return 0;
-
-   transport_generic_free_cmd(se_cmd, 0);
-   return 1;
+   return transport_generic_free_cmd(se_cmd, 0);
 }
 
 static void scsiback_release_cmd(struct se_cmd *se_cmd)
@@ -1385,6 +1379,11 @@ static void scsiback_release_cmd(struct se_cmd *se_cmd)
struct se_session *se_sess = se_cmd->se_sess;
struct se_tmr_req *se_tmr = se_cmd->se_tmr_req;
 
+   if (se_tmr && se_cmd->se_cmd_flags & SCF_SCSI_TMR_CDB) {
+   struct scsiback_tmr *tmr = se_tmr->fabric_tmr_ptr;
+   kfree(tmr);
+   }
+
percpu_ida_free(_sess->sess_tag_pool, se_cmd->map_tag);
 }
 
-- 
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-v2 10/12] usb-gadget/tcm: Convert to TARGET_SCF_ACK_KREF I/O krefs

2016-01-25 Thread Nicholas A. Bellinger
From: Nicholas Bellinger 

This patch drops struct usbg_cmd->kref internal kref-erence
usage, for proper TARGET_SCF_ACK_KREF conversion.

Cc: Sebastian Andrzej Siewior 
Cc: Andrzej Pietrasiewicz 
Signed-off-by: Nicholas Bellinger 
---
 drivers/usb/gadget/function/f_tcm.c | 51 -
 1 file changed, 11 insertions(+), 40 deletions(-)

diff --git a/drivers/usb/gadget/function/f_tcm.c 
b/drivers/usb/gadget/function/f_tcm.c
index 8773572..7276a73 100644
--- a/drivers/usb/gadget/function/f_tcm.c
+++ b/drivers/usb/gadget/function/f_tcm.c
@@ -41,13 +41,6 @@ static inline struct f_uas *to_f_uas(struct usb_function *f)
return container_of(f, struct f_uas, function);
 }
 
-static void usbg_cmd_release(struct kref *);
-
-static inline void usbg_cleanup_cmd(struct usbg_cmd *cmd)
-{
-   kref_put(>ref, usbg_cmd_release);
-}
-
 /* Start bot.c code */
 
 static int bot_enqueue_cmd_cbw(struct f_uas *fu)
@@ -68,7 +61,7 @@ static void bot_status_complete(struct usb_ep *ep, struct 
usb_request *req)
struct usbg_cmd *cmd = req->context;
struct f_uas *fu = cmd->fu;
 
-   usbg_cleanup_cmd(cmd);
+   transport_generic_free_cmd(>se_cmd, 0);
if (req->status < 0) {
pr_err("ERR %s(%d)\n", __func__, __LINE__);
return;
@@ -605,7 +598,7 @@ static void uasp_status_data_cmpl(struct usb_ep *ep, struct 
usb_request *req)
break;
 
case UASP_QUEUE_COMMAND:
-   usbg_cleanup_cmd(cmd);
+   transport_generic_free_cmd(>se_cmd, 0);
usb_ep_queue(fu->ep_cmd, fu->cmd.req, GFP_ATOMIC);
break;
 
@@ -615,7 +608,7 @@ static void uasp_status_data_cmpl(struct usb_ep *ep, struct 
usb_request *req)
return;
 
 cleanup:
-   usbg_cleanup_cmd(cmd);
+   transport_generic_free_cmd(>se_cmd, 0);
 }
 
 static int uasp_send_status_response(struct usbg_cmd *cmd)
@@ -977,7 +970,7 @@ static void usbg_data_write_cmpl(struct usb_ep *ep, struct 
usb_request *req)
return;
 
 cleanup:
-   usbg_cleanup_cmd(cmd);
+   transport_generic_free_cmd(>se_cmd, 0);
 }
 
 static int usbg_prepare_w_request(struct usbg_cmd *cmd, struct usb_request 
*req)
@@ -1046,7 +1039,7 @@ static void usbg_cmd_work(struct work_struct *work)
struct se_cmd *se_cmd;
struct tcm_usbg_nexus *tv_nexus;
struct usbg_tpg *tpg;
-   int dir;
+   int dir, flags = (TARGET_SCF_UNKNOWN_SIZE | TARGET_SCF_ACK_KREF);
 
se_cmd = >se_cmd;
tpg = cmd->fu->tpg;
@@ -1060,9 +1053,9 @@ static void usbg_cmd_work(struct work_struct *work)
goto out;
}
 
-   if (target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess,
-   cmd->cmd_buf, cmd->sense_iu.sense, cmd->unpacked_lun,
-   0, cmd->prio_attr, dir, TARGET_SCF_UNKNOWN_SIZE) < 0)
+   if (target_submit_cmd(se_cmd, tv_nexus->tvn_se_sess, cmd->cmd_buf,
+ cmd->sense_iu.sense, cmd->unpacked_lun, 0,
+ cmd->prio_attr, dir, flags) < 0)
goto out;
 
return;
@@ -1070,7 +1063,7 @@ static void usbg_cmd_work(struct work_struct *work)
 out:
transport_send_check_condition_and_sense(se_cmd,
TCM_UNSUPPORTED_SCSI_OPCODE, 1);
-   usbg_cleanup_cmd(cmd);
+   transport_generic_free_cmd(>se_cmd, 0);
 }
 
 static struct usbg_cmd *usbg_get_cmd(struct f_uas *fu,
@@ -1125,11 +1118,6 @@ static int usbg_submit_command(struct f_uas *fu,
pr_err("usbg_get_cmd failed\n");
return -ENOMEM;
}
-
-   /* XXX until I figure out why I can't free in on complete */
-   kref_init(>ref);
-   kref_get(>ref);
-
memcpy(cmd->cmd_buf, cmd_iu->cdb, cmd_len);
 
if (fu->flags & USBG_USE_STREAMS) {
@@ -1202,7 +1190,7 @@ static void bot_cmd_work(struct work_struct *work)
 out:
transport_send_check_condition_and_sense(se_cmd,
TCM_UNSUPPORTED_SCSI_OPCODE, 1);
-   usbg_cleanup_cmd(cmd);
+   transport_generic_free_cmd(>se_cmd, 0);
 }
 
 static int bot_submit_command(struct f_uas *fu,
@@ -1238,11 +1226,6 @@ static int bot_submit_command(struct f_uas *fu,
pr_err("usbg_get_cmd failed\n");
return -ENOMEM;
}
-
-   /* XXX until I figure out why I can't free in on complete */
-   kref_init(>ref);
-   kref_get(>ref);
-
memcpy(cmd->cmd_buf, cbw->CDB, cmd_len);
 
cmd->bot_tag = cbw->Tag;
@@ -1296,14 +1279,6 @@ static u32 usbg_tpg_get_inst_index(struct 
se_portal_group *se_tpg)
return 1;
 }
 
-static void usbg_cmd_release(struct kref *ref)
-{
-   struct usbg_cmd *cmd = container_of(ref, struct usbg_cmd,
-   ref);
-
-   transport_generic_free_cmd(>se_cmd, 0);
-}
-
 static void usbg_release_cmd(struct se_cmd 

[PATCH-v2 05/12] tcm_fc: Convert to target_alloc_session usage

2016-01-25 Thread Nicholas A. Bellinger
From: Nicholas Bellinger 

Cc: Vasu Dev 
Signed-off-by: Nicholas Bellinger 
---
 drivers/target/tcm_fc/tfc_sess.c | 44 
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c
index e19f4c5..d0c3e18 100644
--- a/drivers/target/tcm_fc/tfc_sess.c
+++ b/drivers/target/tcm_fc/tfc_sess.c
@@ -186,6 +186,20 @@ out:
return NULL;
 }
 
+static int ft_sess_alloc_cb(struct se_portal_group *se_tpg,
+   struct se_session *se_sess, void *p)
+{
+   struct ft_sess *sess = p;
+   struct ft_tport *tport = sess->tport;
+   struct hlist_head *head = >hash[ft_sess_hash(sess->port_id)];
+
+   pr_debug("port_id %x sess %p\n", sess->port_id, sess);
+   hlist_add_head_rcu(>hash, head);
+   tport->sess_count++;
+
+   return 0;
+}
+
 /*
  * Allocate session and enter it in the hash for the local port.
  * Caller holds ft_lport_lock.
@@ -194,7 +208,6 @@ static struct ft_sess *ft_sess_create(struct ft_tport 
*tport, u32 port_id,
  struct fc_rport_priv *rdata)
 {
struct se_portal_group *se_tpg = >tpg->se_tpg;
-   struct se_node_acl *se_acl;
struct ft_sess *sess;
struct hlist_head *head;
unsigned char initiatorname[TRANSPORT_IQN_LEN];
@@ -210,31 +223,18 @@ static struct ft_sess *ft_sess_create(struct ft_tport 
*tport, u32 port_id,
if (!sess)
return NULL;
 
-   sess->se_sess = transport_init_session_tags(TCM_FC_DEFAULT_TAGS,
-   sizeof(struct ft_cmd),
-   TARGET_PROT_NORMAL);
-   if (IS_ERR(sess->se_sess)) {
-   kfree(sess);
-   return NULL;
-   }
+   kref_init(>kref); /* ref for table entry */
+   sess->tport = tport;
+   sess->port_id = port_id;
 
-   se_acl = core_tpg_get_initiator_node_acl(se_tpg, [0]);
-   if (!se_acl) {
-   transport_free_session(sess->se_sess);
+   sess->se_sess = target_alloc_session(se_tpg, TCM_FC_DEFAULT_TAGS,
+sizeof(struct ft_cmd),
+TARGET_PROT_NORMAL, 
[0],
+sess, ft_sess_alloc_cb);
+   if (IS_ERR(sess->se_sess)) {
kfree(sess);
return NULL;
}
-   sess->se_sess->se_node_acl = se_acl;
-   sess->tport = tport;
-   sess->port_id = port_id;
-   kref_init(>kref); /* ref for table entry */
-   hlist_add_head_rcu(>hash, head);
-   tport->sess_count++;
-
-   pr_debug("port_id %x sess %p\n", port_id, sess);
-
-   transport_register_session(>tpg->se_tpg, se_acl,
-  sess->se_sess, sess);
return sess;
 }
 
-- 
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-v2 07/12] sbp-target: Conversion to percpu_ida tag pre-allocation

2016-01-25 Thread Nicholas A. Bellinger
From: Nicholas Bellinger 

Cc: Chris Boot 
Cc: Christoph Hellwig 
Cc: Hannes Reinecke 
Signed-off-by: Nicholas Bellinger 
---
 drivers/target/sbp/sbp_target.c | 38 +-
 1 file changed, 33 insertions(+), 5 deletions(-)

diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c
index ddd3398..756e87f 100644
--- a/drivers/target/sbp/sbp_target.c
+++ b/drivers/target/sbp/sbp_target.c
@@ -209,8 +209,10 @@ static struct sbp_session *sbp_session_create(
INIT_DELAYED_WORK(>maint_work, session_maintenance_work);
sess->guid = guid;
 
-   sess->se_sess = target_alloc_session(>se_tpg, 0, 0, 
TARGET_PROT_NORMAL,
-guid_str, sess, NULL);
+   sess->se_sess = target_alloc_session(>se_tpg, 128,
+sizeof(struct sbp_target_request),
+TARGET_PROT_NORMAL, guid_str,
+sess, NULL);
if (IS_ERR(sess->se_sess)) {
pr_err("failed to init se_session\n");
ret = PTR_ERR(sess->se_sess);
@@ -921,6 +923,24 @@ static inline bool tgt_agent_check_active(struct 
sbp_target_agent *agent)
return active;
 }
 
+static struct sbp_target_request *sbp_mgt_get_req(struct sbp_session *sess,
+   struct fw_card *card, u64 next_orb)
+{
+   struct se_session *se_sess = sess->se_sess;
+   struct sbp_target_request *req;
+   int tag;
+
+   tag = percpu_ida_alloc(_sess->sess_tag_pool, GFP_ATOMIC);
+   if (tag < 0)
+   return ERR_PTR(-ENOMEM);
+
+   req = &((struct sbp_target_request *)se_sess->sess_cmd_map)[tag];
+   req->se_cmd.map_tag = tag;
+   req->se_cmd.tag = next_orb;
+
+   return req;
+}
+
 static void tgt_agent_fetch_work(struct work_struct *work)
 {
struct sbp_target_agent *agent =
@@ -932,7 +952,7 @@ static void tgt_agent_fetch_work(struct work_struct *work)
u64 next_orb = agent->orb_pointer;
 
while (next_orb && tgt_agent_check_active(agent)) {
-   req = kzalloc(sizeof(*req), GFP_KERNEL);
+   req = sbp_mgt_get_req(sess, sess->card, next_orb);
if (!req) {
spin_lock_bh(>lock);
agent->state = AGENT_STATE_DEAD;
@@ -1430,9 +1450,13 @@ static int sbp_send_sense(struct sbp_target_request *req)
 
 static void sbp_free_request(struct sbp_target_request *req)
 {
+   struct se_cmd *se_cmd = >se_cmd;
+   struct se_session *se_sess = se_cmd->se_sess;
+
kfree(req->pg_tbl);
kfree(req->cmd_buf);
-   kfree(req);
+
+   percpu_ida_free(_sess->sess_tag_pool, se_cmd->map_tag);
 }
 
 static void sbp_mgt_agent_process(struct work_struct *work)
@@ -1592,8 +1616,12 @@ static void sbp_mgt_agent_rw(struct fw_card *card,
rcode = RCODE_CONFLICT_ERROR;
goto out;
}
-
+   // XXX:
+#if 0
+   req = sbp_mgt_get_req(agent->login->sess, card);
+#else
req = kzalloc(sizeof(*req), GFP_ATOMIC);
+#endif
if (!req) {
rcode = RCODE_CONFLICT_ERROR;
goto 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


Re: [PATCH] storvsc: use small sg_tablesize on x86

2016-01-25 Thread Olaf Hering
On Fri, Oct 02, Olaf Hering wrote:

> On Thu, Oct 01, James Bottomley wrote:
> 
> > On Thu, 2015-10-01 at 20:30 +, KY Srinivasan wrote:
> 
> > > > +#if defined(CONFIG_X86_32)
> 
> > Um, this is a bit architecture specific (I know Azure is x86, but
> > still).  Can you make the define check CONFIG_32BIT rather than
> > CONFIG_X86_32?
> 
> According to arch/x86/Kconfig there is no such thing.

What is the status of this change? Looks like there is nothing more to
do on my side.

Olaf
--
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 00/12] target: target_alloc_session w/ percpu_ida+ACK_KREF conversion

2016-01-25 Thread Nicholas A. Bellinger
From: Nicholas Bellinger 

Hi folks,

Here is -v2 series code for target_alloc_session() helper
support using existing percpu-ida tag pre-allocation, along
with a new (*callback)() for allowing fabric driver code
to complete ahead of transport_register_session() finishing
I_T nexus setup.

This includes a tree-wide fabric driver conversion to use
use target_alloc_session() + associated (*callback)() with
common code.

Also as per HCH, it contains sbp-target, usb-gadget/tcm
and xen-scsiback driver percpu_ida tag pre-allocation
conversions, along with initial TARGET_SCF_ACK_KREF
support for v4.6-rc code.

Please review.

--nab

Christoph Hellwig (1):
  target: Convert demo-mode only drivers to target_alloc_session

Nicholas Bellinger (11):
  target: Add target_alloc_session() helper function
  vhost/scsi: Convert to target_alloc_session usage
  tcm_qla2xxx: Convert to target_alloc_session usage
  tcm_fc: Convert to target_alloc_session usage
  ib_srpt: Convert to target_alloc_session usage
  sbp-target: Conversion to percpu_ida tag pre-allocation
  sbp-target: Convert to TARGET_SCF_ACK_KREF I/O krefs
  usb-gadget/tcm: Conversion to percpu_ida tag pre-allocation
  usb-gadget/tcm: Convert to TARGET_SCF_ACK_KREF I/O krefs
  xen-scsiback: Convert to percpu_ida tag allocation
  xen-scsiback: Convert to TARGET_SCF_ACK_KREF I/O krefs

 drivers/infiniband/ulp/srpt/ib_srpt.c  |  23 +--
 drivers/scsi/qla2xxx/qla_target.c  |   8 +-
 drivers/scsi/qla2xxx/qla_target.h  |   2 +-
 drivers/scsi/qla2xxx/tcm_qla2xxx.c |  79 +-
 drivers/target/loopback/tcm_loop.c |  35 +
 drivers/target/sbp/sbp_target.c|  97 ++--
 drivers/target/target_core_transport.c |  56 +++
 drivers/target/tcm_fc/tfc_sess.c   |  44 +++---
 drivers/usb/gadget/function/f_tcm.c| 181 ++
 drivers/vhost/scsi.c   |  99 +---
 drivers/xen/xen-scsiback.c | 265 -
 include/target/target_core_fabric.h|   6 +
 12 files changed, 437 insertions(+), 458 deletions(-)

-- 
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-v2 01/12] target: Add target_alloc_session() helper function

2016-01-25 Thread Nicholas A. Bellinger
From: Nicholas Bellinger 

Based on HCH's original patch, this adds a full version to
support percpu-ida tag pre-allocation and callback function
pointer into fabric driver code to complete session setup.

Reported-by: Christoph Hellwig 
Cc: Sagi Grimberg 
Cc: Christoph Hellwig 
Cc: Hannes Reinecke 
Cc: Andy Grover 
Signed-off-by: Nicholas Bellinger 
---
 drivers/target/target_core_transport.c | 56 ++
 include/target/target_core_fabric.h|  6 
 2 files changed, 62 insertions(+)

diff --git a/drivers/target/target_core_transport.c 
b/drivers/target/target_core_transport.c
index 6235067..5609f91 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -281,6 +281,17 @@ struct se_session *transport_init_session_tags(unsigned 
int tag_num,
struct se_session *se_sess;
int rc;
 
+   if (tag_num != 0 && !tag_size) {
+   pr_err("init_session_tags called with percpu-ida tag_num:"
+  " %u, but zero tag_size\n", tag_num);
+   return ERR_PTR(-EINVAL);
+   }
+   if (!tag_num && tag_size) {
+   pr_err("init_session_tags called with percpu-ida tag_size:"
+  " %u, but zero tag_num\n", tag_size);
+   return ERR_PTR(-EINVAL);
+   }
+
se_sess = transport_init_session(sup_prot_ops);
if (IS_ERR(se_sess))
return se_sess;
@@ -374,6 +385,51 @@ void transport_register_session(
 }
 EXPORT_SYMBOL(transport_register_session);
 
+struct se_session *
+target_alloc_session(struct se_portal_group *tpg,
+unsigned int tag_num, unsigned int tag_size,
+enum target_prot_op prot_op,
+const char *initiatorname, void *private,
+int (*callback)(struct se_portal_group *,
+struct se_session *, void *))
+{
+   struct se_session *sess;
+
+   /*
+* If the fabric driver is using percpu-ida based pre allocation
+* of I/O descriptor tags, go ahead and perform that setup now..
+*/
+   if (tag_num != 0)
+   sess = transport_init_session_tags(tag_num, tag_size, prot_op);
+   else
+   sess = transport_init_session(prot_op);
+
+   if (IS_ERR(sess))
+   return sess;
+
+   sess->se_node_acl = core_tpg_check_initiator_node_acl(tpg,
+   (unsigned char *)initiatorname);
+   if (!sess->se_node_acl) {
+   transport_free_session(sess);
+   return ERR_PTR(-EACCES);
+   }
+   /*
+* Go ahead and perform any remaining fabric setup that is
+* required before transport_register_session().
+*/
+   if (callback != NULL) {
+   int rc = callback(tpg, sess, private);
+   if (rc) {
+   transport_free_session(sess);
+   return ERR_PTR(rc);
+   }
+   }
+
+   transport_register_session(tpg, sess->se_node_acl, sess, private);
+   return sess;
+}
+EXPORT_SYMBOL(target_alloc_session);
+
 static void target_release_session(struct kref *kref)
 {
struct se_session *se_sess = container_of(kref,
diff --git a/include/target/target_core_fabric.h 
b/include/target/target_core_fabric.h
index 5665340..685a51a 100644
--- a/include/target/target_core_fabric.h
+++ b/include/target/target_core_fabric.h
@@ -108,6 +108,12 @@ void target_unregister_template(const struct 
target_core_fabric_ops *fo);
 int target_depend_item(struct config_item *item);
 void target_undepend_item(struct config_item *item);
 
+struct se_session *target_alloc_session(struct se_portal_group *,
+   unsigned int, unsigned int, enum target_prot_op prot_op,
+   const char *, void *,
+   int (*callback)(struct se_portal_group *,
+   struct se_session *, void *));
+
 struct se_session *transport_init_session(enum target_prot_op);
 int transport_alloc_session_tags(struct se_session *, unsigned int,
unsigned int);
-- 
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-v2 02/12] target: Convert demo-mode only drivers to target_alloc_session

2016-01-25 Thread Nicholas A. Bellinger
From: Christoph Hellwig 

Cc: Christoph Hellwig 
Cc: Hannes Reinecke 
Cc: Chris Boot 
Cc: Sebastian Andrzej Siewior 
Cc: Andrzej Pietrasiewicz 
Cc: Juergen Gross 
Signed-off-by: Nicholas Bellinger 
---
 drivers/target/loopback/tcm_loop.c  | 35 +
 drivers/target/sbp/sbp_target.c | 33 ++--
 drivers/usb/gadget/function/f_tcm.c | 45 ++--
 drivers/xen/xen-scsiback.c  | 51 ++---
 4 files changed, 42 insertions(+), 122 deletions(-)

diff --git a/drivers/target/loopback/tcm_loop.c 
b/drivers/target/loopback/tcm_loop.c
index d41a5c3..0216c75 100644
--- a/drivers/target/loopback/tcm_loop.c
+++ b/drivers/target/loopback/tcm_loop.c
@@ -806,54 +806,33 @@ static int tcm_loop_make_nexus(
struct tcm_loop_tpg *tl_tpg,
const char *name)
 {
-   struct se_portal_group *se_tpg;
struct tcm_loop_hba *tl_hba = tl_tpg->tl_hba;
struct tcm_loop_nexus *tl_nexus;
-   int ret = -ENOMEM;
 
if (tl_tpg->tl_nexus) {
pr_debug("tl_tpg->tl_nexus already exists\n");
return -EEXIST;
}
-   se_tpg = _tpg->tl_se_tpg;
 
tl_nexus = kzalloc(sizeof(struct tcm_loop_nexus), GFP_KERNEL);
if (!tl_nexus) {
pr_err("Unable to allocate struct tcm_loop_nexus\n");
return -ENOMEM;
}
-   /*
-* Initialize the struct se_session pointer
-*/
-   tl_nexus->se_sess = transport_init_session(
-   TARGET_PROT_DIN_PASS | TARGET_PROT_DOUT_PASS);
+
+   tl_nexus->se_sess = target_alloc_session(_tpg->tl_se_tpg, 0, 0,
+   TARGET_PROT_DIN_PASS | 
TARGET_PROT_DOUT_PASS,
+   name, tl_nexus, NULL);
if (IS_ERR(tl_nexus->se_sess)) {
-   ret = PTR_ERR(tl_nexus->se_sess);
-   goto out;
-   }
-   /*
-* Since we are running in 'demo mode' this call with generate a
-* struct se_node_acl for the tcm_loop struct se_portal_group with the 
SCSI
-* Initiator port name of the passed configfs group 'name'.
-*/
-   tl_nexus->se_sess->se_node_acl = core_tpg_check_initiator_node_acl(
-   se_tpg, (unsigned char *)name);
-   if (!tl_nexus->se_sess->se_node_acl) {
-   transport_free_session(tl_nexus->se_sess);
-   goto out;
+   kfree(tl_nexus);
+   return PTR_ERR(tl_nexus->se_sess);
}
-   /* Now, register the I_T Nexus as active. */
-   transport_register_session(se_tpg, tl_nexus->se_sess->se_node_acl,
-   tl_nexus->se_sess, tl_nexus);
+
tl_tpg->tl_nexus = tl_nexus;
pr_debug("TCM_Loop_ConfigFS: Established I_T Nexus to emulated"
" %s Initiator Port: %s\n", tcm_loop_dump_proto_id(tl_hba),
name);
return 0;
-
-out:
-   kfree(tl_nexus);
-   return ret;
 }
 
 static int tcm_loop_drop_nexus(
diff --git a/drivers/target/sbp/sbp_target.c b/drivers/target/sbp/sbp_target.c
index 3072f1a..ddd3398 100644
--- a/drivers/target/sbp/sbp_target.c
+++ b/drivers/target/sbp/sbp_target.c
@@ -196,45 +196,28 @@ static struct sbp_session *sbp_session_create(
struct sbp_session *sess;
int ret;
char guid_str[17];
-   struct se_node_acl *se_nacl;
+
+   snprintf(guid_str, sizeof(guid_str), "%016llx", guid);
 
sess = kmalloc(sizeof(*sess), GFP_KERNEL);
if (!sess) {
pr_err("failed to allocate session descriptor\n");
return ERR_PTR(-ENOMEM);
}
+   spin_lock_init(>lock);
+   INIT_LIST_HEAD(>login_list);
+   INIT_DELAYED_WORK(>maint_work, session_maintenance_work);
+   sess->guid = guid;
 
-   sess->se_sess = transport_init_session(TARGET_PROT_NORMAL);
+   sess->se_sess = target_alloc_session(>se_tpg, 0, 0, 
TARGET_PROT_NORMAL,
+guid_str, sess, NULL);
if (IS_ERR(sess->se_sess)) {
pr_err("failed to init se_session\n");
-
ret = PTR_ERR(sess->se_sess);
kfree(sess);
return ERR_PTR(ret);
}
 
-   snprintf(guid_str, sizeof(guid_str), "%016llx", guid);
-
-   se_nacl = core_tpg_check_initiator_node_acl(>se_tpg, guid_str);
-   if (!se_nacl) {
-   pr_warn("Node ACL not found for %s\n", guid_str);
-
-   transport_free_session(sess->se_sess);
-   kfree(sess);
-
-   return ERR_PTR(-EPERM);
-   }
-
-   sess->se_sess->se_node_acl = se_nacl;
-
-   spin_lock_init(>lock);
-   INIT_LIST_HEAD(>login_list);
-   INIT_DELAYED_WORK(>maint_work, session_maintenance_work);
-

[PATCH-v2 03/12] vhost/scsi: Convert to target_alloc_session usage

2016-01-25 Thread Nicholas A. Bellinger
From: Nicholas Bellinger 

Acked-by: Michael S. Tsirkin 
Signed-off-by: Nicholas Bellinger 
---
 drivers/vhost/scsi.c | 99 ++--
 1 file changed, 41 insertions(+), 58 deletions(-)

diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 29cfc57..cd5f20f 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -1664,8 +1664,7 @@ static void vhost_scsi_port_unlink(struct se_portal_group 
*se_tpg,
mutex_unlock(_scsi_mutex);
 }
 
-static void vhost_scsi_free_cmd_map_res(struct vhost_scsi_nexus *nexus,
-  struct se_session *se_sess)
+static void vhost_scsi_free_cmd_map_res(struct se_session *se_sess)
 {
struct vhost_scsi_cmd *tv_cmd;
unsigned int i;
@@ -1721,98 +1720,82 @@ static struct configfs_attribute 
*vhost_scsi_tpg_attrib_attrs[] = {
NULL,
 };
 
-static int vhost_scsi_make_nexus(struct vhost_scsi_tpg *tpg,
-   const char *name)
+static int vhost_scsi_nexus_cb(struct se_portal_group *se_tpg,
+  struct se_session *se_sess, void *p)
 {
-   struct se_portal_group *se_tpg;
-   struct se_session *se_sess;
-   struct vhost_scsi_nexus *tv_nexus;
struct vhost_scsi_cmd *tv_cmd;
unsigned int i;
 
-   mutex_lock(>tv_tpg_mutex);
-   if (tpg->tpg_nexus) {
-   mutex_unlock(>tv_tpg_mutex);
-   pr_debug("tpg->tpg_nexus already exists\n");
-   return -EEXIST;
-   }
-   se_tpg = >se_tpg;
-
-   tv_nexus = kzalloc(sizeof(struct vhost_scsi_nexus), GFP_KERNEL);
-   if (!tv_nexus) {
-   mutex_unlock(>tv_tpg_mutex);
-   pr_err("Unable to allocate struct vhost_scsi_nexus\n");
-   return -ENOMEM;
-   }
-   /*
-*  Initialize the struct se_session pointer and setup tagpool
-*  for struct vhost_scsi_cmd descriptors
-*/
-   tv_nexus->tvn_se_sess = transport_init_session_tags(
-   VHOST_SCSI_DEFAULT_TAGS,
-   sizeof(struct vhost_scsi_cmd),
-   TARGET_PROT_DIN_PASS | 
TARGET_PROT_DOUT_PASS);
-   if (IS_ERR(tv_nexus->tvn_se_sess)) {
-   mutex_unlock(>tv_tpg_mutex);
-   kfree(tv_nexus);
-   return -ENOMEM;
-   }
-   se_sess = tv_nexus->tvn_se_sess;
for (i = 0; i < VHOST_SCSI_DEFAULT_TAGS; i++) {
tv_cmd = &((struct vhost_scsi_cmd *)se_sess->sess_cmd_map)[i];
 
tv_cmd->tvc_sgl = kzalloc(sizeof(struct scatterlist) *
VHOST_SCSI_PREALLOC_SGLS, GFP_KERNEL);
if (!tv_cmd->tvc_sgl) {
-   mutex_unlock(>tv_tpg_mutex);
pr_err("Unable to allocate tv_cmd->tvc_sgl\n");
goto out;
}
 
tv_cmd->tvc_upages = kzalloc(sizeof(struct page *) *
-   VHOST_SCSI_PREALLOC_UPAGES, GFP_KERNEL);
+   VHOST_SCSI_PREALLOC_UPAGES, GFP_KERNEL);
if (!tv_cmd->tvc_upages) {
-   mutex_unlock(>tv_tpg_mutex);
pr_err("Unable to allocate tv_cmd->tvc_upages\n");
goto out;
}
 
tv_cmd->tvc_prot_sgl = kzalloc(sizeof(struct scatterlist) *
-   VHOST_SCSI_PREALLOC_PROT_SGLS, 
GFP_KERNEL);
+   VHOST_SCSI_PREALLOC_PROT_SGLS, GFP_KERNEL);
if (!tv_cmd->tvc_prot_sgl) {
-   mutex_unlock(>tv_tpg_mutex);
pr_err("Unable to allocate tv_cmd->tvc_prot_sgl\n");
goto out;
}
}
+   return 0;
+out:
+   vhost_scsi_free_cmd_map_res(se_sess);
+   return -ENOMEM;
+}
+
+static int vhost_scsi_make_nexus(struct vhost_scsi_tpg *tpg,
+   const char *name)
+{
+   struct se_portal_group *se_tpg;
+   struct vhost_scsi_nexus *tv_nexus;
+
+   mutex_lock(>tv_tpg_mutex);
+   if (tpg->tpg_nexus) {
+   mutex_unlock(>tv_tpg_mutex);
+   pr_debug("tpg->tpg_nexus already exists\n");
+   return -EEXIST;
+   }
+   se_tpg = >se_tpg;
+
+   tv_nexus = kzalloc(sizeof(struct vhost_scsi_nexus), GFP_KERNEL);
+   if (!tv_nexus) {
+   mutex_unlock(>tv_tpg_mutex);
+   pr_err("Unable to allocate struct vhost_scsi_nexus\n");
+   return -ENOMEM;
+   }
/*
 * Since we are running in 'demo mode' this call with generate a
 * struct se_node_acl for the vhost_scsi struct se_portal_group with
 * the SCSI Initiator port name of the passed configfs group 'name'.
 */
-   

Re: [PATCH] drivers/scsi/emcctd: drivers/scsi/emcctd: Client driver implementation for EMC-Symmetrix GuestOS emulated Cut-Through Device

2016-01-25 Thread Johannes Thumshirn
On Sat, Jan 23, 2016 at 05:51:50AM +, Singhal, Maneesh wrote:
> Thanks for your time. My replies inlined...
> 

[...]

> > > + }
> > > +
> > 
> > You don't do any cleanup work at
> > ctd_scsi_response_sanity_check_complete. You
> > could just reutrn 0 here as well. 
> [MS>] Just avoiding multiple exit points from the function

Please have a look at Documentation/CodingStyle Chapter 7: Centralized exiting 
of functions. Especially this part:


The goto statement comes in handy when a function exits from multiple
locations and some common work such as cleanup has to be done.  If there is no
cleanup needed then just return directly.


and the example below that section.

> > 
> > > +
> > > + ctd_dprintk_crit(

[...]

> > > + if (request && request->io_timeout < EMCCTD_MAX_RETRY) {
> > 
> > The following block is a bit long and therefore it's hard to spot an
> > eventual
> > error of handling the io_mgmt_lock. Can't it be factored out in a helper
> > function?
> > 
> [MS>] I know its little longer, but actually fits logically together... Will 
> see if it can be factored. Not sure though.

Yes please. It's not uber important but short functions and paths are
generally favoured when debugging and reviewing code.


Thanks,
Johannes

-- 
Johannes Thumshirn  Storage
jthumsh...@suse.de+49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
--
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] scsi: Allow activation of scsi-mq per-driver

2016-01-25 Thread Christoph Hellwig
On Fri, Jan 22, 2016 at 02:41:28PM +0100, Johannes Thumshirn wrote:
> Allow the activation of the scsi-mq feature on a per-driver bassis as opposed
> to the current stack global (de)activation.
> 
> This allows us to have setups which can combine "slow" rotational media and
> fast media on two different HBA types.

It's still the wrong thing to do.  One of your co-workers has been
working on slicing for blk-mq to better support slower adapters.

Anything that prolongs the misery of keeping the old request code around
is a bad idea.

> The following is from a host with rotational disks behind a HP SAS Adapter and
> a fibre channel array behind a Emulex FC Adapter. The hpsa driver does not
> support scsi-mq yet (and has rotational disks attached to it), but the lpfc
> does. This patch allows an optimal combination of the scsi-mq enabled lpfc
> driver and the hpsa driver which still uses a single queue scsi layer and thus
> can make use of IO schedulers.

And this is another reason why this is bad.  There are very slow dumb
FC array arounds as well as really fast ones.  And there are really slow
SATA disks behind SAS controllers as well as really fast SSDs.

The host is simply the wrong place to decide these things.
--
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] drivers/scsi/emcctd: drivers/scsi/emcctd: Client driver implementation for EMC-Symmetrix GuestOS emulated Cut-Through Device

2016-01-25 Thread Johannes Thumshirn
On Sat, Jan 23, 2016 at 05:33:31AM +, Singhal, Maneesh wrote:
> Hello Thumshirn.
> Thanks for taking out time to review the patch. I appreciate that. Please 
> find my comments inlined.
> 

[...]

> > 
> > Wouldn't it be nice to have this in the Kconfig file? No user will ever
> > look
> > at the README file in the driver directory.
> 
> [MS>] Certainly, I will keep this README as it is (for someone who really 
> reads this) and also add these details in Kconfig as well.
> > 

OK, I can live with this.

> > > diff --git a/drivers/scsi/emcctd/emc_ctd_interface.h
> > b/drivers/scsi/emcctd/emc_ctd_interface.h
> > > new file mode 100644
> > > index 000..58a0276
> > > --- /dev/null
> > > +++ b/drivers/scsi/emcctd/emc_ctd_interface.h
> > > @@ -0,0 +1,386 @@

[...]

> > > +
> > > +/* a CTD v010 scatter/gather list entry: */
> > > +struct emc_ctd_v010_sgl {
> > > +
> > > + /* the physical address of the buffer: */
> > > + emc_ctd_uint32_t emc_ctd_v010_sgl_paddr_0_31;
> > > + emc_ctd_uint32_t emc_ctd_v010_sgl_paddr_32_63;
> > > +
> > > + /* the size of the buffer: */
> > > + emc_ctd_uint32_t emc_ctd_v010_sgl_size;
> > > +};
> > > +
> > > +/* a CTD v010 header: */
> > > +struct emc_ctd_v010_header {
> > > +
> > > + /* the other address: */
> > > + emc_ctd_uint16_t emc_ctd_v010_header_address;
> > > +
> > > + /* the minor version: */
> > > + emc_ctd_uint8_t emc_ctd_v010_header_minor;
> > > +
> > > + /* the what: */
> > > + emc_ctd_uint8_t emc_ctd_v010_header_what;
> > > +};
> > 
> > Well this is a matter of taste but you have (and not only in this struct,
> > just
> > an example)
> > 
> > emc_ctd_v010_header.emc_ctd_v010_header_address
> > 
> > all the emc_ctd_v010_header_ stuff is totally redundant and you
> > suffer from extremely
> > long lines in your dirver anyways. Just a hint.
> [MS>] Well, didn't actually get what you meant here, header_stuff is getting 
> used in the code, and is extremely useful as well.
> Also, I tried reducing long lines ... I don't think the left overs could be 
> reduced in a better way.


I'd suggest the following:

/* a CTD v010 header: */
struct emc_ctd_v010_header {

/* the other address: */
u16 header_address;

/* the minor version: */
u8 header_minor;

/* the what: */
u8 what;
};

and then use it like:

static void
ctd_handle_response(union emc_ctd_v010_message *io_message,
struct ctd_pci_private *ctd_private)
{
struct emc_ctd_v010_header *msg_header;

msg_header = _message->emc_ctd_v010_message_header;

switch (msg_header->what) {

case EMC_CTD_V010_WHAT_DETECT:
ctd_handle_detect((struct emc_ctd_v010_detect *)io_message,
ctd_private);

All the "emc_ctd_v010_header_" is unneeded redundant information, that doesn't
really solve a purpose in my opinion.

> > 
> > > +
> > > +/* a CTD v010 name: */
> > > +struct emc_ctd_v010_name {
> > > +
> > > + /* the name: */
> > > + emc_ctd_uint8_t emc_ctd_v010_name_bytes[8];
> > > +};
> > > +
> > > +/* a CTD v010 detect message: */
> > > +struct emc_ctd_v010_detect {
> > > +
> > > + /* the header: */
> > > + struct emc_ctd_v010_header emc_ctd_v010_detect_header;
> > > +
> > > + /* the flags: */
> > > + emc_ctd_uint32_t emc_ctd_v010_detect_flags;
> > > +
> > > + /* the name: */
> > > + struct emc_ctd_v010_name emc_ctd_v010_detect_name;
> > > +
> > > + /* the key: */
> > > + emc_ctd_uint64_t emc_ctd_v010_detect_key;
> > > +};
> > > +

[...]

> > > +
> > > +/* nomenclature for versioning
> > > + * MAJOR:MINOR:SUBVERSION:PATCH
> > > + */
> > > +
> > > +#define EMCCTD_MODULE_VERSION "2.0.0.24"
> > > +
> > > +MODULE_LICENSE("GPL");
> > > +MODULE_AUTHOR("EMC");
> > > +MODULE_DESCRIPTION("EMC CTD V1 - Build 18-Jan-2016");
> > 
> > This is very misleading. If I was a user I'd think the kernel was build on
> > 18-Jan-2016. Anyways The version should be enough.
> [MS>] I actually wanted to understand when this driver was last touched, and 
> hence this description was added.
> > 

If you insist.

> > > +MODULE_VERSION(EMCCTD_MODULE_VERSION);
> > > +

[...]

> > > +#define ctd_dprintk(__m_fmt, ...)\
> > > +do { \
> > > + if (ctd_debug)  \
> > > + pr_info("%s:%d:"__m_fmt, __func__, __LINE__,
> > ##__VA_ARGS__); \
> > > +} while (0)
> > 
> > Please use pr_debug() here.
> [MS>] Sure.
> > 
> > > +
> > > +#define ctd_dprintk_crit(__m_fmt, ...)   \
> > > + pr_crit("%s:%d:"__m_fmt, __func__, __LINE__,
> > ##__VA_ARGS__)
> > 
> > File and line information is probably not of any interest for the users
> > and
> > serves a debugging purpose only.
> [MS>] That's precisely why it is there...

Then please use the kernel's dynamic debug facility.

Thanks,
Johannes
-- 
Johannes Thumshirn  Storage
jthumsh...@suse.de+49 911 74053 689
SUSE 

RE: [PATCH] drivers/scsi/emcctd: drivers/scsi/emcctd: Client driver implementation for EMC-Symmetrix GuestOS emulated Cut-Through Device

2016-01-25 Thread Singhal, Maneesh
Thanks Johannes for generously reviewing my patch. It indeed is going to 
improve the thing a lot. I agree with all your comments so far, and will submit 
a newer patch soon. 
Since this is my first patch, I have couple of questions regarding submitting 
the patch:

1.  Is there a page/place where I can see the review comments rather neatly ?, 
finding out all the comments and infact reading to entire code on text file is 
cumbersome. If there is no way, then its fine,... I can live with it.
2. When I address the review comments and want to resubmit the patch, do I need 
to submit the incremental patch or the entire code patch again ? 
git-format-patch gives me incremental patch only.

Thanks
Maneesh

> -Original Message-
> From: Johannes Thumshirn [mailto:jthumsh...@suse.de]
> Sent: Monday, January 25, 2016 2:56 PM
> To: Singhal, Maneesh
> Cc: linux-scsi@vger.kernel.org; linux-ker...@vger.kernel.org;
> jbottom...@odin.com; martin.peter...@oracle.com; linux-
> a...@vger.kernel.org
> Subject: Re: [PATCH] drivers/scsi/emcctd: drivers/scsi/emcctd: Client
> driver implementation for EMC-Symmetrix GuestOS emulated Cut-
> Through Device
> 
> On Sat, Jan 23, 2016 at 05:51:50AM +, Singhal, Maneesh wrote:
> > Thanks for your time. My replies inlined...
> >
> 
> [...]
> 
> > > > +   }
> > > > +
> > >
> > > You don't do any cleanup work at
> > > ctd_scsi_response_sanity_check_complete. You could just reutrn 0
> > > here as well.
> > [MS>] Just avoiding multiple exit points from the function
> 
> Please have a look at Documentation/CodingStyle Chapter 7:
> Centralized exiting of functions. Especially this part:
> 
> 
> The goto statement comes in handy when a function exits from
> multiple locations and some common work such as cleanup has to be
> done.  If there is no cleanup needed then just return directly.
> 
> 
> and the example below that section.
> 
> > >
> > > > +
> > > > +   ctd_dprintk_crit(
> 
> [...]
> 
> > > > +   if (request && request->io_timeout < EMCCTD_MAX_RETRY) {
> > >
> > > The following block is a bit long and therefore it's hard to spot an
> > > eventual error of handling the io_mgmt_lock. Can't it be factored
> > > out in a helper function?
> > >
> > [MS>] I know its little longer, but actually fits logically together... Will
> see if it can be factored. Not sure though.
> 
> Yes please. It's not uber important but short functions and paths are
> generally favoured when debugging and reviewing code.
> 
> 
> Thanks,
>   Johannes
> 
> --
> Johannes Thumshirn  Storage
> jthumsh...@suse.de+49 911 74053 689
> SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
> GF: Felix Imendörffer, Jane Smithard, Graham Norton HRB 21284 (AG
> Nürnberg) Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D
> 2D76 0850
--
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] drivers/scsi/emcctd: drivers/scsi/emcctd: Client driver implementation for EMC-Symmetrix GuestOS emulated Cut-Through Device

2016-01-25 Thread Johannes Thumshirn
On Mon, Jan 25, 2016 at 09:30:47AM +, Singhal, Maneesh wrote:
> Thanks Johannes for generously reviewing my patch. It indeed is going to 
> improve the thing a lot. I agree with all your comments so far, and will 
> submit a newer patch soon. 
> Since this is my first patch, I have couple of questions regarding submitting 
> the patch:
> 
> 1.  Is there a page/place where I can see the review comments rather neatly 
> ?, finding out all the comments and infact reading to entire code on text 
> file is cumbersome. If there is no way, then its fine,... I can live with it.

Nope unfortunately not. That's why it's nice when people trim their e-mails
;-)

> 2. When I address the review comments and want to resubmit the patch, do I 
> need to submit the incremental patch or the entire code patch again ? 
> git-format-patch gives me incremental patch only.

Ususally you change your code and do a git commit --amend. This modifies your
commit instead of creating a new one. If you already have a new commit than
you can use git rebase -i  and squash the
commit's into one (git gives you a nice readme when doing rebase -i). Afterwards
you do a git format-patch -1 -v 2, this creates a v2-0001-your-patch-name.patch
for git send-email which has an updated [PATCH V2] in the subject.

At least, the above is the way I do it (i.e. there are more than one ways to
do it).


-- 
Johannes Thumshirn  Storage
jthumsh...@suse.de+49 911 74053 689
SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
--
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: What partition should the MTMKPART argument specify? Was: Re: st driver doesn't seem to grok LTO partitioning

2016-01-25 Thread Emmanuel Florac
Le Sun, 24 Jan 2016 23:05:17 +0200 (EET)
Kai Makisara  écrivait:

> Below is a test patch that implements the current behaviour with 
> non-negative argument (but works with LTOs etc.) and makes partition 
> zero size absolute value of argument (MB) if argument is negative. If 
> you want to test the patch, note that the current mt-st does not
> accept negative numbers. A minimal patch is needed.

OK I'm going to try this one.

-- 

Emmanuel Florac |   Direction technique
|   Intellique
|   
|   +33 1 78 94 84 02

--
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] drivers/scsi/emcctd: drivers/scsi/emcctd: Client driver implementation for EMC-Symmetrix GuestOS emulated Cut-Through Device

2016-01-25 Thread Singhal, Maneesh
Thanks a lot for detailed information. Appreciate it !

Regards
Maneesh

> -Original Message-
> From: Johannes Thumshirn [mailto:jthumsh...@suse.de]
> Sent: Monday, January 25, 2016 3:39 PM
> To: Singhal, Maneesh
> Cc: linux-scsi@vger.kernel.org; linux-ker...@vger.kernel.org;
> jbottom...@odin.com; martin.peter...@oracle.com; linux-
> a...@vger.kernel.org
> Subject: Re: [PATCH] drivers/scsi/emcctd: drivers/scsi/emcctd: Client
> driver implementation for EMC-Symmetrix GuestOS emulated Cut-
> Through Device
> 
> On Mon, Jan 25, 2016 at 09:30:47AM +, Singhal, Maneesh wrote:
> > Thanks Johannes for generously reviewing my patch. It indeed is
> going to improve the thing a lot. I agree with all your comments so far,
> and will submit a newer patch soon.
> > Since this is my first patch, I have couple of questions regarding
> submitting the patch:
> >
> > 1.  Is there a page/place where I can see the review comments
> rather neatly ?, finding out all the comments and infact reading to
> entire code on text file is cumbersome. If there is no way, then its
> fine,... I can live with it.
> 
> Nope unfortunately not. That's why it's nice when people trim their e-
> mails
> ;-)
> 
> > 2. When I address the review comments and want to resubmit the
> patch, do I need to submit the incremental patch or the entire code
> patch again ? git-format-patch gives me incremental patch only.
> 
> Ususally you change your code and do a git commit --amend. This
> modifies your commit instead of creating a new one. If you already
> have a new commit than you can use git rebase -i  commit to amend> and squash the commit's into one (git gives you a
> nice readme when doing rebase -i). Afterwards you do a git format-
> patch -1 -v 2, this creates a v2-0001-your-patch-name.patch for git
> send-email which has an updated [PATCH V2] in the subject.
> 
> At least, the above is the way I do it (i.e. there are more than one ways
> to do it).
> 
> 
> --
> Johannes Thumshirn  Storage
> jthumsh...@suse.de+49 911 74053 689
> SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg
> GF: Felix Imendörffer, Jane Smithard, Graham Norton HRB 21284 (AG
> Nürnberg) Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D
> 2D76 0850
--
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] scsi: Allow activation of scsi-mq per-driver

2016-01-25 Thread Johannes Thumshirn
On Mon, Jan 25, 2016 at 02:05:25AM -0800, Christoph Hellwig wrote:
> On Fri, Jan 22, 2016 at 02:41:28PM +0100, Johannes Thumshirn wrote:
> > Allow the activation of the scsi-mq feature on a per-driver bassis as 
> > opposed
> > to the current stack global (de)activation.
> > 
> > This allows us to have setups which can combine "slow" rotational media and
> > fast media on two different HBA types.
> 
> It's still the wrong thing to do.  One of your co-workers has been
> working on slicing for blk-mq to better support slower adapters.

I know but there are no results yet.

> 
> Anything that prolongs the misery of keeping the old request code around
> is a bad idea.

Agreed, but this patch is a "quick fix" for the problem until the nice solution
is in place. The way it currently works is unacceptable from a distribution
point of view.

> 
> > The following is from a host with rotational disks behind a HP SAS Adapter 
> > and
> > a fibre channel array behind a Emulex FC Adapter. The hpsa driver does not
> > support scsi-mq yet (and has rotational disks attached to it), but the lpfc
> > does. This patch allows an optimal combination of the scsi-mq enabled lpfc
> > driver and the hpsa driver which still uses a single queue scsi layer and 
> > thus
> > can make use of IO schedulers.
> 
> And this is another reason why this is bad.  There are very slow dumb
> FC array arounds as well as really fast ones.  And there are really slow
> SATA disks behind SAS controllers as well as really fast SSDs.
> 
> The host is simply the wrong place to decide these things.


Yes, but this way the admin can _decide_ on which driver's he/she is going to
activate scsi-mq and on which not. Of casue this only solves the issue if
multiple drivers are involved, but still better than a global on/off switch.

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