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