Re: [PATCH 2/9] IB: add a proper completion queue abstraction

2015-11-17 Thread Sagi Grimberg

Hi Bart,


+ */
+void ib_process_cq_direct(struct ib_cq *cq)
+{
+WARN_ON_ONCE(cq->poll_ctx != IB_POLL_DIRECT);
+
+__ib_process_cq(cq, INT_MAX);
+}
+EXPORT_SYMBOL(ib_process_cq_direct);


My proposal is to drop this function and to export __ib_process_cq()
instead (with or without renaming). That will allow callers of this
function to compare the poll budget with the number of completions that
have been processed and use that information to decide whether or not to
call this function again.


I agree with that.




+static void ib_cq_poll_work(struct work_struct *work)
+{
+struct ib_cq *cq = container_of(work, struct ib_cq, work);
+int completed;
+
+completed = __ib_process_cq(cq, IB_POLL_BUDGET_WORKQUEUE);
+if (completed >= IB_POLL_BUDGET_WORKQUEUE ||
+ib_req_notify_cq(cq, IB_POLL_FLAGS) > 0)
+queue_work(ib_comp_wq, &cq->work);
+}
+
+static void ib_cq_completion_workqueue(struct ib_cq *cq, void *private)
+{
+queue_work(ib_comp_wq, &cq->work);
+}


The above code will cause all polling to occur on the context of the CPU
that received the completion interrupt. This approach is not powerful
enough. For certain workloads throughput is higher if work completions
are processed by another CPU core on the same CPU socket. Has it been
considered to make the CPU core on which work completions are processed
configurable ?


The workqueue is unbound. This means that the functionality you are
you are asking for exists.
--
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 4/9] srpt: chain RDMA READ/WRITE requests

2015-11-17 Thread Bart Van Assche

On 11/13/2015 05:46 AM, Christoph Hellwig wrote:

-   ret = ib_post_send(ch->qp, &wr.wr, &bad_wr);
-   if (ret)
-   break;
+   if (i == n_rdma - 1) {
+   /* only get completion event for the last rdma read */
+   if (dir == DMA_TO_DEVICE)
+   wr->wr.send_flags = IB_SEND_SIGNALED;
+   wr->wr.next = NULL;
+   } else {
+   wr->wr.next = &ioctx->rdma_ius[i + 1].wr;
+   }
}

+   ret = ib_post_send(ch->qp, &ioctx->rdma_ius->wr, &bad_wr);
if (ret)
pr_err("%s[%d]: ib_post_send() returned %d for %d/%d\n",
 __func__, __LINE__, ret, i, n_rdma);


Hello Christoph,

Chaining RDMA requests is a great idea. But it seems to me that this 
patch is based on the assumption that posting multiple RDMA requests 
either succeeds as a whole or fails as a whole. Sorry but I'm not sure 
that the verbs API guarantees this. In the ib_srpt driver a QP can be 
changed at any time into the error state and there might be drivers that 
report an immediate failure in that case. I think even when chaining 
RDMA requests that we still need a mechanism to wait until ongoing RDMA 
transfers have finished if some but not all RDMA requests have been posted.


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


Re: [PATCH v2] qla2xxx: Remove unavailable firmware files

2015-11-17 Thread Julian Calaby
Hi Himanshu,

On Wed, Nov 18, 2015 at 7:44 AM, Himanshu Madhani
 wrote:
> Remove firmware binary names for the ISPs, which
> are not submitted to linux-firmware
>
> Signed-off-by: Himanshu Madhani 
> Signed-off-by: Giridhar Malavali 
> Reviewed-by: Julian Calaby 

The patch looks good so for what it's worth:

Reviewed-by: Julian Calaby 

Thanks,

-- 
Julian Calaby

Email: julian.cal...@gmail.com
Profile: http://www.google.com/profiles/julian.calaby/
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH, RESEND] qla2xxx: Fix rwlock recursion

2015-11-17 Thread Martin K. Petersen
> "Bart" == Bart Van Assche  writes:

Bart> This patch fixes the following kernel bug

Applied (4.4).

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


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

2015-11-17 Thread Martin K. Petersen
> "Lee" == Lee Duncan  writes:

Lee> Martin: I will be glad to update the patch, creating a modprobe
Lee> parameter as suggested, if you find this acceptable.

For development use a module parameter would be fine. But I am concerned
about our support folks that rely on the incrementing host number when
analyzing customer log files.

Ewan: How do you folks feel about this change?

-- 
Martin K. Petersen  Oracle Linux Engineering
--
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] qla2xxx: Remove unavailable firmware files

2015-11-17 Thread Himanshu Madhani
Remove firmware binary names for the ISPs, which
are not submitted to linux-firmware

Signed-off-by: Himanshu Madhani 
Signed-off-by: Giridhar Malavali 
Reviewed-by: Julian Calaby 
Reviewed-by: Xose Vazquez Perez 
Cc: Hannes Reinecke 
---
 drivers/scsi/qla2xxx/Kconfig  |3 ---
 drivers/scsi/qla2xxx/qla_os.c |3 ---
 2 files changed, 0 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig
index a0f732b..10aa18b 100644
--- a/drivers/scsi/qla2xxx/Kconfig
+++ b/drivers/scsi/qla2xxx/Kconfig
@@ -18,9 +18,6 @@ config SCSI_QLA_FC
2322, 6322ql2322_fw.bin
24xx, 54xxql2400_fw.bin
25xx  ql2500_fw.bin
-   2031  ql2600_fw.bin
-   8031  ql8300_fw.bin
-   27xx  ql2700_fw.bin
 
Upon request, the driver caches the firmware image until
the driver is unloaded.
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index bfa9a64..6be32fd 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -5843,6 +5843,3 @@ MODULE_FIRMWARE(FW_FILE_ISP2300);
 MODULE_FIRMWARE(FW_FILE_ISP2322);
 MODULE_FIRMWARE(FW_FILE_ISP24XX);
 MODULE_FIRMWARE(FW_FILE_ISP25XX);
-MODULE_FIRMWARE(FW_FILE_ISP2031);
-MODULE_FIRMWARE(FW_FILE_ISP8031);
-MODULE_FIRMWARE(FW_FILE_ISP27XX);
-- 
1.7.7

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


Re: [PATCH 1/2] qla2xxx: Remove unavailable firmware files

2015-11-17 Thread Xose Vazquez Perez
On 10/14/2015 05:57 PM, Himanshu Madhani wrote:

> Remove firmware binary names for the ISPs, which
> are not submitted to linux-firmware
> 
> Signed-off-by: Himanshu Madhani 
> Signed-off-by: Giridhar Malavali 
> ---
>  drivers/scsi/qla2xxx/qla_os.c |   29 -
>  1 files changed, 0 insertions(+), 29 deletions(-)
> 
> diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
> index c2dd17b..41aca16 100644
> --- a/drivers/scsi/qla2xxx/qla_os.c
> +++ b/drivers/scsi/qla2xxx/qla_os.c
> @@ -5293,11 +5293,6 @@ qla2x00_timer(scsi_qla_host_t *vha)
>  #define FW_ISP2322   3
>  #define FW_ISP24XX   4
>  #define FW_ISP25XX   5
> -#define FW_ISP81XX   6
> -#define FW_ISP82XX   7
> -#define FW_ISP2031   8
> -#define FW_ISP8031   9
> -#define FW_ISP27XX   10
>  
>  #define FW_FILE_ISP21XX  "ql2100_fw.bin"
>  #define FW_FILE_ISP22XX  "ql2200_fw.bin"
> @@ -5305,12 +5300,6 @@ qla2x00_timer(scsi_qla_host_t *vha)
>  #define FW_FILE_ISP2322  "ql2322_fw.bin"
>  #define FW_FILE_ISP24XX  "ql2400_fw.bin"
>  #define FW_FILE_ISP25XX  "ql2500_fw.bin"
> -#define FW_FILE_ISP81XX  "ql8100_fw.bin"
> -#define FW_FILE_ISP82XX  "ql8200_fw.bin"
> -#define FW_FILE_ISP2031  "ql2600_fw.bin"
> -#define FW_FILE_ISP8031  "ql8300_fw.bin"
> -#define FW_FILE_ISP27XX  "ql2700_fw.bin"
> -
>  
>  static DEFINE_MUTEX(qla_fw_lock);
>  
> @@ -5321,11 +5310,6 @@ static struct fw_blob qla_fw_blobs[FW_BLOBS] = {
>   { .name = FW_FILE_ISP2322, .segs = { 0x800, 0x1c000, 0x1e000, 0 }, },
>   { .name = FW_FILE_ISP24XX, },
>   { .name = FW_FILE_ISP25XX, },
> - { .name = FW_FILE_ISP81XX, },
> - { .name = FW_FILE_ISP82XX, },
> - { .name = FW_FILE_ISP2031, },
> - { .name = FW_FILE_ISP8031, },
> - { .name = FW_FILE_ISP27XX, },
>  };
>  
>  struct fw_blob *
> @@ -5346,16 +5330,6 @@ qla2x00_request_firmware(scsi_qla_host_t *vha)
>   blob = &qla_fw_blobs[FW_ISP24XX];
>   } else if (IS_QLA25XX(ha)) {
>   blob = &qla_fw_blobs[FW_ISP25XX];
> - } else if (IS_QLA81XX(ha)) {
> - blob = &qla_fw_blobs[FW_ISP81XX];
> - } else if (IS_QLA82XX(ha)) {
> - blob = &qla_fw_blobs[FW_ISP82XX];
> - } else if (IS_QLA2031(ha)) {
> - blob = &qla_fw_blobs[FW_ISP2031];
> - } else if (IS_QLA8031(ha)) {
> - blob = &qla_fw_blobs[FW_ISP8031];
> - } else if (IS_QLA27XX(ha)) {
> - blob = &qla_fw_blobs[FW_ISP27XX];
>   } else {
>   return NULL;
>   }
> @@ -5844,6 +5818,3 @@ MODULE_FIRMWARE(FW_FILE_ISP2300);
>  MODULE_FIRMWARE(FW_FILE_ISP2322);
>  MODULE_FIRMWARE(FW_FILE_ISP24XX);
>  MODULE_FIRMWARE(FW_FILE_ISP25XX);
> -MODULE_FIRMWARE(FW_FILE_ISP2031);
> -MODULE_FIRMWARE(FW_FILE_ISP8031);
> -MODULE_FIRMWARE(FW_FILE_ISP27XX);
> -- 
> 1.7.7

You should remove this info also from Kconfig:
  2031  ql2600_fw.bin
  8031  ql8300_fw.bin
  27xx  ql2700_fw.bin

Anyway,

Reviewed-by: Xose Vazquez Perez 


BTW, linux-firmware still contains release 7.03.00 of ql2400_fw.bin and 
ql2500_fw.bin .
SLES-11_SP4 already brings 8.00.00. And I did test 8.01.00 time ago and it 
worked flawlessly.

So, please *regularly* send latest FW releases to linux-firmware.git

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


[PATCH] qla2xxx: Remove unavailable firmware files

2015-11-17 Thread Himanshu Madhani
Remove firmware binary names for the ISPs, which
are not submitted to linux-firmware

Signed-off-by: Himanshu Madhani 
Signed-off-by: Giridhar Malavali 
Cc: Hannes Reinecke 
Cc: Julian Calaby 
Cc: Xose Vazquez Perez 
---
 drivers/scsi/qla2xxx/qla_os.c |3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index bfa9a64..6be32fd 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -5843,6 +5843,3 @@ MODULE_FIRMWARE(FW_FILE_ISP2300);
 MODULE_FIRMWARE(FW_FILE_ISP2322);
 MODULE_FIRMWARE(FW_FILE_ISP24XX);
 MODULE_FIRMWARE(FW_FILE_ISP25XX);
-MODULE_FIRMWARE(FW_FILE_ISP2031);
-MODULE_FIRMWARE(FW_FILE_ISP8031);
-MODULE_FIRMWARE(FW_FILE_ISP27XX);
-- 
1.7.7

--
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] st: Remove obsolete scsi_tape.max_pfn

2015-11-17 Thread Kai Mäkisara (Kolumbus)

> On 15.11.2015, at 13.48, Geert Uytterhoeven  wrote:
> 
> Its last user was removed 10 years ago, in commit
> 8b05b773b6030de5 ("[SCSI] convert st to use scsi_execute_async").
> 
> Signed-off-by: Geert Uytterhoeven 

Acked-by: Kai Mäkisara 

Thanks,
Kai

--
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 6/9] srp: use the new CQ API

2015-11-17 Thread Bart Van Assche

On 11/13/2015 05:46 AM, Christoph Hellwig wrote:

+static void srp_inv_rkey_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+   srp_handle_qp_err(cq, wc, "INV RKEY");
+}

>

[ ... ]

>

+static void srp_reg_mr_done(struct ib_cq *cq, struct ib_wc *wc)
+{
+   srp_handle_qp_err(cq, wc, "FAST REG");
+}


How about using names like srp_inv_rkey_err() and srp_reg_mr_err() to 
make clear that these completion functions are only called if an error 
occurred ?


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


Re: [PATCH 5/9] srpt: use the new CQ API

2015-11-17 Thread Bart Van Assche

On 11/13/2015 05:46 AM, Christoph Hellwig wrote:

[ ... ]


This patch contains two logical changes:
- Conversion to the new CQ API.
- Removal of the ib_srpt_compl thread.

Had it been considered to implement these changes as two separate patches ?

Thanks,

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


[PATCH 32/52] atp870u: Replace port 0x80 delay by udelay

2015-11-17 Thread Ondrej Zary
tscam() is using port 0x80 access for delays but that's x86-only.
Use udelay(2) instead.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   18 +-
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index bccf872..c4a59cc 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1036,7 +1036,7 @@ static void tscam(struct Scsi_Host *host)
atp_writeb_io(dev, 0, 0x02, 0x7f);
atp_writeb_io(dev, 0, 0x1b, 0x02);
 
-   outb(0, 0x80);
+   udelay(2);
 
val = 0x0080;   /* bsy  */
atp_writew_io(dev, 0, 0x1c, val);
@@ -1044,7 +1044,7 @@ static void tscam(struct Scsi_Host *host)
atp_writew_io(dev, 0, 0x1c, val);
val |= 0x0004;  /* msg  */
atp_writew_io(dev, 0, 0x1c, val);
-   inb(0x80);  /* 2 deskew delay(45ns*2=90ns) */
+   udelay(2);  /* 2 deskew delay(45ns*2=90ns) */
val &= 0x007f;  /* no bsy  */
atp_writew_io(dev, 0, 0x1c, val);
mdelay(128);
@@ -1052,7 +1052,7 @@ static void tscam(struct Scsi_Host *host)
atp_writew_io(dev, 0, 0x1c, val);
while ((atp_readb_io(dev, 0, 0x1c) & 0x04) != 0)
;
-   outb(1, 0x80);
+   udelay(2);
udelay(100);
for (n = 0; n < 0x3; n++)
if ((atp_readb_io(dev, 0, 0x1c) & 0x80) != 0)   /* bsy ? */
@@ -1060,13 +1060,13 @@ static void tscam(struct Scsi_Host *host)
if (n < 0x3)
for (n = 0; n < 0x3; n++)
if ((atp_readb_io(dev, 0, 0x1c) & 0x81) == 0x0081) {
-   inb(0x80);
+   udelay(2);
val |= 0x8003;  /* io,cd,db7  */
atp_writew_io(dev, 0, 0x1c, val);
-   inb(0x80);
+   udelay(2);
val &= 0x00bf;  /* no sel */
atp_writew_io(dev, 0, 0x1c, val);
-   outb(2, 0x80);
+   udelay(2);
break;
}
while (1) {
@@ -1093,18 +1093,18 @@ static void tscam(struct Scsi_Host *host)
val &= 0x00ff;  /* synchronization  */
val |= 0x3f00;
fun_scam(dev, &val);
-   outb(3, 0x80);
+   udelay(2);
val &= 0x00ff;  /* isolation*/
val |= 0x2000;
fun_scam(dev, &val);
-   outb(4, 0x80);
+   udelay(2);
i = 8;
j = 0;
 
while (1) {
if ((atp_readw_io(dev, 0, 0x1c) & 0x2000) == 0)
continue;
-   outb(5, 0x80);
+   udelay(2);
val &= 0x00ff;  /* get ID_STRING */
val |= 0x2000;
k = fun_scam(dev, &val);
-- 
Ondrej Zary

--
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 41/52] atp870u: Improve _probe()

2015-11-17 Thread Ondrej Zary
Move scsi_host_alloc() to the top of _probe() to remove code duplication,
*p and unneeded atpdev (de)allocation and copying.
While at it, fix the error paths to return real error codes and also add
missing pci_disble_device() call.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |  236 +++-
 1 file changed, 113 insertions(+), 123 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 0b349bc..d0119f1 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1248,29 +1248,41 @@ static int atp870u_probe(struct pci_dev *pdev, const 
struct pci_device_id *ent)
unsigned int base_io, error,n;
unsigned char host_id;
struct Scsi_Host *shpnt = NULL;
-   struct atp_unit *atpdev, *p;
+   struct atp_unit *atpdev;
unsigned char setupdata[2][16];
+   int err;
 
-   atpdev = kzalloc(sizeof(*atpdev), GFP_KERNEL);
-   if (!atpdev)
-   return -ENOMEM;
-
-   if (pci_enable_device(pdev))
-   goto err_eio;
+   err = pci_enable_device(pdev);
+   if (err)
+   goto fail;
 
if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
 printk(KERN_ERR "atp870u: DMA mask required but not 
available.\n");
-   goto err_eio;
+err = -EIO;
+goto disable_device;
 }
 
+err = -ENOMEM;
+   shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
+   if (!shpnt)
+   goto disable_device;
+
+   atpdev = shost_priv(shpnt);
+
+   atpdev->host = shpnt;
+   atpdev->pdev = pdev;
+   pci_set_drvdata(pdev, atpdev);
+
/*
 * It's probably easier to weed out some revisions like
 * this than via the PCI device table
 */
if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610) {
atpdev->chip_ver = pdev->revision;
-   if (atpdev->chip_ver < 2)
-   goto err_eio;
+   if (atpdev->chip_ver < 2) {
+   err = -ENODEV;
+   goto unregister;
+   }
}
 
switch (ent->device) {
@@ -1358,41 +1370,33 @@ flash_ok_880:
atpdev->async[0] = ~(atpdev->async[0]);
atp_writeb_base(atpdev, 0x35, atpdev->global_map[0]);
  
-   shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct 
atp_unit));
-   if (!shpnt)
-   goto err_nomem;
-
-   p = (struct atp_unit *)&shpnt->hostdata;
-
-   atpdev->host = shpnt;
-   atpdev->pdev = pdev;
-   pci_set_drvdata(pdev, p);
-   memcpy(p, atpdev, sizeof(*atpdev));
if (atp870u_init_tables(shpnt) < 0) {
printk(KERN_ERR "Unable to allocate tables for Acard 
controller\n");
+   err = -ENOMEM;
goto unregister;
}
 
-   if (request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, 
"atp880i", shpnt)) {
+   err = request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, 
"atp880i", shpnt);
+   if (err) {
printk(KERN_ERR "Unable to allocate IRQ%d for Acard 
controller.\n", pdev->irq);
goto free_tables;
}
 
spin_lock_irqsave(shpnt->host_lock, flags);
-   k = atp_readb_base(p, 0x38) & 0x80;
-   atp_writeb_base(p, 0x38, k);
-   atp_writeb_base(p, 0x3b, 0x20);
+   k = atp_readb_base(atpdev, 0x38) & 0x80;
+   atp_writeb_base(atpdev, 0x38, k);
+   atp_writeb_base(atpdev, 0x3b, 0x20);
mdelay(32);
-   atp_writeb_base(p, 0x3b, 0);
+   atp_writeb_base(atpdev, 0x3b, 0);
mdelay(32);
-   atp_readb_io(p, 0, 0x1b);
-   atp_readb_io(p, 0, 0x17);
+   atp_readb_io(atpdev, 0, 0x1b);
+   atp_readb_io(atpdev, 0, 0x17);
 
-   atp_set_host_id(p, 0, host_id);
+   atp_set_host_id(atpdev, 0, host_id);
 
tscam(shpnt);
-   atp_is(p, 0, true, atp_readb_base(p, 0x3f) & 0x40);
-   atp_writeb_base(p, 0x38, 0xb0);
+   atp_is(atpdev, 0, true, atp_readb_base(atpdev, 0x3f) & 0x40);
+   atp_writeb_base(atpdev, 0x38, 0xb0);
shpnt->max_id = 16;
shpnt->this_id = host_id;
shpnt->unique_id = base_io;
@@ -1410,50 +1414,43 @@ flash_ok_880:
atpdev->pciport[0] = base_io + 0x40;
atpdev->pciport[1] = base_io + 0x50;

-   shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct 
atp_unit));
-   if (!shpnt)
-   goto err_nomem;
-   
-   p = (struct atp_unit *)&shpnt->host

[PATCH 39/52] atp870u: Remove useless and broken card counting

2015-11-17 Thread Ondrej Zary
Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   10 --
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index a06a0a4..0b349bc 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1250,7 +1250,6 @@ static int atp870u_probe(struct pci_dev *pdev, const 
struct pci_device_id *ent)
struct Scsi_Host *shpnt = NULL;
struct atp_unit *atpdev, *p;
unsigned char setupdata[2][16];
-   int count = 0;
 
atpdev = kzalloc(sizeof(*atpdev), GFP_KERNEL);
if (!atpdev)
@@ -1298,8 +1297,8 @@ static int atp870u_probe(struct pci_dev *pdev, const 
struct pci_device_id *ent)
host_id = atp_readb_base(atpdev, 0x39);
host_id >>= 0x04;
 
-   printk(KERN_INFO "   ACARD AEC-67160 PCI Ultra3 LVD Host 
Adapter: %d"
-   "IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
+   printk(KERN_INFO "   ACARD AEC-67160 PCI Ultra3 LVD Host 
Adapter:"
+   "IO:%x, IRQ:%d.\n", base_io, pdev->irq);
atpdev->dev_id = ent->device;
atpdev->host_id[0] = host_id;
 
@@ -1546,8 +1545,8 @@ flash_ok_885:
} else {
error = pci_read_config_byte(pdev, 0x49, &host_id);
 
-   printk(KERN_INFO "   ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host 
Adapter: %d "
-   "IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
+   printk(KERN_INFO "   ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host 
Adapter: "
+   "IO:%x, IRQ:%d.\n", base_io, pdev->irq);
 
atpdev->ioport[0] = base_io;
atpdev->pciport[0] = base_io + 0x20;
@@ -1612,7 +1611,6 @@ flash_ok_885:
spin_unlock_irqrestore(shpnt->host_lock, flags);
if (!request_region(base_io, shpnt->n_io_port, "atp870u"))
goto request_io_fail;
-   count++;
if (scsi_add_host(shpnt, &pdev->dev))
goto scsi_add_fail;
scsi_scan_host(shpnt);
-- 
Ondrej Zary

--
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 52/52] atp870u: Introduce atp870_init()

2015-11-17 Thread Ondrej Zary
Move 870-specific init code to a separate function atp870_init()

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |  104 +---
 1 file changed, 54 insertions(+), 50 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 584b90f..8b52a9d 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1249,6 +1249,57 @@ static void atp_set_host_id(struct atp_unit *atp, u8 c, 
u8 host_id)
atp_writeb_io(atp, c, 0x11, 0x20);
 }
 
+static void atp870_init(struct Scsi_Host *shpnt)
+{
+   struct atp_unit *atpdev = shost_priv(shpnt);
+   struct pci_dev *pdev = atpdev->pdev;
+   unsigned char k, host_id;
+   u8 scam_on;
+   bool wide_chip =
+   (pdev->device == PCI_DEVICE_ID_ARTOP_AEC7610 &&
+pdev->revision == 4) ||
+   (pdev->device == PCI_DEVICE_ID_ARTOP_AEC7612UW) ||
+   (pdev->device == PCI_DEVICE_ID_ARTOP_AEC7612SUW);
+
+   pci_read_config_byte(pdev, 0x49, &host_id);
+
+   dev_info(&pdev->dev, "ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host Adapter: 
IO:%lx, IRQ:%d.\n",
+shpnt->io_port, shpnt->irq);
+
+   atpdev->ioport[0] = shpnt->io_port;
+   atpdev->pciport[0] = shpnt->io_port + 0x20;
+   host_id &= 0x07;
+   atpdev->host_id[0] = host_id;
+   scam_on = atp_readb_pci(atpdev, 0, 2);
+   atpdev->global_map[0] = atp_readb_base(atpdev, 0x2d);
+   atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x2e);
+
+   if (atpdev->ultra_map[0] == 0) {
+   scam_on = 0x00;
+   atpdev->global_map[0] = 0x20;
+   atpdev->ultra_map[0] = 0x;
+   }
+
+   if (pdev->revision > 0x07)  /* check if atp876 chip */
+   atp_writeb_base(atpdev, 0x3e, 0x00); /* enable terminator */
+
+   k = (atp_readb_base(atpdev, 0x3a) & 0xf3) | 0x10;
+   atp_writeb_base(atpdev, 0x3a, k);
+   atp_writeb_base(atpdev, 0x3a, k & 0xdf);
+   mdelay(32);
+   atp_writeb_base(atpdev, 0x3a, k);
+   mdelay(32);
+   atp_set_host_id(atpdev, 0, host_id);
+
+   tscam(shpnt, wide_chip, scam_on);
+   atp_writeb_base(atpdev, 0x3a, atp_readb_base(atpdev, 0x3a) | 0x10);
+   atp_is(atpdev, 0, wide_chip, 0);
+   atp_writeb_base(atpdev, 0x3a, atp_readb_base(atpdev, 0x3a) & 0xef);
+   atp_writeb_base(atpdev, 0x3b, atp_readb_base(atpdev, 0x3b) | 0x20);
+   shpnt->max_id = wide_chip ? 16 : 8;
+   shpnt->this_id = host_id;
+}
+
 static void atp880_init(struct Scsi_Host *shpnt)
 {
struct atp_unit *atpdev = shost_priv(shpnt);
@@ -1445,9 +1496,6 @@ static void atp885_init(struct Scsi_Host *shpnt)
 /* return non-zero on detection */
 static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-   unsigned char k;
-   unsigned int error;
-   unsigned char host_id;
struct Scsi_Host *shpnt = NULL;
struct atp_unit *atpdev;
int err;
@@ -1500,53 +1548,9 @@ static int atp870u_probe(struct pci_dev *pdev, const 
struct pci_device_id *ent)
atp880_init(shpnt);
else if (is885(atpdev))
atp885_init(shpnt);
-   else {
-   u8 scam_on;
-   bool wide_chip =
-   (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610 &&
-pdev->revision == 4) ||
-   (ent->device == PCI_DEVICE_ID_ARTOP_AEC7612UW) ||
-   (ent->device == PCI_DEVICE_ID_ARTOP_AEC7612SUW);
-   error = pci_read_config_byte(pdev, 0x49, &host_id);
-
-   printk(KERN_INFO "   ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host 
Adapter: "
-   "IO:%lx, IRQ:%d.\n", shpnt->io_port, shpnt->irq);
-
-   atpdev->ioport[0] = shpnt->io_port;
-   atpdev->pciport[0] = shpnt->io_port + 0x20;
-   host_id &= 0x07;
-   atpdev->host_id[0] = host_id;
-   scam_on = atp_readb_pci(atpdev, 0, 2);
-   atpdev->global_map[0] = atp_readb_base(atpdev, 0x2d);
-   atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x2e);
-
-   if (atpdev->ultra_map[0] == 0) {
-   scam_on = 0x00;
-   atpdev->global_map[0] = 0x20;
-   atpdev->ultra_map[0] = 0x;
-   }
-
-   if (pdev->revision > 0x07)  /* check if atp876 chip then 
enable terminator */
-   atp_writeb_base(atpdev, 0x3e, 0x00);
- 
-   k = (atp_readb_base(atpdev, 0x3a) & 0xf3) | 0x10;
-   atp_writeb_base(atpdev, 0x3a, k);
-   atp_writeb_base(atpdev, 0x3a, k & 0xdf);
-   mdelay(32);
-   atp_writeb_base(atpdev, 0x3a, k);
-   mdelay(32);
-   atp_set_host_id(atpdev, 0, host_id);
-
-
-   tscam(shpnt, wide_chip, scam_on);
-   atp_writeb_base(atpdev, 0x3a, atp_readb_base(atpdev,

[PATCH 28/52] atp870u: Move 870-specific code out of is870()

2015-11-17 Thread Ondrej Zary
Move few remaining 870-specific code lines out of is870()

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index d76d386..6427f87 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1174,8 +1174,6 @@ static void is870(struct atp_unit *dev, unsigned char c, 
bool wide_chip)
static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 };
static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
 
-   atp_writeb_io(dev, c, 0x3a, atp_readb_io(dev, c, 0x3a) | 0x10);
-
for (i = 0; i < 16; i++) {
if (!wide_chip && (i > 7))
break;
@@ -1587,7 +1585,6 @@ tar_dcons:
 set_syn_ok:
dev->id[c][i].devsp = (dev->id[c][i].devsp & 0x0f) | j;
}
-   atp_writeb_io(dev, c, 0x3a, atp_readb_io(dev, c, 0x3a) & 0xef);
 }
 
 static void atp870u_free_tables(struct Scsi_Host *host)
@@ -2032,7 +2029,9 @@ flash_ok_885:
outb(0x20, base_io + 0x11);
 
tscam(shpnt);
+   atp_writeb_io(p, 0, 0x3a, atp_readb_io(p, 0, 0x3a) | 0x10);
is870(p, 0, p->chip_ver == 4);
+   atp_writeb_io(p, 0, 0x3a, atp_readb_io(p, 0, 0x3a) & 0xef);
outb((inb(base_io + 0x3a) & 0xef), base_io + 0x3a);
outb((inb(base_io + 0x3b) | 0x20), base_io + 0x3b);
if (atpdev->chip_ver == 4)
-- 
Ondrej Zary

--
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 35/52] atp870u: Reduce log spam on module load/unload

