[PATCH] virtio_scsi: fix memory leak on full queue condition.

2012-11-08 Thread Eric Northup
virtscsi_queuecommand was leaking memory when the virtio queue was full.

Tested: Guest operates correctly even with very small queue sizes, validated
we're not leaking kmalloc-192 sized allocations anymore.

Signed-off-by: Eric Northup 
---
 drivers/scsi/virtio_scsi.c |2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index 595af1a..dd8dc27 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -469,6 +469,8 @@ static int virtscsi_queuecommand(struct Scsi_Host *sh, 
struct scsi_cmnd *sc)
  sizeof cmd->req.cmd, sizeof cmd->resp.cmd,
  GFP_ATOMIC) >= 0)
ret = 0;
+   else
+   mempool_free(cmd, virtscsi_cmd_pool);
 
 out:
return ret;
-- 
1.7.7.3

--
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: scsi target, likely GPL violation

2012-11-08 Thread Andy Grover
On 11/07/2012 05:02 PM, Jon Mason wrote:
> On Wed, Nov 7, 2012 at 9:50 AM, Andy Grover  wrote:
>> Your company appears to be shipping kernel features in RTS OS that are
>> not made available under the GPL, specifically support for the
>> EXTENDED_COPY and COMPARE_AND_WRITE SCSI commands, in order to claim
>> full Vmware vSphere 5 VAAI support.
>>
>> http://www.risingtidesystems.com/storage.html
>> http://www.linux-iscsi.org/wiki/VAAI
>>
>> Private emails to you and RTS CEO Marc Fleischmann have not elicited a
>> useful response.
>>
>> You are subsystem maintainer for the in-kernel SCSI target support
>> (drivers/target/*), and your company appears to be violating the GPL.
> 
> The peanut gallery needs more information, as this is quite an
> incendiary claim to be making on a Linux kernel forum.  How are they
> violating the GPL?  I'm not a lawyer, nor do I play one on TV, but if
> I understand the GPL correctly, RTS only needs to provide the relevant
> source to their customers upon request.  Are there customers (perhaps
> Redhat) that they have not provided this to?  If so, then they need to
> be publicly shamed (gpl-violations.org would be a good place to go as
> well).  If not, then they are within their rights to behave the way
> they are currently behaving.
> 
> Again, we need more info before we start flinging the tomatoes at them.

Look at the marketing material on their website. They demonstrate how
RTS OS fully implements vSphere 5 VAAI features. We know to a very high
certainty that this must have been implemented with kernel code, so
therefore this must be a GPL violation, since these changes have not
been made public.

-- Andy
--
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: scsi target, likely GPL violation

2012-11-08 Thread Andy Grover
On 11/07/2012 05:57 PM, Chris Friesen wrote:
> On 11/07/2012 07:02 PM, Jon Mason wrote:
>> I'm not a lawyer, nor do I play one on TV, but if
>> I understand the GPL correctly, RTS only needs to provide the relevant
>> source to their customers upon request.
> 
> Not quite.
> 
> Assuming the GPL applies, and that they have modified the code, then
> they must either:
> 
> 1) include the source with the distributed binary
> 
> or
> 
> 2) include with the binary an offer to provide the source to *any* third
> party

So you'd have me find one of their customers, and then get the source
via your #2 method...

...and then turn around and submit it to Nick since he's the target
subsystem maintainer? Nick is probably the one who wrote it!

I'm happy to do that, but we should recognize something is seriously
skewed when the person nominally in charge of the in-kernel code also
has a vested interest in *not* seeing new features added, since it then
competes better with his company's offering.

RTS is trying to use an "open core" business model. This works fine for
BSD-licensed code or code originally authored entirely by you, but their
code (all of it even the new stuff) is a derivative work of the Linux
kernel source code, and the GPL says they need to contribute it back.

Regards -- Andy
--
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: scsi target, likely GPL violation

2012-11-08 Thread Nicholas A. Bellinger
On Thu, 2012-11-08 at 08:57 -0800, Andy Grover wrote:
> On 11/07/2012 05:57 PM, Chris Friesen wrote:
> > On 11/07/2012 07:02 PM, Jon Mason wrote:
> >> I'm not a lawyer, nor do I play one on TV, but if
> >> I understand the GPL correctly, RTS only needs to provide the relevant
> >> source to their customers upon request.
> > 
> > Not quite.
> > 
> > Assuming the GPL applies, and that they have modified the code, then
> > they must either:
> > 
> > 1) include the source with the distributed binary
> > 
> > or
> > 
> > 2) include with the binary an offer to provide the source to *any* third
> > party
> 
> So you'd have me find one of their customers, and then get the source
> via your #2 method...
> 
> ...and then turn around and submit it to Nick since he's the target
> subsystem maintainer? Nick is probably the one who wrote it!
> 
> I'm happy to do that, but we should recognize something is seriously
> skewed when the person nominally in charge of the in-kernel code also
> has a vested interest in *not* seeing new features added, since it then
> competes better with his company's offering.
> 
> RTS is trying to use an "open core" business model. This works fine for
> BSD-licensed code or code originally authored entirely by you, but their
> code (all of it even the new stuff) is a derivative work of the Linux
> kernel source code, and the GPL says they need to contribute it back.
> 

Andy,

Accusing us of violating GPL is a serious legal claim.  

In fact, we are not violating GPL.  In short, this is because we wrote
the code you are referring to (the SCSI target core in our commercial
RTS OS product), we have exclusive copyright ownership of it, and this
code contains no GPL code from the community.  GPL obligations only
apply downstream to licensees, and not to the author of the code.  Those
who use the code under GPL are subject to its conditions; we are not.

As you know, we contributed the Linux SCSI target core, including the
relevant interfaces, to the Linux kernel.  To be clear, we wrote that
code entirely ourselves, so we have the right to use it as we please.
The version we use in RTS OS is a different, proprietary version, which
we also wrote ourselves.  However, the fact that we contributed a
version of the code to the Linux kernel does not require us to provide
our proprietary version to anyone.

If you want to understand better how dual licensing works, perhaps we
can talk off list.  But we don’t really have a responsibility to respond
to untrue accusations, nor to explain GPL, nor discuss our proprietary
code.

We’re very disappointed that Red Hat would not be more professional in
its communications about licensing compliance matters, particularly to a
company like ours that has been a major contributor to Linux and
therefore also to Red Hat’s own products.  So, while I invite you to
talk about this with us directly, I also advise you – respectfully – not
to make public accusations that are not true.  That is harmful to our
reputation – and candidly, it doesn’t reflect well on you or your
company.

--nab

--
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] target/iblock: Fix double iblock_complete_cmd callback bug

2012-11-08 Thread Nicholas A. Bellinger
From: Nicholas Bellinger 

This patch fixes a double completion bug where ibr->pending = 2 usage
plus the extra callback to iblock_complete_cmd() invoked after bio
submission in iblock_execute_rw() can interfere with the normal
bio->bi_done() -> iblock_bio_done() -> iblock_complete_cmd() completion
path, causing a double target_complete_cmd() call to occur.

This bug was introduced during v3.4-rc2 code with:

commit 5787cacd0bd5ee016ad807b244550d34fe2beebe
Author: Christoph Hellwig 
Date:   Tue Apr 24 00:25:06 2012 -0400

target: remove struct se_task

Also drop the bio_cnt >= IBLOCK_MAX_BIO_PER_TASK rolling call to
iblock_submit_bios() to avoid the exception case where outstanding
bios completing via iblock_bio_done() are not accounted for when
returning returning non zero from iblock_execute_rw().

This bug was originally reported by Kelsey when a single se_cmd
descriptor required more than one bio to complete.

Reported-by: Kelsey Prantis 
Cc: Christoph Hellwig 
Cc: sta...@vger.kernel.org
Signed-off-by: Nicholas Bellinger 
---
 drivers/target/target_core_iblock.c |   11 +--
 1 files changed, 1 insertions(+), 10 deletions(-)

diff --git a/drivers/target/target_core_iblock.c 
b/drivers/target/target_core_iblock.c
index 57d7674..d066932 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -47,7 +47,6 @@
 
 #include "target_core_iblock.h"
 
-#define IBLOCK_MAX_BIO_PER_TASK 32 /* max # of bios to submit at a 
time */
 #define IBLOCK_BIO_POOL_SIZE   128
 
 static struct se_subsystem_api iblock_template;
@@ -602,7 +601,6 @@ static int iblock_execute_rw(struct se_cmd *cmd)
struct scatterlist *sg;
u32 sg_num = sgl_nents;
sector_t block_lba;
-   unsigned bio_cnt;
int rw;
int i;
 
@@ -658,8 +656,7 @@ static int iblock_execute_rw(struct se_cmd *cmd)
bio_list_init(&list);
bio_list_add(&list, bio);
 
-   atomic_set(&ibr->pending, 2);
-   bio_cnt = 1;
+   atomic_set(&ibr->pending, 1);
 
for_each_sg(sgl, sg, sgl_nents, i) {
/*
@@ -669,10 +666,6 @@ static int iblock_execute_rw(struct se_cmd *cmd)
 */
while (bio_add_page(bio, sg_page(sg), sg->length, sg->offset)
!= sg->length) {
-   if (bio_cnt >= IBLOCK_MAX_BIO_PER_TASK) {
-   iblock_submit_bios(&list, rw);
-   bio_cnt = 0;
-   }
 
bio = iblock_get_bio(cmd, block_lba, sg_num);
if (!bio)
@@ -680,7 +673,6 @@ static int iblock_execute_rw(struct se_cmd *cmd)
 
atomic_inc(&ibr->pending);
bio_list_add(&list, bio);
-   bio_cnt++;
}
 
/* Always in 512 byte units for Linux/Block */
@@ -689,7 +681,6 @@ static int iblock_execute_rw(struct se_cmd *cmd)
}
 
iblock_submit_bios(&list, rw);
-   iblock_complete_cmd(cmd);
return 0;
 
 fail_put_bios:
-- 
1.7.2.5

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


[PATCH 0/3] target/iblock: Add WRITE_SAME w/ UNMAP=0 emulation

2012-11-08 Thread Nicholas A. Bellinger
From: Nicholas Bellinger 

Hi folks,

This series for-3.8 adds support for proper WRITE_SAME w/ UNMAP=0 emulation
for IBLOCK device backends to follow MKP's WRITE_SAME patches that have
been merged for v3.7-rc1.

Currently it uses a bio_add_page() call for each sector in order to allow
scatterlist w/ page offsets to work, as blkdev_issue_write_same() currently
assumes underlying hw support + zero page offset.

So far it has been tested on target-pending/for-next code with iscsi-target
and tcm_loop fabric ports.

Please review,

--nab

Nicholas Bellinger (3):
  target/sbc: Make WRITE_SAME check differentiate between UNMAP=[1,0]
  target: Add max_write_same_len device attribute
  target/iblock: Add WRITE_SAME w/ UNMAP=0 emulation support

 drivers/target/target_core_configfs.c |4 ++
 drivers/target/target_core_device.c   |   11 +
 drivers/target/target_core_iblock.c   |   78 +---
 drivers/target/target_core_internal.h |1 +
 drivers/target/target_core_sbc.c  |   19 +++-
 drivers/target/target_core_spc.c  |8 +++-
 include/target/target_core_base.h |4 ++
 7 files changed, 104 insertions(+), 21 deletions(-)

-- 
1.7.2.5

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


[PATCH 1/3] target/sbc: Make WRITE_SAME check differentiate between UNMAP=[1,0]

2012-11-08 Thread Nicholas A. Bellinger
From: Nicholas Bellinger 

This patch updates sbc_write_same_supported() to set SCF_WRITE_SAME_DISCARD
to signal when WRITE_SAME w/ UNMAP=1 is requested.

Also, allow WRITE_SAME w/ UNMAP=0 to be passed to backend driver logic.

Cc: Christoph Hellwig 
Cc: Martin K. Petersen 
Signed-off-by: Nicholas Bellinger 
---
 drivers/target/target_core_sbc.c  |   19 +++
 include/target/target_core_base.h |1 +
 2 files changed, 8 insertions(+), 12 deletions(-)

diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c
index b802421..ee9fa52 100644
--- a/drivers/target/target_core_sbc.c
+++ b/drivers/target/target_core_sbc.c
@@ -235,7 +235,7 @@ static inline unsigned long long 
transport_lba_64_ext(unsigned char *cdb)
return ((unsigned long long)__v2) | (unsigned long long)__v1 << 32;
 }
 
