Re: [PATCH 2/2] m68k/amiga - Zorro ESP: new zorro_esp.c
2018-03-04 0:54 GMT+01:00 Michael Schmitz : > +static struct zorro_device_id zorro_esp_zorro_tbl[] = { > + { > + .id = ZORRO_PROD_PHASE5_BLIZZARD_1220_CYBERSTORM, > + .driver_data = (unsigned long)&zorro_esp_driver_data[0], > + }, > + { > + .id = > ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060, > + .driver_data = (unsigned long)&zorro_esp_driver_data[0], > + }, > + { > + .id = ZORRO_PROD_PHASE5_CYBERSTORM_MK_II, > + .driver_data = (unsigned long)&zorro_esp_driver_data[1], > + }, > + { > + .id = ZORRO_PROD_PHASE5_BLIZZARD_2060, > + .driver_data = (unsigned long)&zorro_esp_driver_data[2], > + }, > + { > + .id = ZORRO_PROD_PHASE5_BLIZZARD_1230_IV_1260, > + .driver_data = (unsigned long)&zorro_esp_driver_data[3], > + }, > + { > + .id = > ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060, > + .driver_data = (unsigned long)&zorro_esp_driver_data[4], > + }, > + { 0 } > +}; > +MODULE_DEVICE_TABLE(zorro, zorro_esp_zorro_tbl); The ID ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060 is used at index 1 and index 5. I'm guessing only the first one will be detected. Regards, Kars.
[PATCH 0/4] SCSI-HPSA: Adjustments for hpsa_big_passthru_ioctl()
From: Markus Elfring Date: Mon, 5 Mar 2018 09:14:32 +0100 A few update suggestions were taken into account from static source code analysis. Markus Elfring (4): Use memdup_user() rather than duplicating its implementation Less function calls in hpsa_big_passthru_ioctl() after error detection Delete an unnecessary initialisation Move a variable assignment drivers/scsi/hpsa.c | 44 +--- 1 file changed, 21 insertions(+), 23 deletions(-) -- 2.16.2
[PATCH 1/4] scsi: hpsa: Use memdup_user() rather than duplicating its implementation
From: Markus Elfring Date: Sun, 4 Mar 2018 21:19:52 +0100 * Reuse existing functionality from memdup_user() instead of keeping duplicate source code. This issue was detected by using the Coccinelle software. * Return directly after this function call failed at the beginning. Signed-off-by: Markus Elfring --- drivers/scsi/hpsa.c | 13 - 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 5293e6827ce5..b35248becef9 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -6390,15 +6390,10 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp) return -EINVAL; if (!capable(CAP_SYS_RAWIO)) return -EPERM; - ioc = kmalloc(sizeof(*ioc), GFP_KERNEL); - if (!ioc) { - status = -ENOMEM; - goto cleanup1; - } - if (copy_from_user(ioc, argp, sizeof(*ioc))) { - status = -EFAULT; - goto cleanup1; - } + ioc = memdup_user(argp, sizeof(*ioc)); + if (IS_ERR(ioc)) + return PTR_ERR(ioc); + if ((ioc->buf_size < 1) && (ioc->Request.Type.Direction != XFER_NONE)) { status = -EINVAL; -- 2.16.2
[PATCH 2/4] scsi: hpsa: Less function calls in hpsa_big_passthru_ioctl() after error detection
From: Markus Elfring Date: Sun, 4 Mar 2018 22:00:19 +0100 The function "kfree" was called in a few cases by the hpsa_big_passthru_ioctl() function during error handling even if the passed variable contained a null pointer. * Adjust jump targets. * Delete two initialisations and a check (for the local variable "buff") which became unnecessary with this refactoring. Signed-off-by: Markus Elfring --- drivers/scsi/hpsa.c | 26 ++ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index b35248becef9..45177ead811f 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -6377,8 +6377,8 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp) { BIG_IOCTL_Command_struct *ioc; struct CommandList *c; - unsigned char **buff = NULL; - int *buff_size = NULL; + unsigned char **buff; + int *buff_size; u64 temp64; BYTE sg_used = 0; int status = 0; @@ -6397,26 +6397,26 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp) if ((ioc->buf_size < 1) && (ioc->Request.Type.Direction != XFER_NONE)) { status = -EINVAL; - goto cleanup1; + goto free_ioc; } /* Check kmalloc limits using all SGs */ if (ioc->malloc_size > MAX_KMALLOC_SIZE) { status = -EINVAL; - goto cleanup1; + goto free_ioc; } if (ioc->buf_size > ioc->malloc_size * SG_ENTRIES_IN_CMD) { status = -EINVAL; - goto cleanup1; - } - buff = kzalloc(SG_ENTRIES_IN_CMD * sizeof(char *), GFP_KERNEL); - if (!buff) { - status = -ENOMEM; - goto cleanup1; + goto free_ioc; } buff_size = kmalloc(SG_ENTRIES_IN_CMD * sizeof(int), GFP_KERNEL); if (!buff_size) { status = -ENOMEM; - goto cleanup1; + goto free_ioc; + } + buff = kzalloc(SG_ENTRIES_IN_CMD * sizeof(char *), GFP_KERNEL); + if (!buff) { + status = -ENOMEM; + goto free_buff_size; } left = ioc->buf_size; data_ptr = ioc->buf; @@ -6501,14 +6501,16 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp) cleanup0: cmd_free(h, c); cleanup1: - if (buff) { + { int i; for (i = 0; i < sg_used; i++) kfree(buff[i]); kfree(buff); } +free_buff_size: kfree(buff_size); +free_ioc: kfree(ioc); return status; } -- 2.16.2
[PATCH 3/4] scsi: hpsa: Delete an unnecessary initialisation in hpsa_big_passthru_ioctl()
From: Markus Elfring Date: Sun, 4 Mar 2018 22:02:10 +0100 The variable "status" will be set to an appropriate value a bit later. Thus omit the explicit initialisation at the beginning. Signed-off-by: Markus Elfring --- drivers/scsi/hpsa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 45177ead811f..86d371ab39e7 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -6381,7 +6381,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp) int *buff_size; u64 temp64; BYTE sg_used = 0; - int status = 0; + int status; u32 left; u32 sz; BYTE __user *data_ptr; -- 2.16.2
[PATCH 4/4] scsi: hpsa: Move a variable assignment in hpsa_big_passthru_ioctl()
From: Markus Elfring Date: Sun, 4 Mar 2018 22:16:05 +0100 Move an assignment for the local variable "sg_used" so that its setting will only be performed after corresponding memory allocations succeeded by this function. Signed-off-by: Markus Elfring --- drivers/scsi/hpsa.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 86d371ab39e7..bb6df194ac31 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -6380,7 +6380,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp) unsigned char **buff; int *buff_size; u64 temp64; - BYTE sg_used = 0; + BYTE sg_used; int status; u32 left; u32 sz; @@ -6420,6 +6420,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp) } left = ioc->buf_size; data_ptr = ioc->buf; + sg_used = 0; while (left) { sz = (left > ioc->malloc_size) ? ioc->malloc_size : left; buff_size[sg_used] = sz; -- 2.16.2
Re: [PATCH 2/2] m68k/amiga - Zorro ESP: new zorro_esp.c
Hi Michael, On Sun, Mar 4, 2018 at 12:54 AM, Michael Schmitz wrote: > From: Michael Schmitz > > New combined SCSI driver for all ESP based Zorro SCSI boards for > m68k Amiga. Thanks for your patch! > --- /dev/null > +++ b/drivers/scsi/zorro_esp.c > @@ -0,0 +1,785 @@ > +static struct zorro_driver_data { > + const char *name; > + unsigned long offset; > + unsigned long dma_offset; > + int absolute; > + int zorro3; /* offset is absolute address */ zorro3 is unused. > +} zorro_esp_driver_data[] = { > + { .name = "CyberStormI", .offset = 0xf400, .dma_offset = 0xf800, > + .absolute = 0, .zorro3 = 0 }, > + { .name = "CyberStormII", .offset = 0x1ff03, .dma_offset = 0x1ff43, > + .absolute = 0, .zorro3 = 0 }, > + { .name = "Blizzard 2060", .offset = 0x1ff00, .dma_offset = 0x1ffe0, > + .absolute = 0, .zorro3 = 0 }, > + { .name = "Blizzard 1230", .offset = 0x8000, .dma_offset = 0x1, > + .absolute = 0, .zorro3 = 0 }, > + { .name = "Blizzard 1230II", .offset = 0x1, .dma_offset = 0x10021, > + .absolute = 0, .zorro3 = 0 }, > + { .name = "Fastlane", .offset = 0x101, .dma_offset = 0x141, > + .absolute = 0, .zorro3 = 1 }, > + { 0 } I think it's better to not use an array here, but individual structs: static struct zorro_driver_data cyberstorm_data = ... static struct zorro_driver_data cyberstorm2_data = ... ... That makes it easier to review the references from zorro_esp_zorro_tbl[] below. > +}; > + > +static struct zorro_device_id zorro_esp_zorro_tbl[] = { > + { > + .id = ZORRO_PROD_PHASE5_BLIZZARD_1220_CYBERSTORM, > + .driver_data = (unsigned long)&zorro_esp_driver_data[0], > + }, [...] > +static unsigned char ctrl_data;/* Keep backup of the stuff written > +* to ctrl_reg. Always write a copy > +* to this register when writing to > +* the hardware register! > +*/ This should be part of the device's zorro_esp_priv. > +/* > + * private data used for PIO > + */ > +struct zorro_esp_priv { > + struct esp *esp; > + int error; > +} zorro_esp_private_data[8]; Dynamic allocation, please. > +static void zorro_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count, > +u32 dma_count, int write, u8 cmd) > +{ > + struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp); > + u8 __iomem *fifo = esp->regs + ESP_FDATA * 16; > + u8 phase = esp->sreg & ESP_STAT_PMASK; > + > + cmd &= ~ESP_CMD_DMA; > + zep->error = 0; > + > + /* We are passed DMA addresses i.e. physical addresses, but must use > +* kernel virtual addresses here, so remap to virtual. This is easy > +* enough for the case of residual bytes of an extended message in > +* transfer - we know the address must be esp->command_block_dma. > +* In other cases, hope that phys_to_virt() works ... > +*/ > + if (addr == esp->command_block_dma) > + addr = (u32) esp->command_block; > + else > + addr = (u32) phys_to_virt(addr); To avoid having a need for phys_to_virt(), you should remember the addresses passed to/returned from dma_map_*(). if you assign the address to a different variable with the proper type, you don't need the cast below + if (write) { + u8 *dst = (u8 *)addr; ... here. > + } else { The read case doesn't use addr? > +static void zorro_esp_send_blz1230_dma_cmd(struct esp *esp, u32 addr, > + u32 esp_count, u32 dma_count, int write, u8 cmd) > +{ > + struct blz1230_dma_registers *dregs = > + (struct blz1230_dma_registers *) (esp->dma_regs); > + u8 phase = esp->sreg & ESP_STAT_PMASK; > + > + if (phase == ESP_MIP) { > + zorro_esp_send_pio_cmd(esp, addr, esp_count, > + dma_count, write, cmd); > + return; > + } > + > + BUG_ON(!(cmd & ESP_CMD_DMA)); > + > + if (write) > + cache_clear(addr, esp_count); > + else > + cache_push(addr, esp_count); dma_sync_*() > +static int zorro_esp_init_one(struct zorro_dev *z, > + const struct zorro_device_id *ent) > +{ > + struct scsi_host_template *tpnt = &scsi_esp_template; > + struct Scsi_Host *host; > + struct esp *esp; > + struct zorro_driver_data *zdd; > + struct zorro_esp_priv *zep; > + unsigned long board, ioaddr, dmaaddr; > + int err = -ENOMEM; Initialization not needed. > + > + board = zorro_resource_start(z); > + zdd = (struct zorro_driver_data *)ent->driver_data; > + > + pr_info(PFX "%s found at address 0x%lx.\n", zdd->name, board); >
Re: [PATCH 1/1] scsi: ufs: Add support for Auto-Hibernate Idle Timer
On 19/02/18 08:35, Adrian Hunter wrote: > On 18/02/18 11:45, Avri Altman wrote: >> >> >>> -Original Message- >>> From: linux-scsi-ow...@vger.kernel.org [mailto:linux-scsi- >>> ow...@vger.kernel.org] On Behalf Of Adrian Hunter >>> Sent: Friday, February 16, 2018 2:01 PM >>> To: Vinayak Holikatti ; Martin K. Petersen >>> ; James E.J. Bottomley >>> >>> Cc: Stanislav Nijnikov ; Jaegeuk Kim >>> ; Bart Van Assche ; linux- >>> s...@vger.kernel.org; linux-ker...@vger.kernel.org; Michal Potomski >>> ; Szymon Mielczarek >>> >>> Subject: [PATCH 1/1] scsi: ufs: Add support for Auto-Hibernate Idle Timer >>> >>> UFS host controllers may support an autonomous power management >>> feature called the Auto-Hibernate Idle Timer. The timer is set to the number >>> of microseconds of idle time before the UFS host controller will >>> autonomously put the link into Hibernate state. That will save power at the >>> expense of increased latency. Any access to the host controller interface >>> registers will automatically put the link out of Hibernate state. So once >>> configured, the feature is transparent to the driver. >>> >>> Expose the Auto-Hibernate Idle Timer value via SysFS to allow users to >>> choose between power efficiency or lower latency. Set a default value of >>> 150 ms. >>> >>> Signed-off-by: Adrian Hunter >>> --- >>> Documentation/ABI/testing/sysfs-driver-ufs | 15 ++ >>> drivers/scsi/ufs/ufs-sysfs.c | 77 >>> ++ >>> drivers/scsi/ufs/ufshcd.c | 26 ++ >>> drivers/scsi/ufs/ufshcd.h | 3 ++ >>> drivers/scsi/ufs/ufshci.h | 7 +++ >>> 5 files changed, 128 insertions(+) >>> >>> diff --git a/Documentation/ABI/testing/sysfs-driver-ufs >>> b/Documentation/ABI/testing/sysfs-driver-ufs >>> index 07f1c2f8dbfc..c7f9441079eb 100644 >>> --- a/Documentation/ABI/testing/sysfs-driver-ufs >>> +++ b/Documentation/ABI/testing/sysfs-driver-ufs >>> @@ -1,3 +1,18 @@ >>> +What: /sys/bus/*/drivers/ufshcd/*/auto_hibern8 >>> +Date: February 2018 >>> +Contact: linux-scsi@vger.kernel.org >>> +Description: >>> + This file contains the auto-hibernate idle timer setting of a >>> + UFS host controller. A value of '-1' means auto-hibernate is >>> not >>> + supported. A value of '0' means auto-hibernate is not >>> enabled. >>> + Otherwise the value is the number of microseconds of idle >>> time >>> + before the UFS host controller will autonomously put the link >>> + into hibernate state. That will save power at the expense of >>> + increased latency. Note that the hardware supports 10-bit >>> values >>> + with a power-of-ten multiplier which allows a maximum >>> value of >>> + 10230. Refer to the UFS Host Controller Interface >>> + specification for more details. >>> + >>> What: >>> /sys/bus/platform/drivers/ufshcd/*/device_descriptor/device_type >>> Date: February 2018 >>> Contact: Stanislav Nijnikov >>> diff --git a/drivers/scsi/ufs/ufs-sysfs.c b/drivers/scsi/ufs/ufs-sysfs.c >>> index >>> cd7174d2d225..a0e38776dc92 100644 SNIP >>> @@ -7843,6 +7863,12 @@ int ufshcd_init(struct ufs_hba *hba, void >>> __iomem *mmio_base, unsigned int irq) >>> UFS_SLEEP_PWR_MODE, >>> UIC_LINK_HIBERN8_STATE); >>> >>> + /* Set the default auto-hiberate idle timer value to 150 ms */ >> Your commit said you are setting an idle timer in microseconds, Better use >> usec to avoid confusion? > > As the SysFS documentation says "Note that the hardware supports 10-bit > values with a power-of-ten multiplier ... Refer to the UFS Host Controller > Interface specification for more details.", so 150,000 us is still a value > of 150 with a power-of-ten multiplier of 3. Are there any other comments?
Re: [PATCH v2 1/8] dt-bindings: scsi: hisi_sas: add an property of signal attenuation
On Fri, Mar 2, 2018 at 10:10 AM, John Garry wrote: > On 02/03/2018 15:57, Rob Herring wrote: >> >> On Fri, Mar 2, 2018 at 9:06 AM, John Garry wrote: >>> >>> > From: Xiaofei Tan >>> > >>> > For some new boards with hip07 chipset we are required to >>> > set PHY config registers differently. The hw property which >>> > determines how to set these registers is in the PHY signal >>> > attenuation readings. >>> > >>> > This patch add an devicetree property, hisi-signal-attenuation, >>> > which is used to describe the signal attenuation of an board. >>> > >>> > Cc: Rob Herring >>> > Cc: Mark Rutland >>> > Signed-off-by: Xiaofei Tan >>> > Signed-off-by: John Garry >>> > --- >>> > Documentation/devicetree/bindings/scsi/hisilicon-sas.txt | 7 +++ >>> > 1 file changed, 7 insertions(+) >>> > >>> > diff --git a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt >>> > b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt >>> > index df3bef7..6f6876a 100644 >>> > --- a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt >>> > +++ b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt >>> > @@ -53,6 +53,13 @@ Main node required properties: >>> > Optional main node properties: >>> > - hip06-sas-v2-quirk-amt : when set, indicates that the v2 controller >>> > has the >>> > "am-max-transmissions" limitation. >>> > + - hisi-signal-attenuation : array of 3 32-bit values, containing >>> > de-emphasis, >> >> The format for vendor prefixes is: ,property-name >> >> And should only be ones defined in vendor-prefixes.txt > > > Hi Rob, > > To save a v4, that would be "hisilicon,signal-attenuation", right? Right. Rob
RE: [PATCH V3 1/8] scsi: hpsa: fix selection of reply queue
> -Original Message- > From: Kashyap Desai [mailto:kashyap.de...@broadcom.com] > Sent: Monday, March 05, 2018 1:24 AM > To: Laurence Oberman ; Don Brace > ; Ming Lei > Cc: Jens Axboe ; linux-bl...@vger.kernel.org; Christoph > Hellwig ; Mike Snitzer ; linux- > s...@vger.kernel.org; Hannes Reinecke ; Arun Easi > ; Omar Sandoval ; Martin K . > Petersen ; James Bottomley > ; Christoph Hellwig ; > Peter Rivera ; Meelis Roos > Subject: RE: [PATCH V3 1/8] scsi: hpsa: fix selection of reply queue > > EXTERNAL EMAIL > > > > -Original Message- > > From: Laurence Oberman [mailto:lober...@redhat.com] > > Sent: Saturday, March 3, 2018 3:23 AM > > To: Don Brace; Ming Lei > > Cc: Jens Axboe; linux-bl...@vger.kernel.org; Christoph Hellwig; Mike > > Snitzer; > > linux-scsi@vger.kernel.org; Hannes Reinecke; Arun Easi; Omar Sandoval; > > Martin K . Petersen; James Bottomley; Christoph Hellwig; Kashyap Desai; > > Peter > > Rivera; Meelis Roos > > Subject: Re: [PATCH V3 1/8] scsi: hpsa: fix selection of reply queue > > > > On Fri, 2018-03-02 at 15:03 +, Don Brace wrote: > > > > -Original Message- > > > > From: Laurence Oberman [mailto:lober...@redhat.com] > > > > Sent: Friday, March 02, 2018 8:09 AM > > > > To: Ming Lei > > > > Cc: Don Brace ; Jens Axboe > > > k>; > > > > linux-bl...@vger.kernel.org; Christoph Hellwig ; > > > > Mike Snitzer ; linux-scsi@vger.kernel.org; > > > > Hannes Reinecke ; Arun Easi ; > > > > Omar Sandoval ; Martin K . Petersen > > > > ; James Bottomley > > > > ; Christoph Hellwig > > > > ; Kashyap Desai ; Peter > > > > Rivera ; Meelis Roos > > > > Subject: Re: [PATCH V3 1/8] scsi: hpsa: fix selection of reply queue > > > > > > > > EXTERNAL EMAIL > > > > > > > > > > > > On Fri, 2018-03-02 at 10:16 +0800, Ming Lei wrote: > > > > > On Thu, Mar 01, 2018 at 04:19:34PM -0500, Laurence Oberman wrote: > > > > > > On Thu, 2018-03-01 at 14:01 -0500, Laurence Oberman wrote: > > > > > > > On Thu, 2018-03-01 at 16:18 +, Don Brace wrote: > > > > > > > > > -Original Message- > > > > > > > > > From: Ming Lei [mailto:ming@redhat.com] > > > > > > > > > Sent: Tuesday, February 27, 2018 4:08 AM > > > > > > > > > To: Jens Axboe ; linux-block@vger.kernel > > > > > > > > > .org ; Christoph Hellwig ; Mike Snitzer > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > Cc: linux-scsi@vger.kernel.org; Hannes Reinecke > > > > > > > > e.de > > > > > > > > > > ; > > > > > > > > > > > > > > > > > > Arun Easi > > > > > > > > > ; Omar Sandoval ; > > > > > > > > > Martin K . > > > > > > > > > Petersen ; James Bottomley > > > > > > > > > ; Christoph Hellwig > > > > > > > > > ; Don Brace ; > > > > > > > > > Kashyap Desai ; Peter Rivera > > > > > > > > > > > > > > > > > om>; > > > > > > > > > Laurence Oberman ; Ming Lei > > > > > > > > > ; Meelis Roos > > > > > > > > > Subject: [PATCH V3 1/8] scsi: hpsa: fix selection of reply > > > > > > > > > queue > > > > > > > > > > > > > > > > > > > Seems Don run into IO failure without blk-mq, could you run your > > > > > tests again in legacy mode? > > > > > > > > > > Thanks, > > > > > Ming > > > > > > > > Hello Ming > > > > I ran multiple passes on Legacy and still see no issues in my test > > > > bed > > > > Tests ran all weekend without issues. > > > > BOOT_IMAGE=/vmlinuz-4.16.0-rc2.ming+ root=UUID=43f86d71-b1bf- > 4789- > > > > a28e- > > > > 21c6ddc90195 ro crashkernel=256M@64M log_buf_len=64M > > > > console=ttyS1,115200n8 > > > > > > > > HEAD of the git kernel I am using > > > > > > > > 694e16f scsi: megaraid: improve scsi_mq performance via .host_tagset > > > > 793686c scsi: hpsa: improve scsi_mq performance via .host_tagset > > > > 60d5b36 block: null_blk: introduce module parameter of 'g_host_tags' > > > > 8847067 scsi: Add template flag 'host_tagset' > > > > a8fbdd6 blk-mq: introduce BLK_MQ_F_HOST_TAGS 4710fab blk-mq: > > > > introduce 'start_tag' field to 'struct blk_mq_tags' > > > > 09bb153 scsi: megaraid_sas: fix selection of reply queue > > > > 52700d8 scsi: hpsa: fix selection of reply queue > > > > > > I checkout out Linus's tree (4.16.0-rc3+) and re-applied the above > > > patches. > > > I and have been running 24 hours with no issues. > > > Evidently my forked copy was corrupted. > > > > > > So, my I/O testing has gone well. > > > > > > I'll run some performance numbers next. > > > > > > Thanks, > > > Don > > > > Unless Kashyap is not happy we need to consider getting this in to Linus > > now > > because we are seeing HPE servers that keep hanging now with the original > > commit now upstream. > > > > Kashyap, are you good with the v3 patchset or still concerned with > > performance. I was getting pretty good IOPS/sec to individual SSD drives > > set > > up as jbod devices on the megaraid_sas. > > Laurence - > Did you find difference with/without the patch ? What was IOPs number with > and without patch. > It is not urgent feature, so I would like to take some time to get BRCM's > performance team involve
[PATCH v3 5/8] scsi: hisi_sas: increase timer expire of internal abort task
From: Xiaofei Tan The current 110ms expiry time is not long enough for the internal abort task. The reason is that the internal abort task could be blocked in HW if the HW is retrying to set up link. The internal abort task will be executed only when the retry process finished. The maximum time is 5s for the retry of setting up link. So, the timer expire should be more than 5s. This patch increases it from 110ms to 6s. Signed-off-by: Xiaofei Tan Signed-off-by: John Garry --- drivers/scsi/hisi_sas/hisi_sas_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 9d16372..9ff8790 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -871,6 +871,7 @@ static void hisi_sas_tmf_timedout(struct timer_list *t) #define TASK_TIMEOUT 20 #define TASK_RETRY 3 +#define INTERNAL_ABORT_TIMEOUT 6 static int hisi_sas_exec_internal_tmf_task(struct domain_device *device, void *parameter, u32 para_len, struct hisi_sas_tmf_task *tmf) @@ -1574,7 +1575,7 @@ static int hisi_sas_query_task(struct sas_task *task) task->task_proto = device->tproto; task->task_done = hisi_sas_task_done; task->slow_task->timer.function = hisi_sas_tmf_timedout; - task->slow_task->timer.expires = jiffies + msecs_to_jiffies(110); + task->slow_task->timer.expires = jiffies + INTERNAL_ABORT_TIMEOUT*HZ; add_timer(&task->slow_task->timer); res = hisi_sas_internal_abort_task_exec(hisi_hba, sas_dev->device_id, -- 1.9.1
[PATCH v3 2/8] scsi: hisi_sas: support the property of signal attenuation for v2 hw
From: Xiaofei Tan The register SAS_PHY_CTRL is configured according to signal quality. The signal quality is calculated by signal attenuation of hardware physical link. It may be different for different PCB layout. So, in order to give better support to new board, this patch add support to reading the devicetree property, "hisilicon,signal-attenuation". Of course, we still keep an default value in driver to adapt old board. Signed-off-by: Xiaofei Tan Signed-off-by: John Garry --- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 39 +- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 4ccb61e..42b3fd6 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -406,6 +406,17 @@ struct hisi_sas_err_record_v2 { __le32 dma_rx_err_type; }; +struct signal_attenuation_s { + u32 de_emphasis; + u32 preshoot; + u32 boost; +}; + +struct sig_atten_lu_s { + const struct signal_attenuation_s *att; + u32 sas_phy_ctrl; +}; + static const struct hisi_sas_hw_error one_bit_ecc_errors[] = { { .irq_msk = BIT(SAS_ECC_INTR_DQE_ECC_1B_OFF), @@ -1130,9 +1141,16 @@ static void phys_try_accept_stp_links_v2_hw(struct hisi_hba *hisi_hba) } } +static const struct signal_attenuation_s x6000 = {9200, 0, 10476}; +static const struct sig_atten_lu_s sig_atten_lu[] = { + { &x6000, 0x3016a68 }, +}; + static void init_reg_v2_hw(struct hisi_hba *hisi_hba) { struct device *dev = hisi_hba->dev; + u32 sas_phy_ctrl = 0x30b9908; + u32 signal[3]; int i; /* Global registers init */ @@ -1176,9 +1194,28 @@ static void init_reg_v2_hw(struct hisi_hba *hisi_hba) hisi_sas_write32(hisi_hba, AXI_AHB_CLK_CFG, 1); hisi_sas_write32(hisi_hba, HYPER_STREAM_ID_EN_CFG, 1); + /* Get sas_phy_ctrl value to deal with TX FFE issue. */ + if (!device_property_read_u32_array(dev, "hisilicon,signal-attenuation", + signal, ARRAY_SIZE(signal))) { + for (i = 0; i < ARRAY_SIZE(sig_atten_lu); i++) { + const struct sig_atten_lu_s *lookup = &sig_atten_lu[i]; + const struct signal_attenuation_s *att = lookup->att; + + if ((signal[0] == att->de_emphasis) && + (signal[1] == att->preshoot) && + (signal[2] == att->boost)) { + sas_phy_ctrl = lookup->sas_phy_ctrl; + break; + } + } + + if (i == ARRAY_SIZE(sig_atten_lu)) + dev_warn(dev, "unknown signal attenuation values, using default PHY ctrl config\n"); + } + for (i = 0; i < hisi_hba->n_phy; i++) { hisi_sas_phy_write32(hisi_hba, i, PROG_PHY_LINK_RATE, 0x855); - hisi_sas_phy_write32(hisi_hba, i, SAS_PHY_CTRL, 0x30b9908); + hisi_sas_phy_write32(hisi_hba, i, SAS_PHY_CTRL, sas_phy_ctrl); hisi_sas_phy_write32(hisi_hba, i, SL_TOUT_CFG, 0x7d7d7d7d); hisi_sas_phy_write32(hisi_hba, i, SL_CONTROL, 0x0); hisi_sas_phy_write32(hisi_hba, i, TXID_AUTO, 0x2); -- 1.9.1
[PATCH v3 8/8] scsi: hisi_sas: Code cleanup and minor bug fixes
From: Xiang Chen The patch does some code cleanup and fixes some small bugs: - Correct return status of phy_up_v3_hw() - Add static for function phy_get_max_linkrate_v3_hw() - Change exception return status when no reset method - Change magic value to ts->stat in slot_complete_vx_hw() - Remove unnecessary check for dev_is_sata() - Fix some issues of alignment and indents (Authored by Xiaofei Tan in another patch, but added here to be practical) Signed-off-by: Xiaofei Tan Signed-off-by: Xiang Chen Signed-off-by: John Garry --- drivers/scsi/hisi_sas/hisi_sas_main.c | 14 +++--- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 4 +++- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 10 ++ drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 16 +--- 4 files changed, 25 insertions(+), 19 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index dff9723..49c1fa6 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -33,7 +33,7 @@ u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction) case ATA_CMD_FPDMA_RECV: case ATA_CMD_FPDMA_SEND: case ATA_CMD_NCQ_NON_DATA: - return HISI_SAS_SATA_PROTOCOL_FPDMA; + return HISI_SAS_SATA_PROTOCOL_FPDMA; case ATA_CMD_DOWNLOAD_MICRO: case ATA_CMD_ID_ATA: @@ -45,7 +45,7 @@ u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction) case ATA_CMD_WRITE_LOG_EXT: case ATA_CMD_PIO_WRITE: case ATA_CMD_PIO_WRITE_EXT: - return HISI_SAS_SATA_PROTOCOL_PIO; + return HISI_SAS_SATA_PROTOCOL_PIO; case ATA_CMD_DSM: case ATA_CMD_DOWNLOAD_MICRO_DMA: @@ -64,7 +64,7 @@ u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction) case ATA_CMD_WRITE_LOG_DMA_EXT: case ATA_CMD_WRITE_STREAM_DMA_EXT: case ATA_CMD_ZAC_MGMT_IN: - return HISI_SAS_SATA_PROTOCOL_DMA; + return HISI_SAS_SATA_PROTOCOL_DMA; case ATA_CMD_CHK_POWER: case ATA_CMD_DEV_RESET: @@ -77,21 +77,21 @@ u8 hisi_sas_get_ata_protocol(struct host_to_dev_fis *fis, int direction) case ATA_CMD_STANDBY: case ATA_CMD_STANDBYNOW1: case ATA_CMD_ZAC_MGMT_OUT: - return HISI_SAS_SATA_PROTOCOL_NONDATA; + return HISI_SAS_SATA_PROTOCOL_NONDATA; default: { if (fis->command == ATA_CMD_SET_MAX) { switch (fis->features) { case ATA_SET_MAX_PASSWD: case ATA_SET_MAX_LOCK: - return HISI_SAS_SATA_PROTOCOL_PIO; + return HISI_SAS_SATA_PROTOCOL_PIO; case ATA_SET_MAX_PASSWD_DMA: case ATA_SET_MAX_UNLOCK_DMA: - return HISI_SAS_SATA_PROTOCOL_DMA; + return HISI_SAS_SATA_PROTOCOL_DMA; default: - return HISI_SAS_SATA_PROTOCOL_NONDATA; + return HISI_SAS_SATA_PROTOCOL_NONDATA; } } if (direction == DMA_NONE) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 8dd0e6a6..520ba69 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -651,8 +651,10 @@ static int reset_hw_v1_hw(struct hisi_hba *hisi_hba) dev_err(dev, "De-reset failed\n"); return -EIO; } - } else + } else { dev_warn(dev, "no reset method\n"); + return -EIO; + } return 0; } diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index bd1a48a..69c4dd1 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -1095,8 +1095,10 @@ static int reset_hw_v2_hw(struct hisi_hba *hisi_hba) dev_err(dev, "SAS de-reset fail.\n"); return -EIO; } - } else - dev_warn(dev, "no reset method\n"); + } else { + dev_err(dev, "no reset method\n"); + return -EIO; + } return 0; } @@ -2408,7 +2410,7 @@ static void slot_err_v2_hw(struct hisi_hba *hisi_hba, spin_lock_irqsave(&hisi_hba->lock, flags); hisi_sas_slot_task_free(hisi_hba, task, slot); spin_unlock_irqrestore(&hisi_hba->lock, flags); - return -1; + return ts->stat; } if (unlikely(!sas_dev)) { @@ -2667,7 +2669,7 @@ static int prep_abort_v2_hw(struct hisi_hba *hisi_hba, /* dw0 */ hdr->dw0 = cpu_to_le32((5 << CMD_HDR_CMD_OFF) | /*abort*/ (port->id << CMD_HDR_PORT_OF
[PATCH v3 1/8] dt-bindings: scsi: hisi_sas: add an property of signal attenuation
From: Xiaofei Tan For some new boards with hip07 chipset we are required to set PHY config registers differently. The hw property which determines how to set these registers is in the PHY signal attenuation readings. This patch add an devicetree property, "hisilicon,signal-attenuation", which is used to describe the signal attenuation of an board. Cc: Rob Herring Cc: Mark Rutland Signed-off-by: Xiaofei Tan Signed-off-by: John Garry --- Documentation/devicetree/bindings/scsi/hisilicon-sas.txt | 7 +++ 1 file changed, 7 insertions(+) diff --git a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt index df3bef7..8c6659e 100644 --- a/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt +++ b/Documentation/devicetree/bindings/scsi/hisilicon-sas.txt @@ -53,6 +53,13 @@ Main node required properties: Optional main node properties: - hip06-sas-v2-quirk-amt : when set, indicates that the v2 controller has the "am-max-transmissions" limitation. + - hisilicon,signal-attenuation : array of 3 32-bit values, containing de-emphasis, + preshoot, and boost attenuation readings for the board. They + are used to describe the signal attenuation of the board. These + values' range is 7600 to 12400, and used to represent -24dB to + 24dB. + The formula is "y = (x-1)/1". For example, 10478 + means 4.78dB. Example: sas0: sas@c100 { -- 1.9.1
[PATCH v3 6/8] scsi: hisi_sas: remove unused variable hisi_sas_devices.running_req
From: Xiang Chen The structure element hisi_sas_devices.running_req to count how many commands are active is in effect only ever written in the code, so remove it. Signed-off-by: Xiang Chen Signed-off-by: John Garry --- drivers/scsi/hisi_sas/hisi_sas.h | 1 - drivers/scsi/hisi_sas/hisi_sas_main.c | 9 - drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 3 --- 3 files changed, 13 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas.h b/drivers/scsi/hisi_sas/hisi_sas.h index e7fd287..d1153e8 100644 --- a/drivers/scsi/hisi_sas/hisi_sas.h +++ b/drivers/scsi/hisi_sas/hisi_sas.h @@ -175,7 +175,6 @@ struct hisi_sas_device { struct hisi_sas_dq *dq; struct list_headlist; u64 attached_phy; - atomic64_t running_req; enum sas_device_typedev_type; int device_id; int sata_idx; diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 9ff8790..88ad8d4 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -200,8 +200,6 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task, if (task) { struct device *dev = hisi_hba->dev; - struct domain_device *device = task->dev; - struct hisi_sas_device *sas_dev = device->lldd_dev; if (!task->lldd_task) return; @@ -213,9 +211,6 @@ void hisi_sas_slot_task_free(struct hisi_hba *hisi_hba, struct sas_task *task, dma_unmap_sg(dev, task->scatter, task->num_scatter, task->data_dir); - - if (sas_dev) - atomic64_dec(&sas_dev->running_req); } if (slot->buf) @@ -431,8 +426,6 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq spin_unlock_irqrestore(&task->task_state_lock, flags); dq->slot_prep = slot; - - atomic64_inc(&sas_dev->running_req); ++(*pass); return 0; @@ -1517,8 +1510,6 @@ static int hisi_sas_query_task(struct sas_task *task) dq->slot_prep = slot; - atomic64_inc(&sas_dev->running_req); - /* send abort command to the chip */ hisi_hba->hw->start_delivery(dq); spin_unlock_irqrestore(&dq->lock, flags_dq); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 2eb8980..8dd0e6a6 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -1407,9 +1407,6 @@ static int slot_complete_v1_hw(struct hisi_hba *hisi_hba, } out: - if (sas_dev) - atomic64_dec(&sas_dev->running_req); - hisi_sas_slot_task_free(hisi_hba, task, slot); sts = ts->stat; -- 1.9.1
[PATCH v3 4/8] scsi: hisi_sas: fix the issue of setting linkrate register
From: Xiaofei Tan It is not right to set the register PROG_PHY_LINK_RATE while PHY is still enabled. So if we want to change PHY linkrate, we need to disable PHY before setting the register PROG_PHY_LINK_RATE, and then start-up PHY. This patch is to fix this issue. Signed-off-by: Xiaofei Tan Signed-off-by: John Garry --- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 5 +++-- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 5 +++-- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 5 +++-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 38bbda9..2eb8980 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -881,10 +881,11 @@ static void phy_set_linkrate_v1_hw(struct hisi_hba *hisi_hba, int phy_no, prog_phy_link_rate &= ~0xff; prog_phy_link_rate |= rate_mask; + disable_phy_v1_hw(hisi_hba, phy_no); + msleep(100); hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE, prog_phy_link_rate); - - phy_hard_reset_v1_hw(hisi_hba, phy_no); + start_phy_v1_hw(hisi_hba, phy_no); } static int get_wideport_bitmap_v1_hw(struct hisi_hba *hisi_hba, int port_id) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 67be346..bd1a48a 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -1611,10 +1611,11 @@ static void phy_set_linkrate_v2_hw(struct hisi_hba *hisi_hba, int phy_no, prog_phy_link_rate &= ~0xff; prog_phy_link_rate |= rate_mask; + disable_phy_v2_hw(hisi_hba, phy_no); + msleep(100); hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE, prog_phy_link_rate); - - phy_hard_reset_v2_hw(hisi_hba, phy_no); + start_phy_v2_hw(hisi_hba, phy_no); } static int get_wideport_bitmap_v2_hw(struct hisi_hba *hisi_hba, int port_id) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index 1ee95ab..8da9de7 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -1862,10 +1862,11 @@ static void phy_set_linkrate_v3_hw(struct hisi_hba *hisi_hba, int phy_no, prog_phy_link_rate &= ~0xff; prog_phy_link_rate |= rate_mask; + disable_phy_v3_hw(hisi_hba, phy_no); + msleep(100); hisi_sas_phy_write32(hisi_hba, phy_no, PROG_PHY_LINK_RATE, prog_phy_link_rate); - - phy_hard_reset_v3_hw(hisi_hba, phy_no); + start_phy_v3_hw(hisi_hba, phy_no); } static void interrupt_disable_v3_hw(struct hisi_hba *hisi_hba) -- 1.9.1
[PATCH v3 0/8] hisi_sas: support x6000 board and some misc changes
This patchset primarily adds support for the Huawei x6000 board, which includes hip07 chipset. Unfortunately, due to some board layout differences with our development board, we need to set a PHY-related register differently for optimal signal quality. As such, a signal attenuation property is added to describe the differences in the boards and allow the PHY register to be set appropriately. In addition to this above feature, some misc changes are added for: - PHY linkrate sysfs interface - linkrate set function - internal abort timer timeout increase Differences to v2: - rename dt binding property name to "hisilicon,signal-attenuation" Differences to v1: - rename dt binding property name to include "hisi-" prefix Xiang Chen (2): scsi: hisi_sas: remove unused variable hisi_sas_devices.running_req scsi: hisi_sas: Code cleanup and minor bug fixes Xiaofei Tan (6): dt-bindings: scsi: hisi_sas: add an property of signal attenuation scsi: hisi_sas: support the property of signal attenuation for v2 hw scsi: hisi_sas: fix the issue of link rate inconsistency scsi: hisi_sas: fix the issue of setting linkrate register scsi: hisi_sas: increase timer expire of internal abort task scsi: hisi_sas: fix return value of hisi_sas_task_prep() .../devicetree/bindings/scsi/hisilicon-sas.txt | 7 +++ drivers/scsi/hisi_sas/hisi_sas.h | 1 - drivers/scsi/hisi_sas/hisi_sas_main.c | 34 +--- drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 13 +++-- drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 62 +- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 34 +--- 6 files changed, 88 insertions(+), 63 deletions(-) -- 1.9.1
[PATCH v3 3/8] scsi: hisi_sas: fix the issue of link rate inconsistency
From: Xiaofei Tan In sysfs, there are two files about minimum linkrate, and also two files for maximum linkrate. Take maximum linkrate example, maximum_linkrate_hw is read-only and indicated by the register HARD_PHY_LINKRATE, and maximum_linkrate is read-write and corresponding to the register PROG_PHY_LINK_RATE. But in the function phy_up_v*_hw(), we get *_linkrate value from HARD_PHY_LINKRATE. It is not right. This patch is to fix this issue. Unreferenced PHY-interrupt enum is also removed for v3 hw. Signed-off-by: Xiaofei Tan Signed-off-by: John Garry --- drivers/scsi/hisi_sas/hisi_sas_main.c | 2 ++ drivers/scsi/hisi_sas/hisi_sas_v1_hw.c | 1 - drivers/scsi/hisi_sas/hisi_sas_v2_hw.c | 8 +--- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 13 + 4 files changed, 4 insertions(+), 20 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 2d4dbed..9d16372 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -683,6 +683,8 @@ static void hisi_sas_phy_init(struct hisi_hba *hisi_hba, int phy_no) phy->hisi_hba = hisi_hba; phy->port = NULL; + phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS; + phy->maximum_linkrate = hisi_hba->hw->phy_get_max_linkrate(); sas_phy->enabled = (phy_no < hisi_hba->n_phy) ? 1 : 0; sas_phy->class = SAS; sas_phy->iproto = SAS_PROTOCOL_ALL; diff --git a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c index 679e76f..38bbda9 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v1_hw.c @@ -873,7 +873,6 @@ static void phy_set_linkrate_v1_hw(struct hisi_hba *hisi_hba, int phy_no, sas_phy->phy->maximum_linkrate = max; sas_phy->phy->minimum_linkrate = min; - min -= SAS_LINK_RATE_1_5_GBPS; max -= SAS_LINK_RATE_1_5_GBPS; for (i = 0; i <= max; i++) diff --git a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c index 42b3fd6..67be346 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v2_hw.c @@ -1603,7 +1603,6 @@ static void phy_set_linkrate_v2_hw(struct hisi_hba *hisi_hba, int phy_no, sas_phy->phy->maximum_linkrate = max; sas_phy->phy->minimum_linkrate = min; - min -= SAS_LINK_RATE_1_5_GBPS; max -= SAS_LINK_RATE_1_5_GBPS; for (i = 0; i <= max; i++) @@ -2684,7 +2683,7 @@ static int prep_abort_v2_hw(struct hisi_hba *hisi_hba, static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba) { int i, res = IRQ_HANDLED; - u32 port_id, link_rate, hard_phy_linkrate; + u32 port_id, link_rate; struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; struct asd_sas_phy *sas_phy = &phy->sas_phy; struct device *dev = hisi_hba->dev; @@ -2723,11 +2722,6 @@ static int phy_up_v2_hw(int phy_no, struct hisi_hba *hisi_hba) } sas_phy->linkrate = link_rate; - hard_phy_linkrate = hisi_sas_phy_read32(hisi_hba, phy_no, - HARD_PHY_LINKRATE); - phy->maximum_linkrate = hard_phy_linkrate & 0xf; - phy->minimum_linkrate = (hard_phy_linkrate >> 4) & 0xf; - sas_phy->oob_mode = SAS_OOB_MODE; memcpy(sas_phy->attached_sas_addr, &id->sas_addr, SAS_ADDR_SIZE); dev_info(dev, "phyup: phy%d link_rate=%d\n", phy_no, link_rate); diff --git a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c index a1f1868..1ee95ab 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +++ b/drivers/scsi/hisi_sas/hisi_sas_v3_hw.c @@ -340,12 +340,6 @@ struct hisi_sas_err_record_v3 { #define HISI_SAS_COMMAND_ENTRIES_V3_HW 4096 #define HISI_SAS_MSI_COUNT_V3_HW 32 -enum { - HISI_SAS_PHY_PHY_UPDOWN, - HISI_SAS_PHY_CHNL_INT, - HISI_SAS_PHY_INT_NR -}; - #define DIR_NO_DATA 0 #define DIR_TO_INI 1 #define DIR_TO_DEVICE 2 @@ -1121,7 +1115,7 @@ static int prep_abort_v3_hw(struct hisi_hba *hisi_hba, static int phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba) { int i, res = 0; - u32 context, port_id, link_rate, hard_phy_linkrate; + u32 context, port_id, link_rate; struct hisi_sas_phy *phy = &hisi_hba->phy[phy_no]; struct asd_sas_phy *sas_phy = &phy->sas_phy; struct device *dev = hisi_hba->dev; @@ -1139,10 +1133,6 @@ static int phy_up_v3_hw(int phy_no, struct hisi_hba *hisi_hba) goto end; } sas_phy->linkrate = link_rate; - hard_phy_linkrate = hisi_sas_phy_read32(hisi_hba, phy_no, - HARD_PHY_LINKRATE); - phy->maximum_linkrate = hard_phy_linkrate & 0xf; - phy->minimum_linkrate = (hard_phy_linkrate >> 4) & 0xf; phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA); /* Check for SATA dev */ @@ -1864,7 +1854,6 @@ static void phy_s
[PATCH v3 7/8] scsi: hisi_sas: fix return value of hisi_sas_task_prep()
From: Xiaofei Tan It is an implicit regulation that error code that function returned should be negative. But hisi_sas_task_prep() doesn't follow this. This may cause problems in the upper layer code. For example, in sas_expander.c of libsas, smp_execute_task_sg() may return the number of bytes of underrun. It will be conflicted with the scenaio lldd_execute_task() return an positive error code. This patch change the return value from SAS_PHY_DOWN to -ECOMM in hisi_sas_task_prep(). Signed-off-by: Xiaofei Tan Signed-off-by: John Garry --- drivers/scsi/hisi_sas/hisi_sas_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/hisi_sas/hisi_sas_main.c b/drivers/scsi/hisi_sas/hisi_sas_main.c index 88ad8d4..dff9723 100644 --- a/drivers/scsi/hisi_sas/hisi_sas_main.c +++ b/drivers/scsi/hisi_sas/hisi_sas_main.c @@ -316,7 +316,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq */ if (device->dev_type != SAS_SATA_DEV) task->task_done(task); - return SAS_PHY_DOWN; + return -ECOMM; } if (DEV_IS_GONE(sas_dev)) { @@ -327,7 +327,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq dev_info(dev, "task prep: device %016llx not ready\n", SAS_ADDR(device->sas_addr)); - return SAS_PHY_DOWN; + return -ECOMM; } port = to_hisi_sas_port(sas_port); @@ -337,7 +337,7 @@ static int hisi_sas_task_prep(struct sas_task *task, struct hisi_sas_dq "SATA/STP" : "SAS", device->port->id); - return SAS_PHY_DOWN; + return -ECOMM; } if (!sas_protocol_ata(task->task_proto)) { -- 1.9.1
[PATCH] smartpqi: add in new supported controllers
From: Kevin Barnett Reviewed-by: Scott Benesh Signed-off-by: Kevin Barnett Signed-off-by: Don Brace --- drivers/scsi/smartpqi/smartpqi_init.c | 44 + 1 file changed, 44 insertions(+) diff --git a/drivers/scsi/smartpqi/smartpqi_init.c b/drivers/scsi/smartpqi/smartpqi_init.c index b2880c7709e6..b3aeb88456d8 100644 --- a/drivers/scsi/smartpqi/smartpqi_init.c +++ b/drivers/scsi/smartpqi/smartpqi_init.c @@ -6795,6 +6795,14 @@ static __maybe_unused int pqi_resume(struct pci_dev *pci_dev) /* Define the PCI IDs for the controllers that we support. */ static const struct pci_device_id pqi_pci_id_table[] = { + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x105b, 0x1211) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x105b, 0x1321) + }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x152d, 0x8a22) @@ -6815,6 +6823,38 @@ static const struct pci_device_id pqi_pci_id_table[] = { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, 0x152d, 0x8a37) }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x193d, 0x8460) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x193d, 0x8461) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x193d, 0xf460) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x193d, 0xf461) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1bd4, 0x0045) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1bd4, 0x0046) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1bd4, 0x0047) + }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + 0x1bd4, 0x0048) + }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, PCI_VENDOR_ID_ADAPTEC2, 0x0110) @@ -6915,6 +6955,10 @@ static const struct pci_device_id pqi_pci_id_table[] = { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, PCI_VENDOR_ID_ADAPTEC2, 0x1281) }, + { + PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, + PCI_VENDOR_ID_ADAPTEC2, 0x1282) + }, { PCI_DEVICE_SUB(PCI_VENDOR_ID_ADAPTEC2, 0x028f, PCI_VENDOR_ID_ADAPTEC2, 0x1300)
Re: [PATCH V3 1/8] scsi: hpsa: fix selection of reply queue
On Mon, Mar 05 2018 at 2:23am -0500, Kashyap Desai wrote: > > -Original Message- > > From: Laurence Oberman [mailto:lober...@redhat.com] > > Sent: Saturday, March 3, 2018 3:23 AM > > To: Don Brace; Ming Lei > > Cc: Jens Axboe; linux-bl...@vger.kernel.org; Christoph Hellwig; Mike > > Snitzer; > > linux-scsi@vger.kernel.org; Hannes Reinecke; Arun Easi; Omar Sandoval; > > Martin K . Petersen; James Bottomley; Christoph Hellwig; Kashyap Desai; > > Peter > > Rivera; Meelis Roos > > Subject: Re: [PATCH V3 1/8] scsi: hpsa: fix selection of reply queue > > ... > > Unless Kashyap is not happy we need to consider getting this in to Linus > > now > > because we are seeing HPE servers that keep hanging now with the original > > commit now upstream. > > > > Kashyap, are you good with the v3 patchset or still concerned with > > performance. I was getting pretty good IOPS/sec to individual SSD drives > > set > > up as jbod devices on the megaraid_sas. > > Laurence - > Did you find difference with/without the patch ? What was IOPs number with > and without patch. > It is not urgent feature, so I would like to take some time to get BRCM's > performance team involved and do full analysis of performance run and find > pros/cons. Performance doesn't matter if the system cannot even boot (e.g. HPE servers with hpsa using the latest linus tree). Have you tried your testbed with just applying the first 2 patches? Or do those cause the performance hit and the follow-on patches in the series attempt to recover from it? Mike
Re: [PATCH 2/2] m68k/amiga - Zorro ESP: new zorro_esp.c
On 05.03.2018 03:11, Michael Schmitz wrote: Hi Finn, On Mon, Mar 5, 2018 at 2:01 PM, Finn Thain wrote: On Mon, 5 Mar 2018, Michael Schmitz wrote: +fail_unmap_dma_regs: + if (ioaddr > 0xff) + iounmap(esp->dma_regs); I think you need to test for ZORRO_PROD_PHASE5_BLIZZARD_1230_IV_1260 here? On second thought - no, I don't. the ID check above only determines what Zorro-3 address is ioremapped, but in each case where ioaddr > 0xff, something will have been mapped at this point. I think you are talking about esp->regs? For esp->dma_regs, the ioremap is conditional on ent->id, but the unmap is not. The details of the ioremap are conditional on the ID, but the fact that the ioremap happens (and hence esp->dma_regs is an ioremapped address) is not. All Zorro-3 boards have to have both their regs and dma_regs remapped. What's confusing is that there is only a single Zorro-3 board currently supported by the driver. Others will be added and I"ll use a switch statement to pick the appropriate address based on the ID. That might make it clearer. Fastlane might be the only Z3 SCSI board that has the chip. -Tuomas +} + +static void zorro_esp_remove_one(struct zorro_dev *z) +{ + struct Scsi_Host *host = zorro_get_drvdata(z); + struct esp *esp = shost_priv(host); + + scsi_esp_unregister(esp); + + /* Disable interrupts. Perhaps use disable_irq instead ... */ + + free_irq(host->irq, esp); + dma_free_coherent(esp->dev, 16, + esp->command_block, + esp->command_block_dma); + + if (host->base > 0xff) { + iounmap(esp->dma_regs); Do you need to test for ZORRO_PROD_PHASE5_BLIZZARD_1230_IV_1260 first? I can't - ent->id is not available here... Maybe store ent->id in the private struct to get around that? Yes, that could be done. I still think it's not needed. Cheers, Michael -- -- To unsubscribe from this list: send the line "unsubscribe linux-m68k" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] scsi: lpfc: Switch memcpy_fromio() to __read32_copy()
On 3/4/2018 10:56 PM, 陈华才 wrote: No one has the same problem? Or this patch need improve? Huacai -- Original -- From: "陈华才"; Date: Thu, Mar 1, 2018 01:59 PM To: "James Smart"; "Dick Kennedy"; Cc: "James E . J . Bottomley"; "Martin K . Petersen"; "Fuxin Zhang"; "linux-scsi"; "stable"; Subject: Re:[PATCH] scsi: lpfc: Switch memcpy_fromio() to __read32_copy() Ping? -- Original -- From: "Huacai Chen"; Date: Fri, Jan 26, 2018 08:53 PM To: "James Smart"; "Dick Kennedy"; Cc: "James E . J . Bottomley"; "Martin K . Petersen"; "Fuxin Zhang"; "linux-scsi"; "Huacai Chen"; "stable"; Subject: [PATCH] scsi: lpfc: Switch memcpy_fromio() to __read32_copy() In commit bc73905abf770192 ("[SCSI] lpfc 8.3.16: SLI Additions, updates, and code cleanup"), lpfc_memcpy_to_slim() have switched memcpy_toio() to __write32_copy() in order to prevent unaligned 64 bit copy. Recently, we found that lpfc_memcpy_from_slim() have similar issues, so let it switch memcpy_fromio() to __read32_copy(). Cc: sta...@vger.kernel.org Signed-off-by: Huacai Chen --- drivers/scsi/lpfc/lpfc_compat.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_compat.h b/drivers/scsi/lpfc/lpfc_compat.h index 6b32b0a..47d4fad 100644 --- a/drivers/scsi/lpfc/lpfc_compat.h +++ b/drivers/scsi/lpfc/lpfc_compat.h @@ -91,8 +91,8 @@ lpfc_memcpy_to_slim( void __iomem *dest, void *src, unsigned int bytes) static inline void lpfc_memcpy_from_slim( void *dest, void __iomem *src, unsigned int bytes) { - /* actually returns 1 byte past dest */ - memcpy_fromio( dest, src, bytes); + /* convert bytes in argument list to word count for copy function */ + __ioread32_copy(dest, src, bytes / sizeof(uint32_t)); } #endif /* __BIG_ENDIAN */ Huacai, Note: the original change was 7 yrs ago and we've had no reports of issues. but This change didn't look necessary as the memcpy_XXXio() should allow byte alignments and byte-based lengths. Which means the original patch also wasn't necessary, which implies that the platform that had the issues has an api restriction not normally found on the other platforms. I have no problem with the change though. -- james Signed-off-by: James Smart
[PATCH] lpfc: use __raw_writeX on DPP copies
This patch replaces: https://www.spinics.net/lists/linux-scsi/msg117838.html A prior lpfc patch: scsi: lpfc: Add push-to-adapter support to sli4 commitid=1351e69fc6db30e186295f1c9495d03cef6a01a2 Fails compilation on some 32-bit systems as writeq() is not supported on all architectures. Additionally, it was pointed out that as writeX() does byteswapping if necessary for pci vs the cpu endianness, the code was broken on BE PPC. After discussions with Arnd Bergmann, we've resolved the issue to the following: When 32-bit, use 32-bit accesses. Instead of writeX(), use __raw_writeX() - which writes to io space while preserving byte order. To use this, the code was changed to use a different buffer that lpfc prepped via sli_pcimem_bcopy() that was set to the bytestream to be written. Signed-off-by: Dick Kennedy Signed-off-by: James Smart --- drivers/scsi/lpfc/lpfc_sli.c | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 4ce3ca6f4b79..675914cc8ab8 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -140,9 +140,16 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe) lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size); if (q->dpp_enable && q->phba->cfg_enable_dpp) { /* write to DPP aperture taking advatage of Combined Writes */ - tmp = (uint8_t *)wqe; + tmp = (uint8_t *)temp_wqe; +#ifdef CONFIG_64BIT for (i = 0; i < q->entry_size; i += sizeof(uint64_t)) - writeq(*((uint64_t *)(tmp + i)), q->dpp_regaddr + i); + __raw_writeq(*((uint64_t *)(tmp + i)), + q->dpp_regaddr + i); +#else + for (i = 0; i < q->entry_size; i += sizeof(uint32_t)) + __raw_writel(*((uint32_t *)(tmp + i)), + q->dpp_regaddr + i); +#endif } /* ensure WQE bcopy and DPP flushed before doorbell write */ wmb(); -- 2.13.1
Re: [PATCH v3 0/2] scsi: mpt3sas: prevent oops in the shutdown/unload path
Martin, James, On 02/22/2018 01:07 AM, Martin K. Petersen wrote: The first patch prevents the SCSI error handlers to run once the shutdown/unload path starts. This avoids an oops at least in the host reset handler, on kernels with a recent patch, and also in the abort handler on kernels without that patch. The second patch goes a step further, and prevents the SCSI error handlers to be called for SCSI IO commands running at the shutdown/unload time (in case adapter interrupts are disabled before they complete) by finishing them. Notice the second patch only affects SCSI IO commands. Other command types, e.g., Task Manangement Functions, which are running at the shutdown/unload time still must be handled separately -- this is also covered in patch 1. Applied to 4.16/scsi-fixes. Thank you! Thank you. Are you OK with / would ack this patchset for stable (v4.14+) ? I have the backports ready and can submit if you are OK with it. Thanks, Mauricio
Re: [PATCH] lpfc: use __raw_writeX on DPP copies
On Mon, 2018-03-05 at 09:03 -0800, James Smart wrote: > This patch replaces: > https://www.spinics.net/lists/linux-scsi/msg117838.html > > A prior lpfc patch: > scsi: lpfc: Add push-to-adapter support to sli4 > commitid=1351e69fc6db30e186295f1c9495d03cef6a01a2 > > Fails compilation on some 32-bit systems as writeq() is not supported > on all architectures. Additionally, it was pointed out that as > writeX() > does byteswapping if necessary for pci vs the cpu endianness, the > code > was broken on BE PPC. > > After discussions with Arnd Bergmann, we've resolved the issue > to the following: > When 32-bit, use 32-bit accesses. > Instead of writeX(), use __raw_writeX() - which writes to io > space while preserving byte order. To use this, the code > was changed to use a different buffer that lpfc prepped > via sli_pcimem_bcopy() that was set to the bytestream to > be written. > > Signed-off-by: Dick Kennedy > Signed-off-by: James Smart > --- > drivers/scsi/lpfc/lpfc_sli.c | 11 +-- > 1 file changed, 9 insertions(+), 2 deletions(-) > > diff --git a/drivers/scsi/lpfc/lpfc_sli.c > b/drivers/scsi/lpfc/lpfc_sli.c > index 4ce3ca6f4b79..675914cc8ab8 100644 > --- a/drivers/scsi/lpfc/lpfc_sli.c > +++ b/drivers/scsi/lpfc/lpfc_sli.c > @@ -140,9 +140,16 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union > lpfc_wqe *wqe) > lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size); > if (q->dpp_enable && q->phba->cfg_enable_dpp) { > /* write to DPP aperture taking advatage of Combined > Writes */ > - tmp = (uint8_t *)wqe; > + tmp = (uint8_t *)temp_wqe; > +#ifdef CONFIG_64BIT Whether a platform has a functioning writeq isn't related to its 64 bitness, there are a few 32 bit platforms which have it. As long as you don't get an include of the lo-hi helpers which really confused this situation, the define you're looking for is #ifdef __raw_writeq James
[PATCH v2] lpfc: use __raw_writeX on DPP copies
This patch replaces: https://www.spinics.net/lists/linux-scsi/msg117838.html A prior lpfc patch: scsi: lpfc: Add push-to-adapter support to sli4 commitid=1351e69fc6db30e186295f1c9495d03cef6a01a2 Fails compilation on some 32-bit systems as writeq() is not supported on all architectures. Additionally, it was pointed out that as writeX() does byteswapping if necessary for pci vs the cpu endianness, the code was broken on BE PPC. After discussions with Arnd Bergmann, we've resolved the issue to the following: Instead of writeX(), use __raw_writeX() - which writes to io space while preserving byte order. To use this, the code was changed to use a different buffer that lpfc prepped via sli_pcimem_bcopy() that was set to the bytestream to be written. On platforms with __raw_writeq support, use the routine, otherwise use __raw_writel() Signed-off-by: Dick Kennedy Signed-off-by: James Smart --- v2: check for __raw_writeq defined, instead of CONFIG_64bit allows 32bit platforms with support to use it. --- drivers/scsi/lpfc/lpfc_sli.c | 11 +-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 4ce3ca6f4b79..d20cf51ca15d 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -140,9 +140,16 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe *wqe) lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size); if (q->dpp_enable && q->phba->cfg_enable_dpp) { /* write to DPP aperture taking advatage of Combined Writes */ - tmp = (uint8_t *)wqe; + tmp = (uint8_t *)temp_wqe; +#ifdef __raw_writeq for (i = 0; i < q->entry_size; i += sizeof(uint64_t)) - writeq(*((uint64_t *)(tmp + i)), q->dpp_regaddr + i); + __raw_writeq(*((uint64_t *)(tmp + i)), + q->dpp_regaddr + i); +#else + for (i = 0; i < q->entry_size; i += sizeof(uint32_t)) + __raw_writel(*((uint32_t *)(tmp + i)), + q->dpp_regaddr + i); +#endif } /* ensure WQE bcopy and DPP flushed before doorbell write */ wmb(); -- 2.13.1
Re: [PATCH v2] lpfc: use __raw_writeX on DPP copies
On Mon, Mar 5, 2018 at 7:29 PM, James Smart wrote: > This patch replaces: > https://www.spinics.net/lists/linux-scsi/msg117838.html > > A prior lpfc patch: > scsi: lpfc: Add push-to-adapter support to sli4 > commitid=1351e69fc6db30e186295f1c9495d03cef6a01a2 > > Fails compilation on some 32-bit systems as writeq() is not supported > on all architectures. Additionally, it was pointed out that as writeX() > does byteswapping if necessary for pci vs the cpu endianness, the code > was broken on BE PPC. > > After discussions with Arnd Bergmann, we've resolved the issue > to the following: > Instead of writeX(), use __raw_writeX() - which writes to io > space while preserving byte order. To use this, the code > was changed to use a different buffer that lpfc prepped > via sli_pcimem_bcopy() that was set to the bytestream to > be written. > On platforms with __raw_writeq support, use the routine, otherwise > use __raw_writel() > > Signed-off-by: Dick Kennedy > Signed-off-by: James Smart Reviewed-by: Arnd Bergmann It would be interesting to try this version on powerpc64 as well (with a patch to use ioremap_wc() an d set dpp_enable), the lack of "sync" style barriers in __raw_writel should make it much faster than the old version. Arnd
[PATCH 003/103] sched, treewide: Replace hardcoded nice values with MIN_NICE/MAX_NICE
From: Dongsheng Yang Replace various -20/+19 hardcoded nice values with MIN_NICE/MAX_NICE. Signed-off-by: Dongsheng Yang Acked-by: Tejun Heo Signed-off-by: Peter Zijlstra Link: http://lkml.kernel.org/r/ff13819fd09b7a5dba5ab5ae797f2e7019bdfa17.1394532288.git.yangds.f...@cn.fujitsu.com Cc: de...@driverdev.osuosl.org Cc: devicet...@vger.kernel.org Cc: fcoe-de...@open-fcoe.org Cc: linux...@de.ibm.com Cc: linux-ker...@vger.kernel.org Cc: linux...@kvack.org Cc: linux-s...@vger.kernel.org Cc: linux-scsi@vger.kernel.org Cc: nbd-gene...@lists.sourceforge.net Cc: ocfs2-de...@oss.oracle.com Cc: openipmi-develo...@lists.sourceforge.net Cc: qla2xxx-upstr...@qlogic.com Cc: linux-a...@vger.kernel.org [ Consolidated the patches, twiddled the changelog. ] Signed-off-by: Ingo Molnar Change-Id: I00a4ccd66fcc206211f462245d98d35a853f8264 --- drivers/block/loop.c | 2 +- drivers/block/nbd.c | 2 +- drivers/block/pktcdvd.c | 2 +- drivers/char/ipmi/ipmi_si_intf.c | 2 +- drivers/s390/crypto/ap_bus.c | 2 +- drivers/scsi/bnx2fc/bnx2fc_fcoe.c | 4 ++-- drivers/scsi/bnx2i/bnx2i_hwi.c| 2 +- drivers/scsi/fcoe/fcoe.c | 2 +- drivers/scsi/ibmvscsi/ibmvfc.c| 2 +- drivers/scsi/ibmvscsi/ibmvscsi.c | 2 +- drivers/scsi/lpfc/lpfc_hbadisc.c | 2 +- drivers/scsi/qla2xxx/qla_os.c | 2 +- fs/ocfs2/cluster/heartbeat.c | 2 +- kernel/workqueue.c| 6 +++--- mm/huge_memory.c | 2 +- 15 files changed, 18 insertions(+), 18 deletions(-) diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 333458c..029e43c 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -547,7 +547,7 @@ static int loop_thread(void *data) struct loop_device *lo = data; struct bio *bio; - set_user_nice(current, -20); + set_user_nice(current, MIN_NICE); while (!kthread_should_stop() || !bio_list_empty(&lo->lo_bio_list)) { diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index d593fa5..f1a2da8 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -533,7 +533,7 @@ static int nbd_thread(void *data) struct nbd_device *nbd = data; struct request *req; - set_user_nice(current, -20); + set_user_nice(current, MIN_NICE); while (!kthread_should_stop() || !list_empty(&nbd->waiting_queue)) { /* wait for something to do */ wait_event_interruptible(nbd->waiting_wq, diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index caddb5d..14a8075 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -1471,7 +1471,7 @@ static int kcdrwd(void *foobar) struct packet_data *pkt; long min_sleep_time, residue; - set_user_nice(current, -20); + set_user_nice(current, MIN_NICE); set_freezable(); for (;;) { diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index a67ac2a..fc22dec 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -992,7 +992,7 @@ static int ipmi_thread(void *data) struct timespec busy_until; ipmi_si_set_not_busy(&busy_until); - set_user_nice(current, 19); + set_user_nice(current, MAX_NICE); while (!kthread_should_stop()) { int busy_wait; diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 6f512fa..b30ffb8 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c @@ -1755,7 +1755,7 @@ static int ap_poll_thread(void *data) int requests; struct ap_device *ap_dev; - set_user_nice(current, 19); + set_user_nice(current, MAX_NICE); while (1) { if (ap_suspend_flag) return 0; diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index aad5535..ff08516 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -471,7 +471,7 @@ static int bnx2fc_l2_rcv_thread(void *arg) struct fcoe_percpu_s *bg = arg; struct sk_buff *skb; - set_user_nice(current, -20); + set_user_nice(current, MIN_NICE); set_current_state(TASK_INTERRUPTIBLE); while (!kthread_should_stop()) { schedule(); @@ -610,7 +610,7 @@ int bnx2fc_percpu_io_thread(void *arg) struct bnx2fc_work *work, *tmp; LIST_HEAD(work_list); - set_user_nice(current, -20); + set_user_nice(current, MIN_NICE); set_current_state(TASK_INTERRUPTIBLE); while (!kthread_should_stop()) { schedule(); diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index a28b03e..a95ea80 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c @@ -1870,7 +1870,7 @@ int bnx2i_percpu_io_thread(void *arg) struct bnx2i_work *work, *tmp; LIST_HEAD(work_list); - set_user_ni
[PATCH 0/9] lpfc updates for 12.0.0.1
This patch contains lpfc bug fixes The patches were cut against the Martin's 4.17/scsi-queue tree, plus the following patch applied: [PATCH v2] lpfc: use __raw_writeX on DPP copies https://marc.info/?l=linux-scsi&m=152027455929958&w=2 James Smart (9): lpfc: Fix NVME Initiator FirstBurst lpfc: Code cleanup for 128byte wqe data type lpfc: Streamline NVME Initiator WQE setup lpfc: Streamline NVME Targe6t WQE setup lpfc: Fix SCSI lun discovery when port configured for both SCSI and NVME lpfc: Fix mailbox wait for POST_SGL mbox command lpfc: Memory allocation error during driver start-up on power8 lpfc: update driver version to 12.0.0.1 lpfc: Change Copyright of 12.0.0.1 modified files to 2018 drivers/scsi/lpfc/lpfc_attr.c | 4 + drivers/scsi/lpfc/lpfc_crtn.h | 2 + drivers/scsi/lpfc/lpfc_ct.c| 1 - drivers/scsi/lpfc/lpfc_els.c | 1 + drivers/scsi/lpfc/lpfc_hbadisc.c | 5 + drivers/scsi/lpfc/lpfc_hw4.h | 12 +- drivers/scsi/lpfc/lpfc_init.c | 4 +- drivers/scsi/lpfc/lpfc_nportdisc.c | 15 +- drivers/scsi/lpfc/lpfc_nvme.c | 352 ++--- drivers/scsi/lpfc/lpfc_nvme.h | 4 +- drivers/scsi/lpfc/lpfc_nvmet.c | 305 drivers/scsi/lpfc/lpfc_scsi.c | 7 +- drivers/scsi/lpfc/lpfc_scsi.h | 2 +- drivers/scsi/lpfc/lpfc_sli.c | 127 ++--- drivers/scsi/lpfc/lpfc_sli.h | 6 +- drivers/scsi/lpfc/lpfc_version.h | 2 +- 16 files changed, 514 insertions(+), 335 deletions(-) -- 2.13.1
[PATCH 3/9] lpfc: Streamline NVME Initiator WQE setup
To reduce latency when initializing WQE content, created templates for the most common wqes. This reduces the number of operations taken to set the content. It's not a lot of speed up, but every bit helps. This patch updates the NVME initiator path. Signed-off-by: Dick Kennedy Signed-off-by: James Smart --- drivers/scsi/lpfc/lpfc_crtn.h | 1 + drivers/scsi/lpfc/lpfc_hw4.h | 1 + drivers/scsi/lpfc/lpfc_init.c | 1 + drivers/scsi/lpfc/lpfc_nvme.c | 327 ++ 4 files changed, 203 insertions(+), 127 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index 14a86b5b51e4..c7df22683e85 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -565,6 +565,7 @@ void lpfc_nvme_mod_param_dep(struct lpfc_hba *phba); void lpfc_nvme_abort_fcreq_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_wcqe_complete *abts_cmpl); +void lpfc_nvme_cmd_template(void); extern int lpfc_enable_nvmet_cnt; extern unsigned long long lpfc_enable_nvmet[]; extern int lpfc_no_hba_reset_cnt; diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index a2f372d14eaa..98b80559c215 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -4183,6 +4183,7 @@ struct wqe_common { #define wqe_iod_SHIFT 13 #define wqe_iod_MASK 0x0001 #define wqe_iod_WORD word10 +#define LPFC_WQE_IOD_NONE 0 #define LPFC_WQE_IOD_WRITE 0 #define LPFC_WQE_IOD_READ 1 #define wqe_dbde_SHIFT14 diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 50bc6c6efa87..68adea8e0a04 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -12583,6 +12583,7 @@ lpfc_init(void) fc_release_transport(lpfc_transport_template); return -ENOMEM; } + lpfc_nvme_cmd_template(); /* Initialize in case vector mapping is needed */ lpfc_used_cpu = NULL; diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 6d215f27448f..52dd9479b538 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -65,6 +65,136 @@ lpfc_release_nvme_buf(struct lpfc_hba *, struct lpfc_nvme_buf *); static struct nvme_fc_port_template lpfc_nvme_template; +union lpfc_wqe128 lpfc_iread_cmd_template; +union lpfc_wqe128 lpfc_iwrite_cmd_template; +union lpfc_wqe128 lpfc_icmnd_cmd_template; + +/* Setup WQE templates for NVME IOs */ +void +lpfc_nvme_cmd_template() +{ + union lpfc_wqe128 *wqe; + + /* IREAD template */ + wqe = &lpfc_iread_cmd_template; + memset(wqe, 0, sizeof(union lpfc_wqe128)); + + /* Word 0, 1, 2 - BDE is variable */ + + /* Word 3 - cmd_buff_len, payload_offset_len is zero */ + + /* Word 4 - total_xfer_len is variable */ + + /* Word 5 - is zero */ + + /* Word 6 - ctxt_tag, xri_tag is variable */ + + /* Word 7 */ + bf_set(wqe_cmnd, &wqe->fcp_iread.wqe_com, CMD_FCP_IREAD64_WQE); + bf_set(wqe_pu, &wqe->fcp_iread.wqe_com, PARM_READ_CHECK); + bf_set(wqe_class, &wqe->fcp_iread.wqe_com, CLASS3); + bf_set(wqe_ct, &wqe->fcp_iread.wqe_com, SLI4_CT_RPI); + + /* Word 8 - abort_tag is variable */ + + /* Word 9 - reqtag is variable */ + + /* Word 10 - dbde, wqes is variable */ + bf_set(wqe_qosd, &wqe->fcp_iread.wqe_com, 0); + bf_set(wqe_nvme, &wqe->fcp_iread.wqe_com, 1); + bf_set(wqe_iod, &wqe->fcp_iread.wqe_com, LPFC_WQE_IOD_READ); + bf_set(wqe_lenloc, &wqe->fcp_iread.wqe_com, LPFC_WQE_LENLOC_WORD4); + bf_set(wqe_dbde, &wqe->fcp_iread.wqe_com, 0); + bf_set(wqe_wqes, &wqe->fcp_iread.wqe_com, 1); + + /* Word 11 - pbde is variable */ + bf_set(wqe_cmd_type, &wqe->fcp_iread.wqe_com, NVME_READ_CMD); + bf_set(wqe_cqid, &wqe->fcp_iread.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); + bf_set(wqe_pbde, &wqe->fcp_iread.wqe_com, 1); + + /* Word 12 - is zero */ + + /* Word 13, 14, 15 - PBDE is variable */ + + /* IWRITE template */ + wqe = &lpfc_iwrite_cmd_template; + memset(wqe, 0, sizeof(union lpfc_wqe128)); + + /* Word 0, 1, 2 - BDE is variable */ + + /* Word 3 - cmd_buff_len, payload_offset_len is zero */ + + /* Word 4 - total_xfer_len is variable */ + + /* Word 5 - initial_xfer_len is variable */ + + /* Word 6 - ctxt_tag, xri_tag is variable */ + + /* Word 7 */ + bf_set(wqe_cmnd, &wqe->fcp_iwrite.wqe_com, CMD_FCP_IWRITE64_WQE); + bf_set(wqe_pu, &wqe->fcp_iwrite.wqe_com, PARM_READ_CHECK); + bf_set(wqe_class, &wqe->fcp_iwrite.wqe_com, CLASS3); + bf_set(wqe_ct, &wqe->fcp_iwrite.wqe_com, SLI4_CT_RPI); + + /* Word 8 - abort_tag is variable */ + + /* Word 9 - reqtag is variable */ + + /* Word 10 - dbde, wqes is variable */ + bf_
[PATCH 5/9] lpfc: Fix SCSI lun discovery when port configured for both SCSI and NVME
When a port is configured for NVME and SCSI Initiator support and it probes a target supporting both SCSI and NVME, NVME devices are discovered, but SCSI devices are not. The nlp_fc4_type for all NPorts should be cleared on Link Up or just before GID_FTs get issued, as opposed to just during GID_FT cmpl. RSCN activity as well as Link Up can trigger GID_FT. One GID_FT may complete before the next one is issued. Fix by clearng nlp_fc4_type on link up and just before both GID_FTs are issued. During port swapping, copy nlp_fc4_type to the new ndlp Signed-off-by: Dick Kennedy Signed-off-by: James Smart --- drivers/scsi/lpfc/lpfc_ct.c | 1 - drivers/scsi/lpfc/lpfc_els.c | 1 + drivers/scsi/lpfc/lpfc_hbadisc.c | 5 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_ct.c b/drivers/scsi/lpfc/lpfc_ct.c index ebe8ac1b88e7..0617c8ea88c6 100644 --- a/drivers/scsi/lpfc/lpfc_ct.c +++ b/drivers/scsi/lpfc/lpfc_ct.c @@ -471,7 +471,6 @@ lpfc_prep_node_fc4type(struct lpfc_vport *vport, uint32_t Did, uint8_t fc4_type) "Parse GID_FTrsp: did:x%x flg:x%x x%x", Did, ndlp->nlp_flag, vport->fc_flag); - ndlp->nlp_fc4_type &= ~(NLP_FC4_FCP | NLP_FC4_NVME); /* By default, the driver expects to support FCP FC4 */ if (fc4_type == FC_TYPE_FCP) ndlp->nlp_fc4_type |= NLP_FC4_FCP; diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 09e4eb9fbc69..74895e62aaea 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -1661,6 +1661,7 @@ lpfc_plogi_confirm_nport(struct lpfc_hba *phba, uint32_t *prsp, if (ndlp->nrport) { ndlp->nrport = NULL; lpfc_nlp_put(ndlp); + new_ndlp->nlp_fc4_type = ndlp->nlp_fc4_type; } /* We shall actually free the ndlp with both nlp_DID and diff --git a/drivers/scsi/lpfc/lpfc_hbadisc.c b/drivers/scsi/lpfc/lpfc_hbadisc.c index 7855afa13568..3e7712cd6c9a 100644 --- a/drivers/scsi/lpfc/lpfc_hbadisc.c +++ b/drivers/scsi/lpfc/lpfc_hbadisc.c @@ -959,6 +959,7 @@ lpfc_linkup_cleanup_nodes(struct lpfc_vport *vport) struct lpfc_nodelist *ndlp; list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { + ndlp->nlp_fc4_type &= ~(NLP_FC4_FCP | NLP_FC4_NVME); if (!NLP_CHK_NODE_ACT(ndlp)) continue; if (ndlp->nlp_state == NLP_STE_UNUSED_NODE) @@ -3875,6 +3876,10 @@ int lpfc_issue_gidft(struct lpfc_vport *vport) { struct lpfc_hba *phba = vport->phba; + struct lpfc_nodelist *ndlp; + + list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) + ndlp->nlp_fc4_type &= ~(NLP_FC4_FCP | NLP_FC4_NVME); /* Good status, issue CT Request to NameServer */ if ((phba->cfg_enable_fc4_type == LPFC_ENABLE_BOTH) || -- 2.13.1
[PATCH 4/9] lpfc: Streamline NVME Targe6t WQE setup
To reduce latency when initializing WQE content, created templates for the most common wqes. This reduces the number of operations taken to set the content. It's not a lot of speed up, but every bit helps. This patch updates the NVME target path. Signed-off-by: Dick Kennedy Signed-off-by: James Smart --- drivers/scsi/lpfc/lpfc_crtn.h | 1 + drivers/scsi/lpfc/lpfc_init.c | 1 + drivers/scsi/lpfc/lpfc_nvmet.c | 293 ++--- 3 files changed, 191 insertions(+), 104 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_crtn.h b/drivers/scsi/lpfc/lpfc_crtn.h index c7df22683e85..4ae9ba425e78 100644 --- a/drivers/scsi/lpfc/lpfc_crtn.h +++ b/drivers/scsi/lpfc/lpfc_crtn.h @@ -566,6 +566,7 @@ void lpfc_nvme_abort_fcreq_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, struct lpfc_wcqe_complete *abts_cmpl); void lpfc_nvme_cmd_template(void); +void lpfc_nvmet_cmd_template(void); extern int lpfc_enable_nvmet_cnt; extern unsigned long long lpfc_enable_nvmet[]; extern int lpfc_no_hba_reset_cnt; diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 68adea8e0a04..17551540a1c5 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -12584,6 +12584,7 @@ lpfc_init(void) return -ENOMEM; } lpfc_nvme_cmd_template(); + lpfc_nvmet_cmd_template(); /* Initialize in case vector mapping is needed */ lpfc_used_cpu = NULL; diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c index a17583ce1b06..66218afa1453 100644 --- a/drivers/scsi/lpfc/lpfc_nvmet.c +++ b/drivers/scsi/lpfc/lpfc_nvmet.c @@ -74,6 +74,149 @@ static int lpfc_nvmet_unsol_ls_issue_abort(struct lpfc_hba *, static void lpfc_nvmet_wqfull_flush(struct lpfc_hba *, struct lpfc_queue *, struct lpfc_nvmet_rcv_ctx *); +union lpfc_wqe128 lpfc_tsend_cmd_template; +union lpfc_wqe128 lpfc_treceive_cmd_template; +union lpfc_wqe128 lpfc_trsp_cmd_template; + +/* Setup WQE templates for NVME IOs */ +void +lpfc_nvmet_cmd_template() +{ + union lpfc_wqe128 *wqe; + + /* TSEND template */ + wqe = &lpfc_tsend_cmd_template; + memset(wqe, 0, sizeof(union lpfc_wqe128)); + + /* Word 0, 1, 2 - BDE is variable */ + + /* Word 3 - payload_offset_len is zero */ + + /* Word 4 - relative_offset is variable */ + + /* Word 5 - is zero */ + + /* Word 6 - ctxt_tag, xri_tag is variable */ + + /* Word 7 - wqe_ar is variable */ + bf_set(wqe_cmnd, &wqe->fcp_tsend.wqe_com, CMD_FCP_TSEND64_WQE); + bf_set(wqe_pu, &wqe->fcp_tsend.wqe_com, PARM_REL_OFF); + bf_set(wqe_class, &wqe->fcp_tsend.wqe_com, CLASS3); + bf_set(wqe_ct, &wqe->fcp_tsend.wqe_com, SLI4_CT_RPI); + bf_set(wqe_ar, &wqe->fcp_tsend.wqe_com, 1); + + /* Word 8 - abort_tag is variable */ + + /* Word 9 - reqtag, rcvoxid is variable */ + + /* Word 10 - wqes, xc is variable */ + bf_set(wqe_nvme, &wqe->fcp_tsend.wqe_com, 1); + bf_set(wqe_dbde, &wqe->fcp_tsend.wqe_com, 1); + bf_set(wqe_wqes, &wqe->fcp_tsend.wqe_com, 0); + bf_set(wqe_xc, &wqe->fcp_tsend.wqe_com, 1); + bf_set(wqe_iod, &wqe->fcp_tsend.wqe_com, LPFC_WQE_IOD_WRITE); + bf_set(wqe_lenloc, &wqe->fcp_tsend.wqe_com, LPFC_WQE_LENLOC_WORD12); + + /* Word 11 - sup, irsp, irsplen is variable */ + bf_set(wqe_cmd_type, &wqe->fcp_tsend.wqe_com, FCP_COMMAND_TSEND); + bf_set(wqe_cqid, &wqe->fcp_tsend.wqe_com, LPFC_WQE_CQ_ID_DEFAULT); + bf_set(wqe_sup, &wqe->fcp_tsend.wqe_com, 0); + bf_set(wqe_irsp, &wqe->fcp_tsend.wqe_com, 0); + bf_set(wqe_irsplen, &wqe->fcp_tsend.wqe_com, 0); + bf_set(wqe_pbde, &wqe->fcp_tsend.wqe_com, 0); + + /* Word 12 - fcp_data_len is variable */ + + /* Word 13, 14, 15 - PBDE is zero */ + + /* TRECEIVE template */ + wqe = &lpfc_treceive_cmd_template; + memset(wqe, 0, sizeof(union lpfc_wqe128)); + + /* Word 0, 1, 2 - BDE is variable */ + + /* Word 3 */ + wqe->fcp_treceive.payload_offset_len = TXRDY_PAYLOAD_LEN; + + /* Word 4 - relative_offset is variable */ + + /* Word 5 - is zero */ + + /* Word 6 - ctxt_tag, xri_tag is variable */ + + /* Word 7 */ + bf_set(wqe_cmnd, &wqe->fcp_treceive.wqe_com, CMD_FCP_TRECEIVE64_WQE); + bf_set(wqe_pu, &wqe->fcp_treceive.wqe_com, PARM_REL_OFF); + bf_set(wqe_class, &wqe->fcp_treceive.wqe_com, CLASS3); + bf_set(wqe_ct, &wqe->fcp_treceive.wqe_com, SLI4_CT_RPI); + bf_set(wqe_ar, &wqe->fcp_treceive.wqe_com, 0); + + /* Word 8 - abort_tag is variable */ + + /* Word 9 - reqtag, rcvoxid is variable */ + + /* Word 10 - xc is variable */ + bf_set(wqe_dbde, &wqe->fcp_treceive.wqe_com, 1); + bf_set(wqe_wqes, &wqe->fcp_treceive.wqe_com, 0); + bf_set(wqe_nvme, &wqe->fcp_treceiv
[PATCH 1/9] lpfc: Fix NVME Initiator FirstBurst
First Burst support was not properly indicated in NVMe PRLI. Correct the bit position and the logic to check and set first burst support. Signed-off-by: Dick Kennedy Signed-off-by: James Smart --- drivers/scsi/lpfc/lpfc_nportdisc.c | 15 ++- drivers/scsi/lpfc/lpfc_nvme.h | 2 ++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_nportdisc.c b/drivers/scsi/lpfc/lpfc_nportdisc.c index b63179d895e2..022060636ae1 100644 --- a/drivers/scsi/lpfc/lpfc_nportdisc.c +++ b/drivers/scsi/lpfc/lpfc_nportdisc.c @@ -1998,8 +1998,14 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ndlp->nlp_type |= NLP_NVME_TARGET; if (bf_get_be32(prli_disc, nvpr)) ndlp->nlp_type |= NLP_NVME_DISCOVERY; + + /* +* If prli_fba is set, the Target supports FirstBurst. +* If prli_fb_sz is 0, the FirstBurst size is unlimited, +* otherwise it defines the actual size supported by +* the NVME Target. +*/ if ((bf_get_be32(prli_fba, nvpr) == 1) && - (bf_get_be32(prli_fb_sz, nvpr) > 0) && (phba->cfg_nvme_enable_fb) && (!phba->nvmet_support)) { /* Both sides support FB. The target's first @@ -2008,6 +2014,13 @@ lpfc_cmpl_prli_prli_issue(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, ndlp->nlp_flag |= NLP_FIRSTBURST; ndlp->nvme_fb_size = bf_get_be32(prli_fb_sz, nvpr); + + /* Expressed in units of 512 bytes */ + if (ndlp->nvme_fb_size) + ndlp->nvme_fb_size <<= + LPFC_NVME_FB_SHIFT; + else + ndlp->nvme_fb_size = LPFC_NVME_MAX_FB; } } diff --git a/drivers/scsi/lpfc/lpfc_nvme.h b/drivers/scsi/lpfc/lpfc_nvme.h index e79f8f75758c..48b0229ebc99 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.h +++ b/drivers/scsi/lpfc/lpfc_nvme.h @@ -27,6 +27,8 @@ #define LPFC_NVME_WAIT_TMO 10 #define LPFC_NVME_EXPEDITE_XRICNT 8 +#define LPFC_NVME_FB_SHIFT 9 +#define LPFC_NVME_MAX_FB (1 << 20) /* 1M */ struct lpfc_nvme_qhandle { uint32_t index; /* WQ index to use */ -- 2.13.1
[PATCH 2/9] lpfc: Code cleanup for 128byte wqe data type
The driver is very sloppy about the WQE structure passed between routines. The base struct type is a 64byte wqe. But in many routines they typecast and access 128byte wqes. There were a couple of cases in the past (corrected already) where the typecasts were incorrectly done and the 64byte buffer was accessed as a 128 byte buffer. Clean this up by properly declaring wqe's as 128byte wqe's and removing the typecasts. 64byte wqes are considered a subset of the 128byte wqes. Signed-off-by: Dick Kennedy Signed-off-by: James Smart --- drivers/scsi/lpfc/lpfc_hw4.h | 11 +-- drivers/scsi/lpfc/lpfc_nvme.c | 25 +++--- drivers/scsi/lpfc/lpfc_nvmet.c | 12 +++ drivers/scsi/lpfc/lpfc_sli.c | 74 ++ drivers/scsi/lpfc/lpfc_sli.h | 5 ++- 5 files changed, 61 insertions(+), 66 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_hw4.h b/drivers/scsi/lpfc/lpfc_hw4.h index 37c547b4bc78..a2f372d14eaa 100644 --- a/drivers/scsi/lpfc/lpfc_hw4.h +++ b/drivers/scsi/lpfc/lpfc_hw4.h @@ -4601,11 +4601,18 @@ union lpfc_wqe128 { struct fcp_icmnd64_wqe fcp_icmd; struct fcp_iread64_wqe fcp_iread; struct fcp_iwrite64_wqe fcp_iwrite; + struct abort_cmd_wqe abort_cmd; + struct create_xri_wqe create_xri; + struct xmit_bcast64_wqe xmit_bcast64; + struct xmit_seq64_wqe xmit_sequence; + struct xmit_bls_rsp64_wqe xmit_bls_rsp; + struct xmit_els_rsp64_wqe xmit_els_rsp; + struct els_request64_wqe els_req; + struct gen_req64_wqe gen_req; struct fcp_trsp64_wqe fcp_trsp; struct fcp_tsend64_wqe fcp_tsend; struct fcp_treceive64_wqe fcp_treceive; - struct xmit_seq64_wqe xmit_sequence; - struct gen_req64_wqe gen_req; + struct send_frame_wqe send_frame; }; struct lpfc_grp_hdr { diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c index 6ea6cc372647..6d215f27448f 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.c +++ b/drivers/scsi/lpfc/lpfc_nvme.c @@ -275,14 +275,14 @@ lpfc_nvme_cmpl_gen_req(struct lpfc_hba *phba, struct lpfc_iocbq *cmdwqe, static int lpfc_nvme_gen_req(struct lpfc_vport *vport, struct lpfc_dmabuf *bmp, struct lpfc_dmabuf *inp, -struct nvmefc_ls_req *pnvme_lsreq, -void (*cmpl)(struct lpfc_hba *, struct lpfc_iocbq *, - struct lpfc_wcqe_complete *), -struct lpfc_nodelist *ndlp, uint32_t num_entry, -uint32_t tmo, uint8_t retry) + struct nvmefc_ls_req *pnvme_lsreq, + void (*cmpl)(struct lpfc_hba *, struct lpfc_iocbq *, + struct lpfc_wcqe_complete *), + struct lpfc_nodelist *ndlp, uint32_t num_entry, + uint32_t tmo, uint8_t retry) { - struct lpfc_hba *phba = vport->phba; - union lpfc_wqe *wqe; + struct lpfc_hba *phba = vport->phba; + union lpfc_wqe128 *wqe; struct lpfc_iocbq *genwqe; struct ulp_bde64 *bpl; struct ulp_bde64 bde; @@ -628,8 +628,7 @@ lpfc_nvme_adj_fcp_sgls(struct lpfc_vport *vport, * the dma address. */ - /* 128 byte wqe support here */ - wqe = (union lpfc_wqe128 *)&lpfc_ncmd->cur_iocbq.wqe; + wqe = &lpfc_ncmd->cur_iocbq.wqe; /* * Adjust the FCP_CMD and FCP_RSP DMA data and sge_len to @@ -1048,7 +1047,7 @@ lpfc_nvme_prep_io_cmd(struct lpfc_vport *vport, struct lpfc_hba *phba = vport->phba; struct nvmefc_fcp_req *nCmd = lpfc_ncmd->nvmeCmd; struct lpfc_iocbq *pwqeq = &(lpfc_ncmd->cur_iocbq); - union lpfc_wqe128 *wqe = (union lpfc_wqe128 *)&pwqeq->wqe; + union lpfc_wqe128 *wqe = &pwqeq->wqe; uint32_t req_len; if (!pnode || !NLP_CHK_NODE_ACT(pnode)) @@ -1187,7 +1186,7 @@ lpfc_nvme_prep_io_dma(struct lpfc_vport *vport, { struct lpfc_hba *phba = vport->phba; struct nvmefc_fcp_req *nCmd = lpfc_ncmd->nvmeCmd; - union lpfc_wqe128 *wqe = (union lpfc_wqe128 *)&lpfc_ncmd->cur_iocbq.wqe; + union lpfc_wqe128 *wqe = &lpfc_ncmd->cur_iocbq.wqe; struct sli4_sge *sgl = lpfc_ncmd->nvme_sgl; struct scatterlist *data_sg; struct sli4_sge *first_data_sgl; @@ -1595,7 +1594,7 @@ lpfc_nvme_fcp_abort(struct nvme_fc_local_port *pnvme_lport, struct lpfc_iocbq *abts_buf; struct lpfc_iocbq *nvmereq_wqe; struct lpfc_nvme_fcpreq_priv *freqpriv; - union lpfc_wqe *abts_wqe; + union lpfc_wqe128 *abts_wqe; unsigned long flags; int ret_val; @@ -2139,7 +2138,7 @@ lpfc_new_nvme_buf(struct lpfc_vport *vport, int num_to_alloc) break; } pwqeq = &(lpfc_ncmd->cur_iocbq); - wqe = (union lpfc_wqe128 *)&pwqeq->wqe; + wqe = &pwqeq->wqe; /* Allocate iotag for lpfc_ncmd->cur_iocbq. */ iotag = lpfc_sli_next_iotag(phba,
[PATCH 6/9] lpfc: Fix mailbox wait for POST_SGL mbox command
POST_SGL_PAGES mailbox command failed with status (timeout). wait_event_interruptible_timeout when called from mailbox wait interface, gets interrupted, and will randomly fail. Behavior seems very specific to 1 particular server type. Fix by changing from wait_event_interruptible_timeout to wait_for_completion_timeout. Signed-off-by: Dick Kennedy Signed-off-by: James Smart --- drivers/scsi/lpfc/lpfc_sli.c | 34 -- drivers/scsi/lpfc/lpfc_sli.h | 1 + 2 files changed, 13 insertions(+), 22 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 7999a40e1370..1a9083adef1f 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -2388,18 +2388,18 @@ lpfc_sli_chk_mbx_command(uint8_t mbxCommand) void lpfc_sli_wake_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq) { - wait_queue_head_t *pdone_q; unsigned long drvr_flag; + struct completion *pmbox_done; /* -* If pdone_q is empty, the driver thread gave up waiting and +* If pmbox_done is empty, the driver thread gave up waiting and * continued running. */ pmboxq->mbox_flag |= LPFC_MBX_WAKE; spin_lock_irqsave(&phba->hbalock, drvr_flag); - pdone_q = (wait_queue_head_t *) pmboxq->context1; - if (pdone_q) - wake_up_interruptible(pdone_q); + pmbox_done = (struct completion *)pmboxq->context3; + if (pmbox_done) + complete(pmbox_done); spin_unlock_irqrestore(&phba->hbalock, drvr_flag); return; } @@ -11665,31 +11665,25 @@ int lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq, uint32_t timeout) { - DECLARE_WAIT_QUEUE_HEAD_ONSTACK(done_q); - MAILBOX_t *mb = NULL; + struct completion mbox_done; int retval; unsigned long flag; - /* The caller might set context1 for extended buffer */ - if (pmboxq->context1) - mb = (MAILBOX_t *)pmboxq->context1; - pmboxq->mbox_flag &= ~LPFC_MBX_WAKE; /* setup wake call as IOCB callback */ pmboxq->mbox_cmpl = lpfc_sli_wake_mbox_wait; - /* setup context field to pass wait_queue pointer to wake function */ - pmboxq->context1 = &done_q; + /* setup context3 field to pass wait_queue pointer to wake function */ + init_completion(&mbox_done); + pmboxq->context3 = &mbox_done; /* now issue the command */ retval = lpfc_sli_issue_mbox(phba, pmboxq, MBX_NOWAIT); if (retval == MBX_BUSY || retval == MBX_SUCCESS) { - wait_event_interruptible_timeout(done_q, - pmboxq->mbox_flag & LPFC_MBX_WAKE, - msecs_to_jiffies(timeout * 1000)); + wait_for_completion_timeout(&mbox_done, + msecs_to_jiffies(timeout * 1000)); spin_lock_irqsave(&phba->hbalock, flag); - /* restore the possible extended buffer for free resource */ - pmboxq->context1 = (uint8_t *)mb; + pmboxq->context3 = NULL; /* * if LPFC_MBX_WAKE flag is set the mailbox is completed * else do not free the resources. @@ -11701,11 +11695,7 @@ lpfc_sli_issue_mbox_wait(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmboxq, pmboxq->mbox_cmpl = lpfc_sli_def_mbox_cmpl; } spin_unlock_irqrestore(&phba->hbalock, flag); - } else { - /* restore the possible extended buffer for free resource */ - pmboxq->context1 = (uint8_t *)mb; } - return retval; } diff --git a/drivers/scsi/lpfc/lpfc_sli.h b/drivers/scsi/lpfc/lpfc_sli.h index ad7b2e0a2018..431754195505 100644 --- a/drivers/scsi/lpfc/lpfc_sli.h +++ b/drivers/scsi/lpfc/lpfc_sli.h @@ -147,6 +147,7 @@ typedef struct lpfcMboxq { struct lpfc_vport *vport;/* virtual port pointer */ void *context1; /* caller context information */ void *context2; /* caller context information */ + void *context3; void (*mbox_cmpl) (struct lpfc_hba *, struct lpfcMboxq *); uint8_t mbox_flag; -- 2.13.1
[PATCH 9/9] lpfc: Change Copyright of 12.0.0.1 modified files to 2018
Updated Copyright in files updated as part of 12.0.0.1 Signed-off-by: Dick Kennedy Signed-off-by: James Smart --- drivers/scsi/lpfc/lpfc_nvme.h | 2 +- drivers/scsi/lpfc/lpfc_scsi.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_nvme.h b/drivers/scsi/lpfc/lpfc_nvme.h index 48b0229ebc99..9216653e0441 100644 --- a/drivers/scsi/lpfc/lpfc_nvme.h +++ b/drivers/scsi/lpfc/lpfc_nvme.h @@ -1,7 +1,7 @@ /*** * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters.* - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex.* diff --git a/drivers/scsi/lpfc/lpfc_scsi.h b/drivers/scsi/lpfc/lpfc_scsi.h index 5da7e15400cb..8e38e0204c47 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.h +++ b/drivers/scsi/lpfc/lpfc_scsi.h @@ -1,7 +1,7 @@ /*** * This file is part of the Emulex Linux Device Driver for * * Fibre Channel Host Bus Adapters.* - * Copyright (C) 2017 Broadcom. All Rights Reserved. The term * + * Copyright (C) 2017-2018 Broadcom. All Rights Reserved. The term * * “Broadcom” refers to Broadcom Limited and/or its subsidiaries. * * Copyright (C) 2004-2016 Emulex. All rights reserved. * * EMULEX and SLI are trademarks of Emulex.* -- 2.13.1
[PATCH 8/9] lpfc: update driver version to 12.0.0.1
Update the driver version to 12.0.0.1 Signed-off-by: Dick Kennedy Signed-off-by: James Smart --- drivers/scsi/lpfc/lpfc_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/lpfc/lpfc_version.h b/drivers/scsi/lpfc/lpfc_version.h index b1ae62a44aae..e8b089abbfb3 100644 --- a/drivers/scsi/lpfc/lpfc_version.h +++ b/drivers/scsi/lpfc/lpfc_version.h @@ -20,7 +20,7 @@ * included with this package. * ***/ -#define LPFC_DRIVER_VERSION "12.0.0.0" +#define LPFC_DRIVER_VERSION "12.0.0.1" #define LPFC_DRIVER_NAME "lpfc" /* Used for SLI 2/3 */ -- 2.13.1
[PATCH 7/9] lpfc: Memory allocation error during driver start-up on power8
The driver fails to allocate command buffers in the routine lpfc_new_scsi_buf_s4 There is an inconsistency between lpfc_mem_alloc(), where the phba->lpfc_sg_dma_buf_pool is created, and lpfc_new_scsi_buf_s4(), when we allocate a buffer from the pool and check the alignment. The alignment should be on a page boundary, based on LPFC_SLI3_BG_ENABLED in sli3_options, for both cases. Fix by explicitly tracking sli4 vs sli3 and BG options. The result is that phba->cfg_sg_dma_buf_size is now set correctly for SLI-4. Signed-off-by: Dick Kennedy Signed-off-by: James Smart --- drivers/scsi/lpfc/lpfc_attr.c | 4 drivers/scsi/lpfc/lpfc_init.c | 2 +- drivers/scsi/lpfc/lpfc_scsi.c | 7 ++- drivers/scsi/lpfc/lpfc_sli.c | 19 ++- 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 46f6d97d21d6..2ac1d21c553f 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -6344,6 +6344,10 @@ lpfc_get_cfgparam(struct lpfc_hba *phba) phba->cfg_poll = 0; else phba->cfg_poll = lpfc_poll; + + if (phba->cfg_enable_bg) + phba->sli3_options |= LPFC_SLI3_BG_ENABLED; + lpfc_suppress_rsp_init(phba, lpfc_suppress_rsp); lpfc_enable_fc4_type_init(phba, lpfc_enable_fc4_type); diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 17551540a1c5..7887468c71b4 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -5912,7 +5912,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba) * Since lpfc_sg_seg_cnt is module param, the sg_dma_buf_size * used to create the sg_dma_buf_pool must be calculated. */ - if (phba->cfg_enable_bg) { + if (phba->sli3_options & LPFC_SLI3_BG_ENABLED) { /* * The scsi_buf for a T10-DIF I/O holds the FCP cmnd, * the FCP rsp, and a SGE. Sice we have no control diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index fb81e8a8fb1c..050f04418f5f 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -837,8 +837,13 @@ lpfc_new_scsi_buf_s4(struct lpfc_vport *vport, int num_to_alloc) * 4K Page alignment is CRITICAL to BlockGuard, double check * to be sure. */ - if (phba->cfg_enable_bg && (((unsigned long)(psb->data) & + if ((phba->sli3_options & LPFC_SLI3_BG_ENABLED) && + (((unsigned long)(psb->data) & (unsigned long)(SLI4_PAGE_SIZE - 1)) != 0)) { + lpfc_printf_log(phba, KERN_ERR, LOG_FCP, + "3369 Memory alignment error " + "addr=%lx\n", + (unsigned long)psb->data); dma_pool_free(phba->lpfc_sg_dma_buf_pool, psb->data, psb->dma_handle); kfree(psb); diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 1a9083adef1f..cb17e2b2be81 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -4993,13 +4993,14 @@ lpfc_sli_config_port(struct lpfc_hba *phba, int sli_mode) phba->hbq_get = phba->mbox->us.s3_pgp.hbq_get; phba->port_gp = phba->mbox->us.s3_pgp.port; - if (phba->cfg_enable_bg) { - if (pmb->u.mb.un.varCfgPort.gbg) - phba->sli3_options |= LPFC_SLI3_BG_ENABLED; - else + if (phba->sli3_options & LPFC_SLI3_BG_ENABLED) { + if (pmb->u.mb.un.varCfgPort.gbg == 0) { + phba->cfg_enable_bg = 0; + phba->sli3_options &= ~LPFC_SLI3_BG_ENABLED; lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0443 Adapter did not grant " "BlockGuard\n"); + } } } else { phba->hbq_get = NULL; @@ -6991,12 +6992,12 @@ lpfc_sli4_hba_setup(struct lpfc_hba *phba) * then turn off the global config parameters to disable the * feature in the driver. This is not a fatal error. */ - phba->sli3_options &= ~LPFC_SLI3_BG_ENABLED; - if (phba->cfg_enable_bg) { - if (bf_get(lpfc_mbx_rq_ftr_rsp_dif, &mqe->un.req_ftrs)) - phba->sli3_options |= LPFC_SLI3_BG_ENABLED; - else + if (phba->sli3_options & LPFC_SLI3_BG_ENABLED) { + if (!(bf_get(lpfc_mbx_rq_ftr_rsp_dif, &mqe->un.req_ftrs))) { + phba->cfg_enable_bg = 0; + phba->sli3_options &= ~LPFC_SLI3_BG_
Re: [PATCH V2] scsi: qla2xxx: Fix crashes in qla2x00_probe_one on probe failure
Hi Bill, > On Mar 4, 2018, at 9:02 PM, Bill Kuzeja wrote: > > Because of the shifting around of code in qla2x00_probe_one recently, > failures during adapter initialization can lead to problems, i.e. NULL > pointer crashes and doubly freed data structures which cause eventual > panics. > > This V2 version makes the relevant memory free routines idempotent, so > repeat calls won't cause any harm. I also removed the problematic > probe_init_failed exit point as it is not needed. > > Fixes: d64d6c5671db ("scsi: qla2xxx: Fix NULL pointer crash due to probe > failure") > Signed-off-by: Bill Kuzeja > > --- > > Some of these issues are due to: > > commit d64d6c5671db scsi: qla2xxx: Fix NULL pointer crash due to probe failure > > where some frees were moved around, as well as the error exit from > a qla2x00_request_irqs failure. > > This was a fix for: > > commit d74595278f4a scsi: qla2xxx: Add multiple queue pair functionality. > > which caused problems of its own. > > To reproduce these issues, I run a test where I break the card early in > init, (and also through kprobe fault injection). This way, I've been able > to hit several different types of crashes, all started by failures of > various routines called throughout the probe. > > The problematic routines that fail and their exit points are: > > qla2x00_alloc_queues => probe_init_failed > initialize_adapter=> probe_failed > kthread_create=> probe_failed > scsi_add_host => probe_failed > > Exit points are ordered in this way: > > probe_init_failed: >qla2x00_free_req_que(ha, req); >ha->req_q_map[0] = NULL; >clear_bit(0, ha->req_qid_map); >qla2x00_free_rsp_que(ha, rsp); >ha->rsp_q_map[0] = NULL; >clear_bit(0, ha->rsp_qid_map); >ha->max_req_queues = ha->max_rsp_queues = 0; > > probe_failed: >if (base_vha->timer_active) >qla2x00_stop_timer(base_vha); > ... >qla2x00_free_device(base_vha); > >scsi_host_put(base_vha->host); > > probe_hw_failed: >qla2x00_mem_free(ha); >qla2x00_free_req_que(ha, req); >qla2x00_free_rsp_que(ha, rsp); >qla2x00_clear_drv_active(ha); > > Note that qla2x00_free_device calls qla2x00_mem_free and > qla2x00_free_rsp_que and qla2x00_free_req_que. So if we exit to > probe_failed or probe_init_failed, we'll end up calling these > routines multiple times. > > These routines are not idempotent, I am making them so. This solves > most of the issues. > > Also probe_init_failed is not needed. In the place that it is called, > ha->req_q_map[0] and ha->rsp_q_map[0] are not setup. And we now call > qla2x00_free_rsp_que/qla2x00_free_req_que below in probe_hw_failed. > I removed this exit point entirely. > > Along the way I found that the return code for qla2x00_alloc_queues > never really causes us to exit out of the probe routine. > > In order to fail... > >if (!qla2x00_alloc_queues(ha, req, rsp)) { > > ...we must return 0. However, internally, if this routine succeeds it > returns 1 and if it fails it returns -ENOMEM. So I am modifying > qla2x00_alloc_queues to fall in line with other return conventions > where zero is a success (and obviously have changed the probe routine > accordingly). > > One more issue falls out of this case: when qla2x00_abort_all_cmds > is invoked from qla2x00_free_device and request queues are not > allocated (qla2x00_alloc_queues has not succeeded), we crash on a NULL > pointer (ha->req_q_map[que]). So check for this at the start of > qla2x00_abort_all_cmds and exit accordingly. > > I've tested out these changes thoroughly failing initialization at > various times. I've also used kprobes to inject errors to force us > into various error paths. > --- > drivers/scsi/qla2xxx/qla_os.c | 59 +++ > 1 file changed, 37 insertions(+), 22 deletions(-) > > diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c > index afcb5567..3860bdfc 100644 > --- a/drivers/scsi/qla2xxx/qla_os.c > +++ b/drivers/scsi/qla2xxx/qla_os.c > @@ -454,7 +454,7 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha, > struct req_que *req, > ha->req_q_map[0] = req; > set_bit(0, ha->rsp_qid_map); > set_bit(0, ha->req_qid_map); > - return 1; > + return 0; > > fail_qpair_map: > kfree(ha->base_qpair); > @@ -471,6 +471,9 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha, > struct req_que *req, > > static void qla2x00_free_req_que(struct qla_hw_data *ha, struct req_que *req) > { > + if (!ha->req_q_map) > + return; > + > if (IS_QLAFX00(ha)) { > if (req && req->ring_fx00) > dma_free_coherent(&ha->pdev->dev, > @@ -481,14 +484,17 @@ static void qla2x00_free_req_que(struct qla_hw_data > *ha, struct req_que *req) > (req->length + 1) * sizeof(request_t), > req->ring, req->dma); > > - if (req) >
Re: [PATCH v2] scsi: ufs-qcom: add number of lanes for Tx and Rx links
On Tue, Feb 27, 2018 at 01:46:17PM +0800, Can Guo wrote: > From: Gilad Broner > > Different platforms may have different number of lanes for the UFS Tx/Rx > links. Add parameter to device tree specifying how many lanes should be > configured for the UFS Tx/Rx links. And don't print err message for clocks > that are optional, this leads to unnecessary confusion about failure. > > Signed-off-by: Gilad Broner > Signed-off-by: Subhash Jadavani > Signed-off-by: Can Guo > --- > > Changes since v1: > - Change commit subject for better description. > - Incorporated Rob's review comments to use lanes-tx and lanes-rx > to handle asymmetric Tx/Rx links. > > .../devicetree/bindings/ufs/ufshcd-pltfrm.txt | 4 ++ Reviewed-by: Rob Herring > drivers/scsi/ufs/ufs-qcom.c| 65 > +- > drivers/scsi/ufs/ufshcd.c | 29 ++ > drivers/scsi/ufs/ufshcd.h | 5 ++ > 4 files changed, 78 insertions(+), 25 deletions(-)
Re: [PATCH 2/2] m68k/amiga - Zorro ESP: new zorro_esp.c
Hi Kars, Index 1 should have been ZORRO_PROD_PHASE5_CYBERSTORM_MK_II, I've corrected that in the meantime. Fastlane / Blizzard 1230_II distinction is something I an not quite sure about - does the probe function get called twice if the device table contains the same ID twice but with different driver_data contents? Cheers, Michael On Mon, Mar 5, 2018 at 9:02 PM, Kars de Jong wrote: > 2018-03-04 0:54 GMT+01:00 Michael Schmitz : >> +static struct zorro_device_id zorro_esp_zorro_tbl[] = { >> + { >> + .id = ZORRO_PROD_PHASE5_BLIZZARD_1220_CYBERSTORM, >> + .driver_data = (unsigned long)&zorro_esp_driver_data[0], >> + }, >> + { >> + .id = >> ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060, >> + .driver_data = (unsigned long)&zorro_esp_driver_data[0], >> + }, >> + { >> + .id = ZORRO_PROD_PHASE5_CYBERSTORM_MK_II, >> + .driver_data = (unsigned long)&zorro_esp_driver_data[1], >> + }, >> + { >> + .id = ZORRO_PROD_PHASE5_BLIZZARD_2060, >> + .driver_data = (unsigned long)&zorro_esp_driver_data[2], >> + }, >> + { >> + .id = ZORRO_PROD_PHASE5_BLIZZARD_1230_IV_1260, >> + .driver_data = (unsigned long)&zorro_esp_driver_data[3], >> + }, >> + { >> + .id = >> ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060, >> + .driver_data = (unsigned long)&zorro_esp_driver_data[4], >> + }, >> + { 0 } >> +}; >> +MODULE_DEVICE_TABLE(zorro, zorro_esp_zorro_tbl); > > > The ID ZORRO_PROD_PHASE5_BLIZZARD_1230_II_FASTLANE_Z3_CYBERSCSI_CYBERSTORM060 > is used at index 1 and index 5. > I'm guessing only the first one will be detected. > > Regards, > > Kars.
Re: [PATCH] scsi: lpfc: Switch memcpy_fromio() to __read32_copy()
Hi, James, At least on MIPS (Loongson-3), we found that this patch is necessary. Huacai -- Original -- From: "James Smart"; Date: Mon, Mar 5, 2018 11:37 PM To: "陈华才"; "Dick Kennedy"; Cc: "James E . J . Bottomley"; "Martin K . Petersen"; "Fuxin Zhang"; "linux-scsi"; "stable"; Subject: Re: [PATCH] scsi: lpfc: Switch memcpy_fromio() to __read32_copy() On 3/4/2018 10:56 PM, 陈华才 wrote: > No one has the same problem? Or this patch need improve? > > Huacai > > -- Original -- > From: "陈华才"; > Date: Thu, Mar 1, 2018 01:59 PM > To: "James Smart"; "Dick > Kennedy"; > Cc: "James E . J . Bottomley"; "Martin K . > Petersen"; "Fuxin Zhang"; > "linux-scsi"; "stable"; > Subject: Re:[PATCH] scsi: lpfc: Switch memcpy_fromio() to __read32_copy() > > Ping? > > -- Original -- > From: "Huacai Chen"; > Date: Fri, Jan 26, 2018 08:53 PM > To: "James Smart"; "Dick > Kennedy"; > Cc: "James E . J . Bottomley"; "Martin K . > Petersen"; "Fuxin Zhang"; > "linux-scsi"; "Huacai Chen"; > "stable"; > Subject: [PATCH] scsi: lpfc: Switch memcpy_fromio() to __read32_copy() > > In commit bc73905abf770192 ("[SCSI] lpfc 8.3.16: SLI Additions, updates, > and code cleanup"), lpfc_memcpy_to_slim() have switched memcpy_toio() to > __write32_copy() in order to prevent unaligned 64 bit copy. Recently, we > found that lpfc_memcpy_from_slim() have similar issues, so let it switch > memcpy_fromio() to __read32_copy(). > > Cc: sta...@vger.kernel.org > Signed-off-by: Huacai Chen > --- > drivers/scsi/lpfc/lpfc_compat.h | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/scsi/lpfc/lpfc_compat.h b/drivers/scsi/lpfc/lpfc_compat.h > index 6b32b0a..47d4fad 100644 > --- a/drivers/scsi/lpfc/lpfc_compat.h > +++ b/drivers/scsi/lpfc/lpfc_compat.h > @@ -91,8 +91,8 @@ lpfc_memcpy_to_slim( void __iomem *dest, void *src, > unsigned int bytes) > static inline void > lpfc_memcpy_from_slim( void *dest, void __iomem *src, unsigned int bytes) > { > - /* actually returns 1 byte past dest */ > - memcpy_fromio( dest, src, bytes); > + /* convert bytes in argument list to word count for copy function */ > + __ioread32_copy(dest, src, bytes / sizeof(uint32_t)); > } > > #endif /* __BIG_ENDIAN */ Huacai, Note: the original change was 7 yrs ago and we've had no reports of issues. but This change didn't look necessary as the memcpy_XXXio() should allow byte alignments and byte-based lengths. Which means the original patch also wasn't necessary, which implies that the platform that had the issues has an api restriction not normally found on the other platforms. I have no problem with the change though. -- james Signed-off-by: James Smart
Re: [PATCH 2/2] m68k/amiga - Zorro ESP: new zorro_esp.c
Hi Geert, thanks, will comment on a few points that were not already raised by Finn below. On Tue, Mar 6, 2018 at 12:29 AM, Geert Uytterhoeven wrote: >> +static struct zorro_driver_data { >> + const char *name; >> + unsigned long offset; >> + unsigned long dma_offset; >> + int absolute; >> + int zorro3; /* offset is absolute address */ > > zorro3 is unused. Fastlane support isn't yet included, I expect to use it there. > >> +} zorro_esp_driver_data[] = { >> + { .name = "CyberStormI", .offset = 0xf400, .dma_offset = 0xf800, >> + .absolute = 0, .zorro3 = 0 }, >> + { .name = "CyberStormII", .offset = 0x1ff03, .dma_offset = 0x1ff43, >> + .absolute = 0, .zorro3 = 0 }, >> + { .name = "Blizzard 2060", .offset = 0x1ff00, .dma_offset = 0x1ffe0, >> + .absolute = 0, .zorro3 = 0 }, >> + { .name = "Blizzard 1230", .offset = 0x8000, .dma_offset = 0x1, >> + .absolute = 0, .zorro3 = 0 }, >> + { .name = "Blizzard 1230II", .offset = 0x1, .dma_offset = >> 0x10021, >> + .absolute = 0, .zorro3 = 0 }, >> + { .name = "Fastlane", .offset = 0x101, .dma_offset = 0x141, >> + .absolute = 0, .zorro3 = 1 }, >> + { 0 } > > I think it's better to not use an array here, but individual structs: > > static struct zorro_driver_data cyberstorm_data = ... > static struct zorro_driver_data cyberstorm2_data = ... > ... > > That makes it easier to review the references from zorro_esp_zorro_tbl[] > below. Might have avoided the error of using &zorro_esp_driver_data[0] twice ... >> +static unsigned char ctrl_data;/* Keep backup of the stuff written >> +* to ctrl_reg. Always write a copy >> +* to this register when writing to >> +* the hardware register! >> +*/ > > This should be part of the device's zorro_esp_priv. It's only used in the cyber_dma_setup, and I not actually read anywhere else. Might as well be on the stack instead of static... >> +static void zorro_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count, >> +u32 dma_count, int write, u8 cmd) >> +{ >> + struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp); >> + u8 __iomem *fifo = esp->regs + ESP_FDATA * 16; >> + u8 phase = esp->sreg & ESP_STAT_PMASK; >> + >> + cmd &= ~ESP_CMD_DMA; >> + zep->error = 0; >> + >> + /* We are passed DMA addresses i.e. physical addresses, but must use >> +* kernel virtual addresses here, so remap to virtual. This is easy >> +* enough for the case of residual bytes of an extended message in >> +* transfer - we know the address must be esp->command_block_dma. >> +* In other cases, hope that phys_to_virt() works ... >> +*/ >> + if (addr == esp->command_block_dma) >> + addr = (u32) esp->command_block; >> + else >> + addr = (u32) phys_to_virt(addr); > > To avoid having a need for phys_to_virt(), you should remember the addresses > passed to/returned from dma_map_*(). Interesting - can we be certain that only one mapping is being used at any one time? > > if you assign the address to a different variable with the proper > type, you don't > need the cast below > > + if (write) { > + u8 *dst = (u8 *)addr; > > ... here. > >> + } else { > > The read case doesn't use addr? It's hidden in ZORRO_ESP_PIO_LOOP and ZORRO_ESP_PIO_FILL, but it's there. Might be the reason for the u32 type? >> +static void zorro_esp_send_blz1230_dma_cmd(struct esp *esp, u32 addr, >> + u32 esp_count, u32 dma_count, int write, u8 cmd) >> +{ >> + struct blz1230_dma_registers *dregs = >> + (struct blz1230_dma_registers *) (esp->dma_regs); >> + u8 phase = esp->sreg & ESP_STAT_PMASK; >> + >> + if (phase == ESP_MIP) { >> + zorro_esp_send_pio_cmd(esp, addr, esp_count, >> + dma_count, write, cmd); >> + return; >> + } >> + >> + BUG_ON(!(cmd & ESP_CMD_DMA)); >> + >> + if (write) >> + cache_clear(addr, esp_count); >> + else >> + cache_push(addr, esp_count); > > dma_sync_*() > >> +static int zorro_esp_init_one(struct zorro_dev *z, >> + const struct zorro_device_id *ent) >> +{ >> + struct scsi_host_template *tpnt = &scsi_esp_template; >> + struct Scsi_Host *host; >> + struct esp *esp; >> + struct zorro_driver_data *zdd; >> + struct zorro_esp_priv *zep; >> + unsigned long board, ioaddr, dmaaddr; >> + int err = -ENOMEM; > > Initialization not needed. The initialized err variable is used when bailing out .. >> + >> + board = zorro_resource_start(z); >> + zdd = (struct
Re: [PATCH 2/2] m68k/amiga - Zorro ESP: new zorro_esp.c
On Tue, 6 Mar 2018, Michael Schmitz wrote: > >> +static void zorro_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 > >> esp_count, > >> +u32 dma_count, int write, u8 cmd) > >> +{ > >> + struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp); > >> + u8 __iomem *fifo = esp->regs + ESP_FDATA * 16; > >> + u8 phase = esp->sreg & ESP_STAT_PMASK; > >> + > >> + cmd &= ~ESP_CMD_DMA; > >> + zep->error = 0; > >> + > >> + /* We are passed DMA addresses i.e. physical addresses, but must > >> use > >> +* kernel virtual addresses here, so remap to virtual. This is easy > >> +* enough for the case of residual bytes of an extended message in > >> +* transfer - we know the address must be esp->command_block_dma. > >> +* In other cases, hope that phys_to_virt() works ... > >> +*/ > >> + if (addr == esp->command_block_dma) > >> + addr = (u32) esp->command_block; > >> + else > >> + addr = (u32) phys_to_virt(addr); > > > > To avoid having a need for phys_to_virt(), you should remember the > > addresses passed to/returned from dma_map_*(). > > Interesting - can we be certain that only one mapping is being used at > any one time? > I don't know how Geert's suggestion would work in this case. But I think we covered this problem back in December: https://marc.info/?l=linux-m68k&m=151365452606870 (That thread also helps explain the PIO vs. ESP_CMD_SELAS issue.) Is it sufficient to solve just the tag byte/MSG IN problem to get the driver working? (That is, the addr == esp->command_block_dma case.) If so, might it be simpler to address the full PIO problem in a separate patch? (Including the ESP_INTR_FDONE/MSG OUT issue.) --
Donation For Charity Work
-- Good Day, My wife and I have awarded you with a donation of $ 1,000,000.00 Dollars from part of our Jackpot Lottery of 50 Million Dollars, respond with your details for claims. We await your earliest response and God Bless you. Friedrich And Ann Mayrhofer.
Re: [PATCH 2/2] m68k/amiga - Zorro ESP: new zorro_esp.c
Hi Finn, Am 06.03.2018 um 16:04 schrieb Finn Thain: > On Tue, 6 Mar 2018, Michael Schmitz wrote: > +static void zorro_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count, +u32 dma_count, int write, u8 cmd) +{ + struct zorro_esp_priv *zep = ZORRO_ESP_GET_PRIV(esp); + u8 __iomem *fifo = esp->regs + ESP_FDATA * 16; + u8 phase = esp->sreg & ESP_STAT_PMASK; + + cmd &= ~ESP_CMD_DMA; + zep->error = 0; + + /* We are passed DMA addresses i.e. physical addresses, but must use +* kernel virtual addresses here, so remap to virtual. This is easy +* enough for the case of residual bytes of an extended message in +* transfer - we know the address must be esp->command_block_dma. +* In other cases, hope that phys_to_virt() works ... +*/ + if (addr == esp->command_block_dma) + addr = (u32) esp->command_block; + else + addr = (u32) phys_to_virt(addr); >>> >>> To avoid having a need for phys_to_virt(), you should remember the >>> addresses passed to/returned from dma_map_*(). >> >> Interesting - can we be certain that only one mapping is being used at >> any one time? >> > > I don't know how Geert's suggestion would work in this case. But I think I suppose storing the virtual address in the driver private data struct, and looking up that stored virtual address in the PIO transfer function. > we covered this problem back in December: > https://marc.info/?l=linux-m68k&m=151365452606870 > > (That thread also helps explain the PIO vs. ESP_CMD_SELAS issue.) Yes, rereading that thread now suggests we had explored a few options but the issue of autosense commands was making it a little too complicated. > Is it sufficient to solve just the tag byte/MSG IN problem to get the > driver working? (That is, the addr == esp->command_block_dma case.) > > If so, might it be simpler to address the full PIO problem in a separate > patch? (Including the ESP_INTR_FDONE/MSG OUT issue.) The driver works just fine using PIO exclusively for transferring the extended message bytes in message in phase, and doing everything else by DMA. The whole !write branch will never be executed, and I could just omit it entirely for now, or leave it as it was in the Mac driver. Cheers, Michael
Re: [PATCH 2/2] m68k/amiga - Zorro ESP: new zorro_esp.c
Hi Michael, On Tue, Mar 6, 2018 at 2:11 AM, Michael Schmitz wrote: > Index 1 should have been ZORRO_PROD_PHASE5_CYBERSTORM_MK_II, I've > corrected that in the meantime. > > Fastlane / Blizzard 1230_II distinction is something I an not quite > sure about - does the probe function get called twice if the device > table contains the same ID twice but with different driver_data > contents? No, the probe function gets called on the first match only. Cfr. drivers/zorro/zorro-driver.c:zorro_device_probe(). Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds
Re: [PATCH 2/2] m68k/amiga - Zorro ESP: new zorro_esp.c
Hi Michael, On Tue, Mar 6, 2018 at 2:33 AM, Michael Schmitz wrote: > On Tue, Mar 6, 2018 at 12:29 AM, Geert Uytterhoeven > wrote: >>> +static unsigned char ctrl_data;/* Keep backup of the stuff written >>> +* to ctrl_reg. Always write a copy >>> +* to this register when writing to >>> +* the hardware register! >>> +*/ >> >> This should be part of the device's zorro_esp_priv. > > It's only used in the cyber_dma_setup, and I not actually read > anywhere else. Might as well be on the stack instead of static... OK, I missed that. Yes, local variable is better. >>> +static int zorro_esp_init_one(struct zorro_dev *z, >>> + const struct zorro_device_id *ent) BTW, please call the probe/remove functions zorro_esp_probe() resp. zorro_esp_remove(). >>> +{ >>> + struct scsi_host_template *tpnt = &scsi_esp_template; >>> + struct Scsi_Host *host; >>> + struct esp *esp; >>> + struct zorro_driver_data *zdd; >>> + struct zorro_esp_priv *zep; >>> + unsigned long board, ioaddr, dmaaddr; >>> + int err = -ENOMEM; >> >> Initialization not needed. > > The initialized err variable is used when bailing out .. > >>> + >>> + board = zorro_resource_start(z); >>> + zdd = (struct zorro_driver_data *)ent->driver_data; >>> + >>> + pr_info(PFX "%s found at address 0x%lx.\n", zdd->name, board); >>> + >>> + if (zdd->absolute) { >>> + ioaddr = zdd->offset; >>> + dmaaddr = zdd->dma_offset; >>> + } else { >>> + ioaddr = board + zdd->offset; >>> + dmaaddr = board + zdd->dma_offset; >>> + } >>> + >>> + if (!zorro_request_device(z, zdd->name)) { >>> + pr_err(PFX "cannot reserve region 0x%lx, abort\n", >>> + board); >>> + return -EBUSY; >>> + } >>> + >>> + /* Fill in the required pieces of hostdata */ >>> + >>> + host = scsi_host_alloc(tpnt, sizeof(struct esp)); >>> + >>> + if (!host) { >>> + pr_err(PFX "No host detected; board configuration >>> problem?\n"); >>> + goto out_free; >>> + } > > here. But I can add the err=-NOMEM here. After out_free it returns fixed -ENODEV ;-) Doing "err = -ENOMEM" here, and returning err at the end is better, as it propagates meaningful error codes. Gr{oetje,eeting}s, Geert -- Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- ge...@linux-m68k.org In personal conversations with technical people, I call myself a hacker. But when I'm talking to journalists I just say "programmer" or something like that. -- Linus Torvalds