2015-11-17 Thread Ondrej Zary
Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 9621403..b662e39 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1260,9 +1260,7 @@ static int atp870u_probe(struct pci_dev *pdev, const 
struct pci_device_id *ent)
if (pci_enable_device(pdev))
goto err_eio;
 
-if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
-printk(KERN_INFO "atp870u: use 32bit DMA mask.\n");
-} else {
+   if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
 printk(KERN_ERR "atp870u: DMA mask required but not 
available.\n");
goto err_eio;
 }
@@ -1742,12 +1740,9 @@ static void atp870u_remove (struct pci_dev *pdev)


scsi_remove_host(pshost);
-   printk(KERN_INFO "free_irq : %d\n",pshost->irq);
free_irq(pshost->irq, pshost);
release_region(pshost->io_port, pshost->n_io_port);
-   printk(KERN_INFO "atp870u_free_tables : %p\n",pshost);
atp870u_free_tables(pshost);
-   printk(KERN_INFO "scsi_host_put : %p\n",pshost);
scsi_host_put(pshost);
 }
 MODULE_LICENSE("GPL");
-- 
Ondrej Zary

--
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 29/52] atp870u: Remove is870()

2015-11-17 Thread Ondrej Zary
Now that is885() supports everything from is870() and the rest of the code
is almost identical, remove is870() and use is885() instead.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |  427 +---
 1 file changed, 1 insertion(+), 426 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 6427f87..918875b 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1162,431 +1162,6 @@ static void tscam(struct Scsi_Host *host)
}
 }
 
-static void is870(struct atp_unit *dev, unsigned char c, bool wide_chip)
-{
-   unsigned char i, j, k, rmb, n;
-   unsigned short int m;
-   static unsigned char mbuf[512];
-   static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 };
-   static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 };
-   static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
-   static unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0c, 0x0e };
-   static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 };
-   static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
-
-   for (i = 0; i < 16; i++) {
-   if (!wide_chip && (i > 7))
-   break;
-   m = 1;
-   m = m << i;
-   if ((m & dev->active_id[c]) != 0) {
-   continue;
-   }
-   if (i == dev->host_id[c]) {
-   printk(KERN_INFO " ID: %2d  Host Adapter\n", 
dev->host_id[c]);
-   continue;
-   }
-   atp_writeb_io(dev, c, 0x1b, wide_chip ? 0x01 : 0x00);
-   atp_writeb_io(dev, c, 1, 0x08);
-   atp_writeb_io(dev, c, 2, 0x7f);
-   atp_writeb_io(dev, c, 3, satn[0]);
-   atp_writeb_io(dev, c, 4, satn[1]);
-   atp_writeb_io(dev, c, 5, satn[2]);
-   atp_writeb_io(dev, c, 6, satn[3]);
-   atp_writeb_io(dev, c, 7, satn[4]);
-   atp_writeb_io(dev, c, 8, satn[5]);
-   atp_writeb_io(dev, c, 0x0f, 0);
-   atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
-   atp_writeb_io(dev, c, 0x12, 0);
-   atp_writeb_io(dev, c, 0x13, satn[6]);
-   atp_writeb_io(dev, c, 0x14, satn[7]);
-   j = i;
-   if ((j & 0x08) != 0) {
-   j = (j & 0x07) | 0x40;
-   }
-   atp_writeb_io(dev, c, 0x15, j);
-   atp_writeb_io(dev, c, 0x18, satn[8]);
-
-   while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
-   cpu_relax();
-
-   if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 
0x17) != 0x8e)
-   continue;
-
-   while (atp_readb_io(dev, c, 0x17) != 0x8e)
-   cpu_relax();
-
-   dev->active_id[c] |= m;
-
-   atp_writeb_io(dev, c, 0x10, 0x30);
-   atp_writeb_io(dev, c, 0x04, 0x00);
-
-phase_cmd:
-   atp_writeb_io(dev, c, 0x18, 0x08);
-
-   while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
-   cpu_relax();
-
-   j = atp_readb_io(dev, c, 0x17);
-   if (j != 0x16) {
-   atp_writeb_io(dev, c, 0x10, 0x41);
-   goto phase_cmd;
-   }
-sel_ok:
-   atp_writeb_io(dev, c, 3, inqd[0]);
-   atp_writeb_io(dev, c, 4, inqd[1]);
-   atp_writeb_io(dev, c, 5, inqd[2]);
-   atp_writeb_io(dev, c, 6, inqd[3]);
-   atp_writeb_io(dev, c, 7, inqd[4]);
-   atp_writeb_io(dev, c, 8, inqd[5]);
-   atp_writeb_io(dev, c, 0x0f, 0);
-   atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
-   atp_writeb_io(dev, c, 0x12, 0);
-   atp_writeb_io(dev, c, 0x13, inqd[6]);
-   atp_writeb_io(dev, c, 0x14, inqd[7]);
-   atp_writeb_io(dev, c, 0x18, inqd[8]);
-
-   while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
-   cpu_relax();
-
-   if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 
0x17) != 0x8e)
-   continue;
-
-   while (atp_readb_io(dev, c, 0x17) != 0x8e)
-   cpu_relax();
-
-   if (wide_chip)
-   atp_writeb_io(dev, c, 0x1b, 0x00);
-
-   atp_writeb_io(dev, c, 0x18, 0x08);
-   j = 0;
-rd_inq_data:
-   k = atp_readb_io(dev, c, 0x1f);
-   if ((k & 0x01) != 0) {
-   mbuf[j++] = atp_readb_io(dev, c, 0x19);
-   goto rd_inq_data;
-   }
-   if ((k & 0x80) == 0) {
-   goto rd_inq_data;
-   }
-   j = atp_readb_io(dev, c, 0x17);
-   if (j == 0x16) {
-   goto 

[PATCH 48/52] atp870u: Remove scam_on from struct atp_unit

2015-11-17 Thread Ondrej Zary
scam_on is used only during probe, no need to keep it later.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   14 +++---
 drivers/scsi/atp870u.h |1 -
 2 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 4719df4..dd0b520 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -963,7 +963,7 @@ static unsigned char fun_scam(struct atp_unit *dev, 
unsigned short int *val)
return j;
 }
 
-static void tscam(struct Scsi_Host *host, bool wide_chip)
+static void tscam(struct Scsi_Host *host, bool wide_chip, u8 scam_on)
 {
 
unsigned char i, j, k;
@@ -986,7 +986,7 @@ static void tscam(struct Scsi_Host *host, bool wide_chip)
atp_writeb_io(dev, 0, 2, 0x7f);
atp_writeb_io(dev, 0, 0x11, 0x20);
 
-   if ((dev->scam_on & 0x40) == 0) {
+   if ((scam_on & 0x40) == 0) {
return;
}
m = 1;
@@ -1311,7 +1311,6 @@ static int atp870u_probe(struct pci_dev *pdev, const 
struct pci_device_id *ent)
"IO:%lx, IRQ:%d.\n", shpnt->io_port, shpnt->irq);
atpdev->host_id[0] = host_id;
 
-   atpdev->scam_on = atp_readb_base(atpdev, 0x22);
atpdev->global_map[0] = atp_readb_base(atpdev, 0x35);
atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x3c);
 
@@ -1384,7 +1383,7 @@ flash_ok_880:
 
atp_set_host_id(atpdev, 0, host_id);
 
-   tscam(shpnt, true);
+   tscam(shpnt, true, atp_readb_base(atpdev, 0x22));
atp_is(atpdev, 0, true, atp_readb_base(atpdev, 0x3f) & 0x40);
atp_writeb_base(atpdev, 0x38, 0xb0);
shpnt->max_id = 16;
@@ -1509,6 +1508,7 @@ flash_ok_885:
shpnt->max_channel = 1;
shpnt->this_id = atpdev->host_id[0];
} else {
+   u8 scam_on;
bool wide_chip =
(ent->device == PCI_DEVICE_ID_ARTOP_AEC7610 &&
 pdev->revision == 4) ||
@@ -1523,12 +1523,12 @@ flash_ok_885:
atpdev->pciport[0] = shpnt->io_port + 0x20;
host_id &= 0x07;
atpdev->host_id[0] = host_id;
-   atpdev->scam_on = atp_readb_pci(atpdev, 0, 2);
+   scam_on = atp_readb_pci(atpdev, 0, 2);
atpdev->global_map[0] = atp_readb_base(atpdev, 0x2d);
atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x2e);
 
if (atpdev->ultra_map[0] == 0) {
-   atpdev->scam_on = 0x00;
+   scam_on = 0x00;
atpdev->global_map[0] = 0x20;
atpdev->ultra_map[0] = 0x;
}
@@ -1551,7 +1551,7 @@ flash_ok_885:
atp_set_host_id(atpdev, 0, host_id);
 
 
-   tscam(shpnt, wide_chip);
+   tscam(shpnt, wide_chip, scam_on);
atp_writeb_base(atpdev, 0x3a, atp_readb_base(atpdev, 0x3a) | 
0x10);
atp_is(atpdev, 0, wide_chip, 0);
atp_writeb_base(atpdev, 0x3a, atp_readb_base(atpdev, 0x3a) & 
0xef);
diff --git a/drivers/scsi/atp870u.h b/drivers/scsi/atp870u.h
index f9d62a2..9b839b1 100644
--- a/drivers/scsi/atp870u.h
+++ b/drivers/scsi/atp870u.h
@@ -32,7 +32,6 @@ struct atp_unit
unsigned char quhd[2];
unsigned char quend[2];
unsigned char global_map[2];
-   unsigned char scam_on;
unsigned char host_id[2];
unsigned int working[2];
unsigned short wide_id[2];
-- 
Ondrej Zary

--
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 13/52] atp870u: Remove ugly gotos

2015-11-17 Thread Ondrej Zary
Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   84 +---
 1 file changed, 30 insertions(+), 54 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 4d840a5..886e54b 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -55,20 +55,17 @@ static irqreturn_t atp870u_intr_handle(int irq, void 
*dev_id)
 #ifdef ED_DBGP
unsigned long l;
 #endif
-   int errstus;
struct Scsi_Host *host = dev_id;
struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
 
for (c = 0; c < 2; c++) {
j = inb(dev->ioport[c] + 0x1f);
if ((j & 0x80) != 0)
-   {   
-   goto ch_sel;
-   }
+   break;
dev->in_int[c] = 0;
}
-   return IRQ_NONE;
-ch_sel:
+   if ((j & 0x80) == 0)
+   return IRQ_NONE;
 #ifdef ED_DBGP 
printk("atp870u_intr_handle enter\n");
 #endif 
@@ -82,15 +79,12 @@ ch_sel:
if ((inb(dev->pciport[c]) & 0x08) != 0)
{
for (k=0; k < 1000; k++) {
-   if ((inb(dev->pciport[c] + 2) & 0x08) == 0) {
-   goto stop_dma;
-   }
-   if ((inb(dev->pciport[c] + 2) & 0x01) == 0) {
-   goto stop_dma;
-   }
+   if ((inb(dev->pciport[c] + 2) & 0x08) == 0)
+   break;
+   if ((inb(dev->pciport[c] + 2) & 0x01) == 0)
+   break;
}
}
-stop_dma:
outb(0x00, dev->pciport[c]);

i = inb(dev->ioport[c] + 0x17);
@@ -170,13 +164,13 @@ stop_dma:
 #ifdef ED_DBGP
printk("Status 0x85 return\n");
 #endif 
-   goto handled;
+   return IRQ_HANDLED;
}
 
if (i == 0x40) {
 dev->last_cmd[c] |= 0x40;
 dev->in_int[c] = 0;
-goto handled;
+return IRQ_HANDLED;
}
 
if (i == 0x21) {
@@ -194,7 +188,7 @@ stop_dma:
outb(0x41, dev->ioport[c] + 0x10);
outb(0x08, dev->ioport[c] + 0x18);
dev->in_int[c] = 0;
-   goto handled;
+   return IRQ_HANDLED;
}
 
if (dev->dev_id == ATP885_DEVID) {
@@ -231,7 +225,7 @@ stop_dma:
dev->id[c][target_id].last_len = adrcnt;
outb(0x08, dev->ioport[c] + 0x18);
dev->in_int[c] = 0;
-   goto handled;
+   return IRQ_HANDLED;
} else {
 #ifdef ED_DBGP
printk("cmdp != 0x41\n");
@@ -243,7 +237,7 @@ stop_dma:
outb(0x00, dev->ioport[c] + 0x14);
outb(0x08, dev->ioport[c] + 0x18);
dev->in_int[c] = 0;
-   goto handled;
+   return IRQ_HANDLED;
}
}
if (dev->last_cmd[c] != 0xff) {
@@ -336,7 +330,7 @@ stop_dma:
 #ifdef ED_DBGP
printk("dev->id[c][target_id].last_len = 0\n");
 #endif 
-   goto handled;
+   return IRQ_HANDLED;
}
 #ifdef ED_DBGP
printk("target_id = %d adrcnt = %d\n",target_id,adrcnt);
@@ -382,7 +376,7 @@ stop_dma:
 #ifdef ED_DBGP
printk("status 0x80 return dirct != 0\n");
 #endif 
-   goto handled;
+   return IRQ_HANDLED;
}
outb(0x08, dev->ioport[c] + 0x18);
outb(0x09, dev->pciport[c]);
@@ -390,7 +384,7 @@ stop_dma:
 #ifdef ED_DBGP
printk("status 0x80 return dirct = 0\n");
 #endif 
-   goto handled;
+   return IRQ_HANDLED;
}
 
/*
@@ -399,27 +393,19 @@ stop_dma:
 
workreq = dev->id[c][target_id].curr_req;
 
-   if (i == 0x42) {
-   if ((dev->last_cmd[c] & 0xf0) != 0x40)
-   {
-

[PATCH 22/52] atp870u: Unify code format in is870(), is880() and is885()

2015-11-17 Thread Ondrej Zary
Unify code formatting in is870(), is880() and is885() functions to simplify
comparing them.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |  170 
 1 file changed, 101 insertions(+), 69 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index ad7af54..595c5c5 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1173,7 +1173,7 @@ static void is870(struct atp_unit *dev)
static unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0c, 0x0e };
static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 };
static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
-   
+
atp_writeb_io(dev, 0, 0x3a, atp_readb_io(dev, 0, 0x3a) | 0x10);
 
for (i = 0; i < 16; i++) {
@@ -1230,8 +1230,10 @@ static void is870(struct atp_unit *dev)
 
 phase_cmd:
atp_writeb_io(dev, 0, 0x18, 0x08);
+
while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0x00)
cpu_relax();
+
j = atp_readb_io(dev, 0, 0x17);
if (j != 0x16) {
atp_writeb_io(dev, 0, 0x10, 0x41);
@@ -1253,13 +1255,13 @@ sel_ok:
 
while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0x00)
cpu_relax();
-   
+
if (atp_readb_io(dev, 0, 0x17) != 0x11 && atp_readb_io(dev, 0, 
0x17) != 0x8e)
continue;
 
while (atp_readb_io(dev, 0, 0x17) != 0x8e)
cpu_relax();
-   
+
if (dev->chip_ver == 4)
atp_writeb_io(dev, 0, 0x1b, 0x00);
 
@@ -1286,10 +1288,10 @@ rd_inq_data:
 
while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0x00)
cpu_relax();
-   
-   if (atp_readb_io(dev, 0, 0x17) != 0x16) {
+
+   if (atp_readb_io(dev, 0, 0x17) != 0x16)
goto sel_ok;
-   }
+
 inq_ok:
mbuf[36] = 0;
printk(KERN_INFO " ID: %2d  %s\n", i, &mbuf[8]);
@@ -1321,13 +1323,13 @@ inq_ok:
 
while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0x00)
cpu_relax();
-   
+
if (atp_readb_io(dev, 0, 0x17) != 0x11 && atp_readb_io(dev, 0, 
0x17) != 0x8e)
continue;
 
while (atp_readb_io(dev, 0, 0x17) != 0x8e)
cpu_relax();
-   
+
 try_wide:
j = 0;
atp_writeb_io(dev, 0, 0x14, 0x05);
@@ -1337,10 +1339,10 @@ try_wide:
if ((atp_readb_io(dev, 0, 0x1f) & 0x01) != 0)
atp_writeb_io(dev, 0, 0x19, wide[j++]);
}
-   
+
while ((atp_readb_io(dev, 0, 0x17) & 0x80) == 0x00)
cpu_relax();
-   
+
j = atp_readb_io(dev, 0, 0x17) & 0x0f;
if (j == 0x0f) {
goto widep_in;
@@ -1449,13 +1451,13 @@ set_sync:
 
while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0x00)
cpu_relax();
-   
+
if (atp_readb_io(dev, 0, 0x17) != 0x11 && atp_readb_io(dev, 0, 
0x17) != 0x8e)
continue;
 
while (atp_readb_io(dev, 0, 0x17) != 0x8e)
cpu_relax();
-   
+
 try_sync:
j = 0;
atp_writeb_io(dev, 0, 0x14, 0x06);
@@ -1474,10 +1476,10 @@ try_sync:
}
}
}
-   
+
while ((atp_readb_io(dev, 0, 0x17) & 0x80) == 0x00)
cpu_relax();
-   
+
j = atp_readb_io(dev, 0, 0x17) & 0x0f;
if (j == 0x0f) {
goto phase_ins;
@@ -1526,7 +1528,7 @@ phase_ins1:
 
while ((atp_readb_io(dev, 0, 0x17) & 0x80) == 0x00)
cpu_relax();
-   
+
j = atp_readb_io(dev, 0, 0x17);
if (j == 0x85) {
goto tar_dcons;
@@ -1547,10 +1549,10 @@ phase_cmds:
 tar_dcons:
atp_writeb_io(dev, 0, 0x14, 0x00);
atp_writeb_io(dev, 0, 0x18, 0x08);
-   
+
while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0x00)
cpu_relax();
-   
+
j = atp_readb_io(dev, 0, 0x17);
if (j != 0x16) {
continue;
@@ -1649,7 +1651,7 @@ static void is880(struct atp_unit *dev)
 
while (atp_readb_io(dev, 0, 0x17) != 0x8e)
cpu_relax();
-   
+
dev->active_id[0] |= m;
 
atp_writeb_io(dev, 0, 0x10, 0

[PATCH 42/52] atp870u: Improve unsupported chip detection

2015-11-17 Thread Ondrej Zary
Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   20 
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index d0119f1..128613e 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1252,6 +1252,11 @@ static int atp870u_probe(struct pci_dev *pdev, const 
struct pci_device_id *ent)
unsigned char setupdata[2][16];
int err;
 
+   if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610 && pdev->revision < 2) {
+   dev_err(&pdev->dev, "ATP850S chips (AEC6710L/F cards) are not 
supported.\n");
+   return -ENODEV;
+   }
+
err = pci_enable_device(pdev);
if (err)
goto fail;
@@ -1273,19 +1278,10 @@ static int atp870u_probe(struct pci_dev *pdev, const 
struct pci_device_id *ent)
atpdev->pdev = pdev;
pci_set_drvdata(pdev, atpdev);
 
-   /*
-* It's probably easier to weed out some revisions like
-* this than via the PCI device table
-*/
-   if (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610) {
-   atpdev->chip_ver = pdev->revision;
-   if (atpdev->chip_ver < 2) {
-   err = -ENODEV;
-   goto unregister;
-   }
-   }
-
switch (ent->device) {
+   case PCI_DEVICE_ID_ARTOP_AEC7610:
+   atpdev->chip_ver = pdev->revision;
+   break;
case PCI_DEVICE_ID_ARTOP_AEC7612UW:
case PCI_DEVICE_ID_ARTOP_AEC7612SUW:
case ATP880_DEVID1: 
-- 
Ondrej Zary

--
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 10/52] atp870u: Untangle tmport #8

2015-11-17 Thread Ondrej Zary
Untangle the tmport crap so it becomes obvious what ports are accessed.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |  478 ++--
 1 file changed, 177 insertions(+), 301 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index f5a11f4..993442d 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -2870,7 +2870,6 @@ static void tscam_885(void)
 
 static void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c)
 {
-   unsigned int tmport;
unsigned char i, j, k, rmb, n, lvdmode;
unsigned short int m;
static unsigned char mbuf[512];
@@ -2895,123 +2894,93 @@ static void is885(struct atp_unit *dev, unsigned int 
wkport,unsigned char c)
printk(KERN_INFO " ID: %2d  Host Adapter\n", 
dev->host_id[c]);
continue;
}
-   tmport = wkport + 0x1b;
-   outb(0x01, tmport);
-   tmport = wkport + 0x01;
-   outb(0x08, tmport++);
-   outb(0x7f, tmport++);
-   outb(satn[0], tmport++);
-   outb(satn[1], tmport++);
-   outb(satn[2], tmport++);
-   outb(satn[3], tmport++);
-   outb(satn[4], tmport++);
-   outb(satn[5], tmport++);
-   tmport += 0x06;
-   outb(0, tmport);
-   tmport += 0x02;
-   outb(dev->id[c][i].devsp, tmport++);
+   outb(0x01, wkport + 0x1b);
+   outb(0x08, wkport + 0x01);
+   outb(0x7f, wkport + 0x02);
+   outb(satn[0], wkport + 0x03);
+   outb(satn[1], wkport + 0x04);
+   outb(satn[2], wkport + 0x05);
+   outb(satn[3], wkport + 0x06);
+   outb(satn[4], wkport + 0x07);
+   outb(satn[5], wkport + 0x08);
+   outb(0, wkport + 0x0f);
+   outb(dev->id[c][i].devsp, wkport + 0x11);

-   outb(0, tmport++);
-   outb(satn[6], tmport++);
-   outb(satn[7], tmport++);
+   outb(0, wkport + 0x12);
+   outb(satn[6], wkport + 0x13);
+   outb(satn[7], wkport + 0x14);
j = i;
if ((j & 0x08) != 0) {
j = (j & 0x07) | 0x40;
}
-   outb(j, tmport);
-   tmport += 0x03;
-   outb(satn[8], tmport);
-   tmport += 0x07;
+   outb(j, wkport + 0x15);
+   outb(satn[8], wkport + 0x18);
 