-static int sbc_write_same_supported(struct se_device *dev,
+static int sbc_write_same_supported(struct se_cmd *cmd,
unsigned char *flags)
 {
if ((flags[0] & 0x04) || (flags[0] & 0x02)) {
@@ -244,16 +244,11 @@ static int sbc_write_same_supported(struct se_device *dev,
" Emulation\n");
return -ENOSYS;
}
-
/*
-* Currently for the emulated case we only accept
-* tpws with the UNMAP=1 bit set.
+* UNMAP=1 bit translantes to blkdev_issue_discard() execution
 */
-   if (!(flags[0] & 0x08)) {
-   pr_err("WRITE_SAME w/o UNMAP bit not"
-   " supported for Block Discard Emulation\n");
-   return -ENOSYS;
-   }
+   if (flags[0] & 0x08)
+   cmd->se_cmd_flags |= SCF_WRITE_SAME_DISCARD;
 
return 0;
 }
@@ -431,7 +426,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
size = sbc_get_size(cmd, 1);
cmd->t_task_lba = get_unaligned_be64(&cdb[12]);
 
-   if (sbc_write_same_supported(dev, &cdb[10]) < 0)
+   if (sbc_write_same_supported(cmd, &cdb[10]) < 0)
return TCM_UNSUPPORTED_SCSI_OPCODE;
cmd->execute_cmd = ops->execute_write_same;
break;
@@ -507,7 +502,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
size = sbc_get_size(cmd, 1);
cmd->t_task_lba = get_unaligned_be64(&cdb[2]);
 
-   if (sbc_write_same_supported(dev, &cdb[1]) < 0)
+   if (sbc_write_same_supported(cmd, &cdb[1]) < 0)
return TCM_UNSUPPORTED_SCSI_OPCODE;
cmd->execute_cmd = ops->execute_write_same;
break;
@@ -528,7 +523,7 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops)
 * Follow sbcr26 with WRITE_SAME (10) and check for the 
existence
 * of byte 1 bit 3 UNMAP instead of original reserved field
 */
-   if (sbc_write_same_supported(dev, &cdb[1]) < 0)
+   if (sbc_write_same_supported(cmd, &cdb[1]) < 0)
return TCM_UNSUPPORTED_SCSI_OPCODE;
cmd->execute_cmd = ops->execute_write_same;
break;
diff --git a/include/target/target_core_base.h 
b/include/target/target_core_base.h
index 5350f6e..2787b85 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -154,6 +154,7 @@ enum se_cmd_flags_table {
SCF_ALUA_NON_OPTIMIZED  = 0x8000,
SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC = 0x0002,
SCF_ACK_KREF= 0x0004,
+   SCF_WRITE_SAME_DISCARD  = 0x0008,
 };
 
 /* struct se_dev_entry->lun_flags and struct se_lun->lun_access */
-- 
1.7.2.5

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


[PATCH 3/3] target/iblock: Add WRITE_SAME w/ UNMAP=0 emulation support

2012-11-08 Thread Nicholas A. Bellinger
From: Nicholas Bellinger 

This patch adds support for emulation of WRITE_SAME w/ UNMAP=0 within
iblock_execute_write_same() backend code.

The emulation uses a bio_add_page() call for each sector, and by default
enforces a limit of max_write_same_len=0x (65536) sectors following
what scsi_debug reports per default for MAXIMUM WRITE SAME LENGTH.

It also sets max_write_same_len to the operational default at setup ->
iblock_configure_device() time.

Cc: Christoph Hellwig 
Cc: Martin K. Petersen 
Signed-off-by: Nicholas Bellinger 
---
 drivers/target/target_core_iblock.c |   78 +++
 1 files changed, 70 insertions(+), 8 deletions(-)

diff --git a/drivers/target/target_core_iblock.c 
b/drivers/target/target_core_iblock.c
index 53f4501..33a5248 100644
--- a/drivers/target/target_core_iblock.c
+++ b/drivers/target/target_core_iblock.c
@@ -151,6 +151,10 @@ static int iblock_configure_device(struct se_device *dev)
pr_debug("IBLOCK: BLOCK Discard support available,"
" disabled by default\n");
}
+   /*
+* Enable WRITE_SAME emulation for IBLOCK, use scsi_debug.c default
+*/
+   dev->dev_attrib.max_write_same_len = 0x;
 
if (blk_queue_nonrot(q))
dev->dev_attrib.is_nonrot = 1;
@@ -375,22 +379,80 @@ err:
return ret;
 }
 
