Brian King <brk...@linux.vnet.ibm.com> writes:

> I think I'd prefer if we managed to only change the download behavior
> on the new drawer rather than affecting all older SAS enclosures as well,
> since this then impacts 5802, 5803, 5886, 5887, 5888, EDR1, as well as 
> embedded
> enclosures in a whole bunch of systems going back quite a ways.
>
> What happens if we try a write buffer with the large buffer on the new drawer?
> Do we get an illegal request sense key back? If so, we could change the logic 
> to
> something like:
>
> 1. Try sending mode E, with the full buffer
> 2. If we get an Illegal Request, try sending mode E with the smaller buffer
> 3. If we get an Illegal Request, revert to mode5
>

Brian,

Thanks for your review.

I implemented the things you pointed out and changed the code to send a
single large Write Buffer for supported adapters.  This should maintain
the previous behavior for old adapters and still support ESLS.

This was tested on a ESLS and on a 5887 without any obvious regressions.

Please, let me know what you think.

-- >8 --
Subject: [PATCH v2] iprutils: Support Write buffer with smaller buffer length.

Some new enclosures, like ESLS only supports a limited buffer of 4k
bytes during SCSI Write Buffer calls. This means that doing a single
Write Buffer with mode 0Eh to download a large microcode will fail with
an Illegal Request.  This patch adds a fallback mode to the Write Buffer
command in iprlib, allowing it to limit the buffer block size to 4K, in
case the single full write fails.  If the device supports large buffers,
behavior remains unchanged, and iprlib can only issue a single write.

Signed-off-by: Gabriel Krisman Bertazi <kris...@linux.vnet.ibm.com>
---
 iprlib.c | 35 ++++++++++++++++++++++++++---------
 1 file changed, 26 insertions(+), 9 deletions(-)

diff --git a/iprlib.c b/iprlib.c
index 70e2924..a02dfed 100644
--- a/iprlib.c
+++ b/iprlib.c
@@ -4655,8 +4655,8 @@ int ipr_resume_device_bus(struct ipr_dev *dev,
  * Returns:
  *   0 if success / non-zero on failure
  **/
-static int __ipr_write_buffer(struct ipr_dev *dev, u8 mode, void *buff, int 
length,
-                             struct sense_data_t *sense_data)
+static int __ipr_write_buffer(struct ipr_dev *dev, u8 mode, void *buff,
+                             int offset, int length, struct sense_data_t 
*sense_data)
 {
        u32 direction = length ? SG_DXFER_TO_DEV : SG_DXFER_NONE;
        u8 cdb[IPR_CCB_CDB_LEN];
@@ -4670,6 +4670,9 @@ static int __ipr_write_buffer(struct ipr_dev *dev, u8 
mode, void *buff, int leng
 
        cdb[0] = WRITE_BUFFER;
        cdb[1] = mode;
+       cdb[3] = (offset & 0xff0000) >> 16;
+       cdb[4] = (offset & 0x00ff00) >> 8;
+       cdb[5] = (offset & 0x0000ff);
        cdb[6] = (length & 0xff0000) >> 16;
        cdb[7] = (length & 0x00ff00) >> 8;
        cdb[8] = length & 0x0000ff;
@@ -4721,6 +4724,9 @@ int ipr_write_buffer(struct ipr_dev *dev, void *buff, int 
length)
        int sas_ses = 0;
        int sas_ses_retries = 5;
        int mode5 = 1;
+       u32 write_len = 0;
+       u32 offset;
+       u32 write_buffer_chunk_sz = length;
 
        ENTER;
        if ((rc = ipr_get_dev_attr(dev, &attr))) {
@@ -4745,9 +4751,14 @@ int ipr_write_buffer(struct ipr_dev *dev, void *buff, 
int length)
        }
 
        if (sas_ses) {
-               if (!mode5) {
+               for (offset = 0; offset < length && !mode5; offset += 
write_len) {
+                       write_len = write_buffer_chunk_sz;
+                       if (offset + write_len > length)
+                               write_len = length - offset;
+
                        for (i = 0; i < (sas_ses_retries + 1); i++) {
-                               rc = __ipr_write_buffer(dev, 0x0e, buff, 
length, &sense_data);
+                               rc = __ipr_write_buffer(dev, 0x0e, buff + 
offset, offset,
+                                                       write_len, &sense_data);
                                if (!rc) {
                                        break;
                                } else if (rc && sense_data.sense_key == 
UNIT_ATTENTION &&
@@ -4755,7 +4766,13 @@ int ipr_write_buffer(struct ipr_dev *dev, void *buff, 
int length)
                                           sense_data.add_sense_code_qual == 
0x00) {
                                        continue;
                                } else if (rc && sense_data.sense_key == 
ILLEGAL_REQUEST) {
-                                       mode5 = 1;
+                                       if (write_buffer_chunk_sz == 4096) {
+                                               mode5 = 1;
+                                       } else {
+                                               /* Attempt 4k write */
+                                               write_buffer_chunk_sz = 4096;
+                                               write_len = 0;
+                                       }
                                        break;
                                } else if (rc) {
                                        goto out;
@@ -4773,9 +4790,9 @@ int ipr_write_buffer(struct ipr_dev *dev, void *buff, int 
length)
 
                for (i = 0; i < (sas_ses_retries + 1); i++) {
                        if (mode5)
-                               rc = __ipr_write_buffer(dev, 5, buff, length, 
&sense_data);
+                               rc = __ipr_write_buffer(dev, 5, buff, 0, 
length, &sense_data);
                        else
-                               rc = __ipr_write_buffer(dev, 0x0f, NULL, 0, 
&sense_data);
+                               rc = __ipr_write_buffer(dev, 0x0f, NULL, 0, 0, 
&sense_data);
 
                        if (rc && sense_data.sense_key == UNIT_ATTENTION &&
                                   sense_data.add_sense_code == 0x29 &&
@@ -4791,7 +4808,7 @@ int ipr_write_buffer(struct ipr_dev *dev, void *buff, int 
length)
                        goto out_resume;
                }
        } else {
-               if ((rc = __ipr_write_buffer(dev, 5, buff, length, 
&sense_data)))
+               if ((rc = __ipr_write_buffer(dev, 5, buff, 0, length, 
&sense_data)))
                        goto out;
        }
 
@@ -5671,7 +5688,7 @@ int ipr_set_ses_mode(struct ipr_dev *dev, int mode) {
        struct sense_data_t sense_data;
        u8 buff = (u8)mode;
 
-       rc = __ipr_write_buffer(dev, 0x1f, &buff, sizeof(buff), &sense_data);
+       rc = __ipr_write_buffer(dev, 0x1f, &buff, 0, sizeof(buff), &sense_data);
        return rc;
 }
 
-- 
2.1.0


------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785471&iu=/4140
_______________________________________________
Iprdd-devel mailing list
Iprdd-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/iprdd-devel

Reply via email to