-   while ((inb(tmport) & 0x80) == 0x00)
+   while ((inb(wkport + 0x1f) & 0x80) == 0x00)
cpu_relax();
-   tmport -= 0x08;
-   if ((inb(tmport) != 0x11) && (inb(tmport) != 0x8e)) {
+   if ((inb(wkport + 0x17) != 0x11) && (inb(wkport + 0x17) != 
0x8e)) {
continue;
}
-   while (inb(tmport) != 0x8e)
+   while (inb(wkport + 0x17) != 0x8e)
cpu_relax();
dev->active_id[c] |= m;
 
-   tmport = wkport + 0x10;
-   outb(0x30, tmport);
-   tmport = wkport + 0x14;
-   outb(0x00, tmport);
+   outb(0x30, wkport + 0x10);
+   outb(0x00, wkport + 0x14);
 
 phase_cmd:
-   tmport = wkport + 0x18;
-   outb(0x08, tmport);
-   tmport += 0x07;
-   while ((inb(tmport) & 0x80) == 0x00)
+   outb(0x08, wkport + 0x18);
+   while ((inb(wkport + 0x1f) & 0x80) == 0x00)
cpu_relax();
-   tmport -= 0x08;
-   j = inb(tmport);
+   j = inb(wkport + 0x17);
if (j != 0x16) {
-   tmport = wkport + 0x10;
-   outb(0x41, tmport);
+   outb(0x41, wkport + 0x10);
goto phase_cmd;
}
 sel_ok:
-   tmport = wkport + 0x03;
-   outb(inqd[0], tmport++);
-   outb(inqd[1], tmport++);
-   outb(inqd[2], tmport++);
-   outb(inqd[3], tmport++);
-   outb(inqd[4], tmport++);
-   outb(inqd[5], tmport);
-   tmport += 0x07;
-   outb(0, tmport);
-   tmport += 0x02;
-   outb(dev->id[c][i].devsp, tmport++);
-   outb(0, tmport++);
-   outb(inqd[6], tmport++);
-   outb(inqd[7], tmport++);
-   tmport += 0x03;
-   outb(inqd[8], tmport);
-   tmport += 0x07;
-   while ((inb(tmport) & 0x80) == 0x00)
+   outb(inqd[0], wkport + 0x03);
+   outb(inqd[1], wkport + 0x04);
+   outb(inqd[2], wkport + 0x05);
+   outb(inqd[3], wkport + 0x06);
+   o

[PATCH 27/52] atp870u: Add remaining 870 support to is885()

2015-11-17 Thread Ondrej Zary
Add remaining 870 support to is885():
 - different synw, no synuw
 - synu[4] = 0x0c
 - atp_writeb_io(dev, c, 0x04, 0x00); instead of
   atp_writeb_io(dev, c, 0x14, 0x00); (isn't that a bug?)
 - atp_writeb_io(dev, c, 0x14, 0xff); instead of
   atp_writeb_io(dev, c, 0x14, 0x06);
 - different mbuf[3] and mbuf[4] checks

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   45 +++--
 1 file changed, 31 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 0548d07..d76d386 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -2262,6 +2262,7 @@ static void is885(struct atp_unit *dev, unsigned char c, 
bool wide_chip, unsigne
static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
+   static unsigned char synw_870[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 };
unsigned char synuw[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 
0x02 };
@@ -2311,7 +2312,10 @@ static void is885(struct atp_unit *dev, unsigned char c, 
bool wide_chip, unsigne
dev->active_id[c] |= m;
 
atp_writeb_io(dev, c, 0x10, 0x30);
-   atp_writeb_io(dev, c, 0x14, 0x00);
+   if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 
|| dev->dev_id == ATP880_DEVID2)
+   atp_writeb_io(dev, c, 0x14, 0x00);
+   else /* result of is870() merge - is this a bug? */
+   atp_writeb_io(dev, c, 0x04, 0x00);
 
 phase_cmd:
atp_writeb_io(dev, c, 0x18, 0x08);
@@ -2657,7 +2661,7 @@ not_wide:
}
continue;
 set_sync:
-   if (dev->sp[c][i] == 0x02) {
+   if ((dev->dev_id != ATP885_DEVID && dev->dev_id != 
ATP880_DEVID1 && dev->dev_id != ATP880_DEVID2) || (dev->sp[c][i] == 0x02)) {
synu[4] = 0x0c;
synuw[4] = 0x0c;
} else {
@@ -2701,11 +2705,14 @@ try_sync:
while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0) {
if ((atp_readb_io(dev, c, 0x1f) & 0x01) != 0) {
if ((m & dev->wide_id[c]) != 0) {
-   if ((m & dev->ultra_map[c]) != 0) {
-   atp_writeb_io(dev, c, 0x19, 
synuw[j++]);
-   } else {
-   atp_writeb_io(dev, c, 0x19, 
synw[j++]);
-   }
+   if (dev->dev_id == ATP885_DEVID || 
dev->dev_id == ATP880_DEVID1 || dev->dev_id == ATP880_DEVID2) {
+   if ((m & dev->ultra_map[c]) != 
0) {
+   atp_writeb_io(dev, c, 
0x19, synuw[j++]);
+   } else {
+   atp_writeb_io(dev, c, 
0x19, synw[j++]);
+   }
+   } else
+   atp_writeb_io(dev, c, 0x19, 
synw_870[j++]);
} else {
if ((m & dev->ultra_map[c]) != 0) {
atp_writeb_io(dev, c, 0x19, 
synu[j++]);
@@ -2753,7 +2760,10 @@ phase_outs:
}
continue;
 phase_ins:
-   atp_writeb_io(dev, c, 0x14, 0x06);
+   if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 
|| dev->dev_id == ATP880_DEVID2)
+   atp_writeb_io(dev, c, 0x14, 0x06);
+   else
+   atp_writeb_io(dev, c, 0x14, 0xff);
atp_writeb_io(dev, c, 0x18, 0x20);
k = 0;
 phase_ins1:
@@ -2808,14 +2818,21 @@ tar_dcons:
if (mbuf[3] > 0x64) {
continue;
}
-   if (mbuf[4] > 0x0e) {
-   mbuf[4] = 0x0e;
+   if (dev->dev_id == ATP885_DEVID || dev->dev_id == ATP880_DEVID1 
|| dev->dev_id == ATP880_DEVID2) {
+   if (mbuf[4] > 0x0e) {
+   mbuf[4] = 0x0e;
+   }
+   } else {
+   if (mbuf[4] > 0x0c) {
+   mbuf[4] = 0x0c;
+   }
}
dev->id[c][i].devsp = mbuf[4];
-   if (mbuf[3] < 0x0c) {
-   j = 0xb0;
-   goto set_syn_ok;
-   }
+   if (dev->dev_id == ATP885_DEVID || dev->dev

[PATCH 43/52] atp870u: Remove chip_ver from struct atp_unit

2015-11-17 Thread Ondrej Zary
chip_ver is used for wide chip detection only. Remove it and use a local
variable instead (for 870; 880 and 885 are always wide).

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   39 ++-
 drivers/scsi/atp870u.h |1 -
 2 files changed, 14 insertions(+), 26 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 128613e..f92eb00 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -954,7 +954,7 @@ static unsigned char fun_scam(struct atp_unit *dev, 
unsigned short int *val)
return j;
 }
 
-static void tscam(struct Scsi_Host *host)
+static void tscam(struct Scsi_Host *host, bool wide_chip)
 {
 
unsigned char i, j, k;
@@ -983,7 +983,7 @@ static void tscam(struct Scsi_Host *host)
m = 1;
m <<= dev->host_id[0];
j = 16;
-   if (dev->chip_ver < 4) {
+   if (!wide_chip) {
m |= 0xff00;
j = 8;
}
@@ -1012,7 +1012,7 @@ static void tscam(struct Scsi_Host *host)
k = i;
}
atp_writeb_io(dev, 0, 0x15, k);
-   if (dev->chip_ver == 4)
+   if (wide_chip)
atp_writeb_io(dev, 0, 0x1b, 0x01);
else
atp_writeb_io(dev, 0, 0x1b, 0x00);
@@ -1278,25 +1278,11 @@ static int atp870u_probe(struct pci_dev *pdev, const 
struct pci_device_id *ent)
atpdev->pdev = pdev;
pci_set_drvdata(pdev, atpdev);
 
-   switch (ent->device) {
-   case PCI_DEVICE_ID_ARTOP_AEC7610:
-   atpdev->chip_ver = pdev->revision;
-   break;
-   case PCI_DEVICE_ID_ARTOP_AEC7612UW:
-   case PCI_DEVICE_ID_ARTOP_AEC7612SUW:
-   case ATP880_DEVID1: 
-   case ATP880_DEVID2: 
-   case ATP885_DEVID:  
-   atpdev->chip_ver = 0x04;
-   default:
-   break;
-   }
base_io = pci_resource_start(pdev, 0);
base_io &= 0xfff8;
atpdev->baseport = base_io;
 
if ((ent->device == ATP880_DEVID1)||(ent->device == ATP880_DEVID2)) {
-   atpdev->chip_ver = pdev->revision;
pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803
 
atpdev->ioport[0] = base_io + 0x40;
@@ -1390,7 +1376,7 @@ flash_ok_880:
 
atp_set_host_id(atpdev, 0, host_id);
 
-   tscam(shpnt);
+   tscam(shpnt, true);
atp_is(atpdev, 0, true, atp_readb_base(atpdev, 0x3f) & 0x40);
atp_writeb_base(atpdev, 0x38, 0xb0);
shpnt->max_id = 16;
@@ -1536,6 +1522,11 @@ flash_ok_885:
shpnt->irq = pdev->irq;

} else {
+   bool wide_chip =
+   (ent->device == PCI_DEVICE_ID_ARTOP_AEC7610 &&
+pdev->revision == 4) ||
+   (ent->device == PCI_DEVICE_ID_ARTOP_AEC7612UW) ||
+   (ent->device == PCI_DEVICE_ID_ARTOP_AEC7612SUW);
error = pci_read_config_byte(pdev, 0x49, &host_id);
 
printk(KERN_INFO "   ACARD AEC-671X PCI Ultra/W SCSI-2/3 Host 
Adapter: "
@@ -1569,7 +1560,7 @@ flash_ok_885:
}
 
spin_lock_irqsave(shpnt->host_lock, flags);
-   if (atpdev->chip_ver > 0x07)/* check if atp876 chip then 
enable terminator */
+   if (pdev->revision > 0x07)  /* check if atp876 chip then 
enable terminator */
atp_writeb_base(atpdev, 0x3e, 0x00);
  
k = (atp_readb_base(atpdev, 0x3a) & 0xf3) | 0x10;
@@ -1580,15 +1571,13 @@ flash_ok_885:
mdelay(32);
atp_set_host_id(atpdev, 0, host_id);
 
-   tscam(shpnt);
+
+   tscam(shpnt, wide_chip);
atp_writeb_base(atpdev, 0x3a, atp_readb_base(atpdev, 0x3a) | 
0x10);
-   atp_is(atpdev, 0, atpdev->chip_ver == 4, 0);
+   atp_is(atpdev, 0, wide_chip, 0);
atp_writeb_base(atpdev, 0x3a, atp_readb_base(atpdev, 0x3a) & 
0xef);
atp_writeb_base(atpdev, 0x3b, atp_readb_base(atpdev, 0x3b) | 
0x20);
-   if (atpdev->chip_ver == 4)
-   shpnt->max_id = 16;
-   else
-   shpnt->max_id = 8;
+   shpnt->max_id = wide_chip ? 16 : 8;
shpnt->this_id = host_id;
shpnt->unique_id = base_io;
shpnt->io_port = base_io;
diff --git a/drivers/scsi/atp870u.h b/drivers/scsi/atp870u.h
index c3c6c13..8c47c53 100644
--- a/drivers/scsi/atp870u.h
+++ b/drivers/scsi/atp870u.h
@@ -32,7 +32,6 @@ struct atp_unit
unsigned char quhd[2];
unsigned char quend[2];
unsigned char global_map[2];
-   unsigned char chip_ver;
unsigned char scam_on;
unsigned char host_id[2];
unsigned int working[2];
--

[PATCH 34/52] atp870u: Introduce atp_set_host_id

2015-11-17 Thread Ondrej Zary
The code for setting host adapter ID is the same for all chips.
Move it to a common function.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   57 +++-
 1 file changed, 18 insertions(+), 39 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 04b29d3..9621403 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1229,6 +1229,18 @@ static int atp870u_init_tables(struct Scsi_Host *host)
return 0;
 }
 
+static void atp_set_host_id(struct atp_unit *atp, u8 c, u8 host_id)
+{
+   atp_writeb_io(atp, c, 0, host_id | 0x08);
+   atp_writeb_io(atp, c, 0x18, 0);
+   while ((atp_readb_io(atp, c, 0x1f) & 0x80) == 0)
+   mdelay(1);
+   atp_readb_io(atp, c, 0x17);
+   atp_writeb_io(atp, c, 1, 8);
+   atp_writeb_io(atp, c, 2, 0x7f);
+   atp_writeb_io(atp, c, 0x11, 0x20);
+}
+
 /* return non-zero on detection */
 static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
@@ -1379,14 +1391,8 @@ flash_ok_880:
mdelay(32);
atp_readb_io(p, 0, 0x1b);
atp_readb_io(p, 0, 0x17);
-   atp_writeb_io(p, 0, 0, host_id | 0x08);
-   atp_writeb_io(p, 0, 0x18, 0);
-   while ((atp_readb_io(p, 0, 0x1f) & 0x80) == 0)
-   mdelay(1);
-   atp_readb_io(p, 0, 0x17);
-   atp_writeb_io(p, 0, 1, 8);
-   atp_writeb_io(p, 0, 2, 0x7f);
-   atp_writeb_io(p, 0, 0x11, 0x20);
+
+   atp_set_host_id(p, 0, host_id);
 
tscam(shpnt);
atp_is(p, 0, true, atp_readb_base(p, 0x3f) & 0x40);
@@ -1503,35 +1509,16 @@ flash_ok_885:
atp_readb_io(p, 0, 0x17);
atp_readb_io(p, 1, 0x1b);
atp_readb_io(p, 1, 0x17);
+
k=p->host_id[0];
if (k > 7)
   k = (k & 0x07) | 0x40;
-   k |= 0x08;
-   atp_writeb_io(p, 0, 0, k);
-   atp_writeb_io(p, 0, 0x18, 0);
-
-   while ((atp_readb_io(p, 0, 0x1f) & 0x80) == 0)
-   cpu_relax();
-   
-   atp_readb_io(p, 0, 0x17);
-   atp_writeb_io(p, 0, 1, 8);
-   atp_writeb_io(p, 0, 2, 0x7f);
-   atp_writeb_io(p, 0, 0x11, 0x20);
+   atp_set_host_id(p, 0, k);
 
k=p->host_id[1];
if (k > 7)
   k = (k & 0x07) | 0x40;
-   k |= 0x08;
-   atp_writeb_io(p, 1, 0, k);
-   atp_writeb_io(p, 1, 0x18, 0);
-
-   while ((atp_readb_io(p, 1, 0x1f) & 0x80) == 0)
-   cpu_relax();
-
-   atp_readb_io(p, 1, 0x17);
-   atp_writeb_io(p, 1, 1, 8);
-   atp_writeb_io(p, 1, 2, 0x7f);
-   atp_writeb_io(p, 1, 0x11, 0x20);
+   atp_set_host_id(p, 1, k);
 
tscam_885();
printk(KERN_INFO "   Scanning Channel A SCSI Device ...\n");
@@ -1608,15 +1595,7 @@ flash_ok_885:
mdelay(32);
atp_writeb_base(p, 0x3a, k);
mdelay(32);
-   atp_writeb_io(p, 0, 0, host_id | 0x08);
-   atp_writeb_io(p, 0, 0x18, 0);
-   while ((atp_readb_io(p, 0, 0x1f) & 0x80) == 0)
-   mdelay(1);
-
-   atp_readb_io(p, 0, 0x17);
-   atp_writeb_io(p, 0, 1, 8);
-   atp_writeb_io(p, 0, 2, 0x7f);
-   atp_writeb_io(p, 0, 0x11, 0x20);
+   atp_set_host_id(p, 0, host_id);
 
tscam(shpnt);
atp_writeb_base(p, 0x3a, atp_readb_base(p, 0x3a) | 0x10);
-- 
Ondrej Zary

--
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 47/52] atp870u: Request IRQ later, remove weird locking

2015-11-17 Thread Ondrej Zary
Allocate IRQ later during probe to avoid code duplication and also remove
the need for weird locking in _probe.
(It was probably there to prevent race with the IRQ handler?)

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   47 ---
 1 file changed, 12 insertions(+), 35 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 87dd886..4719df4 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1253,7 +1253,6 @@ static void atp_set_host_id(struct atp_unit *atp, u8 c, 
u8 host_id)
 static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
unsigned char k, m, c;
-   unsigned long flags;
unsigned int error,n;
unsigned char host_id;
struct Scsi_Host *shpnt = NULL;
@@ -1374,13 +1373,6 @@ flash_ok_880:
goto unregister;
}
 
-   err = request_irq(shpnt->irq, atp870u_intr_handle, IRQF_SHARED, 
"atp880i", shpnt);
-   if (err) {
-   printk(KERN_ERR "Unable to allocate IRQ%d for Acard 
controller.\n", shpnt->irq);
-   goto free_tables;
-   }
-
-   spin_lock_irqsave(shpnt->host_lock, flags);
k = atp_readb_base(atpdev, 0x38) & 0x80;
atp_writeb_base(atpdev, 0x38, k);
atp_writeb_base(atpdev, 0x3b, 0x20);
@@ -1412,17 +1404,6 @@ flash_ok_880:
goto unregister;
}

-#ifdef ED_DBGP 
-   printk("request_irq() shpnt %p hostdata %p\n", shpnt, atpdev);
-#endif 
-   err = request_irq(shpnt->irq, atp870u_intr_handle, IRQF_SHARED, 
"atp870u", shpnt);
-   if (err) {
-   printk(KERN_ERR "Unable to allocate IRQ for 
Acard controller.\n");
-   goto free_tables;
-   }
-   
-   spin_lock_irqsave(shpnt->host_lock, flags); 

-   
c = atp_readb_base(atpdev, 0x29);
atp_writeb_base(atpdev, 0x29, c | 0x04);

@@ -1558,13 +1539,6 @@ flash_ok_885:
goto unregister;
}
 
-   err = request_irq(shpnt->irq, atp870u_intr_handle, IRQF_SHARED, 
"atp870i", shpnt);
-   if (err) {
-   printk(KERN_ERR "Unable to allocate IRQ%d for Acard 
controller.\n", shpnt->irq);
-   goto free_tables;
-   }
-
-   spin_lock_irqsave(shpnt->host_lock, flags);
if (pdev->revision > 0x07)  /* check if atp876 chip then 
enable terminator */
atp_writeb_base(atpdev, 0x3e, 0x00);
  
@@ -1586,15 +1560,18 @@ flash_ok_885:
shpnt->this_id = host_id;
 
} 
-   spin_unlock_irqrestore(shpnt->host_lock, flags);
-   err = scsi_add_host(shpnt, &pdev->dev);
-   if (err)
-   goto scsi_add_fail;
-   scsi_scan_host(shpnt);
-#ifdef ED_DBGP 
-   printk("atp870u_prob : exit\n");
-#endif 
-   return 0;
+   err = request_irq(shpnt->irq, atp870u_intr_handle, IRQF_SHARED, 
"atp870u", shpnt);
+   if (err) {
+   dev_err(&pdev->dev, "Unable to allocate IRQ %d.\n", shpnt->irq);
+   goto free_tables;
+   }
+
+   err = scsi_add_host(shpnt, &pdev->dev);
+   if (err)
+   goto scsi_add_fail;
+   scsi_scan_host(shpnt);
+
+   return 0;
 
 scsi_add_fail:
free_irq(shpnt->irq, shpnt);
-- 
Ondrej Zary

--
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 40/52] atp870u: Remove unused irq from struct atp_unit

2015-11-17 Thread Ondrej Zary
Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.h |1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/scsi/atp870u.h b/drivers/scsi/atp870u.h
index 5cf6256..c3c6c13 100644
--- a/drivers/scsi/atp870u.h
+++ b/drivers/scsi/atp870u.h
@@ -26,7 +26,6 @@ struct atp_unit
unsigned long baseport;
unsigned long ioport[2];
unsigned long pciport[2];
-   unsigned long irq;
unsigned char last_cmd[2];
unsigned char in_snd[2];
unsigned char in_int[2];
-- 
Ondrej Zary

--
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 12/52] atp870u: Untangle tmpcip #2

2015-11-17 Thread Ondrej Zary
Untangle the tmpcip crap so it becomes obvious what ports are accessed.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   25 +
 1 file changed, 9 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 32544bb..4d840a5 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -645,7 +645,7 @@ static void send_s870(struct atp_unit *dev,unsigned char c)
unsigned int i;//,k;
unsigned char  j, target_id;
unsigned char *prd;
-   unsigned short int tmpcip, w;
+   unsigned short int w;
unsigned long l, bttl = 0;
unsigned long  sg_count;
 
@@ -813,7 +813,6 @@ oktosend:
dev->in_snd[c] = 0;
return;
}
-   tmpcip = dev->pciport[c];
prd = dev->id[c][target_id].prd_table;
dev->id[c][target_id].prd_pos = prd;
 
@@ -850,34 +849,28 @@ oktosend:
printk("2. bttl %x, l %x\n",bttl, l);
 #endif 
}
-   tmpcip += 4;
 #ifdef ED_DBGP 
-   printk("send_s870: prdaddr_2 0x%8x tmpcip %x target_id %d\n", 
dev->id[c][target_id].prdaddr,tmpcip,target_id);
+   printk("send_s870: prdaddr_2 0x%8x target_id %d\n", 
dev->id[c][target_id].prdaddr,target_id);
 #endif 
dev->id[c][target_id].prdaddr = dev->id[c][target_id].prd_bus;
-   outl(dev->id[c][target_id].prdaddr, tmpcip);
-   tmpcip = tmpcip - 2;
-   outb(0x06, tmpcip);
-   outb(0x00, tmpcip);
+   outl(dev->id[c][target_id].prdaddr, dev->pciport[c] + 4);
+   outb(0x06, dev->pciport[c] + 2);
+   outb(0x00, dev->pciport[c] + 2);
if (dev->dev_id == ATP885_DEVID) {
-   tmpcip--;
-   j=inb(tmpcip) & 0xf3;
+   j = inb(dev->pciport[c] + 1) & 0xf3;
if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) ||
(workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
j |= 0x0c;
}
-   outb(j,tmpcip);
-   tmpcip--;   
+   outb(j, dev->pciport[c] + 1);
} else if ((dev->dev_id == ATP880_DEVID1) ||
   (dev->dev_id == ATP880_DEVID2)) {
-   tmpcip =tmpcip -2;  
if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || 
(workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
outb((unsigned char) ((inb(dev->ioport[c] - 0x05) & 
0x3f) | 0xc0), dev->ioport[c] - 0x05);
} else {
outb((unsigned char) (inb(dev->ioport[c] - 0x05) & 
0x3f), dev->ioport[c] - 0x05);
}   
} else {
-   tmpcip =tmpcip -2;
if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || 
(workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a)) {
outb((inb(dev->ioport[c] + 0x3a) & 0xf3) | 0x08, 
dev->ioport[c] + 0x3a);
} else {
@@ -889,7 +882,7 @@ oktosend:
dev->id[c][target_id].dirct = 0x20;
if (inb(dev->ioport[c] + 0x1c) == 0) {
outb(0x08, dev->ioport[c] + 0x18);
-   outb(0x01, tmpcip);
+   outb(0x01, dev->pciport[c]);
 #ifdef ED_DBGP 
printk( "start DMA(to target)\n");
 #endif 
@@ -901,7 +894,7 @@ oktosend:
}
if (inb(dev->ioport[c] + 0x1c) == 0) {
outb(0x08, dev->ioport[c] + 0x18);
-   outb(0x09, tmpcip);
+   outb(0x09, dev->pciport[c]);
 #ifdef ED_DBGP 
printk( "start DMA(to host)\n");
 #endif 
-- 
Ondrej Zary

--
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 37/52] atp870u: Use module_pci_driver

2015-11-17 Thread Ondrej Zary
Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   20 +---
 1 file changed, 1 insertion(+), 19 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 2570919..7f53a50 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1785,21 +1785,7 @@ static struct pci_driver atp870u_driver = {
.remove = atp870u_remove,
 };
 
-static int __init atp870u_init(void)
-{
-#ifdef ED_DBGP 
-   printk("atp870u_init: Entry\n");
-#endif 
-   return pci_register_driver(&atp870u_driver);
-}
-
-static void __exit atp870u_exit(void)
-{
-#ifdef ED_DBGP 
-   printk("atp870u_exit: Entry\n");
-#endif
-   pci_unregister_driver(&atp870u_driver);
-}
+module_pci_driver(atp870u_driver);
 
 static void atp_is(struct atp_unit *dev, unsigned char c, bool wide_chip, 
unsigned char lvdmode)
 {
@@ -2406,7 +2392,3 @@ set_syn_ok:
 #endif
}
 }
-
-module_init(atp870u_init);
-module_exit(atp870u_exit);
-
-- 
Ondrej Zary

--
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 17/52] atp870u: Remove ugly gotos #5

2015-11-17 Thread Ondrej Zary
Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |  134 ++--
 1 file changed, 62 insertions(+), 72 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 68afe11..fd2bb6f 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1007,28 +1007,22 @@ static void tscam(struct Scsi_Host *host)
