Skip to content

Commit a1bffa4

Browse files
committed
Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI fixes from James Bottomley: "Three fixes: one in drivers (lpfc) and two for zoned block devices. The latter also impinges on the block layer but only to introduce a new block API for setting the zone model rather than fiddling with the queue directly in the zoned block driver" * tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: scsi: sd: sd_zbc: Fix ZBC disk initialization scsi: sd: sd_zbc: Fix handling of host-aware ZBC disks scsi: lpfc: Fix initial FLOGI failure due to BBSCN not supported
2 parents 692495b + 6c5dee1 commit a1bffa4

File tree

6 files changed

+159
-73
lines changed

6 files changed

+159
-73
lines changed

block/blk-settings.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,52 @@ bool blk_queue_can_use_dma_map_merging(struct request_queue *q,
801801
}
802802
EXPORT_SYMBOL_GPL(blk_queue_can_use_dma_map_merging);
803803

804+
/**
805+
* blk_queue_set_zoned - configure a disk queue zoned model.
806+
* @disk: the gendisk of the queue to configure
807+
* @model: the zoned model to set
808+
*
809+
* Set the zoned model of the request queue of @disk according to @model.
810+
* When @model is BLK_ZONED_HM (host managed), this should be called only
811+
* if zoned block device support is enabled (CONFIG_BLK_DEV_ZONED option).
812+
* If @model specifies BLK_ZONED_HA (host aware), the effective model used
813+
* depends on CONFIG_BLK_DEV_ZONED settings and on the existence of partitions
814+
* on the disk.
815+
*/
816+
void blk_queue_set_zoned(struct gendisk *disk, enum blk_zoned_model model)
817+
{
818+
switch (model) {
819+
case BLK_ZONED_HM:
820+
/*
821+
* Host managed devices are supported only if
822+
* CONFIG_BLK_DEV_ZONED is enabled.
823+
*/
824+
WARN_ON_ONCE(!IS_ENABLED(CONFIG_BLK_DEV_ZONED));
825+
break;
826+
case BLK_ZONED_HA:
827+
/*
828+
* Host aware devices can be treated either as regular block
829+
* devices (similar to drive managed devices) or as zoned block
830+
* devices to take advantage of the zone command set, similarly
831+
* to host managed devices. We try the latter if there are no
832+
* partitions and zoned block device support is enabled, else
833+
* we do nothing special as far as the block layer is concerned.
834+
*/
835+
if (!IS_ENABLED(CONFIG_BLK_DEV_ZONED) ||
836+
disk_has_partitions(disk))
837+
model = BLK_ZONED_NONE;
838+
break;
839+
case BLK_ZONED_NONE:
840+
default:
841+
if (WARN_ON_ONCE(model != BLK_ZONED_NONE))
842+
model = BLK_ZONED_NONE;
843+
break;
844+
}
845+
846+
disk->queue->limits.zoned = model;
847+
}
848+
EXPORT_SYMBOL_GPL(blk_queue_set_zoned);
849+
804850
static int __init blk_settings_init(void)
805851
{
806852
blk_max_low_pfn = max_low_pfn - 1;

drivers/scsi/lpfc/lpfc_hbadisc.c

Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ static void lpfc_disc_timeout_handler(struct lpfc_vport *);
7171
static void lpfc_disc_flush_list(struct lpfc_vport *vport);
7272
static void lpfc_unregister_fcfi_cmpl(struct lpfc_hba *, LPFC_MBOXQ_t *);
7373
static int lpfc_fcf_inuse(struct lpfc_hba *);
74+
static void lpfc_mbx_cmpl_read_sparam(struct lpfc_hba *, LPFC_MBOXQ_t *);
7475

7576
void
7677
lpfc_terminate_rport_io(struct fc_rport *rport)
@@ -1138,11 +1139,13 @@ lpfc_mbx_cmpl_clear_la(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
11381139
return;
11391140
}
11401141

1141-
11421142
void
11431143
lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
11441144
{
11451145
struct lpfc_vport *vport = pmb->vport;
1146+
LPFC_MBOXQ_t *sparam_mb;
1147+
struct lpfc_dmabuf *sparam_mp;
1148+
int rc;
11461149

11471150
if (pmb->u.mb.mbxStatus)
11481151
goto out;
@@ -1167,12 +1170,42 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
11671170
}
11681171

11691172
/* Start discovery by sending a FLOGI. port_state is identically
1170-
* LPFC_FLOGI while waiting for FLOGI cmpl. Check if sending
1171-
* the FLOGI is being deferred till after MBX_READ_SPARAM completes.
1173+
* LPFC_FLOGI while waiting for FLOGI cmpl.
11721174
*/
11731175
if (vport->port_state != LPFC_FLOGI) {
1174-
if (!(phba->hba_flag & HBA_DEFER_FLOGI))
1176+
/* Issue MBX_READ_SPARAM to update CSPs before FLOGI if
1177+
* bb-credit recovery is in place.
1178+
*/
1179+
if (phba->bbcredit_support && phba->cfg_enable_bbcr &&
1180+
!(phba->link_flag & LS_LOOPBACK_MODE)) {
1181+
sparam_mb = mempool_alloc(phba->mbox_mem_pool,
1182+
GFP_KERNEL);
1183+
if (!sparam_mb)
1184+
goto sparam_out;
1185+
1186+
rc = lpfc_read_sparam(phba, sparam_mb, 0);
1187+
if (rc) {
1188+
mempool_free(sparam_mb, phba->mbox_mem_pool);
1189+
goto sparam_out;
1190+
}
1191+
sparam_mb->vport = vport;
1192+
sparam_mb->mbox_cmpl = lpfc_mbx_cmpl_read_sparam;
1193+
rc = lpfc_sli_issue_mbox(phba, sparam_mb, MBX_NOWAIT);
1194+
if (rc == MBX_NOT_FINISHED) {
1195+
sparam_mp = (struct lpfc_dmabuf *)
1196+
sparam_mb->ctx_buf;
1197+
lpfc_mbuf_free(phba, sparam_mp->virt,
1198+
sparam_mp->phys);
1199+
kfree(sparam_mp);
1200+
sparam_mb->ctx_buf = NULL;
1201+
mempool_free(sparam_mb, phba->mbox_mem_pool);
1202+
goto sparam_out;
1203+
}
1204+
1205+
phba->hba_flag |= HBA_DEFER_FLOGI;
1206+
} else {
11751207
lpfc_initial_flogi(vport);
1208+
}
11761209
} else {
11771210
if (vport->fc_flag & FC_PT2PT)
11781211
lpfc_disc_start(vport);
@@ -1184,6 +1217,7 @@ lpfc_mbx_cmpl_local_config_link(struct lpfc_hba *phba, LPFC_MBOXQ_t *pmb)
11841217
"0306 CONFIG_LINK mbxStatus error x%x "
11851218
"HBA state x%x\n",
11861219
pmb->u.mb.mbxStatus, vport->port_state);
1220+
sparam_out:
11871221
mempool_free(pmb, phba->mbox_mem_pool);
11881222

11891223
lpfc_linkdown(phba);
@@ -3239,21 +3273,6 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
32393273
lpfc_linkup(phba);
32403274
sparam_mbox = NULL;
32413275

3242-
if (!(phba->hba_flag & HBA_FCOE_MODE)) {
3243-
cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
3244-
if (!cfglink_mbox)
3245-
goto out;
3246-
vport->port_state = LPFC_LOCAL_CFG_LINK;
3247-
lpfc_config_link(phba, cfglink_mbox);
3248-
cfglink_mbox->vport = vport;
3249-
cfglink_mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link;
3250-
rc = lpfc_sli_issue_mbox(phba, cfglink_mbox, MBX_NOWAIT);
3251-
if (rc == MBX_NOT_FINISHED) {
3252-
mempool_free(cfglink_mbox, phba->mbox_mem_pool);
3253-
goto out;
3254-
}
3255-
}
3256-
32573276
sparam_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
32583277
if (!sparam_mbox)
32593278
goto out;
@@ -3274,7 +3293,20 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
32743293
goto out;
32753294
}
32763295

