[PATCH 09/12] hpsa: reduce warning messages on device removal
Reviewed-by: Scott BeneshReviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace --- drivers/scsi/hpsa.c |6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 27a1aca..228d744 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1865,11 +1865,13 @@ static void hpsa_wait_for_outstanding_commands_for_dev(struct ctlr_info *h, break; if (++waits > 20) break; + msleep(1000); + } + + if (waits > 20) dev_warn(>pdev->dev, "%s: removing device with %d outstanding commands!\n", __func__, cmds); - msleep(1000); - } } static void hpsa_remove_device(struct ctlr_info *h,
[PATCH 10/12] hpsa: correct logical volume removal
Suggested-by: Martin WilckReviewed-by: Scott Benesh Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace --- drivers/scsi/hpsa.c |9 ++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 228d744..a536ed6 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1882,6 +1882,12 @@ static void hpsa_remove_device(struct ctlr_info *h, if (!h->scsi_host) return; + /* +* Allow for commands to drain +*/ + device->removed = 1; + hpsa_wait_for_outstanding_commands_for_dev(h, device); + if (is_logical_device(device)) { /* RAID */ sdev = scsi_device_lookup(h->scsi_host, device->bus, device->target, device->lun); @@ -1899,9 +1905,6 @@ static void hpsa_remove_device(struct ctlr_info *h, } } else { /* HBA */ - device->removed = 1; - hpsa_wait_for_outstanding_commands_for_dev(h, device); - hpsa_remove_sas_device(device); } }
[PATCH 08/12] hpsa: update queue depth for externals
- preserve external device queue depth during a scan operation. Reviewed-by: Scott BeneshReviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace --- drivers/scsi/hpsa.c |8 ++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 6a998b0..27a1aca 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1765,8 +1765,12 @@ static void hpsa_figure_phys_disk_ptrs(struct ctlr_info *h, * way too high for partial stripe writes */ logical_drive->queue_depth = qdepth; - else - logical_drive->queue_depth = h->nr_cmds; + else { + if (logical_drive->external) + logical_drive->queue_depth = EXTERNAL_QD; + else + logical_drive->queue_depth = h->nr_cmds; + } } static void hpsa_update_log_drive_phys_drive_ptrs(struct ctlr_info *h,
[PATCH 07/12] hpsa: correct smart path enabled
- correct re-enabling ioaccel after: 1) RAID transformations and 2) multi-path fail-overs. Reviewed-by: Scott BeneshReviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 189 +-- 1 file changed, 151 insertions(+), 38 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 4ab53df..6a998b0 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -787,7 +787,12 @@ static ssize_t host_show_hp_ssd_smart_path_enabled(struct device *dev, } offload_enabled = hdev->offload_enabled; spin_unlock_irqrestore(>lock, flags); - return snprintf(buf, 20, "%d\n", offload_enabled); + + if (hdev->devtype == TYPE_DISK || hdev->devtype == TYPE_ZBC) + return snprintf(buf, 20, "%d\n", offload_enabled); + else + return snprintf(buf, 40, "%s\n", + "Not applicable for a controller"); } #define MAX_PATHS 8 @@ -1270,7 +1275,7 @@ static void hpsa_show_dev_msg(const char *level, struct ctlr_info *h, dev->model, label, dev->offload_config ? '+' : '-', - dev->offload_enabled ? '+' : '-', + dev->offload_to_be_enabled ? '+' : '-', dev->expose_device); } @@ -1345,36 +1350,42 @@ static int hpsa_scsi_add_entry(struct ctlr_info *h, (*nadded)++; hpsa_show_dev_msg(KERN_INFO, h, device, device->expose_device ? "added" : "masked"); - device->offload_to_be_enabled = device->offload_enabled; - device->offload_enabled = 0; return 0; } -/* Update an entry in h->dev[] array. */ +/* + * Called during a scan operation. + * + * Update an entry in h->dev[] array. + */ static void hpsa_scsi_update_entry(struct ctlr_info *h, int entry, struct hpsa_scsi_dev_t *new_entry) { - int offload_enabled; /* assumes h->devlock is held */ BUG_ON(entry < 0 || entry >= HPSA_MAX_DEVICES); /* Raid level changed. */ h->dev[entry]->raid_level = new_entry->raid_level; + /* +* ioacccel_handle may have changed for a dual domain disk +*/ + h->dev[entry]->ioaccel_handle = new_entry->ioaccel_handle; + /* Raid offload parameters changed. Careful about the ordering. */ - if (new_entry->offload_config && new_entry->offload_enabled) { + if (new_entry->offload_config && new_entry->offload_to_be_enabled) { /* * if drive is newly offload_enabled, we want to copy the * raid map data first. If previously offload_enabled and * offload_config were set, raid map data had better be -* the same as it was before. if raid map data is changed +* the same as it was before. If raid map data has changed * then it had better be the case that * h->dev[entry]->offload_enabled is currently 0. */ h->dev[entry]->raid_map = new_entry->raid_map; h->dev[entry]->ioaccel_handle = new_entry->ioaccel_handle; } - if (new_entry->hba_ioaccel_enabled) { + if (new_entry->offload_to_be_enabled) { h->dev[entry]->ioaccel_handle = new_entry->ioaccel_handle; wmb(); /* set ioaccel_handle *before* hba_ioaccel_enabled */ } @@ -1385,17 +1396,18 @@ static void hpsa_scsi_update_entry(struct ctlr_info *h, /* * We can turn off ioaccel offload now, but need to delay turning -* it on until we can update h->dev[entry]->phys_disk[], but we +* ioaccel on until we can update h->dev[entry]->phys_disk[], but we * can't do that until all the devices are updated. */ - h->dev[entry]->offload_to_be_enabled = new_entry->offload_enabled; - if (!new_entry->offload_enabled) + h->dev[entry]->offload_to_be_enabled = new_entry->offload_to_be_enabled; + + /* +* turn ioaccel off immediately if told to do so. +*/ + if (!new_entry->offload_to_be_enabled) h->dev[entry]->offload_enabled = 0; - offload_enabled = h->dev[entry]->offload_enabled; - h->dev[entry]->offload_enabled = h->dev[entry]->offload_to_be_enabled; hpsa_show_dev_msg(KERN_INFO, h, h->dev[entry], "updated"); - h->dev[entry]->offload_enabled = offload_enabled; } /* Replace an entry from h->dev[] array. */ @@ -1421,9 +1433,8 @@ static void hpsa_scsi_replace_entry(struct ctlr_info *h, h->dev[entry] = new_entry; added[*nadded] = new_entry; (*nadded)++; + hpsa_show_dev_msg(KERN_INFO, h, new_entry, "replaced"); - new_entry->offload_to_be_enabled
[PATCH 11/12] hpsa: add enclosure logical identifier
add support for enclosure logical identifier Reviewed-by: Scott BeneshReviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 69 ++- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index a536ed6..5428a4c 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -2965,6 +2965,57 @@ static void hpsa_scsi_interpret_error(struct ctlr_info *h, } } +static int hpsa_do_receive_diagnostic(struct ctlr_info *h, u8 *scsi3addr, + u8 page, u8 *buf, size_t bufsize) +{ + int rc = IO_OK; + struct CommandList *c; + struct ErrorInfo *ei; + + c = cmd_alloc(h); + if (fill_cmd(c, RECEIVE_DIAGNOSTIC, h, buf, bufsize, + page, scsi3addr, TYPE_CMD)) { + rc = -1; + goto out; + } + rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, + PCI_DMA_FROMDEVICE, NO_TIMEOUT); + if (rc) + goto out; + ei = c->err_info; + if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) { + hpsa_scsi_interpret_error(h, c); + rc = -1; + } +out: + cmd_free(h, c); + return rc; +} + +static u64 hpsa_get_enclosure_logical_identifier(struct ctlr_info *h, + u8 *scsi3addr) +{ + u8 *buf; + u64 sa = 0; + int rc = 0; + + buf = kzalloc(1024, GFP_KERNEL); + if (!buf) + return 0; + + rc = hpsa_do_receive_diagnostic(h, scsi3addr, RECEIVE_DIAGNOSTIC, + buf, 1024); + + if (rc) + goto out; + + sa = get_unaligned_be64(buf+12); + +out: + kfree(buf); + return sa; +} + static int hpsa_scsi_do_inquiry(struct ctlr_info *h, unsigned char *scsi3addr, u16 page, unsigned char *buf, unsigned char bufsize) @@ -3400,6 +3451,9 @@ static void hpsa_get_enclosure_info(struct ctlr_info *h, bmic_device_index = GET_BMIC_DRIVE_NUMBER(>lunid[0]); + encl_dev->sas_address = + hpsa_get_enclosure_logical_identifier(h, scsi3addr); + if (encl_dev->target == -1 || encl_dev->lun == -1) { rc = IO_OK; goto out; @@ -6571,6 +6625,17 @@ static int fill_cmd(struct CommandList *c, u8 cmd, struct ctlr_info *h, c->Request.CDB[0] = HPSA_INQUIRY; c->Request.CDB[4] = size & 0xFF; break; + case RECEIVE_DIAGNOSTIC: + c->Request.CDBLen = 6; + c->Request.type_attr_dir = + TYPE_ATTR_DIR(cmd_type, ATTR_SIMPLE, XFER_READ); + c->Request.Timeout = 0; + c->Request.CDB[0] = cmd; + c->Request.CDB[1] = 1; + c->Request.CDB[2] = 1; + c->Request.CDB[3] = (size >> 8) & 0xFF; + c->Request.CDB[4] = size & 0xFF; + break; case HPSA_REPORT_LOG: case HPSA_REPORT_PHYS: /* Talking to controller so It's a physical command @@ -9508,7 +9573,7 @@ static int hpsa_add_sas_host(struct ctlr_info *h) struct hpsa_sas_port *hpsa_sas_port; struct hpsa_sas_phy *hpsa_sas_phy; - parent_dev = >scsi_host->shost_gendev; + parent_dev = >scsi_host->shost_dev; hpsa_sas_node = hpsa_alloc_sas_node(parent_dev); if (!hpsa_sas_node) @@ -9599,7 +9664,7 @@ hpsa_sas_get_linkerrors(struct sas_phy *phy) static int hpsa_sas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier) { - *identifier = 0; + *identifier = rphy->identify.sas_address; return 0; }
[PATCH 04/12] hpsa: add controller checkpoint
tell hpsa controller to generate a checkpoint for rare lockup conditions. Reviewed-by: Scott BeneshReviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace --- drivers/scsi/hpsa.c |4 drivers/scsi/hpsa_cmd.h |1 + 2 files changed, 5 insertions(+) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 0330f17..9c491c5 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -8009,6 +8009,10 @@ static void controller_lockup_detected(struct ctlr_info *h) spin_unlock_irqrestore(>lock, flags); dev_warn(>pdev->dev, "Controller lockup detected: 0x%08x after %d\n", lockup_detected, h->heartbeat_sample_interval / HZ); + if (lockup_detected == 0x) { + dev_warn(>pdev->dev, "Telling controller to do a CHKPT\n"); + writel(DOORBELL_GENERATE_CHKPT, h->vaddr + SA5_DOORBELL); + } pci_disable_device(h->pdev); fail_all_outstanding_cmds(h); } diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h index 078afe4..78c3b64 100644 --- a/drivers/scsi/hpsa_cmd.h +++ b/drivers/scsi/hpsa_cmd.h @@ -142,6 +142,7 @@ #define DOORBELL_CTLR_RESET0x0004l #define DOORBELL_CTLR_RESET2 0x0020l #define DOORBELL_CLEAR_EVENTS 0x0040l +#define DOORBELL_GENERATE_CHKPT0x0080l #define CFGTBL_Trans_Simple 0x0002l #define CFGTBL_Trans_Performant 0x0004l
[PATCH 12/12] hpsa: bump driver version
Reviewed-by: Gerry MorongReviewed-by: Scott Benesh Signed-off-by: Don Brace --- 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 5428a4c..e514489 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -60,7 +60,7 @@ * HPSA_DRIVER_VERSION must be 3 byte values (0-255) separated by '.' * with an optional trailing '-' followed by a byte value (0-255). */ -#define HPSA_DRIVER_VERSION "3.4.20-0" +#define HPSA_DRIVER_VERSION "3.4.20-125" #define DRIVER_NAME "HP HPSA Driver (v " HPSA_DRIVER_VERSION ")" #define HPSA "hpsa"
[PATCH 00/12] hpsa updates
These patches are based on Linus's tree The changes are: hpsa: update discovery polling - Correct corner case for RBODs with no initial volumes. hpsa: add controller checkpoint - Provide method to generate a controller checkpoint. hpsa: change timeout for internal cmds - There are times when the default time-out value has proven to be too small. hpsa: correct smart path enabled - Correct some corner cases where the ioaccel path is not re-enabled after a multipath failover or a transformation. hpsa: update queue depth for externals - A re-scan can change the queue-depth of external logical volumes. hpsa: reduce warning messages on device removal - Repeated warnings are not necessary. hpsa: correct logical volume removal - Also check for outstanding commands during logical volume removal. hpsa: add enclosure logical identifier - Populate sysfs enclosure_identifier. hpsa: destroy sas transport properties before scsi_host - This patch was proposed by Martin Wilck on 10/21/2016: https://www.spinics.net/lists/linux-scsi/msg102085.html - but had no effect until Hannes's patch: commit 9441284fbc39 ("scsi-fixup-kernel-warning-during-rmmod") was applied to the kernel. - Re-submitting with Martin Wilck's permission. hpsa: cleanup sas_phy structures in sysfs when unloading - This patch was proposed by Martin Wilck on 10/21/2016: https://www.spinics.net/lists/linux-scsi/msg102083.html - cleans up dangling symlinks in sysfs. - Re-submitting with Martin Wilck's permission. hpsa: clear tmpdevice in scan thread - Clean up some meta data issues for devices during a re-scan. hpsa: bump driver version --- Bader Ali Saleh (1): hpsa: update discovery polling Don Brace (8): hpsa: add controller checkpoint hpsa: change timeout for internal cmds hpsa: correct smart path enabled hpsa: update queue depth for externals hpsa: reduce warning messages on device removal hpsa: correct logical volume removal hpsa: add enclosure logical identifier hpsa: bump driver version Martin Wilck (2): hpsa: destroy sas transport properties before scsi_host hpsa: cleanup sas_phy structures in sysfs when unloading Scott Teel (1): hpsa: clear tmpdevice in scan thread drivers/scsi/hpsa.c | 356 +-- drivers/scsi/hpsa_cmd.h |3 2 files changed, 284 insertions(+), 75 deletions(-) -- Signature
[PATCH 05/12] hpsa: update discovery polling
From: Bader Ali SalehCorrect a corner case where newly created volumes are not detected automatically on an external RAID controller that has no configured volumes during initial device discovery. The fix is to set the discovery_polling flag when an external RAID controller is detected. This causes a device rescan every 20-30 seconds, so that newly created volumes will be detected automatically. Reviewed-by: Scott Benesh Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 39 ++- drivers/scsi/hpsa_cmd.h |2 ++ 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 9c491c5..6056bbd 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -3472,6 +3472,30 @@ static void hpsa_get_sas_address(struct ctlr_info *h, unsigned char *scsi3addr, dev->sas_address = sa; } +static void hpsa_ext_ctrl_present(struct ctlr_info *h, + struct ReportExtendedLUNdata *physdev) +{ + u32 nphysicals; + int i; + + if (h->discovery_polling) + return; + + nphysicals = (get_unaligned_be32(physdev->LUNListLength) / 24) + 1; + + for (i = 0; i < nphysicals; i++) { + if (physdev->LUN[i].device_type == + BMIC_DEVICE_TYPE_CONTROLLER + && !is_hba_lunid(physdev->LUN[i].lunid)) { + dev_info(>pdev->dev, + "External controller present, activate discovery polling and disable rld caching\n"); + hpsa_disable_rld_caching(h); + h->discovery_polling = 1; + break; + } + } +} + /* Get a device id from inquiry page 0x83 */ static bool hpsa_vpd_page_supported(struct ctlr_info *h, unsigned char scsi3addr[], u8 page) @@ -4228,6 +4252,8 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) */ ndevs_to_allocate = nphysicals + nlogicals + MAX_EXT_TARGETS + 1; + hpsa_ext_ctrl_present(h, physdev_list); + /* Allocate the per device structures */ for (i = 0; i < ndevs_to_allocate; i++) { if (i >= HPSA_MAX_DEVICES) { @@ -4298,18 +4324,6 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) figure_bus_target_lun(h, lunaddrbytes, tmpdevice); this_device = currentsd[ncurrent]; - /* Turn on discovery_polling if there are ext target devices. -* Event-based change notification is unreliable for those. -*/ - if (!h->discovery_polling) { - if (tmpdevice->external) { - h->discovery_polling = 1; - dev_info(>pdev->dev, - "External target, activate discovery polling.\n"); - } - } - - *this_device = *tmpdevice; this_device->physical_device = physical_device; @@ -8247,7 +8261,6 @@ static void hpsa_rescan_ctlr_worker(struct work_struct *work) if (h->drv_req_rescan || hpsa_offline_devices_ready(h)) { hpsa_perform_rescan(h); } else if (h->discovery_polling) { - hpsa_disable_rld_caching(h); if (hpsa_luns_changed(h)) { dev_info(>pdev->dev, "driver discovery polling rescan.\n"); diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h index 78c3b64..21a726e 100644 --- a/drivers/scsi/hpsa_cmd.h +++ b/drivers/scsi/hpsa_cmd.h @@ -780,6 +780,8 @@ struct bmic_identify_physical_device { u8 phys_bay_in_box; /* phys drv bay this drive resides */ __le32 rpm; /* Drive rotational speed in rpm */ u8 device_type; /* type of drive */ +#define BMIC_DEVICE_TYPE_CONTROLLER0x07 + u8 sata_version; /* only valid when drive_type is SATA */ __le64 big_total_block_count; __le64 ris_starting_lba;
[PATCH 06/12] hpsa: change timeout for internal cmds
There are times when the DEFAULT_TIMEOUT (30 seconds) is not enough. Reviewed-by: Scott BeneshReviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace --- drivers/scsi/hpsa.c | 22 +++--- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 6056bbd..4ab53df 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -2929,7 +2929,7 @@ static int hpsa_scsi_do_inquiry(struct ctlr_info *h, unsigned char *scsi3addr, goto out; } rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT); + PCI_DMA_FROMDEVICE, NO_TIMEOUT); if (rc) goto out; ei = c->err_info; @@ -3213,7 +3213,7 @@ static int hpsa_get_raid_map(struct ctlr_info *h, return -1; } rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT); + PCI_DMA_FROMDEVICE, NO_TIMEOUT); if (rc) goto out; ei = c->err_info; @@ -3256,7 +3256,7 @@ static int hpsa_bmic_sense_subsystem_information(struct ctlr_info *h, c->Request.CDB[9] = (bmic_device_index >> 8) & 0xff; rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT); + PCI_DMA_FROMDEVICE, NO_TIMEOUT); if (rc) goto out; ei = c->err_info; @@ -3284,7 +3284,7 @@ static int hpsa_bmic_id_controller(struct ctlr_info *h, goto out; rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT); + PCI_DMA_FROMDEVICE, NO_TIMEOUT); if (rc) goto out; ei = c->err_info; @@ -3315,7 +3315,7 @@ static int hpsa_bmic_id_physical_device(struct ctlr_info *h, c->Request.CDB[9] = (bmic_device_index >> 8) & 0xff; hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_FROMDEVICE, - DEFAULT_TIMEOUT); + NO_TIMEOUT); ei = c->err_info; if (ei->CommandStatus != 0 && ei->CommandStatus != CMD_DATA_UNDERRUN) { hpsa_scsi_interpret_error(h, c); @@ -3388,7 +3388,7 @@ static void hpsa_get_enclosure_info(struct ctlr_info *h, c->Request.CDB[5] = 0; rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, PCI_DMA_FROMDEVICE, - DEFAULT_TIMEOUT); + NO_TIMEOUT); if (rc) goto out; @@ -3628,7 +3628,7 @@ static int hpsa_scsi_do_report_luns(struct ctlr_info *h, int logical, if (extended_response) c->Request.CDB[1] = extended_response; rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT); + PCI_DMA_FROMDEVICE, NO_TIMEOUT); if (rc) goto out; ei = c->err_info; @@ -3763,7 +3763,7 @@ static unsigned char hpsa_volume_offline(struct ctlr_info *h, (void) fill_cmd(c, TEST_UNIT_READY, h, NULL, 0, 0, scsi3addr, TYPE_CMD); rc = hpsa_scsi_do_simple_cmd(h, c, DEFAULT_REPLY_QUEUE, - DEFAULT_TIMEOUT); + NO_TIMEOUT); if (rc) { cmd_free(h, c); return HPSA_VPD_LV_STATUS_UNSUPPORTED; @@ -8620,7 +8620,7 @@ static void hpsa_disable_rld_caching(struct ctlr_info *h) goto errout; rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT); + PCI_DMA_FROMDEVICE, NO_TIMEOUT); if ((rc != 0) || (c->err_info->CommandStatus != 0)) goto errout; @@ -8632,7 +8632,7 @@ static void hpsa_disable_rld_caching(struct ctlr_info *h) goto errout; rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_TODEVICE, DEFAULT_TIMEOUT); + PCI_DMA_TODEVICE, NO_TIMEOUT); if ((rc != 0) || (c->err_info->CommandStatus != 0)) goto errout; @@ -8642,7 +8642,7 @@ static void hpsa_disable_rld_caching(struct ctlr_info *h) goto errout; rc = hpsa_scsi_do_simple_cmd_with_retry(h, c, - PCI_DMA_FROMDEVICE, DEFAULT_TIMEOUT); + PCI_DMA_FROMDEVICE, NO_TIMEOUT); if ((rc != 0) || (c->err_info->CommandStatus != 0)) goto errout;
[PATCH 03/12] hpsa: clear tmpdevice in scan thread
From: Scott Teelclean up stale information. Reviewed-by: Scott Benesh Reviewed-by: Scott Teel Reviewed-by: Kevin Barnett Signed-off-by: Don Brace --- drivers/scsi/hpsa.c |2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 76461c4..0330f17 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -4258,6 +4258,8 @@ static void hpsa_update_scsi_devices(struct ctlr_info *h) int phys_dev_index = i - (raid_ctlr_position == 0); bool skip_device = false; + memset(tmpdevice, 0, sizeof(*tmpdevice)); + physical_device = i < nphysicals + (raid_ctlr_position == 0); /* Figure out where the LUN ID info is coming from */
[PATCH 01/12] hpsa: destroy sas transport properties before scsi_host
From: Martin WilckThis patch cleans up a lot of warnings when unloading the driver. A current example of the stack trace starts with: [ 142.570715] sysfs group 'power' not found for kobject 'port-5:0' There can be hundreds of these messages during a driver unload. I am resubmitting this patch on behalf of Martin Wilck with his permission. His original patch can be found here: https://www.spinics.net/lists/linux-scsi/msg102085.html This patch did not help until Hannes's commit 9441284fbc39 ("scsi-fixup-kernel-warning-during-rmmod") was applied to the kernel. --- Original patch description: --- Unloading the hpsa driver causes warnings [ 1063.793652] WARNING: CPU: 1 PID: 4850 at ../fs/sysfs/group.c:237 device_del+0x54/0x240() [ 1063.793659] sysfs group 81cf21a0 not found for kobject 'port-2:0' with two different stacks: 1) [ 1063.793774] [] device_del+0x54/0x240 [ 1063.793780] [] transport_remove_classdev+0x4a/0x60 [ 1063.793784] [] attribute_container_device_trigger+0xa6/0xb0 [ 1063.793802] [] sas_port_delete+0x126/0x160 [scsi_transport_sas] [ 1063.793819] [] hpsa_free_sas_port+0x3c/0x70 [hpsa] 2) [ 1063.797103] [] device_del+0x54/0x240 [ 1063.797118] [] sas_port_delete+0x12e/0x160 [scsi_transport_sas] [ 1063.797134] [] hpsa_free_sas_port+0x3c/0x70 [hpsa] This is caused by the fact that host device hostX is deleted before the SAS transport devices hostX/port-a:b. This patch fixes this by reverting the order of device deletions. Tested-by: Don Brace Reviewed-by: Don Brace Signed-off-by: Martin Wilck Signed-off-by: Don Brace --- drivers/scsi/hpsa.c |4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 9abe810..aff4a4f 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -8684,6 +8684,8 @@ static void hpsa_remove_one(struct pci_dev *pdev) destroy_workqueue(h->rescan_ctlr_wq); destroy_workqueue(h->resubmit_wq); + hpsa_delete_sas_host(h); + /* * Call before disabling interrupts. * scsi_remove_host can trigger I/O operations especially @@ -8718,8 +8720,6 @@ static void hpsa_remove_one(struct pci_dev *pdev) h->lockup_detected = NULL; /* init_one 2 */ /* (void) pci_disable_pcie_error_reporting(pdev); *//* init_one 1 */ - hpsa_delete_sas_host(h); - kfree(h); /* init_one 1 */ }
[PATCH 02/12] hpsa: cleanup sas_phy structures in sysfs when unloading
From: Martin WilckI am resubmitting this patch on behalf of Martin Wilck with his permission. The original patch can be found here: https://www.spinics.net/lists/linux-scsi/msg102083.html This patch did not help until Hannes's commit 9441284fbc39 ("scsi-fixup-kernel-warning-during-rmmod") was applied to the kernel. -- Original patch description from Martin: -- When the hpsa module is unloaded using rmmod, dangling symlinks remain under /sys/class/sas_phy. Fix this by calling sas_phy_delete() rather than sas_phy_free (which, according to comments, should not be called for PHYs that have been set up successfully, anyway). Tested-by: Don Brace Reviewed-by: Don Brace Signed-off-by: Martin Wilck Signed-off-by: Don Brace --- 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 aff4a4f..76461c4 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -9207,9 +9207,9 @@ static void hpsa_free_sas_phy(struct hpsa_sas_phy *hpsa_sas_phy) struct sas_phy *phy = hpsa_sas_phy->phy; sas_port_delete_phy(hpsa_sas_phy->parent_port->port, phy); - sas_phy_free(phy); if (hpsa_sas_phy->added_to_port) list_del(_sas_phy->phy_list_entry); + sas_phy_delete(phy); kfree(hpsa_sas_phy); }
[PATCH] smartpqi: correct spelling error in documentation
Correct spelling error. Signed-off-by: Kevin BarnettSigned-off-by: Don Brace --- Documentation/scsi/smartpqi.txt |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/scsi/smartpqi.txt b/Documentation/scsi/smartpqi.txt index ab377d9..201f80c 100644 --- a/Documentation/scsi/smartpqi.txt +++ b/Documentation/scsi/smartpqi.txt @@ -21,7 +21,7 @@ http://www.t10.org/members/w_pqi2.htm Supported devices: -- - + smartpqi specific entries in /sys -
[PATCH] Suppress a kernel warning in case the prep function returns BLKPREP_DEFER
The legacy block layer handles requests as follows: - If the prep function returns BLKPREP_OK, let blk_peek_request() return the pointer to that request. - If the prep function returns BLKPREP_DEFER, keep the RQF_STARTED flag and retry calling the prep function later. - If the prep function returns BLKPREP_KILL or BLKPREP_INVALID, end the request. In none of these cases it is correct to clear the SCMD_INITIALIZED flag from inside scsi_prep_fn(). Since scsi_prep_fn() already guarantees that scsi_init_command() will be called once even if scsi_prep_fn() is called multiple times, remove the code that clears SCMD_INITIALIZED from scsi_prep_fn(). The scsi-mq code handles requests as follows: - If scsi_mq_prep_fn() returns BLKPREP_OK, set the RQF_DONTPREP flag and submit the request to the SCSI LLD. - If scsi_mq_prep_fn() returns BLKPREP_DEFER, call blk_mq_delay_run_hw_queue() and return BLK_STS_RESOURCE. - If the prep function returns BLKPREP_KILL or BLKPREP_INVALID, call scsi_mq_uninit_cmd() and let the blk-mq core end the request. In none of these cases scsi_mq_prep_fn() should clear the SCMD_INITIALIZED flag. Hence remove the code from scsi_mq_prep_fn() function that clears that flag. This patch avoids that the following warning is triggered when using the legacy block layer: [ cut here ] WARNING: CPU: 1 PID: 4198 at drivers/scsi/scsi_lib.c:654 scsi_end_request+0x1de/0x220 CPU: 1 PID: 4198 Comm: mkfs.f2fs Not tainted 4.14.0-rc5+ #1 task: 91c147a4b800 task.stack: b282c37b8000 RIP: 0010:scsi_end_request+0x1de/0x220 Call Trace: scsi_io_completion+0x204/0x5e0 scsi_finish_command+0xce/0xe0 scsi_softirq_done+0x126/0x130 blk_done_softirq+0x6e/0x80 __do_softirq+0xcf/0x2a8 irq_exit+0xab/0xb0 do_IRQ+0x7b/0xc0 common_interrupt+0x90/0x90 RIP: 0010:_raw_spin_unlock_irqrestore+0x9/0x10 __test_set_page_writeback+0xc7/0x2c0 __block_write_full_page+0x158/0x3b0 block_write_full_page+0xc4/0xd0 blkdev_writepage+0x13/0x20 __writepage+0x12/0x40 write_cache_pages+0x204/0x500 generic_writepages+0x48/0x70 blkdev_writepages+0x9/0x10 do_writepages+0x34/0xc0 __filemap_fdatawrite_range+0x6c/0x90 file_write_and_wait_range+0x31/0x90 blkdev_fsync+0x16/0x40 vfs_fsync_range+0x44/0xa0 do_fsync+0x38/0x60 SyS_fsync+0xb/0x10 entry_SYSCALL_64_fastpath+0x13/0x94 ---[ end trace 86e8ef85a4a6c1d1 ]--- Fixes: commit 64104f703212 ("scsi: Call scsi_initialize_rq() for filesystem requests") Signed-off-by: Bart Van AsscheCc: Damien Le Moal Cc: Christoph Hellwig Cc: Hannes Reinecke Cc: Johannes Thumshirn --- drivers/scsi/scsi_lib.c | 8 +--- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 1779c8e91d09..5745af3e81bd 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1378,8 +1378,6 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) ret = scsi_setup_cmnd(sdev, req); out: - if (ret != BLKPREP_OK) - cmd->flags &= ~SCMD_INITIALIZED; return scsi_prep_return(q, req, ret); } @@ -1899,7 +1897,6 @@ static int scsi_mq_prep_fn(struct request *req) struct scsi_device *sdev = req->q->queuedata; struct Scsi_Host *shost = sdev->host; struct scatterlist *sg; - int ret; scsi_init_command(sdev, cmd); @@ -1933,10 +1930,7 @@ static int scsi_mq_prep_fn(struct request *req) blk_mq_start_request(req); - ret = scsi_setup_cmnd(sdev, req); - if (ret != BLK_STS_OK) - cmd->flags &= ~SCMD_INITIALIZED; - return ret; + return scsi_setup_cmnd(sdev, req); } static void scsi_mq_done(struct scsi_cmnd *cmd) -- 2.14.2
Re: [PATCH 9/9] bsg: split handling of SCSI CDBs vs transport requeues
On Fri, Oct 20, 2017 at 06:26:30PM +0200, Christoph Hellwig wrote: > On Thu, Oct 19, 2017 at 05:59:33PM +0200, Benjamin Block wrote: > > > +#define ptr64(val) ((void __user *)(uintptr_t)(val)) > > > > Better to reflect the special property, that it is a user pointer, in > > the name of the macro. Maybe something like user_ptr(64). The same > > comment for the same macro in bsg.c. > > Not sure it's worth it especially now that Martin has merged the patch. He did? I only saw a mail that he picked patches 2-5. So all the bsg changes are still open I think. (Maybe I just missed that, I haven't exactly followed the list very closely as of late) > But given how many interface we have all over the kernel that use a u64 > to store a user pointer in ioctls and similar it might make sense to > lift a helper like this to a generic header. In that case we'll need > a more descriptive name for sure. > > > > +static int bsg_transport_check_proto(struct sg_io_v4 *hdr) > > > +{ > > > + if (hdr->protocol != BSG_PROTOCOL_SCSI || > > > + hdr->subprotocol != BSG_SUB_PROTOCOL_SCSI_TRANSPORT) > > > + return -EINVAL; > > > + if (!capable(CAP_SYS_RAWIO)) > > > + return -EPERM; > > > > Any particular reason why this is not symmetric with bsg_scsi? IOW > > permission checking done in bsg_transport_fill_hdr(), like it is done in > > bsg_scsi_fill_hdr()? > > > > We might save some time copying memory with this (we also only talk > > about ~20 bytes here), but on the other hand the interface would be more > > clean otherwise IMO (if we already do restructure the interface) - > > similar callbacks have similar responsibilities. > > I could move the capable check around, no sure why I had done it that > way, it's been a while. Probably because blk_verify_command needs the > CDB while a simple capable() check does not. That was my guess, too. I just though it would be more consistent otherwise. Its not a big thing, really. Beste Grüße / Best regards, - Benjamin Block -- Linux on z Systems Development / IBM Systems & Technology Group IBM Deutschland Research & Development GmbH Vorsitz. AufsR.: Martina Koederitz /Geschäftsführung: Dirk Wittkopp Sitz der Gesellschaft: Böblingen / Registergericht: AmtsG Stuttgart, HRB 243294
Re: [PATCH 9/9] bsg: split handling of SCSI CDBs vs transport requeues
On Thu, Oct 19, 2017 at 05:59:33PM +0200, Benjamin Block wrote: > > +#define ptr64(val) ((void __user *)(uintptr_t)(val)) > > Better to reflect the special property, that it is a user pointer, in > the name of the macro. Maybe something like user_ptr(64). The same > comment for the same macro in bsg.c. Not sure it's worth it especially now that Martin has merged the patch. But given how many interface we have all over the kernel that use a u64 to store a user pointer in ioctls and similar it might make sense to lift a helper like this to a generic header. In that case we'll need a more descriptive name for sure. > > +static int bsg_transport_check_proto(struct sg_io_v4 *hdr) > > +{ > > + if (hdr->protocol != BSG_PROTOCOL_SCSI || > > + hdr->subprotocol != BSG_SUB_PROTOCOL_SCSI_TRANSPORT) > > + return -EINVAL; > > + if (!capable(CAP_SYS_RAWIO)) > > + return -EPERM; > > Any particular reason why this is not symmetric with bsg_scsi? IOW > permission checking done in bsg_transport_fill_hdr(), like it is done in > bsg_scsi_fill_hdr()? > > We might save some time copying memory with this (we also only talk > about ~20 bytes here), but on the other hand the interface would be more > clean otherwise IMO (if we already do restructure the interface) - > similar callbacks have similar responsibilities. I could move the capable check around, no sure why I had done it that way, it's been a while. Probably because blk_verify_command needs the CDB while a simple capable() check does not. > If I understand this right, the this reflects the old code, if only > written down a little different. > > But I wonder why we do that? Wouldn't that be interesting to know for > uspace, if more was received than it allocated space for? Isn't that the > typical residual over run case (similar to LUN scanning in SCSI common > code), and din_resid is signed after all? Well I guess it could be an > ABI break, I don't know. > > Ah well, at least the documentation for 'struct sg_io_v4' makes no such > restrictions (that it can not be below 0). > > Just a thought I had while reading it. Maybe it would, but I really didn't want to change behavior. If we were to redo transport passthrough I would do it totally different today. > > + job->reply = kzalloc(SCSI_SENSE_BUFFERSIZE, gfp); > > One suggestion here. Maybe we could get rid of this implicit knowledge > about SCSI_SENSE_BUFFERSIZE being the max size for a bsg-reply? > Especially if we use this patch and get rid of other similarities (like > using scsi_request). > > Maybe we can just define a extra macro in bsg-lib.c, or in one of the > headers, and define its size to be SCSI_SENSE_BUFFERSIZE (for now) and > then use that in all cases. > > I tried something similar some time ego if you remember, but I couldn't > follow up because other stuff got more important in the meantime. One > could also static check the transport reply-types against that. > > This way, should need to change that value for a sepcific transport, we > only need to change one knob, and not 10 (I guess SCSI_SENSE_BUFFERSIZE > could not be changed for such cases ;) ). There shouldn't be any dependencies on SCSI_SENSE_BUFFERSIZE left, so yes, this could be cleaned up. Great opportunity for a follow on patch. > > - /* if the LLD has been removed then the bsg_unregister_queue will > > -* eventually be called and the class_dev was freed, so we can no > > -* longer use this request_queue. Return no such address. > > -*/ > > Why remove the comment? Has that changed? Nothing, but then again it's standard behavior so the comment doesn't really add any value. > > + rq->timeout = msecs_to_jiffies(hdr->timeout); > > + if (!rq->timeout) > > + rq->timeout = rq->q->sg_timeout; > > No need to use the rq pointer, you already have a variable q with the > same content. True. > > - ret = blk_rq_map_user(q, rq, NULL, dxferp, dxfer_len, > > - GFP_KERNEL); > > - if (ret) > > - goto out; > > + ret = blk_rq_map_user(q, rq, NULL, ptr64(hdr->din_xferp), > > + hdr->din_xfer_len, GFP_KERNEL); > > + } else { > > + ret = blk_rq_map_user(q, rq, NULL, NULL, 0, GFP_KERNEL); > > Why do we behave differently in this case now? To prevent special > handling elsewhere? Otherwise it seems a bit pointless/error-prone > mapping zero length to nothing. Yes, this could be removed again. I'll send a follow up.
[PATCH 1/1] qla2xxx: Fix oops in qla2x00_probe_one error path
On error, kthread_create() returns an errno-encoded pointer, not NULL. The routine qla2x00_probe_one() detects the error case and jumps to probe_failed, but has already assigned the return value from kthread_create() to ha->dpc_thread. Then probe_failed checks to see if ha->dpc_thread is not NULL before doing cleanup on it. Since in the error case this is also not NULL, it ends up trying to access an invalid task pointer. Solution is to assign NULL to ha->dpc_thread in the error path to avoid kthread cleanup in that case. Signed-off-by: Douglas Miller--- drivers/scsi/qla2xxx/qla_os.c |1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 9372098..bd39bf2 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -3212,6 +3212,7 @@ static void qla2x00_iocb_work_fn(struct work_struct *work) ql_log(ql_log_fatal, base_vha, 0x00ed, "Failed to start DPC thread.\n"); ret = PTR_ERR(ha->dpc_thread); + ha->dpc_thread = NULL; goto probe_failed; } ql_dbg(ql_dbg_init, base_vha, 0x00ee, -- 1.7.1
[PATCH 0/1] qla2xxx: Fix oops in qla2x00_probe_one error path
See [PATCH 1/1] qla2xxx: Fix oops in qla2x00_probe_one error path
IMPORTANT INFORMATION,
Good Day, Please accept my apologies for writing you a surprise letter.I am Mr Thomas Alpha, account Manager with an investment bank here in Burkina Faso. I have a very important business I want to discuss with you.There is a draft account opened in my firm by a long-time client of our bank.I have the opportunity of transferring the left over fund (10.Million Us Dollars)Ten Million United States of American Dollars of one of my Bank clients who died at the collapsing of the world trade center at the United States on September 11th 2001. I want to invest this funds and introduce you to our bank for this deal.All I require is your honest co-operation and I guarantee you that this will be executed under a legitimate arrangement that will protect us from any breach of the law.I agree that 40% of this money will be for you as my foreign partner,50% for me while 10% is for establishing of foundation for the less privileges in your country.If you are really interested in my proposal return my email with the below information and i will forward a text of application letter to you which you are going to fill and send to the bank for claiming of the fund. Your Full Name... Your Age and Sex Your Private Telephone... Your Occupation... Your Country Yours Sincerely, Mr Thomas Alpha.
RE: [PATCH 0/6] v4 block refcount conversion patches
> Elena Reshetovawrites: > > Elena Reshetova (6): > > block: convert bio.__bi_cnt from atomic_t to refcount_t > > block: convert blk_queue_tag.refcnt from atomic_t to refcount_t > > block: convert blkcg_gq.refcnt from atomic_t to refcount_t > > block: convert io_context.active_ref from atomic_t to refcount_t > > block: convert bsg_device.ref_count from atomic_t to refcount_t > > drivers, block: convert xen_blkif.refcnt from atomic_t to refcount_t > > Hi Elena, > > While the bsg ref_count is cheap, do you have any numbers how the other > conversions compare in performance (throughput and latency) vs atomics? Hi Johannes, The performance would depend on which "breed" of refcount_t is used underneath. We currently have 3 versions: - refcount_t defaults to atomic_t (no CONFIG_REFCOUNT_FULL enabled, no arch. support) Impact is zero in this case since it is just atomic functions are used. - refcount_t uses arch. specific implementation (arch. enables ARCH_HAS_REFCOUNT) Impact depends on arch. implementation. Currently only x86 provides one. - refcount_t uses "full" arch. independent implementation. Here are cycle numbers for comparing these 3 (https://lwn.net/Articles/728626/): Just copy pasting for convenience: ">These are the cycle counts comparing a loop of refcount_inc() from 1 >to INT_MAX and back down to 0 (via refcount_dec_and_test()), between >unprotected refcount_t (atomic_t), fully protected REFCOUNT_FULL >(refcount_t-full), and this overflow-protected refcount (refcount_t-fast): >2147483646 refcount_inc()s and 2147483647 refcount_dec_and_test()s: cycles protections >atomic_t 82249267387 none >refcount_t-fast82211446892 overflow, untested dec-to-zero >refcount_t-full 144814735193 overflow, untested dec-to-zero, inc-from-zero" So, the middle option (called here refcount_t-fast) with arch. specific implementation gives a negligible impact. The "full" one is more pricey, but it is disabled by default anyway, so only people who want strict security enable it. Are these numbers convincing enough that we don't have to measure the block devices? :) Best Regards, Elena. > > It should be quite easy to measure against a null_blk device. > > Thanks a lot, >Johannes > > -- > Johannes Thumshirn Storage > jthumsh...@suse.de+49 911 74053 689 > SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg > GF: Felix Imendörffer, Jane Smithard, Graham Norton > HRB 21284 (AG Nürnberg) > Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
Re: [PATCH v5 2/5] dt-bindings: scsi: ufs: add document for hisi-ufs
On Fri, Oct 20, 2017 at 10:52 AM, Li Weiwrote: > --- /dev/null > +++ b/Documentation/devicetree/bindings/ufs/ufs-hisi.txt > @@ -0,0 +1,46 @@ > +* Hisilicon Universal Flash Storage (UFS) Host Controller > + > +UFS nodes are defined to describe on-chip UFS hardware macro. > +Each UFS Host Controller should have its own node. > + > +Required properties: > +- compatible: compatible list, contains one of the following - > + "hisilicon,hi3660-ufs" for hisi ufs host controller > +present on Hi3660 chipset. > +- reg : should contain UFS register address space & UFS SYS > CTRL register address, > +- interrupt-parent : interrupt device > +- interrupts: interrupt number > +- clocks : List of phandle and clock specifier pairs > +- clock-names : List of clock input name strings sorted in the same > + order as the clocks property. "clk_ref", "clk_phy" is > optional > +- resets: reset node register, one reset the clk and the other > reset the controller > +- reset-names : describe reset node register I think I've asked about this before, but I think this should be done more consistently with the other UFS bindings. In particular, I wonder if what you describe as the "UFS SYS CTRL" area corresponds to what Qualcomm have described as their PHY implementation. It certainly seems to driver some of the properties that would normally be associated with a PHY. For the "clock-names" property, you specify "clk_ref", which I assume is the same as what Qualcomm call "ref_clk". I'd suggest you use the existing name and add that as the default name in the ufshcd-pltfrm.txt binding document. The "clk_phy" property appears to be related to the PHY, so it might be better to have a separate phy node with either just the clk, or with the clk plus the "UFS SYS CTRL" register area, whichever matches your hardware better, and then use teh "phys/phy-names" property to refer to that. The reset handling you describe here (both resets and reset-gpios) appears to be completely generic, so I'd suggest adding those to ufshcd-pltfrm.txt instead of your own binding, to ensure that future drivers use the same identifiers. Arnd
[PATCH v4 2/5] dt-bindings: scsi: ufs: add document for hisi-ufs
add ufs node document for Hisilicon. Signed-off-by: Li Wei--- Documentation/devicetree/bindings/ufs/ufs-hisi.txt | 47 ++ 1 file changed, 47 insertions(+) create mode 100644 Documentation/devicetree/bindings/ufs/ufs-hisi.txt diff --git a/Documentation/devicetree/bindings/ufs/ufs-hisi.txt b/Documentation/devicetree/bindings/ufs/ufs-hisi.txt new file mode 100644 index ..ee114a65143d --- /dev/null +++ b/Documentation/devicetree/bindings/ufs/ufs-hisi.txt @@ -0,0 +1,47 @@ +* Hisilicon Universal Flash Storage (UFS) Host Controller + +UFS nodes are defined to describe on-chip UFS hardware macro. +Each UFS Host Controller should have its own node. + +Required properties: +- compatible: compatible list, contains one of the following - + "hisilicon,hi3660-ufs" for hisi ufs host controller +present on Hi3660 chipset. +- reg : should contain UFS register address space & UFS SYS CTRL register address, +- interrupt-parent : interrupt device +- interrupts: interrupt number +- clocks : List of phandle and clock specifier pairs +- clock-names : List of clock input name strings sorted in the same + order as the clocks property. "clk_ref", "clk_phy" is optional +- resets: reset node register, one reset the clk and the other reset the controller +- reset-names : describe reset node register + +Optional properties for board device: +- reset-gpio : specifies to reset devices + +Example: + + ufs: ufs@ff3b { + compatible = "hisilicon,hi3660-ufs", "jedec,ufs-1.1"; + /* 0: HCI standard */ + /* 1: UFS SYS CTRL */ + reg = <0x0 0xff3b 0x0 0x1000>, + <0x0 0xff3b1000 0x0 0x1000>; + interrupt-parent = <>; + interrupts = ; + clocks = <_ctrl HI3660_CLK_GATE_UFSIO_REF>, + <_ctrl HI3660_CLK_GATE_UFSPHY_CFG>; + clock-names = "clk_ref", "clk_phy"; + freq-table-hz = <0 0>, <0 0>; + /* offset: 0x84; bit: 12 */ + /* offset: 0x84; bit: 7 */ + resets = <_rst 0x84 12>, + <_rst 0x84 7>; + reset-names = "rst", "assert"; + }; + +{ + reset-gpio = < 1 0>; + status = "okay"; + }; + -- 2.11.0
[PATCH v4 1/5] scsi: ufs: add Hisilicon ufs driver code
add Hisilicon ufs driver code. Signed-off-by: Li WeiSigned-off-by: Geng Jianfeng Signed-off-by: Zang Leigang Signed-off-by: Yu Jianfeng --- drivers/scsi/ufs/Kconfig| 9 + drivers/scsi/ufs/Makefile | 1 + drivers/scsi/ufs/ufs-hisi.c | 625 drivers/scsi/ufs/ufs-hisi.h | 161 4 files changed, 796 insertions(+) create mode 100644 drivers/scsi/ufs/ufs-hisi.c create mode 100644 drivers/scsi/ufs/ufs-hisi.h diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig index e27b4d4e6ae2..bf2ff5628b15 100644 --- a/drivers/scsi/ufs/Kconfig +++ b/drivers/scsi/ufs/Kconfig @@ -80,6 +80,15 @@ config SCSI_UFSHCD_PLATFORM If unsure, say N. +config SCSI_UFS_HISI + tristate "Hisilicon specific hooks to UFS controller platform driver" + depends on (ARCH_HISI || COMPILE_TEST) && SCSI_UFSHCD_PLATFORM + ---help--- + This selects the Hisilicon specific additions to UFSHCD platform driver. + + Select this if you have UFS controller on Hisilicon chipset. + If unsure, say N. + config SCSI_UFS_DWC_TC_PLATFORM tristate "DesignWare platform support using a G210 Test Chip" depends on SCSI_UFSHCD_PLATFORM diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile index 6e77cb0bfee9..9f2c17029a38 100644 --- a/drivers/scsi/ufs/Makefile +++ b/drivers/scsi/ufs/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o ufshcd-dwc.o tc-dwc-g210.o obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o tc-dwc-g210.o obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o +obj-$(CONFIG_SCSI_UFS_HISI) += ufs-hisi.o obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o diff --git a/drivers/scsi/ufs/ufs-hisi.c b/drivers/scsi/ufs/ufs-hisi.c new file mode 100644 index ..8b7aea2d44c5 --- /dev/null +++ b/drivers/scsi/ufs/ufs-hisi.c @@ -0,0 +1,625 @@ +/* + * + * HiSilicon Hi UFS Driver + * + * Copyright (c) 2016-2017 Linaro Ltd. + * Copyright (c) 2016-2017 HiSilicon Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ufshcd.h" +#include "ufshcd-pltfrm.h" +#include "unipro.h" +#include "ufs-hisi.h" +#include "ufshci.h" + +static int ufs_hisi_check_hibern8(struct ufs_hba *hba) +{ + int err; + u32 tx_fsm_val_0; + u32 tx_fsm_val_1; + unsigned long timeout = jiffies + msecs_to_jiffies(HBRN8_POLL_TOUT_MS); + + do { + err = ufshcd_dme_get(hba, UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE, 0), + _fsm_val_0); + err |= ufshcd_dme_get(hba, + UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE, 1), _fsm_val_1); + if (err || (tx_fsm_val_0 == TX_FSM_HIBERN8 && + tx_fsm_val_1 == TX_FSM_HIBERN8)) + break; + + /* sleep for max. 200us */ + usleep_range(100, 200); + } while (time_before(jiffies, timeout)); + + /* +* we might have scheduled out for long during polling so +* check the state again. +*/ + if (time_after(jiffies, timeout)) { + err = ufshcd_dme_get(hba, UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE, 0), +_fsm_val_0); + err |= ufshcd_dme_get(hba, +UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE, 1), _fsm_val_1); + } + + if (err) { + dev_err(hba->dev, "%s: unable to get TX_FSM_STATE, err %d\n", + __func__, err); + } else if (tx_fsm_val_0 != TX_FSM_HIBERN8 || +tx_fsm_val_1 != TX_FSM_HIBERN8) { + err = -1; + dev_err(hba->dev, "%s: invalid TX_FSM_STATE, lane0 = %d, lane1 = %d\n", + __func__, tx_fsm_val_0, tx_fsm_val_1); + } + + return err; +} + +static void ufs_hisi_clk_init(struct ufs_hba *hba) +{ + struct ufs_hisi_host *host = ufshcd_get_variant(hba); + + ufs_sys_ctrl_clr_bits(host, BIT_SYSCTRL_REF_CLOCK_EN, PHY_CLK_CTRL); + if (ufs_sys_ctrl_readl(host, PHY_CLK_CTRL) & BIT_SYSCTRL_REF_CLOCK_EN) + mdelay(1); + /* use abb clk */ + ufs_sys_ctrl_clr_bits(host, BIT_UFS_REFCLK_SRC_SEl, UFS_SYSCTRL); + ufs_sys_ctrl_clr_bits(host, BIT_UFS_REFCLK_ISO_EN, PHY_ISO_EN); + /* open mphy ref clk */ + ufs_sys_ctrl_set_bits(host, BIT_SYSCTRL_REF_CLOCK_EN, PHY_CLK_CTRL); +} + +static void
[PATCH v4 4/5] arm64: defconfig: enable configs for Hisilicon ufs
This enable configs for Hisilicon Hi UFS driver. Signed-off-by: Li WeiSigned-off-by: Zhangfei Gao Signed-off-by: Guodong Xu --- arch/arm64/configs/defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 34480e9af2e7..8aff981915f5 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -168,6 +168,9 @@ CONFIG_BLK_DEV_SD=y CONFIG_SCSI_SAS_ATA=y CONFIG_SCSI_HISI_SAS=y CONFIG_SCSI_HISI_SAS_PCI=y +CONFIG_SCSI_UFSHCD=y +CONFIG_SCSI_UFSHCD_PLATFORM=y +CONFIG_SCSI_UFS_HISI=y CONFIG_ATA=y CONFIG_SATA_AHCI=y CONFIG_SATA_AHCI_PLATFORM=y -- 2.11.0
[PATCH v5 0/5] scsi: ufs: add ufs driver code for Hisilicon Hi3660 SoC
This patchset adds driver support for UFS for Hi3660 SoC. It is verified on HiKey960 board. Li Wei (5): scsi: ufs: add Hisilicon ufs driver code dt-bindings: scsi: ufs: add document for hisi-ufs arm64: dts: add ufs dts node arm64: defconfig: enable configs for Hisilicon ufs arm64: defconfig: enable f2fs and squashfs Documentation/devicetree/bindings/ufs/ufs-hisi.txt | 46 ++ arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts | 5 + arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 19 + arch/arm64/configs/defconfig | 11 + drivers/scsi/ufs/Kconfig | 9 + drivers/scsi/ufs/Makefile | 1 + drivers/scsi/ufs/ufs-hisi.c| 625 + drivers/scsi/ufs/ufs-hisi.h| 161 ++ 8 files changed, 877 insertions(+) create mode 100644 Documentation/devicetree/bindings/ufs/ufs-hisi.txt create mode 100644 drivers/scsi/ufs/ufs-hisi.c create mode 100644 drivers/scsi/ufs/ufs-hisi.h -- 2.11.0
[PATCH v5 4/5] arm64: defconfig: enable configs for Hisilicon ufs
This enable configs for Hisilicon Hi UFS driver. Signed-off-by: Li WeiSigned-off-by: Zhangfei Gao Signed-off-by: Guodong Xu --- arch/arm64/configs/defconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 34480e9af2e7..8aff981915f5 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -168,6 +168,9 @@ CONFIG_BLK_DEV_SD=y CONFIG_SCSI_SAS_ATA=y CONFIG_SCSI_HISI_SAS=y CONFIG_SCSI_HISI_SAS_PCI=y +CONFIG_SCSI_UFSHCD=y +CONFIG_SCSI_UFSHCD_PLATFORM=y +CONFIG_SCSI_UFS_HISI=y CONFIG_ATA=y CONFIG_SATA_AHCI=y CONFIG_SATA_AHCI_PLATFORM=y -- 2.11.0
[PATCH v5 5/5] arm64: defconfig: enable f2fs and squashfs
Partitions in HiKey960 are formatted as f2fs and squashfs. f2fs is for userdata; squashfs is for system. Both partitions are required by Android. Signed-off-by: Li WeiSigned-off-by: Zhangfei Gao Signed-off-by: Guodong Xu --- arch/arm64/configs/defconfig | 8 1 file changed, 8 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 8aff981915f5..0a8a843cd0be 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -555,6 +555,7 @@ CONFIG_ACPI_APEI_GHES=y CONFIG_ACPI_APEI_PCIEAER=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y +CONFIG_F2FS_FS=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_BTRFS_FS=m CONFIG_BTRFS_FS_POSIX_ACL=y @@ -570,6 +571,13 @@ CONFIG_HUGETLBFS=y CONFIG_CONFIGFS_FS=y CONFIG_EFIVAR_FS=y CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_FILE_DIRECT=y +CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_LZ4=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +CONFIG_SQUASHFS_4K_DEVBLK_SIZE=y CONFIG_NFS_FS=y CONFIG_NFS_V4=y CONFIG_NFS_V4_1=y -- 2.11.0
[PATCH v5 2/5] dt-bindings: scsi: ufs: add document for hisi-ufs
add ufs node document for Hisilicon. Signed-off-by: Li Wei--- Documentation/devicetree/bindings/ufs/ufs-hisi.txt | 46 ++ 1 file changed, 46 insertions(+) create mode 100644 Documentation/devicetree/bindings/ufs/ufs-hisi.txt diff --git a/Documentation/devicetree/bindings/ufs/ufs-hisi.txt b/Documentation/devicetree/bindings/ufs/ufs-hisi.txt new file mode 100644 index ..17da633c9ed5 --- /dev/null +++ b/Documentation/devicetree/bindings/ufs/ufs-hisi.txt @@ -0,0 +1,46 @@ +* Hisilicon Universal Flash Storage (UFS) Host Controller + +UFS nodes are defined to describe on-chip UFS hardware macro. +Each UFS Host Controller should have its own node. + +Required properties: +- compatible: compatible list, contains one of the following - + "hisilicon,hi3660-ufs" for hisi ufs host controller +present on Hi3660 chipset. +- reg : should contain UFS register address space & UFS SYS CTRL register address, +- interrupt-parent : interrupt device +- interrupts: interrupt number +- clocks : List of phandle and clock specifier pairs +- clock-names : List of clock input name strings sorted in the same + order as the clocks property. "clk_ref", "clk_phy" is optional +- resets: reset node register, one reset the clk and the other reset the controller +- reset-names : describe reset node register + +Optional properties for board device: +- reset-gpios : specifies to reset devices + +Example: + + ufs: ufs@ff3b { + compatible = "hisilicon,hi3660-ufs", "jedec,ufs-1.1"; + /* 0: HCI standard */ + /* 1: UFS SYS CTRL */ + reg = <0x0 0xff3b 0x0 0x1000>, + <0x0 0xff3b1000 0x0 0x1000>; + interrupt-parent = <>; + interrupts = ; + clocks = <_ctrl HI3660_CLK_GATE_UFSIO_REF>, + <_ctrl HI3660_CLK_GATE_UFSPHY_CFG>; + clock-names = "clk_ref", "clk_phy"; + freq-table-hz = <0 0>, <0 0>; + /* offset: 0x84; bit: 12 */ + /* offset: 0x84; bit: 7 */ + resets = <_rst 0x84 12>, + <_rst 0x84 7>; + reset-names = "rst", "assert"; + }; + +{ + reset-gpios = < 1 0>; + }; + -- 2.11.0
[PATCH v5 1/5] scsi: ufs: add Hisilicon ufs driver code
add Hisilicon ufs driver code. Signed-off-by: Li WeiSigned-off-by: Geng Jianfeng Signed-off-by: Zang Leigang Signed-off-by: Yu Jianfeng --- drivers/scsi/ufs/Kconfig| 9 + drivers/scsi/ufs/Makefile | 1 + drivers/scsi/ufs/ufs-hisi.c | 625 drivers/scsi/ufs/ufs-hisi.h | 161 4 files changed, 796 insertions(+) create mode 100644 drivers/scsi/ufs/ufs-hisi.c create mode 100644 drivers/scsi/ufs/ufs-hisi.h diff --git a/drivers/scsi/ufs/Kconfig b/drivers/scsi/ufs/Kconfig index e27b4d4e6ae2..bf2ff5628b15 100644 --- a/drivers/scsi/ufs/Kconfig +++ b/drivers/scsi/ufs/Kconfig @@ -80,6 +80,15 @@ config SCSI_UFSHCD_PLATFORM If unsure, say N. +config SCSI_UFS_HISI + tristate "Hisilicon specific hooks to UFS controller platform driver" + depends on (ARCH_HISI || COMPILE_TEST) && SCSI_UFSHCD_PLATFORM + ---help--- + This selects the Hisilicon specific additions to UFSHCD platform driver. + + Select this if you have UFS controller on Hisilicon chipset. + If unsure, say N. + config SCSI_UFS_DWC_TC_PLATFORM tristate "DesignWare platform support using a G210 Test Chip" depends on SCSI_UFSHCD_PLATFORM diff --git a/drivers/scsi/ufs/Makefile b/drivers/scsi/ufs/Makefile index 6e77cb0bfee9..9f2c17029a38 100644 --- a/drivers/scsi/ufs/Makefile +++ b/drivers/scsi/ufs/Makefile @@ -2,6 +2,7 @@ obj-$(CONFIG_SCSI_UFS_DWC_TC_PCI) += tc-dwc-g210-pci.o ufshcd-dwc.o tc-dwc-g210.o obj-$(CONFIG_SCSI_UFS_DWC_TC_PLATFORM) += tc-dwc-g210-pltfrm.o ufshcd-dwc.o tc-dwc-g210.o obj-$(CONFIG_SCSI_UFS_QCOM) += ufs-qcom.o +obj-$(CONFIG_SCSI_UFS_HISI) += ufs-hisi.o obj-$(CONFIG_SCSI_UFSHCD) += ufshcd.o obj-$(CONFIG_SCSI_UFSHCD_PCI) += ufshcd-pci.o obj-$(CONFIG_SCSI_UFSHCD_PLATFORM) += ufshcd-pltfrm.o diff --git a/drivers/scsi/ufs/ufs-hisi.c b/drivers/scsi/ufs/ufs-hisi.c new file mode 100644 index ..38a2e238c5e1 --- /dev/null +++ b/drivers/scsi/ufs/ufs-hisi.c @@ -0,0 +1,625 @@ +/* + * + * HiSilicon Hi UFS Driver + * + * Copyright (c) 2016-2017 Linaro Ltd. + * Copyright (c) 2016-2017 HiSilicon Technologies Co., Ltd. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ufshcd.h" +#include "ufshcd-pltfrm.h" +#include "unipro.h" +#include "ufs-hisi.h" +#include "ufshci.h" + +static int ufs_hisi_check_hibern8(struct ufs_hba *hba) +{ + int err; + u32 tx_fsm_val_0; + u32 tx_fsm_val_1; + unsigned long timeout = jiffies + msecs_to_jiffies(HBRN8_POLL_TOUT_MS); + + do { + err = ufshcd_dme_get(hba, UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE, 0), + _fsm_val_0); + err |= ufshcd_dme_get(hba, + UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE, 1), _fsm_val_1); + if (err || (tx_fsm_val_0 == TX_FSM_HIBERN8 && + tx_fsm_val_1 == TX_FSM_HIBERN8)) + break; + + /* sleep for max. 200us */ + usleep_range(100, 200); + } while (time_before(jiffies, timeout)); + + /* +* we might have scheduled out for long during polling so +* check the state again. +*/ + if (time_after(jiffies, timeout)) { + err = ufshcd_dme_get(hba, UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE, 0), +_fsm_val_0); + err |= ufshcd_dme_get(hba, +UIC_ARG_MIB_SEL(MPHY_TX_FSM_STATE, 1), _fsm_val_1); + } + + if (err) { + dev_err(hba->dev, "%s: unable to get TX_FSM_STATE, err %d\n", + __func__, err); + } else if (tx_fsm_val_0 != TX_FSM_HIBERN8 || +tx_fsm_val_1 != TX_FSM_HIBERN8) { + err = -1; + dev_err(hba->dev, "%s: invalid TX_FSM_STATE, lane0 = %d, lane1 = %d\n", + __func__, tx_fsm_val_0, tx_fsm_val_1); + } + + return err; +} + +static void ufs_hisi_clk_init(struct ufs_hba *hba) +{ + struct ufs_hisi_host *host = ufshcd_get_variant(hba); + + ufs_sys_ctrl_clr_bits(host, BIT_SYSCTRL_REF_CLOCK_EN, PHY_CLK_CTRL); + if (ufs_sys_ctrl_readl(host, PHY_CLK_CTRL) & BIT_SYSCTRL_REF_CLOCK_EN) + mdelay(1); + /* use abb clk */ + ufs_sys_ctrl_clr_bits(host, BIT_UFS_REFCLK_SRC_SEl, UFS_SYSCTRL); + ufs_sys_ctrl_clr_bits(host, BIT_UFS_REFCLK_ISO_EN, PHY_ISO_EN); + /* open mphy ref clk */ + ufs_sys_ctrl_set_bits(host, BIT_SYSCTRL_REF_CLOCK_EN, PHY_CLK_CTRL); +} + +static void
[PATCH v5 3/5] arm64: dts: add ufs dts node
arm64: dts: add ufs node for Hisilicon. Signed-off-by: Li Wei--- arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts | 5 + arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 19 +++ 2 files changed, 24 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts b/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts index fd4705c451e2..677d0e41667f 100644 --- a/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts +++ b/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts @@ -276,3 +276,8 @@ interrupts = <3 IRQ_TYPE_EDGE_RISING>; }; }; + + { + reset-gpios = < 1 0>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi index b7a90d632959..a24ab8472347 100644 --- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi @@ -978,5 +978,24 @@ clocks = <_ctrl HI3660_OSC32K>; clock-names = "apb_pclk"; }; + + ufs: ufs@ff3b { + compatible = "hisilicon,hi3660-ufs", "jedec,ufs-1.1"; + /* 0: HCI standard */ + /* 1: UFS SYS CTRL */ + reg = <0x0 0xff3b 0x0 0x1000>, + <0x0 0xff3b1000 0x0 0x1000>; + interrupt-parent = <>; + interrupts = ; + clocks = <_ctrl HI3660_CLK_GATE_UFSIO_REF>, + <_ctrl HI3660_CLK_GATE_UFSPHY_CFG>; + clock-names = "clk_ref", "clk_phy"; + freq-table-hz = <0 0>, <0 0>; + /* offset: 0x84; bit: 12 */ + /* offset: 0x84; bit: 7 */ + resets = <_rst 0x84 12>, + <_rst 0x84 7>; + reset-names = "rst", "assert"; + }; }; }; -- 2.11.0
[PATCH v4 5/5] arm64: defconfig: enable f2fs and squashfs
Partitions in HiKey960 are formatted as f2fs and squashfs. f2fs is for userdata; squashfs is for system. Both partitions are required by Android. Signed-off-by: Li WeiSigned-off-by: Zhangfei Gao Signed-off-by: Guodong Xu --- arch/arm64/configs/defconfig | 8 1 file changed, 8 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 8aff981915f5..0a8a843cd0be 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -555,6 +555,7 @@ CONFIG_ACPI_APEI_GHES=y CONFIG_ACPI_APEI_PCIEAER=y CONFIG_EXT2_FS=y CONFIG_EXT3_FS=y +CONFIG_F2FS_FS=y CONFIG_EXT4_FS_POSIX_ACL=y CONFIG_BTRFS_FS=m CONFIG_BTRFS_FS_POSIX_ACL=y @@ -570,6 +571,13 @@ CONFIG_HUGETLBFS=y CONFIG_CONFIGFS_FS=y CONFIG_EFIVAR_FS=y CONFIG_SQUASHFS=y +CONFIG_SQUASHFS_FILE_DIRECT=y +CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_LZ4=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +CONFIG_SQUASHFS_4K_DEVBLK_SIZE=y CONFIG_NFS_FS=y CONFIG_NFS_V4=y CONFIG_NFS_V4_1=y -- 2.11.0
[PATCH v4 3/5] arm64: dts: add ufs dts node
arm64: dts: add ufs node for Hisilicon. Signed-off-by: Li Wei--- arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts | 5 + arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 19 +++ 2 files changed, 24 insertions(+) diff --git a/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts b/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts index fd4705c451e2..457645a2b53f 100644 --- a/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts +++ b/arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts @@ -276,3 +276,8 @@ interrupts = <3 IRQ_TYPE_EDGE_RISING>; }; }; + + { + reset-gpio = < 1 0>; + status = "okay"; +}; diff --git a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi index b7a90d632959..a24ab8472347 100644 --- a/arch/arm64/boot/dts/hisilicon/hi3660.dtsi +++ b/arch/arm64/boot/dts/hisilicon/hi3660.dtsi @@ -978,5 +978,24 @@ clocks = <_ctrl HI3660_OSC32K>; clock-names = "apb_pclk"; }; + + ufs: ufs@ff3b { + compatible = "hisilicon,hi3660-ufs", "jedec,ufs-1.1"; + /* 0: HCI standard */ + /* 1: UFS SYS CTRL */ + reg = <0x0 0xff3b 0x0 0x1000>, + <0x0 0xff3b1000 0x0 0x1000>; + interrupt-parent = <>; + interrupts = ; + clocks = <_ctrl HI3660_CLK_GATE_UFSIO_REF>, + <_ctrl HI3660_CLK_GATE_UFSPHY_CFG>; + clock-names = "clk_ref", "clk_phy"; + freq-table-hz = <0 0>, <0 0>; + /* offset: 0x84; bit: 12 */ + /* offset: 0x84; bit: 7 */ + resets = <_rst 0x84 12>, + <_rst 0x84 7>; + reset-names = "rst", "assert"; + }; }; }; -- 2.11.0
[PATCH v4 0/5] scsi: ufs: add ufs driver code for Hisilicon Hi3660 SoC
This patchset adds driver support for UFS for Hi3660 SoC. It is verified on HiKey960 board. Li Wei (5): scsi: ufs: add Hisilicon ufs driver code dt-bindings: scsi: ufs: add document for hisi-ufs arm64: dts: add ufs dts node arm64: defconfig: enable configs for Hisilicon ufs arm64: defconfig: enable f2fs and squashfs Documentation/devicetree/bindings/ufs/ufs-hisi.txt | 47 ++ arch/arm64/boot/dts/hisilicon/hi3660-hikey960.dts | 5 + arch/arm64/boot/dts/hisilicon/hi3660.dtsi | 19 + arch/arm64/configs/defconfig | 11 + drivers/scsi/ufs/Kconfig | 9 + drivers/scsi/ufs/Makefile | 1 + drivers/scsi/ufs/ufs-hisi.c| 625 + drivers/scsi/ufs/ufs-hisi.h| 161 ++ 8 files changed, 878 insertions(+) create mode 100644 Documentation/devicetree/bindings/ufs/ufs-hisi.txt create mode 100644 drivers/scsi/ufs/ufs-hisi.c create mode 100644 drivers/scsi/ufs/ufs-hisi.h -- 2.11.0
Re: [PATCH 0/6] v4 block refcount conversion patches
Elena Reshetovawrites: > Elena Reshetova (6): > block: convert bio.__bi_cnt from atomic_t to refcount_t > block: convert blk_queue_tag.refcnt from atomic_t to refcount_t > block: convert blkcg_gq.refcnt from atomic_t to refcount_t > block: convert io_context.active_ref from atomic_t to refcount_t > block: convert bsg_device.ref_count from atomic_t to refcount_t > drivers, block: convert xen_blkif.refcnt from atomic_t to refcount_t Hi Elena, While the bsg ref_count is cheap, do you have any numbers how the other conversions compare in performance (throughput and latency) vs atomics? It should be quite easy to measure against a null_blk device. Thanks a lot, Johannes -- Johannes Thumshirn Storage jthumsh...@suse.de+49 911 74053 689 SUSE LINUX GmbH, Maxfeldstr. 5, 90409 Nürnberg GF: Felix Imendörffer, Jane Smithard, Graham Norton HRB 21284 (AG Nürnberg) Key fingerprint = EC38 9CAB C2C4 F25D 8600 D0D0 0393 969D 2D76 0850
[PATCH 1/6] block: convert bio.__bi_cnt from atomic_t to refcount_t
atomic_t variables are currently used to implement reference counters with the following properties: - counter is initialized to 1 using atomic_set() - a resource is freed upon counter reaching zero - once counter reaches zero, its further increments aren't allowed - counter schema uses basic atomic operations (set, inc, inc_not_zero, dec_and_test, etc.) Such atomic variables should be converted to a newly provided refcount_t type and API that prevents accidental counter overflows and underflows. This is important since overflows and underflows can lead to use-after-free situation and be exploitable. The variable bio.__bi_cnt is used as pure reference counter. Convert it to refcount_t and fix up the operations. Suggested-by: Kees CookReviewed-by: David Windsor Reviewed-by: Hans Liljestrand Signed-off-by: Elena Reshetova --- block/bio.c | 6 +++--- fs/btrfs/volumes.c| 2 +- include/linux/bio.h | 4 ++-- include/linux/blk_types.h | 3 ++- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/block/bio.c b/block/bio.c index 101c2a9..58edc1b 100644 --- a/block/bio.c +++ b/block/bio.c @@ -279,7 +279,7 @@ void bio_init(struct bio *bio, struct bio_vec *table, { memset(bio, 0, sizeof(*bio)); atomic_set(>__bi_remaining, 1); - atomic_set(>__bi_cnt, 1); + refcount_set(>__bi_cnt, 1); bio->bi_io_vec = table; bio->bi_max_vecs = max_vecs; @@ -557,12 +557,12 @@ void bio_put(struct bio *bio) if (!bio_flagged(bio, BIO_REFFED)) bio_free(bio); else { - BIO_BUG_ON(!atomic_read(>__bi_cnt)); + BIO_BUG_ON(!refcount_read(>__bi_cnt)); /* * last put frees it */ - if (atomic_dec_and_test(>__bi_cnt)) + if (refcount_dec_and_test(>__bi_cnt)) bio_free(bio); } } diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index b397375..11812ee 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -450,7 +450,7 @@ static noinline void run_scheduled_bios(struct btrfs_device *device) waitqueue_active(_info->async_submit_wait)) wake_up(_info->async_submit_wait); - BUG_ON(atomic_read(>__bi_cnt) == 0); + BUG_ON(refcount_read(>__bi_cnt) == 0); /* * if we're doing the sync list, record that our diff --git a/include/linux/bio.h b/include/linux/bio.h index 275c91c..0fa4dd2 100644 --- a/include/linux/bio.h +++ b/include/linux/bio.h @@ -253,7 +253,7 @@ static inline void bio_get(struct bio *bio) { bio->bi_flags |= (1 << BIO_REFFED); smp_mb__before_atomic(); - atomic_inc(>__bi_cnt); + refcount_inc(>__bi_cnt); } static inline void bio_cnt_set(struct bio *bio, unsigned int count) @@ -262,7 +262,7 @@ static inline void bio_cnt_set(struct bio *bio, unsigned int count) bio->bi_flags |= (1 << BIO_REFFED); smp_mb__before_atomic(); } - atomic_set(>__bi_cnt, count); + refcount_set(>__bi_cnt, count); } static inline bool bio_flagged(struct bio *bio, unsigned int bit) diff --git a/include/linux/blk_types.h b/include/linux/blk_types.h index a2d2aa7..1ec370e 100644 --- a/include/linux/blk_types.h +++ b/include/linux/blk_types.h @@ -7,6 +7,7 @@ #include #include +#include struct bio_set; struct bio; @@ -104,7 +105,7 @@ struct bio { unsigned short bi_max_vecs;/* max bvl_vecs we can hold */ - atomic_t__bi_cnt; /* pin count */ + refcount_t __bi_cnt; /* pin count */ struct bio_vec *bi_io_vec; /* the actual vec list */ -- 2.7.4
[PATCH 3/6] block: convert blkcg_gq.refcnt from atomic_t to refcount_t
atomic_t variables are currently used to implement reference counters with the following properties: - counter is initialized to 1 using atomic_set() - a resource is freed upon counter reaching zero - once counter reaches zero, its further increments aren't allowed - counter schema uses basic atomic operations (set, inc, inc_not_zero, dec_and_test, etc.) Such atomic variables should be converted to a newly provided refcount_t type and API that prevents accidental counter overflows and underflows. This is important since overflows and underflows can lead to use-after-free situation and be exploitable. The variable blkcg_gq.refcnt is used as pure reference counter. Convert it to refcount_t and fix up the operations. Suggested-by: Kees CookReviewed-by: David Windsor Reviewed-by: Hans Liljestrand Signed-off-by: Elena Reshetova --- block/blk-cgroup.c | 2 +- include/linux/blk-cgroup.h | 11 ++- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c index d3f56ba..1e7cedc 100644 --- a/block/blk-cgroup.c +++ b/block/blk-cgroup.c @@ -107,7 +107,7 @@ static struct blkcg_gq *blkg_alloc(struct blkcg *blkcg, struct request_queue *q, blkg->q = q; INIT_LIST_HEAD(>q_node); blkg->blkcg = blkcg; - atomic_set(>refcnt, 1); + refcount_set(>refcnt, 1); /* root blkg uses @q->root_rl, init rl only for !root blkgs */ if (blkcg != _root) { diff --git a/include/linux/blk-cgroup.h b/include/linux/blk-cgroup.h index 9d92153..c95d29d 100644 --- a/include/linux/blk-cgroup.h +++ b/include/linux/blk-cgroup.h @@ -19,6 +19,7 @@ #include #include #include +#include /* percpu_counter batch for blkg_[rw]stats, per-cpu drift doesn't matter */ #define BLKG_STAT_CPU_BATCH(INT_MAX / 2) @@ -122,7 +123,7 @@ struct blkcg_gq { struct request_list rl; /* reference count */ - atomic_trefcnt; + refcount_t refcnt; /* is this blkg online? protected by both blkcg and q locks */ boolonline; @@ -354,8 +355,8 @@ static inline int blkg_path(struct blkcg_gq *blkg, char *buf, int buflen) */ static inline void blkg_get(struct blkcg_gq *blkg) { - WARN_ON_ONCE(atomic_read(>refcnt) <= 0); - atomic_inc(>refcnt); + WARN_ON_ONCE(refcount_read(>refcnt) == 0); + refcount_inc(>refcnt); } void __blkg_release_rcu(struct rcu_head *rcu); @@ -366,8 +367,8 @@ void __blkg_release_rcu(struct rcu_head *rcu); */ static inline void blkg_put(struct blkcg_gq *blkg) { - WARN_ON_ONCE(atomic_read(>refcnt) <= 0); - if (atomic_dec_and_test(>refcnt)) + WARN_ON_ONCE(refcount_read(>refcnt) == 0); + if (refcount_dec_and_test(>refcnt)) call_rcu(>rcu_head, __blkg_release_rcu); } -- 2.7.4
[PATCH 6/6] drivers, block: convert xen_blkif.refcnt from atomic_t to refcount_t
atomic_t variables are currently used to implement reference counters with the following properties: - counter is initialized to 1 using atomic_set() - a resource is freed upon counter reaching zero - once counter reaches zero, its further increments aren't allowed - counter schema uses basic atomic operations (set, inc, inc_not_zero, dec_and_test, etc.) Such atomic variables should be converted to a newly provided refcount_t type and API that prevents accidental counter overflows and underflows. This is important since overflows and underflows can lead to use-after-free situation and be exploitable. The variable xen_blkif.refcnt is used as pure reference counter. Convert it to refcount_t and fix up the operations. Suggested-by: Kees CookReviewed-by: David Windsor Reviewed-by: Hans Liljestrand Signed-off-by: Elena Reshetova --- drivers/block/xen-blkback/common.h | 7 --- drivers/block/xen-blkback/xenbus.c | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index ecb35fe..0c3320d 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -319,7 +320,7 @@ struct xen_blkif { struct xen_vbd vbd; /* Back pointer to the backend_info. */ struct backend_info *be; - atomic_trefcnt; + refcount_t refcnt; /* for barrier (drain) requests */ struct completion drain_complete; atomic_tdrain; @@ -372,10 +373,10 @@ struct pending_req { (_v)->bdev->bd_part->nr_sects : \ get_capacity((_v)->bdev->bd_disk)) -#define xen_blkif_get(_b) (atomic_inc(&(_b)->refcnt)) +#define xen_blkif_get(_b) (refcount_inc(&(_b)->refcnt)) #define xen_blkif_put(_b) \ do {\ - if (atomic_dec_and_test(&(_b)->refcnt)) \ + if (refcount_dec_and_test(&(_b)->refcnt)) \ schedule_work(&(_b)->free_work);\ } while (0) diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 21c1be1..5955b61 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c @@ -176,7 +176,7 @@ static struct xen_blkif *xen_blkif_alloc(domid_t domid) return ERR_PTR(-ENOMEM); blkif->domid = domid; - atomic_set(>refcnt, 1); + refcount_set(>refcnt, 1); init_completion(>drain_complete); INIT_WORK(>free_work, xen_blkif_deferred_free); -- 2.7.4
[PATCH 4/6] block: convert io_context.active_ref from atomic_t to refcount_t
atomic_t variables are currently used to implement reference counters with the following properties: - counter is initialized to 1 using atomic_set() - a resource is freed upon counter reaching zero - once counter reaches zero, its further increments aren't allowed - counter schema uses basic atomic operations (set, inc, inc_not_zero, dec_and_test, etc.) Such atomic variables should be converted to a newly provided refcount_t type and API that prevents accidental counter overflows and underflows. This is important since overflows and underflows can lead to use-after-free situation and be exploitable. The variable io_context.active_ref is used as pure reference counter. Convert it to refcount_t and fix up the operations. Suggested-by: Kees CookReviewed-by: David Windsor Reviewed-by: Hans Liljestrand Signed-off-by: Elena Reshetova --- block/bfq-iosched.c | 2 +- block/blk-ioc.c | 4 ++-- block/cfq-iosched.c | 4 ++-- include/linux/iocontext.h | 7 --- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c index a4783da..1ec9b22 100644 --- a/block/bfq-iosched.c +++ b/block/bfq-iosched.c @@ -4030,7 +4030,7 @@ static void bfq_update_has_short_ttime(struct bfq_data *bfqd, * bfqq. Otherwise check average think time to * decide whether to mark as has_short_ttime */ - if (atomic_read(>icq.ioc->active_ref) == 0 || + if (refcount_read(>icq.ioc->active_ref) == 0 || (bfq_sample_valid(bfqq->ttime.ttime_samples) && bfqq->ttime.ttime_mean > bfqd->bfq_slice_idle)) has_short_ttime = false; diff --git a/block/blk-ioc.c b/block/blk-ioc.c index 63898d2..69704d2 100644 --- a/block/blk-ioc.c +++ b/block/blk-ioc.c @@ -176,7 +176,7 @@ void put_io_context_active(struct io_context *ioc) unsigned long flags; struct io_cq *icq; - if (!atomic_dec_and_test(>active_ref)) { + if (!refcount_dec_and_test(>active_ref)) { put_io_context(ioc); return; } @@ -275,7 +275,7 @@ int create_task_io_context(struct task_struct *task, gfp_t gfp_flags, int node) /* initialize */ atomic_long_set(>refcount, 1); atomic_set(>nr_tasks, 1); - atomic_set(>active_ref, 1); + refcount_set(>active_ref, 1); spin_lock_init(>lock); INIT_RADIX_TREE(>icq_tree, GFP_ATOMIC | __GFP_HIGH); INIT_HLIST_HEAD(>icq_list); diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c index 9f342ef..e6d5d6d 100644 --- a/block/cfq-iosched.c +++ b/block/cfq-iosched.c @@ -2941,7 +2941,7 @@ static void cfq_arm_slice_timer(struct cfq_data *cfqd) * task has exited, don't wait */ cic = cfqd->active_cic; - if (!cic || !atomic_read(>icq.ioc->active_ref)) + if (!cic || !refcount_read(>icq.ioc->active_ref)) return; /* @@ -3933,7 +3933,7 @@ cfq_update_idle_window(struct cfq_data *cfqd, struct cfq_queue *cfqq, if (cfqq->next_rq && req_noidle(cfqq->next_rq)) enable_idle = 0; - else if (!atomic_read(>icq.ioc->active_ref) || + else if (!refcount_read(>icq.ioc->active_ref) || !cfqd->cfq_slice_idle || (!cfq_cfqq_deep(cfqq) && CFQQ_SEEKY(cfqq))) enable_idle = 0; diff --git a/include/linux/iocontext.h b/include/linux/iocontext.h index df38db2..a1e28c3 100644 --- a/include/linux/iocontext.h +++ b/include/linux/iocontext.h @@ -3,6 +3,7 @@ #include #include +#include #include enum { @@ -96,7 +97,7 @@ struct io_cq { */ struct io_context { atomic_long_t refcount; - atomic_t active_ref; + refcount_t active_ref; atomic_t nr_tasks; /* all the fields below are protected by this lock */ @@ -128,9 +129,9 @@ struct io_context { static inline void get_io_context_active(struct io_context *ioc) { WARN_ON_ONCE(atomic_long_read(>refcount) <= 0); - WARN_ON_ONCE(atomic_read(>active_ref) <= 0); + WARN_ON_ONCE(refcount_read(>active_ref) == 0); atomic_long_inc(>refcount); - atomic_inc(>active_ref); + refcount_inc(>active_ref); } static inline void ioc_task_link(struct io_context *ioc) -- 2.7.4
[PATCH 5/6] block: convert bsg_device.ref_count from atomic_t to refcount_t
atomic_t variables are currently used to implement reference counters with the following properties: - counter is initialized to 1 using atomic_set() - a resource is freed upon counter reaching zero - once counter reaches zero, its further increments aren't allowed - counter schema uses basic atomic operations (set, inc, inc_not_zero, dec_and_test, etc.) Such atomic variables should be converted to a newly provided refcount_t type and API that prevents accidental counter overflows and underflows. This is important since overflows and underflows can lead to use-after-free situation and be exploitable. The variable bsg_device.ref_count is used as pure reference counter. Convert it to refcount_t and fix up the operations. Suggested-by: Kees CookReviewed-by: David Windsor Reviewed-by: Hans Liljestrand Signed-off-by: Elena Reshetova --- block/bsg.c | 9 + 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/block/bsg.c b/block/bsg.c index ee1335c..6c98422 100644 --- a/block/bsg.c +++ b/block/bsg.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -38,7 +39,7 @@ struct bsg_device { struct list_head busy_list; struct list_head done_list; struct hlist_node dev_list; - atomic_t ref_count; + refcount_t ref_count; int queued_cmds; int done_cmds; wait_queue_head_t wq_done; @@ -710,7 +711,7 @@ static int bsg_put_device(struct bsg_device *bd) mutex_lock(_mutex); - do_free = atomic_dec_and_test(>ref_count); + do_free = refcount_dec_and_test(>ref_count); if (!do_free) { mutex_unlock(_mutex); goto out; @@ -768,7 +769,7 @@ static struct bsg_device *bsg_add_device(struct inode *inode, bsg_set_block(bd, file); - atomic_set(>ref_count, 1); + refcount_set(>ref_count, 1); mutex_lock(_mutex); hlist_add_head(>dev_list, bsg_dev_idx_hash(iminor(inode))); @@ -788,7 +789,7 @@ static struct bsg_device *__bsg_get_device(int minor, struct request_queue *q) hlist_for_each_entry(bd, bsg_dev_idx_hash(minor), dev_list) { if (bd->queue == q) { - atomic_inc(>ref_count); + refcount_inc(>ref_count); goto found; } } -- 2.7.4
[PATCH 2/6] block: convert blk_queue_tag.refcnt from atomic_t to refcount_t
atomic_t variables are currently used to implement reference counters with the following properties: - counter is initialized to 1 using atomic_set() - a resource is freed upon counter reaching zero - once counter reaches zero, its further increments aren't allowed - counter schema uses basic atomic operations (set, inc, inc_not_zero, dec_and_test, etc.) Such atomic variables should be converted to a newly provided refcount_t type and API that prevents accidental counter overflows and underflows. This is important since overflows and underflows can lead to use-after-free situation and be exploitable. The variable blk_queue_tag.refcnt is used as pure reference counter. Convert it to refcount_t and fix up the operations. Suggested-by: Kees CookReviewed-by: David Windsor Reviewed-by: Hans Liljestrand Signed-off-by: Elena Reshetova --- block/blk-tag.c| 8 include/linux/blkdev.h | 3 ++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/block/blk-tag.c b/block/blk-tag.c index e1a9c15..a7263e3 100644 --- a/block/blk-tag.c +++ b/block/blk-tag.c @@ -35,7 +35,7 @@ EXPORT_SYMBOL(blk_queue_find_tag); */ void blk_free_tags(struct blk_queue_tag *bqt) { - if (atomic_dec_and_test(>refcnt)) { + if (refcount_dec_and_test(>refcnt)) { BUG_ON(find_first_bit(bqt->tag_map, bqt->max_depth) < bqt->max_depth); @@ -130,7 +130,7 @@ static struct blk_queue_tag *__blk_queue_init_tags(struct request_queue *q, if (init_tag_map(q, tags, depth)) goto fail; - atomic_set(>refcnt, 1); + refcount_set(>refcnt, 1); tags->alloc_policy = alloc_policy; tags->next_tag = 0; return tags; @@ -180,7 +180,7 @@ int blk_queue_init_tags(struct request_queue *q, int depth, queue_flag_set(QUEUE_FLAG_QUEUED, q); return 0; } else - atomic_inc(>refcnt); + refcount_inc(>refcnt); /* * assign it, all done @@ -225,7 +225,7 @@ int blk_queue_resize_tags(struct request_queue *q, int new_depth) * Currently cannot replace a shared tag map with a new * one, so error out if this is the case */ - if (atomic_read(>refcnt) != 1) + if (refcount_read(>refcnt) != 1) return -EBUSY; /* diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 02fa42d..1fefdbb 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -26,6 +26,7 @@ #include #include #include +#include struct module; struct scsi_ioctl_command; @@ -295,7 +296,7 @@ struct blk_queue_tag { unsigned long *tag_map; /* bit map of free/busy tags */ int max_depth; /* what we will send to device */ int real_max_depth; /* what the array can hold */ - atomic_t refcnt;/* map can be shared */ + refcount_t refcnt; /* map can be shared */ int alloc_policy; /* tag allocation policy */ int next_tag; /* next tag */ }; -- 2.7.4
[PATCH 0/6] v4 block refcount conversion patches
Changes in v4: - Improved commit messages and signoff info. - Rebase on top of linux-next as of yesterday. - WARN_ONs are restored since x86 refcount_t does not WARN on zero Changes in v3: No changes in patches apart from trivial rebases, but now by default refcount_t = atomic_t and uses all atomic standard operations unless CONFIG_REFCOUNT_FULL is enabled. This is a compromize for the systems that are critical on performance and cannot accept even slight delay on the refcounter operations. Changes in v2: Not needed WARNs are removed since refcount_t warns by itself. BUG_ONs are left as it is, since refcount_t doesn't bug by default. This series, for block subsystem, replaces atomic_t reference counters with the new refcount_t type and API (see include/linux/refcount.h). By doing this we prevent intentional or accidental underflows or overflows that can lead to use-after-free vulnerabilities. The patches are fully independent and can be cherry-picked separately. If there are no objections to the patches, please merge them via respective trees. Elena Reshetova (6): block: convert bio.__bi_cnt from atomic_t to refcount_t block: convert blk_queue_tag.refcnt from atomic_t to refcount_t block: convert blkcg_gq.refcnt from atomic_t to refcount_t block: convert io_context.active_ref from atomic_t to refcount_t block: convert bsg_device.ref_count from atomic_t to refcount_t drivers, block: convert xen_blkif.refcnt from atomic_t to refcount_t block/bfq-iosched.c| 2 +- block/bio.c| 6 +++--- block/blk-cgroup.c | 2 +- block/blk-ioc.c| 4 ++-- block/blk-tag.c| 8 block/bsg.c| 9 + block/cfq-iosched.c| 4 ++-- drivers/block/xen-blkback/common.h | 7 --- drivers/block/xen-blkback/xenbus.c | 2 +- fs/btrfs/volumes.c | 2 +- include/linux/bio.h| 4 ++-- include/linux/blk-cgroup.h | 11 ++- include/linux/blk_types.h | 3 ++- include/linux/blkdev.h | 3 ++- include/linux/iocontext.h | 7 --- 15 files changed, 40 insertions(+), 34 deletions(-) -- 2.7.4
Re: [PATCH v2 02/15] usb: gadget: make config_item_type structures const
On Thu, Oct 19, 2017 at 5:05 PM, Laurent Pinchartwrote: > Hi Christoph, > > On Thursday, 19 October 2017 17:06:57 EEST Christoph Hellwig wrote: >> > Now we have 9 const instances of the config_item_type structure that are >> > identical, with only the .ct_owner field set. Should they be all merged >> > into a single structure ? >> >> I think that's a good idea. >> >> But I'm about to slurp up this whole series into my tree, how about making >> that an incremental patch? > > I'm fine with that. > > Bhumika, would you like to submit an incremental patch, or should I do it ? > I will submit a patch for merging these structures. But should I make a separate patch for this particular change or send a v3 for the whole series? Thanks, Bhumika > -- > Regards, > > Laurent Pinchart >
Re: [PATCH v2 02/15] usb: gadget: make config_item_type structures const
On Thu, 19 Oct 2017, Laurent Pinchart wrote: > Hi Christoph, > > On Thursday, 19 October 2017 17:06:57 EEST Christoph Hellwig wrote: > > > Now we have 9 const instances of the config_item_type structure that are > > > identical, with only the .ct_owner field set. Should they be all merged > > > into a single structure ? > > > > I think that's a good idea. > > > > But I'm about to slurp up this whole series into my tree, how about making > > that an incremental patch? > > I'm fine with that. > > Bhumika, would you like to submit an incremental patch, or should I do it ? For various types, there seem to be a few hundred of these, eg: static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = { .rates = SNDRV_PCM_RATE_44100, /* fixed rate */ }; static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = { .rates = SNDRV_PCM_RATE_44100, /* fixed rate */ }; Would it be desirable to remove them? I guess one would have to check that there are not any pointer equality checks on these values. Would it be useful to put a #define to keep the orignal names? julia
Re: [PATCH] scsi/eh: fix hang adding ehandler wakeups after decrementing host_busy
ping On 09/05/2017 03:54 PM, Pavel Tikhomirov wrote: We have a problem on several our nodes with scsi EH. Imagine such an order of execution of two threads: CPU1 scsi_eh_scmd_add CPU2 scsi_host_queue_ready /* shost->host_busy == 1 initialy */ if (shost->shost_state == SHOST_RECOVERY) /* does not get here */ return 0; lock(shost->host_lock); shost->shost_state = SHOST_RECOVERY; busy = shost->host_busy++; /* host->can_queue == 1 initialy, busy == 1 * - go to starved label */ lock(shost->host_lock) /* wait */ shost->host_failed++; /* shost->host_busy == 2, shost->host_failed == 1 */ call scsi_eh_wakeup(shost) { if (host_busy == host_failed) { /* does not get here */ wake_up_process(shost->ehandler) } } unlock(shost->host_lock) /* acquire lock */ shost->host_busy--; Finaly we do not wakeup scsi_error_handler and all other commands coming will hang as we are in never ending recovery state as there is no one left to wakeup handler. So scsi disc in these host becomes unresponsive and all bio on node hangs. (We trigger these problem when scsi cmnds to DVD drive timeout.) Main idea of the fix is to try to do wake up every time we decrement host_busy or increment host_failed(the latter is already OK). Now the very *last* one of busy threads getting host_lock after decrementing host_busy will see all write operations on host's shost_state, host_busy and host_failed completed thanks to implied memory barriers on spin_lock/unlock, so at the time of busy==failed we will trigger wakeup in at least one thread. (Thats why putting recovery and failed checks under lock) Signed-off-by: Pavel Tikhomirov--- drivers/scsi/scsi_lib.c | 21 + 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index f6097b89d5d3..6c99221d60aa 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -320,12 +320,11 @@ void scsi_device_unbusy(struct scsi_device *sdev) if (starget->can_queue > 0) atomic_dec(>target_busy); + spin_lock_irqsave(shost->host_lock, flags); if (unlikely(scsi_host_in_recovery(shost) && -(shost->host_failed || shost->host_eh_scheduled))) { - spin_lock_irqsave(shost->host_lock, flags); +(shost->host_failed || shost->host_eh_scheduled))) scsi_eh_wakeup(shost); - spin_unlock_irqrestore(shost->host_lock, flags); - } + spin_unlock_irqrestore(shost->host_lock, flags); atomic_dec(>device_busy); } @@ -1503,6 +1502,13 @@ static inline int scsi_host_queue_ready(struct request_queue *q, spin_unlock_irq(shost->host_lock); out_dec: atomic_dec(>host_busy); + + spin_lock_irq(shost->host_lock); + if (unlikely(scsi_host_in_recovery(shost) && +(shost->host_failed || shost->host_eh_scheduled))) + scsi_eh_wakeup(shost); + spin_unlock_irq(shost->host_lock); + return 0; } @@ -1964,6 +1970,13 @@ static blk_status_t scsi_queue_rq(struct blk_mq_hw_ctx *hctx, out_dec_host_busy: atomic_dec(>host_busy); + + spin_lock_irq(shost->host_lock); + if (unlikely(scsi_host_in_recovery(shost) && +(shost->host_failed || shost->host_eh_scheduled))) + scsi_eh_wakeup(shost); + spin_unlock_irq(shost->host_lock); + out_dec_target_busy: if (scsi_target(sdev)->can_queue > 0) atomic_dec(_target(sdev)->target_busy); -- Best regards, Tikhomirov Pavel Software Developer, Virtuozzo.