;
outb(1, 0x80);
udelay(100);
-   for (n = 0; n < 0x3; n++) {
-   if ((inb(dev->ioport[0] + 0x1c) & 0x80) != 0) { /* bsy ? */
-   goto wait_io;
-   }
-   }
-   goto TCM_SYNC;
-wait_io:
-   for (n = 0; n < 0x3; n++) {
-   if ((inb(dev->ioport[0] + 0x1c) & 0x81) == 0x0081) {
-   goto wait_io1;
-   }
-   }
-   goto TCM_SYNC;
-wait_io1:
-   inb(0x80);
-   val |= 0x8003;  /* io,cd,db7  */
-   outw(val, dev->ioport[0] + 0x1c);
-   inb(0x80);
-   val &= 0x00bf;  /* no sel */
-   outw(val, dev->ioport[0] + 0x1c);
-   outb(2, 0x80);
-TCM_SYNC:
+   for (n = 0; n < 0x3; n++)
+   if ((inb(dev->ioport[0] + 0x1c) & 0x80) != 0)   /* bsy ? */
+   break;
+   if (n < 0x3)
+   for (n = 0; n < 0x3; n++)
+   if ((inb(dev->ioport[0] + 0x1c) & 0x81) == 0x0081) {
+   inb(0x80);
+   val |= 0x8003;  /* io,cd,db7  */
+   outw(val, dev->ioport[0] + 0x1c);
+   inb(0x80);
+   val &= 0x00bf;  /* no sel */
+   outw(val, dev->ioport[0] + 0x1c);
+   outb(2, 0x80);
+   break;
+   }
+   while (1) {
/*
 * The funny division into multiple delays is to accomodate
 * arches like ARM where udelay() multiplies its argument by
@@ -1059,31 +1053,28 @@ TCM_SYNC:
outb(4, 0x80);
i = 8;
j = 0;
-TCM_ID:
-   if ((inw(dev->ioport[0] + 0x1c) & 0x2000) == 0) {
-   goto TCM_ID;
-   }
-   outb(5, 0x80);
-   val &= 0x00ff;  /* get ID_STRING */
-   val |= 0x2000;
-   k = fun_scam(dev, &val);
-   if ((k & 0x03) == 0) {
-   goto TCM_5;
-   }
-   mbuf[j] <<= 0x01;
-   mbuf[j] &= 0xfe;
-   if ((k & 0x02) != 0) {
-   mbuf[j] |= 0x01;
-   }
-   i--;
-   if (i > 0) {
-   goto TCM_ID;
+
+   while (1) {
+   if ((inw(dev->ioport[0] + 0x1c) & 0x2000) == 0)
+   continue;
+   outb(5, 0x80);
+   val &= 0x00ff;  /* get ID_STRING */
+   val |= 0x2000;
+   k = fun_scam(dev, &val);
+   if ((k & 0x03) == 0)
+   break;
+   mbuf[j] <<= 0x01;
+   mbuf[j] &= 0xfe;
+   if ((k & 0x02) != 0)
+   mbuf[j] |= 0x01;
+   i--;
+   if (i > 0)
+   continue;
+   j++;
+   i = 8;
}
-   j++;
-   i = 8;
-   goto TCM_ID;
 
-TCM_5: /* isolation complete..  */
+   /* isolation complete..  */
 /*mbuf[32]=0;
printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */
i = 15;
@@ -1091,33 +1082,33 @@ TCM_5:  /* isolation complete..  */
if ((j & 0x20) != 0) {  /* bit5=1:ID up to 7  */
i = 7;
}
-   if ((j & 0x06) == 0) {  /* IDvalid? */
-   goto G2Q5;
-   }
-   k = mbuf[1];
-small_id:
-   m = 1;
-   m <<= k;
-   if ((m & assignid_map) == 0) {
-   goto G2Q_QUIN;
-   }
-   if (k > 0) {
-   k--;
-   goto small_id;
-   }
-G2Q5:  /* srch from max acceptable ID#  */
-   k = i;  /* max acceptable ID#*/
-G2Q_LP:
-   m = 1;
-   m <<= k;
-   if ((m & assignid_map) == 0) {
-   goto G2Q_QUIN;
+   if ((j & 0x06) != 0) {  /* IDvalid? */
+   k = mbuf[1];
+   while (1) {
+   m = 1;
+   m <<= k;
+   if ((m & assignid_map) == 0)
+   break;
+   if (k > 0)
+   k--;
+   else
+   break;
+   }
}
-   if (k > 0) {
-   k--;
-   goto G2Q_LP;
+   if ((m & assignid_map) != 0) {  /* srch from max acceptable ID#  */
+   k = i;  /* max acceptable ID#*/
+   while (1) {
+   m = 1;
+  

[PATCH 46/52] atp870u: Use pci_request_regions

2015-11-17 Thread Ondrej Zary
Use pci_request_regions and do it before accessing the I/O ports.
Also add missing pci_disable_device() call to atp870u_remove().

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   21 ++---
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 4bb0f4f..87dd886 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1276,10 +1276,15 @@ static int atp870u_probe(struct pci_dev *pdev, const 
struct pci_device_id *ent)
 goto disable_device;
 }
 
+   err = pci_request_regions(pdev, "atp870u");
+   if (err)
+   goto disable_device;
+   pci_set_master(pdev);
+
 err = -ENOMEM;
shpnt = scsi_host_alloc(&atp870u_template, sizeof(struct atp_unit));
if (!shpnt)
-   goto disable_device;
+   goto release_region;
 
atpdev = shost_priv(shpnt);
 
@@ -1582,10 +1587,6 @@ flash_ok_885:
 
} 
spin_unlock_irqrestore(shpnt->host_lock, flags);
-   if (!request_region(shpnt->io_port, shpnt->n_io_port, 
"atp870u")) {
-   err = -EBUSY;
-   goto request_io_fail;
-   }
err = scsi_add_host(shpnt, &pdev->dev);
if (err)
goto scsi_add_fail;
@@ -1596,16 +1597,13 @@ flash_ok_885:
return 0;
 
 scsi_add_fail:
-   printk("atp870u_prob:scsi_add_fail\n");
-   release_region(shpnt->io_port, shpnt->n_io_port);
-request_io_fail:
-   printk("atp870u_prob:request_io_fail\n");
free_irq(shpnt->irq, shpnt);
 free_tables:
-   printk("atp870u_prob:free_table\n");
atp870u_free_tables(shpnt);
 unregister:
scsi_host_put(shpnt);
+release_region:
+   pci_release_regions(pdev);
 disable_device:
pci_disable_device(pdev);
 fail:
@@ -1696,7 +1694,8 @@ static void atp870u_remove (struct pci_dev *pdev)

scsi_remove_host(pshost);
free_irq(pshost->irq, pshost);
-   release_region(pshost->io_port, pshost->n_io_port);
+   pci_release_regions(pdev);
+   pci_disable_device(pdev);
atp870u_free_tables(pshost);
scsi_host_put(pshost);
 }
-- 
Ondrej Zary

--
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 44/52] atp870u: Simplify _probe()

2015-11-17 Thread Ondrej Zary
Move shpnt common code to the top, remove base_io, use pci_resource_len.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   65 +---
 1 file changed, 28 insertions(+), 37 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index f92eb00..8af51a9 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1245,7 +1245,7 @@ static int atp870u_probe(struct pci_dev *pdev, const 
struct pci_device_id *ent)
 {
unsigned char k, m, c;
unsigned long flags;
-   unsigned int base_io, error,n;
+   unsigned int error,n;
unsigned char host_id;
struct Scsi_Host *shpnt = NULL;
struct atp_unit *atpdev;
@@ -1278,21 +1278,24 @@ static int atp870u_probe(struct pci_dev *pdev, const 
struct pci_device_id *ent)
atpdev->pdev = pdev;
pci_set_drvdata(pdev, atpdev);
 
-   base_io = pci_resource_start(pdev, 0);
-   base_io &= 0xfff8;
-   atpdev->baseport = base_io;
+   shpnt->io_port = pci_resource_start(pdev, 0);
+   shpnt->io_port &= 0xfff8;
+   shpnt->n_io_port = pci_resource_len(pdev, 0);
+   atpdev->baseport = shpnt->io_port;
+   shpnt->unique_id = shpnt->io_port;
+   shpnt->irq = pdev->irq;
 
if ((ent->device == ATP880_DEVID1)||(ent->device == ATP880_DEVID2)) {
pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803
 
-   atpdev->ioport[0] = base_io + 0x40;
-   atpdev->pciport[0] = base_io + 0x28;
+   atpdev->ioport[0] = shpnt->io_port + 0x40;
+   atpdev->pciport[0] = shpnt->io_port + 0x28;
 
host_id = atp_readb_base(atpdev, 0x39);
host_id >>= 0x04;
 
printk(KERN_INFO "   ACARD AEC-67160 PCI Ultra3 LVD Host 
Adapter:"
-   "IO:%x, IRQ:%d.\n", base_io, pdev->irq);
+   "IO:%lx, IRQ:%d.\n", shpnt->io_port, shpnt->irq);
atpdev->dev_id = ent->device;
atpdev->host_id[0] = host_id;
 
@@ -1358,9 +1361,9 @@ flash_ok_880:
goto unregister;
}
 
-   err = request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, 
"atp880i", shpnt);
+   err = request_irq(shpnt->irq, atp870u_intr_handle, IRQF_SHARED, 
"atp880i", shpnt);
if (err) {
-   printk(KERN_ERR "Unable to allocate IRQ%d for Acard 
controller.\n", pdev->irq);
+   printk(KERN_ERR "Unable to allocate IRQ%d for Acard 
controller.\n", shpnt->irq);
goto free_tables;
}
 
@@ -1381,20 +1384,16 @@ flash_ok_880:
atp_writeb_base(atpdev, 0x38, 0xb0);
shpnt->max_id = 16;
shpnt->this_id = host_id;
-   shpnt->unique_id = base_io;
-   shpnt->io_port = base_io;
-   shpnt->n_io_port = 0x60;/* Number of bytes of I/O space 
used */
-   shpnt->irq = pdev->irq; 
} else if (ent->device == ATP885_DEVID) {   
-   printk(KERN_INFO "   ACARD AEC-67162 PCI Ultra3 LVD 
Host Adapter:  IO:%x, IRQ:%d.\n"
-  , base_io, pdev->irq);
+   printk(KERN_INFO "   ACARD AEC-67162 PCI Ultra3 LVD 
Host Adapter:  IO:%lx, IRQ:%d.\n"
+  , shpnt->io_port, shpnt->irq);

atpdev->pdev = pdev;
atpdev->dev_id  = ent->device;
-   atpdev->ioport[0] = base_io + 0x80;
-   atpdev->ioport[1] = base_io + 0xc0;
-   atpdev->pciport[0] = base_io + 0x40;
-   atpdev->pciport[1] = base_io + 0x50;
+   atpdev->ioport[0] = shpnt->io_port + 0x80;
+   atpdev->ioport[1] = shpnt->io_port + 0xc0;
+   atpdev->pciport[0] = shpnt->io_port + 0x40;
+   atpdev->pciport[1] = shpnt->io_port + 0x50;

if (atp870u_init_tables(shpnt) < 0) {
err = -ENOMEM;
@@ -1404,7 +1403,7 @@ flash_ok_880:
 #ifdef ED_DBGP 
printk("request_irq() shpnt %p hostdata %p\n", shpnt, atpdev);
 #endif 
-   err = request_irq(pdev->irq, atp870u_intr_handle, IRQF_SHARED, 
"atp870u", shpnt);
+   err = request_irq(shpnt->irq, atp870u_intr_handle, IRQF_SHARED, 
"atp870u", shpnt);
if (err) {
printk(KERN_ERR "Unable to allocate IRQ for 
Acard controller.\n");
goto free_tables;
@@ -1516,11 +1515,6 @@ flash_ok_885:
shpnt->max_lun = (atpdev->global_map[0] & 0x07) + 1;
shpnt->max_channel = 1;
shpnt->this_id = atpdev->host_id[0];
-   shpnt->unique_id = base_io;
-   shpnt->io_port = base_io;
-   shpnt->n_io_port = 0xff;  

[PATCH 14/52] atp870u: Remove ugly gotos #2

2015-11-17 Thread Ondrej Zary
Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   68 +---
 1 file changed, 30 insertions(+), 38 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 886e54b..999bf74 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -617,7 +617,7 @@ static DEF_SCSI_QCMD(atp870u_queuecommand)
  */
 static void send_s870(struct atp_unit *dev,unsigned char c)
 {
-   struct scsi_cmnd *workreq;
+   struct scsi_cmnd *workreq = NULL;
unsigned int i;//,k;
unsigned char  j, target_id;
unsigned char *prd;
@@ -638,50 +638,42 @@ static void send_s870(struct atp_unit *dev,unsigned char 
c)
if ((dev->last_cmd[c] != 0xff) && ((dev->last_cmd[c] & 0x40) != 0)) {
dev->last_cmd[c] &= 0x0f;
workreq = dev->id[c][dev->last_cmd[c]].curr_req;
-   if (workreq != NULL) {  /* check NULL pointer */
-  goto cmd_subp;
-   }
-   dev->last_cmd[c] = 0xff;
-   if (dev->quhd[c] == dev->quend[c]) {
-   dev->in_snd[c] = 0;
-   return ;
+   if (!workreq) {
+   dev->last_cmd[c] = 0xff;
+   if (dev->quhd[c] == dev->quend[c]) {
+   dev->in_snd[c] = 0;
+   return;
+   }
}
}
-   if ((dev->last_cmd[c] != 0xff) && (dev->working[c] != 0)) {
-   dev->in_snd[c] = 0;
-   return ;
-   }
-   dev->working[c]++;
-   j = dev->quhd[c];
-   dev->quhd[c]++;
-   if (dev->quhd[c] >= qcnt) {
-   dev->quhd[c] = 0;
-   }
-   workreq = dev->quereq[c][dev->quhd[c]];
-   if (dev->id[c][scmd_id(workreq)].curr_req == NULL) {
+   if (!workreq) {
+   if ((dev->last_cmd[c] != 0xff) && (dev->working[c] != 0)) {
+   dev->in_snd[c] = 0;
+   return;
+   }
+   dev->working[c]++;
+   j = dev->quhd[c];
+   dev->quhd[c]++;
+   if (dev->quhd[c] >= qcnt)
+   dev->quhd[c] = 0;
+   workreq = dev->quereq[c][dev->quhd[c]];
+   if (dev->id[c][scmd_id(workreq)].curr_req != NULL) {
+   dev->quhd[c] = j;
+   dev->working[c]--;
+   dev->in_snd[c] = 0;
+   return;
+   }
dev->id[c][scmd_id(workreq)].curr_req = workreq;
dev->last_cmd[c] = scmd_id(workreq);
-   goto cmd_subp;
-   }   
-   dev->quhd[c] = j;
-   dev->working[c]--;
-   dev->in_snd[c] = 0;
-   return;
-cmd_subp:
-   if ((inb(dev->ioport[c] + 0x1f) & 0xb0) != 0) {
-   goto abortsnd;
-   }
-   if (inb(dev->ioport[c] + 0x1c) == 0) {
-   goto oktosend;
}
-abortsnd:
+   if ((inb(dev->ioport[c] + 0x1f) & 0xb0) != 0 || inb(dev->ioport[c] + 
0x1c) != 0) {
 #ifdef ED_DBGP
-   printk("Abort to Send\n");
+   printk("Abort to Send\n");
 #endif
-   dev->last_cmd[c] |= 0x40;
-   dev->in_snd[c] = 0;
-   return;
-oktosend:
+   dev->last_cmd[c] |= 0x40;
+   dev->in_snd[c] = 0;
+   return;
+   }
 #ifdef ED_DBGP
printk("OK to Send\n");
scmd_printk(KERN_DEBUG, workreq, "CDB");
-- 
Ondrej Zary

--
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 38/52] atp870u: Use n_io_port in request_region and release_region

2015-11-17 Thread Ondrej Zary
Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   20 +++-
 1 file changed, 3 insertions(+), 17 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 7f53a50..a06a0a4 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1610,16 +1610,8 @@ flash_ok_885:
shpnt->irq = pdev->irq; 
} 
spin_unlock_irqrestore(shpnt->host_lock, flags);
-   if(ent->device==ATP885_DEVID) {
-   if(!request_region(base_io, 0xff, "atp870u")) /* 
Register the IO ports that we use */
-   goto request_io_fail;
-   } else 
if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) {
-   if(!request_region(base_io, 0x60, "atp870u")) /* 
Register the IO ports that we use */
-   goto request_io_fail;
-   } else {
-   if(!request_region(base_io, 0x40, "atp870u")) /* 
Register the IO ports that we use */
-   goto request_io_fail;
-   }   
+   if (!request_region(base_io, shpnt->n_io_port, "atp870u"))
+   goto request_io_fail;
count++;
if (scsi_add_host(shpnt, &pdev->dev))
goto scsi_add_fail;
@@ -1631,13 +1623,7 @@ flash_ok_885:
 
 scsi_add_fail:
printk("atp870u_prob:scsi_add_fail\n");
-   if(ent->device==ATP885_DEVID) {
-   release_region(base_io, 0xff);
-   } else if((ent->device==ATP880_DEVID1)||(ent->device==ATP880_DEVID2)) {
-   release_region(base_io, 0x60);
-   } else {
-   release_region(base_io, 0x40);
-   }
+   release_region(base_io, shpnt->n_io_port);
 request_io_fail:
printk("atp870u_prob:request_io_fail\n");
free_irq(pdev->irq, shpnt);
-- 
Ondrej Zary

--
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 24/52] atp870u: Move chip-specific lines out of is880() and is885()

2015-11-17 Thread Ondrej Zary
Move few chip-specifis lines out of is880() and is885() so they become
almost identical.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   24 ++--
 1 file changed, 10 insertions(+), 14 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index ec61902..1c4b1f9 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -41,7 +41,7 @@
 
 static struct scsi_host_template atp870u_template;
 static void send_s870(struct atp_unit *dev,unsigned char c);
-static void is885(struct atp_unit *dev, unsigned char c);
+static void is885(struct atp_unit *dev, unsigned char c, unsigned char 
lvdmode);
 static void tscam_885(void);
 
 static inline void atp_writeb_base(struct atp_unit *atp, u8 reg, u8 val)
@@ -1596,9 +1596,9 @@ set_syn_ok:
atp_writeb_io(dev, c, 0x3a, atp_readb_io(dev, c, 0x3a) & 0xef);
 }
 
-static void is880(struct atp_unit *dev, unsigned char c)
+static void is880(struct atp_unit *dev, unsigned char c, unsigned char lvdmode)
 {
-   unsigned char i, j, k, rmb, n, lvdmode;
+   unsigned char i, j, k, rmb, n;
unsigned short int m;
static unsigned char mbuf[512];
static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 };
@@ -1610,8 +1610,6 @@ static void is880(struct atp_unit *dev, unsigned char c)
static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 
0x02 };
 
-   lvdmode = atp_readb_base(dev, 0x3f) & 0x40;
-
for (i = 0; i < 16; i++) {
m = 1;
m = m << i;
@@ -2379,7 +2377,7 @@ flash_ok_880:
outb(0x20, base_io + 0x51);
 
tscam(shpnt);
-   is880(p, 0);
+   is880(p, 0, atp_readb_base(p, 0x3f) & 0x40);
outb(0xb0, base_io + 0x38);
shpnt->max_id = 16;
shpnt->this_id = host_id;
@@ -2525,10 +2523,11 @@ flash_ok_885:
 
tscam_885();
printk(KERN_INFO "   Scanning Channel A SCSI Device ...\n");
-   is885(p, 0);
+   is885(p, 0, atp_readb_io(p, 0, 0x1b) >> 7);
+   atp_writeb_io(p, 0, 0x16, 0x80);
printk(KERN_INFO "   Scanning Channel B SCSI Device ...\n");
-   is885(p, 1);
-
+   is885(p, 1, atp_readb_io(p, 1, 0x1b) >> 7);
+   atp_writeb_io(p, 1, 0x16, 0x80);
k = inb(base_io + 0x28) & 0xcf;
k |= 0xc0;
outb(k, base_io + 0x28);
@@ -2829,9 +2828,9 @@ static void tscam_885(void)
 
 
 
-static void is885(struct atp_unit *dev, unsigned char c)
+static void is885(struct atp_unit *dev, unsigned char c, unsigned char lvdmode)
 {
-   unsigned char i, j, k, rmb, n, lvdmode;
+   unsigned char i, j, k, rmb, n;
unsigned short int m;
static unsigned char mbuf[512];
static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 };
@@ -2843,8 +2842,6 @@ static void is885(struct atp_unit *dev, unsigned char c)
static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 
0x02 };
 
-   lvdmode = atp_readb_io(dev, c, 0x1b) >> 7;
-
for (i = 0; i < 16; i++) {
m = 1;
m = m << i;
@@ -3408,7 +3405,6 @@ set_syn_ok:
printk("dev->id[%2d][%2d].devsp = 
%2x\n",c,i,dev->id[c][i].devsp);
 #endif
}
-   atp_writeb_io(dev, c, 0x16, 0x80);
 }
 
 module_init(atp870u_init);
-- 
Ondrej Zary

--
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 23/52] atp870u: Add channel parameter to is870() and is880()

2015-11-17 Thread Ondrej Zary
Add channel parameter to is870() and is880() functions to simplify comparing
them with is885().

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |  684 
 1 file changed, 342 insertions(+), 342 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 595c5c5..ec61902 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1162,7 +1162,7 @@ static void tscam(struct Scsi_Host *host)
}
 }
 
-static void is870(struct atp_unit *dev)
+static void is870(struct atp_unit *dev, unsigned char c)
 {
unsigned char i, j, k, rmb, n;
unsigned short int m;
@@ -1174,7 +1174,7 @@ static void is870(struct atp_unit *dev)
static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 };
static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
 
-   atp_writeb_io(dev, 0, 0x3a, atp_readb_io(dev, 0, 0x3a) | 0x10);
+   atp_writeb_io(dev, c, 0x3a, atp_readb_io(dev, c, 0x3a) | 0x10);
 
for (i = 0; i < 16; i++) {
if ((dev->chip_ver != 4) && (i > 7)) {
@@ -1182,120 +1182,120 @@ static void is870(struct atp_unit *dev)
}
m = 1;
m = m << i;
-   if ((m & dev->active_id[0]) != 0) {
+   if ((m & dev->active_id[c]) != 0) {
continue;
}
-   if (i == dev->host_id[0]) {
-   printk(KERN_INFO " ID: %2d  Host Adapter\n", 
dev->host_id[0]);
+   if (i == dev->host_id[c]) {
+   printk(KERN_INFO " ID: %2d  Host Adapter\n", 
dev->host_id[c]);
continue;
}
if (dev->chip_ver == 4) {
-   atp_writeb_io(dev, 0, 0x1b, 0x01);
+   atp_writeb_io(dev, c, 0x1b, 0x01);
} else {
-   atp_writeb_io(dev, 0, 0x1b, 0x00);
+   atp_writeb_io(dev, c, 0x1b, 0x00);
}
-   atp_writeb_io(dev, 0, 1, 0x08);
-   atp_writeb_io(dev, 0, 2, 0x7f);
-   atp_writeb_io(dev, 0, 3, satn[0]);
-   atp_writeb_io(dev, 0, 4, satn[1]);
-   atp_writeb_io(dev, 0, 5, satn[2]);
-   atp_writeb_io(dev, 0, 6, satn[3]);
-   atp_writeb_io(dev, 0, 7, satn[4]);
-   atp_writeb_io(dev, 0, 8, satn[5]);
-   atp_writeb_io(dev, 0, 0x0f, 0);
-   atp_writeb_io(dev, 0, 0x11, dev->id[0][i].devsp);
-   atp_writeb_io(dev, 0, 0x12, 0);
-   atp_writeb_io(dev, 0, 0x13, satn[6]);
-   atp_writeb_io(dev, 0, 0x14, satn[7]);
+   atp_writeb_io(dev, c, 1, 0x08);
+   atp_writeb_io(dev, c, 2, 0x7f);
+   atp_writeb_io(dev, c, 3, satn[0]);
+   atp_writeb_io(dev, c, 4, satn[1]);
+   atp_writeb_io(dev, c, 5, satn[2]);
+   atp_writeb_io(dev, c, 6, satn[3]);
+   atp_writeb_io(dev, c, 7, satn[4]);
+   atp_writeb_io(dev, c, 8, satn[5]);
+   atp_writeb_io(dev, c, 0x0f, 0);
+   atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
+   atp_writeb_io(dev, c, 0x12, 0);
+   atp_writeb_io(dev, c, 0x13, satn[6]);
+   atp_writeb_io(dev, c, 0x14, satn[7]);
j = i;
if ((j & 0x08) != 0) {
j = (j & 0x07) | 0x40;
}
-   atp_writeb_io(dev, 0, 0x15, j);
-   atp_writeb_io(dev, 0, 0x18, satn[8]);
+   atp_writeb_io(dev, c, 0x15, j);
+   atp_writeb_io(dev, c, 0x18, satn[8]);
 
-   while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0x00)
+   while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
cpu_relax();
 
-   if (atp_readb_io(dev, 0, 0x17) != 0x11 && atp_readb_io(dev, 0, 
0x17) != 0x8e)
+   if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 
0x17) != 0x8e)
continue;
 
-   while (atp_readb_io(dev, 0, 0x17) != 0x8e)
+   while (atp_readb_io(dev, c, 0x17) != 0x8e)
cpu_relax();
 
-   dev->active_id[0] |= m;
+   dev->active_id[c] |= m;
 
-   atp_writeb_io(dev, 0, 0x10, 0x30);
-   atp_writeb_io(dev, 0, 0x04, 0x00);
+   atp_writeb_io(dev, c, 0x10, 0x30);
+   atp_writeb_io(dev, c, 0x04, 0x00);
 
 phase_cmd:
-   atp_writeb_io(dev, 0, 0x18, 0x08);
+   atp_writeb_io(dev, c, 0x18, 0x08);
 
-   while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0x00)
+   while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
cpu_relax();
 
-   j = atp_readb_io(dev, 0, 0x17);
+   j = atp_readb_io(dev, c, 0x17);
if (j != 0x16) {
-   

[PATCH 45/52] atp870u: Introduce is880(), is885() and remove dev_id

2015-11-17 Thread Ondrej Zary
Introduce chip type inline functions to simplify code, allowing to delete
dev_id from struct atp_unit.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   70 ++--
 drivers/scsi/atp870u.h |1 -
 2 files changed, 38 insertions(+), 33 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 8af51a9..4bb0f4f 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -103,6 +103,17 @@ static inline u8 atp_readb_pci(struct atp_unit *atp, u8 
channel, u8 reg)
return inb(atp->pciport[channel] + reg);
 }
 