+static struct bio *iblock_get_bio(struct se_cmd *, sector_t, u32);
+static void iblock_submit_bios(struct bio_list *, int);
+static void iblock_complete_cmd(struct se_cmd *);
+
 static sense_reason_t
 iblock_execute_write_same(struct se_cmd *cmd)
 {
struct iblock_dev *ib_dev = IBLOCK_DEV(cmd->se_dev);
-   int ret;
+   struct iblock_req *ibr;
+   struct scatterlist *sg;
+   struct bio *bio;
+   struct bio_list list;
+   sector_t block_lba = cmd->t_task_lba;
+   unsigned int sectors = spc_get_write_same_sectors(cmd);
+   int rc;
+
+   if (cmd->se_cmd_flags & SCF_WRITE_SAME_DISCARD) {
+   rc = blkdev_issue_discard(ib_dev->ibd_bd, cmd->t_task_lba,
+   spc_get_write_same_sectors(cmd), GFP_KERNEL, 0);
+   if (rc < 0) {
+   pr_warn("blkdev_issue_discard() failed: %d\n", rc);
+   return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+   }
+   target_complete_cmd(cmd, GOOD);
+   return 0;
+   }
+   if (sectors > cmd->se_dev->dev_attrib.max_write_same_len) {
+   pr_warn("WRITE_SAME sectors: %u exceeds max_write_same_len: 
%u\n",
+   sectors, cmd->se_dev->dev_attrib.max_write_same_len);
+   return TCM_INVALID_CDB_FIELD;
+   }
+   sg = &cmd->t_data_sg[0];
 
-   ret = blkdev_issue_discard(ib_dev->ibd_bd, cmd->t_task_lba,
-  spc_get_write_same_sectors(cmd), GFP_KERNEL,
-  0);
-   if (ret < 0) {
-   pr_debug("blkdev_issue_discard() failed for WRITE_SAME\n");
-   return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
+   ibr = kzalloc(sizeof(struct iblock_req), GFP_KERNEL);
+   if (!ibr)
+   goto fail;
+   cmd->priv = ibr;
+
+   bio = iblock_get_bio(cmd, block_lba, 1);
+   if (!bio)
+   goto fail_free_ibr;
+
+   bio_list_init(&list);
+   bio_list_add(&list, bio);
+
+   atomic_set(&ibr->pending, 1);
+
+   while (sectors) {
+   while (bio_add_page(bio, sg_page(sg), sg->length, sg->offset)
+   != sg->length) {
+
+   bio = iblock_get_bio(cmd, block_lba, 1);
+   if (!bio)
+   goto fail_put_bios;
+
+   atomic_inc(&ibr->pending);
+   bio_list_add(&list, bio);
+   }
+
+   /* Always in 512 byte units for Linux/Block */
+   block_lba += sg->length >> IBLOCK_LBA_SHIFT;
+   sectors -= 1;
}
 
-   target_complete_cmd(cmd, GOOD);
+   iblock_submit_bios(&list, WRITE);
return 0;
+
+fail_put_bios:
+   while ((bio = bio_list_pop(&list)))
+   bio_put(bio);
+fail_free_ibr:
+   kfree(ibr);
+fail:
+   return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
 }
 
 enum {
-- 
1.7.2.5

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


[PATCH 2/3] target: Add max_write_same_len device attribute

2012-11-08 Thread Nicholas A. Bellinger
From: Nicholas Bellinger 

This patch adds a new max_write_same_len device attribute for use with
WRITE_SAME w/ UNMAP=0 backend emulation.

Also, update block limits VPD emulation code in spc_emulate_evpd_b0() to
set the default MAXIMUM WRITE SAME LENGTH value of zero.

Cc: Christoph Hellwig 
Cc: Martin K. Petersen 
Signed-off-by: Nicholas Bellinger 
---
 drivers/target/target_core_configfs.c |4 
 drivers/target/target_core_device.c   |   11 +++
 drivers/target/target_core_internal.h |1 +
 drivers/target/target_core_spc.c  |8 +++-
 include/target/target_core_base.h |3 +++
 5 files changed, 26 insertions(+), 1 deletions(-)

diff --git a/drivers/target/target_core_configfs.c 
b/drivers/target/target_core_configfs.c
index 7b473b6..2b14164 100644
--- a/drivers/target/target_core_configfs.c
+++ b/drivers/target/target_core_configfs.c
@@ -676,6 +676,9 @@ SE_DEV_ATTR(unmap_granularity, S_IRUGO | S_IWUSR);
 DEF_DEV_ATTRIB(unmap_granularity_alignment);
 SE_DEV_ATTR(unmap_granularity_alignment, S_IRUGO | S_IWUSR);
 
+DEF_DEV_ATTRIB(max_write_same_len);
+SE_DEV_ATTR(max_write_same_len, S_IRUGO | S_IWUSR);
+
 CONFIGFS_EATTR_OPS(target_core_dev_attrib, se_dev_attrib, da_group);
 
 static struct configfs_attribute *target_core_dev_attrib_attrs[] = {
@@ -701,6 +704,7 @@ static struct configfs_attribute 
*target_core_dev_attrib_attrs[] = {
&target_core_dev_attrib_max_unmap_block_desc_count.attr,
&target_core_dev_attrib_unmap_granularity.attr,
&target_core_dev_attrib_unmap_granularity_alignment.attr,
+   &target_core_dev_attrib_max_write_same_len.attr,
NULL,
 };
 
diff --git a/drivers/target/target_core_device.c 
b/drivers/target/target_core_device.c
index 599374e..54439bc 100644
--- a/drivers/target/target_core_device.c
+++ b/drivers/target/target_core_device.c
@@ -706,6 +706,16 @@ int se_dev_set_unmap_granularity_alignment(
return 0;
 }
 
+int se_dev_set_max_write_same_len(
+   struct se_device *dev,
+   u32 max_write_same_len)
+{
+   dev->dev_attrib.max_write_same_len = max_write_same_len;
+   pr_debug("dev[%p]: Set max_write_same_len: %u\n",
+   dev, dev->dev_attrib.max_write_same_len);
+   return 0;
+}
+
 int se_dev_set_emulate_dpo(struct se_device *dev, int flag)
 {
if (flag != 0 && flag != 1) {
@@ -1393,6 +1403,7 @@ struct se_device *target_alloc_device(struct se_hba *hba, 
const char *name)
dev->dev_attrib.unmap_granularity = DA_UNMAP_GRANULARITY_DEFAULT;
dev->dev_attrib.unmap_granularity_alignment =
DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT;
+   dev->dev_attrib.max_write_same_len = DA_MAX_WRITE_SAME_LEN;
dev->dev_attrib.fabric_max_sectors = DA_FABRIC_MAX_SECTORS;
dev->dev_attrib.optimal_sectors = DA_FABRIC_MAX_SECTORS;
 
diff --git a/drivers/target/target_core_internal.h 
b/drivers/target/target_core_internal.h
index bc9c522..93e9c1f 100644
--- a/drivers/target/target_core_internal.h
+++ b/drivers/target/target_core_internal.h
@@ -24,6 +24,7 @@ int   se_dev_set_max_unmap_lba_count(struct se_device *, u32);
 intse_dev_set_max_unmap_block_desc_count(struct se_device *, u32);
 intse_dev_set_unmap_granularity(struct se_device *, u32);
 intse_dev_set_unmap_granularity_alignment(struct se_device *, u32);
+intse_dev_set_max_write_same_len(struct se_device *, u32);
 intse_dev_set_emulate_dpo(struct se_device *, int);
 intse_dev_set_emulate_fua_write(struct se_device *, int);
 intse_dev_set_emulate_fua_read(struct se_device *, int);
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c
index 4b3c183..cf1b8bb 100644
--- a/drivers/target/target_core_spc.c
+++ b/drivers/target/target_core_spc.c
@@ -465,7 +465,7 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
 * Exit now if we don't support TP.
 */
if (!have_tp)
-   return 0;
+   goto max_write_same;
 
/*
 * Set MAXIMUM UNMAP LBA COUNT
@@ -491,6 +491,12 @@ spc_emulate_evpd_b0(struct se_cmd *cmd, unsigned char *buf)
if (dev->dev_attrib.unmap_granularity_alignment != 0)
buf[32] |= 0x80; /* Set the UGAVALID bit */
 
+   /*
+* MAXIMUM WRITE SAME LENGTH
+*/
+max_write_same:
+   put_unaligned_be64(dev->dev_attrib.max_write_same_len, &buf[36]);
+
return 0;
 }
 
diff --git a/include/target/target_core_base.h 
b/include/target/target_core_base.h
index 2787b85..1b45879 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -71,6 +71,8 @@
 #define DA_UNMAP_GRANULARITY_DEFAULT   0
 /* Default unmap_granularity_alignment */
 #define DA_UNMAP_GRANULARITY_ALIGNMENT_DEFAULT 0
+/* Default max_write_same_len, disabled by default */
+#define DA_MAX_WRITE_SAME_LEN  0
 /* Default max transfer length */
 #define DA_FABRIC_MAX_SECTORS  8192
 /* E

Re: scsi target, likely GPL violation

2012-11-08 Thread Dave Airlie
>> ...and then turn around and submit it to Nick since he's the target
>> subsystem maintainer? Nick is probably the one who wrote it!
>>
>> I'm happy to do that, but we should recognize something is seriously
>> skewed when the person nominally in charge of the in-kernel code also
>> has a vested interest in *not* seeing new features added, since it then
>> competes better with his company's offering.
>>
>> RTS is trying to use an "open core" business model. This works fine for
>> BSD-licensed code or code originally authored entirely by you, but their
>> code (all of it even the new stuff) is a derivative work of the Linux
>> kernel source code, and the GPL says they need to contribute it back.
>>
>
> Andy,
>
> Accusing us of violating GPL is a serious legal claim.
>
> In fact, we are not violating GPL.  In short, this is because we wrote
> the code you are referring to (the SCSI target core in our commercial
> RTS OS product), we have exclusive copyright ownership of it, and this
> code contains no GPL code from the community.  GPL obligations only
> apply downstream to licensees, and not to the author of the code.  Those
> who use the code under GPL are subject to its conditions; we are not.

Just to clarify since I'm not a major GPL expert. Are you:

a) distributing a Linux kernel

b) with a module built against it to be linked into it, whether
completely written in house or not?

Then the module is under the GPL, if you think you are like nvidia or
someone then think again, the corner case they live under is that they
don't distribute a Linux kernel with their module *ever*, and they
have a clear call for non-derived work status since its 90% the same
code as in their Windows drivers.

But if you distribute a kernel and a module in one place which I
assume RTS OS does, then you are in dangerous territory and could be
hit with cease and desist notices, which has happened to people
shipping kernels and linked nvidia binary drivers before.

Dave.
--
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: scsi target, likely GPL violation

2012-11-08 Thread Andy Grover
On 11/08/2012 12:05 PM, Nicholas A. Bellinger wrote:
> Accusing us of violating GPL is a serious legal claim.  
> 
> In fact, we are not violating GPL.  In short, this is because we wrote
> the code you are referring to (the SCSI target core in our commercial
> RTS OS product), we have exclusive copyright ownership of it, and this
> code contains no GPL code from the community.  GPL obligations only
> apply downstream to licensees, and not to the author of the code.  Those
> who use the code under GPL are subject to its conditions; we are not.

Hi Nick, thanks for finally responding.

I believe your argument is wrong for two reasons.

First, LIO is a derivative work of the Linux kernel. It uses kernel APIs
and headers. You ship Linux as part of RTS OS. Even if you had not asked
for LIO to be included in mainline, this would still be true and would
require you to publish your changes under the GPLv2.

Second, you claim you hold exclusive copyright for the code. Not true.
One example: on http://www.risingtidesystems.com/storage.html you claim
support for FCoE. You didn't build tcm_fc, Intel did. Under the GPLv2.
Furthermore, SRP support came from SCST, iirc. None of these
contributors gave RTS any right to use their copyrighted code except
under the conditions of the GPLv2.

> As you know, we contributed the Linux SCSI target core, including the
> relevant interfaces, to the Linux kernel.  To be clear, we wrote that
> code entirely ourselves, so we have the right to use it as we please.
> The version we use in RTS OS is a different, proprietary version, which
> we also wrote ourselves.  However, the fact that we contributed a
> version of the code to the Linux kernel does not require us to provide
> our proprietary version to anyone.

In addition to the two reasons above, how does it make any sense that
you are spending time maintaining in-tree LIO when none of that code can
theoretically benefit RTS's proprietary product? The more likely
scenario is you are basing your product on mainline LIO.

> If you want to understand better how dual licensing works, perhaps we
> can talk off list.  But we don’t really have a responsibility to respond
> to untrue accusations, nor to explain GPL, nor discuss our proprietary
> code.

All the contributions and improvements (there have been a LOT) since LIO
entered mainline are GPLed by their authors. If you incorporated any of
those improvements or fixes into RTS OS, then there's a third reason why
your code is subject to the GPL.

> We’re very disappointed that Red Hat would not be more professional in
> its communications about licensing compliance matters, particularly to a
> company like ours that has been a major contributor to Linux and
> therefore also to Red Hat’s own products.  So, while I invite you to
> talk about this with us directly, I also advise you – respectfully – not
> to make public accusations that are not true.  That is harmful to our
> reputation – and candidly, it doesn’t reflect well on you or your
> company.

I tried the private route but you and your CEO stalled, and then stopped
talking to me.

Please just start behaving properly w/r/t the GPL so we can all get back
to coding.

Regards -- Andy
--
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 1/2] drivers/message/fusion/mptscsih.c: missing break

2012-11-08 Thread akpm
From: Alan Cox 
Subject: drivers/message/fusion/mptscsih.c: missing break

This happens to do the right thing in all cases on fibre channel but not on
other media types

Signed-off-by: Alan Cox 
Cc: James Bottomley 
Cc: Nagalakshmi Nandigama 
Cc: Kashyap Desai 
Signed-off-by: Andrew Morton 
---

 drivers/message/fusion/mptscsih.c |1 +
 1 file changed, 1 insertion(+)

diff -puN 
drivers/message/fusion/mptscsih.c~drivers-message-fusion-mptscsihc-missing-break
 drivers/message/fusion/mptscsih.c
--- 
a/drivers/message/fusion/mptscsih.c~drivers-message-fusion-mptscsihc-missing-break
+++ a/drivers/message/fusion/mptscsih.c
@@ -792,6 +792,7 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_F
 * than an unsolicited DID_ABORT.
 */
sc->result = DID_RESET << 16;
+   break;
 
case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: /* 0x004C */
if (ioc->bus_type == FC)
_
--
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 2/2] drivers/scsi/hptiop: support HighPoint RR4520/RR4522 HBA

2012-11-08 Thread akpm
From: HighPoint Linux Team 
Subject: drivers/scsi/hptiop: support HighPoint RR4520/RR4522 HBA

Support IOP RR4520/RR4522 which are based on Marvell frey.

Signed-off-by: HighPoint Linux Team 
Signed-off-by: Andrew Morton 
---

 Documentation/scsi/hptiop.txt |   69 +
 drivers/scsi/hptiop.c |  413 ++--
 drivers/scsi/hptiop.h |   72 +
 3 files changed, 530 insertions(+), 24 deletions(-)

diff -puN 
Documentation/scsi/hptiop.txt~hptiop-support-highpoint-rr4520-rr4522-hba 
Documentation/scsi/hptiop.txt
--- a/Documentation/scsi/hptiop.txt~hptiop-support-highpoint-rr4520-rr4522-hba
+++ a/Documentation/scsi/hptiop.txt
@@ -37,7 +37,7 @@ For Intel IOP based adapters, the contro
 0x40Inbound Queue Port
 0x44Outbound Queue Port
 
-For Marvell IOP based adapters, the IOP is accessed via PCI BAR0 and BAR1:
+For Marvell not Frey IOP based adapters, the IOP is accessed via PCI BAR0 and 
BAR1:
 
  BAR0 offsetRegister
  0x20400Inbound Doorbell Register
@@ -55,9 +55,31 @@ For Marvell IOP based adapters, the IOP 
  0x40-0x1040Inbound Queue
0x1040-0x2040Outbound Queue
 
+For Marvell Frey IOP based adapters, the IOP is accessed via PCI BAR0 and BAR1:
 
-I/O Request Workflow
---
+ BAR0 offsetRegister
+ 0x0IOP configuration information.
+
+ BAR1 offsetRegister
+  0x4000Inbound List Base Address Low
+  0x4004Inbound List Base Address High
+  0x4018Inbound List Write Pointer
+  0x402CInbound List Configuration and Control
+  0x4050Outbound List Base Address Low
+  0x4054Outbound List Base Address High
+  0x4058Outbound List Copy Pointer Shadow Base Address Low
+  0x405COutbound List Copy Pointer Shadow Base Address High
+  0x4088Outbound List Interrupt Cause
+  0x408COutbound List Interrupt Enable
+ 0x1020CPCIe Function 0 Interrupt Enable
+ 0x10400PCIe Function 0 to CPU Message A
+ 0x10420CPU to PCIe Function 0 Message A
+ 0x10480CPU to PCIe Function 0 Doorbell
+ 0x10484CPU to PCIe Function 0 Doorbell Enable
+
+
+I/O Request Workflow of Not Marvell Frey
+--
 
 All queued requests are handled via inbound/outbound queue port.
 A request packet can be allocated in either IOP or host memory.
@@ -101,6 +123,45 @@ register 0. An outbound message with the
 of an inbound message.
 
 
+I/O Request Workflow of Marvell Frey
+--
+
+All queued requests are handled via inbound/outbound list.
+
+To send a request to the controller:
+
+- Allocate a free request in host DMA coherent memory.
+
+  Requests allocated in host memory must be aligned on 32-bytes boundary.
+
+- Fill the request with index of the request in the flag.
+
+  Fill a free inbound list unit with the physical address and the size of
+  the request.
+
+  Set up the inbound list write pointer with the index of previous unit,
+  round to 0 if the index reaches the supported count of requests.
+
+- Post the inbound list writer pointer to IOP.
+
+- The IOP process the request. When the request is completed, the flag of
+  the request with or-ed IOPMU_QUEUE_MASK_HOST_BITS will be put into a
+  free outbound list unit and the index of the outbound list unit will be
+  put into the copy pointer shadow register. An outbound interrupt will be
+  generated.
+
+- The host read the outbound list copy pointer shadow register and compare
+  with previous saved read ponter N. If they are different, the host will
+  read the (N+1)th outbound list unit.
+
+  The host get the index of the request from the (N+1)th outbound list
+  unit and complete the request.
+
+Non-queued requests (reset communication/reset/flush etc) can be sent via PCIe
+Function 0 to CPU Message A register. The CPU to PCIe Function 0 Message 
register
+with the same value indicates the completion of message.
+
+
 User-level Interface
 -
 
@@ -112,7 +173,7 @@ The driver exposes following sysfs attri
 
 
 -
-Copyright (C) 2006-2009 HighPoint Technologies, Inc. All Rights Reserved.
+Copyright (C) 2006-2012 HighPoint Technologies, Inc. All Rights Reserved.
 
   This file is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
diff -puN drivers/scsi/hptiop.c~hptiop-support-highpoint-rr4520-rr4522-hba 
drivers/scsi/hptiop.c
--- a/drivers/scsi/hptiop.c~hptiop-support-highpoint-rr4520-rr4522-hba
+++ a/drivers/scsi/hptiop.c
@@ -1,6 +1,6 @@
 /*
  * HighPoint RR3xxx/4xxx controller driver for Linux
- * Copyright (C) 2006-2009 HighPoint Technologies, Inc. All Rights Reserved.
+ * Copyright (C) 

Re: scsi target, likely GPL violation

2012-11-08 Thread Nicholas A. Bellinger
On Thu, 2012-11-08 at 13:22 -0800, Andy Grover wrote:
> On 11/08/2012 12:05 PM, Nicholas A. Bellinger wrote:
> > Accusing us of violating GPL is a serious legal claim.  
> > 
> > In fact, we are not violating GPL.  In short, this is because we wrote
> > the code you are referring to (the SCSI target core in our commercial
> > RTS OS product), we have exclusive copyright ownership of it, and this
> > code contains no GPL code from the community.  GPL obligations only
> > apply downstream to licensees, and not to the author of the code.  Those
> > who use the code under GPL are subject to its conditions; we are not.
> 
> Hi Nick, thanks for finally responding.
> 
> I believe your argument is wrong for two reasons.
> 
> First, LIO is a derivative work of the Linux kernel. It uses kernel APIs
> and headers. You ship Linux as part of RTS OS. Even if you had not asked
> for LIO to be included in mainline, this would still be true and would
> require you to publish your changes under the GPLv2.
> 
> Second, you claim you hold exclusive copyright for the code. Not true.
> One example: on http://www.risingtidesystems.com/storage.html you claim
> support for FCoE. You didn't build tcm_fc, Intel did. Under the GPLv2.
> Furthermore, SRP support came from SCST, iirc. None of these
> contributors gave RTS any right to use their copyrighted code except
> under the conditions of the GPLv2.
> 

Andy,

Support for certified VAAI is part of our commercial target core. The
target core constitutes a stand-alone kernel subsystem of which we are
the sole copyright owners. In addition, our target contains a number of
backend drivers, of which we are also the sole copyright owners, and a
number of fabric modules, of which some we are the sole copyright
owners, and of which others we are not, as you pointed out. A
substantial fraction of the code of which we own the sole copyright was
certified by BlackDuck Software as early as in 2007. 

We contributed our target to the Linux kernel in 2010, at which point we
forked it into the upstream version and our commercial version. These
target versions have been diverging over time, as we keep maintaining
either one of them independently.

For our commercial target core, we only use Linux kernel symbols that
are not marked as GPL. In addition, we define the API between the target
core and its backend drivers and between the target core and its fabric
modules, we define the ABI between the target core and user space, and
we have done so years before our code went upstream into the Linux
kernel.

We have been contributing substantially to the upstream target version
to keep improving Linux. We have also been improving our commercial
target version to afford the considerable effort and expense involved in
our ongoing Linux contributions, and to compensate other top Linux
kernel developers for their contributions to the upstream target
version.

RTS OS is based on a stock Linux enterprise kernel. This Linux kernel
has naturally the ability to load either one of our standalone
self-contained target module versions without any modifications.

Again, we’re very disappointed by these untrue and highly damaging
accusations from Red Hat. We have generously contributed to Linux, and
we have generously supported the Linux community for their contributions
to our upstream target and other Linux kernel parts. You have mostly
just incorporated our work into Red Hat’s products.

So yes, Andy, please start behaving properly, so that at least we can
get back to making Linux better.

--nab

--
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] virtio-scsi: Fix incorrect lock release order in virtscsi_kick_cmd

2012-11-08 Thread Nicholas A. Bellinger
From: Nicholas Bellinger 

This patch fixes a regression bug in virtscsi_kick_cmd() that relinquishes
the acquired spinlocks in the incorrect order using the wrong spin_unlock
macros, namely releasing vq->vq_lock before tgt->tgt_lock while invoking
the calls to virtio_ring.c:virtqueue_add_buf() and friends.

This bug was originally introduced in v3.5-rc7 code with:

commit 2bd37f0fde99cbf8b78fb55f1128e8c3a63cf1da
Author: Paolo Bonzini 
Date:   Wed Jun 13 16:56:34 2012 +0200

[SCSI] virtio-scsi: split scatterlist per target

Go ahead and make sure that vq->vq_lock is relinquished w/ spin_unlock
first, then release tgt->tgt_lock w/ spin_unlock_irqrestore.

Cc: Paolo Bonzini 
Cc: James Bottomley 
Cc: Christoph Hellwig 
Cc: sta...@vger.kernel.org
Signed-off-by: Nicholas Bellinger 
---
 drivers/scsi/virtio_scsi.c |4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
index 595af1a..b2abb8a 100644
--- a/drivers/scsi/virtio_scsi.c
+++ b/drivers/scsi/virtio_scsi.c
@@ -417,11 +417,11 @@ static int virtscsi_kick_cmd(struct 
virtio_scsi_target_state *tgt,
 
spin_lock(&vq->vq_lock);
ret = virtqueue_add_buf(vq->vq, tgt->sg, out_num, in_num, cmd, gfp);
-   spin_unlock(&tgt->tgt_lock);
+   spin_unlock(&vq->vq_lock);
if (ret >= 0)
ret = virtqueue_kick_prepare(vq->vq);
 
-   spin_unlock_irqrestore(&vq->vq_lock, flags);
+   spin_unlock_irqrestore(&tgt->tgt_lock, flags);
 
if (ret > 0)
virtqueue_notify(vq->vq);
-- 
1.7.2.5

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


[PATCH v9 00/10] ZPODD Patches

2012-11-08 Thread Aaron Lu
v9:
Build ZPODD as part of libata instead of another standalone module
as it is tightly related to other libata files.
Identify and init ZPODD during probe time instead of after SCSI
device is created as suggested by Tejun Heo.
Make use of pm qos flag to give ACPI hint when choosing ACPI state.
Expose qos flag to give user control of whether power off is allowed.

This patchset used Rafael's pm-qos work:
git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git pm-qos

v8:
This version is a redesign, it doesn't have much to do with previous
versions. The ZPODD implementation is done almost entirely in ATA layer
now, except 2 helper functions from SCSI sr driver to block disk events.

The basic idea is that, when ata port is runtime suspended, it will
check if the ODD is ready to be powered off. And if yes, events is
blocked and power omitted; if not, ODD's power supply remains unchanged
by keeping ACPI state at D0.

Some background knowledge about ZPODD is added below v1 history log.

v7:
Re work of runtime pm of sr driver, based on ideas of Alan Stern and
Oliver Neukum.

Jeff, due to the ready_to_power_off flag added, there is a small
change in [PATCH v7 6/6] libata: acpi: respect may_power_off flag,
please check if I can still get your ack, thanks.

v6:
When user changes may_power_off flag through sysfs entry and if device
is already runtime suspended, resume resume it so that it can respect
this flag next time it is runtime suspended as suggested by Alan Stern.
Call scsi_autopm_get/put_device once in sr_check_events as suggested by
Alan Stern.

v5:
Add may_power_off flag to scsi device.
Alan Stern suggested that I should not mess runtime suspend with
runtime power off, but the current zpodd implementation made it not
easy to seperate. So I re-wrote the zpodd implementation, the end
result is, normal ODD can also enter runtime suspended state, but
their power won't be removed.

v4:
Rebase on top of Linus' tree, due to this, the problem of a missing
flag in v3 is gone;
Add a new function scsi_autopm_put_device_autosuspend to first mark
last busy for the device and then put autosuspend it as suggested by
Oliver Neukum.
Typo fix as pointed by Sergei Shtylyov.
Check can_power_off flag before any runtime pm operations in sr.

v3:
Rebase on top of scsi-misc tree;
Add the sr related patches previously in Jeff's libata tree;
Re-organize the sr patches.
A problem for now: for patch
scsi: sr: support zero power ODD(ZPODD)
I can't set a flag in libata-acpi.c since a related function is
missing in scsi-misc tree. Will fix this when 3.6-rc1 released.

v2:
Bug fix for v1;
Use scsi_autopm_* in sr driver instead of pm_runtime_*;

v1:
Here are some patches to make ZPODD easier to use for end users and
a fix for using ZPODD with system suspend.

Some background knowledge about ZPODD:
ODD means Optical Disc Drive.
ZPODD means Zero Power ODD, it is a mechanism to place the ODD into
zero power state when the system is running at S0 system state without
user's awareness.
It achieved this by ACPI and SATA device attention pin. For power off,
normal ACPI control method is used to place the device into D3 cold
ACPI device state, aka. device power supply omitted. For power on, when
user press the eject button of a drawer type ODD or when user inserts
an ODD into a slot type ODD, the device attention pin will trigger. In
the current x86 implementation, this pin will connect to a GPE, and the
GPE will trigger an ACPI interrupt. With our pre-registered ACPI
notification code, the device can be runtime resumed, and we place the
device back to full power state by setting its ACPI state to D0. The
whole process is transparent to the end user.

Aaron Lu (10):
  scsi: sr: support runtime pm
  ata: zpodd: Add CONFIG_SATA_ZPODD
  ata: zpodd: identify and init ZPODD devices
  libata: acpi: move acpi notification code to zpodd
  libata: separate ATAPI code
  ata: zpodd: check zero power ready status
  block: add a new interface to block events
  scsi: sr: support (un)block events
  ata: zpodd: handle power transition of ODD
  ata: expose pm qos flags to user space for ata device

 block/genhd.c  |  26 
 drivers/ata/Kconfig|  12 ++
 drivers/ata/Makefile   |   3 +-
 drivers/ata/libata-acpi.c  | 123 ++---
 drivers/ata/libata-atapi.c |  88 
 drivers/ata/libata-core.c  |   4 +-
 drivers/ata/libata-eh.c|  87 +---
 drivers/ata/libata-scsi.c  |   4 +
 drivers/ata/libata-zpodd.c | 333 +
 drivers/ata/libata.h   |  33 +
 drivers/scsi/Makefile  |   1 +
 drivers/scsi/sr.c  |  30 +++-
 drivers/scsi/sr_zpodd.c|  21 +++
 drivers/scsi/sr_zpodd.h|   9 ++
 include/linux/genhd.h  |   1 +
 include/linux/libata.h |   2 +
 include/uapi/linux/cdrom.h |  34 +
 17 files changed, 638 insertions(+), 173 deletions(-)
 create mode 100644 drivers/ata/libata-atapi.c
 create mode 100644 drivers/ata/libata-zpodd.c
 create

[PATCH v9 01/10] scsi: sr: support runtime pm

2012-11-08 Thread Aaron Lu
This patch adds runtime pm support for sr.

It did this by increasing the runtime usage_count of the device when:
- its block device is opened;
- the events checking is to run.

And decreasing the runtime usage_count of the device when:
- its block device is closed;
- After the events checking is done.

The idea is discussed in this mail thread:
http://thread.gmane.org/gmane.linux.acpi.devel/55243/focus=52703

Signed-off-by: Aaron Lu 
---
 drivers/scsi/sr.c | 30 +-
 1 file changed, 25 insertions(+), 5 deletions(-)

diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 5fc97d2..4d1a610 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -45,6 +45,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -146,7 +147,8 @@ static inline struct scsi_cd *scsi_cd_get(struct gendisk 
*disk)
kref_get(&cd->kref);
if (scsi_device_get(cd->device))
goto out_put;
-   goto out;
+   if (!scsi_autopm_get_device(cd->device))
+   goto out;
 
  out_put:
kref_put(&cd->kref, sr_kref_release);
@@ -162,6 +164,7 @@ static void scsi_cd_put(struct scsi_cd *cd)
 
mutex_lock(&sr_ref_mutex);
kref_put(&cd->kref, sr_kref_release);
+   scsi_autopm_put_device(sdev);
scsi_device_put(sdev);
mutex_unlock(&sr_ref_mutex);
 }
@@ -211,7 +214,7 @@ static unsigned int sr_check_events(struct 
cdrom_device_info *cdi,
unsigned int clearing, int slot)
 {
struct scsi_cd *cd = cdi->handle;
-   bool last_present;
+   bool last_present = cd->media_present;
struct scsi_sense_hdr sshdr;
unsigned int events;
int ret;
@@ -220,6 +223,8 @@ static unsigned int sr_check_events(struct 
cdrom_device_info *cdi,
if (CDSL_CURRENT != slot)
return 0;
 
+   scsi_autopm_get_device(cd->device);
+
events = sr_get_events(cd->device);
cd->get_event_changed |= events & DISK_EVENT_MEDIA_CHANGE;
 
@@ -246,10 +251,9 @@ static unsigned int sr_check_events(struct 
cdrom_device_info *cdi,
}
 
if (!(clearing & DISK_EVENT_MEDIA_CHANGE))
-   return events;
+   goto out;
 do_tur:
/* let's see whether the media is there with TUR */
-   last_present = cd->media_present;
ret = scsi_test_unit_ready(cd->device, SR_TIMEOUT, MAX_RETRIES, &sshdr);
 
/*
@@ -270,7 +274,7 @@ do_tur:
}
 
if (cd->ignore_get_event)
-   return events;
+   goto out;
 
/* check whether GET_EVENT is reporting spurious MEDIA_CHANGE */
if (!cd->tur_changed) {
@@ -287,6 +291,18 @@ do_tur:
cd->tur_changed = false;
cd->get_event_changed = false;
 
+out:
+   /*
+* If there is no medium detected or the medium has been there
+* since last poll, try to suspend the device. Otherwise, keep
+* it active for one more poll interval so that if user space
+* application opens the block device, we can avoid a runtime
+* status change.
+*/
+   pm_runtime_put_noidle(&cd->device->sdev_gendev);
+   if (!cd->media_present || last_present)
+   pm_runtime_suspend(&cd->device->sdev_gendev);
+
return events;
 }
 
@@ -718,6 +734,8 @@ static int sr_probe(struct device *dev)
 
sdev_printk(KERN_DEBUG, sdev,
"Attached scsi CD-ROM %s\n", cd->cdi.name);
+   scsi_autopm_put_device(cd->device);
+
return 0;
 
 fail_put:
@@ -965,6 +983,8 @@ static int sr_remove(struct device *dev)
 {
struct scsi_cd *cd = dev_get_drvdata(dev);
 
+   scsi_autopm_get_device(cd->device);
+
blk_queue_prep_rq(cd->device->request_queue, scsi_prep_fn);
del_gendisk(cd->disk);
 
-- 
1.7.12.4

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


[PATCH v9 02/10] ata: zpodd: Add CONFIG_SATA_ZPODD

2012-11-08 Thread Aaron Lu
Added a new config CONFIG_SATA_ZPODD, which is used to support
SATA based zero power ODD. It depends on ATA_ACPI, and selects
BLK_DEV_SR as the implementation of ZPODD depends on SCSI sr driver.

A new file libata-zpodd.c is added, which will be used to host ZPODD
related code. It is empty for this commit.

Signed-off-by: Aaron Lu 
---
 drivers/ata/Kconfig  | 12 
 drivers/ata/Makefile |  1 +
 2 files changed, 13 insertions(+)
 create mode 100644 drivers/ata/libata-zpodd.c

diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig
index e08d322..9bcb8fb 100644
--- a/drivers/ata/Kconfig
+++ b/drivers/ata/Kconfig
@@ -58,6 +58,18 @@ config ATA_ACPI
  You can disable this at kernel boot time by using the
  option libata.noacpi=1
 
+config SATA_ZPODD
+   bool "SATA Zero Power ODD Support"
+   depends on ATA_ACPI
+   select BLK_DEV_SR
+   default n
+   help
+ This option adds support for SATA ZPODD. It requires both
+ ODD and the platform support, and if enabled, will automatically
+ power on/off the ODD when certain condition is satisfied. This
+ does not impact user's experience of the ODD, only power is saved
+ when ODD is not in use(i.e. no disc inside).
+
 config SATA_PMP
bool "SATA Port Multiplier support"
default y
diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 9329daf..85e3de4 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -107,3 +107,4 @@ libata-y:= libata-core.o libata-scsi.o libata-eh.o 
libata-transport.o
 libata-$(CONFIG_ATA_SFF)   += libata-sff.o
 libata-$(CONFIG_SATA_PMP)  += libata-pmp.o
 libata-$(CONFIG_ATA_ACPI)  += libata-acpi.o
+libata-$(CONFIG_SATA_ZPODD)+= libata-zpodd.o
diff --git a/drivers/ata/libata-zpodd.c b/drivers/ata/libata-zpodd.c
new file mode 100644
index 000..e69de29
-- 
1.7.12.4

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


[PATCH v9 03/10] ata: zpodd: identify and init ZPODD devices

2012-11-08 Thread Aaron Lu
The ODD can be enabled for ZPODD if the following three conditions are
satisfied:
1 The ODD supports device attention;
2 The platform can runtime power off the ODD through ACPI;
3 The ODD is either slot type or drawer type.
For such ODDs, zpodd_init is called and a new structure is allocated for
it to store ZPODD related stuffs.

And the zpodd_dev_enabled function is used to test if ZPODD is currently
enabled for this ODD.

Signed-off-by: Aaron Lu 
---
 drivers/ata/libata-acpi.c  |   2 +
 drivers/ata/libata-core.c  |   4 +-
 drivers/ata/libata-zpodd.c | 124 +
 drivers/ata/libata.h   |  17 +++
 include/uapi/linux/cdrom.h |  34 +
 5 files changed, 180 insertions(+), 1 deletion(-)

diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index fd9ecf7..3c61100 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -1059,6 +1059,8 @@ void ata_acpi_bind(struct ata_device *dev)
 
 void ata_acpi_unbind(struct ata_device *dev)
 {
+   if (zpodd_dev_enabled(dev))
+   zpodd_deinit(dev);
ata_acpi_remove_pm_notifier(dev);
ata_acpi_unregister_power_resource(dev);
 }
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 3cc7096..a2293b6 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2395,8 +2395,10 @@ int ata_dev_configure(struct ata_device *dev)
dma_dir_string = ", DMADIR";
}
 
-   if (ata_id_has_da(dev->id))
+   if (ata_id_has_da(dev->id)) {
dev->flags |= ATA_DFLAG_DA;
+   zpodd_init(dev);
+   }
 
/* print device info to dmesg */
if (ata_msg_drv(ap) && print_info)
diff --git a/drivers/ata/libata-zpodd.c b/drivers/ata/libata-zpodd.c
index e69de29..fce6ea6 100644
--- a/drivers/ata/libata-zpodd.c
+++ b/drivers/ata/libata-zpodd.c
@@ -0,0 +1,124 @@
+#include 
+#include 
+
+#include "libata.h"
+
+struct zpodd {
+   bool slot:1;
+   bool drawer:1;
+
+   struct ata_device *dev;
+};
+
+static int run_atapi_cmd(struct ata_device *dev, const char *cdb,
+   unsigned short cdb_len, char *buf, unsigned int buf_len)
+{
+   struct ata_taskfile tf = {0};
+
+   tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+   tf.command = ATA_CMD_PACKET;
+
+   if (buf) {
+   tf.protocol = ATAPI_PROT_PIO;
+   tf.lbam = buf_len;
+   } else {
+   tf.protocol = ATAPI_PROT_NODATA;
+   }
+
+   return ata_exec_internal(dev, &tf, cdb,
+   buf ? DMA_FROM_DEVICE : DMA_NONE, buf, buf_len, 0);
+}
+
+/*
+ * Per the spec, only slot type and drawer type ODD can be supported
+ *
+ * Return 0 for slot type, 1 for drawer, -ENODEV for other types or on error.
+ */
+static int check_loading_mechanism(struct ata_device *dev)
+{
+   char buf[16];
+   unsigned int ret;
+   struct rm_feature_desc *desc = (void *)(buf + 8);
+
+   char cdb[] = {  GPCMD_GET_CONFIGURATION,
+   2,  /* only 1 feature descriptor requested */
+   0, 3,   /* 3, removable medium feature */
+   0, 0, 0,/* reserved */
+   0, sizeof(buf),
+   0, 0, 0,
+   };
+
+   ret = run_atapi_cmd(dev, cdb, sizeof(cdb), buf, sizeof(buf));
+   if (ret)
+   return -ENODEV;
+
+   if (be16_to_cpu(desc->feature_code) != 3)
+   return -ENODEV;
+
+   if (desc->mech_type == 0 && desc->load == 0 && desc->eject == 1)
+   return 0; /* slot */
+   else if (desc->mech_type == 1 && desc->load == 0 && desc->eject == 1)
+   return 1; /* drawer */
+   else
+   return -ENODEV;
+}
+
+static bool device_can_poweroff(struct ata_device *ata_dev)
+{
+   acpi_handle handle;
+   acpi_status status;
+   struct acpi_device_power_state *states;
+   struct acpi_device *acpi_dev;
+
+   handle = ata_dev_acpi_handle(ata_dev);
+   if (!handle)
+   return false;
+
+   status = acpi_bus_get_device(handle, &acpi_dev);
+   if (ACPI_FAILURE(status))
+   return false;
+
+   /*
+* If firmware has _PS3 or _PR3 for this device,
+* it means this device can be runtime powered off
+*/
+   states = acpi_dev->power.states;
+   if (states[ACPI_STATE_D3_HOT].flags.valid ||
+   states[ACPI_STATE_D3_COLD].flags.explicit_set)
+   return true;
+   else
+   return false;
+}
+
+void zpodd_init(struct ata_device *dev)
+{
+   int ret;
+   struct zpodd *zpodd;
+
+   if (dev->private_data)
+   return;
+
+   if (!device_can_poweroff(dev))
+   return;
+
+   if ((ret = check_loading_mechanism(dev)) == -ENODEV)
+   return;
+
+   zpodd = kzalloc(sizeof(struct zpodd),

[PATCH v9 04/10] libata: acpi: move acpi notification code to zpodd

2012-11-08 Thread Aaron Lu
Since the ata acpi notification code introduced in commit
3bd46600a7a7e938c54df8cdbac9910668c7dfb0 is solely for ZPODD, and we
now have a dedicated place for it, move these code there.

And the add/remove_pm_notifier code is simplified a little bit that it
does not check things like if the handle is NULL and if a corresponding
acpi_device is there for the handle as they are guaranteed by the
device_can_poweroff already.

Signed-off-by: Aaron Lu 
---
 drivers/ata/libata-acpi.c  | 71 --
 drivers/ata/libata-zpodd.c | 30 
 2 files changed, 30 insertions(+), 71 deletions(-)

diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 3c61100..6b6819c 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -970,57 +970,6 @@ void ata_acpi_on_disable(struct ata_device *dev)
ata_acpi_clear_gtf(dev);
 }
 
-static void ata_acpi_wake_dev(acpi_handle handle, u32 event, void *context)
-{
-   struct ata_device *ata_dev = context;
-
-   if (event == ACPI_NOTIFY_DEVICE_WAKE && ata_dev &&
-   pm_runtime_suspended(&ata_dev->sdev->sdev_gendev))
-   scsi_autopm_get_device(ata_dev->sdev);
-}
-
-static void ata_acpi_add_pm_notifier(struct ata_device *dev)
-{
-   struct acpi_device *acpi_dev;
-   acpi_handle handle;
-   acpi_status status;
-
-   handle = ata_dev_acpi_handle(dev);
-   if (!handle)
-   return;
-
-   status = acpi_bus_get_device(handle, &acpi_dev);
-   if (ACPI_FAILURE(status))
-   return;
-
-   if (dev->sdev->can_power_off) {
-   acpi_install_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-   ata_acpi_wake_dev, dev);
-   device_set_run_wake(&dev->sdev->sdev_gendev, true);
-   }
-}
-
-static void ata_acpi_remove_pm_notifier(struct ata_device *dev)
-{
-   struct acpi_device *acpi_dev;
-   acpi_handle handle;
-   acpi_status status;
-
-   handle = ata_dev_acpi_handle(dev);
-   if (!handle)
-   return;
-
-   status = acpi_bus_get_device(handle, &acpi_dev);
-   if (ACPI_FAILURE(status))
-   return;
-
-   if (dev->sdev->can_power_off) {
-   device_set_run_wake(&dev->sdev->sdev_gendev, false);
-   acpi_remove_notify_handler(handle, ACPI_SYSTEM_NOTIFY,
-   ata_acpi_wake_dev);
-   }
-}
-
 static void ata_acpi_register_power_resource(struct ata_device *dev)
 {
struct scsi_device *sdev = dev->sdev;
@@ -1053,7 +1002,6 @@ static void ata_acpi_unregister_power_resource(struct 
ata_device *dev)
 
 void ata_acpi_bind(struct ata_device *dev)
 {
-   ata_acpi_add_pm_notifier(dev);
ata_acpi_register_power_resource(dev);
 }
 
@@ -1061,7 +1009,6 @@ void ata_acpi_unbind(struct ata_device *dev)
 {
if (zpodd_dev_enabled(dev))
zpodd_deinit(dev);
-   ata_acpi_remove_pm_notifier(dev);
ata_acpi_unregister_power_resource(dev);
 }
 
@@ -1103,9 +1050,6 @@ static int ata_acpi_bind_device(struct ata_port *ap, 
struct scsi_device *sdev,
acpi_handle *handle)
 {
struct ata_device *ata_dev;
-   acpi_status status;
-   struct acpi_device *acpi_dev;
-   struct acpi_device_power_state *states;
 
if (ap->flags & ATA_FLAG_ACPI_SATA)
ata_dev = &ap->link.device[sdev->channel];
@@ -1117,21 +1061,6 @@ static int ata_acpi_bind_device(struct ata_port *ap, 
struct scsi_device *sdev,
if (!*handle)
return -ENODEV;
 
-   status = acpi_bus_get_device(*handle, &acpi_dev);
-   if (ACPI_FAILURE(status))
-   return 0;
-
-   /*
-* If firmware has _PS3 or _PR3 for this device,
-* and this ata ODD device support device attention,
-* it means this device can be powered off
-*/
-   states = acpi_dev->power.states;
-   if ((states[ACPI_STATE_D3_HOT].flags.valid ||
-   states[ACPI_STATE_D3_COLD].flags.explicit_set) &&
-   ata_dev->flags & ATA_DFLAG_DA)
-   sdev->can_power_off = 1;
-
return 0;
 }
 
diff --git a/drivers/ata/libata-zpodd.c b/drivers/ata/libata-zpodd.c
index fce6ea6..ba8c985 100644
--- a/drivers/ata/libata-zpodd.c
+++ b/drivers/ata/libata-zpodd.c
@@ -1,11 +1,14 @@
 #include 
 #include 
+#include 
+#include 
 
 #include "libata.h"
 
 struct zpodd {
bool slot:1;
bool drawer:1;
+   bool from_notify:1; /* resumed as a result of acpi notification */
 
struct ata_device *dev;
 };
@@ -90,6 +93,31 @@ static bool device_can_poweroff(struct ata_device *ata_dev)
return false;
 }
 
+static void zpodd_wake_dev(acpi_handle handle, u32 event, void *context)
+{
+   struct ata_device *ata_dev = context;
+   struct zpodd *zpodd = ata_dev->private_data;
+   struct device *dev = &ata_dev->sdev->sdev_gendev;
+
+ 

[PATCH v9 06/10] ata: zpodd: check zero power ready status

2012-11-08 Thread Aaron Lu
Per the Mount Fuji spec, the ODD is considered zero power ready when:
- For slot type ODD, no media inside;
- For tray type ODD, no media inside and tray closed.

The information can be retrieved by either the returned information of
command GET_EVENT_STATUS_NOTIFICATION(the command is used to poll for
media event) or sense code.

In this implementation, the zero power ready status is determined by
the following factors:
1 polled media status byte, and this info is recorded in status_ready
  field of zpodd structure;
2 sense code by issuing a TEST_UNIT_READY command after status_ready
  is found to be true.

The information provided by the media status byte is not accurate, it is
possible that after a new disc is just inserted, the status byte still
returns media not present. So this information can not be used as the
final deciding factor. But since SCSI ODD driver sr will always poll the
ODD every 2 seconds, this information is readily available without any
much cost. So it is used as a hint: when we find zero power ready status
in the media status byte, we will see if it is really the case with the
sense code method. This way, we can avoid sending too many
TEST_UNIT_READY commands to the ODD.

When we first sensed the ODD in the zero power ready state, the
timestamp will be recoreded. And after ODD stayed in this state for some
pre-defined period, the ODD is considered as power off ready and the
zp_ready flag will be set. The zp_ready flag serves as the deciding
factor other code will use to see if power off is OK for the ODD. The
Mount Fuji spec suggests a delay should be used here, to avoid the case
user ejects the ODD and then instantly inserts a new one again, so that
we can avoid a power transition. And some ODDs may be slow to place its
head to the home position after disc is ejected, so a delay here is
generally a good idea.

The zero power ready status check is performed in the ata port's runtime
suspend code path, when port is not frozen yet, as we need to issue some
IOs to the ODD.

Signed-off-by: Aaron Lu 
---
 drivers/ata/libata-acpi.c  |   8 +++-
 drivers/ata/libata-scsi.c  |   4 ++
 drivers/ata/libata-zpodd.c | 116 +
 drivers/ata/libata.h   |   4 ++
 4 files changed, 131 insertions(+), 1 deletion(-)

diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 6b6819c..13ee178 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -784,7 +784,13 @@ static int ata_acpi_push_id(struct ata_device *dev)
  */
 int ata_acpi_on_suspend(struct ata_port *ap)
 {
-   /* nada */
+   struct ata_device *dev;
+
+   ata_for_each_dev(dev, &ap->link, ENABLED) {
+   if (zpodd_dev_enabled(dev))
+   zpodd_check_zpready(dev);
+   }
+
return 0;
 }
 
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index e3bda07..6f235b9 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -2665,6 +2665,10 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc)
ata_scsi_rbuf_put(cmd, true, &flags);
}
 
+   if (zpodd_dev_enabled(qc->dev) &&
+   scsicmd[0] == GET_EVENT_STATUS_NOTIFICATION)
+   zpodd_snoop_status(qc->dev, cmd);
+
cmd->result = SAM_STAT_GOOD;
}
 
diff --git a/drivers/ata/libata-zpodd.c b/drivers/ata/libata-zpodd.c
index ba8c985..533a39e 100644
--- a/drivers/ata/libata-zpodd.c
+++ b/drivers/ata/libata-zpodd.c
@@ -2,13 +2,21 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "libata.h"
 
+#define POWEROFF_DELAY  (30 * 1000) /* 30 seconds for power off delay */
+
 struct zpodd {
bool slot:1;
bool drawer:1;
bool from_notify:1; /* resumed as a result of acpi notification */
+   bool status_ready:1;/* ready status derived from media event poll,
+  it is not accurate, but serves as a hint */
+   bool zp_ready:1;/* zero power ready state */
+
+   unsigned long last_ready; /* last zero power ready timestamp */
 
struct ata_device *dev;
 };
@@ -93,6 +101,114 @@ static bool device_can_poweroff(struct ata_device *ata_dev)
return false;
 }
 
+/*
+ * Snoop the result of GET_STATUS_NOTIFICATION_EVENT, the media
+ * status byte has information on media present/door closed.
+ *
+ * This information serves only as a hint, as it is not accurate.
+ * The sense code method will be used when deciding if the ODD is
+ * really zero power ready.
+ */
+void zpodd_snoop_status(struct ata_device *dev, struct scsi_cmnd *scmd)
+{
+   bool ready;
+   char buf[8];
+   struct event_header *eh = (void *)buf;
+   struct media_event_desc *med = (void *)(buf + 4);
+   struct sg_table *table = &scmd->sdb.table;
+   struct zpodd *zpodd = dev->private_data;
+
+   if (sg_copy_to_buffer(table->sgl, table->nents, buf,

[PATCH v9 05/10] libata: separate ATAPI code

2012-11-08 Thread Aaron Lu
The atapi_eh_tur and atapi_eh_request_sense can be reused by ZPODD
code, so separate them out to a file named libata-atapi.c, and the
Makefile is modified accordingly. No functional changes should result
from this commit.

Signed-off-by: Aaron Lu 
---
 drivers/ata/Makefile   |  2 +-
 drivers/ata/libata-atapi.c | 88 ++
 drivers/ata/libata-eh.c| 85 
 drivers/ata/libata.h   |  4 +++
 4 files changed, 93 insertions(+), 86 deletions(-)
 create mode 100644 drivers/ata/libata-atapi.c

diff --git a/drivers/ata/Makefile b/drivers/ata/Makefile
index 85e3de4..36377f9 100644
--- a/drivers/ata/Makefile
+++ b/drivers/ata/Makefile
@@ -103,7 +103,7 @@ obj-$(CONFIG_ATA_GENERIC)   += ata_generic.o
 # Should be last libata driver
 obj-$(CONFIG_PATA_LEGACY)  += pata_legacy.o
 
-libata-y   := libata-core.o libata-scsi.o libata-eh.o libata-transport.o
+libata-y   := libata-core.o libata-scsi.o libata-eh.o libata-atapi.o 
libata-transport.o
 libata-$(CONFIG_ATA_SFF)   += libata-sff.o
 libata-$(CONFIG_SATA_PMP)  += libata-pmp.o
 libata-$(CONFIG_ATA_ACPI)  += libata-acpi.o
diff --git a/drivers/ata/libata-atapi.c b/drivers/ata/libata-atapi.c
new file mode 100644
index 000..28684ae
--- /dev/null
+++ b/drivers/ata/libata-atapi.c
@@ -0,0 +1,88 @@
+#include 
+#include 
+#include "libata.h"
+
+/**
+ * atapi_eh_tur - perform ATAPI TEST_UNIT_READY
+ * @dev: target ATAPI device
+ * @r_sense_key: out parameter for sense_key
+ *
+ * Perform ATAPI TEST_UNIT_READY.
+ *
+ * LOCKING:
+ * EH context (may sleep).
+ *
+ * RETURNS:
+ * 0 on success, AC_ERR_* mask on failure.
+ */
+unsigned int atapi_eh_tur(struct ata_device *dev, u8 *r_sense_key)
+{
+   u8 cdb[ATAPI_CDB_LEN] = { TEST_UNIT_READY, 0, 0, 0, 0, 0 };
+   struct ata_taskfile tf;
+   unsigned int err_mask;
+
+   ata_tf_init(dev, &tf);
+
+   tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+   tf.command = ATA_CMD_PACKET;
+   tf.protocol = ATAPI_PROT_NODATA;
+
+   err_mask = ata_exec_internal(dev, &tf, cdb, DMA_NONE, NULL, 0, 0);
+   if (err_mask == AC_ERR_DEV)
+   *r_sense_key = tf.feature >> 4;
+   return err_mask;
+}
+
+/**
+ * atapi_eh_request_sense - perform ATAPI REQUEST_SENSE
+ * @dev: device to perform REQUEST_SENSE to
+ * @sense_buf: result sense data buffer (SCSI_SENSE_BUFFERSIZE bytes long)
+ * @dfl_sense_key: default sense key to use
+ *
+ * Perform ATAPI REQUEST_SENSE after the device reported CHECK
+ * SENSE.  This function is EH helper.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep).
+ *
+ * RETURNS:
+ * 0 on success, AC_ERR_* mask on failure
+ */
+unsigned int atapi_eh_request_sense(struct ata_device *dev,
+   u8 *sense_buf, u8 dfl_sense_key)
+{
+   u8 cdb[ATAPI_CDB_LEN] = {
+   REQUEST_SENSE, 0, 0, 0, SCSI_SENSE_BUFFERSIZE, 0 };
+   struct ata_port *ap = dev->link->ap;
+   struct ata_taskfile tf;
+
+   DPRINTK("ATAPI request sense\n");
+
+   /* FIXME: is this needed? */
+   memset(sense_buf, 0, SCSI_SENSE_BUFFERSIZE);
+
+   /* initialize sense_buf with the error register,
+* for the case where they are -not- overwritten
+*/
+   sense_buf[0] = 0x70;
+   sense_buf[2] = dfl_sense_key;
+
+   /* some devices time out if garbage left in tf */
+   ata_tf_init(dev, &tf);
+
+   tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+   tf.command = ATA_CMD_PACKET;
+
+   /* is it pointless to prefer PIO for "safety reasons"? */
+   if (ap->flags & ATA_FLAG_PIO_DMA) {
+   tf.protocol = ATAPI_PROT_DMA;
+   tf.feature |= ATAPI_PKT_DMA;
+   } else {
+   tf.protocol = ATAPI_PROT_PIO;
+   tf.lbam = SCSI_SENSE_BUFFERSIZE;
+   tf.lbah = 0;
+   }
+
+   return ata_exec_internal(dev, &tf, cdb, DMA_FROM_DEVICE,
+sense_buf, SCSI_SENSE_BUFFERSIZE, 0);
+}
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index e60437c..6487b88 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1579,91 +1579,6 @@ static int ata_eh_read_log_10h(struct ata_device *dev,
 }
 
 /**
- * atapi_eh_tur - perform ATAPI TEST_UNIT_READY
- * @dev: target ATAPI device
- * @r_sense_key: out parameter for sense_key
- *
- * Perform ATAPI TEST_UNIT_READY.
- *
- * LOCKING:
- * EH context (may sleep).
- *
- * RETURNS:
- * 0 on success, AC_ERR_* mask on failure.
- */
-static unsigned int atapi_eh_tur(struct ata_device *dev, u8 *r_sense_key)
-{
-   u8 cdb[ATAPI_CDB_LEN] = { TEST_UNIT_READY, 0, 0, 0, 0, 0 };
-   struct ata_taskfile tf;
-   unsigned int err_mask;
-
-   ata_tf_init(dev, &tf);
-
-   tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-   tf.command = ATA_CMD_PACKET;
-

[PATCH v9 08/10] scsi: sr: support (un)block events

2012-11-08 Thread Aaron Lu
2 interfaces are added to block/unblock events for the disk sr manages.
This is used by SATA ZPODD, when ODD is runtime powered off, the events
poll is no longer needed so better be blocked. And once powered on,
events poll will be unblocked.

These 2 interfaces are needed here because SATA layer does not have
access to the gendisk structure sr manages.

Signed-off-by: Aaron Lu 
---
 drivers/scsi/Makefile   |  1 +
 drivers/scsi/sr_zpodd.c | 21 +
 drivers/scsi/sr_zpodd.h |  9 +
 3 files changed, 31 insertions(+)
 create mode 100644 drivers/scsi/sr_zpodd.c
 create mode 100644 drivers/scsi/sr_zpodd.h

diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 888f73a..474efe2 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -177,6 +177,7 @@ sd_mod-objs := sd.o
 sd_mod-$(CONFIG_BLK_DEV_INTEGRITY) += sd_dif.o
 
 sr_mod-objs:= sr.o sr_ioctl.o sr_vendor.o
+sr_mod-$(CONFIG_SATA_ZPODD) += sr_zpodd.o
 ncr53c8xx-flags-$(CONFIG_SCSI_ZALON) \
:= -DCONFIG_NCR53C8XX_PREFETCH -DSCSI_NCR_BIG_ENDIAN \
-DCONFIG_SCSI_NCR53C8XX_NO_WORD_TRANSFERS
diff --git a/drivers/scsi/sr_zpodd.c b/drivers/scsi/sr_zpodd.c
new file mode 100644
index 000..0686e8c
--- /dev/null
+++ b/drivers/scsi/sr_zpodd.c
@@ -0,0 +1,21 @@
+#include 
+#include 
+#include 
+#include "sr.h"
+
+bool sr_block_events(struct device *dev)
+{
+   struct scsi_cd *cd = dev_get_drvdata(dev);
+   if (cd)
+   return disk_try_block_events(cd->disk);
+   return false;
+}
+EXPORT_SYMBOL(sr_block_events);
+
+void sr_unblock_events(struct device *dev)
+{
+   struct scsi_cd *cd = dev_get_drvdata(dev);
+   if (cd)
+   disk_unblock_events(cd->disk);
+}
+EXPORT_SYMBOL(sr_unblock_events);
diff --git a/drivers/scsi/sr_zpodd.h b/drivers/scsi/sr_zpodd.h
new file mode 100644
index 000..49c6a55
--- /dev/null
+++ b/drivers/scsi/sr_zpodd.h
@@ -0,0 +1,9 @@
+#ifndef __SR_ZPODD_H__
+#define __SR_ZPODD_H__
+
+#include 
+
+extern bool sr_block_events(struct device *dev);
+extern void sr_unblock_events(struct device *dev);
+
+#endif
-- 
1.7.12.4

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


[PATCH v9 09/10] ata: zpodd: handle power transition of ODD

2012-11-08 Thread Aaron Lu
When ata port is runtime suspended, it will check if the ODD attched to
it is in zero power ready state by checking the zp_ready field. And if
this field indicates it is not ready to be powered off, NO_POWEROFF qos
flag will be set to avoid choosing ACPI_STATE_D3_COLD for it.

Once powered off, disk events will be blocked to avoid waking it up
every two seconds.

And on resume, it will re-gain power and go through the recovery
process. When reset for the ata port is done, the ODD is considered
functional, and post processing like eject tray if the ODD is drawer
type is done there. And disk events is unblocked here.

For normal ODDs that do not support zero power state, NO_POWEROFF qos
flag will always be set.

Signed-off-by: Aaron Lu 
---
 drivers/ata/libata-acpi.c  | 40 ++---
 drivers/ata/libata-eh.c|  2 ++
 drivers/ata/libata-zpodd.c | 63 ++
 drivers/ata/libata.h   |  8 ++
 include/linux/libata.h |  2 ++
 5 files changed, 106 insertions(+), 9 deletions(-)

diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 13ee178..91f3405 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -838,6 +838,24 @@ void ata_acpi_on_resume(struct ata_port *ap)
}
 }
 
+static int ata_acpi_choose_state(struct ata_device *dev)
+{
+   /* Always choose D3 for PATA devices */
+   if (!(dev->link->ap->flags & ATA_FLAG_ACPI_SATA))
+   return ACPI_STATE_D3;
+
+   if (zpodd_dev_enabled(dev)) {
+   if (zpodd_poweroff_ready(dev))
+   dev_pm_qos_update_request(&dev->poweroff_req, 0);
+   else
+   dev_pm_qos_update_request(&dev->poweroff_req,
+ PM_QOS_FLAG_NO_POWER_OFF);
+   }
+
+   return acpi_pm_device_sleep_state(&dev->sdev->sdev_gendev,
+ NULL, ACPI_STATE_D3_COLD);
+}
+
 /**
  * ata_acpi_set_state - set the port power state
  * @ap: target ATA port
@@ -864,17 +882,16 @@ void ata_acpi_set_state(struct ata_port *ap, pm_message_t 
state)
continue;
 
if (state.event != PM_EVENT_ON) {
-   acpi_state = acpi_pm_device_sleep_state(
-   &dev->sdev->sdev_gendev, NULL, ACPI_STATE_D3);
-   if (acpi_state > 0)
+   acpi_state = ata_acpi_choose_state(dev);
+   if (acpi_state > 0) {
acpi_bus_set_power(handle, acpi_state);
-   /* TBD: need to check if it's runtime pm request */
-   acpi_pm_device_run_wake(
-   &dev->sdev->sdev_gendev, true);
+   if (zpodd_dev_enabled(dev) &&
+   acpi_state == ACPI_STATE_D3_COLD)
+   zpodd_post_poweroff(dev);
+   }
} else {
-   /* Ditto */
-   acpi_pm_device_run_wake(
-   &dev->sdev->sdev_gendev, false);
+   if (zpodd_dev_enabled(dev))
+   zpodd_pre_poweron(dev);
acpi_bus_set_power(handle, ACPI_STATE_D0);
}
}
@@ -1008,7 +1025,12 @@ static void ata_acpi_unregister_power_resource(struct 
ata_device *dev)
 
 void ata_acpi_bind(struct ata_device *dev)
 {
+   /* ODD can't be put to D3 cold state, unless it is zero power capable */
+   s32 value = dev->class == ATA_DEV_ATAPI ? PM_QOS_FLAG_NO_POWER_OFF : 0;
+
ata_acpi_register_power_resource(dev);
+   dev_pm_qos_add_request(&dev->sdev->sdev_gendev, &dev->poweroff_req,
+   DEV_PM_QOS_FLAGS, value);
 }
 
 void ata_acpi_unbind(struct ata_device *dev)
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 6487b88..1348e7c 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -3771,6 +3771,8 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t 
prereset,
rc = atapi_eh_clear_ua(dev);
if (rc)
goto rest_fail;
+   if (zpodd_dev_enabled(dev))
+   zpodd_post_resume(dev);
}
}
 
