[PATCH] scsi: core: fix two wrong indentation cases
No functional changes. Just fix two wrong indentation cases in scsi_finish_command and scsi_decide_disposition. Signed-off-by: Jianchao Wang --- drivers/scsi/scsi.c | 2 +- drivers/scsi/scsi_error.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index a7e4fba..4c60c26 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -231,7 +231,7 @@ void scsi_finish_command(struct scsi_cmnd *cmd) "(result %x)\n", cmd->result)); good_bytes = scsi_bufflen(cmd); -if (!blk_rq_is_passthrough(cmd->request)) { + if (!blk_rq_is_passthrough(cmd->request)) { int old_good_bytes = good_bytes; drv = scsi_cmd_to_driver(cmd); if (drv->done) diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index d042915..96066d1 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -1888,7 +1888,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd) } return FAILED; - maybe_retry: +maybe_retry: /* we requeue for retry because the error was retryable, and * the request was not marked fast fail. Note that above, -- 2.7.4
[PATCH] scsi: core: use blk_mq_requeue_request in __scsi_queue_insert
In scsi core, __scsi_queue_insert should just put request back on the queue and retry using the same command as before. However, for blk-mq, scsi_mq_requeue_cmd is employed here which will unprepare the request. To align with the semantics of __scsi_queue_insert, just use blk_mq_requeue_request with kick_requeue_list == true. Cc: Christoph Hellwig Signed-off-by: Jianchao Wang --- drivers/scsi/scsi_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index a86df9c..06d8110 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -191,7 +191,7 @@ static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, bool unbusy) */ cmd->result = 0; if (q->mq_ops) { - scsi_mq_requeue_cmd(cmd); + blk_mq_requeue_request(cmd->request, true); return; } spin_lock_irqsave(q->queue_lock, flags); -- 2.7.4
Re: [PATCH] lpfc: correct writeq failures on 32-bit architectures
Looks good, Reviewed-by: Johannes Thumshirn -- 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] scsi: return BLK_STS_OK for DID_OK in __scsi_error_from_host_byte()
When converting __scsi_error_from_host_byte() to BLK_STS error codes the case DID_OK was forgotten, resulting in it always returning an error. Fixes: 2a842acab109 ("block: introduce new block status code type") Cc: Doug Gilbert Signed-off-by: Hannes Reinecke --- drivers/scsi/scsi_lib.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index aea5a1ae318b..11d63136f0bd 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -720,6 +720,8 @@ static blk_status_t __scsi_error_from_host_byte(struct scsi_cmnd *cmd, int result) { switch (host_byte(result)) { + case DID_OK: + return BLK_STS_OK; case DID_TRANSPORT_FAILFAST: return BLK_STS_TRANSPORT; case DID_TARGET_FAILURE: -- 2.12.3
Re: [PATCH v2] Make SCSI Status CONDITION MET equivalent to GOOD
On 02/25/2018 07:29 PM, Douglas Gilbert wrote: > The SCSI PRE-FETCH (10 or 16) command is present both on hard disks > and some SSDs. It is useful when the address of the next block(s) to > be read is known but it is not following the LBA of the current READ > (so read-ahead won't help). It returns two "good" SCSI Status values. > If the requested blocks have fitted (or will most likely fit (when > the IMMED bit is set)) into the disk's cache, it returns CONDITION > MET. If it didn't (or will not) fit then it returns GOOD status. > > The primary goal of this patch is to stop the SCSI subsystem treating > the CONDITION MET SCSI status as an error. The current state makes the > PRE-FETCH command effectively unusable via pass-throughs. The hunt to > find where the erroneous decision was made led to the > scsi_io_completion() function in scsi_lib.c . This is a complicated > function made more complicated by the intertwining of good and error > (or special case) processing paths. > > Future work: if the sd driver was to use the PRE-FETCH command, > decide whether it and/or the block layer needs to know about the > two different "good" statuses. If so a mechanism would be needed > to do that. > > ChangeLog to v2: > - further restructure the code, place some early non-zero > result processing in a new helper function: > scsi_io_completion_nz_result() > - this reduces the number of error checks on the zero result > path (the fast path) at the expense of some extra work for > the non-zero result processing > - rename some variables to make the code a little clearer > > ChangeLog to v1: > - expand scsi_status_is_good() to check for CONDITION MET > - add another corner case in scsi_io_completion() adjacent > to the one for the RECOVERED ERROR sense key case. That > is another "non-error" > - structure code so extra checks are only on the error > path (i.e. when cmd->result is non-zero) > > This patch is against mkp's 4.17/scsi-queue branch. It also applies > to lk 4.15.x where it was re-tested on a SAS SSD. > > Signed-off-by: Douglas Gilbert > --- > drivers/scsi/scsi_lib.c | 140 > +--- > include/scsi/scsi.h | 2 + > 2 files changed, 87 insertions(+), 55 deletions(-) > > diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c > index aea5a1ae318b..e1e974f08d52 100644 > --- a/drivers/scsi/scsi_lib.c > +++ b/drivers/scsi/scsi_lib.c > @@ -738,6 +738,73 @@ static blk_status_t __scsi_error_from_host_byte(struct > scsi_cmnd *cmd, > } > } > > +/* Helper for scsi_io_completion() when cmd->result is non-zero. */ > +static int scsi_io_completion_nz_result(struct scsi_cmnd *cmd, > + blk_status_t *blk_statp) > +{ > + bool sense_valid; > + bool about_current; > + int result = cmd->result; > + struct request *req = cmd->request; > + struct scsi_sense_hdr sshdr; > + > + sense_valid = scsi_command_normalize_sense(cmd, &sshdr); > + about_current = sense_valid ? !scsi_sense_is_deferred(&sshdr) : true; > + > + if (blk_rq_is_passthrough(req)) { > + if (sense_valid) { > + /* > + * SG_IO wants current and deferred errors > + */ > + scsi_req(req)->sense_len = > + min(8 + cmd->sense_buffer[7], > + SCSI_SENSE_BUFFERSIZE); > + } > + if (about_current) > + *blk_statp = __scsi_error_from_host_byte(cmd, result); > + } else if (blk_rq_bytes(req) == 0 && about_current) { > + /* > + * Flush commands do not transfers any data, and thus cannot use > + * good_bytes != blk_rq_bytes(req) as the signal for an error. > + * This sets the error explicitly for the problem case. > + */ > + *blk_statp = __scsi_error_from_host_byte(cmd, result); > + } > + /* > + * Recovered errors need reporting, but they're always treated as > + * success, so fiddle the result code here. For passthrough requests > + * we already took a copy of the original into sreq->result which > + * is what gets returned to the user > + */ > + if (sense_valid && (sshdr.sense_key == RECOVERED_ERROR)) { > + /* > + * if ATA PASS-THROUGH INFORMATION AVAILABLE skip > + * print since caller wants ATA registers. Only occurs > + * on SCSI ATA PASS_THROUGH commands when CK_COND=1 > + */ > + if ((sshdr.asc == 0x0) && (sshdr.ascq == 0x1d)) > + ; > + else if (!(req->rq_flags & RQF_QUIET)) > + scsi_print_sense(cmd); > + result = 0; > + *blk_statp = BLK_STS_OK; > + /* for passthrough, blk_stat may be set */ > + } > + /* > + * Another corne
[PATCH v3] Make SCSI Status CONDITION MET equivalent to GOOD
Comment on v3: Even though there has been no feedback on v2, its seems like a missed opportunity not to continue the refactoring of scsi_io_completion() started in v2. Now the main function has 34 lines of code of which the fast path visits 12; it has half as many local variables and no goto (jumping into a case block). The SCSI PRE-FETCH (10 or 16) command is present both on hard disks and some SSDs. It is useful when the address of the next block(s) to be read is known but it is not following the LBA of the current READ (so read-ahead won't help). It returns two "good" SCSI Status values. If the requested blocks have fitted (or will most likely fit (when the IMMED bit is set)) into the disk's cache, it returns CONDITION MET. If it didn't (or will not) fit then it returns GOOD status. The primary goal of this patch is to stop the SCSI subsystem treating the CONDITION MET SCSI status as an error. The current state makes the PRE-FETCH command effectively unusable via pass-throughs. The hunt to find where the erroneous decision was made led to the scsi_io_completion() function in scsi_lib.c . This is a complicated function made more complicated by the intertwining of good and error (or special case) processing paths. Future work: if the sd driver was to use the PRE-FETCH command, decide whether it and/or the block layer needs to know about the two different "good" statuses. If so a mechanism would be needed to do that. ChangeLog to v3: - continue restructuring, place the trailing special action logic in a new helper function: scsi_io_completion_action() - add conditional hints to the branches that remain in scsi_io_completion() as the fast path passes through here. ChangeLog to v2: - further restructure the code, place some early non-zero result processing in a new helper function: scsi_io_completion_nz_result() - this reduces the number of error checks on the zero result path (the fast path) at the expense of some extra work for the non-zero result processing - rename some variables to make the code a little clearer ChangeLog to v1: - expand scsi_status_is_good() to check for CONDITION MET - add another corner case in scsi_io_completion() adjacent to the one for the RECOVERED ERROR sense key case. That is another "non-error" - structure code so extra checks are only on the error path (i.e. when cmd->result is non-zero) This patch is against mkp's 4.17/scsi-queue branch. It also applies to lk 4.15.x where it was re-tested on a SAS SSD. Signed-off-by: Douglas Gilbert --- drivers/scsi/scsi_lib.c | 290 include/scsi/scsi.h | 2 + 2 files changed, 174 insertions(+), 118 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index aea5a1ae318b..6b68ba98d43f 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -738,104 +738,38 @@ static blk_status_t __scsi_error_from_host_byte(struct scsi_cmnd *cmd, } } -/* - * Function:scsi_io_completion() - * - * Purpose: Completion processing for block device I/O requests. - * - * Arguments: cmd - command that is finished. - * - * Lock status: Assumed that no lock is held upon entry. - * - * Returns: Nothing - * - * Notes: We will finish off the specified number of sectors. If we - * are done, the command block will be released and the queue - * function will be goosed. If we are not done then we have to - * figure out what to do next: - * - * a) We can call scsi_requeue_command(). The request - *will be unprepared and put back on the queue. Then - *a new command will be created for it. This should - *be used if we made forward progress, or if we want - *to switch from READ(10) to READ(6) for example. - * - * b) We can call __scsi_queue_insert(). The request will - *be put back on the queue and retried using the same - *command as before, possibly after a delay. - * - * c) We can call scsi_end_request() with -EIO to fail - *the remainder of the request. - */ -void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) +/* Helper for scsi_io_completion() when cmd->result is non-zero. */ +static int scsi_io_completion_nz_result(struct scsi_cmnd *cmd, + blk_status_t *blk_statp) { + bool sense_valid; + bool about_current; int result = cmd->result; - struct request_queue *q = cmd->device->request_queue; struct request *req = cmd->request; - blk_status_t error = BLK_STS_OK; struct scsi_sense_hdr sshdr; - bool sense_valid = false; - int sense_deferred = 0, level = 0; - enum {ACTION_FAIL, ACTION_REPREP, ACTION_RETRY, - ACTION_DELAYED_RETRY} action; - unsigned long wait_for = (cmd
Re: [PATCH 9/9] scsi: ufs: Add clock ungating to a separate workqueue
On 2/24/2018 5:27 AM, Miguel Ojeda wrote: On Wed, Feb 21, 2018 at 5:56 AM, Asutosh Das wrote: From: Vijay Viswanath UFS driver can receive a request during memory reclaim by kswapd. So when ufs driver puts the ungate work in queue, and if there are no idle workers, kthreadd is invoked to create a new kworker. Since kswapd task holds a mutex which kthreadd also needs, this can cause a deadlock situation. So ungate work must be done in a separate work queue with WQ__RECLAIM flag enabled.Such a workqueue will have WQ_MEM_RECLAIM here. Also space after dot. a rescue thread which will be called when the above deadlock condition is possible. Signed-off-by: Vijay Viswanath Signed-off-by: Can Guo Signed-off-by: Asutosh Das --- drivers/scsi/ufs/ufshcd.c | 10 +- drivers/scsi/ufs/ufshcd.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 6541e1d..bb3382a 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -1503,7 +1503,8 @@ int ufshcd_hold(struct ufs_hba *hba, bool async) hba->clk_gating.state = REQ_CLKS_ON; trace_ufshcd_clk_gating(dev_name(hba->dev), hba->clk_gating.state); - schedule_work(&hba->clk_gating.ungate_work); + queue_work(hba->clk_gating.clk_gating_workq, + &hba->clk_gating.ungate_work); /* * fall through to check if we should wait for this * work to be done or not. @@ -1689,6 +1690,8 @@ static ssize_t ufshcd_clkgate_enable_store(struct device *dev, static void ufshcd_init_clk_gating(struct ufs_hba *hba) { + char wq_name[sizeof("ufs_clk_gating_00")]; + if (!ufshcd_is_clkgating_allowed(hba)) return; @@ -1696,6 +1699,10 @@ static void ufshcd_init_clk_gating(struct ufs_hba *hba) INIT_DELAYED_WORK(&hba->clk_gating.gate_work, ufshcd_gate_work); INIT_WORK(&hba->clk_gating.ungate_work, ufshcd_ungate_work); + snprintf(wq_name, ARRAY_SIZE(wq_name), "ufs_clk_gating_%d", +hba->host->host_no); + hba->clk_gating.clk_gating_workq = create_singlethread_workqueue(wq_name); Shouldn't this be alloc_ordered_workqueue() with WQ_MEM_RECLAIM then? (create_singlethread_workqueue() and friends are deprecated). Cheers, Miguel + hba->clk_gating.is_enabled = true; hba->clk_gating.delay_attr.show = ufshcd_clkgate_delay_show; @@ -1723,6 +1730,7 @@ static void ufshcd_exit_clk_gating(struct ufs_hba *hba) device_remove_file(hba->dev, &hba->clk_gating.enable_attr); cancel_work_sync(&hba->clk_gating.ungate_work); cancel_delayed_work_sync(&hba->clk_gating.gate_work); + destroy_workqueue(hba->clk_gating.clk_gating_workq); } /* Must be called with host lock acquired */ diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 4385741..570c33e 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -361,6 +361,7 @@ struct ufs_clk_gating { struct device_attribute enable_attr; bool is_enabled; int active_reqs; + struct workqueue_struct *clk_gating_workq; }; struct ufs_saved_pwr_info { -- Qualcomm India Private Limited, on behalf of Qualcomm Innovation Center, Inc. Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project. Hi Miguel Thanks for the review. I'll check this and put up the changes in v2. -asd -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, a Linux Foundation Collaborative Project
[PATCH v2] Make SCSI Status CONDITION MET equivalent to GOOD
The SCSI PRE-FETCH (10 or 16) command is present both on hard disks and some SSDs. It is useful when the address of the next block(s) to be read is known but it is not following the LBA of the current READ (so read-ahead won't help). It returns two "good" SCSI Status values. If the requested blocks have fitted (or will most likely fit (when the IMMED bit is set)) into the disk's cache, it returns CONDITION MET. If it didn't (or will not) fit then it returns GOOD status. The primary goal of this patch is to stop the SCSI subsystem treating the CONDITION MET SCSI status as an error. The current state makes the PRE-FETCH command effectively unusable via pass-throughs. The hunt to find where the erroneous decision was made led to the scsi_io_completion() function in scsi_lib.c . This is a complicated function made more complicated by the intertwining of good and error (or special case) processing paths. Future work: if the sd driver was to use the PRE-FETCH command, decide whether it and/or the block layer needs to know about the two different "good" statuses. If so a mechanism would be needed to do that. ChangeLog to v2: - further restructure the code, place some early non-zero result processing in a new helper function: scsi_io_completion_nz_result() - this reduces the number of error checks on the zero result path (the fast path) at the expense of some extra work for the non-zero result processing - rename some variables to make the code a little clearer ChangeLog to v1: - expand scsi_status_is_good() to check for CONDITION MET - add another corner case in scsi_io_completion() adjacent to the one for the RECOVERED ERROR sense key case. That is another "non-error" - structure code so extra checks are only on the error path (i.e. when cmd->result is non-zero) This patch is against mkp's 4.17/scsi-queue branch. It also applies to lk 4.15.x where it was re-tested on a SAS SSD. Signed-off-by: Douglas Gilbert --- drivers/scsi/scsi_lib.c | 140 +--- include/scsi/scsi.h | 2 + 2 files changed, 87 insertions(+), 55 deletions(-) diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index aea5a1ae318b..e1e974f08d52 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -738,6 +738,73 @@ static blk_status_t __scsi_error_from_host_byte(struct scsi_cmnd *cmd, } } +/* Helper for scsi_io_completion() when cmd->result is non-zero. */ +static int scsi_io_completion_nz_result(struct scsi_cmnd *cmd, + blk_status_t *blk_statp) +{ + bool sense_valid; + bool about_current; + int result = cmd->result; + struct request *req = cmd->request; + struct scsi_sense_hdr sshdr; + + sense_valid = scsi_command_normalize_sense(cmd, &sshdr); + about_current = sense_valid ? !scsi_sense_is_deferred(&sshdr) : true; + + if (blk_rq_is_passthrough(req)) { + if (sense_valid) { + /* +* SG_IO wants current and deferred errors +*/ + scsi_req(req)->sense_len = + min(8 + cmd->sense_buffer[7], + SCSI_SENSE_BUFFERSIZE); + } + if (about_current) + *blk_statp = __scsi_error_from_host_byte(cmd, result); + } else if (blk_rq_bytes(req) == 0 && about_current) { + /* +* Flush commands do not transfers any data, and thus cannot use +* good_bytes != blk_rq_bytes(req) as the signal for an error. +* This sets the error explicitly for the problem case. +*/ + *blk_statp = __scsi_error_from_host_byte(cmd, result); + } + /* +* Recovered errors need reporting, but they're always treated as +* success, so fiddle the result code here. For passthrough requests +* we already took a copy of the original into sreq->result which +* is what gets returned to the user +*/ + if (sense_valid && (sshdr.sense_key == RECOVERED_ERROR)) { + /* +* if ATA PASS-THROUGH INFORMATION AVAILABLE skip +* print since caller wants ATA registers. Only occurs +* on SCSI ATA PASS_THROUGH commands when CK_COND=1 +*/ + if ((sshdr.asc == 0x0) && (sshdr.ascq == 0x1d)) + ; + else if (!(req->rq_flags & RQF_QUIET)) + scsi_print_sense(cmd); + result = 0; + *blk_statp = BLK_STS_OK; + /* for passthrough, blk_stat may be set */ + } + /* +* Another corner case: the SCSI status byte is non-zero but 'good'. +* Example: PRE-FETCH command returns SAM_STAT_CONDITION_MET when +* it is able to fit nominated LBs
Re: [PATCH] scsi: lpfc: use memcpy_toio instead of writeq
Arnd Bergmann writes: > 32-bit architectures generally cannot use writeq(), so we now get a build > failure for the lpfc driver: > > drivers/scsi/lpfc/lpfc_sli.c: In function 'lpfc_sli4_wq_put': > drivers/scsi/lpfc/lpfc_sli.c:145:4: error: implicit declaration of function > 'writeq'; did you mean 'writeb'? [-Werror=implicit-function-declaration] Hi Arnd, why can't we use the writeq() from 'io-64-nonatomic-lo-hi.h'? I always thought these are compat versions for 32 Bit archs and even asked James to do so, what's why he did the change in the first place. My apologies for this James. Thanks, Johannes > > Another problem here is that writing out actual data (unlike accessing > mmio registers) means we must write the data with the same endianess > that we have read from memory, but writeq() will perform byte swaps > and add barriers inbetween accesses as we do for registers. > > Using memcpy_toio() should do the right thing here, using register > sized stores with correct endianess conversion and barriers (i.e. none), > but on some architectures might fall back to byte-size access. > > Side note: shouldn't the driver use ioremap_wc() instead of ioremap() > to get a write-combining mapping on all architectures that support this? > > Fixes: 1351e69fc6db ("scsi: lpfc: Add push-to-adapter support to sli4") > Signed-off-by: Arnd Bergmann > --- > drivers/scsi/lpfc/lpfc_sli.c | 9 +++-- > 1 file changed, 3 insertions(+), 6 deletions(-) > > diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c > index 4ce3ca6f4b79..6749d41753b4 100644 > --- a/drivers/scsi/lpfc/lpfc_sli.c > +++ b/drivers/scsi/lpfc/lpfc_sli.c > @@ -115,7 +115,6 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe > *wqe) > struct lpfc_register doorbell; > uint32_t host_index; > uint32_t idx; > - uint32_t i = 0; > uint8_t *tmp; > > /* sanity check on queue memory */ > @@ -138,12 +137,10 @@ lpfc_sli4_wq_put(struct lpfc_queue *q, union lpfc_wqe > *wqe) > if (q->phba->sli3_options & LPFC_SLI4_PHWQ_ENABLED) > bf_set(wqe_wqid, &wqe->generic.wqe_com, q->queue_id); > lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size); > - if (q->dpp_enable && q->phba->cfg_enable_dpp) { > + if (q->dpp_enable && q->phba->cfg_enable_dpp) > /* write to DPP aperture taking advatage of Combined Writes */ > - tmp = (uint8_t *)wqe; > - for (i = 0; i < q->entry_size; i += sizeof(uint64_t)) > - writeq(*((uint64_t *)(tmp + i)), q->dpp_regaddr + i); > - } > + memcpy_toio(tmp, q->dpp_regaddr, q->entry_size); > + > /* ensure WQE bcopy and DPP flushed before doorbell write */ > wmb(); -- 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