+static inline bool is880(struct atp_unit *atp)
+{
+   return atp->pdev->device == ATP880_DEVID1 ||
+  atp->pdev->device == ATP880_DEVID2;
+}
+
+static inline bool is885(struct atp_unit *atp)
+{
+   return atp->pdev->device == ATP885_DEVID;
+}
+
 static irqreturn_t atp870u_intr_handle(int irq, void *dev_id)
 {
unsigned long flags;
@@ -131,7 +142,7 @@ static irqreturn_t atp870u_intr_handle(int irq, void 
*dev_id)
dev->in_int[c] = 1;
cmdp = atp_readb_io(dev, c, 0x10);
if (dev->working[c] != 0) {
-   if (dev->dev_id == ATP885_DEVID) {
+   if (is885(dev)) {
if ((atp_readb_io(dev, c, 0x16) & 0x80) == 0)
atp_writeb_io(dev, c, 0x16, (atp_readb_io(dev, 
c, 0x16) | 0x80));
}   
@@ -148,7 +159,7 @@ static irqreturn_t atp870u_intr_handle(int irq, void 
*dev_id)

i = atp_readb_io(dev, c, 0x17);

-   if (dev->dev_id == ATP885_DEVID)
+   if (is885(dev))
atp_writeb_pci(dev, c, 2, 0x06);
 
target_id = atp_readb_io(dev, c, 0x15);
@@ -169,7 +180,7 @@ static irqreturn_t atp870u_intr_handle(int irq, void 
*dev_id)
 }
 dev->last_cmd[c] |= 0x40;
}
-   if (dev->dev_id == ATP885_DEVID) 
+   if (is885(dev))
dev->r1f[c][target_id] |= j;
 #ifdef ED_DBGP
printk("atp870u_intr_handle status = %x\n",i);
@@ -178,7 +189,7 @@ static irqreturn_t atp870u_intr_handle(int irq, void 
*dev_id)
if ((dev->last_cmd[c] & 0xf0) != 0x40) {
   dev->last_cmd[c] = 0xff;
}
-   if (dev->dev_id == ATP885_DEVID) {
+   if (is885(dev)) {
adrcnt = 0;
((unsigned char *) &adrcnt)[2] = 
atp_readb_io(dev, c, 0x12);
((unsigned char *) &adrcnt)[1] = 
atp_readb_io(dev, c, 0x13);
@@ -249,7 +260,7 @@ static irqreturn_t atp870u_intr_handle(int irq, void 
*dev_id)
return IRQ_HANDLED;
}
 
-   if (dev->dev_id == ATP885_DEVID) {
+   if (is885(dev)) {
if ((i == 0x4c) || (i == 0x4d) || (i == 0x8c) || (i == 
0x8d)) {
if ((i == 0x4c) || (i == 0x8c)) 
i=0x48;
@@ -301,7 +312,7 @@ static irqreturn_t atp870u_intr_handle(int irq, void 
*dev_id)
if (dev->last_cmd[c] != 0xff) {
   dev->last_cmd[c] |= 0x40;
}
-   if (dev->dev_id == ATP885_DEVID) {
+   if (is885(dev)) {
j = atp_readb_base(dev, 0x29) & 0xfe;
atp_writeb_base(dev, 0x29, j);
} else
@@ -316,7 +327,7 @@ static irqreturn_t atp870u_intr_handle(int irq, void 
*dev_id)
} else {
target_id &= 0x07;
}
-   if (dev->dev_id == ATP885_DEVID)
+   if (is885(dev))
atp_writeb_io(dev, c, 0x10, 0x45);
workreq = dev->id[c][target_id].curr_req;
 #ifdef ED_DBGP 
@@ -348,15 +359,14 @@ static irqreturn_t atp870u_intr_handle(int irq, void 
*dev_id)
atp_writeb_io(dev, c, 0x16, 0x80);

/* enable 32 bit fifo transfer */   
-   if (dev->dev_id == ATP885_DEVID) {
+   if (is885(dev)) {
i = atp_readb_pci(dev, c, 1) & 0xf3;
//j=workreq->cmnd[0];   
if ((workreq->cmnd[0] == 0x08) || 
(workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] 
== 0x2a)) {
   i |= 0x0c;
}
atp_writeb_pci(dev, c, 1, i);
-   } else if ((dev->dev_id == ATP880_DEVID1) ||
-

[PATCH 36/52] atp870u: Remove empty tscam_885()

2015-11-17 Thread Ondrej Zary
tscam_885() is empty (except a delay) so remove it.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   15 +--
 1 file changed, 1 insertion(+), 14 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index b662e39..2570919 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -42,7 +42,6 @@
 static struct scsi_host_template atp870u_template;
 static void send_s870(struct atp_unit *dev,unsigned char c);
 static void atp_is(struct atp_unit *dev, unsigned char c, bool wide_chip, 
unsigned char lvdmode);
-static void tscam_885(void);
 
 static inline void atp_writeb_base(struct atp_unit *atp, u8 reg, u8 val)
 {
@@ -1518,7 +1517,7 @@ flash_ok_885:
   k = (k & 0x07) | 0x40;
atp_set_host_id(p, 1, k);
 
-   tscam_885();
+   mdelay(600); /* this delay used to be called tscam_885() */
printk(KERN_INFO "   Scanning Channel A SCSI Device ...\n");
atp_is(p, 0, true, atp_readb_io(p, 0, 0x1b) >> 7);
atp_writeb_io(p, 0, 0x16, 0x80);
@@ -1802,18 +1801,6 @@ static void __exit atp870u_exit(void)
pci_unregister_driver(&atp870u_driver);
 }
 
-static void tscam_885(void)
-{
-   unsigned char i;
-
-   for (i = 0; i < 0x2; i++) {
-   mdelay(300);
-   }
-   return;
-}
-
-
-
 static void atp_is(struct atp_unit *dev, unsigned char c, bool wide_chip, 
unsigned char lvdmode)
 {
unsigned char i, j, k, rmb, n;
-- 
Ondrej Zary

--
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 30/52] atp870u: Rename is885() to atp_is()

2015-11-17 Thread Ondrej Zary
Now that all the is* functions except is885() are gone, rename is885() to
atp_is() to avoid confusion. Don't know what "is" means, though...

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 918875b..0b7d3bd 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -41,7 +41,7 @@
 
 static struct scsi_host_template atp870u_template;
 static void send_s870(struct atp_unit *dev,unsigned char c);
-static void is885(struct atp_unit *dev, unsigned char c, bool wide_chip, 
unsigned char lvdmode);
+static void atp_is(struct atp_unit *dev, unsigned char c, bool wide_chip, 
unsigned char lvdmode);
 static void tscam_885(void);
 
 static inline void atp_writeb_base(struct atp_unit *atp, u8 reg, u8 val)
@@ -1373,7 +1373,7 @@ flash_ok_880:
outb(0x20, base_io + 0x51);
 
tscam(shpnt);
-   is885(p, 0, true, atp_readb_base(p, 0x3f) & 0x40);
+   atp_is(p, 0, true, atp_readb_base(p, 0x3f) & 0x40);
outb(0xb0, base_io + 0x38);
shpnt->max_id = 16;
shpnt->this_id = host_id;
@@ -1519,10 +1519,10 @@ flash_ok_885:
 
tscam_885();
printk(KERN_INFO "   Scanning Channel A SCSI Device ...\n");
-   is885(p, 0, true, atp_readb_io(p, 0, 0x1b) >> 7);
+   atp_is(p, 0, true, atp_readb_io(p, 0, 0x1b) >> 7);
atp_writeb_io(p, 0, 0x16, 0x80);
printk(KERN_INFO "   Scanning Channel B SCSI Device ...\n");
-   is885(p, 1, true, atp_readb_io(p, 1, 0x1b) >> 7);
+   atp_is(p, 1, true, atp_readb_io(p, 1, 0x1b) >> 7);
atp_writeb_io(p, 1, 0x16, 0x80);
k = inb(base_io + 0x28) & 0xcf;
k |= 0xc0;
@@ -1605,7 +1605,7 @@ flash_ok_885:
 
tscam(shpnt);
atp_writeb_io(p, 0, 0x3a, atp_readb_io(p, 0, 0x3a) | 0x10);
-   is885(p, 0, p->chip_ver == 4, 0);
+   atp_is(p, 0, p->chip_ver == 4, 0);
atp_writeb_io(p, 0, 0x3a, atp_readb_io(p, 0, 0x3a) & 0xef);
outb((inb(base_io + 0x3a) & 0xef), base_io + 0x3a);
outb((inb(base_io + 0x3b) | 0x20), base_io + 0x3b);
@@ -1826,7 +1826,7 @@ static void tscam_885(void)
 
 
 
-static void is885(struct atp_unit *dev, unsigned char c, bool wide_chip, 
unsigned char lvdmode)
+static void atp_is(struct atp_unit *dev, unsigned char c, bool wide_chip, 
unsigned char lvdmode)
 {
unsigned char i, j, k, rmb, n;
unsigned short int m;
-- 
Ondrej Zary

--
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 18/52] atp870u: Introduce HW access wrappers

2015-11-17 Thread Ondrej Zary
Introduce *_read? and *_write? wrappers to improve code readability.
Also make sure that baseport is always initialized, not only for ATP880.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |  472 ++--
 1 file changed, 252 insertions(+), 220 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index fd2bb6f..07b50ac 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -44,6 +44,51 @@ static void send_s870(struct atp_unit *dev,unsigned char c);
 static void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c);
 static void tscam_885(void);
 
+static inline void atp_writeb_base(struct atp_unit *atp, u8 reg, u8 val)
+{
+   outb(val, atp->baseport + reg);
+}
+
+static inline void atp_writeb_io(struct atp_unit *atp, u8 channel, u8 reg, u8 
val)
+{
+   outb(val, atp->ioport[channel] + reg);
+}
+
+static inline void atp_writew_io(struct atp_unit *atp, u8 channel, u8 reg, u16 
val)
+{
+   outw(val, atp->ioport[channel] + reg);
+}
+
+static inline void atp_writeb_pci(struct atp_unit *atp, u8 channel, u8 reg, u8 
val)
+{
+   outb(val, atp->pciport[channel] + reg);
+}
+
+static inline void atp_writel_pci(struct atp_unit *atp, u8 channel, u8 reg, 
u32 val)
+{
+   outl(val, atp->pciport[channel] + reg);
+}
+
+static inline u8 atp_readb_base(struct atp_unit *atp, u8 reg)
+{
+   return inb(atp->baseport + reg);
+}
+
+static inline u8 atp_readb_io(struct atp_unit *atp, u8 channel, u8 reg)
+{
+   return inb(atp->ioport[channel] + reg);
+}
+
+static inline u16 atp_readw_io(struct atp_unit *atp, u8 channel, u8 reg)
+{
+   return inw(atp->ioport[channel] + reg);
+}
+
+static inline u8 atp_readb_pci(struct atp_unit *atp, u8 channel, u8 reg)
+{
+   return inb(atp->pciport[channel] + reg);
+}
+
 static irqreturn_t atp870u_intr_handle(int irq, void *dev_id)
 {
unsigned long flags;
@@ -59,7 +104,7 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id)
struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
 
for (c = 0; c < 2; c++) {
-   j = inb(dev->ioport[c] + 0x1f);
+   j = atp_readb_io(dev, c, 0x1f);
if ((j & 0x80) != 0)
break;
dev->in_int[c] = 0;
@@ -70,29 +115,29 @@ static irqreturn_t atp870u_intr_handle(int irq, void 
*dev_id)
printk("atp870u_intr_handle enter\n");
 #endif 
dev->in_int[c] = 1;
-   cmdp = inb(dev->ioport[c] + 0x10);
+   cmdp = atp_readb_io(dev, c, 0x10);
if (dev->working[c] != 0) {
if (dev->dev_id == ATP885_DEVID) {
-   if ((inb(dev->ioport[c] + 0x16) & 0x80) == 0)
-   outb((inb(dev->ioport[c] + 0x16) | 0x80), 
dev->ioport[c] + 0x16);
+   if ((atp_readb_io(dev, c, 0x16) & 0x80) == 0)
+   atp_writeb_io(dev, c, 0x16, (atp_readb_io(dev, 
c, 0x16) | 0x80));
}   
-   if ((inb(dev->pciport[c]) & 0x08) != 0)
+   if ((atp_readb_pci(dev, c, 0x00) & 0x08) != 0)
{
for (k=0; k < 1000; k++) {
-   if ((inb(dev->pciport[c] + 2) & 0x08) == 0)
+   if ((atp_readb_pci(dev, c, 2) & 0x08) == 0)
break;
-   if ((inb(dev->pciport[c] + 2) & 0x01) == 0)
+   if ((atp_readb_pci(dev, c, 2) & 0x01) == 0)
break;
}
}
-   outb(0x00, dev->pciport[c]);
+   atp_writeb_pci(dev, c, 0, 0x00);

-   i = inb(dev->ioport[c] + 0x17);
+   i = atp_readb_io(dev, c, 0x17);

if (dev->dev_id == ATP885_DEVID)
-   outb(0x06, dev->pciport[c] + 2);
+   atp_writeb_pci(dev, c, 2, 0x06);
 
-   target_id = inb(dev->ioport[c] + 0x15);
+   target_id = atp_readb_io(dev, c, 0x15);
 
/*
 *  Remap wide devices onto id numbers
@@ -121,9 +166,9 @@ static irqreturn_t atp870u_intr_handle(int irq, void 
*dev_id)
}
if (dev->dev_id == ATP885_DEVID) {
adrcnt = 0;
-   ((unsigned char *) &adrcnt)[2] = 
inb(dev->ioport[c] + 0x12);
-   ((unsigned char *) &adrcnt)[1] = 
inb(dev->ioport[c] + 0x13);
-   ((unsigned char *) &adrcnt)[0] = 
inb(dev->ioport[c] + 0x14);
+   ((unsigned char *) &adrcnt)[2] = 
atp_readb_io(dev, c, 0x12);
+   ((unsigned char *) &adrcnt)[1] = 
atp_readb_io(dev, c, 0x13);
+   ((unsigned char *) &adrcnt)[0] = 
atp_readb_

[PATCH 20/52] atp870u: Convert is880() to use wrappers

2015-11-17 Thread Ondrej Zary
Subtract 0x40 to use _io access wrappers.
Now it's obvious that is870() and is880() are very similar.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |  352 
 1 file changed, 176 insertions(+), 176 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 305eda8..1b9276f 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1594,7 +1594,7 @@ set_syn_ok:
atp_writeb_io(dev, 0, 0x3a, atp_readb_io(dev, 0, 0x3a) & 0xef);
 }
 
-static void is880(struct atp_unit *dev, unsigned int wkport)
+static void is880(struct atp_unit *dev)
 {
unsigned char i, j, k, rmb, n, lvdmode;
unsigned short int m;
@@ -1608,7 +1608,7 @@ static void is880(struct atp_unit *dev, unsigned int 
wkport)
static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 
0x02 };
 
-   lvdmode = inb(wkport + 0x3f) & 0x40;
+   lvdmode = atp_readb_base(dev, 0x3f) & 0x40;
 
for (i = 0; i < 16; i++) {
m = 1;
@@ -1620,100 +1620,100 @@ static void is880(struct atp_unit *dev, unsigned int 
wkport)
printk(KERN_INFO " ID: %2d  Host Adapter\n", 
dev->host_id[0]);
continue;
}
-   outb(0x01, wkport + 0x5b);
-   outb(0x08, wkport + 0x41);
-   outb(0x7f, wkport + 0x42);
-   outb(satn[0], wkport + 0x43);
-   outb(satn[1], wkport + 0x44);
-   outb(satn[2], wkport + 0x45);
-   outb(satn[3], wkport + 0x46);
-   outb(satn[4], wkport + 0x47);
-   outb(satn[5], wkport + 0x48);
-   outb(0, wkport + 0x4f);
-   outb(dev->id[0][i].devsp, wkport + 0x51);
-   outb(0, wkport + 0x52);
-   outb(satn[6], wkport + 0x53);
-   outb(satn[7], wkport + 0x54);
+   atp_writeb_io(dev, 0, 0x1b, 0x01);
+   atp_writeb_io(dev, 0, 1, 0x08);
+   atp_writeb_io(dev, 0, 2, 0x7f);
+   atp_writeb_io(dev, 0, 3, satn[0]);
+   atp_writeb_io(dev, 0, 4, satn[1]);
+   atp_writeb_io(dev, 0, 5, satn[2]);
+   atp_writeb_io(dev, 0, 6, satn[3]);
+   atp_writeb_io(dev, 0, 7, satn[4]);
+   atp_writeb_io(dev, 0, 8, satn[5]);
+   atp_writeb_io(dev, 0, 0x0f, 0);
+   atp_writeb_io(dev, 0, 0x11, dev->id[0][i].devsp);
+   atp_writeb_io(dev, 0, 0x12, 0);
+   atp_writeb_io(dev, 0, 0x13, satn[6]);
+   atp_writeb_io(dev, 0, 0x14, satn[7]);
j = i;
if ((j & 0x08) != 0) {
j = (j & 0x07) | 0x40;
}
-   outb(j, wkport + 0x55);
-   outb(satn[8], wkport + 0x58);
+   atp_writeb_io(dev, 0, 0x15, j);
+   atp_writeb_io(dev, 0, 0x18, satn[8]);
 
-   while ((inb(wkport + 0x5f) & 0x80) == 0x00)
+   while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0x00)
cpu_relax();
 
-   if (inb(wkport + 0x57) != 0x11 && inb(wkport + 0x57) != 0x8e)
+   if (atp_readb_io(dev, 0, 0x17) != 0x11 && atp_readb_io(dev, 0, 
0x17) != 0x8e)
continue;
 
-   while (inb(wkport + 0x57) != 0x8e)
+   while (atp_readb_io(dev, 0, 0x17) != 0x8e)
cpu_relax();

dev->active_id[0] |= m;
 
-   outb(0x30, wkport + 0x50);
-   outb(0x00, wkport + 0x54);
+   atp_writeb_io(dev, 0, 0x10, 0x30);
+   atp_writeb_io(dev, 0, 0x14, 0x00);
 
 phase_cmd:
-   outb(0x08, wkport + 0x58);
+   atp_writeb_io(dev, 0, 0x18, 0x08);

-   while ((inb(wkport + 0x5f) & 0x80) == 0x00)
+   while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0x00)
cpu_relax();
 
-   j = inb(wkport + 0x57);
+   j = atp_readb_io(dev, 0, 0x17);
if (j != 0x16) {
-   outb(0x41, wkport + 0x50);
+   atp_writeb_io(dev, 0, 0x10, 0x41);
goto phase_cmd;
}
 sel_ok:
-   outb(inqd[0], wkport + 0x43);
-   outb(inqd[1], wkport + 0x44);
-   outb(inqd[2], wkport + 0x45);
-   outb(inqd[3], wkport + 0x46);
-   outb(inqd[4], wkport + 0x47);
-   outb(inqd[5], wkport + 0x48);
-   outb(0, wkport + 0x4f);
-   outb(dev->id[0][i].devsp, wkport + 0x51);
-   outb(0, wkport + 0x52);
-   outb(inqd[6], wkport + 0x53);
-   outb(inqd[7], wkport + 0x54);
-   outb(inqd[8], wkport + 0x58);
+   atp_writeb_io(dev, 0, 3, inqd[0]);
+   

[PATCH 26/52] atp870u: Add wide_chip parameter to is870() and is885()

2015-11-17 Thread Ondrej Zary
Don't check chip_ver in is870() but add wide_chip parameter for that.
Then add the non-wide support to is885().

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   46 +-
 1 file changed, 25 insertions(+), 21 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index d10026a..0548d07 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -41,7 +41,7 @@
 
 static struct scsi_host_template atp870u_template;
 static void send_s870(struct atp_unit *dev,unsigned char c);
-static void is885(struct atp_unit *dev, unsigned char c, unsigned char 
lvdmode);
+static void is885(struct atp_unit *dev, unsigned char c, bool wide_chip, 
unsigned char lvdmode);
 static void tscam_885(void);
 
 static inline void atp_writeb_base(struct atp_unit *atp, u8 reg, u8 val)
@@ -1162,7 +1162,7 @@ static void tscam(struct Scsi_Host *host)
}
 }
 
-static void is870(struct atp_unit *dev, unsigned char c)
+static void is870(struct atp_unit *dev, unsigned char c, bool wide_chip)
 {
unsigned char i, j, k, rmb, n;
unsigned short int m;
@@ -1177,9 +1177,8 @@ static void is870(struct atp_unit *dev, unsigned char c)
atp_writeb_io(dev, c, 0x3a, atp_readb_io(dev, c, 0x3a) | 0x10);
 
for (i = 0; i < 16; i++) {
-   if ((dev->chip_ver != 4) && (i > 7)) {
+   if (!wide_chip && (i > 7))
break;
-   }
m = 1;
m = m << i;
if ((m & dev->active_id[c]) != 0) {
@@ -1189,11 +1188,7 @@ static void is870(struct atp_unit *dev, unsigned char c)
printk(KERN_INFO " ID: %2d  Host Adapter\n", 
dev->host_id[c]);
continue;
}
-   if (dev->chip_ver == 4) {
-   atp_writeb_io(dev, c, 0x1b, 0x01);
-   } else {
-   atp_writeb_io(dev, c, 0x1b, 0x00);
-   }
+   atp_writeb_io(dev, c, 0x1b, wide_chip ? 0x01 : 0x00);
atp_writeb_io(dev, c, 1, 0x08);
atp_writeb_io(dev, c, 2, 0x7f);
atp_writeb_io(dev, c, 3, satn[0]);
@@ -1262,7 +1257,7 @@ sel_ok:
while (atp_readb_io(dev, c, 0x17) != 0x8e)
cpu_relax();
 
-   if (dev->chip_ver == 4)
+   if (wide_chip)
atp_writeb_io(dev, c, 0x1b, 0x00);
 
atp_writeb_io(dev, c, 0x18, 0x08);
@@ -1298,9 +1293,8 @@ inq_ok:
dev->id[c][i].devtype = mbuf[0];
rmb = mbuf[1];
n = mbuf[7];
-   if (dev->chip_ver != 4) {
+   if (!wide_chip)
goto not_wide;
-   }
if ((mbuf[7] & 0x60) == 0) {
goto not_wide;
}
@@ -1807,7 +1801,7 @@ flash_ok_880:
outb(0x20, base_io + 0x51);
 
tscam(shpnt);
-   is885(p, 0, atp_readb_base(p, 0x3f) & 0x40);
+   is885(p, 0, true, atp_readb_base(p, 0x3f) & 0x40);
outb(0xb0, base_io + 0x38);
shpnt->max_id = 16;
shpnt->this_id = host_id;
@@ -1953,10 +1947,10 @@ flash_ok_885:
 
tscam_885();
printk(KERN_INFO "   Scanning Channel A SCSI Device ...\n");
-   is885(p, 0, atp_readb_io(p, 0, 0x1b) >> 7);
+   is885(p, 0, true, atp_readb_io(p, 0, 0x1b) >> 7);
atp_writeb_io(p, 0, 0x16, 0x80);
printk(KERN_INFO "   Scanning Channel B SCSI Device ...\n");
-   is885(p, 1, atp_readb_io(p, 1, 0x1b) >> 7);
+   is885(p, 1, true, atp_readb_io(p, 1, 0x1b) >> 7);
atp_writeb_io(p, 1, 0x16, 0x80);
k = inb(base_io + 0x28) & 0xcf;
k |= 0xc0;
@@ -2038,7 +2032,7 @@ flash_ok_885:
outb(0x20, base_io + 0x11);
 
tscam(shpnt);
-   is870(p, 0);
+   is870(p, 0, p->chip_ver == 4);
outb((inb(base_io + 0x3a) & 0xef), base_io + 0x3a);
outb((inb(base_io + 0x3b) | 0x20), base_io + 0x3b);
if (atpdev->chip_ver == 4)
@@ -2258,7 +2252,7 @@ static void tscam_885(void)
 
 
 
-static void is885(struct atp_unit *dev, unsigned char c, unsigned char lvdmode)
+static void is885(struct atp_unit *dev, unsigned char c, bool wide_chip, 
unsigned char lvdmode)
 {
unsigned char i, j, k, rmb, n;
unsigned short int m;
@@ -2273,6 +2267,8 @@ static void is885(struct atp_unit *dev, unsigned char c, 
unsigned char lvdmode)
static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 
0x02 };
 
for (i = 0; i < 16; i++) {
+   if (!wide_chip && (i > 7))
+   break;
m = 1;
m = m << i;
if ((m & dev->active_id[c]) != 0) {
@@ -2282,7 +227

[PATCH 19/52] atp870u: Convert is870() to use wrappers

2015-11-17 Thread Ondrej Zary
Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |  276 
 1 file changed, 138 insertions(+), 138 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 07b50ac..305eda8 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1162,7 +1162,7 @@ static void tscam(struct Scsi_Host *host)
}
 }
 
-static void is870(struct atp_unit *dev, unsigned int wkport)
+static void is870(struct atp_unit *dev)
 {
unsigned char i, j, k, rmb, n;
unsigned short int m;
@@ -1174,7 +1174,7 @@ static void is870(struct atp_unit *dev, unsigned int 
wkport)
static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 };
static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };

-   outb((unsigned char) (inb(wkport + 0x3a) | 0x10), wkport + 0x3a);
+   atp_writeb_io(dev, 0, 0x3a, atp_readb_io(dev, 0, 0x3a) | 0x10);
 
for (i = 0; i < 16; i++) {
if ((dev->chip_ver != 4) && (i > 7)) {
@@ -1190,104 +1190,104 @@ static void is870(struct atp_unit *dev, unsigned int 
wkport)
continue;
}
if (dev->chip_ver == 4) {
-   outb(0x01, wkport + 0x1b);
+   atp_writeb_io(dev, 0, 0x1b, 0x01);
} else {
-   outb(0x00, wkport + 0x1b);
-   }
-   outb(0x08, wkport + 1);
-   outb(0x7f, wkport + 2);
-   outb(satn[0], wkport + 3);
-   outb(satn[1], wkport + 4);
-   outb(satn[2], wkport + 5);
-   outb(satn[3], wkport + 6);
-   outb(satn[4], wkport + 7);
-   outb(satn[5], wkport + 8);
-   outb(0, wkport + 0x0f);
-   outb(dev->id[0][i].devsp, wkport + 0x11);
-   outb(0, wkport + 0x12);
-   outb(satn[6], wkport + 0x13);
-   outb(satn[7], wkport + 0x14);
+   atp_writeb_io(dev, 0, 0x1b, 0x00);
+   }
+   atp_writeb_io(dev, 0, 1, 0x08);
+   atp_writeb_io(dev, 0, 2, 0x7f);
+   atp_writeb_io(dev, 0, 3, satn[0]);
+   atp_writeb_io(dev, 0, 4, satn[1]);
+   atp_writeb_io(dev, 0, 5, satn[2]);
+   atp_writeb_io(dev, 0, 6, satn[3]);
+   atp_writeb_io(dev, 0, 7, satn[4]);
+   atp_writeb_io(dev, 0, 8, satn[5]);
+   atp_writeb_io(dev, 0, 0x0f, 0);
+   atp_writeb_io(dev, 0, 0x11, dev->id[0][i].devsp);
+   atp_writeb_io(dev, 0, 0x12, 0);
+   atp_writeb_io(dev, 0, 0x13, satn[6]);
+   atp_writeb_io(dev, 0, 0x14, satn[7]);
j = i;
if ((j & 0x08) != 0) {
j = (j & 0x07) | 0x40;
}
-   outb(j, wkport + 0x15);
-   outb(satn[8], wkport + 0x18);
+   atp_writeb_io(dev, 0, 0x15, j);
+   atp_writeb_io(dev, 0, 0x18, satn[8]);
 
-   while ((inb(wkport + 0x1f) & 0x80) == 0x00)
+   while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0x00)
cpu_relax();
 
-   if (inb(wkport + 0x17) != 0x11 && inb(wkport + 0x17) != 0x8e)
+   if (atp_readb_io(dev, 0, 0x17) != 0x11 && atp_readb_io(dev, 0, 
0x17) != 0x8e)
continue;
 
-   while (inb(wkport + 0x17) != 0x8e)
+   while (atp_readb_io(dev, 0, 0x17) != 0x8e)
cpu_relax();
 
dev->active_id[0] |= m;
 
-   outb(0x30, wkport + 0x10);
-   outb(0x00, wkport + 0x04);
+   atp_writeb_io(dev, 0, 0x10, 0x30);
+   atp_writeb_io(dev, 0, 0x04, 0x00);
 
 phase_cmd:
-   outb(0x08, wkport + 0x18);
-   while ((inb(wkport + 0x1f) & 0x80) == 0x00)
+   atp_writeb_io(dev, 0, 0x18, 0x08);
+   while ((atp_readb_io(dev, 0, 0x1f) & 0x80) == 0x00)
cpu_relax();
-   j = inb(wkport + 0x17);
+   j = atp_readb_io(dev, 0, 0x17);
if (j != 0x16) {
-   outb(0x41, wkport + 0x10);
+   atp_writeb_io(dev, 0, 0x10, 0x41);
goto phase_cmd;
}
 sel_ok:
-   outb(inqd[0], wkport + 3);
-   outb(inqd[1], wkport + 4);
-   outb(inqd[2], wkport + 5);
-   outb(inqd[3], wkport + 6);
-   outb(inqd[4], wkport + 7);
-   outb(inqd[5], wkport + 8);
-   outb(0, wkport + 0x0f);
-   outb(dev->id[0][i].devsp, wkport + 0x11);
-   outb(0, wkport + 0x12);
-   outb(inqd[6], wkport + 0x13);
-   outb(inqd[7], wkport + 0x14);
-   outb(inqd[8], wkport + 0x18);
+   atp_writeb_io(dev, 0, 3, inqd[0]);
+   atp_writeb_io(dev,

[PATCH 51/52] atp870u: Introduce atp885_init()

2015-11-17 Thread Ondrej Zary
Move 885-specific init code to a separate function atp885_init()

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |  231 +++-
 1 file changed, 113 insertions(+), 118 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index c1fd9fb..584b90f 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1334,15 +1334,122 @@ static void atp880_init(struct Scsi_Host *shpnt)
shpnt->this_id = host_id;
 }
 
+static void atp885_init(struct Scsi_Host *shpnt)
+{
+   struct atp_unit *atpdev = shost_priv(shpnt);
+   struct pci_dev *pdev = atpdev->pdev;
+   unsigned char k, m, c;
+   unsigned int n;
+   unsigned char setupdata[2][16];
+
+   dev_info(&pdev->dev, "ACARD AEC-67162 PCI Ultra3 LVD Host Adapter: 
IO:%lx, IRQ:%d.\n",
+shpnt->io_port, shpnt->irq);
+
+   atpdev->ioport[0] = shpnt->io_port + 0x80;
+   atpdev->ioport[1] = shpnt->io_port + 0xc0;
+   atpdev->pciport[0] = shpnt->io_port + 0x40;
+   atpdev->pciport[1] = shpnt->io_port + 0x50;
+
+   c = atp_readb_base(atpdev, 0x29);
+   atp_writeb_base(atpdev, 0x29, c | 0x04);
+
+   n = 0x1f80;
+   while (n < 0x2000) {
+   atp_writew_base(atpdev, 0x3c, n);
+   if (atp_readl_base(atpdev, 0x38) == 0x)
+   break;
+   for (m = 0; m < 2; m++) {
+   atpdev->global_map[m] = 0;
+   for (k = 0; k < 4; k++) {
+   atp_writew_base(atpdev, 0x3c, n++);
+   ((unsigned long *)&setupdata[m][0])[k] = 
atp_readl_base(atpdev, 0x38);
+   }
+   for (k = 0; k < 4; k++) {
+   atp_writew_base(atpdev, 0x3c, n++);
+   ((unsigned long *)&atpdev->sp[m][0])[k] = 
atp_readl_base(atpdev, 0x38);
+   }
+   n += 8;
+   }
+   }
+   c = atp_readb_base(atpdev, 0x29);
+   atp_writeb_base(atpdev, 0x29, c & 0xfb);
+   for (c = 0; c < 2; c++) {
+   atpdev->ultra_map[c] = 0;
+   atpdev->async[c] = 0;
+   for (k = 0; k < 16; k++) {
+   n = 1 << k;
+   if (atpdev->sp[c][k] > 1)
+   atpdev->ultra_map[c] |= n;
+   else
+   if (atpdev->sp[c][k] == 0)
+   atpdev->async[c] |= n;
+   }
+   atpdev->async[c] = ~(atpdev->async[c]);
+
+   if (atpdev->global_map[c] == 0) {
+   k = setupdata[c][1];
+   if ((k & 0x40) != 0)
+   atpdev->global_map[c] |= 0x20;
+   k &= 0x07;
+   atpdev->global_map[c] |= k;
+   if ((setupdata[c][2] & 0x04) != 0)
+   atpdev->global_map[c] |= 0x08;
+   atpdev->host_id[c] = setupdata[c][0] & 0x07;
+   }
+   }
+
+   k = atp_readb_base(atpdev, 0x28) & 0x8f;
+   k |= 0x10;
+   atp_writeb_base(atpdev, 0x28, k);
+   atp_writeb_pci(atpdev, 0, 1, 0x80);
+   atp_writeb_pci(atpdev, 1, 1, 0x80);
+   mdelay(100);
+   atp_writeb_pci(atpdev, 0, 1, 0);
+   atp_writeb_pci(atpdev, 1, 1, 0);
+   mdelay(1000);
+   atp_readb_io(atpdev, 0, 0x1b);
+   atp_readb_io(atpdev, 0, 0x17);
+   atp_readb_io(atpdev, 1, 0x1b);
+   atp_readb_io(atpdev, 1, 0x17);
+
+   k = atpdev->host_id[0];
+   if (k > 7)
+   k = (k & 0x07) | 0x40;
+   atp_set_host_id(atpdev, 0, k);
+
+   k = atpdev->host_id[1];
+   if (k > 7)
+   k = (k & 0x07) | 0x40;
+   atp_set_host_id(atpdev, 1, k);
+
+   mdelay(600); /* this delay used to be called tscam_885() */
+   dev_info(&pdev->dev, "Scanning Channel A SCSI Device ...\n");
+   atp_is(atpdev, 0, true, atp_readb_io(atpdev, 0, 0x1b) >> 7);
+   atp_writeb_io(atpdev, 0, 0x16, 0x80);
+   dev_info(&pdev->dev, "Scanning Channel B SCSI Device ...\n");
+   atp_is(atpdev, 1, true, atp_readb_io(atpdev, 1, 0x1b) >> 7);
+   atp_writeb_io(atpdev, 1, 0x16, 0x80);
+   k = atp_readb_base(atpdev, 0x28) & 0xcf;
+   k |= 0xc0;
+   atp_writeb_base(atpdev, 0x28, k);
+   k = atp_readb_base(atpdev, 0x1f) | 0x80;
+   atp_writeb_base(atpdev, 0x1f, k);
+   k = atp_readb_base(atpdev, 0x29) | 0x01;
+   atp_writeb_base(atpdev, 0x29, k);
+   shpnt->max_id = 16;
+   shpnt->max_lun = (atpdev->global_map[0] & 0x07) + 1;
+   shpnt->max_channel = 1;
+   shpnt->this_id = atpdev->host_id[0];
+}
+
 /* return non-zero on detection */
 static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-   unsigned char k, m, c;
-   unsigned int error,n;
+   unsi

[PATCH 33/52] atp870u: Fix incorrect writeb_io access to register 0x3a

2015-11-17 Thread Ondrej Zary
The ioport region is 0x20 bytes long so accessing 0x3a register using
writeb_io is incorrect. Use writeb_base instead.
There's no change in behavior as 870 chips have ioport = baseport.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index c4a59cc..04b29d3 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -364,9 +364,9 @@ static irqreturn_t atp870u_intr_handle(int irq, void 
*dev_id)
atp_writeb_base(dev, 0x3b, 
atp_readb_base(dev, 0x3b) & 0x3f);
} else {
if ((workreq->cmnd[0] == 0x08) || 
(workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] 
== 0x2a))
-   atp_writeb_io(dev, c, 0x3a, 
(atp_readb_io(dev, c, 0x3a) & 0xf3) | 0x08);
+   atp_writeb_base(dev, 0x3a, 
(atp_readb_base(dev, 0x3a) & 0xf3) | 0x08);
else
-   atp_writeb_io(dev, c, 0x3a, 
atp_readb_io(dev, c, 0x3a) & 0xf3);
+   atp_writeb_base(dev, 0x3a, 
atp_readb_base(dev, 0x3a) & 0xf3);
}   
j = 0;
id = 1;
@@ -889,9 +889,9 @@ static void send_s870(struct atp_unit *dev,unsigned char c)
atp_writeb_base(dev, 0x3b, atp_readb_base(dev, 0x3b) & 
0x3f);
} else {
if ((workreq->cmnd[0] == 0x08) || (workreq->cmnd[0] == 0x28) || 
(workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] == 0x2a))
-   atp_writeb_io(dev, c, 0x3a, (atp_readb_io(dev, c, 0x3a) 
& 0xf3) | 0x08);
+   atp_writeb_base(dev, 0x3a, (atp_readb_base(dev, 0x3a) & 
0xf3) | 0x08);
else
-   atp_writeb_io(dev, c, 0x3a, atp_readb_io(dev, c, 0x3a) 
& 0xf3);
+   atp_writeb_base(dev, 0x3a, atp_readb_base(dev, 0x3a) & 
0xf3);
}   
 
if(workreq->sc_data_direction == DMA_TO_DEVICE) {
-- 
Ondrej Zary

--
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 49/52] atp870u: Initialize tables earlier

2015-11-17 Thread Ondrej Zary
Call _init_tables before chip-specific initialization. This avoids code
duplication and fixes a bug(?) in 880 init where the values read from flash
into atpdev->sp are then overwritten by calling init_tables.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   22 ++
 1 file changed, 6 insertions(+), 16 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index dd0b520..3c66539 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1298,6 +1298,12 @@ static int atp870u_probe(struct pci_dev *pdev, const 
struct pci_device_id *ent)
shpnt->unique_id = shpnt->io_port;
shpnt->irq = pdev->irq;
 
+   err = atp870u_init_tables(shpnt);
+   if (err) {
+   dev_err(&pdev->dev, "Unable to allocate tables for Acard 
controller\n");
+   goto unregister;
+   }
+
if (is880(atpdev)) {
pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803
 
@@ -1366,11 +1372,6 @@ flash_ok_880:
atpdev->async[0] = ~(atpdev->async[0]);
atp_writeb_base(atpdev, 0x35, atpdev->global_map[0]);
  
-   if (atp870u_init_tables(shpnt) < 0) {
-   printk(KERN_ERR "Unable to allocate tables for Acard 
controller\n");
-   err = -ENOMEM;
-   goto unregister;
-   }
 
k = atp_readb_base(atpdev, 0x38) & 0x80;
atp_writeb_base(atpdev, 0x38, k);
@@ -1398,11 +1399,6 @@ flash_ok_880:
atpdev->pciport[0] = shpnt->io_port + 0x40;
atpdev->pciport[1] = shpnt->io_port + 0x50;

-   if (atp870u_init_tables(shpnt) < 0) {
-   err = -ENOMEM;
-   goto unregister;
-   }
-   
c = atp_readb_base(atpdev, 0x29);
atp_writeb_base(atpdev, 0x29, c | 0x04);

@@ -1533,12 +1529,6 @@ flash_ok_885:
atpdev->ultra_map[0] = 0x;
}
 
-
-   if (atp870u_init_tables(shpnt) < 0) {
-   err = -ENOMEM;
-   goto unregister;
-   }
-
if (pdev->revision > 0x07)  /* check if atp876 chip then 
enable terminator */
atp_writeb_base(atpdev, 0x3e, 0x00);
  
-- 
Ondrej Zary

--
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 31/52] atp870u: Convert remaining in[bwl] and out[bwl] to wrappers

2015-11-17 Thread Ondrej Zary
Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |  222 +---
 1 file changed, 118 insertions(+), 104 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 0b7d3bd..bccf872 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -49,6 +49,11 @@ static inline void atp_writeb_base(struct atp_unit *atp, u8 
reg, u8 val)
outb(val, atp->baseport + reg);
 }
 
+static inline void atp_writew_base(struct atp_unit *atp, u8 reg, u16 val)
+{
+   outw(val, atp->baseport + reg);
+}
+
 static inline void atp_writeb_io(struct atp_unit *atp, u8 channel, u8 reg, u8 
val)
 {
outb(val, atp->ioport[channel] + reg);
@@ -74,6 +79,16 @@ static inline u8 atp_readb_base(struct atp_unit *atp, u8 reg)
return inb(atp->baseport + reg);
 }
 
+static inline u16 atp_readw_base(struct atp_unit *atp, u8 reg)
+{
+   return inw(atp->baseport + reg);
+}
+
+static inline u32 atp_readl_base(struct atp_unit *atp, u8 reg)
+{
+   return inl(atp->baseport + reg);
+}
+
 static inline u8 atp_readb_io(struct atp_unit *atp, u8 channel, u8 reg)
 {
return inb(atp->ioport[channel] + reg);
@@ -1268,19 +1283,20 @@ static int atp870u_probe(struct pci_dev *pdev, const 
struct pci_device_id *ent)
atpdev->chip_ver = pdev->revision;
pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803
 
-   host_id = inb(base_io + 0x39);
+   atpdev->ioport[0] = base_io + 0x40;
+   atpdev->pciport[0] = base_io + 0x28;
+
+   host_id = atp_readb_base(atpdev, 0x39);
host_id >>= 0x04;
 
printk(KERN_INFO "   ACARD AEC-67160 PCI Ultra3 LVD Host 
Adapter: %d"
"IO:%x, IRQ:%d.\n", count, base_io, pdev->irq);
-   atpdev->ioport[0] = base_io + 0x40;
-   atpdev->pciport[0] = base_io + 0x28;
atpdev->dev_id = ent->device;
atpdev->host_id[0] = host_id;
 
-   atpdev->scam_on = inb(base_io + 0x22);
-   atpdev->global_map[0] = inb(base_io + 0x35);
-   atpdev->ultra_map[0] = inw(base_io + 0x3c);
+   atpdev->scam_on = atp_readb_base(atpdev, 0x22);
+   atpdev->global_map[0] = atp_readb_base(atpdev, 0x35);
+   atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x3c);
 
n = 0x3f09;
 next_fblk_880:
@@ -1288,37 +1304,37 @@ next_fblk_880:
goto flash_ok_880;
 
m = 0;
-   outw(n, base_io + 0x34);
+   atp_writew_base(atpdev, 0x34, n);
n += 0x0002;
-   if (inb(base_io + 0x30) == 0xff)
+   if (atp_readb_base(atpdev, 0x30) == 0xff)
goto flash_ok_880;
 
-   atpdev->sp[0][m++] = inb(base_io + 0x30);
-   atpdev->sp[0][m++] = inb(base_io + 0x31);
-   atpdev->sp[0][m++] = inb(base_io + 0x32);
-   atpdev->sp[0][m++] = inb(base_io + 0x33);
-   outw(n, base_io + 0x34);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
+   atp_writew_base(atpdev, 0x34, n);
n += 0x0002;
-   atpdev->sp[0][m++] = inb(base_io + 0x30);
-   atpdev->sp[0][m++] = inb(base_io + 0x31);
-   atpdev->sp[0][m++] = inb(base_io + 0x32);
-   atpdev->sp[0][m++] = inb(base_io + 0x33);
-   outw(n, base_io + 0x34);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
+   atp_writew_base(atpdev, 0x34, n);
n += 0x0002;
-   atpdev->sp[0][m++] = inb(base_io + 0x30);
-   atpdev->sp[0][m++] = inb(base_io + 0x31);
-   atpdev->sp[0][m++] = inb(base_io + 0x32);
-   atpdev->sp[0][m++] = inb(base_io + 0x33);
-   outw(n, base_io + 0x34);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
+   atp_writew_base(atpdev, 0x34, n);
n += 0x0002;
-   atpdev->sp[0][m++] = inb(base_io + 0x30);
-   atpdev->sp[0][m++] = inb(base_io + 0x31);
-   atpdev->sp[0][m++] = inb(base_io + 0x32);
-   atpdev->sp[0][m++] = inb(base_io + 0x33);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
+

[PATCH 15/52] atp870u: Remove ugly gotos #3

2015-11-17 Thread Ondrej Zary
Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   18 ++
 1 file changed, 6 insertions(+), 12 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 999bf74..b3d4e9d 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -880,34 +880,28 @@ static unsigned char fun_scam(struct atp_unit *dev, 
unsigned short int *val)
unsigned char j;
 
outw(*val, dev->ioport[0] + 0x1c);
-FUN_D7:
for (i = 0; i < 10; i++) {  /* stable >= bus settle delay(400 ns)  
*/
k = inw(dev->ioport[0] + 0x1c);
j = (unsigned char) (k >> 8);
-   if ((k & 0x8000) != 0) {/* DB7 all release?*/
-   goto FUN_D7;
-   }
+   if ((k & 0x8000) != 0)  /* DB7 all release?*/
+   i = 0;
}
*val |= 0x4000; /* assert DB6   */
outw(*val, dev->ioport[0] + 0x1c);
*val &= 0xdfff; /* assert DB5   */
outw(*val, dev->ioport[0] + 0x1c);
-FUN_D5:
for (i = 0; i < 10; i++) {  /* stable >= bus settle delay(400 ns) */
-   if ((inw(dev->ioport[0] + 0x1c) & 0x2000) != 0) {   /* DB5 
all release?   */
-   goto FUN_D5;
-   }
+   if ((inw(dev->ioport[0] + 0x1c) & 0x2000) != 0) /* DB5 all 
release?   */
+   i = 0;
}
*val |= 0x8000; /* no DB4-0, assert DB7*/
*val &= 0xe0ff;
outw(*val, dev->ioport[0] + 0x1c);
*val &= 0xbfff; /* release DB6 */
outw(*val, dev->ioport[0] + 0x1c);
-FUN_D6:
for (i = 0; i < 10; i++) {  /* stable >= bus settle delay(400 ns)  
*/
-   if ((inw(dev->ioport[0] + 0x1c) & 0x4000) != 0) {   /* DB6 
all release?  */
-   goto FUN_D6;
-   }
+   if ((inw(dev->ioport[0] + 0x1c) & 0x4000) != 0) /* DB6 all 
release?  */
+   i = 0;
}
 
return j;
-- 
Ondrej Zary

--
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 50/52] atp870u: Introduce atp880_init()