diff --git a/drivers/ata/libata-zpodd.c b/drivers/ata/libata-zpodd.c
index 533a39e..777f9c7 100644
--- a/drivers/ata/libata-zpodd.c
+++ b/drivers/ata/libata-zpodd.c
@@ -5,6 +5,7 @@
 #include 
 
 #include "libata.h"
+#include "../scsi/sr_zpodd.h"
 
 #define POWEROFF_DELAY  (30 * 1000) /* 30 seconds for power off delay */
 
@@ -15,6 +16,7 @@ struct zpodd {
bool status_ready:1;/* ready status derived from media event poll,
   it is not ac

[PATCH v9 10/10] ata: expose pm qos flags to user space for ata device

2012-11-08 Thread Aaron Lu
Expose pm qos flags to user space so that user has a chance to disable
pm features like power off, if he/she has a broken platform or devices
or simply does not like this pm feature.

This flag is exposed to user space only for ata device or atapi device
that is zero power capable. For normal atapi device, it will never be
powered off.

Signed-off-by: Aaron Lu 
---
 drivers/ata/libata-acpi.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c
index 91f3405..3984290 100644
--- a/drivers/ata/libata-acpi.c
+++ b/drivers/ata/libata-acpi.c
@@ -1031,6 +1031,8 @@ void ata_acpi_bind(struct ata_device *dev)
ata_acpi_register_power_resource(dev);
dev_pm_qos_add_request(&dev->sdev->sdev_gendev, &dev->poweroff_req,
DEV_PM_QOS_FLAGS, value);
+   if (dev->class == ATA_DEV_ATA || zpodd_dev_enabled(dev))
+   dev_pm_qos_expose_flags(&dev->sdev->sdev_gendev, 0);
 }
 
 void ata_acpi_unbind(struct ata_device *dev)
-- 
1.7.12.4

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


[PATCH v9 07/10] block: add a new interface to block events

2012-11-08 Thread Aaron Lu
A new interface to block disk events is added, this interface is
meant to eliminate a race between PM runtime callback and disk events
checking.

Suppose the following device tree:
device_sata_port  (the parent)
  device_ODD  (the child)

When ODD is runtime suspended, sata port will have a chance to enter
runtime suspended state. And in sata port's runtime suspend callback,
it will check if it is OK to omit the power of the ODD. And if yes, the
periodically running events checking work will be stopped, as the ODD
will be waken up by that check and cancel it can make the ODD stay in
zero power state much longer(no worry about how the ODD gets media
change event in ZPODD's case).

I used disk_block_events to do the events blocking, but there is a race
and can lead to a deadlock: when I call disk_block_events in sata port's
runtime suspend callback, the events checking work may already be running
and it will resume the ODD synchronously, and PM core will try to resume
its parent, the sata port first. The PM core makes sure that runtime
resume callback does not run concurrently with runtime suspend callback,
and if the runtime suspend callback is running, the runtime resume
callback will wait for it done. So the events checking work will wait
for sata port's runtime suspend callback, while the sata port's runtime
suspend callback is waiting for the disk events work to finish. Deadlock.

ODD_suspenddisk_events_workfn
  ata_port_suspend   check_events
disk_block_events  resume ODD
  cancel_delayed_work_sync   resume parent
  (waiting for disk_events_workfn)   (waiting for suspend callback)

So a new function disk_try_block_events is added, it will try to
cancel the delayed work if it is pending. If succeed, disk_block_events
will be called and we are done; if failed, false is returned without
doing anything. In this way, the race can be avoided.

The newly added interface and the disk_unblock_events are exported, as
sr driver will need to use them to block/unblock disk events.

Signed-off-by: Aaron Lu 
---
 block/genhd.c | 26 ++
 include/linux/genhd.h |  1 +
 2 files changed, 27 insertions(+)

diff --git a/block/genhd.c b/block/genhd.c
index 6cace66..8632fd3 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -1469,6 +1469,31 @@ void disk_block_events(struct gendisk *disk)
mutex_unlock(&ev->block_mutex);
 }
 
+/*
+ * Under some circumstances, there is a race between the calling thread
+ * of disk_block_events and the events checking function. To avoid such a race,
+ * this function will check if the delayed work is pending. If not, it means
+ * the work is either not queued or is already running, false is returned.
+ * And if yes, try to cancel the delayed work. If succedded, disk_block_events
+ * will be called and there is no worry that cancel_delayed_work_sync will
+ * deadlock the events checking function. And if failed, false is returned.
+ */
+bool disk_try_block_events(struct gendisk *disk)
+{
+   struct disk_events *ev = disk->ev;
+
+   if (!ev)
+   return false;
+
+   if (cancel_delayed_work(&disk->ev->dwork)) {
+   disk_block_events(disk);
+   return true;
+   }
+
+   return false;
+}
+EXPORT_SYMBOL(disk_try_block_events);
+
 static void __disk_unblock_events(struct gendisk *disk, bool check_now)
 {
struct disk_events *ev = disk->ev;
@@ -1512,6 +1537,7 @@ void disk_unblock_events(struct gendisk *disk)
if (disk->ev)
__disk_unblock_events(disk, false);
 }
+EXPORT_SYMBOL(disk_unblock_events);
 
 /**
  * disk_flush_events - schedule immediate event checking and flushing
diff --git a/include/linux/genhd.h b/include/linux/genhd.h
index 4f440b3..b67247f 100644
--- a/include/linux/genhd.h
+++ b/include/linux/genhd.h
@@ -420,6 +420,7 @@ static inline int get_disk_ro(struct gendisk *disk)
 }
 
 extern void disk_block_events(struct gendisk *disk);
+extern bool disk_try_block_events(struct gendisk *disk);
 extern void disk_unblock_events(struct gendisk *disk);
 extern void disk_flush_events(struct gendisk *disk, unsigned int mask);
 extern unsigned int disk_clear_events(struct gendisk *disk, unsigned int mask);
-- 
1.7.12.4

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


[PATCH RESEND v4 0/5] Migrate SCSI drivers to use dev_pm_ops

2012-11-08 Thread Aaron Lu
This patchset has been quiet for a while, so resend them.

v4:
Only Patch 4 is modified:
Fixed a line over 80 characters warning by checkpatch.pl;
Update the changelog so that it is no more a try :-)

v3:
Only patch 4 is modified:
Remove the special case for system freeze in scsi_bus_suspend_common
as pointed out by Alan Stern;
Updated some comments;
Removed the use of typedef (*pm_callback_t)(struct device *).

v2:
Change the runtime suspend behaviour of sd driver by putting the device
into stopped power state.
Revert 2 patches which are no longer needed as pointed out by Alan Stern.
Find out device callbacks in bus callbacks as suggested by Alan Stern.

Due to these changes, patch number grows from 2 -> 5.

v1:
The 2 patches will migrate SCSI drivers to use the pm callbacks defined
in dev_pm_ops as pm_message is deprecated and should not be used by driver.
Bus level callback is changed to use callbacks defined in dev_pm_ops when
needed and sd's pm callback is updated to use what are defined in dev_pm_ops.


Aaron Lu (5):
  sd: put to stopped power state when runtime suspend
  Revert "[SCSI] scsi_pm: set device runtime state before parent
suspended"
  Revert "[SCSI] runtime resume parent for child's system-resume"
  pm: use callbacks from dev_pm_ops for scsi devices
  sd: update sd to use the new pm callbacks

 drivers/scsi/scsi_pm.c | 98 +++---
 drivers/scsi/sd.c  | 18 +++---
 2 files changed, 67 insertions(+), 49 deletions(-)

-- 
1.7.12.21.g871e293

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


[PATCH v4 1/5] sd: put to stopped power state when runtime suspend

2012-11-08 Thread Aaron Lu
When device is runtime suspended, put it to stopped power state to save
some power.

This will also make the behaviour consistent with what the scsi_pm.c
thinks about sd as the comment says:
sd treats runtime suspend, system suspend and system hibernate identical.
With this patch, it is now identical.
And sd_shutdown will also do nothing when it finds the device has been
runtime suspended, if we do not spin down the disk in runtime suspend
by putting it into stopped power state, the disk will be shut down
incorrectly.
And the the same problem can be solved for runtime power off after
runtime suspended case by this change.

With the current runtime scheme for disk, it will only be runtime
suspended when no process opens the disk, so this shouldn't happen a
lot, which makes it acceptable to spin down the disk when runtime
suspended. If some day a more aggressive runtime scheme is used, like
the 'request based runtime pm for disk' that Alan Stern and Lin Ming
has been working, we can introduce some policy to control this. But for
now, make it simple and correct by spinning down the disk.

Signed-off-by: Aaron Lu 
Acked-by: Alan Stern 
Acked-by: Rafael J. Wysocki 
---
 drivers/scsi/sd.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 12f6fdf..8b6e004 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -2911,7 +2911,8 @@ static int sd_suspend(struct device *dev, pm_message_t 
mesg)
goto done;
}
 
-   if ((mesg.event & PM_EVENT_SLEEP) && sdkp->device->manage_start_stop) {
+   if (((mesg.event & PM_EVENT_SLEEP) || PMSG_IS_AUTO(mesg)) &&
+   sdkp->device->manage_start_stop) {
sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
ret = sd_start_stop_device(sdkp, 0);
}
-- 
1.7.12.21.g871e293

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


[PATCH v4 2/5] Revert "[SCSI] scsi_pm: set device runtime state before parent suspended"

2012-11-08 Thread Aaron Lu
This reverts commit 33a2285d96b5e7b9500612ec623bf4313397bb53.

With commit 88d26136a256576e444db312179e17af6dd0ea87 (PM: Prevent
runtime suspend during system resume), this patch is no longer needed.

Signed-off-by: Aaron Lu 
Acked-by: Alan Stern 
Acked-by: Rafael J. Wysocki 
---
 drivers/scsi/scsi_pm.c | 23 +++
 1 file changed, 11 insertions(+), 12 deletions(-)

diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
index dc0ad85..d4201de 100644
--- a/drivers/scsi/scsi_pm.c
+++ b/drivers/scsi/scsi_pm.c
@@ -76,24 +76,23 @@ static int scsi_bus_resume_common(struct device *dev)
 {
int err = 0;
 
-   /*
-* Parent device may have runtime suspended as soon as
-* it is woken up during the system resume.
-*
-* Resume it on behalf of child.
-*/
-   pm_runtime_get_sync(dev->parent);
-
-   if (scsi_is_sdev_device(dev))
+   if (scsi_is_sdev_device(dev)) {
+   /*
+* Parent device may have runtime suspended as soon as
+* it is woken up during the system resume.
+*
+* Resume it on behalf of child.
+*/
+   pm_runtime_get_sync(dev->parent);
err = scsi_dev_type_resume(dev);
+   pm_runtime_put_sync(dev->parent);
+   }
+
if (err == 0) {
pm_runtime_disable(dev);
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
}
-
-   pm_runtime_put_sync(dev->parent);
-
return err;
 }
 