3277-
if (phba->hba_flag & HBA_FCOE_MODE) {
3296+
if (!(phba->hba_flag & HBA_FCOE_MODE)) {
3297+
cfglink_mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
3298+
if (!cfglink_mbox)
3299+
goto out;
3300+
vport->port_state = LPFC_LOCAL_CFG_LINK;
3301+
lpfc_config_link(phba, cfglink_mbox);
3302+
cfglink_mbox->vport = vport;
3303+
cfglink_mbox->mbox_cmpl = lpfc_mbx_cmpl_local_config_link;
3304+
rc = lpfc_sli_issue_mbox(phba, cfglink_mbox, MBX_NOWAIT);
3305+
if (rc == MBX_NOT_FINISHED) {
3306+
mempool_free(cfglink_mbox, phba->mbox_mem_pool);
3307+
goto out;
3308+
}
3309+
} else {
32783310
vport->port_state = LPFC_VPORT_UNKNOWN;
32793311
/*
32803312
* Add the driver's default FCF record at FCF index 0 now. This
@@ -3331,10 +3363,6 @@ lpfc_mbx_process_link_up(struct lpfc_hba *phba, struct lpfc_mbx_read_top *la)
33313363
}
33323364
/* Reset FCF roundrobin bmask for new discovery */
33333365
lpfc_sli4_clear_fcf_rr_bmask(phba);
3334-
} else {
3335-
if (phba->bbcredit_support && phba->cfg_enable_bbcr &&
3336-
!(phba->link_flag & LS_LOOPBACK_MODE))
3337-
phba->hba_flag |= HBA_DEFER_FLOGI;
33383366
}
33393367

33403368
/* Prepare for LINK up registrations */

drivers/scsi/sd.c

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2964,26 +2964,32 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
29642964

29652965
if (sdkp->device->type == TYPE_ZBC) {
29662966
/* Host-managed */
2967-
q->limits.zoned = BLK_ZONED_HM;
2967+
blk_queue_set_zoned(sdkp->disk, BLK_ZONED_HM);
29682968
} else {
29692969
sdkp->zoned = (buffer[8] >> 4) & 3;
2970-
if (sdkp->zoned == 1 && !disk_has_partitions(sdkp->disk)) {
2970+
if (sdkp->zoned == 1) {
29712971
/* Host-aware */
2972-
q->limits.zoned = BLK_ZONED_HA;
2972+
blk_queue_set_zoned(sdkp->disk, BLK_ZONED_HA);
29732973
} else {
2974-
/*
2975-
* Treat drive-managed devices and host-aware devices
2976-
* with partitions as regular block devices.
2977-
*/
2978-
q->limits.zoned = BLK_ZONED_NONE;
2979-
if (sdkp->zoned == 2 && sdkp->first_scan)
2980-
sd_printk(KERN_NOTICE, sdkp,
2981-
"Drive-managed SMR disk\n");
2974+
/* Regular disk or drive managed disk */
2975+
blk_queue_set_zoned(sdkp->disk, BLK_ZONED_NONE);
29822976
}
29832977
}
2984-
if (blk_queue_is_zoned(q) && sdkp->first_scan)
2978+
2979+
if (!sdkp->first_scan)
2980+
goto out;
2981+
2982+
if (blk_queue_is_zoned(q)) {
29852983
sd_printk(KERN_NOTICE, sdkp, "Host-%s zoned block device\n",
29862984
q->limits.zoned == BLK_ZONED_HM ? "managed" : "aware");
2985+
} else {
2986+
if (sdkp->zoned == 1)
2987+
sd_printk(KERN_NOTICE, sdkp,
2988+
"Host-aware SMR disk used as regular disk\n");
2989+
else if (sdkp->zoned == 2)
2990+
sd_printk(KERN_NOTICE, sdkp,
2991+
"Drive-managed SMR disk\n");
2992+
}
29872993

29882994
out:
29892995
kfree(buffer);
@@ -3404,10 +3410,6 @@ static int sd_probe(struct device *dev)
34043410
sdkp->first_scan = 1;
34053411
sdkp->max_medium_access_timeouts = SD_MAX_MEDIUM_TIMEOUTS;
34063412

3407-
error = sd_zbc_init_disk(sdkp);
3408-
if (error)
3409-
goto out_free_index;
3410-
34113413
sd_revalidate_disk(gd);
34123414

34133415
gd->flags = GENHD_FL_EXT_DEVT;

drivers/scsi/sd.h

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,6 @@ static inline int sd_is_zoned(struct scsi_disk *sdkp)
215215

216216
#ifdef CONFIG_BLK_DEV_ZONED
217217

218-
int sd_zbc_init_disk(struct scsi_disk *sdkp);
219218
void sd_zbc_release_disk(struct scsi_disk *sdkp);
220219
int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buffer);
221220
int sd_zbc_revalidate_zones(struct scsi_disk *sdkp);
@@ -231,11 +230,6 @@ blk_status_t sd_zbc_prepare_zone_append(struct scsi_cmnd *cmd, sector_t *lba,
231230

232231
#else /* CONFIG_BLK_DEV_ZONED */
233232

234-
static inline int sd_zbc_init_disk(struct scsi_disk *sdkp)
235-
{
236-
return 0;
237-
}
238-
239233
static inline void sd_zbc_release_disk(struct scsi_disk *sdkp) {}
240234

241235
static inline int sd_zbc_read_zones(struct scsi_disk *sdkp,
@@ -259,7 +253,7 @@ static inline blk_status_t sd_zbc_setup_zone_mgmt_cmnd(struct scsi_cmnd *cmd,
259253
static inline unsigned int sd_zbc_complete(struct scsi_cmnd *cmd,
260254
unsigned int good_bytes, struct scsi_sense_hdr *sshdr)
261255
{
262-
return 0;
256+
return good_bytes;
263257
}
264258

265259
static inline blk_status_t sd_zbc_prepare_zone_append(struct scsi_cmnd *cmd,

drivers/scsi/sd_zbc.c

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,28 @@ static void sd_zbc_print_zones(struct scsi_disk *sdkp)
651651
sdkp->zone_blocks);
652652
}
653653

654+
static int sd_zbc_init_disk(struct scsi_disk *sdkp)
655+
{
656+
sdkp->zones_wp_offset = NULL;
657+
spin_lock_init(&sdkp->zones_wp_offset_lock);
658+
sdkp->rev_wp_offset = NULL;
659+
mutex_init(&sdkp->rev_mutex);
660+
INIT_WORK(&sdkp->zone_wp_offset_work, sd_zbc_update_wp_offset_workfn);
661+
sdkp->zone_wp_update_buf = kzalloc(SD_BUF_SIZE, GFP_KERNEL);
662+
if (!sdkp->zone_wp_update_buf)
663+
return -ENOMEM;
664+
665+
return 0;
666+
}
667+
668+
void sd_zbc_release_disk(struct scsi_disk *sdkp)
669+
{
670+
kvfree(sdkp->zones_wp_offset);
671+
sdkp->zones_wp_offset = NULL;
672+
kfree(sdkp->zone_wp_update_buf);
673+
sdkp->zone_wp_update_buf = NULL;
674+
}
675+
654676
static void sd_zbc_revalidate_zones_cb(struct gendisk *disk)
655677
{
656678
struct scsi_disk *sdkp = scsi_disk(disk);
@@ -667,7 +689,24 @@ int sd_zbc_revalidate_zones(struct scsi_disk *sdkp)
667689
u32 max_append;
668690
int ret = 0;
669691

670-
if (!sd_is_zoned(sdkp))
692+
/*
693+
* For all zoned disks, initialize zone append emulation data if not
694+
* already done. This is necessary also for host-aware disks used as
695+
* regular disks due to the presence of partitions as these partitions
696+
* may be deleted and the disk zoned model changed back from
697+
* BLK_ZONED_NONE to BLK_ZONED_HA.
698+
*/
699+
if (sd_is_zoned(sdkp) && !sdkp->zone_wp_update_buf) {
700+
ret = sd_zbc_init_disk(sdkp);
701+
if (ret)
702+
return ret;
703+
}
704+
705+
/*
706+
* There is nothing to do for regular disks, including host-aware disks
707+
* that have partitions.
708+
*/
709+
if (!blk_queue_is_zoned(q))
671710
return 0;
672711

673712
/*
@@ -764,28 +803,3 @@ int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buf)
764803

765804
return ret;
766805
}
767-
768-
int sd_zbc_init_disk(struct scsi_disk *sdkp)
769-
{
770-
if (!sd_is_zoned(sdkp))
771-
return 0;
772-
773-
sdkp->zones_wp_offset = NULL;
774-
spin_lock_init(&sdkp->zones_wp_offset_lock);
775-
sdkp->rev_wp_offset = NULL;
776-
mutex_init(&sdkp->rev_mutex);
777-
INIT_WORK(&sdkp->zone_wp_offset_work, sd_zbc_update_wp_offset_workfn);
778-
sdkp->zone_wp_update_buf = kzalloc(SD_BUF_SIZE, GFP_KERNEL);
779-
if (!sdkp->zone_wp_update_buf)
780-
return -ENOMEM;
781-
782-
return 0;
783-
}
784-
785-
void sd_zbc_release_disk(struct scsi_disk *sdkp)
786-
{
787-
kvfree(sdkp->zones_wp_offset);
788-
sdkp->zones_wp_offset = NULL;
789-
kfree(sdkp->zone_wp_update_buf);
790-
sdkp->zone_wp_update_buf = NULL;
791-
}

include/linux/blkdev.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -352,6 +352,8 @@ struct queue_limits {
352352
typedef int (*report_zones_cb)(struct blk_zone *zone, unsigned int idx,
353353
void *data);
354354

355+
void blk_queue_set_zoned(struct gendisk *disk, enum blk_zoned_model model);
356+
355357
#ifdef CONFIG_BLK_DEV_ZONED
356358

357359
#define BLK_ALL_ZONES ((unsigned int)-1)

0 commit comments

Comments
 (0)