2015-11-17 Thread Ondrej Zary
Move 880-specific init code to a separate function atp880_init()

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |  174 
 1 file changed, 88 insertions(+), 86 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 3c66539..c1fd9fb 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1249,6 +1249,91 @@ static void atp_set_host_id(struct atp_unit *atp, u8 c, 
u8 host_id)
atp_writeb_io(atp, c, 0x11, 0x20);
 }
 
+static void atp880_init(struct Scsi_Host *shpnt)
+{
+   struct atp_unit *atpdev = shost_priv(shpnt);
+   struct pci_dev *pdev = atpdev->pdev;
+   unsigned char k, m, host_id;
+   unsigned int n;
+
+   pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);
+
+   atpdev->ioport[0] = shpnt->io_port + 0x40;
+   atpdev->pciport[0] = shpnt->io_port + 0x28;
+
+   host_id = atp_readb_base(atpdev, 0x39) >> 4;
+
+   dev_info(&pdev->dev, "ACARD AEC-67160 PCI Ultra3 LVD Host Adapter: 
IO:%lx, IRQ:%d.\n",
+shpnt->io_port, shpnt->irq);
+   atpdev->host_id[0] = host_id;
+
+   atpdev->global_map[0] = atp_readb_base(atpdev, 0x35);
+   atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x3c);
+
+   n = 0x3f09;
+   while (n < 0x4000) {
+   m = 0;
+   atp_writew_base(atpdev, 0x34, n);
+   n += 0x0002;
+   if (atp_readb_base(atpdev, 0x30) == 0xff)
+   break;
+
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
+   atp_writew_base(atpdev, 0x34, n);
+   n += 0x0002;
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
+   atp_writew_base(atpdev, 0x34, n);
+   n += 0x0002;
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
+   atp_writew_base(atpdev, 0x34, n);
+   n += 0x0002;
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x30);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x31);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x32);
+   atpdev->sp[0][m++] = atp_readb_base(atpdev, 0x33);
+   n += 0x0018;
+   }
+   atp_writew_base(atpdev, 0x34, 0);
+   atpdev->ultra_map[0] = 0;
+   atpdev->async[0] = 0;
+   for (k = 0; k < 16; k++) {
+   n = 1 << k;
+   if (atpdev->sp[0][k] > 1)
+   atpdev->ultra_map[0] |= n;
+   else
+   if (atpdev->sp[0][k] == 0)
+   atpdev->async[0] |= n;
+   }
+   atpdev->async[0] = ~(atpdev->async[0]);
+   atp_writeb_base(atpdev, 0x35, atpdev->global_map[0]);
+
+   k = atp_readb_base(atpdev, 0x38) & 0x80;
+   atp_writeb_base(atpdev, 0x38, k);
+   atp_writeb_base(atpdev, 0x3b, 0x20);
+   mdelay(32);
+   atp_writeb_base(atpdev, 0x3b, 0);
+   mdelay(32);
+   atp_readb_io(atpdev, 0, 0x1b);
+   atp_readb_io(atpdev, 0, 0x17);
+
+   atp_set_host_id(atpdev, 0, host_id);
+
+   tscam(shpnt, true, atp_readb_base(atpdev, 0x22));
+   atp_is(atpdev, 0, true, atp_readb_base(atpdev, 0x3f) & 0x40);
+   atp_writeb_base(atpdev, 0x38, 0xb0);
+   shpnt->max_id = 16;
+   shpnt->this_id = host_id;
+}
+
 /* return non-zero on detection */
 static int atp870u_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
@@ -1304,92 +1389,9 @@ static int atp870u_probe(struct pci_dev *pdev, const 
struct pci_device_id *ent)
goto unregister;
}
 
-   if (is880(atpdev)) {
-   pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x80);//JCC082803
-
-   atpdev->ioport[0] = shpnt->io_port + 0x40;
-   atpdev->pciport[0] = shpnt->io_port + 0x28;
-
-   host_id = atp_readb_base(atpdev, 0x39);
-   host_id >>= 0x04;
-
-   printk(KERN_INFO "   ACARD AEC-67160 PCI Ultra3 LVD Host 
Adapter:"
-   "IO:%lx, IRQ:%d.\n", shpnt->io_port, shpnt->irq);
-   atpdev->host_id[0] = host_id;
-
-   atpdev->global_map[0] = atp_readb_base(atpdev, 0x35);
-   atpdev->ultra_map[0] = atp_readw_base(atpdev, 0x3c);
-
-   n = 0x3f09;
-next_fblk_880:
-   if (n >= 0x4000)
-   got

[PATCH 11/52] atp870u: Untangle tmpcip

2015-11-17 Thread Ondrej Zary
Untangle the tmpcip crap so it becomes obvious what ports are accessed.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   64 +---
 1 file changed, 23 insertions(+), 41 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 993442d..32544bb 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -47,7 +47,7 @@ static void tscam_885(void);
 static irqreturn_t atp870u_intr_handle(int irq, void *dev_id)
 {
unsigned long flags;
-   unsigned short int tmpcip, id;
+   unsigned short int id;
unsigned char i, j, c, target_id, lun,cmdp;
unsigned char *prd;
struct scsi_cmnd *workreq;
@@ -79,30 +79,24 @@ ch_sel:
if ((inb(dev->ioport[c] + 0x16) & 0x80) == 0)
outb((inb(dev->ioport[c] + 0x16) | 0x80), 
dev->ioport[c] + 0x16);
}   
-   tmpcip = dev->pciport[c];
-   if ((inb(tmpcip) & 0x08) != 0)
+   if ((inb(dev->pciport[c]) & 0x08) != 0)
{
-   tmpcip += 0x2;
for (k=0; k < 1000; k++) {
-   if ((inb(tmpcip) & 0x08) == 0) {
+   if ((inb(dev->pciport[c] + 2) & 0x08) == 0) {
goto stop_dma;
}
-   if ((inb(tmpcip) & 0x01) == 0) {
+   if ((inb(dev->pciport[c] + 2) & 0x01) == 0) {
goto stop_dma;
}
}
}
 stop_dma:
-   tmpcip = dev->pciport[c];
-   outb(0x00, tmpcip);
+   outb(0x00, dev->pciport[c]);

i = inb(dev->ioport[c] + 0x17);

-   if (dev->dev_id == ATP885_DEVID) {
-   tmpcip += 2;
-   outb(0x06, tmpcip);
-   tmpcip -= 2;
-   }
+   if (dev->dev_id == ATP885_DEVID)
+   outb(0x06, dev->pciport[c] + 2);
 
target_id = inb(dev->ioport[c] + 0x15);
 
@@ -303,13 +297,12 @@ stop_dma:

/* enable 32 bit fifo transfer */   
if (dev->dev_id == ATP885_DEVID) {
-   tmpcip = dev->pciport[c] + 1;
-   i=inb(tmpcip) & 0xf3;
+   i=inb(dev->pciport[c] + 1) & 0xf3;
//j=workreq->cmnd[0];   
if ((workreq->cmnd[0] == 0x08) || 
(workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] 
== 0x2a)) {
   i |= 0x0c;
}
-   outb(i,tmpcip); 

+   outb(i, dev->pciport[c] + 1);
} else if ((dev->dev_id == ATP880_DEVID1) ||
   (dev->dev_id == ATP880_DEVID2) ) {
if ((workreq->cmnd[0] == 0x08) || 
(workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] 
== 0x2a)) {
@@ -371,25 +364,20 @@ stop_dma:
}
}   
}
-   tmpcip = dev->pciport[c] + 0x04;
-   outl(dev->id[c][target_id].prdaddr, tmpcip);
+   outl(dev->id[c][target_id].prdaddr, dev->pciport[c] + 
0x04);
 #ifdef ED_DBGP
printk("dev->id[%d][%d].prdaddr 0x%8x\n", c, target_id, 
dev->id[c][target_id].prdaddr);
 #endif
-   if (dev->dev_id == ATP885_DEVID) {
-   tmpcip -= 0x04;
-   } else {
-   tmpcip -= 0x02;
-   outb(0x06, tmpcip);
-   outb(0x00, tmpcip);
-   tmpcip -= 0x02;
+   if (dev->dev_id != ATP885_DEVID) {
+   outb(0x06, dev->pciport[c] + 2);
+   outb(0x00, dev->pciport[c] + 2);
}
/*
 *  Check transfer direction
 */
if (dev->id[c][target_id].dirct != 0) {
outb(0x08, dev->ioport[c] + 0x18);
-   outb(0x01, tmpcip);
+   outb(0x01, dev->pciport[c]);
dev->in_int[c] = 0;
 #ifdef ED_DBGP
printk("status 0x80 return dirct != 0\n");
@@ -397,7 +385,7 @@ stop_d

[PATCH 21/52] atp870u: Convert is885() to use wrappers

2015-11-17 Thread Ondrej Zary
Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |  358 
 1 file changed, 179 insertions(+), 179 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 1b9276f..ad7af54 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -41,7 +41,7 @@
 
 static struct scsi_host_template atp870u_template;
 static void send_s870(struct atp_unit *dev,unsigned char c);
-static void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c);
+static void is885(struct atp_unit *dev, unsigned char c);
 static void tscam_885(void);
 
 static inline void atp_writeb_base(struct atp_unit *atp, u8 reg, u8 val)
@@ -2521,9 +2521,9 @@ flash_ok_885:
 
tscam_885();
printk(KERN_INFO "   Scanning Channel A SCSI Device ...\n");
-   is885(p, base_io + 0x80, 0);
+   is885(p, 0);
printk(KERN_INFO "   Scanning Channel B SCSI Device ...\n");
-   is885(p, base_io + 0xc0, 1);
+   is885(p, 1);
 
k = inb(base_io + 0x28) & 0xcf;
k |= 0xc0;
@@ -2825,7 +2825,7 @@ static void tscam_885(void)
 
 
 
-static void is885(struct atp_unit *dev, unsigned int wkport,unsigned char c)
+static void is885(struct atp_unit *dev, unsigned char c)
 {
unsigned char i, j, k, rmb, n, lvdmode;
unsigned short int m;
@@ -2839,7 +2839,7 @@ static void is885(struct atp_unit *dev, unsigned int 
wkport,unsigned char c)
static unsigned char wide[6] =  {0x80, 1, 2, 3, 1, 0};
static unsigned char u3[9] = { 0x80,1,6,4,0x09,00,0x0e,0x01,0x02 };
 
-   lvdmode=inb(wkport + 0x1b) >> 7;
+   lvdmode=atp_readb_io(dev, c, 0x1b) >> 7;
 
for (i = 0; i < 16; i++) {
m = 1;
@@ -2851,93 +2851,93 @@ static void is885(struct atp_unit *dev, unsigned int 
wkport,unsigned char c)
printk(KERN_INFO " ID: %2d  Host Adapter\n", 
dev->host_id[c]);
continue;
}
-   outb(0x01, wkport + 0x1b);
-   outb(0x08, wkport + 0x01);
-   outb(0x7f, wkport + 0x02);
-   outb(satn[0], wkport + 0x03);
-   outb(satn[1], wkport + 0x04);
-   outb(satn[2], wkport + 0x05);
-   outb(satn[3], wkport + 0x06);
-   outb(satn[4], wkport + 0x07);
-   outb(satn[5], wkport + 0x08);
-   outb(0, wkport + 0x0f);
-   outb(dev->id[c][i].devsp, wkport + 0x11);
+   atp_writeb_io(dev, c, 0x1b, 0x01);
+   atp_writeb_io(dev, c, 1, 0x08);
+   atp_writeb_io(dev, c, 2, 0x7f);
+   atp_writeb_io(dev, c, 3, satn[0]);
+   atp_writeb_io(dev, c, 4, satn[1]);
+   atp_writeb_io(dev, c, 5, satn[2]);
+   atp_writeb_io(dev, c, 6, satn[3]);
+   atp_writeb_io(dev, c, 7, satn[4]);
+   atp_writeb_io(dev, c, 8, satn[5]);
+   atp_writeb_io(dev, c, 0x0f, 0);
+   atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);

-   outb(0, wkport + 0x12);
-   outb(satn[6], wkport + 0x13);
-   outb(satn[7], wkport + 0x14);
+   atp_writeb_io(dev, c, 0x12, 0);
+   atp_writeb_io(dev, c, 0x13, satn[6]);
+   atp_writeb_io(dev, c, 0x14, satn[7]);
j = i;
if ((j & 0x08) != 0) {
j = (j & 0x07) | 0x40;
}
-   outb(j, wkport + 0x15);
-   outb(satn[8], wkport + 0x18);
+   atp_writeb_io(dev, c, 0x15, j);
+   atp_writeb_io(dev, c, 0x18, satn[8]);
 
-   while ((inb(wkport + 0x1f) & 0x80) == 0x00)
+   while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
cpu_relax();
-   if ((inb(wkport + 0x17) != 0x11) && (inb(wkport + 0x17) != 
0x8e)) {
+   if ((atp_readb_io(dev, c, 0x17) != 0x11) && (atp_readb_io(dev, 
c, 0x17) != 0x8e)) {
continue;
}
-   while (inb(wkport + 0x17) != 0x8e)
+   while (atp_readb_io(dev, c, 0x17) != 0x8e)
cpu_relax();
dev->active_id[c] |= m;
 
-   outb(0x30, wkport + 0x10);
-   outb(0x00, wkport + 0x14);
+   atp_writeb_io(dev, c, 0x10, 0x30);
+   atp_writeb_io(dev, c, 0x14, 0x00);
 
 phase_cmd:
-   outb(0x08, wkport + 0x18);
-   while ((inb(wkport + 0x1f) & 0x80) == 0x00)
+   atp_writeb_io(dev, c, 0x18, 0x08);
+   while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
cpu_relax();
-   j = inb(wkport + 0x17);
+   j = atp_readb_io(dev, c, 0x17);
if (j != 0x16) {
-   outb(0x41, wkport + 0x10);
+   atp_w

[PATCH 16/52] atp870u: Remove ugly gotos #4

2015-11-17 Thread Ondrej Zary
Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   32 +++-
 1 file changed, 15 insertions(+), 17 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index b3d4e9d..68afe11 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -970,19 +970,19 @@ static void tscam(struct Scsi_Host *host)
} else {
outb(0x00, dev->ioport[0] + 0x1b);
}
-wait_rdyok:
-   outb(0x09, dev->ioport[0] + 0x18);
-
-   while ((inb(dev->ioport[0] + 0x1f) & 0x80) == 0x00)
-   cpu_relax();
-   k = inb(dev->ioport[0] + 0x17);
-   if (k != 0x16) {
-   if ((k == 0x85) || (k == 0x42)) {
-   continue;
-   }
-   outb(0x41, dev->ioport[0] + 0x10);
-   goto wait_rdyok;
-   }
+   do {
+   outb(0x09, dev->ioport[0] + 0x18);
+
+   while ((inb(dev->ioport[0] + 0x1f) & 0x80) == 0x00)
+   cpu_relax();
+   k = inb(dev->ioport[0] + 0x17);
+   if ((k == 0x85) || (k == 0x42))
+   break;
+   if (k != 0x16)
+   outb(0x41, dev->ioport[0] + 0x10);
+   } while (k != 0x16);
+   if ((k == 0x85) || (k == 0x42))
+   continue;
assignid_map |= m;
 
}
@@ -1003,10 +1003,8 @@ wait_rdyok:
mdelay(128);
val &= 0x00fb;  /* after 1ms no msg */
outw(val, dev->ioport[0] + 0x1c);
-wait_nomsg:
-   if ((inb(dev->ioport[0] + 0x1c) & 0x04) != 0) {
-   goto wait_nomsg;
-   }
+   while ((inb(dev->ioport[0] + 0x1c) & 0x04) != 0)
+   ;
outb(1, 0x80);
udelay(100);
for (n = 0; n < 0x3; n++) {
-- 
Ondrej Zary

--
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 25/52] atp870u: Remove is880()

2015-11-17 Thread Ondrej Zary
Now that is880() and is885() are almost identical (except for some cpu_relax()
calls and debug printks), remove is880() and use is885() instead.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |  572 +---
 1 file changed, 1 insertion(+), 571 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 1c4b1f9..d10026a 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1596,576 +1596,6 @@ set_syn_ok:
atp_writeb_io(dev, c, 0x3a, atp_readb_io(dev, c, 0x3a) & 0xef);
 }
 
-static void is880(struct atp_unit *dev, unsigned char c, unsigned char lvdmode)
-{
-   unsigned char i, j, k, rmb, n;
-   unsigned short int m;
-   static unsigned char mbuf[512];
-   static unsigned char satn[9] = { 0, 0, 0, 0, 0, 0, 0, 6, 6 };
-   static unsigned char inqd[9] = { 0x12, 0, 0, 0, 0x24, 0, 0, 0x24, 6 };
-   static unsigned char synn[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
-   unsigned char synu[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
-   static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x19, 0x0e };
-   unsigned char synuw[6] = { 0x80, 1, 3, 1, 0x0a, 0x0e };
-   static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };
-   static unsigned char u3[9] = { 0x80, 1, 6, 4, 0x09, 00, 0x0e, 0x01, 
0x02 };
-
-   for (i = 0; i < 16; i++) {
-   m = 1;
-   m = m << i;
-   if ((m & dev->active_id[c]) != 0) {
-   continue;
-   }
-   if (i == dev->host_id[c]) {
-   printk(KERN_INFO " ID: %2d  Host Adapter\n", 
dev->host_id[c]);
-   continue;
-   }
-   atp_writeb_io(dev, c, 0x1b, 0x01);
-   atp_writeb_io(dev, c, 1, 0x08);
-   atp_writeb_io(dev, c, 2, 0x7f);
-   atp_writeb_io(dev, c, 3, satn[0]);
-   atp_writeb_io(dev, c, 4, satn[1]);
-   atp_writeb_io(dev, c, 5, satn[2]);
-   atp_writeb_io(dev, c, 6, satn[3]);
-   atp_writeb_io(dev, c, 7, satn[4]);
-   atp_writeb_io(dev, c, 8, satn[5]);
-   atp_writeb_io(dev, c, 0x0f, 0);
-   atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
-   atp_writeb_io(dev, c, 0x12, 0);
-   atp_writeb_io(dev, c, 0x13, satn[6]);
-   atp_writeb_io(dev, c, 0x14, satn[7]);
-   j = i;
-   if ((j & 0x08) != 0) {
-   j = (j & 0x07) | 0x40;
-   }
-   atp_writeb_io(dev, c, 0x15, j);
-   atp_writeb_io(dev, c, 0x18, satn[8]);
-
-   while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
-   cpu_relax();
-
-   if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 
0x17) != 0x8e)
-   continue;
-
-   while (atp_readb_io(dev, c, 0x17) != 0x8e)
-   cpu_relax();
-
-   dev->active_id[c] |= m;
-
-   atp_writeb_io(dev, c, 0x10, 0x30);
-   atp_writeb_io(dev, c, 0x14, 0x00);
-
-phase_cmd:
-   atp_writeb_io(dev, c, 0x18, 0x08);
-
-   while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
-   cpu_relax();
-
-   j = atp_readb_io(dev, c, 0x17);
-   if (j != 0x16) {
-   atp_writeb_io(dev, c, 0x10, 0x41);
-   goto phase_cmd;
-   }
-sel_ok:
-   atp_writeb_io(dev, c, 3, inqd[0]);
-   atp_writeb_io(dev, c, 4, inqd[1]);
-   atp_writeb_io(dev, c, 5, inqd[2]);
-   atp_writeb_io(dev, c, 6, inqd[3]);
-   atp_writeb_io(dev, c, 7, inqd[4]);
-   atp_writeb_io(dev, c, 8, inqd[5]);
-   atp_writeb_io(dev, c, 0x0f, 0);
-   atp_writeb_io(dev, c, 0x11, dev->id[c][i].devsp);
-   atp_writeb_io(dev, c, 0x12, 0);
-   atp_writeb_io(dev, c, 0x13, inqd[6]);
-   atp_writeb_io(dev, c, 0x14, inqd[7]);
-   atp_writeb_io(dev, c, 0x18, inqd[8]);
-
-   while ((atp_readb_io(dev, c, 0x1f) & 0x80) == 0x00)
-   cpu_relax();
-
-   if (atp_readb_io(dev, c, 0x17) != 0x11 && atp_readb_io(dev, c, 
0x17) != 0x8e)
-   continue;
-
-   while (atp_readb_io(dev, c, 0x17) != 0x8e)
-   cpu_relax();
-
-   atp_writeb_io(dev, c, 0x1b, 0x00);
-   atp_writeb_io(dev, c, 0x18, 0x08);
-   j = 0;
-rd_inq_data:
-   k = atp_readb_io(dev, c, 0x1f);
-   if ((k & 0x01) != 0) {
-   mbuf[j++] = atp_readb_io(dev, c, 0x19);
-   goto rd_inq_data;
-   }
-   if ((k & 0x80) == 0) {
-   goto rd_inq_data;
-   }
-   j = atp_readb_io(dev, c, 0x17);
- 

[PATCH 04/52] atp870u: Untangle tmport #2