-- 
1.7.12.21.g871e293

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


[PATCH v4 3/5] Revert "[SCSI] runtime resume parent for child's system-resume"

2012-11-08 Thread Aaron Lu
This reverts commit 28fd00d42cca178638f51c08efa986a777c24a4b.

With commit 88d26136a256576e444db312179e17af6dd0ea87 (PM: Prevent
runtime suspend during system resume), this patch is no longer needed.

Signed-off-by: Aaron Lu 
Acked-by: Alan Stern 
Acked-by: Rafael J. Wysocki 
---
 drivers/scsi/scsi_pm.c | 11 +--
 1 file changed, 1 insertion(+), 10 deletions(-)

diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
index d4201de..9923b26 100644
--- a/drivers/scsi/scsi_pm.c
+++ b/drivers/scsi/scsi_pm.c
@@ -76,17 +76,8 @@ static int scsi_bus_resume_common(struct device *dev)
 {
int err = 0;
 
-   if (scsi_is_sdev_device(dev)) {
-   /*
-* Parent device may have runtime suspended as soon as
-* it is woken up during the system resume.
-*
-* Resume it on behalf of child.
-*/
-   pm_runtime_get_sync(dev->parent);
+   if (scsi_is_sdev_device(dev))
err = scsi_dev_type_resume(dev);
-   pm_runtime_put_sync(dev->parent);
-   }
 
if (err == 0) {
pm_runtime_disable(dev);
-- 
1.7.12.21.g871e293

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


[PATCH v4 4/5] pm: use callbacks from dev_pm_ops for scsi devices

2012-11-08 Thread Aaron Lu
Use of pm_message_t is deprecated and device driver is not supposed
to use that. This patch migrates the SCSI bus level pm callbacks
to call device's pm callbacks defined in its driver's dev_pm_ops.

This is achieved by finding out which device pm callback should be used
in bus callback function, and then pass that callback function pointer
as a param to the scsi_bus_{suspend,resume}_common routine, which will
further pass that callback to scsi_dev_type_{suspend,resume} after
proper handling.

The special case for freeze in scsi_bus_suspend_common is not necessary
since there is no high level SCSI driver has implemented freeze, so no
need to runtime resume the device if it is in runtime suspended state
for system freeze, just return like the system suspend/hibernate case.

Since only sd has implemented drv->suspend/drv->resume, and I'll update
sd driver to use the new callbacks in the following patch, there is no
need to fallback to call drv->suspend/drv->resume if dev_pm_ops is NULL.

Signed-off-by: Aaron Lu 
Acked-by: Alan Stern 
Acked-by: Rafael J. Wysocki 
---
 drivers/scsi/scsi_pm.c | 86 +++---
 1 file changed, 53 insertions(+), 33 deletions(-)

diff --git a/drivers/scsi/scsi_pm.c b/drivers/scsi/scsi_pm.c
index 9923b26..8f6b12c 100644
--- a/drivers/scsi/scsi_pm.c
+++ b/drivers/scsi/scsi_pm.c
@@ -16,16 +16,14 @@
 
 #include "scsi_priv.h"
 
-static int scsi_dev_type_suspend(struct device *dev, pm_message_t msg)
+static int scsi_dev_type_suspend(struct device *dev, int (*cb)(struct device 
*))
 {
-   struct device_driver *drv;
int err;
 
err = scsi_device_quiesce(to_scsi_device(dev));
if (err == 0) {
-   drv = dev->driver;
-   if (drv && drv->suspend) {
-   err = drv->suspend(dev, msg);
+   if (cb) {
+   err = cb(dev);
if (err)
scsi_device_resume(to_scsi_device(dev));
}
@@ -34,14 +32,12 @@ static int scsi_dev_type_suspend(struct device *dev, 
pm_message_t msg)
return err;
 }
 
-static int scsi_dev_type_resume(struct device *dev)
+static int scsi_dev_type_resume(struct device *dev, int (*cb)(struct device *))
 {
-   struct device_driver *drv;
int err = 0;
 
-   drv = dev->driver;
-   if (drv && drv->resume)
-   err = drv->resume(dev);
+   if (cb)
+   err = cb(dev);
scsi_device_resume(to_scsi_device(dev));
dev_dbg(dev, "scsi resume: %d\n", err);
return err;
@@ -49,35 +45,33 @@ static int scsi_dev_type_resume(struct device *dev)
 
 #ifdef CONFIG_PM_SLEEP
 
-static int scsi_bus_suspend_common(struct device *dev, pm_message_t msg)
+static int
+scsi_bus_suspend_common(struct device *dev, int (*cb)(struct device *))
 {
int err = 0;
 
if (scsi_is_sdev_device(dev)) {
/*
-* sd is the only high-level SCSI driver to implement runtime
-* PM, and sd treats runtime suspend, system suspend, and
-* system hibernate identically (but not system freeze).
+* All the high-level SCSI drivers that implement runtime
+* PM treat runtime suspend, system suspend, and system
+* hibernate identically.
 */
-   if (pm_runtime_suspended(dev)) {
-   if (msg.event == PM_EVENT_SUSPEND ||
-   msg.event == PM_EVENT_HIBERNATE)
-   return 0;   /* already suspended */
+   if (pm_runtime_suspended(dev))
+   return 0;
 
-   /* wake up device so that FREEZE will succeed */
-   pm_runtime_resume(dev);
-   }
-   err = scsi_dev_type_suspend(dev, msg);
+   err = scsi_dev_type_suspend(dev, cb);
}
+
return err;
 }
 
-static int scsi_bus_resume_common(struct device *dev)
+static int
+scsi_bus_resume_common(struct device *dev, int (*cb)(struct device *))
 {
int err = 0;
 
if (scsi_is_sdev_device(dev))
-   err = scsi_dev_type_resume(dev);
+   err = scsi_dev_type_resume(dev, cb);
 
if (err == 0) {
pm_runtime_disable(dev);
@@ -102,26 +96,49 @@ static int scsi_bus_prepare(struct device *dev)
 
 static int scsi_bus_suspend(struct device *dev)
 {
-   return scsi_bus_suspend_common(dev, PMSG_SUSPEND);
+   const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+   return scsi_bus_suspend_common(dev, pm ? pm->suspend : NULL);
+}
+
+static int scsi_bus_resume(struct device *dev)
+{
+   const struct dev_pm_ops *pm = dev->driver ? dev->driver->pm : NULL;
+   return scsi_bus_resume_common(dev, pm ? pm->resume : NULL);
 }
 
 static int scsi_bus_freeze(struct device *dev)
 {
-   return scsi_bus_suspend_common(dev, PMSG_FREEZE);

[PATCH v4 5/5] sd: update sd to use the new pm callbacks

2012-11-08 Thread Aaron Lu
Update sd driver to use the callbacks defined in dev_pm_ops.

sd_freeze is NULL, the bus level callback has taken care of quiescing
the device so there should be nothing needs to be done here.
Consequently, sd_thaw is not needed here either.

suspend, poweroff and runtime suspend share the same routine sd_suspend,
which will sync flush and then stop the drive, this is the same as before.

resume, restore and runtime resume share the same routine sd_resume,
which will start the drive by putting it into active power state, this
is also the same as before.

Signed-off-by: Aaron Lu 
Acked-by: Alan Stern 
Acked-by: Rafael J. Wysocki 
---
 drivers/scsi/sd.c | 19 +--
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 8b6e004..6564305 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -104,7 +104,7 @@ static void sd_unlock_native_capacity(struct gendisk *disk);
 static int  sd_probe(struct device *);
 static int  sd_remove(struct device *);
 static void sd_shutdown(struct device *);
-static int sd_suspend(struct device *, pm_message_t state);
+static int sd_suspend(struct device *);
 static int sd_resume(struct device *);
 static void sd_rescan(struct device *);
 static int sd_done(struct scsi_cmnd *);
@@ -423,15 +423,23 @@ static struct class sd_disk_class = {
.dev_attrs  = sd_disk_attrs,
 };
 
+static const struct dev_pm_ops sd_pm_ops = {
+   .suspend= sd_suspend,
+   .resume = sd_resume,
+   .poweroff   = sd_suspend,
+   .restore= sd_resume,
+   .runtime_suspend= sd_suspend,
+   .runtime_resume = sd_resume,
+};
+
 static struct scsi_driver sd_template = {
.owner  = THIS_MODULE,
.gendrv = {
.name   = "sd",
.probe  = sd_probe,
.remove = sd_remove,
-   .suspend= sd_suspend,
-   .resume = sd_resume,
.shutdown   = sd_shutdown,
+   .pm = &sd_pm_ops,
},
.rescan = sd_rescan,
.done   = sd_done,
@@ -2896,7 +2904,7 @@ exit:
scsi_disk_put(sdkp);
 }
 
-static int sd_suspend(struct device *dev, pm_message_t mesg)
+static int sd_suspend(struct device *dev)
 {
struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
int ret = 0;
@@ -2911,8 +2919,7 @@ static int sd_suspend(struct device *dev, pm_message_t 
mesg)
goto done;
}
 
-   if (((mesg.event & PM_EVENT_SLEEP) || PMSG_IS_AUTO(mesg)) &&
-   sdkp->device->manage_start_stop) {
+   if (sdkp->device->manage_start_stop) {
sd_printk(KERN_NOTICE, sdkp, "Stopping disk\n");
ret = sd_start_stop_device(sdkp, 0);
}
-- 
1.7.12.21.g871e293

--
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/3] [SCSI] mvsas: fix shift in mvs_94xx_free_reg_set()

2012-11-08 Thread Xiangliang Yu

> On 11/6/12 7:06 AM, James Bottomley wrote:
> >
> > Why is this necessary?  As I read the reg set assignment code, it finds
> > a free bit in the 64 bit register and uses that ... which can never be
> > greater than 64 so there's no need for the check.
> 
> This patch just tries to be more defensive for bit(reg_set) with a
> broken reg_set value.  I agree with you that it's not that necessary.

Agree with James, and just need to do NOT operation one time

> 
> > The other two look OK (probably redone as a single patch with a stable
> > tag), but I'd like the input of the mvs people since it seems with the
> > current code, we only use 32 bit regsets and probably hang if we go over
> > that.  The bug fix is either to enable the full 64 if it works, or
> > possibly cap at 32 ... what works with all released devices?
> 
> Thanks for reviewing.  Yeah we'd better to wait for the input from
> the mvs people.

About patch 3, I check the ffz code and found it will check ~0 conditions.


--
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] virtio-scsi: Fix incorrect lock release order in virtscsi_kick_cmd

2012-11-08 Thread Wanlong Gao
On 11/09/2012 02:29 PM, Nicholas A. Bellinger wrote:
> From: Nicholas Bellinger 
> 
> This patch fixes a regression bug in virtscsi_kick_cmd() that relinquishes
> the acquired spinlocks in the incorrect order using the wrong spin_unlock
> macros, namely releasing vq->vq_lock before tgt->tgt_lock while invoking
> the calls to virtio_ring.c:virtqueue_add_buf() and friends.
> 
> This bug was originally introduced in v3.5-rc7 code with:
> 
> commit 2bd37f0fde99cbf8b78fb55f1128e8c3a63cf1da
> Author: Paolo Bonzini 
> Date:   Wed Jun 13 16:56:34 2012 +0200
> 
> [SCSI] virtio-scsi: split scatterlist per target
> 
> Go ahead and make sure that vq->vq_lock is relinquished w/ spin_unlock
> first, then release tgt->tgt_lock w/ spin_unlock_irqrestore.

Did you hit any error? I don't think this order is wrong.

Thanks,
Wanlong Gao

> 
> Cc: Paolo Bonzini 
> Cc: James Bottomley 
> Cc: Christoph Hellwig 
> Cc: sta...@vger.kernel.org
> Signed-off-by: Nicholas Bellinger 
> ---
>  drivers/scsi/virtio_scsi.c |4 ++--
>  1 files changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c
> index 595af1a..b2abb8a 100644
> --- a/drivers/scsi/virtio_scsi.c
> +++ b/drivers/scsi/virtio_scsi.c
> @@ -417,11 +417,11 @@ static int virtscsi_kick_cmd(struct 
> virtio_scsi_target_state *tgt,
>  
>   spin_lock(&vq->vq_lock);
>   ret = virtqueue_add_buf(vq->vq, tgt->sg, out_num, in_num, cmd, gfp);
> - spin_unlock(&tgt->tgt_lock);
> + spin_unlock(&vq->vq_lock);
>   if (ret >= 0)
>   ret = virtqueue_kick_prepare(vq->vq);
>  
> - spin_unlock_irqrestore(&vq->vq_lock, flags);
> + spin_unlock_irqrestore(&tgt->tgt_lock, flags);
>  
>   if (ret > 0)
>   virtqueue_notify(vq->vq);
> 

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