2015-11-17 Thread Ondrej Zary
Untangle the tmport crap so it becomes obvious what ports are accessed.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   79 
 1 file changed, 32 insertions(+), 47 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index a25a300..7112337 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -562,7 +562,7 @@ static int atp870u_queuecommand_lck(struct scsi_cmnd *req_p,
 void (*done) (struct scsi_cmnd *))
 {
unsigned char c;
-   unsigned int tmport,m;  
+   unsigned int m;
struct atp_unit *dev;
struct Scsi_Host *host;
 
@@ -631,11 +631,10 @@ static int atp870u_queuecommand_lck(struct scsi_cmnd 
*req_p,
return 0;
}
dev->quereq[c][dev->quend[c]] = req_p;
-   tmport = dev->ioport[c] + 0x1c;
 #ifdef ED_DBGP 
-   printk("dev->ioport[c] = %x inb(tmport) = %x dev->in_int[%d] = %d 
dev->in_snd[%d] = 
%d\n",dev->ioport[c],inb(tmport),c,dev->in_int[c],c,dev->in_snd[c]);
+   printk("dev->ioport[c] = %x inb(dev->ioport[c] + 0x1c) = %x 
dev->in_int[%d] = %d dev->in_snd[%d] = %d\n",dev->ioport[c],inb(dev->ioport[c] 
+ 0x1c),c,dev->in_int[c],c,dev->in_snd[c]);
 #endif
-   if ((inb(tmport) == 0) && (dev->in_int[c] == 0) && (dev->in_snd[c] == 
0)) {
+   if ((inb(dev->ioport[c] + 0x1c) == 0) && (dev->in_int[c] == 0) && 
(dev->in_snd[c] == 0)) {
 #ifdef ED_DBGP
printk("Call sent_s870(atp870u_queuecommand)\n");
 #endif 
@@ -660,7 +659,6 @@ static DEF_SCSI_QCMD(atp870u_queuecommand)
  */
 static void send_s870(struct atp_unit *dev,unsigned char c)
 {
-   unsigned int tmport;
struct scsi_cmnd *workreq;
unsigned int i;//,k;
unsigned char  j, target_id;
@@ -712,12 +710,10 @@ static void send_s870(struct atp_unit *dev,unsigned char 
c)
dev->in_snd[c] = 0;
return;
 cmd_subp:
-   tmport = dev->ioport[c] + 0x1f;
-   if ((inb(tmport) & 0xb0) != 0) {
+   if ((inb(dev->ioport[c] + 0x1f) & 0xb0) != 0) {
goto abortsnd;
}
-   tmport = dev->ioport[c] + 0x1c;
-   if (inb(tmport) == 0) {
+   if (inb(dev->ioport[c] + 0x1c) == 0) {
goto oktosend;
}
 abortsnd:
@@ -752,7 +748,6 @@ oktosend:
l = 0;
}
 
-   tmport = dev->ioport[c] + 0x1b;
j = 0;
target_id = scmd_id(workreq);
 
@@ -764,9 +759,9 @@ oktosend:
if ((w & dev->wide_id[c]) != 0) {
j |= 0x01;
}
-   outb(j, tmport);
-   while ((inb(tmport) & 0x01) != j) {
-   outb(j,tmport);
+   outb(j, dev->ioport[c] + 0x1b);
+   while ((inb(dev->ioport[c] + 0x1b) & 0x01) != j) {
+   outb(j,dev->ioport[c] + 0x1b);
 #ifdef ED_DBGP
printk("send_s870 while loop 1\n");
 #endif
@@ -775,24 +770,21 @@ oktosend:
 *  Write the command
 */
 
-   tmport = dev->ioport[c];
-   outb(workreq->cmd_len, tmport++);
-   outb(0x2c, tmport++);
+   outb(workreq->cmd_len, dev->ioport[c] + 0x00);
+   outb(0x2c, dev->ioport[c] + 0x01);
if (dev->dev_id == ATP885_DEVID) {
-   outb(0x7f, tmport++);
+   outb(0x7f, dev->ioport[c] + 0x02);
} else {
-   outb(0xcf, tmport++);   
+   outb(0xcf, dev->ioport[c] + 0x02);
}   
for (i = 0; i < workreq->cmd_len; i++) {
-   outb(workreq->cmnd[i], tmport++);
+   outb(workreq->cmnd[i], dev->ioport[c] + 0x03 + i);
}
-   tmport = dev->ioport[c] + 0x0f;
-   outb(workreq->device->lun, tmport);
-   tmport += 0x02;
+   outb(workreq->device->lun, dev->ioport[c] + 0x0f);
/*
 *  Write the target
 */
-   outb(dev->id[c][target_id].devsp, tmport++); 
+   outb(dev->id[c][target_id].devsp, dev->ioport[c] + 0x11);
 #ifdef ED_DBGP 
printk("dev->id[%d][%d].devsp = 
%2x\n",c,target_id,dev->id[c][target_id].devsp);
 #endif
@@ -801,9 +793,9 @@ oktosend:
/*
 *  Write transfer size
 */
-   outb((unsigned char) (((unsigned char *) (&l))[2]), tmport++);
-   outb((unsigned char) (((unsigned char *) (&l))[1]), tmport++);
-   outb((unsigned char) (((unsigned char *) (&l))[0]), tmport++);
+   outb((unsigned char) (((unsigned char *) (&l))[2]), dev->ioport[c] + 
0x12);
+   outb((unsigned char) (((unsigned char *) (&l))[1]), dev->ioport[c] + 
0x13);
+   outb((unsigned char) (((unsigned char *) (&l))[0]), dev->ioport[c] + 
0x14);
j = target_id;  
dev->id[c][j].last_len = l;
dev->id[c][j].tran_len = 0;
@@ -820,21 +812,19 @@ oktosend:
 *  Check transfer direction
 */
if (workreq->sc_data_direction == DMA_TO_DEVICE) {
-   outb((unsigned char) (j | 0x20), tmport++);
+   outb((unsigned char) (j | 0x20), dev->ioport[c] + 0x15);

[PATCH 01/52] atp870u: Remove workport

2015-11-17 Thread Ondrej Zary
Remove workport temporary variable to simplify the code.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   59 +++-
 1 file changed, 28 insertions(+), 31 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 05301bc..3db9d0c 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -51,7 +51,7 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id)
unsigned char i, j, c, target_id, lun,cmdp;
unsigned char *prd;
struct scsi_cmnd *workreq;
-   unsigned int workport, tmport, tmport1;
+   unsigned int tmport, tmport1;
unsigned long adrcnt, k;
 #ifdef ED_DBGP
unsigned long l;
@@ -76,10 +76,9 @@ ch_sel:
 #endif 
dev->in_int[c] = 1;
cmdp = inb(dev->ioport[c] + 0x10);
-   workport = dev->ioport[c];
if (dev->working[c] != 0) {
if (dev->dev_id == ATP885_DEVID) {
-   tmport1 = workport + 0x16;
+   tmport1 = dev->ioport[c] + 0x16;
if ((inb(tmport1) & 0x80) == 0)
outb((inb(tmport1) | 0x80), tmport1);
}   
@@ -160,7 +159,7 @@ stop_dma:
 *  Flip wide
 */ 
if (dev->wide_id[c] != 0) {
-   tmport = workport + 0x1b;
+   tmport = dev->ioport[c] + 0x1b;
outb(0x01, tmport);
while ((inb(tmport) & 0x01) != 0x01) {
outb(0x01, tmport);
@@ -276,9 +275,9 @@ stop_dma:
if (dev->dev_id == ATP885_DEVID) {
j = inb(dev->baseport + 0x29) & 0xfe;
outb(j, dev->baseport + 0x29);
-   tmport = workport + 0x16;
+   tmport = dev->ioport[c] + 0x16;
} else {
-   tmport = workport + 0x10;
+   tmport = dev->ioport[c] + 0x10;
outb(0x45, tmport);
tmport += 0x06; 
}
@@ -293,7 +292,7 @@ stop_dma:
target_id &= 0x07;
}
if (dev->dev_id == ATP885_DEVID) {
-   tmport = workport + 0x10;
+   tmport = dev->ioport[c] + 0x10;
outb(0x45, tmport);
}
workreq = dev->id[c][target_id].curr_req;
@@ -304,7 +303,7 @@ stop_dma:
printk("\n");
 #endif 

-   tmport = workport + 0x0f;
+   tmport = dev->ioport[c] + 0x0f;
outb(lun, tmport);
tmport += 0x02;
outb(dev->id[c][target_id].devsp, tmport++);
@@ -338,21 +337,21 @@ stop_dma:
outb(i,tmpcip); 

} else if ((dev->dev_id == ATP880_DEVID1) ||
   (dev->dev_id == ATP880_DEVID2) ) {
-   tmport = workport - 0x05;
+   tmport = dev->ioport[c] - 0x05;
if ((workreq->cmnd[0] == 0x08) || 
(workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] 
== 0x2a)) {
outb((unsigned char) ((inb(tmport) & 
0x3f) | 0xc0), tmport);
} else {
outb((unsigned char) (inb(tmport) & 
0x3f), tmport);
}
} else {
-   tmport = workport + 0x3a;
+   tmport = dev->ioport[c] + 0x3a;
if ((workreq->cmnd[0] == 0x08) || 
(workreq->cmnd[0] == 0x28) || (workreq->cmnd[0] == 0x0a) || (workreq->cmnd[0] 
== 0x2a)) {
outb((unsigned char) ((inb(tmport) & 
0xf3) | 0x08), tmport);
} else {
outb((unsigned char) (inb(tmport) & 
0xf3), tmport);
}   

}   
-   tmport = workport + 0x1b;
+   tmport = dev->ioport[c] + 0x1b;
j = 0;
id = 1;
id = id << target_id;
@@ -367,7 +366,7 @@ stop_dma:
outb(j,tm

[PATCH 09/52] atp870u: Untangle tmport #7

2015-11-17 Thread Ondrej Zary
Untangle the tmport crap so it becomes obvious what ports are accessed.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |   16 +---
 1 file changed, 5 insertions(+), 11 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index e398ea5..f5a11f4 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -2716,7 +2716,6 @@ static int atp870u_abort(struct scsi_cmnd * SCpnt)
 {
unsigned char  j, k, c;
struct scsi_cmnd *workrequ;
-   unsigned int tmport;
struct atp_unit *dev;   
struct Scsi_Host *host;
host = SCpnt->device->host;
@@ -2726,18 +2725,13 @@ static int atp870u_abort(struct scsi_cmnd * SCpnt)
printk(" atp870u: abort Channel = %x \n", c);
printk("working=%x last_cmd=%x ", dev->working[c], dev->last_cmd[c]);
printk(" quhdu=%x quendu=%x ", dev->quhd[c], dev->quend[c]);
-   tmport = dev->ioport[c];
for (j = 0; j < 0x18; j++) {
-   printk(" r%2x=%2x", j, inb(tmport++));
+   printk(" r%2x=%2x", j, inb(dev->ioport[c] + j));
}
-   tmport += 0x04;
-   printk(" r1c=%2x", inb(tmport));
-   tmport += 0x03;
-   printk(" r1f=%2x in_snd=%2x ", inb(tmport), dev->in_snd[c]);
-   tmport= dev->pciport[c];
-   printk(" d00=%2x", inb(tmport));
-   tmport += 0x02;
-   printk(" d02=%2x", inb(tmport));
+   printk(" r1c=%2x", inb(dev->ioport[c] + 0x1c));
+   printk(" r1f=%2x in_snd=%2x ", inb(dev->ioport[c] + 0x1f), 
dev->in_snd[c]);
+   printk(" d00=%2x", inb(dev->pciport[c]));
+   printk(" d02=%2x", inb(dev->pciport[c] + 0x02));
for(j=0;j<16;j++) {
   if (dev->id[c][j].curr_req != NULL) {
workrequ = dev->id[c][j].curr_req;
-- 
Ondrej Zary

--
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 00/52] [resend] atp870u: Major rework

2015-11-17 Thread Ondrej Zary
This patch series removes the first level of crap from atp870u - the worst
(in-tree) SCSI driver [1] and then cleans up the code a bit.

First the driver is converted to C from something that looks like a (bad)
assembler code: use of tmport for all I/O accesses and gotos all over the
code.
Then I/O access wrappers are introduced.
Finally, is870, is880 and is885 are unified and two of them removed.

After that, some cleanups are done. There's still a lot of work left to do.

Tested on AEC-6710D (ATP870IU-C).

[1] http://www.spinics.net/lists/linux-scsi/msg81142.html

 atp870u.c | 3707 +-
 atp870u.h |4
 2 files changed, 1064 insertions(+), 2647 deletions(-)

Reviewed-by: Hannes Reinecke 
Acked-by: Christoph Hellwig 

--
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 05/52] atp870u: Untangle tmport #3

2015-11-17 Thread Ondrej Zary
Untangle the tmport crap so it becomes obvious what ports are accessed.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |  118 
 1 file changed, 49 insertions(+), 69 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 7112337..a23f387 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -933,38 +933,36 @@ oktosend:
 
 static unsigned char fun_scam(struct atp_unit *dev, unsigned short int *val)
 {
-   unsigned int tmport;
unsigned short int i, k;
unsigned char j;
 
-   tmport = dev->ioport[0] + 0x1c;
-   outw(*val, tmport);
+   outw(*val, dev->ioport[0] + 0x1c);
 FUN_D7:
for (i = 0; i < 10; i++) {  /* stable >= bus settle delay(400 ns)  
*/
-   k = inw(tmport);
+   k = inw(dev->ioport[0] + 0x1c);
j = (unsigned char) (k >> 8);
if ((k & 0x8000) != 0) {/* DB7 all release?*/
goto FUN_D7;
}
}
*val |= 0x4000; /* assert DB6   */
-   outw(*val, tmport);
+   outw(*val, dev->ioport[0] + 0x1c);
*val &= 0xdfff; /* assert DB5   */
-   outw(*val, tmport);
+   outw(*val, dev->ioport[0] + 0x1c);
 FUN_D5:
for (i = 0; i < 10; i++) {  /* stable >= bus settle delay(400 ns) */
-   if ((inw(tmport) & 0x2000) != 0) {  /* DB5 all release? 
  */
+   if ((inw(dev->ioport[0] + 0x1c) & 0x2000) != 0) {   /* DB5 
all release?   */
goto FUN_D5;
}
}
*val |= 0x8000; /* no DB4-0, assert DB7*/
*val &= 0xe0ff;
-   outw(*val, tmport);
+   outw(*val, dev->ioport[0] + 0x1c);
*val &= 0xbfff; /* release DB6 */
-   outw(*val, tmport);
+   outw(*val, dev->ioport[0] + 0x1c);
 FUN_D6:
for (i = 0; i < 10; i++) {  /* stable >= bus settle delay(400 ns)  
*/
-   if ((inw(tmport) & 0x4000) != 0) {  /* DB6 all release?  */
+   if ((inw(dev->ioport[0] + 0x1c) & 0x4000) != 0) {   /* DB6 
all release?  */
goto FUN_D6;
}
}
@@ -975,7 +973,6 @@ FUN_D6:
 static void tscam(struct Scsi_Host *host)
 {
 
-   unsigned int tmport;
unsigned char i, j, k;
unsigned long n;
unsigned short int m, assignid_map, val;
@@ -992,11 +989,9 @@ static void tscam(struct Scsi_Host *host)
}
  */
 
-   tmport = dev->ioport[0] + 1;
-   outb(0x08, tmport++);
-   outb(0x7f, tmport);
-   tmport = dev->ioport[0] + 0x11;
-   outb(0x20, tmport);
+   outb(0x08, dev->ioport[0] + 1);
+   outb(0x7f, dev->ioport[0] + 2);
+   outb(0x20, dev->ioport[0] + 0x11);
 
if ((dev->scam_on & 0x40) == 0) {
return;
@@ -1009,14 +1004,13 @@ static void tscam(struct Scsi_Host *host)
j = 8;
}
assignid_map = m;
-   tmport = dev->ioport[0] + 0x02;
-   outb(0x02, tmport++);   /* 2*2=4ms,3EH 2/32*3E=3.9ms */
-   outb(0, tmport++);
-   outb(0, tmport++);
-   outb(0, tmport++);
-   outb(0, tmport++);
-   outb(0, tmport++);
-   outb(0, tmport++);
+   outb(0x02, dev->ioport[0] + 0x02);  /* 2*2=4ms,3EH 2/32*3E=3.9ms */
+   outb(0, dev->ioport[0] + 0x03);
+   outb(0, dev->ioport[0] + 0x04);
+   outb(0, dev->ioport[0] + 0x05);
+   outb(0, dev->ioport[0] + 0x06);
+   outb(0, dev->ioport[0] + 0x07);
+   outb(0, dev->ioport[0] + 0x08);
 
for (i = 0; i < j; i++) {
m = 1;
@@ -1024,79 +1018,69 @@ static void tscam(struct Scsi_Host *host)
if ((m & assignid_map) != 0) {
continue;
}
-   tmport = dev->ioport[0] + 0x0f;
-   outb(0, tmport++);
-   tmport += 0x02;
-   outb(0, tmport++);
-   outb(0, tmport++);
-   outb(0, tmport++);
+   outb(0, dev->ioport[0] + 0x0f);
+   outb(0, dev->ioport[0] + 0x12);
+   outb(0, dev->ioport[0] + 0x13);
+   outb(0, dev->ioport[0] + 0x14);
if (i > 7) {
k = (i & 0x07) | 0x40;
} else {
k = i;
}
-   outb(k, tmport++);
-   tmport = dev->ioport[0] + 0x1b;
+   outb(k, dev->ioport[0] + 0x15);
if (dev->chip_ver == 4) {
-   outb(0x01, tmport);
+   outb(0x01, dev->ioport[0] + 0x1b);
} else {
-   outb(0x00, tmport);
+   outb(0x00, dev->ioport[0] + 0x1b);
}
 wait_rdyok:
-   tmport = dev->ioport[0] + 0x18;
-   outb(0x09, tmport);
-   tmport += 0x07;
+   outb(

[PATCH 02/52] atp870u: Remove tmport1

2015-11-17 Thread Ondrej Zary
Remove tmport1 temporary variable to simplify the code.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 3db9d0c..aac7d47 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -51,7 +51,7 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id)
unsigned char i, j, c, target_id, lun,cmdp;
unsigned char *prd;
struct scsi_cmnd *workreq;
-   unsigned int tmport, tmport1;
+   unsigned int tmport;
unsigned long adrcnt, k;
 #ifdef ED_DBGP
unsigned long l;
@@ -78,9 +78,8 @@ ch_sel:
cmdp = inb(dev->ioport[c] + 0x10);
if (dev->working[c] != 0) {
if (dev->dev_id == ATP885_DEVID) {
-   tmport1 = dev->ioport[c] + 0x16;
-   if ((inb(tmport1) & 0x80) == 0)
-   outb((inb(tmport1) | 0x80), tmport1);
+   if ((inb(dev->ioport[c] + 0x16) & 0x80) == 0)
+   outb((inb(dev->ioport[c] + 0x16) | 0x80), 
dev->ioport[c] + 0x16);
}   
tmpcip = dev->pciport[c];
if ((inb(tmpcip) & 0x08) != 0)
-- 
Ondrej Zary

--
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/52] atp870u: Untangle tmport

2015-11-17 Thread Ondrej Zary
Untangle the tmport crap so it becomes obvious what ports are accessed.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |  186 ++--
 1 file changed, 71 insertions(+), 115 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index aac7d47..a25a300 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -51,7 +51,6 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id)
unsigned char i, j, c, target_id, lun,cmdp;
unsigned char *prd;
struct scsi_cmnd *workreq;
-   unsigned int tmport;
unsigned long adrcnt, k;
 #ifdef ED_DBGP
unsigned long l;
@@ -61,8 +60,7 @@ static irqreturn_t atp870u_intr_handle(int irq, void *dev_id)
struct atp_unit *dev = (struct atp_unit *)&host->hostdata;
 
for (c = 0; c < 2; c++) {
-   tmport = dev->ioport[c] + 0x1f;
-   j = inb(tmport);
+   j = inb(dev->ioport[c] + 0x1f);
if ((j & 0x80) != 0)
{   
goto ch_sel;
@@ -97,9 +95,8 @@ ch_sel:
 stop_dma:
tmpcip = dev->pciport[c];
outb(0x00, tmpcip);
-   tmport -= 0x08;

-   i = inb(tmport);
+   i = inb(dev->ioport[c] + 0x17);

if (dev->dev_id == ATP885_DEVID) {
tmpcip += 2;
@@ -107,9 +104,7 @@ stop_dma:
tmpcip -= 2;
}
 
-   tmport -= 0x02;
-   target_id = inb(tmport);
-   tmport += 0x02;
+   target_id = inb(dev->ioport[c] + 0x15);
 
/*
 *  Remap wide devices onto id numbers
@@ -137,11 +132,10 @@ stop_dma:
   dev->last_cmd[c] = 0xff;
}
if (dev->dev_id == ATP885_DEVID) {
-   tmport -= 0x05;
adrcnt = 0;
-   ((unsigned char *) &adrcnt)[2] = inb(tmport++);
-   ((unsigned char *) &adrcnt)[1] = inb(tmport++);
-   ((unsigned char *) &adrcnt)[0] = inb(tmport);
+   ((unsigned char *) &adrcnt)[2] = 
inb(dev->ioport[c] + 0x12);
+   ((unsigned char *) &adrcnt)[1] = 
inb(dev->ioport[c] + 0x13);
+   ((unsigned char *) &adrcnt)[0] = 
inb(dev->ioport[c] + 0x14);
if (dev->id[c][target_id].last_len != adrcnt)
{
k = dev->id[c][target_id].last_len;
@@ -150,7 +144,7 @@ stop_dma:
dev->id[c][target_id].last_len = adrcnt;
   
}
 #ifdef ED_DBGP
-   printk("tmport = %x 
dev->id[c][target_id].last_len = %d dev->id[c][target_id].tran_len = 
%d\n",tmport,dev->id[c][target_id].last_len,dev->id[c][target_id].tran_len);
+   printk("dev->id[c][target_id].last_len = %d 
dev->id[c][target_id].tran_len = 
%d\n",dev->id[c][target_id].last_len,dev->id[c][target_id].tran_len);
 #endif 
}
 
@@ -158,10 +152,9 @@ stop_dma:
 *  Flip wide
 */ 
if (dev->wide_id[c] != 0) {
-   tmport = dev->ioport[c] + 0x1b;
-   outb(0x01, tmport);
-   while ((inb(tmport) & 0x01) != 0x01) {
-   outb(0x01, tmport);
+   outb(0x01, dev->ioport[c] + 0x1b);
+   while ((inb(dev->ioport[c] + 0x1b) & 0x01) != 
0x01) {
+   outb(0x01, dev->ioport[c] + 0x1b);
}
}   
/*
@@ -196,19 +189,16 @@ stop_dma:
if ((dev->last_cmd[c] & 0xf0) != 0x40) {
   dev->last_cmd[c] = 0xff;
}
-   tmport -= 0x05;
adrcnt = 0;
-   ((unsigned char *) &adrcnt)[2] = inb(tmport++);
-   ((unsigned char *) &adrcnt)[1] = inb(tmport++);
-   ((unsigned char *) &adrcnt)[0] = inb(tmport);
+   ((unsigned char *) &adrcnt)[2] = inb(dev->ioport[c] + 
0x12);
+   ((unsigned char *) &adrcnt)[1] = inb(dev->ioport[c] + 
0x13);
+   ((unsigned char *) &adrcnt)[0] = inb(dev->ioport[c] + 
0x14);
k = dev->id[c][target_id].last_len;
k -= adrcnt;
dev->id[c][target_id].tran_len = k;
 

[PATCH 07/52] atp870u: Untangle tmport #5

2015-11-17 Thread Ondrej Zary
Untangle the tmport crap so it becomes obvious what ports are accessed.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |  470 ++--
 1 file changed, 173 insertions(+), 297 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 3e3a68b..3bf01fc 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1639,7 +1639,6 @@ set_syn_ok:
 
 static void is880(struct atp_unit *dev, unsigned int wkport)
 {
-   unsigned int tmport;
unsigned char i, j, k, rmb, n, lvdmode;
unsigned short int m;
static unsigned char mbuf[512];
@@ -1664,130 +1663,100 @@ static void is880(struct atp_unit *dev, unsigned int 
wkport)
printk(KERN_INFO " ID: %2d  Host Adapter\n", 
dev->host_id[0]);
continue;
}
-   tmport = wkport + 0x5b;
-   outb(0x01, tmport);
-   tmport = wkport + 0x41;
-   outb(0x08, tmport++);
-   outb(0x7f, tmport++);
-   outb(satn[0], tmport++);
-   outb(satn[1], tmport++);
-   outb(satn[2], tmport++);
-   outb(satn[3], tmport++);
-   outb(satn[4], tmport++);
-   outb(satn[5], tmport++);
-   tmport += 0x06;
-   outb(0, tmport);
-   tmport += 0x02;
-   outb(dev->id[0][i].devsp, tmport++);
-   outb(0, tmport++);
-   outb(satn[6], tmport++);
-   outb(satn[7], tmport++);
+   outb(0x01, wkport + 0x5b);
+   outb(0x08, wkport + 0x41);
+   outb(0x7f, wkport + 0x42);
+   outb(satn[0], wkport + 0x43);
+   outb(satn[1], wkport + 0x44);
+   outb(satn[2], wkport + 0x45);
+   outb(satn[3], wkport + 0x46);
+   outb(satn[4], wkport + 0x47);
+   outb(satn[5], wkport + 0x48);
+   outb(0, wkport + 0x4f);
+   outb(dev->id[0][i].devsp, wkport + 0x51);
+   outb(0, wkport + 0x52);
+   outb(satn[6], wkport + 0x53);
+   outb(satn[7], wkport + 0x54);
j = i;
if ((j & 0x08) != 0) {
j = (j & 0x07) | 0x40;
}
-   outb(j, tmport);
-   tmport += 0x03;
-   outb(satn[8], tmport);
-   tmport += 0x07;
+   outb(j, wkport + 0x55);
+   outb(satn[8], wkport + 0x58);
 
-   while ((inb(tmport) & 0x80) == 0x00)
+   while ((inb(wkport + 0x5f) & 0x80) == 0x00)
cpu_relax();
 
-   tmport -= 0x08;
-   if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
+   if (inb(wkport + 0x57) != 0x11 && inb(wkport + 0x57) != 0x8e)
continue;
 
-   while (inb(tmport) != 0x8e)
+   while (inb(wkport + 0x57) != 0x8e)
cpu_relax();

dev->active_id[0] |= m;
 
-   tmport = wkport + 0x50;
-   outb(0x30, tmport);
-   tmport = wkport + 0x54;
-   outb(0x00, tmport);
+   outb(0x30, wkport + 0x50);
+   outb(0x00, wkport + 0x54);
 
 phase_cmd:
-   tmport = wkport + 0x58;
-   outb(0x08, tmport);
-   tmport += 0x07;
+   outb(0x08, wkport + 0x58);

-   while ((inb(tmport) & 0x80) == 0x00)
+   while ((inb(wkport + 0x5f) & 0x80) == 0x00)
cpu_relax();
 
-   tmport -= 0x08;
-   j = inb(tmport);
+   j = inb(wkport + 0x57);
if (j != 0x16) {
-   tmport = wkport + 0x50;
-   outb(0x41, tmport);
+   outb(0x41, wkport + 0x50);
goto phase_cmd;
}
 sel_ok:
-   tmport = wkport + 0x43;
-   outb(inqd[0], tmport++);
-   outb(inqd[1], tmport++);
-   outb(inqd[2], tmport++);
-   outb(inqd[3], tmport++);
-   outb(inqd[4], tmport++);
-   outb(inqd[5], tmport);
-   tmport += 0x07;
-   outb(0, tmport);
-   tmport += 0x02;
-   outb(dev->id[0][i].devsp, tmport++);
-   outb(0, tmport++);
-   outb(inqd[6], tmport++);
-   outb(inqd[7], tmport++);
-   tmport += 0x03;
-   outb(inqd[8], tmport);
-   tmport += 0x07;
+   outb(inqd[0], wkport + 0x43);
+   outb(inqd[1], wkport + 0x44);
+   outb(inqd[2], wkport + 0x45);
+   outb(inqd[3], wkport + 0x46);
+   outb(inqd[4], wkport + 0x47);
+   outb(inqd[5], wkport + 0x48);
+   outb(0, w

[PATCH 06/52] atp870u: Untangle tmport #4

2015-11-17 Thread Ondrej Zary
Untangle the tmport crap so it becomes obvious what ports are accessed.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |  370 ++--
 1 file changed, 138 insertions(+), 232 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index a23f387..3e3a68b 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -1207,7 +1207,6 @@ G2Q_QUIN: /* k=binID#,   */
 
 static void is870(struct atp_unit *dev, unsigned int wkport)
 {
-   unsigned int tmport;
unsigned char i, j, k, rmb, n;
unsigned short int m;
static unsigned char mbuf[512];
@@ -1218,8 +1217,7 @@ static void is870(struct atp_unit *dev, unsigned int 
wkport)
static unsigned char synw[6] = { 0x80, 1, 3, 1, 0x0c, 0x07 };
static unsigned char wide[6] = { 0x80, 1, 2, 3, 1, 0 };

-   tmport = wkport + 0x3a;
-   outb((unsigned char) (inb(tmport) | 0x10), tmport);
+   outb((unsigned char) (inb(wkport + 0x3a) | 0x10), wkport + 0x3a);
 
for (i = 0; i < 16; i++) {
if ((dev->chip_ver != 4) && (i > 7)) {
@@ -1234,135 +1232,105 @@ static void is870(struct atp_unit *dev, unsigned int 
wkport)
printk(KERN_INFO " ID: %2d  Host Adapter\n", 
dev->host_id[0]);
continue;
}
-   tmport = wkport + 0x1b;
if (dev->chip_ver == 4) {
-   outb(0x01, tmport);
+   outb(0x01, wkport + 0x1b);
} else {
-   outb(0x00, tmport);
-   }
-   tmport = wkport + 1;
-   outb(0x08, tmport++);
-   outb(0x7f, tmport++);
-   outb(satn[0], tmport++);
-   outb(satn[1], tmport++);
-   outb(satn[2], tmport++);
-   outb(satn[3], tmport++);
-   outb(satn[4], tmport++);
-   outb(satn[5], tmport++);
-   tmport += 0x06;
-   outb(0, tmport);
-   tmport += 0x02;
-   outb(dev->id[0][i].devsp, tmport++);
-   outb(0, tmport++);
-   outb(satn[6], tmport++);
-   outb(satn[7], tmport++);
+   outb(0x00, wkport + 0x1b);
+   }
+   outb(0x08, wkport + 1);
+   outb(0x7f, wkport + 2);
+   outb(satn[0], wkport + 3);
+   outb(satn[1], wkport + 4);
+   outb(satn[2], wkport + 5);
+   outb(satn[3], wkport + 6);
+   outb(satn[4], wkport + 7);
+   outb(satn[5], wkport + 8);
+   outb(0, wkport + 0x0f);
+   outb(dev->id[0][i].devsp, wkport + 0x11);
+   outb(0, wkport + 0x12);
+   outb(satn[6], wkport + 0x13);
+   outb(satn[7], wkport + 0x14);
j = i;
if ((j & 0x08) != 0) {
j = (j & 0x07) | 0x40;
}
-   outb(j, tmport);
-   tmport += 0x03;
-   outb(satn[8], tmport);
-   tmport += 0x07;
+   outb(j, wkport + 0x15);
+   outb(satn[8], wkport + 0x18);
 
-   while ((inb(tmport) & 0x80) == 0x00)
+   while ((inb(wkport + 0x1f) & 0x80) == 0x00)
cpu_relax();
 
-   tmport -= 0x08;
-   if (inb(tmport) != 0x11 && inb(tmport) != 0x8e)
+   if (inb(wkport + 0x17) != 0x11 && inb(wkport + 0x17) != 0x8e)
continue;
 
-   while (inb(tmport) != 0x8e)
+   while (inb(wkport + 0x17) != 0x8e)
cpu_relax();
 
dev->active_id[0] |= m;
 
-   tmport = wkport + 0x10;
-   outb(0x30, tmport);
-   tmport = wkport + 0x04;
-   outb(0x00, tmport);
+   outb(0x30, wkport + 0x10);
+   outb(0x00, wkport + 0x04);
 
 phase_cmd:
-   tmport = wkport + 0x18;
-   outb(0x08, tmport);
-   tmport += 0x07;
-   while ((inb(tmport) & 0x80) == 0x00)
+   outb(0x08, wkport + 0x18);
+   while ((inb(wkport + 0x1f) & 0x80) == 0x00)
cpu_relax();
-   tmport -= 0x08;
-   j = inb(tmport);
+   j = inb(wkport + 0x17);
if (j != 0x16) {
-   tmport = wkport + 0x10;
-   outb(0x41, tmport);
+   outb(0x41, wkport + 0x10);
goto phase_cmd;
}
 sel_ok:
-   tmport = wkport + 3;
-   outb(inqd[0], tmport++);
-   outb(inqd[1], tmport++);
-   outb(inqd[2], tmport++);
-   outb(inqd[3], tmport++);
-   outb(inqd[4], tmport++);
-   outb(inqd[5], tmport);
-   tmport +=

[PATCH 08/52] atp870u: Untangle tmport #6

2015-11-17 Thread Ondrej Zary
Untangle the tmport crap so it becomes obvious what ports are accessed.

Signed-off-by: Ondrej Zary 
---
 drivers/scsi/atp870u.c |  136 +---
 1 file changed, 49 insertions(+), 87 deletions(-)

diff --git a/drivers/scsi/atp870u.c b/drivers/scsi/atp870u.c
index 3bf01fc..e398ea5 100644
--- a/drivers/scsi/atp870u.c
+++ b/drivers/scsi/atp870u.c
@@ -2264,7 +2264,7 @@ static int atp870u_probe(struct pci_dev *pdev, const 
struct pci_device_id *ent)
 {
unsigned char k, m, c;
unsigned long flags;
-   unsigned int base_io, tmport, error,n;
+   unsigned int base_io, error,n;
unsigned char host_id;
struct Scsi_Host *shpnt = NULL;
struct atp_unit *atpdev, *p;
@@ -2322,12 +2322,9 @@ static int atp870u_probe(struct pci_dev *pdev, const 
struct pci_device_id *ent)
atpdev->dev_id = ent->device;
atpdev->host_id[0] = host_id;
 
-   tmport = base_io + 0x22;
-   atpdev->scam_on = inb(tmport);
-   tmport += 0x13;
-   atpdev->global_map[0] = inb(tmport);
-   tmport += 0x07;
-   atpdev->ultra_map[0] = inw(tmport);
+   atpdev->scam_on = inb(base_io + 0x22);
+   atpdev->global_map[0] = inb(base_io + 0x35);
+   atpdev->ultra_map[0] = inw(base_io + 0x3c);
 
n = 0x3f09;
 next_fblk_880:
@@ -2402,37 +2399,26 @@ flash_ok_880:
}
 
spin_lock_irqsave(shpnt->host_lock, flags);
-   tmport = base_io + 0x38;
-   k = inb(tmport) & 0x80;
-   outb(k, tmport);
-   tmport += 0x03;
-   outb(0x20, tmport);
+   k = inb(base_io + 0x38) & 0x80;
+   outb(k, base_io + 0x38);
+   outb(0x20, base_io + 0x3b);
mdelay(32);
-   outb(0, tmport);
+   outb(0, base_io + 0x3b);
mdelay(32);
-   tmport = base_io + 0x5b;
-   inb(tmport);
-   tmport -= 0x04;
-   inb(tmport);
-   tmport = base_io + 0x40;
-   outb((host_id | 0x08), tmport);
-   tmport += 0x18;
-   outb(0, tmport);
-   tmport += 0x07;
-   while ((inb(tmport) & 0x80) == 0)
+   inb(base_io + 0x5b);
+   inb(base_io + 0x57);
+   outb((host_id | 0x08), base_io + 0x40);
+   outb(0, base_io + 0x58);
+   while ((inb(base_io + 0x5f) & 0x80) == 0)
mdelay(1);
-   tmport -= 0x08;
-   inb(tmport);
-   tmport = base_io + 0x41;
-   outb(8, tmport++);
-   outb(0x7f, tmport);
-   tmport = base_io + 0x51;
-   outb(0x20, tmport);
+   inb(base_io + 0x57);
+   outb(8, base_io + 0x41);
+   outb(0x7f, base_io + 0x42);
+   outb(0x20, base_io + 0x51);
 
tscam(shpnt);
is880(p, base_io);
-   tmport = base_io + 0x38;
-   outb(0xb0, tmport);
+   outb(0xb0, base_io + 0x38);
shpnt->max_id = 16;
shpnt->this_id = host_id;
shpnt->unique_id = base_io;
@@ -2546,47 +2532,35 @@ flash_ok_885:
inb(base_io + 0x97);
inb(base_io + 0xdb);
inb(base_io + 0xd7);
-   tmport = base_io + 0x80;
k=p->host_id[0];
if (k > 7)
   k = (k & 0x07) | 0x40;
k |= 0x08;
-   outb(k, tmport);
-   tmport += 0x18;
-   outb(0, tmport);
-   tmport += 0x07;
+   outb(k, base_io + 0x80);
+   outb(0, base_io + 0x98);
 
-   while ((inb(tmport) & 0x80) == 0)
+   while ((inb(base_io + 0x9f) & 0x80) == 0)
cpu_relax();

-   tmport -= 0x08;
-   inb(tmport);
-   tmport = base_io + 0x81;
-   outb(8, tmport++);
-   outb(0x7f, tmport);
-   tmport = base_io + 0x91;
-   outb(0x20, tmport);
+   inb(base_io + 0x97);
+   outb(8, base_io + 0x81);
+   outb(0x7f, base_io + 0x82);
+   outb(0x20, base_io + 0x91);
 
-   tmport = base_io + 0xc0;
k=p->host_id[1];
if (k > 7)
   k = (k & 0x07) | 0x40;
k |= 0x08;
-   outb(k, tmport);
-   tmport += 0x18;
-   outb(0, tmport);
-   tmport += 0x07;
+   outb(k, base_io + 0xc0);
+   outb(0, base_io + 0xd8);
 
-   while ((inb(tmport) & 0x80) == 0)
+   while ((inb(base_io + 0xdf) & 0x80) == 0)
cpu_relax();
 
-   tmpo

Re: [PATCH 5/9] srpt: use the new CQ API

2015-11-17 Thread Bart Van Assche

On 11/13/2015 05:46 AM, Christoph Hellwig wrote:
> [ ... ]

The previous patch and this patch look like great work to me. However, 
this patch not only reworks the SRP target driver but also prevents 
users to move the SRP completion thread to another CPU core than the CPU 
core that processes the completion interrupts (with the help of e.g. the 
taskset command). Hence my request to make that CPU core configurable in 
the second patch of this patch series.


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


Re: [PATCH 2/9] IB: add a proper completion queue abstraction

2015-11-17 Thread Bart Van Assche

On 11/13/2015 05:46 AM, Christoph Hellwig wrote:

+ * context and does not ask from completion interrupts from the HCA.

   
Should this perhaps be changed into "for" ?


+ */
+void ib_process_cq_direct(struct ib_cq *cq)
+{
+   WARN_ON_ONCE(cq->poll_ctx != IB_POLL_DIRECT);
+
+   __ib_process_cq(cq, INT_MAX);
+}
+EXPORT_SYMBOL(ib_process_cq_direct);


My proposal is to drop this function and to export __ib_process_cq() 
instead (with or without renaming). That will allow callers of this 
function to compare the poll budget with the number of completions that 
have been processed and use that information to decide whether or not to 
call this function again.



+static void ib_cq_poll_work(struct work_struct *work)
+{
+   struct ib_cq *cq = container_of(work, struct ib_cq, work);
+   int completed;
+
+   completed = __ib_process_cq(cq, IB_POLL_BUDGET_WORKQUEUE);
+   if (completed >= IB_POLL_BUDGET_WORKQUEUE ||
+   ib_req_notify_cq(cq, IB_POLL_FLAGS) > 0)
+   queue_work(ib_comp_wq, &cq->work);
+}
+
+static void ib_cq_completion_workqueue(struct ib_cq *cq, void *private)
+{
+   queue_work(ib_comp_wq, &cq->work);
+}


The above code will cause all polling to occur on the context of the CPU 
that received the completion interrupt. This approach is not powerful 
enough. For certain workloads throughput is higher if work completions 
are processed by another CPU core on the same CPU socket. Has it been 
considered to make the CPU core on which work completions are processed 
configurable ?



diff --git a/drivers/infiniband/ulp/srp/ib_srp.c 
b/drivers/infiniband/ulp/srp/ib_srp.c
index 62b6cba..3027824 100644
--- a/drivers/infiniband/ulp/srp/ib_srp.c
+++ b/drivers/infiniband/ulp/srp/ib_srp.c
@@ -457,10 +457,11 @@ static struct srp_fr_pool *srp_alloc_fr_pool(struct 
srp_target_port *target)
  static void srp_destroy_qp(struct srp_rdma_ch *ch)
  {
static struct ib_qp_attr attr = { .qp_state = IB_QPS_ERR };
-   static struct ib_recv_wr wr = { .wr_id = SRP_LAST_WR_ID };
+   static struct ib_recv_wr wr = { 0 };
struct ib_recv_wr *bad_wr;
int ret;


Since the 'wr' structure is static I don't think it needs to be 
zero-initialized explicitly.


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


Re: [PATCH 1/9] move blk_iopoll to limit and make it generally available

2015-11-17 Thread Bart Van Assche

On 11/17/2015 09:16 AM, Bart Van Assche wrote:

On 11/13/2015 11:02 PM, Christoph Hellwig wrote:

On Fri, Nov 13, 2015 at 11:19:24AM -0800, Bart Van Assche wrote:

On 11/13/2015 05:46 AM, Christoph Hellwig wrote:

The new name is irq_poll as iopoll is already taken.  Better suggestions
welcome.


Would it be possible to provide more background information about this ?
Which other kernel subsystem is using the name iopoll ?


Take a look at include/linux/iopoll.h  - I can't reaplly make much sense
of it to be honest, but it's used in a quite a few places.


How about renaming blk_iopoll into blk_poll ? That way the name still
refers to the block layer. And although the current implementation
performs polling from IRQ context future implementations maybe will
allow polling from thread context.


(replying to my own e-mail)

Please ignore the previous comment - I just noticed that this mechanism 
is not limited to block devices.


Bart.

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


Re: [PATCH 1/9] move blk_iopoll to limit and make it generally available

2015-11-17 Thread Bart Van Assche

On 11/13/2015 11:02 PM, Christoph Hellwig wrote:

On Fri, Nov 13, 2015 at 11:19:24AM -0800, Bart Van Assche wrote:

On 11/13/2015 05:46 AM, Christoph Hellwig wrote:

The new name is irq_poll as iopoll is already taken.  Better suggestions
welcome.


Would it be possible to provide more background information about this ?
Which other kernel subsystem is using the name iopoll ?


Take a look at include/linux/iopoll.h  - I can't reaplly make much sense
of it to be honest, but it's used in a quite a few places.


How about renaming blk_iopoll into blk_poll ? That way the name still 
refers to the block layer. And although the current implementation 
performs polling from IRQ context future implementations maybe will 
allow polling from thread context.


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


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

2015-11-17 Thread Bart Van Assche

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

This is taken from srp, and srp drains using a recv wr due to a race
causing a use-after-free condition in srp which re-posts a recv buffer
in the recv completion handler.


Hello Sagi,

Would it be possible to clarify this ? Does this refer to an existing 
race or a race that would only occur if the code would be modified ?


Thanks,

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


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

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

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

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


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

2015-11-17 Thread Or Gerlitz
On Mon, Nov 16, 2015 at 7:30 PM, Michael Christie  wrote:
>> On Nov 15, 2015, at 4:10 AM, Or Gerlitz  wrote:

>> After the locking change, adding a task to any of the connection
>> mgmtqueue, cmdqueue, or requeue lists is under the session forward lock.
>>
>> Removing tasks from any of these lists in iscsi_data_xmit is under
>> the session forward lock and **before** calling down to the transport
>> to handle the task.
>>
>> The iscsi_complete_task helper was added by Mike's commit
>> 3bbaaad95fd38ded "[SCSI] libiscsi: handle cleanup task races"
>> and is indeed typically called under the backward lock && has this section
>>
>> +   if (!list_empty(&task->running))
>> +   list_del_init(&task->running);
>> which per my reading of the code never comes into play, can you comment?

>> The bug occurs when a target completes a command while we are still
>> processing it. If we are doing a WRITE and the iscsi_task
>> is on the cmdqueue because we are handling a R2T. The target shouldn't
>> send a Check Condition at this time, but some do. If that happens, then
>> iscsi_queuecommand could be adding a new task to the cmdqueue, while the
>> recv path is handling the CC for the task with the outsanding R2T.  The
>> recv path iscsi_complete_task call sees that task it on the cmdqueue and
>> deletes it from the list at the same time iscsi_queuecommand is adding a new
>> task.

So we're now a bit beyond trivial bug and

>> This should not happen per the iscsi spec. There is some wording about
>> waiting to finish the sequence in progress, but targets goof this up.

we have target/s that violate the spec, this is life, but can explain
why it took us 18m to get
bug report. Can you provide few point pointers into the relevant code
pieces that one need
to look at to realize what's going on there? was this code added
before or after the patch?

Or.
--
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 v5 08/32] scsi: hisi_sas: add hisi_sas_remove

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

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

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

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


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

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

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

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


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

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

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

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

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


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

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

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

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

--
To unsubscribe from this list: send the line "unsubscribe 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 v5 11/32] scsi: hisi_sas: add phy SAS ADDR initialization

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

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

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

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


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

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

The SAS domain transport ops are empty at this point.

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

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

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

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

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

diff --git a/drivers/scsi/hisi_sas/Makefile b/drivers/scsi/hisi_sas/Makefile
index d86b05e..3e70eae 100644
--- a/drivers/scsi/hisi_sas/Makefile
+++ b/drivers/scsi/hisi_sas/Makefile
@@ -1 +1,2 @@
 obj-$(CONFIG_SCSI_HISI_SAS)+= hisi_sas_main.o
+obj-$(CONFIG_SCSI_HISI_SAS)+= hisi_sas_v1_hw.o
diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index 3749c46..72533ca 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -269,5 +269,8 @@ union hisi_sas_command_table {
struct hisi_sas_command_table_smp smp;
struct hisi_sas_command_table_stp stp;
 };
+extern int hisi_sas_probe(struct platform_device *pdev,
+ const struct hisi_sas_hw *ops);
+extern int hisi_sas_remove(struct platform_device *pdev);
 
 #endif
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
new file mode 100644
index 000..e9aebce
--- /dev/null
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2015 Linaro Ltd.
+ * Copyright (c) 2015 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include "hisi_sas.h"
+#define DRV_NAME "hisi_sas_v1_hw"
+
+
+struct hisi_sas_complete_v1_hdr {
+   __le32 data;
+};
+static const struct hisi_sas_hw hisi_sas_v1_hw = {
+   .complete_hdr_size = sizeof(struct hisi_sas_complete_v1_hdr),
+};
+
+static int hisi_sas_v1_probe(struct platform_device *pdev)
+{
+   return hisi_sas_probe(pdev, &hisi_sas_v1_hw);
+}
+
+static int hisi_sas_v1_remove(struct platform_device *pdev)
+{
+   return hisi_sas_remove(pdev);
+}
+
+static const struct of_device_id sas_v1_of_match[] = {
+   { .compatible = "hisilicon,hip05-sas-v1",},
+   {},
+};
+MODULE_DEVICE_TABLE(of, sas_v1_of_match);
+
+static struct platform_driver hisi_sas_v1_driver = {
+   .probe = hisi_sas_v1_probe,
+   .remove = hisi_sas_v1_remove,
+   .driver = {
+   .name = DRV_NAME,
+   .of_match_table = sas_v1_of_match,
+   },
+};
+
+module_platform_driver(hisi_sas_v1_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("John Garry ");
+MODULE_DESCRIPTION("HISILICON SAS controller v1 hw driver");
+MODULE_ALIAS("platform:" DRV_NAME);
-- 
1.9.1

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


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

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

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

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

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

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

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

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

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

[PATCH v5 00/32] HiSilicon SAS driver

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

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

The driver uses libsas framework within the SCSI framework.

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

A dependency exists on [1].

Differences to v4:
- fix kbuild issue with patch 0003

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

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

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

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

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

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

Reviewed-by: Arnd Bergmann 
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 v5 16/32] scsi: hisi_sas: add timer and spinlock init

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

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

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


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

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

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

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

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


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

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

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

The HBA is a platform device.

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

diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 5f692ae..37dce23 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -473,6 +473,7 @@ config SCSI_AACRAID
 source "drivers/scsi/aic7xxx/Kconfig.aic7xxx"
 source "drivers/scsi/aic7xxx/Kconfig.aic79xx"
 source "drivers/scsi/aic94xx/Kconfig"
+source "drivers/scsi/hisi_sas/Kconfig"
 source "drivers/scsi/mvsas/Kconfig"
 
 config SCSI_MVUMI
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index c14bca4..862ab4e 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -157,6 +157,7 @@ obj-$(CONFIG_CHR_DEV_SCH)   += ch.o
 obj-$(CONFIG_SCSI_ENCLOSURE)   += ses.o
 
 obj-$(CONFIG_SCSI_OSD_INITIATOR) += osd/
+obj-$(CONFIG_SCSI_HISI_SAS) += hisi_sas/
 
 # This goes last, so that "real" scsi devices probe earlier
 obj-$(CONFIG_SCSI_DEBUG)   += scsi_debug.o
diff --git a/drivers/scsi/hisi_sas/Kconfig b/drivers/scsi/hisi_sas/Kconfig
new file mode 100644
index 000..37a0c71
--- /dev/null
+++ b/drivers/scsi/hisi_sas/Kconfig
@@ -0,0 +1,6 @@
+config SCSI_HISI_SAS
+   tristate "HiSilicon SAS"
+   select SCSI_SAS_LIBSAS
+   select BLK_DEV_INTEGRITY
+   help
+   This driver supports HiSilicon's SAS HBA
diff --git a/drivers/scsi/hisi_sas/Makefile b/drivers/scsi/hisi_sas/Makefile
new file mode 100644
index 000..d86b05e
--- /dev/null
+++ b/drivers/scsi/hisi_sas/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_SCSI_HISI_SAS)+= hisi_sas_main.o
diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
new file mode 100644
index 000..a5cec22
--- /dev/null
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2015 Linaro Ltd.
+ * Copyright (c) 2015 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#ifndef _HISI_SAS_H_
+#define _HISI_SAS_H_
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define DRV_VERSION "v1.0"
+
+#endif
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
new file mode 100644
index 000..7201363
--- /dev/null
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2015 Linaro Ltd.
+ * Copyright (c) 2015 Hisilicon Limited.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#include "hisi_sas.h"
+#define DRV_NAME "hisi_sas"
+
+static struct scsi_transport_template *hisi_sas_stt;
+
+static struct sas_domain_function_template hisi_sas_transport_ops = {
+};
+
+static __init int hisi_sas_init(void)
+{
+   pr_info("hisi_sas: driver version %s\n", DRV_VERSION);
+
+   hisi_sas_stt = sas_domain_attach_transport(&hisi_sas_transport_ops);
+   if (!hisi_sas_stt)
+   return -ENOMEM;
+
+   return 0;
+}
+
+static __exit void hisi_sas_exit(void)
+{
+   sas_release_transport(hisi_sas_stt);
+}
+
+module_init(hisi_sas_init);
+module_exit(hisi_sas_exit);
+
+MODULE_VERSION(DRV_VERSION);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("John Garry ");
+MODULE_DESCRIPTION("HISILICON SAS controller driver");
+MODULE_ALIAS("platform:" DRV_NAME);
-- 
1.9.1

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


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

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

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

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


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

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

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

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


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

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

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

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

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

2015-11-17 Thread John Garry
Include initialisation.

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h
index e5ee3c9..f34f73b 100644
--- a/drivers/scsi/hisi_sas/hisi_sas.h
+++ b/drivers/scsi/hisi_sas/hisi_sas.h
@@ -36,6 +36,7 @@
(((sizeof(union hisi_sas_command_table)+3)/4)*4)
 
 #define HISI_SAS_MAX_SSP_RESP_SZ (sizeof(struct ssp_frame_hdr) + 1024)
+#define HISI_SAS_MAX_SMP_RESP_SZ 1028
 
 #define HISI_SAS_NAME_LEN 32
 
@@ -132,6 +133,8 @@ struct hisi_sas_hw {
int (*prep_ssp)(struct hisi_hba *hisi_hba,
struct hisi_sas_slot *slot, int is_tmf,
struct hisi_sas_tmf_task *tmf);
+   int (*prep_smp)(struct hisi_hba *hisi_hba,
+   struct hisi_sas_slot *slot);
int (*slot_complete)(struct hisi_hba *hisi_hba,
 struct hisi_sas_slot *slot, int abort);
void (*free_device)(struct hisi_hba *hisi_hba,
diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c 
b/drivers/scsi/hisi_sas/hisi_sas_main.c
index 1797851..406ffa0 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_main.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_main.c
@@ -98,6 +98,12 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, 
struct sas_task *task,
 }
 EXPORT_SYMBOL_GPL(hisi_sas_slot_task_free);
 
+static int hisi_sas_task_prep_smp(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot)
+{
+   return hisi_hba->hw->prep_smp(hisi_hba, slot);
+}
+
 static int hisi_sas_task_prep_ssp(struct hisi_hba *hisi_hba,
  struct hisi_sas_slot *slot, int is_tmf,
  struct hisi_sas_tmf_task *tmf)
@@ -215,6 +221,9 @@ static int hisi_sas_task_prep(struct sas_task *task, struct 
hisi_hba *hisi_hba,
memset(slot->cmd_hdr, 0, sizeof(struct hisi_sas_cmd_hdr));
 
switch (task->task_proto) {
+   case SAS_PROTOCOL_SMP:
+   rc = hisi_sas_task_prep_smp(hisi_hba, slot);
+   break;
case SAS_PROTOCOL_SSP:
rc = hisi_sas_task_prep_ssp(hisi_hba, slot, is_tmf, tmf);
break;
diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c 
b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
index ad50aed..64b17a1 100644
--- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
+++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c
@@ -903,6 +903,74 @@ static int prep_prd_sge_v1_hw(struct hisi_hba *hisi_hba,
return 0;
 }
 
+static int prep_smp_v1_hw(struct hisi_hba *hisi_hba,
+ struct hisi_sas_slot *slot)
+{
+   struct sas_task *task = slot->task;
+   struct hisi_sas_cmd_hdr *hdr = slot->cmd_hdr;
+   struct domain_device *device = task->dev;
+   struct device *dev = &hisi_hba->pdev->dev;
+   struct hisi_sas_port *port = slot->port;
+   struct scatterlist *sg_req, *sg_resp;
+   struct hisi_sas_device *sas_dev = device->lldd_dev;
+   dma_addr_t req_dma_addr;
+   unsigned int req_len, resp_len;
+   int elem, rc;
+
+   /*
+   * DMA-map SMP request, response buffers
+   */
+   /* req */
+   sg_req = &task->smp_task.smp_req;
+   elem = dma_map_sg(dev, sg_req, 1, DMA_TO_DEVICE);
+   if (!elem)
+   return -ENOMEM;
+   req_len = sg_dma_len(sg_req);
+   req_dma_addr = sg_dma_address(sg_req);
+
+   /* resp */
+   sg_resp = &task->smp_task.smp_resp;
+   elem = dma_map_sg(dev, sg_resp, 1, DMA_FROM_DEVICE);
+   if (!elem) {
+   rc = -ENOMEM;
+   goto err_out_req;
+   }
+   resp_len = sg_dma_len(sg_resp);
+   if ((req_len & 0x3) || (resp_len & 0x3)) {
+   rc = -EINVAL;
+   goto err_out_resp;
+   }
+
+   /* create header */
+   /* dw0 */
+   hdr->dw0 = cpu_to_le32((port->id << CMD_HDR_PORT_OFF) |
+  (1 << CMD_HDR_PRIORITY_OFF) | /* high pri */
+  (1 << CMD_HDR_MODE_OFF) | /* ini mode */
+  (2 << CMD_HDR_CMD_OFF)); /* smp */
+
+   /* map itct entry */
+   hdr->dw1 = cpu_to_le32(sas_dev->device_id << CMD_HDR_DEVICE_ID_OFF);
+
+   /* dw2 */
+   hdr->dw2 = cpu_to_le32req_len-4)/4) << CMD_HDR_CFL_OFF) |
+  (HISI_SAS_MAX_SMP_RESP_SZ/4 <<
+  CMD_HDR_MRFL_OFF));
+
+   hdr->transfer_tags = cpu_to_le32(slot->idx << CMD_HDR_IPTT_OFF);
+
+   hdr->cmd_table_addr = cpu_to_le64(req_dma_addr);
+   hdr->sts_buffer_addr = cpu_to_le64(slot->status_buffer_dma);
+
+   return 0;
+
+err_out_resp:
+   dma_unmap_sg(dev, &slot->task->smp_task.smp_resp, 1,
+DMA_F

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

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

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

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

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

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

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

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

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


  1   2   >