diff options
Diffstat (limited to 'drivers/scsi')
152 files changed, 4696 insertions, 5730 deletions
diff --git a/drivers/scsi/3w-xxxx.h b/drivers/scsi/3w-xxxx.h index 49dcf03c631a..29b0b84ed69e 100644 --- a/drivers/scsi/3w-xxxx.h +++ b/drivers/scsi/3w-xxxx.h @@ -392,6 +392,8 @@ typedef struct TAG_TW_Passthru unsigned char padding[12]; } TW_Passthru; +#pragma pack() + typedef struct TAG_TW_Device_Extension { u32 base_addr; unsigned long *alignment_virtual_address[TW_Q_LENGTH]; @@ -430,6 +432,4 @@ typedef struct TAG_TW_Device_Extension { wait_queue_head_t ioctl_wqueue; } TW_Device_Extension; -#pragma pack() - #endif /* _3W_XXXX_H */ diff --git a/drivers/scsi/53c700.c b/drivers/scsi/53c700.c index a3adfb4357f5..fabd4be2c985 100644 --- a/drivers/scsi/53c700.c +++ b/drivers/scsi/53c700.c @@ -1005,7 +1005,7 @@ process_script_interrupt(__u32 dsps, __u32 dsp, struct scsi_cmnd *SCp, DMA_TO_DEVICE); cmnd[0] = REQUEST_SENSE; - cmnd[1] = (SCp->device->lun & 0x7) << 5; + cmnd[1] = (lun & 0x7) << 5; cmnd[2] = 0; cmnd[3] = 0; cmnd[4] = SCSI_SENSE_BUFFERSIZE; @@ -1396,7 +1396,8 @@ NCR_700_start_command(struct scsi_cmnd *SCp) struct NCR_700_Host_Parameters *hostdata = (struct NCR_700_Host_Parameters *)SCp->device->host->hostdata[0]; __u16 count = 1; /* for IDENTIFY message */ - + u8 lun = SCp->device->lun; + if(hostdata->state != NCR_700_HOST_FREE) { /* keep this inside the lock to close the race window where * the running command finishes on another CPU while we don't @@ -1415,7 +1416,7 @@ NCR_700_start_command(struct scsi_cmnd *SCp) hostdata->msgout[0] = NCR_700_identify((SCp->cmnd[0] != REQUEST_SENSE && slot->flags != NCR_700_FLAG_AUTOSENSE), - SCp->device->lun); + lun); /* for INQUIRY or REQUEST_SENSE commands, we cannot be sure * if the negotiated transfer parameters still hold, so * always renegotiate them */ diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index baca5897039f..18a3358eb1d4 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -40,13 +40,6 @@ config SCSI_DMA bool default n -config SCSI_TGT - tristate "SCSI target support" - depends on SCSI - ---help--- - If you want to use SCSI target mode drivers enable this option. - If you choose M, the module will be called scsi_tgt. - config SCSI_NETLINK bool default n @@ -197,20 +190,6 @@ config SCSI_ENCLOSURE it has an enclosure device. Selecting this option will just allow certain enclosure conditions to be reported and is not required. -config SCSI_MULTI_LUN - bool "Probe all LUNs on each SCSI device" - depends on SCSI - help - Some devices support more than one LUN (Logical Unit Number) in order - to allow access to several media, e.g. CD jukebox, USB card reader, - mobile phone in mass storage mode. This option forces the kernel to - probe for all LUNs by default. This setting can be overridden by - max_luns boot/module parameter. Note that this option does not affect - devices conforming to SCSI-3 or higher as they can explicitly report - their number of LUNs. It is safe to say Y here unless you have one of - those rare devices which reacts in an unexpected way when probed for - multiple LUNs. - config SCSI_CONSTANTS bool "Verbose SCSI error reporting (kernel size +=12K)" depends on SCSI @@ -285,13 +264,6 @@ config SCSI_FC_ATTRS each attached FiberChannel device to sysfs, say Y. Otherwise, say N. -config SCSI_FC_TGT_ATTRS - bool "SCSI target support for FiberChannel Transport Attributes" - depends on SCSI_FC_ATTRS - depends on SCSI_TGT = y || SCSI_TGT = SCSI_FC_ATTRS - help - If you want to use SCSI target mode drivers enable this option. - config SCSI_ISCSI_ATTRS tristate "iSCSI Transport Attributes" depends on SCSI && NET @@ -318,13 +290,6 @@ config SCSI_SRP_ATTRS If you wish to export transport-specific information about each attached SRP device to sysfs, say Y. -config SCSI_SRP_TGT_ATTRS - bool "SCSI target support for SRP Transport Attributes" - depends on SCSI_SRP_ATTRS - depends on SCSI_TGT = y || SCSI_TGT = SCSI_SRP_ATTRS - help - If you want to use SCSI target mode drivers enable this option. - endmenu menuconfig SCSI_LOWLEVEL @@ -528,7 +493,7 @@ config SCSI_DPT_I2O config SCSI_ADVANSYS tristate "AdvanSys SCSI support" - depends on SCSI && VIRT_TO_BUS + depends on SCSI && VIRT_TO_BUS && !ARM depends on ISA || EISA || PCI help This is a driver for all SCSI host adapters manufactured by @@ -848,20 +813,6 @@ config SCSI_IBMVSCSI To compile this driver as a module, choose M here: the module will be called ibmvscsi. -config SCSI_IBMVSCSIS - tristate "IBM Virtual SCSI Server support" - depends on PPC_PSERIES && SCSI_SRP && SCSI_SRP_TGT_ATTRS - help - This is the SRP target driver for IBM pSeries virtual environments. - - The userspace component needed to initialize the driver and - documentation can be found: - - http://stgt.berlios.de/ - - To compile this driver as a module, choose M here: the - module will be called ibmvstgt. - config SCSI_IBMVFC tristate "IBM Virtual FC support" depends on PPC_PSERIES && SCSI @@ -1750,16 +1701,6 @@ config SCSI_PM8001 This driver supports PMC-Sierra PCIE SAS/SATA 8x6G SPC 8001 chip based host adapters. -config SCSI_SRP - tristate "SCSI RDMA Protocol helper library" - depends on SCSI && PCI - select SCSI_TGT - help - If you wish to use SRP target drivers, say Y. - - To compile this driver as a module, choose M here: the - module will be called libsrp. - config SCSI_BFA_FC tristate "Brocade BFA Fibre Channel Support" depends on PCI && SCSI diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index e172d4f8e02f..5f0d299b0093 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -20,7 +20,6 @@ CFLAGS_gdth.o = # -DDEBUG_GDTH=2 -D__SERIAL__ -D__COM2__ -DGDTH_STATISTICS obj-$(CONFIG_PCMCIA) += pcmcia/ obj-$(CONFIG_SCSI) += scsi_mod.o -obj-$(CONFIG_SCSI_TGT) += scsi_tgt.o obj-$(CONFIG_RAID_ATTRS) += raid_class.o @@ -127,9 +126,7 @@ obj-$(CONFIG_SCSI_LASI700) += 53c700.o lasi700.o obj-$(CONFIG_SCSI_SNI_53C710) += 53c700.o sni_53c710.o obj-$(CONFIG_SCSI_NSP32) += nsp32.o obj-$(CONFIG_SCSI_IPR) += ipr.o -obj-$(CONFIG_SCSI_SRP) += libsrp.o obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsi/ -obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvscsi/ obj-$(CONFIG_SCSI_IBMVFC) += ibmvscsi/ obj-$(CONFIG_SCSI_HPTIOP) += hptiop.o obj-$(CONFIG_SCSI_STEX) += stex.o @@ -173,8 +170,6 @@ scsi_mod-$(CONFIG_PM) += scsi_pm.o hv_storvsc-y := storvsc_drv.o -scsi_tgt-y += scsi_tgt_lib.o scsi_tgt_if.o - sd_mod-objs := sd.o sd_mod-$(CONFIG_BLK_DEV_INTEGRITY) += sd_dif.o diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index 93d13fc9a293..45da3c823322 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -762,7 +762,7 @@ static int __maybe_unused NCR5380_show_info(struct seq_file *m, static void lprint_Scsi_Cmnd(Scsi_Cmnd * cmd, struct seq_file *m) { - SPRINTF("scsi%d : destination target %d, lun %d\n", cmd->device->host->host_no, cmd->device->id, cmd->device->lun); + SPRINTF("scsi%d : destination target %d, lun %llu\n", cmd->device->host->host_no, cmd->device->id, cmd->device->lun); SPRINTF(" command = "); lprint_command(cmd->cmnd, m); } @@ -1039,9 +1039,10 @@ static void NCR5380_main(struct work_struct *work) for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble) { if (prev != tmp) - dprintk(NDEBUG_LISTS, "MAIN tmp=%p target=%d busy=%d lun=%d\n", tmp, tmp->device->id, hostdata->busy[tmp->device->id], tmp->device->lun); + dprintk(NDEBUG_LISTS, "MAIN tmp=%p target=%d busy=%d lun=%llu\n", tmp, tmp->device->id, hostdata->busy[tmp->device->id], tmp->device->lun); /* When we find one, remove it from the issue queue. */ - if (!(hostdata->busy[tmp->device->id] & (1 << tmp->device->lun))) { + if (!(hostdata->busy[tmp->device->id] & + (1 << (u8)(tmp->device->lun & 0xff)))) { if (prev) { REMOVE(prev, prev->host_scribble, tmp, tmp->host_scribble); prev->host_scribble = tmp->host_scribble; @@ -1057,7 +1058,7 @@ static void NCR5380_main(struct work_struct *work) * On failure, we must add the command back to the * issue queue so we can keep trying. */ - dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, "scsi%d : main() : command for target %d lun %d removed from issue_queue\n", instance->host_no, tmp->device->id, tmp->device->lun); + dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, "scsi%d : main() : command for target %d lun %llu removed from issue_queue\n", instance->host_no, tmp->device->id, tmp->device->lun); /* * A successful selection is defined as one that @@ -1524,7 +1525,7 @@ part2: dprintk(NDEBUG_SELECTION, "scsi%d : nexus established.\n", instance->host_no); /* XXX need to handle errors here */ hostdata->connected = cmd; - hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); + hostdata->busy[cmd->device->id] |= (1 << (cmd->device->lun & 0xFF)); initialize_SCp(cmd); @@ -2210,14 +2211,14 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { case LINKED_FLG_CMD_COMPLETE: /* Accept message by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - dprintk(NDEBUG_LINKED, "scsi%d : target %d lun %d linked command complete.\n", instance->host_no, cmd->device->id, cmd->device->lun); + dprintk(NDEBUG_LINKED, "scsi%d : target %d lun %llu linked command complete.\n", instance->host_no, cmd->device->id, cmd->device->lun); /* * Sanity check : A linked command should only terminate with * one of these messages if there are more linked commands * available. */ if (!cmd->next_link) { - printk("scsi%d : target %d lun %d linked command complete, no next_link\n" instance->host_no, cmd->device->id, cmd->device->lun); + printk("scsi%d : target %d lun %llu linked command complete, no next_link\n" instance->host_no, cmd->device->id, cmd->device->lun); sink = 1; do_abort(instance); return; @@ -2226,7 +2227,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { /* The next command is still part of this process */ cmd->next_link->tag = cmd->tag; cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); - dprintk(NDEBUG_LINKED, "scsi%d : target %d lun %d linked request done, calling scsi_done().\n", instance->host_no, cmd->device->id, cmd->device->lun); + dprintk(NDEBUG_LINKED, "scsi%d : target %d lun %llu linked request done, calling scsi_done().\n", instance->host_no, cmd->device->id, cmd->device->lun); collect_stats(hostdata, cmd); cmd->scsi_done(cmd); cmd = hostdata->connected; @@ -2238,8 +2239,8 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { sink = 1; NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); hostdata->connected = NULL; - dprintk(NDEBUG_QUEUES, "scsi%d : command for target %d, lun %d completed\n", instance->host_no, cmd->device->id, cmd->device->lun); - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); + dprintk(NDEBUG_QUEUES, "scsi%d : command for target %d, lun %llu completed\n", instance->host_no, cmd->device->id, cmd->device->lun); + hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xFF)); /* * I'm not sure what the correct thing to do here is : @@ -2304,7 +2305,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { case ORDERED_QUEUE_TAG: case SIMPLE_QUEUE_TAG: cmd->device->simple_tags = 0; - hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); + hostdata->busy[cmd->device->id] |= (1 << (cmd->device->lun & 0xFF)); break; default: break; @@ -2318,7 +2319,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { hostdata->disconnected_queue; hostdata->connected = NULL; hostdata->disconnected_queue = cmd; - dprintk(NDEBUG_QUEUES, "scsi%d : command for target %d lun %d was moved from connected to" " the disconnected_queue\n", instance->host_no, cmd->device->id, cmd->device->lun); + dprintk(NDEBUG_QUEUES, "scsi%d : command for target %d lun %llu was moved from connected to" " the disconnected_queue\n", instance->host_no, cmd->device->id, cmd->device->lun); /* * Restore phase bits to 0 so an interrupted selection, * arbitration can resume. @@ -2426,7 +2427,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { hostdata->last_message = msgout; NCR5380_transfer_pio(instance, &phase, &len, &data); if (msgout == ABORT) { - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); + hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xFF)); hostdata->connected = NULL; cmd->result = DID_ERROR << 16; collect_stats(hostdata, cmd); @@ -2562,7 +2563,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { for (tmp = (Scsi_Cmnd *) hostdata->disconnected_queue, prev = NULL; tmp; prev = tmp, tmp = (Scsi_Cmnd *) tmp->host_scribble) - if ((target_mask == (1 << tmp->device->id)) && (lun == tmp->device->lun) + if ((target_mask == (1 << tmp->device->id)) && (lun == (u8)tmp->device->lun) ) { if (prev) { REMOVE(prev, prev->host_scribble, tmp, tmp->host_scribble); @@ -2588,7 +2589,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) { do_abort(instance); } else { hostdata->connected = tmp; - dprintk(NDEBUG_RESELECTION, "scsi%d : nexus established, target = %d, lun = %d, tag = %d\n", instance->host_no, tmp->device->id, tmp->device->lun, tmp->tag); + dprintk(NDEBUG_RESELECTION, "scsi%d : nexus established, target = %d, lun = %llu, tag = %d\n", instance->host_no, tmp->device->id, tmp->device->lun, tmp->tag); } } diff --git a/drivers/scsi/NCR53c406a.c b/drivers/scsi/NCR53c406a.c index c91888a0a23c..42c7161474f7 100644 --- a/drivers/scsi/NCR53c406a.c +++ b/drivers/scsi/NCR53c406a.c @@ -595,7 +595,7 @@ static int NCR53c406a_release(struct Scsi_Host *shost) { if (shost->irq) free_irq(shost->irq, NULL); -#ifdef USE_DMA +#if USE_DMA if (shost->dma_channel != 0xff) free_dma(shost->dma_channel); #endif @@ -698,7 +698,7 @@ static int NCR53c406a_queue_lck(Scsi_Cmnd * SCpnt, void (*done) (Scsi_Cmnd *)) int i; VDEB(printk("NCR53c406a_queue called\n")); - DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->target, SCpnt->lun, scsi_bufflen(SCpnt))); + DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->device->target, (u8)SCpnt->device->lun, scsi_bufflen(SCpnt))); #if 0 VDEB(for (i = 0; i < SCpnt->cmd_len; i++) diff --git a/drivers/scsi/a100u2w.c b/drivers/scsi/a100u2w.c index 0163457c12bb..522570d297ca 100644 --- a/drivers/scsi/a100u2w.c +++ b/drivers/scsi/a100u2w.c @@ -891,7 +891,7 @@ static int inia100_build_scb(struct orc_host * host, struct orc_scb * scb, struc printk("max cdb length= %x\b", cmd->cmd_len); scb->cdb_len = IMAX_CDB; } - scb->ident = cmd->device->lun | DISC_ALLOW; + scb->ident = (u8)(cmd->device->lun & 0xff) | DISC_ALLOW; if (cmd->device->tagged_supported) { /* Tag Support */ scb->tag_msg = SIMPLE_QUEUE_TAG; /* Do simple tag only */ } else { diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c index 4921ed19a027..63f576c9300a 100644 --- a/drivers/scsi/aacraid/linit.c +++ b/drivers/scsi/aacraid/linit.c @@ -551,7 +551,7 @@ static int aac_eh_abort(struct scsi_cmnd* cmd) int count; int ret = FAILED; - printk(KERN_ERR "%s: Host adapter abort request (%d,%d,%d,%d)\n", + printk(KERN_ERR "%s: Host adapter abort request (%d,%d,%d,%llu)\n", AAC_DRIVERNAME, host->host_no, sdev_channel(dev), sdev_id(dev), dev->lun); switch (cmd->cmnd[0]) { diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index d8145888e66a..43761c1c46f0 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -2512,7 +2512,7 @@ static void asc_prt_scsi_host(struct Scsi_Host *s) printk("Scsi_Host at addr 0x%p, device %s\n", s, dev_name(boardp->dev)); printk(" host_busy %u, host_no %d,\n", - s->host_busy, s->host_no); + atomic_read(&s->host_busy), s->host_no); printk(" base 0x%lx, io_port 0x%lx, irq %d,\n", (ulong)s->base, (ulong)s->io_port, boardp->irq); @@ -3345,8 +3345,8 @@ static void asc_prt_driver_conf(struct seq_file *m, struct Scsi_Host *shost) shost->host_no); seq_printf(m, - " host_busy %u, max_id %u, max_lun %u, max_channel %u\n", - shost->host_busy, shost->max_id, + " host_busy %u, max_id %u, max_lun %llu, max_channel %u\n", + atomic_read(&shost->host_busy), shost->max_id, shost->max_lun, shost->max_channel); seq_printf(m, diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index e86eb6a921fc..e77b72f78006 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -321,7 +321,7 @@ static LIST_HEAD(aha152x_host_list); #define CMDINFO(cmd) \ (cmd) ? ((cmd)->device->host->host_no) : -1, \ (cmd) ? ((cmd)->device->id & 0x0f) : -1, \ - (cmd) ? ((cmd)->device->lun & 0x07) : -1 + (cmd) ? ((u8)(cmd)->device->lun & 0x07) : -1 static inline void CMD_INC_RESID(struct scsi_cmnd *cmd, int inc) @@ -1602,7 +1602,7 @@ static void busfree_run(struct Scsi_Host *shpnt) #if defined(AHA152X_DEBUG) int hostno=DONE_SC->device->host->host_no; int id=DONE_SC->device->id & 0xf; - int lun=DONE_SC->device->lun & 0x7; + int lun=((u8)DONE_SC->device->lun) & 0x7; #endif Scsi_Cmnd *ptr = DONE_SC; DONE_SC=NULL; @@ -2984,7 +2984,7 @@ static void get_command(struct seq_file *m, Scsi_Cmnd * ptr) int i; SPRINTF("%p: target=%d; lun=%d; cmnd=( ", - ptr, ptr->device->id, ptr->device->lun); + ptr, ptr->device->id, (u8)ptr->device->lun); for (i = 0; i < COMMAND_SIZE(ptr->cmnd[0]); i++) SPRINTF("0x%02x ", ptr->cmnd[i]); diff --git a/drivers/scsi/aic7xxx/aic7770_osm.c b/drivers/scsi/aic7xxx/aic7770_osm.c index 0cb8ef64b5ce..3d401d02c019 100644 --- a/drivers/scsi/aic7xxx/aic7770_osm.c +++ b/drivers/scsi/aic7xxx/aic7770_osm.c @@ -85,10 +85,9 @@ aic7770_probe(struct device *dev) int error; sprintf(buf, "ahc_eisa:%d", eisaBase >> 12); - name = kmalloc(strlen(buf) + 1, GFP_ATOMIC); + name = kstrdup(buf, GFP_ATOMIC); if (name == NULL) return (ENOMEM); - strcpy(name, buf); ahc = ahc_alloc(&aic7xxx_driver_template, name); if (ahc == NULL) return (ENOMEM); diff --git a/drivers/scsi/aic7xxx/aic79xx.h b/drivers/scsi/aic7xxx/aic79xx.h index 113874c1284b..df2e0e5367d2 100644 --- a/drivers/scsi/aic7xxx/aic79xx.h +++ b/drivers/scsi/aic7xxx/aic79xx.h @@ -115,7 +115,7 @@ struct scb_platform_data; #endif #define AHD_BUILD_COL_IDX(target, lun) \ - (((lun) << 4) | target) + ((((u8)lun) << 4) | target) #define AHD_GET_SCB_COL_IDX(ahd, scb) \ ((SCB_GET_LUN(scb) << 4) | SCB_GET_TARGET(ahd, scb)) diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.c b/drivers/scsi/aic7xxx/aic79xx_osm.c index 69d5c43a65e5..ed333669a7dc 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm.c @@ -2137,7 +2137,7 @@ ahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd) if (do_fallback) { printk("%s: device overrun (status %x) on %d:%d:%d\n", ahd_name(ahd), status, cmd->device->channel, - cmd->device->id, cmd->device->lun); + cmd->device->id, (u8)cmd->device->lun); } ahd_cmd_set_transaction_status(cmd, new_status); @@ -2253,13 +2253,13 @@ ahd_linux_queue_abort_cmd(struct scsi_cmnd *cmd) disconnected = TRUE; if (ahd_search_qinfifo(ahd, cmd->device->id, cmd->device->channel + 'A', - cmd->device->lun, + cmd->device->lun, pending_scb->hscb->tag, ROLE_INITIATOR, CAM_REQ_ABORTED, SEARCH_COMPLETE) > 0) { printk("%s:%d:%d:%d: Cmd aborted from QINFIFO\n", ahd_name(ahd), cmd->device->channel, - cmd->device->id, cmd->device->lun); + cmd->device->id, (u8)cmd->device->lun); retval = SUCCESS; goto done; } diff --git a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c index 3c85873b14b9..8466aa784ec1 100644 --- a/drivers/scsi/aic7xxx/aic79xx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic79xx_osm_pci.c @@ -178,10 +178,9 @@ ahd_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ahd_get_pci_bus(pci), ahd_get_pci_slot(pci), ahd_get_pci_function(pci)); - name = kmalloc(strlen(buf) + 1, GFP_ATOMIC); + name = kstrdup(buf, GFP_ATOMIC); if (name == NULL) return (-ENOMEM); - strcpy(name, buf); ahd = ahd_alloc(NULL, name); if (ahd == NULL) return (-ENOMEM); diff --git a/drivers/scsi/aic7xxx/aic79xx_proc.c b/drivers/scsi/aic7xxx/aic79xx_proc.c index e9778b4f7e32..27dbfccea774 100644 --- a/drivers/scsi/aic7xxx/aic79xx_proc.c +++ b/drivers/scsi/aic7xxx/aic79xx_proc.c @@ -197,7 +197,7 @@ ahd_dump_device_state(struct seq_file *m, struct scsi_device *sdev) seq_printf(m, "\tChannel %c Target %d Lun %d Settings\n", sdev->sdev_target->channel + 'A', - sdev->sdev_target->id, sdev->lun); + sdev->sdev_target->id, (u8)sdev->lun); seq_printf(m, "\t\tCommands Queued %ld\n", dev->commands_issued); seq_printf(m, "\t\tCommands Active %d\n", dev->active); diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.c b/drivers/scsi/aic7xxx/aic7xxx_osm.c index 114ff0c6e311..d2c9bf39033d 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm.c @@ -2110,7 +2110,7 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) */ printk("%s:%d:%d:%d: Is not an active device\n", ahc_name(ahc), cmd->device->channel, cmd->device->id, - cmd->device->lun); + (u8)cmd->device->lun); retval = SUCCESS; goto no_cmd; } @@ -2118,11 +2118,11 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) if ((dev->flags & (AHC_DEV_Q_BASIC|AHC_DEV_Q_TAGGED)) == 0 && ahc_search_untagged_queues(ahc, cmd, cmd->device->id, cmd->device->channel + 'A', - cmd->device->lun, + (u8)cmd->device->lun, CAM_REQ_ABORTED, SEARCH_COMPLETE) != 0) { printk("%s:%d:%d:%d: Command found on untagged queue\n", ahc_name(ahc), cmd->device->channel, cmd->device->id, - cmd->device->lun); + (u8)cmd->device->lun); retval = SUCCESS; goto done; } @@ -2188,13 +2188,14 @@ ahc_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag) SEARCH_COMPLETE) > 0) { printk("%s:%d:%d:%d: Cmd aborted from QINFIFO\n", ahc_name(ahc), cmd->device->channel, - cmd->device->id, cmd->device->lun); + cmd->device->id, (u8)cmd->device->lun); retval = SUCCESS; goto done; } } else if (ahc_search_qinfifo(ahc, cmd->device->id, cmd->device->channel + 'A', - cmd->device->lun, pending_scb->hscb->tag, + cmd->device->lun, + pending_scb->hscb->tag, ROLE_INITIATOR, /*status*/0, SEARCH_COUNT) > 0) { disconnected = FALSE; diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c index ee05e8410754..0fc14dac7070 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c +++ b/drivers/scsi/aic7xxx/aic7xxx_osm_pci.c @@ -225,10 +225,9 @@ ahc_linux_pci_dev_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ahc_get_pci_bus(pci), ahc_get_pci_slot(pci), ahc_get_pci_function(pci)); - name = kmalloc(strlen(buf) + 1, GFP_ATOMIC); + name = kstrdup(buf, GFP_ATOMIC); if (name == NULL) return (-ENOMEM); - strcpy(name, buf); ahc = ahc_alloc(NULL, name); if (ahc == NULL) return (-ENOMEM); diff --git a/drivers/scsi/aic7xxx/aic7xxx_proc.c b/drivers/scsi/aic7xxx/aic7xxx_proc.c index 383a3d11652d..64eec6c07a83 100644 --- a/drivers/scsi/aic7xxx/aic7xxx_proc.c +++ b/drivers/scsi/aic7xxx/aic7xxx_proc.c @@ -175,7 +175,7 @@ ahc_dump_device_state(struct seq_file *m, struct scsi_device *sdev) seq_printf(m, "\tChannel %c Target %d Lun %d Settings\n", sdev->sdev_target->channel + 'A', - sdev->sdev_target->id, sdev->lun); + sdev->sdev_target->id, (u8)sdev->lun); seq_printf(m, "\t\tCommands Queued %ld\n", dev->commands_issued); seq_printf(m, "\t\tCommands Active %d\n", dev->active); diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 652b41b4ddbd..b13764ca23fd 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -2335,7 +2335,7 @@ static int arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, " poll command abort successfully \n" , acb->host->host_no , ccb->pcmd->device->id - , ccb->pcmd->device->lun + , (u32)ccb->pcmd->device->lun , ccb); ccb->pcmd->result = DID_ABORT << 16; arcmsr_ccb_complete(ccb); @@ -2399,7 +2399,7 @@ static int arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, " poll command abort successfully \n" ,acb->host->host_no ,ccb->pcmd->device->id - ,ccb->pcmd->device->lun + ,(u32)ccb->pcmd->device->lun ,ccb); ccb->pcmd->result = DID_ABORT << 16; arcmsr_ccb_complete(ccb); @@ -2456,7 +2456,7 @@ polling_hbc_ccb_retry: " poll command abort successfully \n" , acb->host->host_no , pCCB->pcmd->device->id - , pCCB->pcmd->device->lun + , (u32)pCCB->pcmd->device->lun , pCCB); pCCB->pcmd->result = DID_ABORT << 16; arcmsr_ccb_complete(pCCB); @@ -3058,7 +3058,7 @@ static int arcmsr_abort(struct scsi_cmnd *cmd) int rtn = FAILED; printk(KERN_NOTICE "arcmsr%d: abort device command of scsi id = %d lun = %d \n", - acb->host->host_no, cmd->device->id, cmd->device->lun); + acb->host->host_no, cmd->device->id, (u32)cmd->device->lun); acb->acb_flags |= ACB_F_ABORT; acb->num_aborts++; /* diff --git a/drivers/scsi/arm/acornscsi.c b/drivers/scsi/arm/acornscsi.c index 2e797a367608..d89b9b4deb3c 100644 --- a/drivers/scsi/arm/acornscsi.c +++ b/drivers/scsi/arm/acornscsi.c @@ -760,7 +760,8 @@ intr_ret_t acornscsi_kick(AS_Host *host) SCpnt->tag = SCpnt->device->current_tag; } else #endif - set_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns); + set_bit(SCpnt->device->id * 8 + + (u8)(SCpnt->device->lun & 0x07), host->busyluns); host->stats.removes += 1; @@ -863,7 +864,8 @@ static void acornscsi_done(AS_Host *host, struct scsi_cmnd **SCpntp, if (!SCpnt->scsi_done) panic("scsi%d.H: null scsi_done function in acornscsi_done", host->host->host_no); - clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns); + clear_bit(SCpnt->device->id * 8 + + (u8)(SCpnt->device->lun & 0x7), host->busyluns); SCpnt->scsi_done(SCpnt); } else @@ -1576,7 +1578,8 @@ void acornscsi_message(AS_Host *host) printk(KERN_NOTICE "scsi%d.%c: disabling tagged queueing\n", host->host->host_no, acornscsi_target(host)); host->SCpnt->device->simple_tags = 0; - set_bit(host->SCpnt->device->id * 8 + host->SCpnt->device->lun, host->busyluns); + set_bit(host->SCpnt->device->id * 8 + + (u8)(host->SCpnt->device->lun & 0x7), host->busyluns); break; #endif case EXTENDED_MESSAGE | (EXTENDED_SDTR << 8): @@ -2671,7 +2674,8 @@ int acornscsi_abort(struct scsi_cmnd *SCpnt) //#if (DEBUG & DEBUG_ABORT) printk("clear "); //#endif - clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, host->busyluns); + clear_bit(SCpnt->device->id * 8 + + (u8)(SCpnt->device->lun & 0x7), host->busyluns); /* * We found the command, and cleared it out. Either @@ -2853,7 +2857,7 @@ static int acornscsi_show_info(struct seq_file *m, struct Scsi_Host *instance) shost_for_each_device(scd, instance) { seq_printf(m, "Device/Lun TaggedQ Sync\n"); - seq_printf(m, " %d/%d ", scd->id, scd->lun); + seq_printf(m, " %d/%llu ", scd->id, scd->lun); if (scd->tagged_supported) seq_printf(m, "%3sabled(%3d) ", scd->simple_tags ? "en" : "dis", diff --git a/drivers/scsi/arm/fas216.c b/drivers/scsi/arm/fas216.c index b46a6f6c0eb3..71cfb1e504c4 100644 --- a/drivers/scsi/arm/fas216.c +++ b/drivers/scsi/arm/fas216.c @@ -1821,7 +1821,8 @@ static void fas216_allocate_tag(FAS216_Info *info, struct scsi_cmnd *SCpnt) SCpnt->tag = SCpnt->device->current_tag; } else #endif - set_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns); + set_bit(SCpnt->device->id * 8 + + (u8)(SCpnt->device->lun & 0x7), info->busyluns); info->stats.removes += 1; switch (SCpnt->cmnd[0]) { @@ -2171,7 +2172,8 @@ static void fas216_done(FAS216_Info *info, unsigned int result) * status. */ info->device[SCpnt->device->id].parity_check = 0; - clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns); + clear_bit(SCpnt->device->id * 8 + + (u8)(SCpnt->device->lun & 0x7), info->busyluns); fn = (void (*)(FAS216_Info *, struct scsi_cmnd *, unsigned int))SCpnt->host_scribble; fn(info, SCpnt, result); @@ -2398,7 +2400,8 @@ static enum res_find fas216_find_command(FAS216_Info *info, * been set. */ info->origSCpnt = NULL; - clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns); + clear_bit(SCpnt->device->id * 8 + + (u8)(SCpnt->device->lun & 0x7), info->busyluns); printk("waiting for execution "); res = res_success; } else @@ -3000,7 +3003,7 @@ void fas216_print_devices(FAS216_Info *info, struct seq_file *m) shost_for_each_device(scd, info->host) { dev = &info->device[scd->id]; - seq_printf(m, " %d/%d ", scd->id, scd->lun); + seq_printf(m, " %d/%llu ", scd->id, scd->lun); if (scd->tagged_supported) seq_printf(m, "%3sabled(%3d) ", scd->simple_tags ? "en" : "dis", diff --git a/drivers/scsi/arm/queue.c b/drivers/scsi/arm/queue.c index cb11ccef54e5..3441ce3ebabf 100644 --- a/drivers/scsi/arm/queue.c +++ b/drivers/scsi/arm/queue.c @@ -167,7 +167,8 @@ struct scsi_cmnd *queue_remove_exclude(Queue_t *queue, unsigned long *exclude) spin_lock_irqsave(&queue->queue_lock, flags); list_for_each(l, &queue->head) { QE_t *q = list_entry(l, QE_t, list); - if (!test_bit(q->SCpnt->device->id * 8 + q->SCpnt->device->lun, exclude)) { + if (!test_bit(q->SCpnt->device->id * 8 + + (u8)(q->SCpnt->device->lun & 0x7), exclude)) { SCpnt = __queue_remove(queue, l); break; } diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 1814aa20b724..79e6f045c2a9 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -361,17 +361,18 @@ static void __init init_tags(void) static int is_lun_busy(Scsi_Cmnd *cmd, int should_be_tagged) { + u8 lun = cmd->device->lun; SETUP_HOSTDATA(cmd->device->host); - if (hostdata->busy[cmd->device->id] & (1 << cmd->device->lun)) + if (hostdata->busy[cmd->device->id] & (1 << lun)) return 1; if (!should_be_tagged || !setup_use_tagged_queuing || !cmd->device->tagged_supported) return 0; - if (TagAlloc[cmd->device->id][cmd->device->lun].nr_allocated >= - TagAlloc[cmd->device->id][cmd->device->lun].queue_size) { + if (TagAlloc[cmd->device->id][lun].nr_allocated >= + TagAlloc[cmd->device->id][lun].queue_size) { dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d: no free tags\n", - H_NO(cmd), cmd->device->id, cmd->device->lun); + H_NO(cmd), cmd->device->id, lun); return 1; } return 0; @@ -385,6 +386,7 @@ static int is_lun_busy(Scsi_Cmnd *cmd, int should_be_tagged) static void cmd_get_tag(Scsi_Cmnd *cmd, int should_be_tagged) { + u8 lun = cmd->device->lun; SETUP_HOSTDATA(cmd->device->host); /* If we or the target don't support tagged queuing, allocate the LUN for @@ -393,11 +395,11 @@ static void cmd_get_tag(Scsi_Cmnd *cmd, int should_be_tagged) if (!should_be_tagged || !setup_use_tagged_queuing || !cmd->device->tagged_supported) { cmd->tag = TAG_NONE; - hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); + hostdata->busy[cmd->device->id] |= (1 << lun); dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d now allocated by untagged " - "command\n", H_NO(cmd), cmd->device->id, cmd->device->lun); + "command\n", H_NO(cmd), cmd->device->id, lun); } else { - TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun]; + TAG_ALLOC *ta = &TagAlloc[cmd->device->id][lun]; cmd->tag = find_first_zero_bit(ta->allocated, MAX_TAGS); set_bit(cmd->tag, ta->allocated); @@ -405,7 +407,7 @@ static void cmd_get_tag(Scsi_Cmnd *cmd, int should_be_tagged) dprintk(NDEBUG_TAGS, "scsi%d: using tag %d for target %d lun %d " "(now %d tags in use)\n", H_NO(cmd), cmd->tag, cmd->device->id, - cmd->device->lun, ta->nr_allocated); + lun, ta->nr_allocated); } } @@ -416,21 +418,22 @@ static void cmd_get_tag(Scsi_Cmnd *cmd, int should_be_tagged) static void cmd_free_tag(Scsi_Cmnd *cmd) { + u8 lun = cmd->device->lun; SETUP_HOSTDATA(cmd->device->host); if (cmd->tag == TAG_NONE) { - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); + hostdata->busy[cmd->device->id] &= ~(1 << lun); dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d untagged cmd finished\n", - H_NO(cmd), cmd->device->id, cmd->device->lun); + H_NO(cmd), cmd->device->id, lun); } else if (cmd->tag >= MAX_TAGS) { printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n", H_NO(cmd), cmd->tag); } else { - TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun]; + TAG_ALLOC *ta = &TagAlloc[cmd->device->id][lun]; clear_bit(cmd->tag, ta->allocated); ta->nr_allocated--; dprintk(NDEBUG_TAGS, "scsi%d: freed tag %d for target %d lun %d\n", - H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun); + H_NO(cmd), cmd->tag, cmd->device->id, lun); } } @@ -713,7 +716,7 @@ static void lprint_Scsi_Cmnd(Scsi_Cmnd *cmd) { int i, s; unsigned char *command; - printk("scsi%d: destination target %d, lun %d\n", + printk("scsi%d: destination target %d, lun %llu\n", H_NO(cmd), cmd->device->id, cmd->device->lun); printk(KERN_CONT " command = "); command = cmd->cmnd; @@ -759,7 +762,7 @@ static void show_Scsi_Cmnd(Scsi_Cmnd *cmd, struct seq_file *m) { int i, s; unsigned char *command; - seq_printf(m, "scsi%d: destination target %d, lun %d\n", + seq_printf(m, "scsi%d: destination target %d, lun %llu\n", H_NO(cmd), cmd->device->id, cmd->device->lun); seq_printf(m, " command = "); command = cmd->cmnd; @@ -1060,12 +1063,13 @@ static void NCR5380_main(struct work_struct *work) #endif for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp)) { + u8 lun = tmp->device->lun; #if (NDEBUG & NDEBUG_LISTS) if (prev != tmp) - printk("MAIN tmp=%p target=%d busy=%d lun=%d\n", + printk("MAIN tmp=%p target=%d busy=%d lun=%llu\n", tmp, tmp->device->id, hostdata->busy[tmp->device->id], - tmp->device->lun); + lun); #endif /* When we find one, remove it from the issue queue. */ /* ++guenther: possible race with Falcon locking */ @@ -1073,7 +1077,7 @@ static void NCR5380_main(struct work_struct *work) #ifdef SUPPORT_TAGS !is_lun_busy( tmp, tmp->cmnd[0] != REQUEST_SENSE) #else - !(hostdata->busy[tmp->device->id] & (1 << tmp->device->lun)) + !(hostdata->busy[tmp->device->id] & (1 << lun)) #endif ) { /* ++guenther: just to be sure, this must be atomic */ @@ -1099,7 +1103,7 @@ static void NCR5380_main(struct work_struct *work) */ dprintk(NDEBUG_MAIN, "scsi%d: main(): command for target %d " "lun %d removed from issue_queue\n", - HOSTNO, tmp->device->id, tmp->device->lun); + HOSTNO, tmp->device->id, lun); /* * REQUEST SENSE commands are issued without tagged * queueing, even on SCSI-II devices because the @@ -2061,7 +2065,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) * accesses to this device will use the * polled-IO. */ printk(KERN_NOTICE "scsi%d: switching target %d " - "lun %d to slow handshake\n", HOSTNO, + "lun %llu to slow handshake\n", HOSTNO, cmd->device->id, cmd->device->lun); cmd->device->borken = 1; NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | @@ -2113,7 +2117,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) /* Accept message by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %d linked command " + dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %llu linked command " "complete.\n", HOSTNO, cmd->device->id, cmd->device->lun); /* Enable reselect interrupts */ @@ -2125,7 +2129,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) */ if (!cmd->next_link) { - printk(KERN_NOTICE "scsi%d: target %d lun %d " + printk(KERN_NOTICE "scsi%d: target %d lun %llu " "linked command complete, no next_link\n", HOSTNO, cmd->device->id, cmd->device->lun); sink = 1; @@ -2138,7 +2142,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) * and don't free it! */ cmd->next_link->tag = cmd->tag; cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); - dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %d linked request " + dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %llu linked request " "done, calling scsi_done().\n", HOSTNO, cmd->device->id, cmd->device->lun); #ifdef NCR5380_STATS @@ -2155,7 +2159,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) /* ++guenther: possible race with Falcon locking */ falcon_dont_release++; hostdata->connected = NULL; - dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d, lun %d " + dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d, lun %llu " "completed\n", HOSTNO, cmd->device->id, cmd->device->lun); #ifdef SUPPORT_TAGS cmd_free_tag(cmd); @@ -2169,7 +2173,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) /* ++Andreas: the mid level code knows about QUEUE_FULL now. */ TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun]; - dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d returned " + dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %llu returned " "QUEUE_FULL after %d commands\n", HOSTNO, cmd->device->id, cmd->device->lun, ta->nr_allocated); @@ -2267,7 +2271,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) cmd->device->tagged_supported = 0; hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); cmd->tag = TAG_NONE; - dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d rejected " + dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %llu rejected " "QUEUE_TAG message; tagged queuing " "disabled\n", HOSTNO, cmd->device->id, cmd->device->lun); @@ -2284,7 +2288,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) hostdata->connected = NULL; hostdata->disconnected_queue = cmd; local_irq_restore(flags); - dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d lun %d was " + dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d lun %llu was " "moved from connected to the " "disconnected_queue\n", HOSTNO, cmd->device->id, cmd->device->lun); @@ -2385,12 +2389,12 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) printk("\n"); } else if (tmp != EXTENDED_MESSAGE) printk(KERN_DEBUG "scsi%d: rejecting unknown " - "message %02x from target %d, lun %d\n", + "message %02x from target %d, lun %llu\n", HOSTNO, tmp, cmd->device->id, cmd->device->lun); else printk(KERN_DEBUG "scsi%d: rejecting unknown " "extended message " - "code %02x, length %d from target %d, lun %d\n", + "code %02x, length %d from target %d, lun %llu\n", HOSTNO, extended_msg[1], extended_msg[0], cmd->device->id, cmd->device->lun); @@ -2588,7 +2592,7 @@ static void NCR5380_reselect(struct Scsi_Host *instance) NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); hostdata->connected = tmp; - dprintk(NDEBUG_RESELECTION, "scsi%d: nexus established, target = %d, lun = %d, tag = %d\n", + dprintk(NDEBUG_RESELECTION, "scsi%d: nexus established, target = %d, lun = %llu, tag = %d\n", HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag); falcon_dont_release--; } diff --git a/drivers/scsi/be2iscsi/be_iscsi.c b/drivers/scsi/be2iscsi/be_iscsi.c index fd284ff36ecf..86162811812d 100644 --- a/drivers/scsi/be2iscsi/be_iscsi.c +++ b/drivers/scsi/be2iscsi/be_iscsi.c @@ -914,7 +914,7 @@ void beiscsi_conn_get_stats(struct iscsi_cls_conn *cls_conn, stats->r2t_pdus = conn->r2t_pdus_cnt; stats->digest_err = 0; stats->timeout_err = 0; - stats->custom_length = 0; + stats->custom_length = 1; strcpy(stats->custom[0].desc, "eh_abort_cnt"); stats->custom[0].value = conn->eh_abort_cnt; } diff --git a/drivers/scsi/be2iscsi/be_mgmt.c b/drivers/scsi/be2iscsi/be_mgmt.c index 07934b0b9ee1..a3e56487616c 100644 --- a/drivers/scsi/be2iscsi/be_mgmt.c +++ b/drivers/scsi/be2iscsi/be_mgmt.c @@ -1015,7 +1015,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba, if (if_info->dhcp_state) { beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, "BG_%d : DHCP Already Enabled\n"); - return 0; + goto exit; } /* The ip_param->len is 1 in DHCP case. Setting proper IP len as this it is used while @@ -1033,7 +1033,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba, sizeof(*reldhcp)); if (rc) - return rc; + goto exit; reldhcp = nonemb_cmd.va; reldhcp->interface_hndl = phba->interface_handle; @@ -1044,7 +1044,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba, beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, "BG_%d : Failed to Delete existing dhcp\n"); - return rc; + goto exit; } } } @@ -1054,7 +1054,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba, rc = mgmt_static_ip_modify(phba, if_info, ip_param, NULL, IP_ACTION_DEL); if (rc) - return rc; + goto exit; } /* Delete the Gateway settings if mode change is to DHCP */ @@ -1064,7 +1064,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba, if (rc) { beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, "BG_%d : Failed to Get Gateway Addr\n"); - return rc; + goto exit; } if (gtway_addr_set.ip_addr.addr[0]) { @@ -1076,7 +1076,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba, beiscsi_log(phba, KERN_WARNING, BEISCSI_LOG_CONFIG, "BG_%d : Failed to clear Gateway Addr Set\n"); - return rc; + goto exit; } } } @@ -1087,7 +1087,7 @@ int mgmt_set_ip(struct beiscsi_hba *phba, OPCODE_COMMON_ISCSI_NTWK_CONFIG_STATELESS_IP_ADDR, sizeof(*dhcpreq)); if (rc) - return rc; + goto exit; dhcpreq = nonemb_cmd.va; dhcpreq->flags = BLOCKING; @@ -1095,12 +1095,14 @@ int mgmt_set_ip(struct beiscsi_hba *phba, dhcpreq->interface_hndl = phba->interface_handle; dhcpreq->ip_type = BE2_DHCP_V4; - return mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); + rc = mgmt_exec_nonemb_cmd(phba, &nonemb_cmd, NULL, 0); } else { - return mgmt_static_ip_modify(phba, if_info, ip_param, + rc = mgmt_static_ip_modify(phba, if_info, ip_param, subnet_param, IP_ACTION_ADD); } +exit: + kfree(if_info); return rc; } diff --git a/drivers/scsi/bfa/bfa_fcs.c b/drivers/scsi/bfa/bfa_fcs.c index a3ab5cce4208..0f19455951ec 100644 --- a/drivers/scsi/bfa/bfa_fcs.c +++ b/drivers/scsi/bfa/bfa_fcs.c @@ -81,7 +81,7 @@ bfa_fcs_attach(struct bfa_fcs_s *fcs, struct bfa_s *bfa, struct bfad_s *bfad, bfa->fcs = BFA_TRUE; fcbuild_init(); - for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) { + for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) { mod = &fcs_modules[i]; if (mod->attach) mod->attach(fcs); @@ -97,7 +97,7 @@ bfa_fcs_init(struct bfa_fcs_s *fcs) int i; struct bfa_fcs_mod_s *mod; - for (i = 0; i < sizeof(fcs_modules) / sizeof(fcs_modules[0]); i++) { + for (i = 0; i < ARRAY_SIZE(fcs_modules); i++) { mod = &fcs_modules[i]; if (mod->modinit) mod->modinit(fcs); @@ -184,7 +184,7 @@ bfa_fcs_exit(struct bfa_fcs_s *fcs) bfa_wc_init(&fcs->wc, bfa_fcs_exit_comp, fcs); - nmods = sizeof(fcs_modules) / sizeof(fcs_modules[0]); + nmods = ARRAY_SIZE(fcs_modules); for (i = 0; i < nmods; i++) { diff --git a/drivers/scsi/bfa/bfa_ioc.h b/drivers/scsi/bfa/bfa_ioc.h index 2e28392c2fb6..a38aafa030b3 100644 --- a/drivers/scsi/bfa/bfa_ioc.h +++ b/drivers/scsi/bfa/bfa_ioc.h @@ -72,7 +72,7 @@ struct bfa_sge_s { } while (0) #define bfa_swap_words(_x) ( \ - ((_x) << 32) | ((_x) >> 32)) + ((u64)(_x) << 32) | ((u64)(_x) >> 32)) #ifdef __BIG_ENDIAN #define bfa_sge_to_be(_x) diff --git a/drivers/scsi/bfa/bfad.c b/drivers/scsi/bfa/bfad.c index 7593b7c1d336..e90a3742f09d 100644 --- a/drivers/scsi/bfa/bfad.c +++ b/drivers/scsi/bfa/bfad.c @@ -1219,7 +1219,7 @@ bfad_install_msix_handler(struct bfad_s *bfad) int bfad_setup_intr(struct bfad_s *bfad) { - int error = 0; + int error; u32 mask = 0, i, num_bit = 0, max_bit = 0; struct msix_entry msix_entries[MAX_MSIX_ENTRY]; struct pci_dev *pdev = bfad->pcidev; @@ -1234,34 +1234,24 @@ bfad_setup_intr(struct bfad_s *bfad) if ((bfa_asic_id_ctc(pdev->device) && !msix_disable_ct) || (bfa_asic_id_cb(pdev->device) && !msix_disable_cb)) { - error = pci_enable_msix(bfad->pcidev, msix_entries, bfad->nvec); - if (error) { - /* In CT1 & CT2, try to allocate just one vector */ - if (bfa_asic_id_ctc(pdev->device)) { - printk(KERN_WARNING "bfa %s: trying one msix " - "vector failed to allocate %d[%d]\n", - bfad->pci_name, bfad->nvec, error); - bfad->nvec = 1; - error = pci_enable_msix(bfad->pcidev, - msix_entries, bfad->nvec); - } + error = pci_enable_msix_exact(bfad->pcidev, + msix_entries, bfad->nvec); + /* In CT1 & CT2, try to allocate just one vector */ + if (error == -ENOSPC && bfa_asic_id_ctc(pdev->device)) { + printk(KERN_WARNING "bfa %s: trying one msix " + "vector failed to allocate %d[%d]\n", + bfad->pci_name, bfad->nvec, error); + bfad->nvec = 1; + error = pci_enable_msix_exact(bfad->pcidev, + msix_entries, 1); + } - /* - * Only error number of vector is available. - * We don't have a mechanism to map multiple - * interrupts into one vector, so even if we - * can try to request less vectors, we don't - * know how to associate interrupt events to - * vectors. Linux doesn't duplicate vectors - * in the MSIX table for this case. - */ - if (error) { - printk(KERN_WARNING "bfad%d: " - "pci_enable_msix failed (%d), " - "use line based.\n", - bfad->inst_no, error); - goto line_based; - } + if (error) { + printk(KERN_WARNING "bfad%d: " + "pci_enable_msix_exact failed (%d), " + "use line based.\n", + bfad->inst_no, error); + goto line_based; } /* Disable INTX in MSI-X mode */ @@ -1281,20 +1271,18 @@ bfad_setup_intr(struct bfad_s *bfad) bfad->bfad_flags |= BFAD_MSIX_ON; - return error; + return 0; } line_based: - error = 0; - if (request_irq - (bfad->pcidev->irq, (irq_handler_t) bfad_intx, BFAD_IRQ_FLAGS, - BFAD_DRIVER_NAME, bfad) != 0) { - /* Enable interrupt handler failed */ - return 1; - } + error = request_irq(bfad->pcidev->irq, (irq_handler_t)bfad_intx, + BFAD_IRQ_FLAGS, BFAD_DRIVER_NAME, bfad); + if (error) + return error; + bfad->bfad_flags |= BFAD_INTX_ON; - return error; + return 0; } void diff --git a/drivers/scsi/bfa/bfad_bsg.c b/drivers/scsi/bfa/bfad_bsg.c index 8994fb857ee9..023b9d42ad9a 100644 --- a/drivers/scsi/bfa/bfad_bsg.c +++ b/drivers/scsi/bfa/bfad_bsg.c @@ -26,7 +26,6 @@ int bfad_iocmd_ioc_enable(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; - int rc = 0; unsigned long flags; spin_lock_irqsave(&bfad->bfad_lock, flags); @@ -34,7 +33,7 @@ bfad_iocmd_ioc_enable(struct bfad_s *bfad, void *cmd) if (!bfa_ioc_is_disabled(&bfad->bfa.ioc)) { spin_unlock_irqrestore(&bfad->bfad_lock, flags); iocmd->status = BFA_STATUS_OK; - return rc; + return 0; } init_completion(&bfad->enable_comp); @@ -43,21 +42,20 @@ bfad_iocmd_ioc_enable(struct bfad_s *bfad, void *cmd) spin_unlock_irqrestore(&bfad->bfad_lock, flags); wait_for_completion(&bfad->enable_comp); - return rc; + return 0; } int bfad_iocmd_ioc_disable(struct bfad_s *bfad, void *cmd) { struct bfa_bsg_gen_s *iocmd = (struct bfa_bsg_gen_s *)cmd; - int rc = 0; unsigned long flags; spin_lock_irqsave(&bfad->bfad_lock, flags); if (bfa_ioc_is_disabled(&bfad->bfa.ioc)) { spin_unlock_irqrestore(&bfad->bfad_lock, flags); iocmd->status = BFA_STATUS_OK; - return rc; + return 0; } if (bfad->disable_active) { @@ -74,7 +72,7 @@ bfad_iocmd_ioc_disable(struct bfad_s *bfad, void *cmd) bfad->disable_active = BFA_FALSE; iocmd->status = BFA_STATUS_OK; - return rc; + return 0; } static int @@ -3270,13 +3268,13 @@ bfad_fcxp_map_sg(struct bfad_s *bfad, void *payload_kbuf, /* Allocate dma coherent memory */ buf_info = buf_base; buf_info->size = payload_len; - buf_info->virt = dma_alloc_coherent(&bfad->pcidev->dev, buf_info->size, - &buf_info->phys, GFP_KERNEL); + buf_info->virt = dma_zalloc_coherent(&bfad->pcidev->dev, + buf_info->size, &buf_info->phys, + GFP_KERNEL); if (!buf_info->virt) goto out_free_mem; /* copy the linear bsg buffer to buf_info */ - memset(buf_info->virt, 0, buf_info->size); memcpy(buf_info->virt, payload_kbuf, buf_info->size); /* diff --git a/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h b/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h index e1f1e3448f98..fe2106c91c08 100644 --- a/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h +++ b/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h @@ -1,3 +1,16 @@ +/* 57xx_hsi_bnx2fc.h: QLogic NetXtreme II Linux FCoE offload driver. + * Handles operations such as session offload/upload etc, and manages + * session resources such as connection id and qp resources. + * + * Copyright (c) 2008 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation + * + * 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. + * + */ + #ifndef __57XX_FCOE_HSI_LINUX_LE__ #define __57XX_FCOE_HSI_LINUX_LE__ diff --git a/drivers/scsi/bnx2fc/Kconfig b/drivers/scsi/bnx2fc/Kconfig index cfcad8bde7cf..f245d543d7b1 100644 --- a/drivers/scsi/bnx2fc/Kconfig +++ b/drivers/scsi/bnx2fc/Kconfig @@ -1,5 +1,5 @@ config SCSI_BNX2X_FCOE - tristate "Broadcom NetXtreme II FCoE support" + tristate "QLogic NetXtreme II FCoE support" depends on PCI select NETDEVICES select ETHERNET @@ -8,5 +8,5 @@ config SCSI_BNX2X_FCOE select LIBFCOE select CNIC ---help--- - This driver supports FCoE offload for the Broadcom NetXtreme II + This driver supports FCoE offload for the QLogic NetXtreme II devices. diff --git a/drivers/scsi/bnx2fc/bnx2fc.h b/drivers/scsi/bnx2fc/bnx2fc.h index 6a976657b475..1346e052e03c 100644 --- a/drivers/scsi/bnx2fc/bnx2fc.h +++ b/drivers/scsi/bnx2fc/bnx2fc.h @@ -1,8 +1,7 @@ -#ifndef _BNX2FC_H_ -#define _BNX2FC_H_ -/* bnx2fc.h: Broadcom NetXtreme II Linux FCoE offload driver. +/* bnx2fc.h: QLogic NetXtreme II Linux FCoE offload driver. * * Copyright (c) 2008 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation * * 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 @@ -11,6 +10,8 @@ * Written by: Bhanu Prakash Gollapudi (bprakash@broadcom.com) */ +#ifndef _BNX2FC_H_ +#define _BNX2FC_H_ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/module.h> diff --git a/drivers/scsi/bnx2fc/bnx2fc_constants.h b/drivers/scsi/bnx2fc/bnx2fc_constants.h index dad9924abbbb..e147cc7ee36c 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_constants.h +++ b/drivers/scsi/bnx2fc/bnx2fc_constants.h @@ -1,3 +1,16 @@ +/* bnx2fc_constants.h: QLogic NetXtreme II Linux FCoE offload driver. + * Handles operations such as session offload/upload etc, and manages + * session resources such as connection id and qp resources. + * + * Copyright (c) 2008 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation + * + * 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. + * + */ + #ifndef __BNX2FC_CONSTANTS_H_ #define __BNX2FC_CONSTANTS_H_ diff --git a/drivers/scsi/bnx2fc/bnx2fc_debug.c b/drivers/scsi/bnx2fc/bnx2fc_debug.c index 0cbee1b23ee2..d055df01faa5 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_debug.c +++ b/drivers/scsi/bnx2fc/bnx2fc_debug.c @@ -1,3 +1,16 @@ +/* bnx2fc_debug.c: QLogic NetXtreme II Linux FCoE offload driver. + * Handles operations such as session offload/upload etc, and manages + * session resources such as connection id and qp resources. + * + * Copyright (c) 2008 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation + * + * 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. + * + */ + #include "bnx2fc.h" void BNX2FC_IO_DBG(const struct bnx2fc_cmd *io_req, const char *fmt, ...) diff --git a/drivers/scsi/bnx2fc/bnx2fc_debug.h b/drivers/scsi/bnx2fc/bnx2fc_debug.h index 4808ff99621f..2b9006774f37 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_debug.h +++ b/drivers/scsi/bnx2fc/bnx2fc_debug.h @@ -1,3 +1,16 @@ +/* bnx2fc_debug.h: QLogic NetXtreme II Linux FCoE offload driver. + * Handles operations such as session offload/upload etc, and manages + * session resources such as connection id and qp resources. + * + * Copyright (c) 2008 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation + * + * 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. + * + */ + #ifndef __BNX2FC_DEBUG__ #define __BNX2FC_DEBUG__ diff --git a/drivers/scsi/bnx2fc/bnx2fc_els.c b/drivers/scsi/bnx2fc/bnx2fc_els.c index b1c9a4f8caee..ca75c7ca2559 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_els.c +++ b/drivers/scsi/bnx2fc/bnx2fc_els.c @@ -1,9 +1,10 @@ /* - * bnx2fc_els.c: Broadcom NetXtreme II Linux FCoE offload driver. + * bnx2fc_els.c: QLogic NetXtreme II Linux FCoE offload driver. * This file contains helper routines that handle ELS requests * and responses. * * Copyright (c) 2008 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation * * 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 diff --git a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c index 785d0d71781e..79e5c94107a9 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_fcoe.c +++ b/drivers/scsi/bnx2fc/bnx2fc_fcoe.c @@ -1,9 +1,10 @@ -/* bnx2fc_fcoe.c: Broadcom NetXtreme II Linux FCoE offload driver. +/* bnx2fc_fcoe.c: QLogic NetXtreme II Linux FCoE offload driver. * This file contains the code that interacts with libfc, libfcoe, * cnic modules to create FCoE instances, send/receive non-offloaded * FIP/FCoE packets, listen to link events etc. * * Copyright (c) 2008 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation * * 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 @@ -26,12 +27,12 @@ DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu); static char version[] = - "Broadcom NetXtreme II FCoE Driver " DRV_MODULE_NAME \ + "QLogic NetXtreme II FCoE Driver " DRV_MODULE_NAME \ " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; MODULE_AUTHOR("Bhanu Prakash Gollapudi <bprakash@broadcom.com>"); -MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710 FCoE Driver"); +MODULE_DESCRIPTION("QLogic NetXtreme II BCM57710 FCoE Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); @@ -692,7 +693,7 @@ static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev) if (!lport->vport) fc_host_max_npiv_vports(lport->host) = USHRT_MAX; snprintf(fc_host_symbolic_name(lport->host), 256, - "%s (Broadcom %s) v%s over %s", + "%s (QLogic %s) v%s over %s", BNX2FC_NAME, hba->chip_num, BNX2FC_VERSION, interface->netdev->name); @@ -2775,7 +2776,7 @@ static struct fc_function_template bnx2fc_vport_xport_function = { */ static struct scsi_host_template bnx2fc_shost_template = { .module = THIS_MODULE, - .name = "Broadcom Offload FCoE Initiator", + .name = "QLogic Offload FCoE Initiator", .queuecommand = bnx2fc_queuecommand, .eh_abort_handler = bnx2fc_eh_abort, /* abts */ .eh_device_reset_handler = bnx2fc_eh_device_reset, /* lun reset */ diff --git a/drivers/scsi/bnx2fc/bnx2fc_hwi.c b/drivers/scsi/bnx2fc/bnx2fc_hwi.c index 512aed3ae4f1..c6688d72a846 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_hwi.c +++ b/drivers/scsi/bnx2fc/bnx2fc_hwi.c @@ -1,8 +1,9 @@ -/* bnx2fc_hwi.c: Broadcom NetXtreme II Linux FCoE offload driver. +/* bnx2fc_hwi.c: QLogic NetXtreme II Linux FCoE offload driver. * This file contains the code that low level functions that interact * with 57712 FCoE firmware. * * Copyright (c) 2008 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation * * 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 diff --git a/drivers/scsi/bnx2fc/bnx2fc_io.c b/drivers/scsi/bnx2fc/bnx2fc_io.c index 7bc47fc7c686..4c5891e66038 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_io.c +++ b/drivers/scsi/bnx2fc/bnx2fc_io.c @@ -1,7 +1,8 @@ -/* bnx2fc_io.c: Broadcom NetXtreme II Linux FCoE offload driver. +/* bnx2fc_io.c: QLogic NetXtreme II Linux FCoE offload driver. * IO manager and SCSI IO processing. * * Copyright (c) 2008 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation * * 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 @@ -1450,9 +1451,9 @@ static void bnx2fc_lun_reset_cmpl(struct bnx2fc_cmd *io_req) struct scsi_cmnd *sc_cmd = io_req->sc_cmd; struct bnx2fc_rport *tgt = io_req->tgt; struct bnx2fc_cmd *cmd, *tmp; - int tm_lun = sc_cmd->device->lun; + u64 tm_lun = sc_cmd->device->lun; + u64 lun; int rc = 0; - int lun; /* called with tgt_lock held */ BNX2FC_IO_DBG(io_req, "Entered bnx2fc_lun_reset_cmpl\n"); diff --git a/drivers/scsi/bnx2fc/bnx2fc_tgt.c b/drivers/scsi/bnx2fc/bnx2fc_tgt.c index 6870cf6781d9..c66c708412a6 100644 --- a/drivers/scsi/bnx2fc/bnx2fc_tgt.c +++ b/drivers/scsi/bnx2fc/bnx2fc_tgt.c @@ -1,8 +1,9 @@ -/* bnx2fc_tgt.c: Broadcom NetXtreme II Linux FCoE offload driver. +/* bnx2fc_tgt.c: QLogic NetXtreme II Linux FCoE offload driver. * Handles operations such as session offload/upload etc, and manages * session resources such as connection id and qp resources. * * Copyright (c) 2008 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation * * 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 diff --git a/drivers/scsi/bnx2i/57xx_iscsi_constants.h b/drivers/scsi/bnx2i/57xx_iscsi_constants.h index 3d33767f2f2c..917534109a50 100644 --- a/drivers/scsi/bnx2i/57xx_iscsi_constants.h +++ b/drivers/scsi/bnx2i/57xx_iscsi_constants.h @@ -1,13 +1,15 @@ -/* 57xx_iscsi_constants.h: Broadcom NetXtreme II iSCSI HSI +/* 57xx_iscsi_constants.h: QLogic NetXtreme II iSCSI HSI * * Copyright (c) 2006 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation * * 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. * * Written by: Anil Veerabhadrappa (anilgv@broadcom.com) - * Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Maintained by: QLogic-Storage-Upstream@qlogic.com */ #ifndef __57XX_ISCSI_CONSTANTS_H_ #define __57XX_ISCSI_CONSTANTS_H_ diff --git a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h index 7052a839b0ea..19b3a97dbacd 100644 --- a/drivers/scsi/bnx2i/57xx_iscsi_hsi.h +++ b/drivers/scsi/bnx2i/57xx_iscsi_hsi.h @@ -1,13 +1,15 @@ -/* 57xx_iscsi_hsi.h: Broadcom NetXtreme II iSCSI HSI. +/* 57xx_iscsi_hsi.h: QLogic NetXtreme II iSCSI HSI. * * Copyright (c) 2006 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation * * 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. * * Written by: Anil Veerabhadrappa (anilgv@broadcom.com) - * Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Maintained by: QLogic-Storage-Upstream@qlogic.com */ #ifndef __57XX_ISCSI_HSI_LINUX_LE__ #define __57XX_ISCSI_HSI_LINUX_LE__ diff --git a/drivers/scsi/bnx2i/Kconfig b/drivers/scsi/bnx2i/Kconfig index 01cff1894b6d..44ce54e536e5 100644 --- a/drivers/scsi/bnx2i/Kconfig +++ b/drivers/scsi/bnx2i/Kconfig @@ -1,5 +1,5 @@ config SCSI_BNX2_ISCSI - tristate "Broadcom NetXtreme II iSCSI support" + tristate "QLogic NetXtreme II iSCSI support" depends on NET depends on PCI select SCSI_ISCSI_ATTRS @@ -8,5 +8,5 @@ config SCSI_BNX2_ISCSI select NET_VENDOR_BROADCOM select CNIC ---help--- - This driver supports iSCSI offload for the Broadcom NetXtreme II + This driver supports iSCSI offload for the QLogic NetXtreme II devices. diff --git a/drivers/scsi/bnx2i/bnx2i.h b/drivers/scsi/bnx2i/bnx2i.h index c73bbcb63c02..ed7f3228e234 100644 --- a/drivers/scsi/bnx2i/bnx2i.h +++ b/drivers/scsi/bnx2i/bnx2i.h @@ -1,15 +1,17 @@ -/* bnx2i.h: Broadcom NetXtreme II iSCSI driver. +/* bnx2i.h: QLogic NetXtreme II iSCSI driver. * * Copyright (c) 2006 - 2013 Broadcom Corporation * Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved. * Copyright (c) 2007, 2008 Mike Christie + * Copyright (c) 2014, QLogic Corporation * * 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. * * Written by: Anil Veerabhadrappa (anilgv@broadcom.com) - * Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Maintained by: QLogic-Storage-Upstream@qlogic.com */ #ifndef _BNX2I_H_ diff --git a/drivers/scsi/bnx2i/bnx2i_hwi.c b/drivers/scsi/bnx2i/bnx2i_hwi.c index d6d491c2f004..fb072cc5e9fd 100644 --- a/drivers/scsi/bnx2i/bnx2i_hwi.c +++ b/drivers/scsi/bnx2i/bnx2i_hwi.c @@ -1,15 +1,17 @@ -/* bnx2i_hwi.c: Broadcom NetXtreme II iSCSI driver. +/* bnx2i_hwi.c: QLogic NetXtreme II iSCSI driver. * * Copyright (c) 2006 - 2013 Broadcom Corporation * Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved. * Copyright (c) 2007, 2008 Mike Christie + * Copyright (c) 2014, QLogic Corporation * * 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. * * Written by: Anil Veerabhadrappa (anilgv@broadcom.com) - * Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Maintained by: QLogic-Storage-Upstream@qlogic.com */ #include <linux/gfp.h> diff --git a/drivers/scsi/bnx2i/bnx2i_init.c b/drivers/scsi/bnx2i/bnx2i_init.c index 80c03b452d61..c8b410c24cf0 100644 --- a/drivers/scsi/bnx2i/bnx2i_init.c +++ b/drivers/scsi/bnx2i/bnx2i_init.c @@ -1,15 +1,17 @@ -/* bnx2i.c: Broadcom NetXtreme II iSCSI driver. +/* bnx2i.c: QLogic NetXtreme II iSCSI driver. * * Copyright (c) 2006 - 2013 Broadcom Corporation * Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved. * Copyright (c) 2007, 2008 Mike Christie + * Copyright (c) 2014, QLogic Corporation * * 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. * * Written by: Anil Veerabhadrappa (anilgv@broadcom.com) - * Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Maintained by: QLogic-Storage-Upstream@qlogic.com */ #include "bnx2i.h" @@ -18,18 +20,18 @@ static struct list_head adapter_list = LIST_HEAD_INIT(adapter_list); static u32 adapter_count; #define DRV_MODULE_NAME "bnx2i" -#define DRV_MODULE_VERSION "2.7.6.2" -#define DRV_MODULE_RELDATE "Jun 06, 2013" +#define DRV_MODULE_VERSION "2.7.10.1" +#define DRV_MODULE_RELDATE "Jul 16, 2014" static char version[] = - "Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \ + "QLogic NetXtreme II iSCSI Driver " DRV_MODULE_NAME \ " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; MODULE_AUTHOR("Anil Veerabhadrappa <anilgv@broadcom.com> and " "Eddie Wai <eddie.wai@broadcom.com>"); -MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/57710/57711/57712" +MODULE_DESCRIPTION("QLogic NetXtreme II BCM5706/5708/5709/57710/57711/57712" "/57800/57810/57840 iSCSI Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_MODULE_VERSION); diff --git a/drivers/scsi/bnx2i/bnx2i_iscsi.c b/drivers/scsi/bnx2i/bnx2i_iscsi.c index 166543f7ef55..40e22497d249 100644 --- a/drivers/scsi/bnx2i/bnx2i_iscsi.c +++ b/drivers/scsi/bnx2i/bnx2i_iscsi.c @@ -1,16 +1,18 @@ /* - * bnx2i_iscsi.c: Broadcom NetXtreme II iSCSI driver. + * bnx2i_iscsi.c: QLogic NetXtreme II iSCSI driver. * * Copyright (c) 2006 - 2013 Broadcom Corporation * Copyright (c) 2007, 2008 Red Hat, Inc. All rights reserved. * Copyright (c) 2007, 2008 Mike Christie + * Copyright (c) 2014, QLogic Corporation * * 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. * * Written by: Anil Veerabhadrappa (anilgv@broadcom.com) - * Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Maintained by: QLogic-Storage-Upstream@qlogic.com */ #include <linux/slab.h> @@ -1643,12 +1645,11 @@ static void bnx2i_conn_get_stats(struct iscsi_cls_conn *cls_conn, stats->r2t_pdus = conn->r2t_pdus_cnt; stats->tmfcmd_pdus = conn->tmfcmd_pdus_cnt; stats->tmfrsp_pdus = conn->tmfrsp_pdus_cnt; - stats->custom_length = 3; - strcpy(stats->custom[2].desc, "eh_abort_cnt"); - stats->custom[2].value = conn->eh_abort_cnt; stats->digest_err = 0; stats->timeout_err = 0; - stats->custom_length = 0; + strcpy(stats->custom[0].desc, "eh_abort_cnt"); + stats->custom[0].value = conn->eh_abort_cnt; + stats->custom_length = 1; } @@ -2249,7 +2250,7 @@ static umode_t bnx2i_attr_is_visible(int param_type, int param) */ static struct scsi_host_template bnx2i_host_template = { .module = THIS_MODULE, - .name = "Broadcom Offload iSCSI Initiator", + .name = "QLogic Offload iSCSI Initiator", .proc_name = "bnx2i", .queuecommand = iscsi_queuecommand, .eh_abort_handler = iscsi_eh_abort, diff --git a/drivers/scsi/bnx2i/bnx2i_sysfs.c b/drivers/scsi/bnx2i/bnx2i_sysfs.c index a0a3d9fe61fe..6d56fd60cb2b 100644 --- a/drivers/scsi/bnx2i/bnx2i_sysfs.c +++ b/drivers/scsi/bnx2i/bnx2i_sysfs.c @@ -1,13 +1,15 @@ -/* bnx2i_sysfs.c: Broadcom NetXtreme II iSCSI driver. +/* bnx2i_sysfs.c: QLogic NetXtreme II iSCSI driver. * * Copyright (c) 2004 - 2013 Broadcom Corporation + * Copyright (c) 2014, QLogic Corporation * * 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. * * Written by: Anil Veerabhadrappa (anilgv@broadcom.com) - * Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Previously Maintained by: Eddie Wai (eddie.wai@broadcom.com) + * Maintained by: QLogic-Storage-Upstream@qlogic.com */ #include "bnx2i.h" diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c index 2a323742ce04..ef5ae0d03616 100644 --- a/drivers/scsi/ch.c +++ b/drivers/scsi/ch.c @@ -84,15 +84,19 @@ static const char * vendor_labels[CH_TYPES-4] = { }; // module_param_string_array(vendor_labels, NULL, 0444); +#define ch_printk(prefix, ch, fmt, a...) \ + sdev_printk(prefix, (ch)->device, "[%s] " fmt, \ + (ch)->name, ##a) + #define DPRINTK(fmt, arg...) \ do { \ if (debug) \ - printk(KERN_DEBUG "%s: " fmt, ch->name, ##arg); \ + ch_printk(KERN_DEBUG, ch, fmt, ##arg); \ } while (0) #define VPRINTK(level, fmt, arg...) \ do { \ if (verbose) \ - printk(level "%s: " fmt, ch->name, ##arg); \ + ch_printk(level, ch, fmt, ##arg); \ } while (0) /* ------------------------------------------------------------------- */ @@ -196,7 +200,7 @@ ch_do_scsi(scsi_changer *ch, unsigned char *cmd, __scsi_print_command(cmd); } - result = scsi_execute_req(ch->device, cmd, direction, buffer, + result = scsi_execute_req(ch->device, cmd, direction, buffer, buflength, &sshdr, timeout * HZ, MAX_RETRIES, NULL); @@ -247,7 +251,7 @@ ch_read_element_status(scsi_changer *ch, u_int elem, char *data) retry: memset(cmd,0,sizeof(cmd)); cmd[0] = READ_ELEMENT_STATUS; - cmd[1] = (ch->device->lun << 5) | + cmd[1] = ((ch->device->lun & 0x7) << 5) | (ch->voltags ? 0x10 : 0) | ch_elem_to_typecode(ch,elem); cmd[2] = (elem >> 8) & 0xff; @@ -283,7 +287,7 @@ ch_init_elem(scsi_changer *ch) VPRINTK(KERN_INFO, "INITIALIZE ELEMENT STATUS, may take some time ...\n"); memset(cmd,0,sizeof(cmd)); cmd[0] = INITIALIZE_ELEMENT_STATUS; - cmd[1] = ch->device->lun << 5; + cmd[1] = (ch->device->lun & 0x7) << 5; err = ch_do_scsi(ch, cmd, NULL, 0, DMA_NONE); VPRINTK(KERN_INFO, "... finished\n"); return err; @@ -303,7 +307,7 @@ ch_readconfig(scsi_changer *ch) memset(cmd,0,sizeof(cmd)); cmd[0] = MODE_SENSE; - cmd[1] = ch->device->lun << 5; + cmd[1] = (ch->device->lun & 0x7) << 5; cmd[2] = 0x1d; cmd[4] = 255; result = ch_do_scsi(ch, cmd, buffer, 255, DMA_FROM_DEVICE); @@ -428,7 +432,7 @@ ch_position(scsi_changer *ch, u_int trans, u_int elem, int rotate) trans = ch->firsts[CHET_MT]; memset(cmd,0,sizeof(cmd)); cmd[0] = POSITION_TO_ELEMENT; - cmd[1] = ch->device->lun << 5; + cmd[1] = (ch->device->lun & 0x7) << 5; cmd[2] = (trans >> 8) & 0xff; cmd[3] = trans & 0xff; cmd[4] = (elem >> 8) & 0xff; @@ -447,7 +451,7 @@ ch_move(scsi_changer *ch, u_int trans, u_int src, u_int dest, int rotate) trans = ch->firsts[CHET_MT]; memset(cmd,0,sizeof(cmd)); cmd[0] = MOVE_MEDIUM; - cmd[1] = ch->device->lun << 5; + cmd[1] = (ch->device->lun & 0x7) << 5; cmd[2] = (trans >> 8) & 0xff; cmd[3] = trans & 0xff; cmd[4] = (src >> 8) & 0xff; @@ -470,7 +474,7 @@ ch_exchange(scsi_changer *ch, u_int trans, u_int src, trans = ch->firsts[CHET_MT]; memset(cmd,0,sizeof(cmd)); cmd[0] = EXCHANGE_MEDIUM; - cmd[1] = ch->device->lun << 5; + cmd[1] = (ch->device->lun & 0x7) << 5; cmd[2] = (trans >> 8) & 0xff; cmd[3] = trans & 0xff; cmd[4] = (src >> 8) & 0xff; @@ -518,7 +522,7 @@ ch_set_voltag(scsi_changer *ch, u_int elem, elem, tag); memset(cmd,0,sizeof(cmd)); cmd[0] = SEND_VOLUME_TAG; - cmd[1] = (ch->device->lun << 5) | + cmd[1] = ((ch->device->lun & 0x7) << 5) | ch_elem_to_typecode(ch,elem); cmd[2] = (elem >> 8) & 0xff; cmd[3] = elem & 0xff; @@ -754,7 +758,7 @@ static long ch_ioctl(struct file *file, voltag_retry: memset(ch_cmd, 0, sizeof(ch_cmd)); ch_cmd[0] = READ_ELEMENT_STATUS; - ch_cmd[1] = (ch->device->lun << 5) | + ch_cmd[1] = ((ch->device->lun & 0x7) << 5) | (ch->voltags ? 0x10 : 0) | ch_elem_to_typecode(ch,elem); ch_cmd[2] = (elem >> 8) & 0xff; @@ -924,8 +928,8 @@ static int ch_probe(struct device *dev) MKDEV(SCSI_CHANGER_MAJOR, ch->minor), ch, "s%s", ch->name); if (IS_ERR(class_dev)) { - printk(KERN_WARNING "ch%d: device_create failed\n", - ch->minor); + sdev_printk(KERN_WARNING, sd, "ch%d: device_create failed\n", + ch->minor); ret = PTR_ERR(class_dev); goto remove_idr; } diff --git a/drivers/scsi/csiostor/csio_scsi.c b/drivers/scsi/csiostor/csio_scsi.c index 7494e4bc69cc..86103c8475d8 100644 --- a/drivers/scsi/csiostor/csio_scsi.c +++ b/drivers/scsi/csiostor/csio_scsi.c @@ -1657,7 +1657,7 @@ csio_scsi_err_handler(struct csio_hw *hw, struct csio_ioreq *req) case FW_SCSI_UNDER_FLOW_ERR: csio_warn(hw, "Under-flow error,cmnd:0x%x expected" - " len:0x%x resid:0x%x lun:0x%x ssn:0x%x\n", + " len:0x%x resid:0x%x lun:0x%llx ssn:0x%x\n", cmnd->cmnd[0], scsi_bufflen(cmnd), scsi_get_resid(cmnd), cmnd->device->lun, rn->flowid); @@ -1957,7 +1957,7 @@ csio_eh_abort_handler(struct scsi_cmnd *cmnd) csio_dbg(hw, "Request to abort ioreq:%p cmd:%p cdb:%08llx" - " ssni:0x%x lun:%d iq:0x%x\n", + " ssni:0x%x lun:%llu iq:0x%x\n", ioreq, cmnd, *((uint64_t *)cmnd->cmnd), rn->flowid, cmnd->device->lun, csio_q_physiqid(hw, ioreq->iq_idx)); @@ -2015,13 +2015,13 @@ inval_scmnd: /* FW successfully aborted the request */ if (host_byte(cmnd->result) == DID_REQUEUE) { csio_info(hw, - "Aborted SCSI command to (%d:%d) serial#:0x%lx\n", + "Aborted SCSI command to (%d:%llu) serial#:0x%lx\n", cmnd->device->id, cmnd->device->lun, cmnd->serial_number); return SUCCESS; } else { csio_info(hw, - "Failed to abort SCSI command, (%d:%d) serial#:0x%lx\n", + "Failed to abort SCSI command, (%d:%llu) serial#:0x%lx\n", cmnd->device->id, cmnd->device->lun, cmnd->serial_number); return FAILED; @@ -2100,13 +2100,13 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd) if (!rn) goto fail; - csio_dbg(hw, "Request to reset LUN:%d (ssni:0x%x tgtid:%d)\n", + csio_dbg(hw, "Request to reset LUN:%llu (ssni:0x%x tgtid:%d)\n", cmnd->device->lun, rn->flowid, rn->scsi_id); if (!csio_is_lnode_ready(ln)) { csio_err(hw, "LUN reset cannot be issued on non-ready" - " local node vnpi:0x%x (LUN:%d)\n", + " local node vnpi:0x%x (LUN:%llu)\n", ln->vnp_flowid, cmnd->device->lun); goto fail; } @@ -2126,7 +2126,7 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd) if (fc_remote_port_chkready(rn->rport)) { csio_err(hw, "LUN reset cannot be issued on non-ready" - " remote node ssni:0x%x (LUN:%d)\n", + " remote node ssni:0x%x (LUN:%llu)\n", rn->flowid, cmnd->device->lun); goto fail; } @@ -2168,7 +2168,7 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd) sld.level = CSIO_LEV_LUN; sld.lnode = ioreq->lnode; sld.rnode = ioreq->rnode; - sld.oslun = (uint64_t)cmnd->device->lun; + sld.oslun = cmnd->device->lun; spin_lock_irqsave(&hw->lock, flags); /* Kick off TM SM on the ioreq */ @@ -2190,7 +2190,7 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd) /* LUN reset timed-out */ if (((struct scsi_cmnd *)csio_scsi_cmnd(ioreq)) == cmnd) { - csio_err(hw, "LUN reset (%d:%d) timed out\n", + csio_err(hw, "LUN reset (%d:%llu) timed out\n", cmnd->device->id, cmnd->device->lun); spin_lock_irq(&hw->lock); @@ -2203,7 +2203,7 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd) /* LUN reset returned, check cached status */ if (cmnd->SCp.Status != FW_SUCCESS) { - csio_err(hw, "LUN reset failed (%d:%d), status: %d\n", + csio_err(hw, "LUN reset failed (%d:%llu), status: %d\n", cmnd->device->id, cmnd->device->lun, cmnd->SCp.Status); goto fail; } @@ -2223,7 +2223,7 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd) /* Aborts may have timed out */ if (retval != 0) { csio_err(hw, - "Attempt to abort I/Os during LUN reset of %d" + "Attempt to abort I/Os during LUN reset of %llu" " returned %d\n", cmnd->device->lun, retval); /* Return I/Os back to active_q */ spin_lock_irq(&hw->lock); @@ -2234,7 +2234,7 @@ csio_eh_lun_reset_handler(struct scsi_cmnd *cmnd) CSIO_INC_STATS(rn, n_lun_rst); - csio_info(hw, "LUN reset occurred (%d:%d)\n", + csio_info(hw, "LUN reset occurred (%d:%llu)\n", cmnd->device->id, cmnd->device->lun); return SUCCESS; diff --git a/drivers/scsi/cxgbi/libcxgbi.c b/drivers/scsi/cxgbi/libcxgbi.c index 3d5322d59f15..d65df6dc106f 100644 --- a/drivers/scsi/cxgbi/libcxgbi.c +++ b/drivers/scsi/cxgbi/libcxgbi.c @@ -283,7 +283,7 @@ void cxgbi_hbas_remove(struct cxgbi_device *cdev) } EXPORT_SYMBOL_GPL(cxgbi_hbas_remove); -int cxgbi_hbas_add(struct cxgbi_device *cdev, unsigned int max_lun, +int cxgbi_hbas_add(struct cxgbi_device *cdev, u64 max_lun, unsigned int max_id, struct scsi_host_template *sht, struct scsi_transport_template *stt) { diff --git a/drivers/scsi/cxgbi/libcxgbi.h b/drivers/scsi/cxgbi/libcxgbi.h index 8ad73d913f02..b3e6e7541cc5 100644 --- a/drivers/scsi/cxgbi/libcxgbi.h +++ b/drivers/scsi/cxgbi/libcxgbi.h @@ -709,7 +709,7 @@ void cxgbi_device_unregister(struct cxgbi_device *); void cxgbi_device_unregister_all(unsigned int flag); struct cxgbi_device *cxgbi_device_find_by_lldev(void *); struct cxgbi_device *cxgbi_device_find_by_netdev(struct net_device *, int *); -int cxgbi_hbas_add(struct cxgbi_device *, unsigned int, unsigned int, +int cxgbi_hbas_add(struct cxgbi_device *, u64, unsigned int, struct scsi_host_template *, struct scsi_transport_template *); void cxgbi_hbas_remove(struct cxgbi_device *); diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index 83d9bf6fa6ca..0c6be0a17f53 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -519,9 +519,7 @@ static struct ParameterData cfg_data[] = { CFG_PARAM_UNSET, 0, 0x2f, -#ifdef CONFIG_SCSI_MULTI_LUN - NAC_SCANLUN | -#endif + NAC_SCANLUN | NAC_GT2DRIVES | NAC_GREATER_1G | NAC_POWERON_SCSI_RESET /*| NAC_ACTIVE_NEG*/, NAC_GT2DRIVES | NAC_GREATER_1G | NAC_POWERON_SCSI_RESET | 0x08 @@ -1089,7 +1087,7 @@ static int dc395x_queue_command_lck(struct scsi_cmnd *cmd, void (*done)(struct s struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)cmd->device->host->hostdata; dprintkdbg(DBG_0, "queue_command: (0x%p) <%02i-%i> cmnd=0x%02x\n", - cmd, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + cmd, cmd->device->id, (u8)cmd->device->lun, cmd->cmnd[0]); /* Assume BAD_TARGET; will be cleared later */ cmd->result = DID_BAD_TARGET << 16; @@ -1104,7 +1102,7 @@ static int dc395x_queue_command_lck(struct scsi_cmnd *cmd, void (*done)(struct s /* does the specified lun on the specified device exist */ if (!(acb->dcb_map[cmd->device->id] & (1 << cmd->device->lun))) { dprintkl(KERN_INFO, "queue_command: Ignore target <%02i-%i>\n", - cmd->device->id, cmd->device->lun); + cmd->device->id, (u8)cmd->device->lun); goto complete; } @@ -1113,7 +1111,7 @@ static int dc395x_queue_command_lck(struct scsi_cmnd *cmd, void (*done)(struct s if (!dcb) { /* should never happen */ dprintkl(KERN_ERR, "queue_command: No such device <%02i-%i>", - cmd->device->id, cmd->device->lun); + cmd->device->id, (u8)cmd->device->lun); goto complete; } @@ -1209,7 +1207,7 @@ static void dump_register_info(struct AdapterCtlBlk *acb, "cmnd=0x%02x <%02i-%i>\n", srb, srb->cmd, srb->cmd->cmnd[0], srb->cmd->device->id, - srb->cmd->device->lun); + (u8)srb->cmd->device->lun); printk(" sglist=%p cnt=%i idx=%i len=%zu\n", srb->segment_x, srb->sg_count, srb->sg_index, srb->total_xfer_length); @@ -1304,7 +1302,7 @@ static int __dc395x_eh_bus_reset(struct scsi_cmnd *cmd) (struct AdapterCtlBlk *)cmd->device->host->hostdata; dprintkl(KERN_INFO, "eh_bus_reset: (0%p) target=<%02i-%i> cmd=%p\n", - cmd, cmd->device->id, cmd->device->lun, cmd); + cmd, cmd->device->id, (u8)cmd->device->lun, cmd); if (timer_pending(&acb->waiting_timer)) del_timer(&acb->waiting_timer); @@ -1371,7 +1369,7 @@ static int dc395x_eh_abort(struct scsi_cmnd *cmd) struct DeviceCtlBlk *dcb; struct ScsiReqBlk *srb; dprintkl(KERN_INFO, "eh_abort: (0x%p) target=<%02i-%i> cmd=%p\n", - cmd, cmd->device->id, cmd->device->lun, cmd); + cmd, cmd->device->id, (u8)cmd->device->lun, cmd); dcb = find_dcb(acb, cmd->device->id, cmd->device->lun); if (!dcb) { @@ -1607,7 +1605,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, dprintkl(KERN_WARNING, "start_scsi: (0x%p) " "Out of tags target=<%02i-%i>)\n", srb->cmd, srb->cmd->device->id, - srb->cmd->device->lun); + (u8)srb->cmd->device->lun); srb->state = SRB_READY; DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_HWRESELECT); @@ -1625,7 +1623,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, /*polling:*/ /* Send CDB ..command block ......... */ dprintkdbg(DBG_KG, "start_scsi: (0x%p) <%02i-%i> cmnd=0x%02x tag=%i\n", - srb->cmd, srb->cmd->device->id, srb->cmd->device->lun, + srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun, srb->cmd->cmnd[0], srb->tag_number); if (srb->flag & AUTO_REQSENSE) { DC395x_write8(acb, TRM_S1040_SCSI_FIFO, REQUEST_SENSE); @@ -2043,7 +2041,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 scsi_status = *pscsi_status; u32 d_left_counter = 0; dprintkdbg(DBG_0, "data_out_phase0: (0x%p) <%02i-%i>\n", - srb->cmd, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun); /* * KG: We need to drain the buffers before we draw any conclusions! @@ -2173,7 +2171,7 @@ static void data_out_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { dprintkdbg(DBG_0, "data_out_phase1: (0x%p) <%02i-%i>\n", - srb->cmd, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun); clear_fifo(acb, "data_out_phase1"); /* do prepare before transfer when data out phase */ data_io_transfer(acb, srb, XFERDATAOUT); @@ -2185,7 +2183,7 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 scsi_status = *pscsi_status; dprintkdbg(DBG_0, "data_in_phase0: (0x%p) <%02i-%i>\n", - srb->cmd, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun); /* * KG: DataIn is much more tricky than DataOut. When the device is finished @@ -2396,7 +2394,7 @@ static void data_in_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { dprintkdbg(DBG_0, "data_in_phase1: (0x%p) <%02i-%i>\n", - srb->cmd, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun); data_io_transfer(acb, srb, XFERDATAIN); } @@ -2408,7 +2406,7 @@ static void data_io_transfer(struct AdapterCtlBlk *acb, u8 bval; dprintkdbg(DBG_0, "data_io_transfer: (0x%p) <%02i-%i> %c len=%i, sg=(%i/%i)\n", - srb->cmd, srb->cmd->device->id, srb->cmd->device->lun, + srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun, ((io_dir & DMACMD_DIR) ? 'r' : 'w'), srb->total_xfer_length, srb->sg_index, srb->sg_count); if (srb == acb->tmp_srb) @@ -2581,7 +2579,7 @@ static void status_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { dprintkdbg(DBG_0, "status_phase0: (0x%p) <%02i-%i>\n", - srb->cmd, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun); srb->target_status = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); srb->end_message = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); /* get message */ srb->state = SRB_COMPLETED; @@ -2595,7 +2593,7 @@ static void status_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { dprintkdbg(DBG_0, "status_phase1: (0x%p) <%02i-%i>\n", - srb->cmd, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd, srb->cmd->device->id, (u8)srb->cmd->device->lun); srb->state = SRB_STATUS; DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */ DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, SCMD_COMP); @@ -3320,7 +3318,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, int ckc_only = 1; dprintkdbg(DBG_1, "srb_done: (0x%p) <%02i-%i>\n", srb->cmd, - srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd->device->id, (u8)srb->cmd->device->lun); dprintkdbg(DBG_SG, "srb_done: srb=%p sg=%i(%i/%i) buf=%p\n", srb, scsi_sg_count(cmd), srb->sg_index, srb->sg_count, scsi_sgtalbe(cmd)); @@ -3500,7 +3498,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, if (srb->total_xfer_length) dprintkdbg(DBG_KG, "srb_done: (0x%p) <%02i-%i> " "cmnd=0x%02x Missed %i bytes\n", - cmd, cmd->device->id, cmd->device->lun, + cmd, cmd->device->id, (u8)cmd->device->lun, cmd->cmnd[0], srb->total_xfer_length); } @@ -3540,7 +3538,7 @@ static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag, dir = p->sc_data_direction; result = MK_RES(0, did_flag, 0, 0); printk("G:%p(%02i-%i) ", p, - p->device->id, p->device->lun); + p->device->id, (u8)p->device->lun); srb_going_remove(dcb, srb); free_tag(dcb, srb); srb_free_insert(acb, srb); @@ -3570,7 +3568,7 @@ static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag, result = MK_RES(0, did_flag, 0, 0); printk("W:%p<%02i-%i>", p, p->device->id, - p->device->lun); + (u8)p->device->lun); srb_waiting_remove(dcb, srb); srb_free_insert(acb, srb); p->result = result; @@ -3679,7 +3677,7 @@ static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, { struct scsi_cmnd *cmd = srb->cmd; dprintkdbg(DBG_1, "request_sense: (0x%p) <%02i-%i>\n", - cmd, cmd->device->id, cmd->device->lun); + cmd, cmd->device->id, (u8)cmd->device->lun); srb->flag |= AUTO_REQSENSE; srb->adapter_status = 0; @@ -4434,15 +4432,10 @@ static void adapter_init_scsi_host(struct Scsi_Host *host) if (host->max_id - 1 == eeprom->scsi_id) host->max_id--; -#ifdef CONFIG_SCSI_MULTI_LUN if (eeprom->channel_cfg & NAC_SCANLUN) host->max_lun = 8; else host->max_lun = 1; -#else - host->max_lun = 1; -#endif - } @@ -4645,7 +4638,7 @@ static int dc395x_show_info(struct seq_file *m, struct Scsi_Host *host) SPRINTF("irq_level 0x%04x, ", acb->irq_level); SPRINTF(" SelTimeout %ims\n", (1638 * acb->sel_timeout) / 1000); - SPRINTF("MaxID %i, MaxLUN %i, ", host->max_id, host->max_lun); + SPRINTF("MaxID %i, MaxLUN %llu, ", host->max_id, host->max_lun); SPRINTF("AdapterID %i\n", host->this_id); SPRINTF("tag_max_num %i", acb->tag_max_num); diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index c0ae8fa57a3b..67283ef418ac 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -459,7 +459,7 @@ static int adpt_queue_lck(struct scsi_cmnd * cmd, void (*done) (struct scsi_cmnd * to the device structure. This should be a TEST_UNIT_READY * command from scan_scsis_single. */ - if ((pDev = adpt_find_device(pHba, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun)) == NULL) { + if ((pDev = adpt_find_device(pHba, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun)) == NULL) { // TODO: if any luns are at this bus, scsi id then fake a TEST_UNIT_READY and INQUIRY response // with type 7F (for all luns less than the max for this bus,id) so the lun scan will continue. cmd->result = (DID_NO_CONNECT << 16); @@ -579,8 +579,8 @@ static int adpt_show_info(struct seq_file *m, struct Scsi_Host *host) seq_printf(m," Rev: %-8.8s\n", d->pScsi_dev->rev); unit = d->pI2o_dev->lct_data.tid; - seq_printf(m, "\tTID=%d, (Channel=%d, Target=%d, Lun=%d) (%s)\n\n", - unit, (int)d->scsi_channel, (int)d->scsi_id, (int)d->scsi_lun, + seq_printf(m, "\tTID=%d, (Channel=%d, Target=%d, Lun=%llu) (%s)\n\n", + unit, (int)d->scsi_channel, (int)d->scsi_id, d->scsi_lun, scsi_device_online(d->pScsi_dev)? "online":"offline"); d = d->next_lun; } @@ -1162,7 +1162,7 @@ static void adpt_i2o_delete_hba(adpt_hba* pHba) } } -static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u32 lun) +static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u64 lun) { struct adpt_device* d; @@ -1462,7 +1462,7 @@ static int adpt_i2o_parse_lct(adpt_hba* pHba) i2o_lct *lct = pHba->lct; u8 bus_no = 0; s16 scsi_id; - s16 scsi_lun; + u64 scsi_lun; u32 buf[10]; // larger than 7, or 8 ... struct adpt_device* pDev; @@ -1496,7 +1496,7 @@ static int adpt_i2o_parse_lct(adpt_hba* pHba) } bus_no = buf[0]>>16; scsi_id = buf[1]; - scsi_lun = (buf[2]>>8 )&0xff; + scsi_lun = scsilun_to_int((struct scsi_lun *)&buf[2]); if(bus_no >= MAX_CHANNEL) { // Something wrong skip it printk(KERN_WARNING"%s: Channel number %d out of range \n", pHba->name, bus_no); continue; @@ -1571,7 +1571,7 @@ static int adpt_i2o_parse_lct(adpt_hba* pHba) if(adpt_i2o_query_scalar(pHba, tid, 0x8000, -1, buf, 32)>=0) { bus_no = buf[0]>>16; scsi_id = buf[1]; - scsi_lun = (buf[2]>>8 )&0xff; + scsi_lun = scsilun_to_int((struct scsi_lun *)&buf[2]); if(bus_no >= MAX_CHANNEL) { // Something wrong skip it continue; } @@ -2407,8 +2407,8 @@ static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd) case I2O_SCSI_DSC_COMMAND_TIMEOUT: case I2O_SCSI_DSC_NO_ADAPTER: case I2O_SCSI_DSC_RESOURCE_UNAVAILABLE: - printk(KERN_WARNING"%s: SCSI Timeout-Device (%d,%d,%d) hba status=0x%x, dev status=0x%x, cmd=0x%x\n", - pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun, hba_status, dev_status, cmd->cmnd[0]); + printk(KERN_WARNING"%s: SCSI Timeout-Device (%d,%d,%llu) hba status=0x%x, dev status=0x%x, cmd=0x%x\n", + pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun, hba_status, dev_status, cmd->cmnd[0]); cmd->result = (DID_TIME_OUT << 16); break; case I2O_SCSI_DSC_ADAPTER_BUSY: @@ -2447,8 +2447,8 @@ static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd) case I2O_SCSI_DSC_QUEUE_FROZEN: case I2O_SCSI_DSC_REQUEST_INVALID: default: - printk(KERN_WARNING"%s: SCSI error %0x-Device(%d,%d,%d) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n", - pHba->name, detailed_status & I2O_SCSI_DSC_MASK, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun, + printk(KERN_WARNING"%s: SCSI error %0x-Device(%d,%d,%llu) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n", + pHba->name, detailed_status & I2O_SCSI_DSC_MASK, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun, hba_status, dev_status, cmd->cmnd[0]); cmd->result = (DID_ERROR << 16); break; @@ -2464,8 +2464,8 @@ static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd) cmd->sense_buffer[2] == DATA_PROTECT ){ /* This is to handle an array failed */ cmd->result = (DID_TIME_OUT << 16); - printk(KERN_WARNING"%s: SCSI Data Protect-Device (%d,%d,%d) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n", - pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun, + printk(KERN_WARNING"%s: SCSI Data Protect-Device (%d,%d,%llu) hba_status=0x%x, dev_status=0x%x, cmd=0x%x\n", + pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun, hba_status, dev_status, cmd->cmnd[0]); } @@ -2476,8 +2476,8 @@ static s32 adpt_i2o_to_scsi(void __iomem *reply, struct scsi_cmnd* cmd) * for a limitted number of retries. */ cmd->result = (DID_TIME_OUT << 16); - printk(KERN_WARNING"%s: I2O MSG_FAIL - Device (%d,%d,%d) tid=%d, cmd=0x%x\n", - pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, (u32)cmd->device->lun, + printk(KERN_WARNING"%s: I2O MSG_FAIL - Device (%d,%d,%llu) tid=%d, cmd=0x%x\n", + pHba->name, (u32)cmd->device->channel, (u32)cmd->device->id, cmd->device->lun, ((struct adpt_device*)(cmd->device->hostdata))->tid, cmd->cmnd[0]); } @@ -2517,7 +2517,7 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba) i2o_lct *lct = pHba->lct; u8 bus_no = 0; s16 scsi_id; - s16 scsi_lun; + u64 scsi_lun; u32 buf[10]; // at least 8 u32's struct adpt_device* pDev = NULL; struct i2o_device* pI2o_dev = NULL; @@ -2564,7 +2564,7 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba) } scsi_id = buf[1]; - scsi_lun = (buf[2]>>8 )&0xff; + scsi_lun = scsilun_to_int((struct scsi_lun *)&buf[2]); pDev = pHba->channel[bus_no].device[scsi_id]; /* da lun */ while(pDev) { @@ -2633,7 +2633,7 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba) while(pDev) { if(pDev->scsi_lun == scsi_lun) { if(!scsi_device_online(pDev->pScsi_dev)) { - printk(KERN_WARNING"%s: Setting device (%d,%d,%d) back online\n", + printk(KERN_WARNING"%s: Setting device (%d,%d,%llu) back online\n", pHba->name,bus_no,scsi_id,scsi_lun); if (pDev->pScsi_dev) { scsi_device_set_state(pDev->pScsi_dev, SDEV_RUNNING); @@ -2665,7 +2665,7 @@ static s32 adpt_i2o_reparse_lct(adpt_hba* pHba) // in the LCT table if (pDev->state & DPTI_DEV_UNSCANNED){ pDev->state = DPTI_DEV_OFFLINE; - printk(KERN_WARNING"%s: Device (%d,%d,%d) offline\n",pHba->name,pDev->scsi_channel,pDev->scsi_id,pDev->scsi_lun); + printk(KERN_WARNING"%s: Device (%d,%d,%llu) offline\n",pHba->name,pDev->scsi_channel,pDev->scsi_id,pDev->scsi_lun); if (pDev->pScsi_dev) { scsi_device_set_state(pDev->pScsi_dev, SDEV_OFFLINE); } diff --git a/drivers/scsi/dpti.h b/drivers/scsi/dpti.h index aeb046186c84..1fa345ab8ecb 100644 --- a/drivers/scsi/dpti.h +++ b/drivers/scsi/dpti.h @@ -184,7 +184,7 @@ struct adpt_device { u32 block_size; u8 scsi_channel; u8 scsi_id; - u8 scsi_lun; + u64 scsi_lun; u8 state; u16 tid; struct i2o_device* pI2o_dev; @@ -231,7 +231,7 @@ typedef struct _adpt_hba { u32 sg_tablesize; // Scatter/Gather List Size. u8 top_scsi_channel; u8 top_scsi_id; - u8 top_scsi_lun; + u64 top_scsi_lun; u8 dma64; i2o_status_block* status_block; @@ -300,7 +300,7 @@ static s32 adpt_send_nop(adpt_hba*pHba,u32 m); static void adpt_i2o_delete_hba(adpt_hba* pHba); static void adpt_inquiry(adpt_hba* pHba); static void adpt_fail_posted_scbs(adpt_hba* pHba); -static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u32 lun); +static struct adpt_device* adpt_find_device(adpt_hba* pHba, u32 chan, u32 id, u64 lun); static int adpt_install_hba(struct scsi_host_template* sht, struct pci_dev* pDev) ; static int adpt_i2o_online_hba(adpt_hba* pHba); static void adpt_i2o_post_wait_complete(u32, int); diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c index ebf57364df91..03372cff38f3 100644 --- a/drivers/scsi/eata.c +++ b/drivers/scsi/eata.c @@ -1399,7 +1399,7 @@ static int port_detect(unsigned long port_base, unsigned int j, if (shost->max_id > 8 || shost->max_lun > 8) printk - ("%s: wide SCSI support enabled, max_id %u, max_lun %u.\n", + ("%s: wide SCSI support enabled, max_id %u, max_lun %llu.\n", ha->board_name, shost->max_id, shost->max_lun); for (i = 0; i <= shost->max_channel; i++) @@ -2449,7 +2449,7 @@ static irqreturn_t ihdlr(struct Scsi_Host *shost) "target_status 0x%x, sense key 0x%x.\n", ha->board_name, SCpnt->device->channel, SCpnt->device->id, - SCpnt->device->lun, + (u8)SCpnt->device->lun, spp->target_status, SCpnt->sense_buffer[2]); ha->target_to[SCpnt->device->id][SCpnt->device->channel] = 0; diff --git a/drivers/scsi/fnic/fnic_isr.c b/drivers/scsi/fnic/fnic_isr.c index 7d9b54ae7f62..a0dd1b67a467 100644 --- a/drivers/scsi/fnic/fnic_isr.c +++ b/drivers/scsi/fnic/fnic_isr.c @@ -257,8 +257,8 @@ int fnic_set_intr_mode(struct fnic *fnic) fnic->raw_wq_count >= m && fnic->wq_copy_count >= o && fnic->cq_count >= n + m + o) { - if (!pci_enable_msix(fnic->pdev, fnic->msix_entry, - n + m + o + 1)) { + if (!pci_enable_msix_exact(fnic->pdev, fnic->msix_entry, + n + m + o + 1)) { fnic->rq_count = n; fnic->raw_wq_count = m; fnic->wq_copy_count = o; diff --git a/drivers/scsi/fnic/fnic_scsi.c b/drivers/scsi/fnic/fnic_scsi.c index ea28b5ca4c73..961bdf5d31cd 100644 --- a/drivers/scsi/fnic/fnic_scsi.c +++ b/drivers/scsi/fnic/fnic_scsi.c @@ -1753,7 +1753,7 @@ int fnic_abort_cmd(struct scsi_cmnd *sc) tag = sc->request->tag; FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, - "Abort Cmd called FCID 0x%x, LUN 0x%x TAG %x flags %x\n", + "Abort Cmd called FCID 0x%x, LUN 0x%llx TAG %x flags %x\n", rport->port_id, sc->device->lun, tag, CMD_FLAGS(sc)); CMD_FLAGS(sc) = FNIC_NO_FLAGS; @@ -2207,7 +2207,7 @@ int fnic_device_reset(struct scsi_cmnd *sc) rport = starget_to_rport(scsi_target(sc->device)); FNIC_SCSI_DBG(KERN_DEBUG, fnic->lport->host, - "Device reset called FCID 0x%x, LUN 0x%x sc 0x%p\n", + "Device reset called FCID 0x%x, LUN 0x%llx sc 0x%p\n", rport->port_id, sc->device->lun, sc); if (lp->state != LPORT_ST_READY || !(lp->link_up)) @@ -2224,6 +2224,22 @@ int fnic_device_reset(struct scsi_cmnd *sc) tag = sc->request->tag; if (unlikely(tag < 0)) { + /* + * XXX(hch): current the midlayer fakes up a struct + * request for the explicit reset ioctls, and those + * don't have a tag allocated to them. The below + * code pokes into midlayer structures to paper over + * this design issue, but that won't work for blk-mq. + * + * Either someone who can actually test the hardware + * will have to come up with a similar hack for the + * blk-mq case, or we'll have to bite the bullet and + * fix the way the EH ioctls work for real, but until + * that happens we fail these explicit requests here. + */ + if (shost_use_blk_mq(sc->device->host)) + goto fnic_device_reset_end; + tag = fnic_scsi_host_start_tag(fnic, sc); if (unlikely(tag == SCSI_NO_TAG)) goto fnic_device_reset_end; diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index a1bc8ca958e1..b331272e93bc 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -768,7 +768,7 @@ static void sprint_command(struct seq_file *m, unsigned char *command) static void sprint_Scsi_Cmnd(struct seq_file *m, Scsi_Cmnd * cmd) { - PRINTP("host number %d destination target %d, lun %d\n" ANDP cmd->device->host->host_no ANDP cmd->device->id ANDP cmd->device->lun); + PRINTP("host number %d destination target %d, lun %llu\n" ANDP cmd->device->host->host_no ANDP cmd->device->id ANDP cmd->device->lun); PRINTP(" command = "); sprint_command(m, cmd->cmnd); } diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 3cbb57a8b846..6de80e352871 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -204,18 +204,33 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev, struct scsi_host_template *sht = shost->hostt; int error = -EINVAL; - printk(KERN_INFO "scsi%d : %s\n", shost->host_no, + shost_printk(KERN_INFO, shost, "%s\n", sht->info ? sht->info(shost) : sht->name); if (!shost->can_queue) { - printk(KERN_ERR "%s: can_queue = 0 no longer supported\n", - sht->name); + shost_printk(KERN_ERR, shost, + "can_queue = 0 no longer supported\n"); goto fail; } + if (shost_use_blk_mq(shost)) { + error = scsi_mq_setup_tags(shost); + if (error) + goto fail; + } + + /* + * Note that we allocate the freelist even for the MQ case for now, + * as we need a command set aside for scsi_reset_provider. Having + * the full host freelist and one command available for that is a + * little heavy-handed, but avoids introducing a special allocator + * just for this. Eventually the structure of scsi_reset_provider + * will need a major overhaul. + */ error = scsi_setup_command_freelist(shost); if (error) - goto fail; + goto out_destroy_tags; + if (!shost->shost_gendev.parent) shost->shost_gendev.parent = dev ? dev : &platform_bus; @@ -226,7 +241,7 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev, error = device_add(&shost->shost_gendev); if (error) - goto out; + goto out_destroy_freelist; pm_runtime_set_active(&shost->shost_gendev); pm_runtime_enable(&shost->shost_gendev); @@ -279,8 +294,11 @@ int scsi_add_host_with_dma(struct Scsi_Host *shost, struct device *dev, device_del(&shost->shost_dev); out_del_gendev: device_del(&shost->shost_gendev); - out: + out_destroy_freelist: scsi_destroy_command_freelist(shost); + out_destroy_tags: + if (shost_use_blk_mq(shost)) + scsi_mq_destroy_tags(shost); fail: return error; } @@ -309,8 +327,13 @@ static void scsi_host_dev_release(struct device *dev) } scsi_destroy_command_freelist(shost); - if (shost->bqt) - blk_free_tags(shost->bqt); + if (shost_use_blk_mq(shost)) { + if (shost->tag_set.tags) + scsi_mq_destroy_tags(shost); + } else { + if (shost->bqt) + blk_free_tags(shost->bqt); + } kfree(shost->shost_data); @@ -436,6 +459,8 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) else shost->dma_boundary = 0xffffffff; + shost->use_blk_mq = scsi_use_blk_mq && !shost->hostt->disable_blk_mq; + device_initialize(&shost->shost_gendev); dev_set_name(&shost->shost_gendev, "host%d", shost->host_no); shost->shost_gendev.bus = &scsi_bus_type; @@ -450,8 +475,9 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) shost->ehandler = kthread_run(scsi_error_handler, shost, "scsi_eh_%d", shost->host_no); if (IS_ERR(shost->ehandler)) { - printk(KERN_WARNING "scsi%d: error handler thread failed to spawn, error = %ld\n", - shost->host_no, PTR_ERR(shost->ehandler)); + shost_printk(KERN_WARNING, shost, + "error handler thread failed to spawn, error = %ld\n", + PTR_ERR(shost->ehandler)); goto fail_kfree; } @@ -584,7 +610,7 @@ EXPORT_SYMBOL(scsi_is_host_device); int scsi_queue_work(struct Scsi_Host *shost, struct work_struct *work) { if (unlikely(!shost->work_q)) { - printk(KERN_ERR + shost_printk(KERN_ERR, shost, "ERROR: Scsi host '%s' attempted to queue scsi-work, " "when no workqueue created.\n", shost->hostt->name); dump_stack(); @@ -603,7 +629,7 @@ EXPORT_SYMBOL_GPL(scsi_queue_work); void scsi_flush_work(struct Scsi_Host *shost) { if (!shost->work_q) { - printk(KERN_ERR + shost_printk(KERN_ERR, shost, "ERROR: Scsi host '%s' attempted to flush scsi-work, " "when no workqueue created.\n", shost->hostt->name); dump_stack(); diff --git a/drivers/scsi/hpsa.c b/drivers/scsi/hpsa.c index 31184b35370f..8545d1826725 100644 --- a/drivers/scsi/hpsa.c +++ b/drivers/scsi/hpsa.c @@ -1708,7 +1708,14 @@ static void complete_scsi_command(struct CommandList *cp) cmd->result |= ei->ScsiStatus; - /* copy the sense data whether we need to or not. */ + scsi_set_resid(cmd, ei->ResidualCnt); + if (ei->CommandStatus == 0) { + cmd_free(h, cp); + cmd->scsi_done(cmd); + return; + } + + /* copy the sense data */ if (SCSI_SENSE_BUFFERSIZE < sizeof(ei->SenseInfo)) sense_data_size = SCSI_SENSE_BUFFERSIZE; else @@ -1717,13 +1724,6 @@ static void complete_scsi_command(struct CommandList *cp) sense_data_size = ei->SenseLen; memcpy(cmd->sense_buffer, ei->SenseInfo, sense_data_size); - scsi_set_resid(cmd, ei->ResidualCnt); - - if (ei->CommandStatus == 0) { - cmd_free(h, cp); - cmd->scsi_done(cmd); - return; - } /* For I/O accelerator commands, copy over some fields to the normal * CISS header used below for error handling. @@ -3686,6 +3686,8 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h, (((u64) cmd->cmnd[2]) << 8) | cmd->cmnd[3]; block_cnt = cmd->cmnd[4]; + if (block_cnt == 0) + block_cnt = 256; break; case WRITE_10: is_write = 1; @@ -3734,7 +3736,6 @@ static int hpsa_scsi_ioaccel_raid_map(struct ctlr_info *h, default: return IO_ACCEL_INELIGIBLE; /* process via normal I/O path */ } - BUG_ON(block_cnt == 0); last_block = first_block + block_cnt - 1; /* check for write to non-RAID-0 */ @@ -4590,7 +4591,7 @@ static int hpsa_eh_abort_handler(struct scsi_cmnd *sc) return FAILED; memset(msg, 0, sizeof(msg)); - ml += sprintf(msg+ml, "ABORT REQUEST on C%d:B%d:T%d:L%d ", + ml += sprintf(msg+ml, "ABORT REQUEST on C%d:B%d:T%d:L%llu ", h->scsi_host->host_no, sc->device->channel, sc->device->id, sc->device->lun); @@ -5092,7 +5093,7 @@ static int hpsa_big_passthru_ioctl(struct ctlr_info *h, void __user *argp) } if (ioc->Request.Type.Direction & XFER_WRITE) { if (copy_from_user(buff[sg_used], data_ptr, sz)) { - status = -ENOMEM; + status = -EFAULT; goto cleanup1; } } else @@ -6365,9 +6366,9 @@ static inline void hpsa_set_driver_support_bits(struct ctlr_info *h) { u32 driver_support; -#ifdef CONFIG_X86 - /* Need to enable prefetch in the SCSI core for 6400 in x86 */ driver_support = readl(&(h->cfgtable->driver_support)); + /* Need to enable prefetch in the SCSI core for 6400 in x86 */ +#ifdef CONFIG_X86 driver_support |= ENABLE_SCSI_PREFETCH; #endif driver_support |= ENABLE_UNIT_ATTN; @@ -6913,8 +6914,12 @@ static int hpsa_offline_devices_ready(struct ctlr_info *h) d = list_entry(this, struct offline_device_entry, offline_list); spin_unlock_irqrestore(&h->offline_device_lock, flags); - if (!hpsa_volume_offline(h, d->scsi3addr)) + if (!hpsa_volume_offline(h, d->scsi3addr)) { + spin_lock_irqsave(&h->offline_device_lock, flags); + list_del(&d->offline_list); + spin_unlock_irqrestore(&h->offline_device_lock, flags); return 1; + } spin_lock_irqsave(&h->offline_device_lock, flags); } spin_unlock_irqrestore(&h->offline_device_lock, flags); @@ -6995,8 +7000,10 @@ reinit_after_soft_reset: /* Allocate and clear per-cpu variable lockup_detected */ h->lockup_detected = alloc_percpu(u32); - if (!h->lockup_detected) + if (!h->lockup_detected) { + rc = -ENOMEM; goto clean1; + } set_lockup_detected_for_all_cpus(h, 0); rc = hpsa_pci_init(h); diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index ee196b363d81..dedb62c21b29 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -1024,7 +1024,7 @@ static int hptiop_queuecommand_lck(struct scsi_cmnd *scp, _req->scp = scp; - dprintk("hptiop_queuecmd(scp=%p) %d/%d/%d/%d cdb=(%08x-%08x-%08x-%08x) " + dprintk("hptiop_queuecmd(scp=%p) %d/%d/%d/%llu cdb=(%08x-%08x-%08x-%08x) " "req_index=%d, req=%p\n", scp, host->host_no, scp->device->channel, diff --git a/drivers/scsi/ibmvscsi/Makefile b/drivers/scsi/ibmvscsi/Makefile index cb150d1e5850..3840c64f2966 100644 --- a/drivers/scsi/ibmvscsi/Makefile +++ b/drivers/scsi/ibmvscsi/Makefile @@ -1,3 +1,2 @@ obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsi.o -obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvstgt.o obj-$(CONFIG_SCSI_IBMVFC) += ibmvfc.o diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 8dd47689d584..598c42cba5a8 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -46,7 +46,7 @@ static unsigned int init_timeout = IBMVFC_INIT_TIMEOUT; static unsigned int default_timeout = IBMVFC_DEFAULT_TIMEOUT; -static unsigned int max_lun = IBMVFC_MAX_LUN; +static u64 max_lun = IBMVFC_MAX_LUN; static unsigned int max_targets = IBMVFC_MAX_TARGETS; static unsigned int max_requests = IBMVFC_MAX_REQUESTS_DEFAULT; static unsigned int disc_threads = IBMVFC_MAX_DISC_THREADS; @@ -71,7 +71,7 @@ MODULE_PARM_DESC(default_timeout, module_param_named(max_requests, max_requests, uint, S_IRUGO); MODULE_PARM_DESC(max_requests, "Maximum requests for this adapter. " "[Default=" __stringify(IBMVFC_MAX_REQUESTS_DEFAULT) "]"); -module_param_named(max_lun, max_lun, uint, S_IRUGO); +module_param_named(max_lun, max_lun, ullong, S_IRUGO); MODULE_PARM_DESC(max_lun, "Maximum allowed LUN. " "[Default=" __stringify(IBMVFC_MAX_LUN) "]"); module_param_named(max_targets, max_targets, uint, S_IRUGO); @@ -166,13 +166,13 @@ static void ibmvfc_trc_start(struct ibmvfc_event *evt) switch (entry->fmt) { case IBMVFC_CMD_FORMAT: entry->op_code = vfc_cmd->iu.cdb[0]; - entry->scsi_id = vfc_cmd->tgt_scsi_id; + entry->scsi_id = be64_to_cpu(vfc_cmd->tgt_scsi_id); entry->lun = scsilun_to_int(&vfc_cmd->iu.lun); entry->tmf_flags = vfc_cmd->iu.tmf_flags; - entry->u.start.xfer_len = vfc_cmd->iu.xfer_len; + entry->u.start.xfer_len = be32_to_cpu(vfc_cmd->iu.xfer_len); break; case IBMVFC_MAD_FORMAT: - entry->op_code = mad->opcode; + entry->op_code = be32_to_cpu(mad->opcode); break; default: break; @@ -199,18 +199,18 @@ static void ibmvfc_trc_end(struct ibmvfc_event *evt) switch (entry->fmt) { case IBMVFC_CMD_FORMAT: entry->op_code = vfc_cmd->iu.cdb[0]; - entry->scsi_id = vfc_cmd->tgt_scsi_id; + entry->scsi_id = be64_to_cpu(vfc_cmd->tgt_scsi_id); entry->lun = scsilun_to_int(&vfc_cmd->iu.lun); entry->tmf_flags = vfc_cmd->iu.tmf_flags; - entry->u.end.status = vfc_cmd->status; - entry->u.end.error = vfc_cmd->error; + entry->u.end.status = be16_to_cpu(vfc_cmd->status); + entry->u.end.error = be16_to_cpu(vfc_cmd->error); entry->u.end.fcp_rsp_flags = vfc_cmd->rsp.flags; entry->u.end.rsp_code = vfc_cmd->rsp.data.info.rsp_code; entry->u.end.scsi_status = vfc_cmd->rsp.scsi_status; break; case IBMVFC_MAD_FORMAT: - entry->op_code = mad->opcode; - entry->u.end.status = mad->status; + entry->op_code = be32_to_cpu(mad->opcode); + entry->u.end.status = be16_to_cpu(mad->status); break; default: break; @@ -270,14 +270,14 @@ static int ibmvfc_get_err_result(struct ibmvfc_cmd *vfc_cmd) { int err; struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp; - int fc_rsp_len = rsp->fcp_rsp_len; + int fc_rsp_len = be32_to_cpu(rsp->fcp_rsp_len); if ((rsp->flags & FCP_RSP_LEN_VALID) && ((fc_rsp_len && fc_rsp_len != 4 && fc_rsp_len != 8) || rsp->data.info.rsp_code)) return DID_ERROR << 16; - err = ibmvfc_get_err_index(vfc_cmd->status, vfc_cmd->error); + err = ibmvfc_get_err_index(be16_to_cpu(vfc_cmd->status), be16_to_cpu(vfc_cmd->error)); if (err >= 0) return rsp->scsi_status | (cmd_status[err].result << 16); return rsp->scsi_status | (DID_ERROR << 16); @@ -807,7 +807,7 @@ static void ibmvfc_fail_request(struct ibmvfc_event *evt, int error_code) evt->cmnd->result = (error_code << 16); evt->done = ibmvfc_scsi_eh_done; } else - evt->xfer_iu->mad_common.status = IBMVFC_MAD_DRIVER_FAILED; + evt->xfer_iu->mad_common.status = cpu_to_be16(IBMVFC_MAD_DRIVER_FAILED); list_del(&evt->queue); del_timer(&evt->timer); @@ -955,7 +955,7 @@ static void ibmvfc_get_host_speed(struct Scsi_Host *shost) spin_lock_irqsave(shost->host_lock, flags); if (vhost->state == IBMVFC_ACTIVE) { - switch (vhost->login_buf->resp.link_speed / 100) { + switch (be64_to_cpu(vhost->login_buf->resp.link_speed) / 100) { case 1: fc_host_speed(shost) = FC_PORTSPEED_1GBIT; break; @@ -976,7 +976,7 @@ static void ibmvfc_get_host_speed(struct Scsi_Host *shost) break; default: ibmvfc_log(vhost, 3, "Unknown port speed: %lld Gbit\n", - vhost->login_buf->resp.link_speed / 100); + be64_to_cpu(vhost->login_buf->resp.link_speed) / 100); fc_host_speed(shost) = FC_PORTSPEED_UNKNOWN; break; } @@ -1171,21 +1171,21 @@ static void ibmvfc_set_login_info(struct ibmvfc_host *vhost) memset(login_info, 0, sizeof(*login_info)); - login_info->ostype = IBMVFC_OS_LINUX; - login_info->max_dma_len = IBMVFC_MAX_SECTORS << 9; - login_info->max_payload = sizeof(struct ibmvfc_fcp_cmd_iu); - login_info->max_response = sizeof(struct ibmvfc_fcp_rsp); - login_info->partition_num = vhost->partition_number; - login_info->vfc_frame_version = 1; - login_info->fcp_version = 3; - login_info->flags = IBMVFC_FLUSH_ON_HALT; + login_info->ostype = cpu_to_be32(IBMVFC_OS_LINUX); + login_info->max_dma_len = cpu_to_be64(IBMVFC_MAX_SECTORS << 9); + login_info->max_payload = cpu_to_be32(sizeof(struct ibmvfc_fcp_cmd_iu)); + login_info->max_response = cpu_to_be32(sizeof(struct ibmvfc_fcp_rsp)); + login_info->partition_num = cpu_to_be32(vhost->partition_number); + login_info->vfc_frame_version = cpu_to_be32(1); + login_info->fcp_version = cpu_to_be16(3); + login_info->flags = cpu_to_be16(IBMVFC_FLUSH_ON_HALT); if (vhost->client_migrated) - login_info->flags |= IBMVFC_CLIENT_MIGRATED; + login_info->flags |= cpu_to_be16(IBMVFC_CLIENT_MIGRATED); - login_info->max_cmds = max_requests + IBMVFC_NUM_INTERNAL_REQ; - login_info->capabilities = IBMVFC_CAN_MIGRATE; - login_info->async.va = vhost->async_crq.msg_token; - login_info->async.len = vhost->async_crq.size * sizeof(*vhost->async_crq.msgs); + login_info->max_cmds = cpu_to_be32(max_requests + IBMVFC_NUM_INTERNAL_REQ); + login_info->capabilities = cpu_to_be64(IBMVFC_CAN_MIGRATE); + login_info->async.va = cpu_to_be64(vhost->async_crq.msg_token); + login_info->async.len = cpu_to_be32(vhost->async_crq.size * sizeof(*vhost->async_crq.msgs)); strncpy(login_info->partition_name, vhost->partition_name, IBMVFC_MAX_NAME); strncpy(login_info->device_name, dev_name(&vhost->host->shost_gendev), IBMVFC_MAX_NAME); @@ -1225,7 +1225,7 @@ static int ibmvfc_init_event_pool(struct ibmvfc_host *vhost) struct ibmvfc_event *evt = &pool->events[i]; atomic_set(&evt->free, 1); evt->crq.valid = 0x80; - evt->crq.ioba = pool->iu_token + (sizeof(*evt->xfer_iu) * i); + evt->crq.ioba = cpu_to_be64(pool->iu_token + (sizeof(*evt->xfer_iu) * i)); evt->xfer_iu = pool->iu_storage + i; evt->vhost = vhost; evt->ext_list = NULL; @@ -1310,8 +1310,8 @@ static void ibmvfc_map_sg_list(struct scsi_cmnd *scmd, int nseg, struct scatterlist *sg; scsi_for_each_sg(scmd, sg, nseg, i) { - md[i].va = sg_dma_address(sg); - md[i].len = sg_dma_len(sg); + md[i].va = cpu_to_be64(sg_dma_address(sg)); + md[i].len = cpu_to_be32(sg_dma_len(sg)); md[i].key = 0; } } @@ -1337,7 +1337,7 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd, sg_mapped = scsi_dma_map(scmd); if (!sg_mapped) { - vfc_cmd->flags |= IBMVFC_NO_MEM_DESC; + vfc_cmd->flags |= cpu_to_be16(IBMVFC_NO_MEM_DESC); return 0; } else if (unlikely(sg_mapped < 0)) { if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL) @@ -1346,10 +1346,10 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd, } if (scmd->sc_data_direction == DMA_TO_DEVICE) { - vfc_cmd->flags |= IBMVFC_WRITE; + vfc_cmd->flags |= cpu_to_be16(IBMVFC_WRITE); vfc_cmd->iu.add_cdb_len |= IBMVFC_WRDATA; } else { - vfc_cmd->flags |= IBMVFC_READ; + vfc_cmd->flags |= cpu_to_be16(IBMVFC_READ); vfc_cmd->iu.add_cdb_len |= IBMVFC_RDDATA; } @@ -1358,7 +1358,7 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd, return 0; } - vfc_cmd->flags |= IBMVFC_SCATTERLIST; + vfc_cmd->flags |= cpu_to_be16(IBMVFC_SCATTERLIST); if (!evt->ext_list) { evt->ext_list = dma_pool_alloc(vhost->sg_pool, GFP_ATOMIC, @@ -1374,8 +1374,8 @@ static int ibmvfc_map_sg_data(struct scsi_cmnd *scmd, ibmvfc_map_sg_list(scmd, sg_mapped, evt->ext_list); - data->va = evt->ext_list_token; - data->len = sg_mapped * sizeof(struct srp_direct_buf); + data->va = cpu_to_be64(evt->ext_list_token); + data->len = cpu_to_be32(sg_mapped * sizeof(struct srp_direct_buf)); data->key = 0; return 0; } @@ -1404,15 +1404,15 @@ static void ibmvfc_timeout(struct ibmvfc_event *evt) static int ibmvfc_send_event(struct ibmvfc_event *evt, struct ibmvfc_host *vhost, unsigned long timeout) { - u64 *crq_as_u64 = (u64 *) &evt->crq; + __be64 *crq_as_u64 = (__be64 *) &evt->crq; int rc; /* Copy the IU into the transfer area */ *evt->xfer_iu = evt->iu; if (evt->crq.format == IBMVFC_CMD_FORMAT) - evt->xfer_iu->cmd.tag = (u64)evt; + evt->xfer_iu->cmd.tag = cpu_to_be64((u64)evt); else if (evt->crq.format == IBMVFC_MAD_FORMAT) - evt->xfer_iu->mad_common.tag = (u64)evt; + evt->xfer_iu->mad_common.tag = cpu_to_be64((u64)evt); else BUG(); @@ -1428,7 +1428,8 @@ static int ibmvfc_send_event(struct ibmvfc_event *evt, mb(); - if ((rc = ibmvfc_send_crq(vhost, crq_as_u64[0], crq_as_u64[1]))) { + if ((rc = ibmvfc_send_crq(vhost, be64_to_cpu(crq_as_u64[0]), + be64_to_cpu(crq_as_u64[1])))) { list_del(&evt->queue); del_timer(&evt->timer); @@ -1451,7 +1452,7 @@ static int ibmvfc_send_event(struct ibmvfc_event *evt, evt->cmnd->result = DID_ERROR << 16; evt->done = ibmvfc_scsi_eh_done; } else - evt->xfer_iu->mad_common.status = IBMVFC_MAD_CRQ_ERROR; + evt->xfer_iu->mad_common.status = cpu_to_be16(IBMVFC_MAD_CRQ_ERROR); evt->done(evt); } else @@ -1472,7 +1473,7 @@ static void ibmvfc_log_error(struct ibmvfc_event *evt) struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp; struct scsi_cmnd *cmnd = evt->cmnd; const char *err = unknown_error; - int index = ibmvfc_get_err_index(vfc_cmd->status, vfc_cmd->error); + int index = ibmvfc_get_err_index(be16_to_cpu(vfc_cmd->status), be16_to_cpu(vfc_cmd->error)); int logerr = 0; int rsp_code = 0; @@ -1526,13 +1527,13 @@ static void ibmvfc_scsi_done(struct ibmvfc_event *evt) struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp; struct scsi_cmnd *cmnd = evt->cmnd; u32 rsp_len = 0; - u32 sense_len = rsp->fcp_sense_len; + u32 sense_len = be32_to_cpu(rsp->fcp_sense_len); if (cmnd) { - if (vfc_cmd->response_flags & IBMVFC_ADAPTER_RESID_VALID) - scsi_set_resid(cmnd, vfc_cmd->adapter_resid); + if (be16_to_cpu(vfc_cmd->response_flags) & IBMVFC_ADAPTER_RESID_VALID) + scsi_set_resid(cmnd, be32_to_cpu(vfc_cmd->adapter_resid)); else if (rsp->flags & FCP_RESID_UNDER) - scsi_set_resid(cmnd, rsp->fcp_resid); + scsi_set_resid(cmnd, be32_to_cpu(rsp->fcp_resid)); else scsi_set_resid(cmnd, 0); @@ -1540,12 +1541,13 @@ static void ibmvfc_scsi_done(struct ibmvfc_event *evt) cmnd->result = ibmvfc_get_err_result(vfc_cmd); if (rsp->flags & FCP_RSP_LEN_VALID) - rsp_len = rsp->fcp_rsp_len; + rsp_len = be32_to_cpu(rsp->fcp_rsp_len); if ((sense_len + rsp_len) > SCSI_SENSE_BUFFERSIZE) sense_len = SCSI_SENSE_BUFFERSIZE - rsp_len; if ((rsp->flags & FCP_SNS_LEN_VALID) && rsp->fcp_sense_len && rsp_len <= 8) memcpy(cmnd->sense_buffer, rsp->data.sense + rsp_len, sense_len); - if ((vfc_cmd->status & IBMVFC_VIOS_FAILURE) && (vfc_cmd->error == IBMVFC_PLOGI_REQUIRED)) + if ((be16_to_cpu(vfc_cmd->status) & IBMVFC_VIOS_FAILURE) && + (be16_to_cpu(vfc_cmd->error) == IBMVFC_PLOGI_REQUIRED)) ibmvfc_relogin(cmnd->device); if (!cmnd->result && (!scsi_get_resid(cmnd) || (rsp->flags & FCP_RESID_OVER))) @@ -1630,19 +1632,19 @@ static int ibmvfc_queuecommand_lck(struct scsi_cmnd *cmnd, cmnd->scsi_done = done; vfc_cmd = &evt->iu.cmd; memset(vfc_cmd, 0, sizeof(*vfc_cmd)); - vfc_cmd->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp); - vfc_cmd->resp.len = sizeof(vfc_cmd->rsp); - vfc_cmd->frame_type = IBMVFC_SCSI_FCP_TYPE; - vfc_cmd->payload_len = sizeof(vfc_cmd->iu); - vfc_cmd->resp_len = sizeof(vfc_cmd->rsp); - vfc_cmd->cancel_key = (unsigned long)cmnd->device->hostdata; - vfc_cmd->tgt_scsi_id = rport->port_id; - vfc_cmd->iu.xfer_len = scsi_bufflen(cmnd); + vfc_cmd->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_cmd, rsp)); + vfc_cmd->resp.len = cpu_to_be32(sizeof(vfc_cmd->rsp)); + vfc_cmd->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE); + vfc_cmd->payload_len = cpu_to_be32(sizeof(vfc_cmd->iu)); + vfc_cmd->resp_len = cpu_to_be32(sizeof(vfc_cmd->rsp)); + vfc_cmd->cancel_key = cpu_to_be32((unsigned long)cmnd->device->hostdata); + vfc_cmd->tgt_scsi_id = cpu_to_be64(rport->port_id); + vfc_cmd->iu.xfer_len = cpu_to_be32(scsi_bufflen(cmnd)); int_to_scsilun(cmnd->device->lun, &vfc_cmd->iu.lun); memcpy(vfc_cmd->iu.cdb, cmnd->cmnd, cmnd->cmd_len); if (scsi_populate_tag_msg(cmnd, tag)) { - vfc_cmd->task_tag = tag[1]; + vfc_cmd->task_tag = cpu_to_be64(tag[1]); switch (tag[0]) { case MSG_SIMPLE_TAG: vfc_cmd->iu.pri_task_attr = IBMVFC_SIMPLE_TASK; @@ -1732,12 +1734,12 @@ static int ibmvfc_bsg_timeout(struct fc_bsg_job *job) tmf = &evt->iu.tmf; memset(tmf, 0, sizeof(*tmf)); - tmf->common.version = 1; - tmf->common.opcode = IBMVFC_TMF_MAD; - tmf->common.length = sizeof(*tmf); - tmf->scsi_id = port_id; - tmf->cancel_key = IBMVFC_PASSTHRU_CANCEL_KEY; - tmf->my_cancel_key = IBMVFC_INTERNAL_CANCEL_KEY; + tmf->common.version = cpu_to_be32(1); + tmf->common.opcode = cpu_to_be32(IBMVFC_TMF_MAD); + tmf->common.length = cpu_to_be16(sizeof(*tmf)); + tmf->scsi_id = cpu_to_be64(port_id); + tmf->cancel_key = cpu_to_be32(IBMVFC_PASSTHRU_CANCEL_KEY); + tmf->my_cancel_key = cpu_to_be32(IBMVFC_INTERNAL_CANCEL_KEY); rc = ibmvfc_send_event(evt, vhost, default_timeout); if (rc != 0) { @@ -1789,10 +1791,10 @@ static int ibmvfc_bsg_plogi(struct ibmvfc_host *vhost, unsigned int port_id) ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_MAD_FORMAT); plogi = &evt->iu.plogi; memset(plogi, 0, sizeof(*plogi)); - plogi->common.version = 1; - plogi->common.opcode = IBMVFC_PORT_LOGIN; - plogi->common.length = sizeof(*plogi); - plogi->scsi_id = port_id; + plogi->common.version = cpu_to_be32(1); + plogi->common.opcode = cpu_to_be32(IBMVFC_PORT_LOGIN); + plogi->common.length = cpu_to_be16(sizeof(*plogi)); + plogi->scsi_id = cpu_to_be64(port_id); evt->sync_iu = &rsp_iu; init_completion(&evt->comp); @@ -1904,26 +1906,26 @@ static int ibmvfc_bsg_request(struct fc_bsg_job *job) mad = &evt->iu.passthru; memset(mad, 0, sizeof(*mad)); - mad->common.version = 1; - mad->common.opcode = IBMVFC_PASSTHRU; - mad->common.length = sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu); - - mad->cmd_ioba.va = (u64)evt->crq.ioba + - offsetof(struct ibmvfc_passthru_mad, iu); - mad->cmd_ioba.len = sizeof(mad->iu); - - mad->iu.cmd_len = job->request_payload.payload_len; - mad->iu.rsp_len = job->reply_payload.payload_len; - mad->iu.flags = fc_flags; - mad->iu.cancel_key = IBMVFC_PASSTHRU_CANCEL_KEY; - - mad->iu.cmd.va = sg_dma_address(job->request_payload.sg_list); - mad->iu.cmd.len = sg_dma_len(job->request_payload.sg_list); - mad->iu.rsp.va = sg_dma_address(job->reply_payload.sg_list); - mad->iu.rsp.len = sg_dma_len(job->reply_payload.sg_list); - mad->iu.scsi_id = port_id; - mad->iu.tag = (u64)evt; - rsp_len = mad->iu.rsp.len; + mad->common.version = cpu_to_be32(1); + mad->common.opcode = cpu_to_be32(IBMVFC_PASSTHRU); + mad->common.length = cpu_to_be16(sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu)); + + mad->cmd_ioba.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + + offsetof(struct ibmvfc_passthru_mad, iu)); + mad->cmd_ioba.len = cpu_to_be32(sizeof(mad->iu)); + + mad->iu.cmd_len = cpu_to_be32(job->request_payload.payload_len); + mad->iu.rsp_len = cpu_to_be32(job->reply_payload.payload_len); + mad->iu.flags = cpu_to_be32(fc_flags); + mad->iu.cancel_key = cpu_to_be32(IBMVFC_PASSTHRU_CANCEL_KEY); + + mad->iu.cmd.va = cpu_to_be64(sg_dma_address(job->request_payload.sg_list)); + mad->iu.cmd.len = cpu_to_be32(sg_dma_len(job->request_payload.sg_list)); + mad->iu.rsp.va = cpu_to_be64(sg_dma_address(job->reply_payload.sg_list)); + mad->iu.rsp.len = cpu_to_be32(sg_dma_len(job->reply_payload.sg_list)); + mad->iu.scsi_id = cpu_to_be64(port_id); + mad->iu.tag = cpu_to_be64((u64)evt); + rsp_len = be32_to_cpu(mad->iu.rsp.len); evt->sync_iu = &rsp_iu; init_completion(&evt->comp); @@ -1986,15 +1988,15 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) tmf = &evt->iu.cmd; memset(tmf, 0, sizeof(*tmf)); - tmf->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp); - tmf->resp.len = sizeof(tmf->rsp); - tmf->frame_type = IBMVFC_SCSI_FCP_TYPE; - tmf->payload_len = sizeof(tmf->iu); - tmf->resp_len = sizeof(tmf->rsp); - tmf->cancel_key = (unsigned long)sdev->hostdata; - tmf->tgt_scsi_id = rport->port_id; + tmf->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_cmd, rsp)); + tmf->resp.len = cpu_to_be32(sizeof(tmf->rsp)); + tmf->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE); + tmf->payload_len = cpu_to_be32(sizeof(tmf->iu)); + tmf->resp_len = cpu_to_be32(sizeof(tmf->rsp)); + tmf->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata); + tmf->tgt_scsi_id = cpu_to_be64(rport->port_id); int_to_scsilun(sdev->lun, &tmf->iu.lun); - tmf->flags = (IBMVFC_NO_MEM_DESC | IBMVFC_TMF); + tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF)); tmf->iu.tmf_flags = type; evt->sync_iu = &rsp_iu; @@ -2020,8 +2022,8 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc) rsp_code = fc_rsp->data.info.rsp_code; sdev_printk(KERN_ERR, sdev, "%s reset failed: %s (%x:%x) " - "flags: %x fcp_rsp: %x, scsi_status: %x\n", - desc, ibmvfc_get_cmd_error(rsp_iu.cmd.status, rsp_iu.cmd.error), + "flags: %x fcp_rsp: %x, scsi_status: %x\n", desc, + ibmvfc_get_cmd_error(be16_to_cpu(rsp_iu.cmd.status), be16_to_cpu(rsp_iu.cmd.error)), rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code, fc_rsp->scsi_status); rsp_rc = -EIO; @@ -2185,19 +2187,19 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type) tmf = &evt->iu.tmf; memset(tmf, 0, sizeof(*tmf)); - tmf->common.version = 1; - tmf->common.opcode = IBMVFC_TMF_MAD; - tmf->common.length = sizeof(*tmf); - tmf->scsi_id = rport->port_id; + tmf->common.version = cpu_to_be32(1); + tmf->common.opcode = cpu_to_be32(IBMVFC_TMF_MAD); + tmf->common.length = cpu_to_be16(sizeof(*tmf)); + tmf->scsi_id = cpu_to_be64(rport->port_id); int_to_scsilun(sdev->lun, &tmf->lun); - if (!(vhost->login_buf->resp.capabilities & IBMVFC_CAN_SUPPRESS_ABTS)) + if (!(be64_to_cpu(vhost->login_buf->resp.capabilities) & IBMVFC_CAN_SUPPRESS_ABTS)) type &= ~IBMVFC_TMF_SUPPRESS_ABTS; if (vhost->state == IBMVFC_ACTIVE) - tmf->flags = (type | IBMVFC_TMF_LUA_VALID); + tmf->flags = cpu_to_be32((type | IBMVFC_TMF_LUA_VALID)); else - tmf->flags = ((type & IBMVFC_TMF_SUPPRESS_ABTS) | IBMVFC_TMF_LUA_VALID); - tmf->cancel_key = (unsigned long)sdev->hostdata; - tmf->my_cancel_key = (unsigned long)starget->hostdata; + tmf->flags = cpu_to_be32(((type & IBMVFC_TMF_SUPPRESS_ABTS) | IBMVFC_TMF_LUA_VALID)); + tmf->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata); + tmf->my_cancel_key = cpu_to_be32((unsigned long)starget->hostdata); evt->sync_iu = &rsp; init_completion(&evt->comp); @@ -2217,7 +2219,7 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type) sdev_printk(KERN_INFO, sdev, "Cancelling outstanding commands.\n"); wait_for_completion(&evt->comp); - status = rsp.mad_common.status; + status = be16_to_cpu(rsp.mad_common.status); spin_lock_irqsave(vhost->host->host_lock, flags); ibmvfc_free_event(evt); spin_unlock_irqrestore(vhost->host->host_lock, flags); @@ -2252,7 +2254,7 @@ static int ibmvfc_match_key(struct ibmvfc_event *evt, void *key) unsigned long cancel_key = (unsigned long)key; if (evt->crq.format == IBMVFC_CMD_FORMAT && - evt->iu.cmd.cancel_key == cancel_key) + be32_to_cpu(evt->iu.cmd.cancel_key) == cancel_key) return 1; return 0; } @@ -2316,15 +2318,15 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev) tmf = &evt->iu.cmd; memset(tmf, 0, sizeof(*tmf)); - tmf->resp.va = (u64)evt->crq.ioba + offsetof(struct ibmvfc_cmd, rsp); - tmf->resp.len = sizeof(tmf->rsp); - tmf->frame_type = IBMVFC_SCSI_FCP_TYPE; - tmf->payload_len = sizeof(tmf->iu); - tmf->resp_len = sizeof(tmf->rsp); - tmf->cancel_key = (unsigned long)sdev->hostdata; - tmf->tgt_scsi_id = rport->port_id; + tmf->resp.va = cpu_to_be64(be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_cmd, rsp)); + tmf->resp.len = cpu_to_be32(sizeof(tmf->rsp)); + tmf->frame_type = cpu_to_be32(IBMVFC_SCSI_FCP_TYPE); + tmf->payload_len = cpu_to_be32(sizeof(tmf->iu)); + tmf->resp_len = cpu_to_be32(sizeof(tmf->rsp)); + tmf->cancel_key = cpu_to_be32((unsigned long)sdev->hostdata); + tmf->tgt_scsi_id = cpu_to_be64(rport->port_id); int_to_scsilun(sdev->lun, &tmf->iu.lun); - tmf->flags = (IBMVFC_NO_MEM_DESC | IBMVFC_TMF); + tmf->flags = cpu_to_be16((IBMVFC_NO_MEM_DESC | IBMVFC_TMF)); tmf->iu.tmf_flags = IBMVFC_ABORT_TASK_SET; evt->sync_iu = &rsp_iu; @@ -2380,7 +2382,7 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev) sdev_printk(KERN_ERR, sdev, "Abort failed: %s (%x:%x) " "flags: %x fcp_rsp: %x, scsi_status: %x\n", - ibmvfc_get_cmd_error(rsp_iu.cmd.status, rsp_iu.cmd.error), + ibmvfc_get_cmd_error(be16_to_cpu(rsp_iu.cmd.status), be16_to_cpu(rsp_iu.cmd.error)), rsp_iu.cmd.status, rsp_iu.cmd.error, fc_rsp->flags, rsp_code, fc_rsp->scsi_status); rsp_rc = -EIO; @@ -2641,14 +2643,14 @@ static const char *ibmvfc_get_link_state(enum ibmvfc_ae_link_state state) static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq, struct ibmvfc_host *vhost) { - const struct ibmvfc_async_desc *desc = ibmvfc_get_ae_desc(crq->event); + const struct ibmvfc_async_desc *desc = ibmvfc_get_ae_desc(be64_to_cpu(crq->event)); struct ibmvfc_target *tgt; ibmvfc_log(vhost, desc->log_level, "%s event received. scsi_id: %llx, wwpn: %llx," " node_name: %llx%s\n", desc->desc, crq->scsi_id, crq->wwpn, crq->node_name, ibmvfc_get_link_state(crq->link_state)); - switch (crq->event) { + switch (be64_to_cpu(crq->event)) { case IBMVFC_AE_RESUME: switch (crq->link_state) { case IBMVFC_AE_LS_LINK_DOWN: @@ -2691,15 +2693,15 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq, list_for_each_entry(tgt, &vhost->targets, queue) { if (!crq->scsi_id && !crq->wwpn && !crq->node_name) break; - if (crq->scsi_id && tgt->scsi_id != crq->scsi_id) + if (crq->scsi_id && cpu_to_be64(tgt->scsi_id) != crq->scsi_id) continue; - if (crq->wwpn && tgt->ids.port_name != crq->wwpn) + if (crq->wwpn && cpu_to_be64(tgt->ids.port_name) != crq->wwpn) continue; - if (crq->node_name && tgt->ids.node_name != crq->node_name) + if (crq->node_name && cpu_to_be64(tgt->ids.node_name) != crq->node_name) continue; - if (tgt->need_login && crq->event == IBMVFC_AE_ELS_LOGO) + if (tgt->need_login && be64_to_cpu(crq->event) == IBMVFC_AE_ELS_LOGO) tgt->logo_rcvd = 1; - if (!tgt->need_login || crq->event == IBMVFC_AE_ELS_PLOGI) { + if (!tgt->need_login || be64_to_cpu(crq->event) == IBMVFC_AE_ELS_PLOGI) { ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); ibmvfc_reinit_host(vhost); } @@ -2730,7 +2732,7 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq, static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost) { long rc; - struct ibmvfc_event *evt = (struct ibmvfc_event *)crq->ioba; + struct ibmvfc_event *evt = (struct ibmvfc_event *)be64_to_cpu(crq->ioba); switch (crq->valid) { case IBMVFC_CRQ_INIT_RSP: @@ -3336,7 +3338,7 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt) struct ibmvfc_host *vhost = evt->vhost; struct ibmvfc_process_login *rsp = &evt->xfer_iu->prli; struct ibmvfc_prli_svc_parms *parms = &rsp->parms; - u32 status = rsp->common.status; + u32 status = be16_to_cpu(rsp->common.status); int index, level = IBMVFC_DEFAULT_LOG_LEVEL; vhost->discovery_threads--; @@ -3347,14 +3349,14 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt) parms->type, parms->flags, parms->service_parms); if (parms->type == IBMVFC_SCSI_FCP_TYPE) { - index = ibmvfc_get_prli_rsp(parms->flags); + index = ibmvfc_get_prli_rsp(be16_to_cpu(parms->flags)); if (prli_rsp[index].logged_in) { - if (parms->flags & IBMVFC_PRLI_EST_IMG_PAIR) { + if (be16_to_cpu(parms->flags) & IBMVFC_PRLI_EST_IMG_PAIR) { tgt->need_login = 0; tgt->ids.roles = 0; - if (parms->service_parms & IBMVFC_PRLI_TARGET_FUNC) + if (be32_to_cpu(parms->service_parms) & IBMVFC_PRLI_TARGET_FUNC) tgt->ids.roles |= FC_PORT_ROLE_FCP_TARGET; - if (parms->service_parms & IBMVFC_PRLI_INITIATOR_FUNC) + if (be32_to_cpu(parms->service_parms) & IBMVFC_PRLI_INITIATOR_FUNC) tgt->ids.roles |= FC_PORT_ROLE_FCP_INITIATOR; tgt->add_rport = 1; } else @@ -3373,17 +3375,18 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt) break; case IBMVFC_MAD_FAILED: default: - if ((rsp->status & IBMVFC_VIOS_FAILURE) && rsp->error == IBMVFC_PLOGI_REQUIRED) + if ((be16_to_cpu(rsp->status) & IBMVFC_VIOS_FAILURE) && + be16_to_cpu(rsp->error) == IBMVFC_PLOGI_REQUIRED) level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi); else if (tgt->logo_rcvd) level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi); - else if (ibmvfc_retry_cmd(rsp->status, rsp->error)) + else if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error))) level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_prli); else ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); tgt_log(tgt, level, "Process Login failed: %s (%x:%x) rc=0x%02X\n", - ibmvfc_get_cmd_error(rsp->status, rsp->error), + ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), rsp->status, rsp->error, status); break; }; @@ -3414,14 +3417,14 @@ static void ibmvfc_tgt_send_prli(struct ibmvfc_target *tgt) evt->tgt = tgt; prli = &evt->iu.prli; memset(prli, 0, sizeof(*prli)); - prli->common.version = 1; - prli->common.opcode = IBMVFC_PROCESS_LOGIN; - prli->common.length = sizeof(*prli); - prli->scsi_id = tgt->scsi_id; + prli->common.version = cpu_to_be32(1); + prli->common.opcode = cpu_to_be32(IBMVFC_PROCESS_LOGIN); + prli->common.length = cpu_to_be16(sizeof(*prli)); + prli->scsi_id = cpu_to_be64(tgt->scsi_id); prli->parms.type = IBMVFC_SCSI_FCP_TYPE; - prli->parms.flags = IBMVFC_PRLI_EST_IMG_PAIR; - prli->parms.service_parms = IBMVFC_PRLI_INITIATOR_FUNC; + prli->parms.flags = cpu_to_be16(IBMVFC_PRLI_EST_IMG_PAIR); + prli->parms.service_parms = cpu_to_be32(IBMVFC_PRLI_INITIATOR_FUNC); ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT); if (ibmvfc_send_event(evt, vhost, default_timeout)) { @@ -3442,7 +3445,7 @@ static void ibmvfc_tgt_plogi_done(struct ibmvfc_event *evt) struct ibmvfc_target *tgt = evt->tgt; struct ibmvfc_host *vhost = evt->vhost; struct ibmvfc_port_login *rsp = &evt->xfer_iu->plogi; - u32 status = rsp->common.status; + u32 status = be16_to_cpu(rsp->common.status); int level = IBMVFC_DEFAULT_LOG_LEVEL; vhost->discovery_threads--; @@ -3472,15 +3475,15 @@ static void ibmvfc_tgt_plogi_done(struct ibmvfc_event *evt) break; case IBMVFC_MAD_FAILED: default: - if (ibmvfc_retry_cmd(rsp->status, rsp->error)) + if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error))) level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_plogi); else ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); tgt_log(tgt, level, "Port Login failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n", - ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error, - ibmvfc_get_fc_type(rsp->fc_type), rsp->fc_type, - ibmvfc_get_ls_explain(rsp->fc_explain), rsp->fc_explain, status); + ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), rsp->status, rsp->error, + ibmvfc_get_fc_type(be16_to_cpu(rsp->fc_type)), rsp->fc_type, + ibmvfc_get_ls_explain(be16_to_cpu(rsp->fc_explain)), rsp->fc_explain, status); break; }; @@ -3512,10 +3515,10 @@ static void ibmvfc_tgt_send_plogi(struct ibmvfc_target *tgt) evt->tgt = tgt; plogi = &evt->iu.plogi; memset(plogi, 0, sizeof(*plogi)); - plogi->common.version = 1; - plogi->common.opcode = IBMVFC_PORT_LOGIN; - plogi->common.length = sizeof(*plogi); - plogi->scsi_id = tgt->scsi_id; + plogi->common.version = cpu_to_be32(1); + plogi->common.opcode = cpu_to_be32(IBMVFC_PORT_LOGIN); + plogi->common.length = cpu_to_be16(sizeof(*plogi)); + plogi->scsi_id = cpu_to_be64(tgt->scsi_id); if (ibmvfc_send_event(evt, vhost, default_timeout)) { vhost->discovery_threads--; @@ -3535,7 +3538,7 @@ static void ibmvfc_tgt_implicit_logout_done(struct ibmvfc_event *evt) struct ibmvfc_target *tgt = evt->tgt; struct ibmvfc_host *vhost = evt->vhost; struct ibmvfc_implicit_logout *rsp = &evt->xfer_iu->implicit_logout; - u32 status = rsp->common.status; + u32 status = be16_to_cpu(rsp->common.status); vhost->discovery_threads--; ibmvfc_free_event(evt); @@ -3585,10 +3588,10 @@ static void ibmvfc_tgt_implicit_logout(struct ibmvfc_target *tgt) evt->tgt = tgt; mad = &evt->iu.implicit_logout; memset(mad, 0, sizeof(*mad)); - mad->common.version = 1; - mad->common.opcode = IBMVFC_IMPLICIT_LOGOUT; - mad->common.length = sizeof(*mad); - mad->old_scsi_id = tgt->scsi_id; + mad->common.version = cpu_to_be32(1); + mad->common.opcode = cpu_to_be32(IBMVFC_IMPLICIT_LOGOUT); + mad->common.length = cpu_to_be16(sizeof(*mad)); + mad->old_scsi_id = cpu_to_be64(tgt->scsi_id); ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT); if (ibmvfc_send_event(evt, vhost, default_timeout)) { @@ -3616,7 +3619,7 @@ static int ibmvfc_adisc_needs_plogi(struct ibmvfc_passthru_mad *mad, if (memcmp(&mad->fc_iu.response[4], &tgt->ids.node_name, sizeof(tgt->ids.node_name))) return 1; - if (mad->fc_iu.response[6] != tgt->scsi_id) + if (be32_to_cpu(mad->fc_iu.response[6]) != tgt->scsi_id) return 1; return 0; } @@ -3631,7 +3634,7 @@ static void ibmvfc_tgt_adisc_done(struct ibmvfc_event *evt) struct ibmvfc_target *tgt = evt->tgt; struct ibmvfc_host *vhost = evt->vhost; struct ibmvfc_passthru_mad *mad = &evt->xfer_iu->passthru; - u32 status = mad->common.status; + u32 status = be16_to_cpu(mad->common.status); u8 fc_reason, fc_explain; vhost->discovery_threads--; @@ -3649,10 +3652,10 @@ static void ibmvfc_tgt_adisc_done(struct ibmvfc_event *evt) case IBMVFC_MAD_FAILED: default: ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); - fc_reason = (mad->fc_iu.response[1] & 0x00ff0000) >> 16; - fc_explain = (mad->fc_iu.response[1] & 0x0000ff00) >> 8; + fc_reason = (be32_to_cpu(mad->fc_iu.response[1]) & 0x00ff0000) >> 16; + fc_explain = (be32_to_cpu(mad->fc_iu.response[1]) & 0x0000ff00) >> 8; tgt_info(tgt, "ADISC failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n", - ibmvfc_get_cmd_error(mad->iu.status, mad->iu.error), + ibmvfc_get_cmd_error(be16_to_cpu(mad->iu.status), be16_to_cpu(mad->iu.error)), mad->iu.status, mad->iu.error, ibmvfc_get_fc_type(fc_reason), fc_reason, ibmvfc_get_ls_explain(fc_explain), fc_explain, status); @@ -3674,22 +3677,22 @@ static void ibmvfc_init_passthru(struct ibmvfc_event *evt) struct ibmvfc_passthru_mad *mad = &evt->iu.passthru; memset(mad, 0, sizeof(*mad)); - mad->common.version = 1; - mad->common.opcode = IBMVFC_PASSTHRU; - mad->common.length = sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu); - mad->cmd_ioba.va = (u64)evt->crq.ioba + - offsetof(struct ibmvfc_passthru_mad, iu); - mad->cmd_ioba.len = sizeof(mad->iu); - mad->iu.cmd_len = sizeof(mad->fc_iu.payload); - mad->iu.rsp_len = sizeof(mad->fc_iu.response); - mad->iu.cmd.va = (u64)evt->crq.ioba + + mad->common.version = cpu_to_be32(1); + mad->common.opcode = cpu_to_be32(IBMVFC_PASSTHRU); + mad->common.length = cpu_to_be16(sizeof(*mad) - sizeof(mad->fc_iu) - sizeof(mad->iu)); + mad->cmd_ioba.va = cpu_to_be64((u64)be64_to_cpu(evt->crq.ioba) + + offsetof(struct ibmvfc_passthru_mad, iu)); + mad->cmd_ioba.len = cpu_to_be32(sizeof(mad->iu)); + mad->iu.cmd_len = cpu_to_be32(sizeof(mad->fc_iu.payload)); + mad->iu.rsp_len = cpu_to_be32(sizeof(mad->fc_iu.response)); + mad->iu.cmd.va = cpu_to_be64((u64)be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_passthru_mad, fc_iu) + - offsetof(struct ibmvfc_passthru_fc_iu, payload); - mad->iu.cmd.len = sizeof(mad->fc_iu.payload); - mad->iu.rsp.va = (u64)evt->crq.ioba + + offsetof(struct ibmvfc_passthru_fc_iu, payload)); + mad->iu.cmd.len = cpu_to_be32(sizeof(mad->fc_iu.payload)); + mad->iu.rsp.va = cpu_to_be64((u64)be64_to_cpu(evt->crq.ioba) + offsetof(struct ibmvfc_passthru_mad, fc_iu) + - offsetof(struct ibmvfc_passthru_fc_iu, response); - mad->iu.rsp.len = sizeof(mad->fc_iu.response); + offsetof(struct ibmvfc_passthru_fc_iu, response)); + mad->iu.rsp.len = cpu_to_be32(sizeof(mad->fc_iu.response)); } /** @@ -3748,11 +3751,11 @@ static void ibmvfc_adisc_timeout(struct ibmvfc_target *tgt) evt->tgt = tgt; tmf = &evt->iu.tmf; memset(tmf, 0, sizeof(*tmf)); - tmf->common.version = 1; - tmf->common.opcode = IBMVFC_TMF_MAD; - tmf->common.length = sizeof(*tmf); - tmf->scsi_id = tgt->scsi_id; - tmf->cancel_key = tgt->cancel_key; + tmf->common.version = cpu_to_be32(1); + tmf->common.opcode = cpu_to_be32(IBMVFC_TMF_MAD); + tmf->common.length = cpu_to_be16(sizeof(*tmf)); + tmf->scsi_id = cpu_to_be64(tgt->scsi_id); + tmf->cancel_key = cpu_to_be32(tgt->cancel_key); rc = ibmvfc_send_event(evt, vhost, default_timeout); @@ -3794,16 +3797,16 @@ static void ibmvfc_tgt_adisc(struct ibmvfc_target *tgt) ibmvfc_init_passthru(evt); mad = &evt->iu.passthru; - mad->iu.flags = IBMVFC_FC_ELS; - mad->iu.scsi_id = tgt->scsi_id; - mad->iu.cancel_key = tgt->cancel_key; + mad->iu.flags = cpu_to_be32(IBMVFC_FC_ELS); + mad->iu.scsi_id = cpu_to_be64(tgt->scsi_id); + mad->iu.cancel_key = cpu_to_be32(tgt->cancel_key); - mad->fc_iu.payload[0] = IBMVFC_ADISC; + mad->fc_iu.payload[0] = cpu_to_be32(IBMVFC_ADISC); memcpy(&mad->fc_iu.payload[2], &vhost->login_buf->resp.port_name, sizeof(vhost->login_buf->resp.port_name)); memcpy(&mad->fc_iu.payload[4], &vhost->login_buf->resp.node_name, sizeof(vhost->login_buf->resp.node_name)); - mad->fc_iu.payload[6] = vhost->login_buf->resp.scsi_id & 0x00ffffff; + mad->fc_iu.payload[6] = cpu_to_be32(be64_to_cpu(vhost->login_buf->resp.scsi_id) & 0x00ffffff); if (timer_pending(&tgt->timer)) mod_timer(&tgt->timer, jiffies + (IBMVFC_ADISC_TIMEOUT * HZ)); @@ -3834,7 +3837,7 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt) struct ibmvfc_target *tgt = evt->tgt; struct ibmvfc_host *vhost = evt->vhost; struct ibmvfc_query_tgt *rsp = &evt->xfer_iu->query_tgt; - u32 status = rsp->common.status; + u32 status = be16_to_cpu(rsp->common.status); int level = IBMVFC_DEFAULT_LOG_LEVEL; vhost->discovery_threads--; @@ -3842,8 +3845,8 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt) switch (status) { case IBMVFC_MAD_SUCCESS: tgt_dbg(tgt, "Query Target succeeded\n"); - tgt->new_scsi_id = rsp->scsi_id; - if (rsp->scsi_id != tgt->scsi_id) + tgt->new_scsi_id = be64_to_cpu(rsp->scsi_id); + if (be64_to_cpu(rsp->scsi_id) != tgt->scsi_id) ibmvfc_init_tgt(tgt, ibmvfc_tgt_implicit_logout); else ibmvfc_init_tgt(tgt, ibmvfc_tgt_adisc); @@ -3855,19 +3858,20 @@ static void ibmvfc_tgt_query_target_done(struct ibmvfc_event *evt) break; case IBMVFC_MAD_FAILED: default: - if ((rsp->status & IBMVFC_FABRIC_MAPPED) == IBMVFC_FABRIC_MAPPED && - rsp->error == IBMVFC_UNABLE_TO_PERFORM_REQ && - rsp->fc_explain == IBMVFC_PORT_NAME_NOT_REG) + if ((be16_to_cpu(rsp->status) & IBMVFC_FABRIC_MAPPED) == IBMVFC_FABRIC_MAPPED && + be16_to_cpu(rsp->error) == IBMVFC_UNABLE_TO_PERFORM_REQ && + be16_to_cpu(rsp->fc_explain) == IBMVFC_PORT_NAME_NOT_REG) ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); - else if (ibmvfc_retry_cmd(rsp->status, rsp->error)) + else if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error))) level += ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_query_target); else ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT); tgt_log(tgt, level, "Query Target failed: %s (%x:%x) %s (%x) %s (%x) rc=0x%02X\n", - ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error, - ibmvfc_get_fc_type(rsp->fc_type), rsp->fc_type, - ibmvfc_get_gs_explain(rsp->fc_explain), rsp->fc_explain, status); + ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), + rsp->status, rsp->error, ibmvfc_get_fc_type(be16_to_cpu(rsp->fc_type)), + rsp->fc_type, ibmvfc_get_gs_explain(be16_to_cpu(rsp->fc_explain)), + rsp->fc_explain, status); break; }; @@ -3897,10 +3901,10 @@ static void ibmvfc_tgt_query_target(struct ibmvfc_target *tgt) ibmvfc_init_event(evt, ibmvfc_tgt_query_target_done, IBMVFC_MAD_FORMAT); query_tgt = &evt->iu.query_tgt; memset(query_tgt, 0, sizeof(*query_tgt)); - query_tgt->common.version = 1; - query_tgt->common.opcode = IBMVFC_QUERY_TARGET; - query_tgt->common.length = sizeof(*query_tgt); - query_tgt->wwpn = tgt->ids.port_name; + query_tgt->common.version = cpu_to_be32(1); + query_tgt->common.opcode = cpu_to_be32(IBMVFC_QUERY_TARGET); + query_tgt->common.length = cpu_to_be16(sizeof(*query_tgt)); + query_tgt->wwpn = cpu_to_be64(tgt->ids.port_name); ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT); if (ibmvfc_send_event(evt, vhost, default_timeout)) { @@ -3971,7 +3975,8 @@ static int ibmvfc_alloc_targets(struct ibmvfc_host *vhost) for (i = 0, rc = 0; !rc && i < vhost->num_targets; i++) rc = ibmvfc_alloc_target(vhost, - vhost->disc_buf->scsi_id[i] & IBMVFC_DISC_TGT_SCSI_ID_MASK); + be32_to_cpu(vhost->disc_buf->scsi_id[i]) & + IBMVFC_DISC_TGT_SCSI_ID_MASK); return rc; } @@ -3985,19 +3990,20 @@ static void ibmvfc_discover_targets_done(struct ibmvfc_event *evt) { struct ibmvfc_host *vhost = evt->vhost; struct ibmvfc_discover_targets *rsp = &evt->xfer_iu->discover_targets; - u32 mad_status = rsp->common.status; + u32 mad_status = be16_to_cpu(rsp->common.status); int level = IBMVFC_DEFAULT_LOG_LEVEL; switch (mad_status) { case IBMVFC_MAD_SUCCESS: ibmvfc_dbg(vhost, "Discover Targets succeeded\n"); - vhost->num_targets = rsp->num_written; + vhost->num_targets = be32_to_cpu(rsp->num_written); ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_ALLOC_TGTS); break; case IBMVFC_MAD_FAILED: level += ibmvfc_retry_host_init(vhost); ibmvfc_log(vhost, level, "Discover Targets failed: %s (%x:%x)\n", - ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error); + ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), + rsp->status, rsp->error); break; case IBMVFC_MAD_DRIVER_FAILED: break; @@ -4024,12 +4030,12 @@ static void ibmvfc_discover_targets(struct ibmvfc_host *vhost) ibmvfc_init_event(evt, ibmvfc_discover_targets_done, IBMVFC_MAD_FORMAT); mad = &evt->iu.discover_targets; memset(mad, 0, sizeof(*mad)); - mad->common.version = 1; - mad->common.opcode = IBMVFC_DISC_TARGETS; - mad->common.length = sizeof(*mad); - mad->bufflen = vhost->disc_buf_sz; - mad->buffer.va = vhost->disc_buf_dma; - mad->buffer.len = vhost->disc_buf_sz; + mad->common.version = cpu_to_be32(1); + mad->common.opcode = cpu_to_be32(IBMVFC_DISC_TARGETS); + mad->common.length = cpu_to_be16(sizeof(*mad)); + mad->bufflen = cpu_to_be32(vhost->disc_buf_sz); + mad->buffer.va = cpu_to_be64(vhost->disc_buf_dma); + mad->buffer.len = cpu_to_be32(vhost->disc_buf_sz); ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT_WAIT); if (!ibmvfc_send_event(evt, vhost, default_timeout)) @@ -4046,7 +4052,7 @@ static void ibmvfc_discover_targets(struct ibmvfc_host *vhost) static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt) { struct ibmvfc_host *vhost = evt->vhost; - u32 mad_status = evt->xfer_iu->npiv_login.common.status; + u32 mad_status = be16_to_cpu(evt->xfer_iu->npiv_login.common.status); struct ibmvfc_npiv_login_resp *rsp = &vhost->login_buf->resp; unsigned int npiv_max_sectors; int level = IBMVFC_DEFAULT_LOG_LEVEL; @@ -4056,12 +4062,13 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt) ibmvfc_free_event(evt); break; case IBMVFC_MAD_FAILED: - if (ibmvfc_retry_cmd(rsp->status, rsp->error)) + if (ibmvfc_retry_cmd(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error))) level += ibmvfc_retry_host_init(vhost); else ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD); ibmvfc_log(vhost, level, "NPIV Login failed: %s (%x:%x)\n", - ibmvfc_get_cmd_error(rsp->status, rsp->error), rsp->status, rsp->error); + ibmvfc_get_cmd_error(be16_to_cpu(rsp->status), be16_to_cpu(rsp->error)), + rsp->status, rsp->error); ibmvfc_free_event(evt); return; case IBMVFC_MAD_CRQ_ERROR: @@ -4078,7 +4085,7 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt) vhost->client_migrated = 0; - if (!(rsp->flags & IBMVFC_NATIVE_FC)) { + if (!(be32_to_cpu(rsp->flags) & IBMVFC_NATIVE_FC)) { dev_err(vhost->dev, "Virtual adapter does not support FC. %x\n", rsp->flags); ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD); @@ -4086,7 +4093,7 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt) return; } - if (rsp->max_cmds <= IBMVFC_NUM_INTERNAL_REQ) { + if (be32_to_cpu(rsp->max_cmds) <= IBMVFC_NUM_INTERNAL_REQ) { dev_err(vhost->dev, "Virtual adapter supported queue depth too small: %d\n", rsp->max_cmds); ibmvfc_link_down(vhost, IBMVFC_LINK_DEAD); @@ -4095,27 +4102,27 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt) } vhost->logged_in = 1; - npiv_max_sectors = min((uint)(rsp->max_dma_len >> 9), IBMVFC_MAX_SECTORS); + npiv_max_sectors = min((uint)(be64_to_cpu(rsp->max_dma_len) >> 9), IBMVFC_MAX_SECTORS); dev_info(vhost->dev, "Host partition: %s, device: %s %s %s max sectors %u\n", rsp->partition_name, rsp->device_name, rsp->port_loc_code, rsp->drc_name, npiv_max_sectors); - fc_host_fabric_name(vhost->host) = rsp->node_name; - fc_host_node_name(vhost->host) = rsp->node_name; - fc_host_port_name(vhost->host) = rsp->port_name; - fc_host_port_id(vhost->host) = rsp->scsi_id; + fc_host_fabric_name(vhost->host) = be64_to_cpu(rsp->node_name); + fc_host_node_name(vhost->host) = be64_to_cpu(rsp->node_name); + fc_host_port_name(vhost->host) = be64_to_cpu(rsp->port_name); + fc_host_port_id(vhost->host) = be64_to_cpu(rsp->scsi_id); fc_host_port_type(vhost->host) = FC_PORTTYPE_NPIV; fc_host_supported_classes(vhost->host) = 0; - if (rsp->service_parms.class1_parms[0] & 0x80000000) + if (be32_to_cpu(rsp->service_parms.class1_parms[0]) & 0x80000000) fc_host_supported_classes(vhost->host) |= FC_COS_CLASS1; - if (rsp->service_parms.class2_parms[0] & 0x80000000) + if (be32_to_cpu(rsp->service_parms.class2_parms[0]) & 0x80000000) fc_host_supported_classes(vhost->host) |= FC_COS_CLASS2; - if (rsp->service_parms.class3_parms[0] & 0x80000000) + if (be32_to_cpu(rsp->service_parms.class3_parms[0]) & 0x80000000) fc_host_supported_classes(vhost->host) |= FC_COS_CLASS3; fc_host_maxframe_size(vhost->host) = - rsp->service_parms.common.bb_rcv_sz & 0x0fff; + be16_to_cpu(rsp->service_parms.common.bb_rcv_sz) & 0x0fff; - vhost->host->can_queue = rsp->max_cmds - IBMVFC_NUM_INTERNAL_REQ; + vhost->host->can_queue = be32_to_cpu(rsp->max_cmds) - IBMVFC_NUM_INTERNAL_REQ; vhost->host->max_sectors = npiv_max_sectors; ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY); wake_up(&vhost->work_wait_q); @@ -4138,11 +4145,11 @@ static void ibmvfc_npiv_login(struct ibmvfc_host *vhost) memcpy(vhost->login_buf, &vhost->login_info, sizeof(vhost->login_info)); mad = &evt->iu.npiv_login; memset(mad, 0, sizeof(struct ibmvfc_npiv_login_mad)); - mad->common.version = 1; - mad->common.opcode = IBMVFC_NPIV_LOGIN; - mad->common.length = sizeof(struct ibmvfc_npiv_login_mad); - mad->buffer.va = vhost->login_buf_dma; - mad->buffer.len = sizeof(*vhost->login_buf); + mad->common.version = cpu_to_be32(1); + mad->common.opcode = cpu_to_be32(IBMVFC_NPIV_LOGIN); + mad->common.length = cpu_to_be16(sizeof(struct ibmvfc_npiv_login_mad)); + mad->buffer.va = cpu_to_be64(vhost->login_buf_dma); + mad->buffer.len = cpu_to_be32(sizeof(*vhost->login_buf)); ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT_WAIT); @@ -4160,7 +4167,7 @@ static void ibmvfc_npiv_login(struct ibmvfc_host *vhost) static void ibmvfc_npiv_logout_done(struct ibmvfc_event *evt) { struct ibmvfc_host *vhost = evt->vhost; - u32 mad_status = evt->xfer_iu->npiv_logout.common.status; + u32 mad_status = be16_to_cpu(evt->xfer_iu->npiv_logout.common.status); ibmvfc_free_event(evt); @@ -4199,9 +4206,9 @@ static void ibmvfc_npiv_logout(struct ibmvfc_host *vhost) mad = &evt->iu.npiv_logout; memset(mad, 0, sizeof(*mad)); - mad->common.version = 1; - mad->common.opcode = IBMVFC_NPIV_LOGOUT; - mad->common.length = sizeof(struct ibmvfc_npiv_logout_mad); + mad->common.version = cpu_to_be32(1); + mad->common.opcode = cpu_to_be32(IBMVFC_NPIV_LOGOUT); + mad->common.length = cpu_to_be16(sizeof(struct ibmvfc_npiv_logout_mad)); ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_LOGO_WAIT); @@ -4343,14 +4350,14 @@ static void ibmvfc_tgt_add_rport(struct ibmvfc_target *tgt) if (rport) { tgt_dbg(tgt, "rport add succeeded\n"); tgt->rport = rport; - rport->maxframe_size = tgt->service_parms.common.bb_rcv_sz & 0x0fff; + rport->maxframe_size = be16_to_cpu(tgt->service_parms.common.bb_rcv_sz) & 0x0fff; rport->supported_classes = 0; tgt->target_id = rport->scsi_target_id; - if (tgt->service_parms.class1_parms[0] & 0x80000000) + if (be32_to_cpu(tgt->service_parms.class1_parms[0]) & 0x80000000) rport->supported_classes |= FC_COS_CLASS1; - if (tgt->service_parms.class2_parms[0] & 0x80000000) + if (be32_to_cpu(tgt->service_parms.class2_parms[0]) & 0x80000000) rport->supported_classes |= FC_COS_CLASS2; - if (tgt->service_parms.class3_parms[0] & 0x80000000) + if (be32_to_cpu(tgt->service_parms.class3_parms[0]) & 0x80000000) rport->supported_classes |= FC_COS_CLASS3; if (rport->rqst_q) blk_queue_max_segments(rport->rqst_q, 1); diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index 017a5290e8c1..8fae03215a85 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h @@ -135,12 +135,12 @@ enum ibmvfc_mad_types { }; struct ibmvfc_mad_common { - u32 version; - u32 reserved; - u32 opcode; - u16 status; - u16 length; - u64 tag; + __be32 version; + __be32 reserved; + __be32 opcode; + __be16 status; + __be16 length; + __be64 tag; }__attribute__((packed, aligned (8))); struct ibmvfc_npiv_login_mad { @@ -155,76 +155,76 @@ struct ibmvfc_npiv_logout_mad { #define IBMVFC_MAX_NAME 256 struct ibmvfc_npiv_login { - u32 ostype; + __be32 ostype; #define IBMVFC_OS_LINUX 0x02 - u32 pad; - u64 max_dma_len; - u32 max_payload; - u32 max_response; - u32 partition_num; - u32 vfc_frame_version; - u16 fcp_version; - u16 flags; + __be32 pad; + __be64 max_dma_len; + __be32 max_payload; + __be32 max_response; + __be32 partition_num; + __be32 vfc_frame_version; + __be16 fcp_version; + __be16 flags; #define IBMVFC_CLIENT_MIGRATED 0x01 #define IBMVFC_FLUSH_ON_HALT 0x02 - u32 max_cmds; - u64 capabilities; + __be32 max_cmds; + __be64 capabilities; #define IBMVFC_CAN_MIGRATE 0x01 - u64 node_name; + __be64 node_name; struct srp_direct_buf async; u8 partition_name[IBMVFC_MAX_NAME]; u8 device_name[IBMVFC_MAX_NAME]; u8 drc_name[IBMVFC_MAX_NAME]; - u64 reserved2[2]; + __be64 reserved2[2]; }__attribute__((packed, aligned (8))); struct ibmvfc_common_svc_parms { - u16 fcph_version; - u16 b2b_credit; - u16 features; - u16 bb_rcv_sz; /* upper nibble is BB_SC_N */ - u32 ratov; - u32 edtov; + __be16 fcph_version; + __be16 b2b_credit; + __be16 features; + __be16 bb_rcv_sz; /* upper nibble is BB_SC_N */ + __be32 ratov; + __be32 edtov; }__attribute__((packed, aligned (4))); struct ibmvfc_service_parms { struct ibmvfc_common_svc_parms common; u8 port_name[8]; u8 node_name[8]; - u32 class1_parms[4]; - u32 class2_parms[4]; - u32 class3_parms[4]; - u32 obsolete[4]; - u32 vendor_version[4]; - u32 services_avail[2]; - u32 ext_len; - u32 reserved[30]; - u32 clk_sync_qos[2]; + __be32 class1_parms[4]; + __be32 class2_parms[4]; + __be32 class3_parms[4]; + __be32 obsolete[4]; + __be32 vendor_version[4]; + __be32 services_avail[2]; + __be32 ext_len; + __be32 reserved[30]; + __be32 clk_sync_qos[2]; }__attribute__((packed, aligned (4))); struct ibmvfc_npiv_login_resp { - u32 version; - u16 status; - u16 error; - u32 flags; + __be32 version; + __be16 status; + __be16 error; + __be32 flags; #define IBMVFC_NATIVE_FC 0x01 - u32 reserved; - u64 capabilities; + __be32 reserved; + __be64 capabilities; #define IBMVFC_CAN_FLUSH_ON_HALT 0x08 #define IBMVFC_CAN_SUPPRESS_ABTS 0x10 - u32 max_cmds; - u32 scsi_id_sz; - u64 max_dma_len; - u64 scsi_id; - u64 port_name; - u64 node_name; - u64 link_speed; + __be32 max_cmds; + __be32 scsi_id_sz; + __be64 max_dma_len; + __be64 scsi_id; + __be64 port_name; + __be64 node_name; + __be64 link_speed; u8 partition_name[IBMVFC_MAX_NAME]; u8 device_name[IBMVFC_MAX_NAME]; u8 port_loc_code[IBMVFC_MAX_NAME]; u8 drc_name[IBMVFC_MAX_NAME]; struct ibmvfc_service_parms service_parms; - u64 reserved2; + __be64 reserved2; }__attribute__((packed, aligned (8))); union ibmvfc_npiv_login_data { @@ -233,20 +233,20 @@ union ibmvfc_npiv_login_data { }__attribute__((packed, aligned (8))); struct ibmvfc_discover_targets_buf { - u32 scsi_id[1]; + __be32 scsi_id[1]; #define IBMVFC_DISC_TGT_SCSI_ID_MASK 0x00ffffff }; struct ibmvfc_discover_targets { struct ibmvfc_mad_common common; struct srp_direct_buf buffer; - u32 flags; - u16 status; - u16 error; - u32 bufflen; - u32 num_avail; - u32 num_written; - u64 reserved[2]; + __be32 flags; + __be16 status; + __be16 error; + __be32 bufflen; + __be32 num_avail; + __be32 num_written; + __be64 reserved[2]; }__attribute__((packed, aligned (8))); enum ibmvfc_fc_reason { @@ -278,32 +278,32 @@ enum ibmvfc_gs_explain { struct ibmvfc_port_login { struct ibmvfc_mad_common common; - u64 scsi_id; - u16 reserved; - u16 fc_service_class; - u32 blksz; - u32 hdr_per_blk; - u16 status; - u16 error; /* also fc_reason */ - u16 fc_explain; - u16 fc_type; - u32 reserved2; + __be64 scsi_id; + __be16 reserved; + __be16 fc_service_class; + __be32 blksz; + __be32 hdr_per_blk; + __be16 status; + __be16 error; /* also fc_reason */ + __be16 fc_explain; + __be16 fc_type; + __be32 reserved2; struct ibmvfc_service_parms service_parms; struct ibmvfc_service_parms service_parms_change; - u64 reserved3[2]; + __be64 reserved3[2]; }__attribute__((packed, aligned (8))); struct ibmvfc_prli_svc_parms { u8 type; #define IBMVFC_SCSI_FCP_TYPE 0x08 u8 type_ext; - u16 flags; + __be16 flags; #define IBMVFC_PRLI_ORIG_PA_VALID 0x8000 #define IBMVFC_PRLI_RESP_PA_VALID 0x4000 #define IBMVFC_PRLI_EST_IMG_PAIR 0x2000 - u32 orig_pa; - u32 resp_pa; - u32 service_parms; + __be32 orig_pa; + __be32 resp_pa; + __be32 service_parms; #define IBMVFC_PRLI_TASK_RETRY 0x00000200 #define IBMVFC_PRLI_RETRY 0x00000100 #define IBMVFC_PRLI_DATA_OVERLAY 0x00000040 @@ -315,47 +315,47 @@ struct ibmvfc_prli_svc_parms { struct ibmvfc_process_login { struct ibmvfc_mad_common common; - u64 scsi_id; + __be64 scsi_id; struct ibmvfc_prli_svc_parms parms; u8 reserved[48]; - u16 status; - u16 error; /* also fc_reason */ - u32 reserved2; - u64 reserved3[2]; + __be16 status; + __be16 error; /* also fc_reason */ + __be32 reserved2; + __be64 reserved3[2]; }__attribute__((packed, aligned (8))); struct ibmvfc_query_tgt { struct ibmvfc_mad_common common; - u64 wwpn; - u64 scsi_id; - u16 status; - u16 error; - u16 fc_explain; - u16 fc_type; - u64 reserved[2]; + __be64 wwpn; + __be64 scsi_id; + __be16 status; + __be16 error; + __be16 fc_explain; + __be16 fc_type; + __be64 reserved[2]; }__attribute__((packed, aligned (8))); struct ibmvfc_implicit_logout { struct ibmvfc_mad_common common; - u64 old_scsi_id; - u64 reserved[2]; + __be64 old_scsi_id; + __be64 reserved[2]; }__attribute__((packed, aligned (8))); struct ibmvfc_tmf { struct ibmvfc_mad_common common; - u64 scsi_id; + __be64 scsi_id; struct scsi_lun lun; - u32 flags; + __be32 flags; #define IBMVFC_TMF_ABORT_TASK 0x02 #define IBMVFC_TMF_ABORT_TASK_SET 0x04 #define IBMVFC_TMF_LUN_RESET 0x10 #define IBMVFC_TMF_TGT_RESET 0x20 #define IBMVFC_TMF_LUA_VALID 0x40 #define IBMVFC_TMF_SUPPRESS_ABTS 0x80 - u32 cancel_key; - u32 my_cancel_key; - u32 pad; - u64 reserved[2]; + __be32 cancel_key; + __be32 my_cancel_key; + __be32 pad; + __be64 reserved[2]; }__attribute__((packed, aligned (8))); enum ibmvfc_fcp_rsp_info_codes { @@ -366,7 +366,7 @@ enum ibmvfc_fcp_rsp_info_codes { }; struct ibmvfc_fcp_rsp_info { - u16 reserved; + __be16 reserved; u8 rsp_code; u8 reserved2[4]; }__attribute__((packed, aligned (2))); @@ -388,13 +388,13 @@ union ibmvfc_fcp_rsp_data { }__attribute__((packed, aligned (8))); struct ibmvfc_fcp_rsp { - u64 reserved; - u16 retry_delay_timer; + __be64 reserved; + __be16 retry_delay_timer; u8 flags; u8 scsi_status; - u32 fcp_resid; - u32 fcp_sense_len; - u32 fcp_rsp_len; + __be32 fcp_resid; + __be32 fcp_sense_len; + __be32 fcp_rsp_len; union ibmvfc_fcp_rsp_data data; }__attribute__((packed, aligned (8))); @@ -429,58 +429,58 @@ struct ibmvfc_fcp_cmd_iu { #define IBMVFC_RDDATA 0x02 #define IBMVFC_WRDATA 0x01 u8 cdb[IBMVFC_MAX_CDB_LEN]; - u32 xfer_len; + __be32 xfer_len; }__attribute__((packed, aligned (4))); struct ibmvfc_cmd { - u64 task_tag; - u32 frame_type; - u32 payload_len; - u32 resp_len; - u32 adapter_resid; - u16 status; - u16 error; - u16 flags; - u16 response_flags; + __be64 task_tag; + __be32 frame_type; + __be32 payload_len; + __be32 resp_len; + __be32 adapter_resid; + __be16 status; + __be16 error; + __be16 flags; + __be16 response_flags; #define IBMVFC_ADAPTER_RESID_VALID 0x01 - u32 cancel_key; - u32 exchange_id; + __be32 cancel_key; + __be32 exchange_id; struct srp_direct_buf ext_func; struct srp_direct_buf ioba; struct srp_direct_buf resp; - u64 correlation; - u64 tgt_scsi_id; - u64 tag; - u64 reserved3[2]; + __be64 correlation; + __be64 tgt_scsi_id; + __be64 tag; + __be64 reserved3[2]; struct ibmvfc_fcp_cmd_iu iu; struct ibmvfc_fcp_rsp rsp; }__attribute__((packed, aligned (8))); struct ibmvfc_passthru_fc_iu { - u32 payload[7]; + __be32 payload[7]; #define IBMVFC_ADISC 0x52000000 - u32 response[7]; + __be32 response[7]; }; struct ibmvfc_passthru_iu { - u64 task_tag; - u32 cmd_len; - u32 rsp_len; - u16 status; - u16 error; - u32 flags; + __be64 task_tag; + __be32 cmd_len; + __be32 rsp_len; + __be16 status; + __be16 error; + __be32 flags; #define IBMVFC_FC_ELS 0x01 #define IBMVFC_FC_CT_IU 0x02 - u32 cancel_key; + __be32 cancel_key; #define IBMVFC_PASSTHRU_CANCEL_KEY 0x80000000 #define IBMVFC_INTERNAL_CANCEL_KEY 0x80000001 - u32 reserved; + __be32 reserved; struct srp_direct_buf cmd; struct srp_direct_buf rsp; - u64 correlation; - u64 scsi_id; - u64 tag; - u64 reserved2[2]; + __be64 correlation; + __be64 scsi_id; + __be64 tag; + __be64 reserved2[2]; }__attribute__((packed, aligned (8))); struct ibmvfc_passthru_mad { @@ -552,7 +552,7 @@ struct ibmvfc_crq { volatile u8 valid; volatile u8 format; u8 reserved[6]; - volatile u64 ioba; + volatile __be64 ioba; }__attribute__((packed, aligned (8))); struct ibmvfc_crq_queue { @@ -572,12 +572,12 @@ struct ibmvfc_async_crq { volatile u8 valid; u8 link_state; u8 pad[2]; - u32 pad2; - volatile u64 event; - volatile u64 scsi_id; - volatile u64 wwpn; - volatile u64 node_name; - u64 reserved; + __be32 pad2; + volatile __be64 event; + volatile __be64 scsi_id; + volatile __be64 wwpn; + volatile __be64 node_name; + __be64 reserved; }__attribute__((packed, aligned (8))); struct ibmvfc_async_crq_queue { diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c deleted file mode 100644 index 56f8a861ed72..000000000000 --- a/drivers/scsi/ibmvscsi/ibmvstgt.c +++ /dev/null @@ -1,1001 +0,0 @@ -/* - * IBM eServer i/pSeries Virtual SCSI Target Driver - * Copyright (C) 2003-2005 Dave Boutcher (boutcher@us.ibm.com) IBM Corp. - * Santiago Leon (santil@us.ibm.com) IBM Corp. - * Linda Xie (lxie@us.ibm.com) IBM Corp. - * - * Copyright (C) 2005-2006 FUJITA Tomonori <tomof@acm.org> - * - * 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. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 - * USA - */ -#include <linux/interrupt.h> -#include <linux/module.h> -#include <linux/slab.h> -#include <scsi/scsi.h> -#include <scsi/scsi_host.h> -#include <scsi/scsi_transport_srp.h> -#include <scsi/scsi_tgt.h> -#include <scsi/libsrp.h> -#include <asm/hvcall.h> -#include <asm/iommu.h> -#include <asm/prom.h> -#include <asm/vio.h> - -#include "ibmvscsi.h" - -#define INITIAL_SRP_LIMIT 16 -#define DEFAULT_MAX_SECTORS 256 - -#define TGT_NAME "ibmvstgt" - -/* - * Hypervisor calls. - */ -#define h_copy_rdma(l, sa, sb, da, db) \ - plpar_hcall_norets(H_COPY_RDMA, l, sa, sb, da, db) -#define h_send_crq(ua, l, h) \ - plpar_hcall_norets(H_SEND_CRQ, ua, l, h) -#define h_reg_crq(ua, tok, sz)\ - plpar_hcall_norets(H_REG_CRQ, ua, tok, sz); -#define h_free_crq(ua) \ - plpar_hcall_norets(H_FREE_CRQ, ua); - -/* tmp - will replace with SCSI logging stuff */ -#define eprintk(fmt, args...) \ -do { \ - printk("%s(%d) " fmt, __func__, __LINE__, ##args); \ -} while (0) -/* #define dprintk eprintk */ -#define dprintk(fmt, args...) - -struct vio_port { - struct vio_dev *dma_dev; - - struct crq_queue crq_queue; - struct work_struct crq_work; - - unsigned long liobn; - unsigned long riobn; - struct srp_target *target; - - struct srp_rport *rport; -}; - -static struct workqueue_struct *vtgtd; -static struct scsi_transport_template *ibmvstgt_transport_template; - -/* - * These are fixed for the system and come from the Open Firmware device tree. - * We just store them here to save getting them every time. - */ -static char system_id[64] = ""; -static char partition_name[97] = "UNKNOWN"; -static unsigned int partition_number = -1; - -static struct vio_port *target_to_port(struct srp_target *target) -{ - return (struct vio_port *) target->ldata; -} - -static inline union viosrp_iu *vio_iu(struct iu_entry *iue) -{ - return (union viosrp_iu *) (iue->sbuf->buf); -} - -static int send_iu(struct iu_entry *iue, uint64_t length, uint8_t format) -{ - struct srp_target *target = iue->target; - struct vio_port *vport = target_to_port(target); - long rc, rc1; - union { - struct viosrp_crq cooked; - uint64_t raw[2]; - } crq; - - /* First copy the SRP */ - rc = h_copy_rdma(length, vport->liobn, iue->sbuf->dma, - vport->riobn, iue->remote_token); - - if (rc) - eprintk("Error %ld transferring data\n", rc); - - crq.cooked.valid = 0x80; - crq.cooked.format = format; - crq.cooked.reserved = 0x00; - crq.cooked.timeout = 0x00; - crq.cooked.IU_length = length; - crq.cooked.IU_data_ptr = vio_iu(iue)->srp.rsp.tag; - - if (rc == 0) - crq.cooked.status = 0x99; /* Just needs to be non-zero */ - else - crq.cooked.status = 0x00; - - rc1 = h_send_crq(vport->dma_dev->unit_address, crq.raw[0], crq.raw[1]); - - if (rc1) { - eprintk("%ld sending response\n", rc1); - return rc1; - } - - return rc; -} - -#define SRP_RSP_SENSE_DATA_LEN 18 - -static int send_rsp(struct iu_entry *iue, struct scsi_cmnd *sc, - unsigned char status, unsigned char asc) -{ - union viosrp_iu *iu = vio_iu(iue); - uint64_t tag = iu->srp.rsp.tag; - - /* If the linked bit is on and status is good */ - if (test_bit(V_LINKED, &iue->flags) && (status == NO_SENSE)) - status = 0x10; - - memset(iu, 0, sizeof(struct srp_rsp)); - iu->srp.rsp.opcode = SRP_RSP; - iu->srp.rsp.req_lim_delta = 1; - iu->srp.rsp.tag = tag; - - if (test_bit(V_DIOVER, &iue->flags)) - iu->srp.rsp.flags |= SRP_RSP_FLAG_DIOVER; - - iu->srp.rsp.data_in_res_cnt = 0; - iu->srp.rsp.data_out_res_cnt = 0; - - iu->srp.rsp.flags &= ~SRP_RSP_FLAG_RSPVALID; - - iu->srp.rsp.resp_data_len = 0; - iu->srp.rsp.status = status; - if (status) { - uint8_t *sense = iu->srp.rsp.data; - - if (sc) { - iu->srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID; - iu->srp.rsp.sense_data_len = SCSI_SENSE_BUFFERSIZE; - memcpy(sense, sc->sense_buffer, SCSI_SENSE_BUFFERSIZE); - } else { - iu->srp.rsp.status = SAM_STAT_CHECK_CONDITION; - iu->srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID; - iu->srp.rsp.sense_data_len = SRP_RSP_SENSE_DATA_LEN; - - /* Valid bit and 'current errors' */ - sense[0] = (0x1 << 7 | 0x70); - /* Sense key */ - sense[2] = status; - /* Additional sense length */ - sense[7] = 0xa; /* 10 bytes */ - /* Additional sense code */ - sense[12] = asc; - } - } - - send_iu(iue, sizeof(iu->srp.rsp) + SRP_RSP_SENSE_DATA_LEN, - VIOSRP_SRP_FORMAT); - - return 0; -} - -static void handle_cmd_queue(struct srp_target *target) -{ - struct Scsi_Host *shost = target->shost; - struct srp_rport *rport = target_to_port(target)->rport; - struct iu_entry *iue; - struct srp_cmd *cmd; - unsigned long flags; - int err; - -retry: - spin_lock_irqsave(&target->lock, flags); - - list_for_each_entry(iue, &target->cmd_queue, ilist) { - if (!test_and_set_bit(V_FLYING, &iue->flags)) { - spin_unlock_irqrestore(&target->lock, flags); - cmd = iue->sbuf->buf; - err = srp_cmd_queue(shost, cmd, iue, - (unsigned long)rport, 0); - if (err) { - eprintk("cannot queue cmd %p %d\n", cmd, err); - srp_iu_put(iue); - } - goto retry; - } - } - - spin_unlock_irqrestore(&target->lock, flags); -} - -static int ibmvstgt_rdma(struct scsi_cmnd *sc, struct scatterlist *sg, int nsg, - struct srp_direct_buf *md, int nmd, - enum dma_data_direction dir, unsigned int rest) -{ - struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr; - struct srp_target *target = iue->target; - struct vio_port *vport = target_to_port(target); - dma_addr_t token; - long err; - unsigned int done = 0; - int i, sidx, soff; - - sidx = soff = 0; - token = sg_dma_address(sg + sidx); - - for (i = 0; i < nmd && rest; i++) { - unsigned int mdone, mlen; - - mlen = min(rest, md[i].len); - for (mdone = 0; mlen;) { - int slen = min(sg_dma_len(sg + sidx) - soff, mlen); - - if (dir == DMA_TO_DEVICE) - err = h_copy_rdma(slen, - vport->riobn, - md[i].va + mdone, - vport->liobn, - token + soff); - else - err = h_copy_rdma(slen, - vport->liobn, - token + soff, - vport->riobn, - md[i].va + mdone); - - if (err != H_SUCCESS) { - eprintk("rdma error %d %d %ld\n", dir, slen, err); - return -EIO; - } - - mlen -= slen; - mdone += slen; - soff += slen; - done += slen; - - if (soff == sg_dma_len(sg + sidx)) { - sidx++; - soff = 0; - token = sg_dma_address(sg + sidx); - - if (sidx > nsg) { - eprintk("out of sg %p %d %d\n", - iue, sidx, nsg); - return -EIO; - } - } - }; - - rest -= mlen; - } - return 0; -} - -static int ibmvstgt_cmd_done(struct scsi_cmnd *sc, - void (*done)(struct scsi_cmnd *)) -{ - unsigned long flags; - struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr; - struct srp_target *target = iue->target; - int err = 0; - - dprintk("%p %p %x %u\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0], - scsi_sg_count(sc)); - - if (scsi_sg_count(sc)) - err = srp_transfer_data(sc, &vio_iu(iue)->srp.cmd, ibmvstgt_rdma, 1, 1); - - spin_lock_irqsave(&target->lock, flags); - list_del(&iue->ilist); - spin_unlock_irqrestore(&target->lock, flags); - - if (err|| sc->result != SAM_STAT_GOOD) { - eprintk("operation failed %p %d %x\n", - iue, sc->result, vio_iu(iue)->srp.cmd.cdb[0]); - send_rsp(iue, sc, HARDWARE_ERROR, 0x00); - } else - send_rsp(iue, sc, NO_SENSE, 0x00); - - done(sc); - srp_iu_put(iue); - return 0; -} - -int send_adapter_info(struct iu_entry *iue, - dma_addr_t remote_buffer, uint16_t length) -{ - struct srp_target *target = iue->target; - struct vio_port *vport = target_to_port(target); - struct Scsi_Host *shost = target->shost; - dma_addr_t data_token; - struct mad_adapter_info_data *info; - int err; - - info = dma_alloc_coherent(target->dev, sizeof(*info), &data_token, - GFP_KERNEL); - if (!info) { - eprintk("bad dma_alloc_coherent %p\n", target); - return 1; - } - - /* Get remote info */ - err = h_copy_rdma(sizeof(*info), vport->riobn, remote_buffer, - vport->liobn, data_token); - if (err == H_SUCCESS) { - dprintk("Client connect: %s (%d)\n", - info->partition_name, info->partition_number); - } - - memset(info, 0, sizeof(*info)); - - strcpy(info->srp_version, "16.a"); - strncpy(info->partition_name, partition_name, - sizeof(info->partition_name)); - info->partition_number = partition_number; - info->mad_version = 1; - info->os_type = 2; - info->port_max_txu[0] = shost->hostt->max_sectors << 9; - - /* Send our info to remote */ - err = h_copy_rdma(sizeof(*info), vport->liobn, data_token, - vport->riobn, remote_buffer); - - dma_free_coherent(target->dev, sizeof(*info), info, data_token); - - if (err != H_SUCCESS) { - eprintk("Error sending adapter info %d\n", err); - return 1; - } - - return 0; -} - -static void process_login(struct iu_entry *iue) -{ - union viosrp_iu *iu = vio_iu(iue); - struct srp_login_rsp *rsp = &iu->srp.login_rsp; - uint64_t tag = iu->srp.rsp.tag; - struct Scsi_Host *shost = iue->target->shost; - struct srp_target *target = host_to_srp_target(shost); - struct vio_port *vport = target_to_port(target); - struct srp_rport_identifiers ids; - - memset(&ids, 0, sizeof(ids)); - sprintf(ids.port_id, "%x", vport->dma_dev->unit_address); - ids.roles = SRP_RPORT_ROLE_INITIATOR; - if (!vport->rport) - vport->rport = srp_rport_add(shost, &ids); - - /* TODO handle case that requested size is wrong and - * buffer format is wrong - */ - memset(iu, 0, sizeof(struct srp_login_rsp)); - rsp->opcode = SRP_LOGIN_RSP; - rsp->req_lim_delta = INITIAL_SRP_LIMIT; - rsp->tag = tag; - rsp->max_it_iu_len = sizeof(union srp_iu); - rsp->max_ti_iu_len = sizeof(union srp_iu); - /* direct and indirect */ - rsp->buf_fmt = SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT; - - send_iu(iue, sizeof(*rsp), VIOSRP_SRP_FORMAT); -} - -static inline void queue_cmd(struct iu_entry *iue) -{ - struct srp_target *target = iue->target; - unsigned long flags; - - spin_lock_irqsave(&target->lock, flags); - list_add_tail(&iue->ilist, &target->cmd_queue); - spin_unlock_irqrestore(&target->lock, flags); -} - -static int process_tsk_mgmt(struct iu_entry *iue) -{ - union viosrp_iu *iu = vio_iu(iue); - int fn; - - dprintk("%p %u\n", iue, iu->srp.tsk_mgmt.tsk_mgmt_func); - - switch (iu->srp.tsk_mgmt.tsk_mgmt_func) { - case SRP_TSK_ABORT_TASK: - fn = ABORT_TASK; - break; - case SRP_TSK_ABORT_TASK_SET: - fn = ABORT_TASK_SET; - break; - case SRP_TSK_CLEAR_TASK_SET: - fn = CLEAR_TASK_SET; - break; - case SRP_TSK_LUN_RESET: - fn = LOGICAL_UNIT_RESET; - break; - case SRP_TSK_CLEAR_ACA: - fn = CLEAR_ACA; - break; - default: - fn = 0; - } - if (fn) - scsi_tgt_tsk_mgmt_request(iue->target->shost, - (unsigned long)iue->target->shost, - fn, - iu->srp.tsk_mgmt.task_tag, - (struct scsi_lun *) &iu->srp.tsk_mgmt.lun, - iue); - else - send_rsp(iue, NULL, ILLEGAL_REQUEST, 0x20); - - return !fn; -} - -static int process_mad_iu(struct iu_entry *iue) -{ - union viosrp_iu *iu = vio_iu(iue); - struct viosrp_adapter_info *info; - struct viosrp_host_config *conf; - - switch (iu->mad.empty_iu.common.type) { - case VIOSRP_EMPTY_IU_TYPE: - eprintk("%s\n", "Unsupported EMPTY MAD IU"); - break; - case VIOSRP_ERROR_LOG_TYPE: - eprintk("%s\n", "Unsupported ERROR LOG MAD IU"); - iu->mad.error_log.common.status = 1; - send_iu(iue, sizeof(iu->mad.error_log), VIOSRP_MAD_FORMAT); - break; - case VIOSRP_ADAPTER_INFO_TYPE: - info = &iu->mad.adapter_info; - info->common.status = send_adapter_info(iue, info->buffer, - info->common.length); - send_iu(iue, sizeof(*info), VIOSRP_MAD_FORMAT); - break; - case VIOSRP_HOST_CONFIG_TYPE: - conf = &iu->mad.host_config; - conf->common.status = 1; - send_iu(iue, sizeof(*conf), VIOSRP_MAD_FORMAT); - break; - default: - eprintk("Unknown type %u\n", iu->srp.rsp.opcode); - } - - return 1; -} - -static int process_srp_iu(struct iu_entry *iue) -{ - union viosrp_iu *iu = vio_iu(iue); - int done = 1; - u8 opcode = iu->srp.rsp.opcode; - - switch (opcode) { - case SRP_LOGIN_REQ: - process_login(iue); - break; - case SRP_TSK_MGMT: - done = process_tsk_mgmt(iue); - break; - case SRP_CMD: - queue_cmd(iue); - done = 0; - break; - case SRP_LOGIN_RSP: - case SRP_I_LOGOUT: - case SRP_T_LOGOUT: - case SRP_RSP: - case SRP_CRED_REQ: - case SRP_CRED_RSP: - case SRP_AER_REQ: - case SRP_AER_RSP: - eprintk("Unsupported type %u\n", opcode); - break; - default: - eprintk("Unknown type %u\n", opcode); - } - - return done; -} - -static void process_iu(struct viosrp_crq *crq, struct srp_target *target) -{ - struct vio_port *vport = target_to_port(target); - struct iu_entry *iue; - long err; - int done = 1; - - iue = srp_iu_get(target); - if (!iue) { - eprintk("Error getting IU from pool, %p\n", target); - return; - } - - iue->remote_token = crq->IU_data_ptr; - - err = h_copy_rdma(crq->IU_length, vport->riobn, - iue->remote_token, vport->liobn, iue->sbuf->dma); - - if (err != H_SUCCESS) { - eprintk("%ld transferring data error %p\n", err, iue); - goto out; - } - - if (crq->format == VIOSRP_MAD_FORMAT) - done = process_mad_iu(iue); - else - done = process_srp_iu(iue); -out: - if (done) - srp_iu_put(iue); -} - -static irqreturn_t ibmvstgt_interrupt(int dummy, void *data) -{ - struct srp_target *target = data; - struct vio_port *vport = target_to_port(target); - - vio_disable_interrupts(vport->dma_dev); - queue_work(vtgtd, &vport->crq_work); - - return IRQ_HANDLED; -} - -static int crq_queue_create(struct crq_queue *queue, struct srp_target *target) -{ - int err; - struct vio_port *vport = target_to_port(target); - - queue->msgs = (struct viosrp_crq *) get_zeroed_page(GFP_KERNEL); - if (!queue->msgs) - goto malloc_failed; - queue->size = PAGE_SIZE / sizeof(*queue->msgs); - - queue->msg_token = dma_map_single(target->dev, queue->msgs, - queue->size * sizeof(*queue->msgs), - DMA_BIDIRECTIONAL); - - if (dma_mapping_error(target->dev, queue->msg_token)) - goto map_failed; - - err = h_reg_crq(vport->dma_dev->unit_address, queue->msg_token, - PAGE_SIZE); - - /* If the adapter was left active for some reason (like kexec) - * try freeing and re-registering - */ - if (err == H_RESOURCE) { - do { - err = h_free_crq(vport->dma_dev->unit_address); - } while (err == H_BUSY || H_IS_LONG_BUSY(err)); - - err = h_reg_crq(vport->dma_dev->unit_address, queue->msg_token, - PAGE_SIZE); - } - - if (err != H_SUCCESS && err != 2) { - eprintk("Error 0x%x opening virtual adapter\n", err); - goto reg_crq_failed; - } - - err = request_irq(vport->dma_dev->irq, &ibmvstgt_interrupt, - 0, "ibmvstgt", target); - if (err) - goto req_irq_failed; - - vio_enable_interrupts(vport->dma_dev); - - h_send_crq(vport->dma_dev->unit_address, 0xC001000000000000, 0); - - queue->cur = 0; - spin_lock_init(&queue->lock); - - return 0; - -req_irq_failed: - do { - err = h_free_crq(vport->dma_dev->unit_address); - } while (err == H_BUSY || H_IS_LONG_BUSY(err)); - -reg_crq_failed: - dma_unmap_single(target->dev, queue->msg_token, - queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL); -map_failed: - free_page((unsigned long) queue->msgs); - -malloc_failed: - return -ENOMEM; -} - -static void crq_queue_destroy(struct srp_target *target) -{ - struct vio_port *vport = target_to_port(target); - struct crq_queue *queue = &vport->crq_queue; - int err; - - free_irq(vport->dma_dev->irq, target); - do { - err = h_free_crq(vport->dma_dev->unit_address); - } while (err == H_BUSY || H_IS_LONG_BUSY(err)); - - dma_unmap_single(target->dev, queue->msg_token, - queue->size * sizeof(*queue->msgs), DMA_BIDIRECTIONAL); - - free_page((unsigned long) queue->msgs); -} - -static void process_crq(struct viosrp_crq *crq, struct srp_target *target) -{ - struct vio_port *vport = target_to_port(target); - dprintk("%x %x\n", crq->valid, crq->format); - - switch (crq->valid) { - case 0xC0: - /* initialization */ - switch (crq->format) { - case 0x01: - h_send_crq(vport->dma_dev->unit_address, - 0xC002000000000000, 0); - break; - case 0x02: - break; - default: - eprintk("Unknown format %u\n", crq->format); - } - break; - case 0xFF: - /* transport event */ - break; - case 0x80: - /* real payload */ - switch (crq->format) { - case VIOSRP_SRP_FORMAT: - case VIOSRP_MAD_FORMAT: - process_iu(crq, target); - break; - case VIOSRP_OS400_FORMAT: - case VIOSRP_AIX_FORMAT: - case VIOSRP_LINUX_FORMAT: - case VIOSRP_INLINE_FORMAT: - eprintk("Unsupported format %u\n", crq->format); - break; - default: - eprintk("Unknown format %u\n", crq->format); - } - break; - default: - eprintk("unknown message type 0x%02x!?\n", crq->valid); - } -} - -static inline struct viosrp_crq *next_crq(struct crq_queue *queue) -{ - struct viosrp_crq *crq; - unsigned long flags; - - spin_lock_irqsave(&queue->lock, flags); - crq = &queue->msgs[queue->cur]; - if (crq->valid & 0x80) { - if (++queue->cur == queue->size) - queue->cur = 0; - } else - crq = NULL; - spin_unlock_irqrestore(&queue->lock, flags); - - return crq; -} - -static void handle_crq(struct work_struct *work) -{ - struct vio_port *vport = container_of(work, struct vio_port, crq_work); - struct srp_target *target = vport->target; - struct viosrp_crq *crq; - int done = 0; - - while (!done) { - while ((crq = next_crq(&vport->crq_queue)) != NULL) { - process_crq(crq, target); - crq->valid = 0x00; - } - - vio_enable_interrupts(vport->dma_dev); - - crq = next_crq(&vport->crq_queue); - if (crq) { - vio_disable_interrupts(vport->dma_dev); - process_crq(crq, target); - crq->valid = 0x00; - } else - done = 1; - } - - handle_cmd_queue(target); -} - - -static int ibmvstgt_eh_abort_handler(struct scsi_cmnd *sc) -{ - unsigned long flags; - struct iu_entry *iue = (struct iu_entry *) sc->SCp.ptr; - struct srp_target *target = iue->target; - - dprintk("%p %p %x\n", iue, target, vio_iu(iue)->srp.cmd.cdb[0]); - - spin_lock_irqsave(&target->lock, flags); - list_del(&iue->ilist); - spin_unlock_irqrestore(&target->lock, flags); - - srp_iu_put(iue); - - return 0; -} - -static int ibmvstgt_tsk_mgmt_response(struct Scsi_Host *shost, - u64 itn_id, u64 mid, int result) -{ - struct iu_entry *iue = (struct iu_entry *) ((void *) mid); - union viosrp_iu *iu = vio_iu(iue); - unsigned char status, asc; - - eprintk("%p %d\n", iue, result); - status = NO_SENSE; - asc = 0; - - switch (iu->srp.tsk_mgmt.tsk_mgmt_func) { - case SRP_TSK_ABORT_TASK: - asc = 0x14; - if (result) - status = ABORTED_COMMAND; - break; - default: - break; - } - - send_rsp(iue, NULL, status, asc); - srp_iu_put(iue); - - return 0; -} - -static int ibmvstgt_it_nexus_response(struct Scsi_Host *shost, u64 itn_id, - int result) -{ - struct srp_target *target = host_to_srp_target(shost); - struct vio_port *vport = target_to_port(target); - - if (result) { - eprintk("%p %d\n", shost, result); - srp_rport_del(vport->rport); - vport->rport = NULL; - } - return 0; -} - -static ssize_t system_id_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%s\n", system_id); -} - -static ssize_t partition_number_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%x\n", partition_number); -} - -static ssize_t unit_address_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct Scsi_Host *shost = class_to_shost(dev); - struct srp_target *target = host_to_srp_target(shost); - struct vio_port *vport = target_to_port(target); - return snprintf(buf, PAGE_SIZE, "%x\n", vport->dma_dev->unit_address); -} - -static DEVICE_ATTR(system_id, S_IRUGO, system_id_show, NULL); -static DEVICE_ATTR(partition_number, S_IRUGO, partition_number_show, NULL); -static DEVICE_ATTR(unit_address, S_IRUGO, unit_address_show, NULL); - -static struct device_attribute *ibmvstgt_attrs[] = { - &dev_attr_system_id, - &dev_attr_partition_number, - &dev_attr_unit_address, - NULL, -}; - -static struct scsi_host_template ibmvstgt_sht = { - .name = TGT_NAME, - .module = THIS_MODULE, - .can_queue = INITIAL_SRP_LIMIT, - .sg_tablesize = SG_ALL, - .use_clustering = DISABLE_CLUSTERING, - .max_sectors = DEFAULT_MAX_SECTORS, - .transfer_response = ibmvstgt_cmd_done, - .eh_abort_handler = ibmvstgt_eh_abort_handler, - .shost_attrs = ibmvstgt_attrs, - .proc_name = TGT_NAME, - .supported_mode = MODE_TARGET, -}; - -static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id) -{ - struct Scsi_Host *shost; - struct srp_target *target; - struct vio_port *vport; - unsigned int *dma, dma_size; - int err = -ENOMEM; - - vport = kzalloc(sizeof(struct vio_port), GFP_KERNEL); - if (!vport) - return err; - shost = scsi_host_alloc(&ibmvstgt_sht, sizeof(struct srp_target)); - if (!shost) - goto free_vport; - shost->transportt = ibmvstgt_transport_template; - - target = host_to_srp_target(shost); - target->shost = shost; - vport->dma_dev = dev; - target->ldata = vport; - vport->target = target; - err = srp_target_alloc(target, &dev->dev, INITIAL_SRP_LIMIT, - SRP_MAX_IU_LEN); - if (err) - goto put_host; - - dma = (unsigned int *) vio_get_attribute(dev, "ibm,my-dma-window", - &dma_size); - if (!dma || dma_size != 40) { - eprintk("Couldn't get window property %d\n", dma_size); - err = -EIO; - goto free_srp_target; - } - vport->liobn = dma[0]; - vport->riobn = dma[5]; - - INIT_WORK(&vport->crq_work, handle_crq); - - err = scsi_add_host(shost, target->dev); - if (err) - goto free_srp_target; - - err = scsi_tgt_alloc_queue(shost); - if (err) - goto remove_host; - - err = crq_queue_create(&vport->crq_queue, target); - if (err) - goto free_queue; - - return 0; -free_queue: - scsi_tgt_free_queue(shost); -remove_host: - scsi_remove_host(shost); -free_srp_target: - srp_target_free(target); -put_host: - scsi_host_put(shost); -free_vport: - kfree(vport); - return err; -} - -static int ibmvstgt_remove(struct vio_dev *dev) -{ - struct srp_target *target = dev_get_drvdata(&dev->dev); - struct Scsi_Host *shost = target->shost; - struct vio_port *vport = target->ldata; - - crq_queue_destroy(target); - srp_remove_host(shost); - scsi_remove_host(shost); - scsi_tgt_free_queue(shost); - srp_target_free(target); - kfree(vport); - scsi_host_put(shost); - return 0; -} - -static struct vio_device_id ibmvstgt_device_table[] = { - {"v-scsi-host", "IBM,v-scsi-host"}, - {"",""} -}; - -MODULE_DEVICE_TABLE(vio, ibmvstgt_device_table); - -static struct vio_driver ibmvstgt_driver = { - .id_table = ibmvstgt_device_table, - .probe = ibmvstgt_probe, - .remove = ibmvstgt_remove, - .name = "ibmvscsis", -}; - -static int get_system_info(void) -{ - struct device_node *rootdn; - const char *id, *model, *name; - const unsigned int *num; - - rootdn = of_find_node_by_path("/"); - if (!rootdn) - return -ENOENT; - - model = of_get_property(rootdn, "model", NULL); - id = of_get_property(rootdn, "system-id", NULL); - if (model && id) - snprintf(system_id, sizeof(system_id), "%s-%s", model, id); - - name = of_get_property(rootdn, "ibm,partition-name", NULL); - if (name) - strncpy(partition_name, name, sizeof(partition_name)); - - num = of_get_property(rootdn, "ibm,partition-no", NULL); - if (num) - partition_number = *num; - - of_node_put(rootdn); - return 0; -} - -static struct srp_function_template ibmvstgt_transport_functions = { - .tsk_mgmt_response = ibmvstgt_tsk_mgmt_response, - .it_nexus_response = ibmvstgt_it_nexus_response, -}; - -static int __init ibmvstgt_init(void) -{ - int err = -ENOMEM; - - printk("IBM eServer i/pSeries Virtual SCSI Target Driver\n"); - - ibmvstgt_transport_template = - srp_attach_transport(&ibmvstgt_transport_functions); - if (!ibmvstgt_transport_template) - return err; - - vtgtd = create_workqueue("ibmvtgtd"); - if (!vtgtd) - goto release_transport; - - err = get_system_info(); - if (err) - goto destroy_wq; - - err = vio_register_driver(&ibmvstgt_driver); - if (err) - goto destroy_wq; - - return 0; -destroy_wq: - destroy_workqueue(vtgtd); -release_transport: - srp_release_transport(ibmvstgt_transport_template); - return err; -} - -static void __exit ibmvstgt_exit(void) -{ - printk("Unregister IBM virtual SCSI driver\n"); - - destroy_workqueue(vtgtd); - vio_unregister_driver(&ibmvstgt_driver); - srp_release_transport(ibmvstgt_transport_template); -} - -MODULE_DESCRIPTION("IBM Virtual SCSI Target"); -MODULE_AUTHOR("Santiago Leon"); -MODULE_LICENSE("GPL"); - -module_init(ibmvstgt_init); -module_exit(ibmvstgt_exit); diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c index b1c4d831137d..ddf0694d87f0 100644 --- a/drivers/scsi/in2000.c +++ b/drivers/scsi/in2000.c @@ -2251,14 +2251,14 @@ static int in2000_show_info(struct seq_file *m, struct Scsi_Host *instance) seq_printf(m, "\nconnected: "); if (hd->connected) { cmd = (Scsi_Cmnd *) hd->connected; - seq_printf(m, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + seq_printf(m, " %d:%llu(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]); } } if (hd->proc & PR_INPUTQ) { seq_printf(m, "\ninput_Q: "); cmd = (Scsi_Cmnd *) hd->input_Q; while (cmd) { - seq_printf(m, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + seq_printf(m, " %d:%llu(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]); cmd = (Scsi_Cmnd *) cmd->host_scribble; } } @@ -2266,7 +2266,7 @@ static int in2000_show_info(struct seq_file *m, struct Scsi_Host *instance) seq_printf(m, "\ndisconnected_Q:"); cmd = (Scsi_Cmnd *) hd->disconnected_Q; while (cmd) { - seq_printf(m, " %d:%d(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + seq_printf(m, " %d:%llu(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]); cmd = (Scsi_Cmnd *) cmd->host_scribble; } } diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index 695b34e9154e..4198e45ea941 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c @@ -356,7 +356,7 @@ static int isci_setup_interrupts(struct pci_dev *pdev) for (i = 0; i < num_msix; i++) pci_info->msix_entries[i].entry = i; - err = pci_enable_msix(pdev, pci_info->msix_entries, num_msix); + err = pci_enable_msix_exact(pdev, pci_info->msix_entries, num_msix); if (err) goto intx; diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 3d1bc67bac9d..f9f3a1224dfa 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -260,7 +260,7 @@ static int iscsi_check_tmf_restrictions(struct iscsi_task *task, int opcode) { struct iscsi_conn *conn = task->conn; struct iscsi_tm *tmf = &conn->tmhdr; - unsigned int hdr_lun; + u64 hdr_lun; if (conn->tmf_state == TMF_INITIAL) return 0; @@ -1859,8 +1859,7 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn, * Fail commands. session lock held and recv side suspended and xmit * thread flushed */ -static void fail_scsi_tasks(struct iscsi_conn *conn, unsigned lun, - int error) +static void fail_scsi_tasks(struct iscsi_conn *conn, u64 lun, int error) { struct iscsi_task *task; int i; @@ -2279,7 +2278,8 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc) cls_session = starget_to_session(scsi_target(sc->device)); session = cls_session->dd_data; - ISCSI_DBG_EH(session, "LU Reset [sc %p lun %u]\n", sc, sc->device->lun); + ISCSI_DBG_EH(session, "LU Reset [sc %p lun %llu]\n", sc, + sc->device->lun); mutex_lock(&session->eh_mutex); spin_lock_bh(&session->frwd_lock); @@ -2971,7 +2971,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) */ for (;;) { spin_lock_irqsave(session->host->host_lock, flags); - if (!session->host->host_busy) { /* OK for ERL == 0 */ + if (!atomic_read(&session->host->host_busy)) { /* OK for ERL == 0 */ spin_unlock_irqrestore(session->host->host_lock, flags); break; } @@ -2979,7 +2979,7 @@ void iscsi_conn_teardown(struct iscsi_cls_conn *cls_conn) msleep_interruptible(500); iscsi_conn_printk(KERN_INFO, conn, "iscsi conn_destroy(): " "host_busy %d host_failed %d\n", - session->host->host_busy, + atomic_read(&session->host->host_busy), session->host->host_failed); /* * force eh_abort() to unblock diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 25d0f127424d..24e477d2ea70 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c @@ -404,7 +404,7 @@ static int sas_recover_lu(struct domain_device *dev, struct scsi_cmnd *cmd) int_to_scsilun(cmd->device->lun, &lun); - SAS_DPRINTK("eh: device %llx LUN %x has the task\n", + SAS_DPRINTK("eh: device %llx LUN %llx has the task\n", SAS_ADDR(dev->sas_addr), cmd->device->lun); @@ -490,7 +490,8 @@ static void sas_wait_eh(struct domain_device *dev) } EXPORT_SYMBOL(sas_wait_eh); -static int sas_queue_reset(struct domain_device *dev, int reset_type, int lun, int wait) +static int sas_queue_reset(struct domain_device *dev, int reset_type, + u64 lun, int wait) { struct sas_ha_struct *ha = dev->port->ha; int scheduled = 0, tries = 100; @@ -689,7 +690,7 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head * reset: tmf_resp = sas_recover_lu(task->dev, cmd); if (tmf_resp == TMF_RESP_FUNC_COMPLETE) { - SAS_DPRINTK("dev %016llx LU %x is " + SAS_DPRINTK("dev %016llx LU %llx is " "recovered\n", SAS_ADDR(task->dev), cmd->device->lun); @@ -742,7 +743,7 @@ static void sas_eh_handle_sas_errors(struct Scsi_Host *shost, struct list_head * * of effort could recover from errors. Quite * possibly the HA just disappeared. */ - SAS_DPRINTK("error from device %llx, LUN %x " + SAS_DPRINTK("error from device %llx, LUN %llx " "couldn't be recovered in any way\n", SAS_ADDR(task->dev->sas_addr), cmd->device->lun); @@ -812,7 +813,7 @@ retry: spin_unlock_irq(shost->host_lock); SAS_DPRINTK("Enter %s busy: %d failed: %d\n", - __func__, shost->host_busy, shost->host_failed); + __func__, atomic_read(&shost->host_busy), shost->host_failed); /* * Deal with commands that still have SAS tasks (i.e. they didn't * complete via the normal sas_task completion mechanism), @@ -857,7 +858,8 @@ out: goto retry; SAS_DPRINTK("--- Exit %s: busy: %d failed: %d tries: %d\n", - __func__, shost->host_busy, shost->host_failed, tries); + __func__, atomic_read(&shost->host_busy), + shost->host_failed, tries); } enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *cmd) @@ -941,7 +943,7 @@ int sas_slave_configure(struct scsi_device *scsi_dev) scsi_set_tag_type(scsi_dev, MSG_SIMPLE_TAG); scsi_activate_tcq(scsi_dev, SAS_DEF_QD); } else { - SAS_DPRINTK("device %llx, LUN %x doesn't support " + SAS_DPRINTK("device %llx, LUN %llx doesn't support " "TCQ\n", SAS_ADDR(dev->sas_addr), scsi_dev->lun); scsi_dev->tagged_supported = 0; diff --git a/drivers/scsi/libsrp.c b/drivers/scsi/libsrp.c deleted file mode 100644 index 0707ecdbaa32..000000000000 --- a/drivers/scsi/libsrp.c +++ /dev/null @@ -1,447 +0,0 @@ -/* - * SCSI RDMA Protocol lib functions - * - * Copyright (C) 2006 FUJITA Tomonori <tomof@acm.org> - * - * 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. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ -#include <linux/err.h> -#include <linux/slab.h> -#include <linux/kfifo.h> -#include <linux/scatterlist.h> -#include <linux/dma-mapping.h> -#include <linux/module.h> -#include <scsi/scsi.h> -#include <scsi/scsi_cmnd.h> -#include <scsi/scsi_tcq.h> -#include <scsi/scsi_tgt.h> -#include <scsi/srp.h> -#include <scsi/libsrp.h> - -enum srp_task_attributes { - SRP_SIMPLE_TASK = 0, - SRP_HEAD_TASK = 1, - SRP_ORDERED_TASK = 2, - SRP_ACA_TASK = 4 -}; - -/* tmp - will replace with SCSI logging stuff */ -#define eprintk(fmt, args...) \ -do { \ - printk("%s(%d) " fmt, __func__, __LINE__, ##args); \ -} while (0) -/* #define dprintk eprintk */ -#define dprintk(fmt, args...) - -static int srp_iu_pool_alloc(struct srp_queue *q, size_t max, - struct srp_buf **ring) -{ - int i; - struct iu_entry *iue; - - q->pool = kcalloc(max, sizeof(struct iu_entry *), GFP_KERNEL); - if (!q->pool) - return -ENOMEM; - q->items = kcalloc(max, sizeof(struct iu_entry), GFP_KERNEL); - if (!q->items) - goto free_pool; - - spin_lock_init(&q->lock); - kfifo_init(&q->queue, (void *) q->pool, max * sizeof(void *)); - - for (i = 0, iue = q->items; i < max; i++) { - kfifo_in(&q->queue, (void *) &iue, sizeof(void *)); - iue->sbuf = ring[i]; - iue++; - } - return 0; - - kfree(q->items); -free_pool: - kfree(q->pool); - return -ENOMEM; -} - -static void srp_iu_pool_free(struct srp_queue *q) -{ - kfree(q->items); - kfree(q->pool); -} - -static struct srp_buf **srp_ring_alloc(struct device *dev, - size_t max, size_t size) -{ - int i; - struct srp_buf **ring; - - ring = kcalloc(max, sizeof(struct srp_buf *), GFP_KERNEL); - if (!ring) - return NULL; - - for (i = 0; i < max; i++) { - ring[i] = kzalloc(sizeof(struct srp_buf), GFP_KERNEL); - if (!ring[i]) - goto out; - ring[i]->buf = dma_alloc_coherent(dev, size, &ring[i]->dma, - GFP_KERNEL); - if (!ring[i]->buf) - goto out; - } - return ring; - -out: - for (i = 0; i < max && ring[i]; i++) { - if (ring[i]->buf) - dma_free_coherent(dev, size, ring[i]->buf, ring[i]->dma); - kfree(ring[i]); - } - kfree(ring); - - return NULL; -} - -static void srp_ring_free(struct device *dev, struct srp_buf **ring, size_t max, - size_t size) -{ - int i; - - for (i = 0; i < max; i++) { - dma_free_coherent(dev, size, ring[i]->buf, ring[i]->dma); - kfree(ring[i]); - } - kfree(ring); -} - -int srp_target_alloc(struct srp_target *target, struct device *dev, - size_t nr, size_t iu_size) -{ - int err; - - spin_lock_init(&target->lock); - INIT_LIST_HEAD(&target->cmd_queue); - - target->dev = dev; - dev_set_drvdata(target->dev, target); - - target->srp_iu_size = iu_size; - target->rx_ring_size = nr; - target->rx_ring = srp_ring_alloc(target->dev, nr, iu_size); - if (!target->rx_ring) - return -ENOMEM; - err = srp_iu_pool_alloc(&target->iu_queue, nr, target->rx_ring); - if (err) - goto free_ring; - - return 0; - -free_ring: - srp_ring_free(target->dev, target->rx_ring, nr, iu_size); - return -ENOMEM; -} -EXPORT_SYMBOL_GPL(srp_target_alloc); - -void srp_target_free(struct srp_target *target) -{ - srp_ring_free(target->dev, target->rx_ring, target->rx_ring_size, - target->srp_iu_size); - srp_iu_pool_free(&target->iu_queue); -} -EXPORT_SYMBOL_GPL(srp_target_free); - -struct iu_entry *srp_iu_get(struct srp_target *target) -{ - struct iu_entry *iue = NULL; - - if (kfifo_out_locked(&target->iu_queue.queue, (void *) &iue, - sizeof(void *), &target->iu_queue.lock) != sizeof(void *)) { - WARN_ONCE(1, "unexpected fifo state"); - return NULL; - } - if (!iue) - return iue; - iue->target = target; - INIT_LIST_HEAD(&iue->ilist); - iue->flags = 0; - return iue; -} -EXPORT_SYMBOL_GPL(srp_iu_get); - -void srp_iu_put(struct iu_entry *iue) -{ - kfifo_in_locked(&iue->target->iu_queue.queue, (void *) &iue, - sizeof(void *), &iue->target->iu_queue.lock); -} -EXPORT_SYMBOL_GPL(srp_iu_put); - -static int srp_direct_data(struct scsi_cmnd *sc, struct srp_direct_buf *md, - enum dma_data_direction dir, srp_rdma_t rdma_io, - int dma_map, int ext_desc) -{ - struct iu_entry *iue = NULL; - struct scatterlist *sg = NULL; - int err, nsg = 0, len; - - if (dma_map) { - iue = (struct iu_entry *) sc->SCp.ptr; - sg = scsi_sglist(sc); - - dprintk("%p %u %u %d\n", iue, scsi_bufflen(sc), - md->len, scsi_sg_count(sc)); - - nsg = dma_map_sg(iue->target->dev, sg, scsi_sg_count(sc), - DMA_BIDIRECTIONAL); - if (!nsg) { - printk("fail to map %p %d\n", iue, scsi_sg_count(sc)); - return 0; - } - len = min(scsi_bufflen(sc), md->len); - } else - len = md->len; - - err = rdma_io(sc, sg, nsg, md, 1, dir, len); - - if (dma_map) - dma_unmap_sg(iue->target->dev, sg, nsg, DMA_BIDIRECTIONAL); - - return err; -} - -static int srp_indirect_data(struct scsi_cmnd *sc, struct srp_cmd *cmd, - struct srp_indirect_buf *id, - enum dma_data_direction dir, srp_rdma_t rdma_io, - int dma_map, int ext_desc) -{ - struct iu_entry *iue = NULL; - struct srp_direct_buf *md = NULL; - struct scatterlist dummy, *sg = NULL; - dma_addr_t token = 0; - int err = 0; - int nmd, nsg = 0, len; - - if (dma_map || ext_desc) { - iue = (struct iu_entry *) sc->SCp.ptr; - sg = scsi_sglist(sc); - - dprintk("%p %u %u %d %d\n", - iue, scsi_bufflen(sc), id->len, - cmd->data_in_desc_cnt, cmd->data_out_desc_cnt); - } - - nmd = id->table_desc.len / sizeof(struct srp_direct_buf); - - if ((dir == DMA_FROM_DEVICE && nmd == cmd->data_in_desc_cnt) || - (dir == DMA_TO_DEVICE && nmd == cmd->data_out_desc_cnt)) { - md = &id->desc_list[0]; - goto rdma; - } - - if (ext_desc && dma_map) { - md = dma_alloc_coherent(iue->target->dev, id->table_desc.len, - &token, GFP_KERNEL); - if (!md) { - eprintk("Can't get dma memory %u\n", id->table_desc.len); - return -ENOMEM; - } - - sg_init_one(&dummy, md, id->table_desc.len); - sg_dma_address(&dummy) = token; - sg_dma_len(&dummy) = id->table_desc.len; - err = rdma_io(sc, &dummy, 1, &id->table_desc, 1, DMA_TO_DEVICE, - id->table_desc.len); - if (err) { - eprintk("Error copying indirect table %d\n", err); - goto free_mem; - } - } else { - eprintk("This command uses external indirect buffer\n"); - return -EINVAL; - } - -rdma: - if (dma_map) { - nsg = dma_map_sg(iue->target->dev, sg, scsi_sg_count(sc), - DMA_BIDIRECTIONAL); - if (!nsg) { - eprintk("fail to map %p %d\n", iue, scsi_sg_count(sc)); - err = -EIO; - goto free_mem; - } - len = min(scsi_bufflen(sc), id->len); - } else - len = id->len; - - err = rdma_io(sc, sg, nsg, md, nmd, dir, len); - - if (dma_map) - dma_unmap_sg(iue->target->dev, sg, nsg, DMA_BIDIRECTIONAL); - -free_mem: - if (token && dma_map) - dma_free_coherent(iue->target->dev, id->table_desc.len, md, token); - - return err; -} - -static int data_out_desc_size(struct srp_cmd *cmd) -{ - int size = 0; - u8 fmt = cmd->buf_fmt >> 4; - - switch (fmt) { - case SRP_NO_DATA_DESC: - break; - case SRP_DATA_DESC_DIRECT: - size = sizeof(struct srp_direct_buf); - break; - case SRP_DATA_DESC_INDIRECT: - size = sizeof(struct srp_indirect_buf) + - sizeof(struct srp_direct_buf) * cmd->data_out_desc_cnt; - break; - default: - eprintk("client error. Invalid data_out_format %x\n", fmt); - break; - } - return size; -} - -/* - * TODO: this can be called multiple times for a single command if it - * has very long data. - */ -int srp_transfer_data(struct scsi_cmnd *sc, struct srp_cmd *cmd, - srp_rdma_t rdma_io, int dma_map, int ext_desc) -{ - struct srp_direct_buf *md; - struct srp_indirect_buf *id; - enum dma_data_direction dir; - int offset, err = 0; - u8 format; - - offset = cmd->add_cdb_len & ~3; - - dir = srp_cmd_direction(cmd); - if (dir == DMA_FROM_DEVICE) - offset += data_out_desc_size(cmd); - - if (dir == DMA_TO_DEVICE) - format = cmd->buf_fmt >> 4; - else - format = cmd->buf_fmt & ((1U << 4) - 1); - - switch (format) { - case SRP_NO_DATA_DESC: - break; - case SRP_DATA_DESC_DIRECT: - md = (struct srp_direct_buf *) - (cmd->add_data + offset); - err = srp_direct_data(sc, md, dir, rdma_io, dma_map, ext_desc); - break; - case SRP_DATA_DESC_INDIRECT: - id = (struct srp_indirect_buf *) - (cmd->add_data + offset); - err = srp_indirect_data(sc, cmd, id, dir, rdma_io, dma_map, - ext_desc); - break; - default: - eprintk("Unknown format %d %x\n", dir, format); - err = -EINVAL; - } - - return err; -} -EXPORT_SYMBOL_GPL(srp_transfer_data); - -static int vscsis_data_length(struct srp_cmd *cmd, enum dma_data_direction dir) -{ - struct srp_direct_buf *md; - struct srp_indirect_buf *id; - int len = 0, offset = cmd->add_cdb_len & ~3; - u8 fmt; - - if (dir == DMA_TO_DEVICE) - fmt = cmd->buf_fmt >> 4; - else { - fmt = cmd->buf_fmt & ((1U << 4) - 1); - offset += data_out_desc_size(cmd); - } - - switch (fmt) { - case SRP_NO_DATA_DESC: - break; - case SRP_DATA_DESC_DIRECT: - md = (struct srp_direct_buf *) (cmd->add_data + offset); - len = md->len; - break; - case SRP_DATA_DESC_INDIRECT: - id = (struct srp_indirect_buf *) (cmd->add_data + offset); - len = id->len; - break; - default: - eprintk("invalid data format %x\n", fmt); - break; - } - return len; -} - -int srp_cmd_queue(struct Scsi_Host *shost, struct srp_cmd *cmd, void *info, - u64 itn_id, u64 addr) -{ - enum dma_data_direction dir; - struct scsi_cmnd *sc; - int tag, len, err; - - switch (cmd->task_attr) { - case SRP_SIMPLE_TASK: - tag = MSG_SIMPLE_TAG; - break; - case SRP_ORDERED_TASK: - tag = MSG_ORDERED_TAG; - break; - case SRP_HEAD_TASK: - tag = MSG_HEAD_TAG; - break; - default: - eprintk("Task attribute %d not supported\n", cmd->task_attr); - tag = MSG_ORDERED_TAG; - } - - dir = srp_cmd_direction(cmd); - len = vscsis_data_length(cmd, dir); - - dprintk("%p %x %lx %d %d %d %llx\n", info, cmd->cdb[0], - cmd->lun, dir, len, tag, (unsigned long long) cmd->tag); - - sc = scsi_host_get_command(shost, dir, GFP_KERNEL); - if (!sc) - return -ENOMEM; - - sc->SCp.ptr = info; - memcpy(sc->cmnd, cmd->cdb, MAX_COMMAND_SIZE); - sc->sdb.length = len; - sc->sdb.table.sgl = (void *) (unsigned long) addr; - sc->tag = tag; - err = scsi_tgt_queue_command(sc, itn_id, (struct scsi_lun *)&cmd->lun, - cmd->tag); - if (err) - scsi_host_put_command(shost, sc); - - return err; -} -EXPORT_SYMBOL_GPL(srp_cmd_queue); - -MODULE_DESCRIPTION("SCSI RDMA Protocol lib functions"); -MODULE_AUTHOR("FUJITA Tomonori"); -MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/lpfc/lpfc_attr.c b/drivers/scsi/lpfc/lpfc_attr.c index 1d7a5c34ee8c..6eed9e76a166 100644 --- a/drivers/scsi/lpfc/lpfc_attr.c +++ b/drivers/scsi/lpfc/lpfc_attr.c @@ -1998,6 +1998,14 @@ lpfc_vport_param_show(name)\ lpfc_vport_param_init(name, defval, minval, maxval)\ static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL) +#define LPFC_VPORT_ULL_ATTR_R(name, defval, minval, maxval, desc) \ +static uint64_t lpfc_##name = defval;\ +module_param(lpfc_##name, ullong, S_IRUGO);\ +MODULE_PARM_DESC(lpfc_##name, desc);\ +lpfc_vport_param_show(name)\ +lpfc_vport_param_init(name, defval, minval, maxval)\ +static DEVICE_ATTR(lpfc_##name, S_IRUGO , lpfc_##name##_show, NULL) + #define LPFC_VPORT_ATTR_RW(name, defval, minval, maxval, desc) \ static uint lpfc_##name = defval;\ module_param(lpfc_##name, uint, S_IRUGO);\ @@ -4596,7 +4604,7 @@ LPFC_VPORT_ATTR(discovery_threads, 32, 1, 64, "Maximum number of ELS commands " # Value range is [0,65535]. Default value is 255. # NOTE: The SCSI layer might probe all allowed LUN on some old targets. */ -LPFC_VPORT_ATTR_R(max_luns, 255, 0, 65535, "Maximum allowed LUN ID"); +LPFC_VPORT_ULL_ATTR_R(max_luns, 255, 0, 65535, "Maximum allowed LUN ID"); /* # lpfc_poll_tmo: .Milliseconds driver will wait between polling FCP ring. diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 06f9a5b79e66..a5769a9960ac 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -8242,7 +8242,7 @@ lpfc_sli_enable_msix(struct lpfc_hba *phba) if (rc) { lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "0420 PCI enable MSI-X failed (%d)\n", rc); - goto msi_fail_out; + goto vec_fail_out; } for (i = 0; i < LPFC_MSIX_VECTORS; i++) lpfc_printf_log(phba, KERN_INFO, LOG_INIT, @@ -8320,6 +8320,8 @@ irq_fail_out: msi_fail_out: /* Unconfigure MSI-X capability structure */ pci_disable_msix(phba->pcidev); + +vec_fail_out: return rc; } @@ -8812,7 +8814,7 @@ enable_msix_vectors: } else if (rc) { lpfc_printf_log(phba, KERN_INFO, LOG_INIT, "0484 PCI enable MSI-X failed (%d)\n", rc); - goto msi_fail_out; + goto vec_fail_out; } /* Log MSI-X vector assignment */ @@ -8875,9 +8877,10 @@ cfg_fail_out: &phba->sli4_hba.fcp_eq_hdl[index]); } -msi_fail_out: /* Unconfigure MSI-X capability structure */ pci_disable_msix(phba->pcidev); + +vec_fail_out: return rc; } diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 2df11daad85b..7862c5540861 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -258,7 +258,7 @@ static void lpfc_send_sdev_queuedepth_change_event(struct lpfc_hba *phba, struct lpfc_vport *vport, struct lpfc_nodelist *ndlp, - uint32_t lun, + uint64_t lun, uint32_t old_val, uint32_t new_val) { @@ -3823,7 +3823,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, if (rsplen != 0 && rsplen != 4 && rsplen != 8) { lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, "2719 Invalid response length: " - "tgt x%x lun x%x cmnd x%x rsplen x%x\n", + "tgt x%x lun x%llx cmnd x%x rsplen x%x\n", cmnd->device->id, cmnd->device->lun, cmnd->cmnd[0], rsplen); @@ -3834,7 +3834,7 @@ lpfc_handle_fcp_err(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, "2757 Protocol failure detected during " "processing of FCP I/O op: " - "tgt x%x lun x%x cmnd x%x rspInfo3 x%x\n", + "tgt x%x lun x%llx cmnd x%x rspInfo3 x%x\n", cmnd->device->id, cmnd->device->lun, cmnd->cmnd[0], fcprsp->rspInfo3); @@ -4045,7 +4045,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, else logit = LOG_FCP | LOG_FCP_UNDER; lpfc_printf_vlog(vport, KERN_WARNING, logit, - "9030 FCP cmd x%x failed <%d/%d> " + "9030 FCP cmd x%x failed <%d/%lld> " "status: x%x result: x%x " "sid: x%x did: x%x oxid: x%x " "Data: x%x x%x\n", @@ -4157,7 +4157,7 @@ lpfc_scsi_cmd_iocb_cmpl(struct lpfc_hba *phba, struct lpfc_iocbq *pIocbIn, uint32_t *lp = (uint32_t *)cmd->sense_buffer; lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, - "0710 Iodone <%d/%d> cmd %p, error " + "0710 Iodone <%d/%llu> cmd %p, error " "x%x SNS x%x x%x Data: x%x x%x\n", cmd->device->id, cmd->device->lun, cmd, cmd->result, *lp, *(lp + 3), cmd->retries, @@ -4390,7 +4390,7 @@ lpfc_scsi_prep_cmnd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, static int lpfc_scsi_prep_task_mgmt_cmd(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd, - unsigned int lun, + uint64_t lun, uint8_t task_mgmt_cmd) { struct lpfc_iocbq *piocbq; @@ -4719,12 +4719,12 @@ lpfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd) atomic_dec(&ndlp->cmd_pending); lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, "3376 FCP could not issue IOCB err %x" - "FCP cmd x%x <%d/%d> " + "FCP cmd x%x <%d/%llu> " "sid: x%x did: x%x oxid: x%x " "Data: x%x x%x x%x x%x\n", err, cmnd->cmnd[0], cmnd->device ? cmnd->device->id : 0xffff, - cmnd->device ? cmnd->device->lun : 0xffff, + cmnd->device ? cmnd->device->lun : (u64) -1, vport->fc_myDID, ndlp->nlp_DID, phba->sli_rev == LPFC_SLI_REV4 ? lpfc_cmd->cur_iocbq.sli4_xritag : 0xffff, @@ -4807,7 +4807,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd) spin_unlock_irqrestore(&phba->hbalock, flags); lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, "2873 SCSI Layer I/O Abort Request IO CMPL Status " - "x%x ID %d LUN %d\n", + "x%x ID %d LUN %llu\n", SUCCESS, cmnd->device->id, cmnd->device->lun); return SUCCESS; } @@ -4924,7 +4924,7 @@ wait_for_cmpl: lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, "0748 abort handler timed out waiting " "for abortng I/O (xri:x%x) to complete: " - "ret %#x, ID %d, LUN %d\n", + "ret %#x, ID %d, LUN %llu\n", iocb->sli4_xritag, ret, cmnd->device->id, cmnd->device->lun); } @@ -4935,7 +4935,7 @@ out_unlock: out: lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP, "0749 SCSI Layer I/O Abort Request Status x%x ID %d " - "LUN %d\n", ret, cmnd->device->id, + "LUN %llu\n", ret, cmnd->device->id, cmnd->device->lun); return ret; } @@ -5047,7 +5047,7 @@ lpfc_check_fcp_rsp(struct lpfc_vport *vport, struct lpfc_scsi_buf *lpfc_cmd) **/ static int lpfc_send_taskmgmt(struct lpfc_vport *vport, struct lpfc_rport_data *rdata, - unsigned tgt_id, unsigned int lun_id, + unsigned tgt_id, uint64_t lun_id, uint8_t task_mgmt_cmd) { struct lpfc_hba *phba = vport->phba; @@ -5083,7 +5083,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct lpfc_rport_data *rdata, iocbq->iocb_cmpl = lpfc_tskmgmt_def_cmpl; lpfc_printf_vlog(vport, KERN_INFO, LOG_FCP, - "0702 Issue %s to TGT %d LUN %d " + "0702 Issue %s to TGT %d LUN %llu " "rpi x%x nlp_flag x%x Data: x%x x%x\n", lpfc_taskmgmt_name(task_mgmt_cmd), tgt_id, lun_id, pnode->nlp_rpi, pnode->nlp_flag, iocbq->sli4_xritag, @@ -5094,7 +5094,7 @@ lpfc_send_taskmgmt(struct lpfc_vport *vport, struct lpfc_rport_data *rdata, if ((status != IOCB_SUCCESS) || (iocbqrsp->iocb.ulpStatus != IOSTAT_SUCCESS)) { lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, - "0727 TMF %s to TGT %d LUN %d failed (%d, %d) " + "0727 TMF %s to TGT %d LUN %llu failed (%d, %d) " "iocb_flag x%x\n", lpfc_taskmgmt_name(task_mgmt_cmd), tgt_id, lun_id, iocbqrsp->iocb.ulpStatus, @@ -5238,7 +5238,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) struct lpfc_rport_data *rdata; struct lpfc_nodelist *pnode; unsigned tgt_id = cmnd->device->id; - unsigned int lun_id = cmnd->device->lun; + uint64_t lun_id = cmnd->device->lun; struct lpfc_scsi_event_header scsi_event; int status; @@ -5273,7 +5273,7 @@ lpfc_device_reset_handler(struct scsi_cmnd *cmnd) FCP_LUN_RESET); lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, - "0713 SCSI layer issued Device Reset (%d, %d) " + "0713 SCSI layer issued Device Reset (%d, %llu) " "return x%x\n", tgt_id, lun_id, status); /* @@ -5308,7 +5308,7 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd) struct lpfc_rport_data *rdata; struct lpfc_nodelist *pnode; unsigned tgt_id = cmnd->device->id; - unsigned int lun_id = cmnd->device->lun; + uint64_t lun_id = cmnd->device->lun; struct lpfc_scsi_event_header scsi_event; int status; @@ -5343,7 +5343,7 @@ lpfc_target_reset_handler(struct scsi_cmnd *cmnd) FCP_TARGET_RESET); lpfc_printf_vlog(vport, KERN_ERR, LOG_FCP, - "0723 SCSI layer issued Target Reset (%d, %d) " + "0723 SCSI layer issued Target Reset (%d, %llu) " "return x%x\n", tgt_id, lun_id, status); /* diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index b7770516f4c2..ac5d94cfd52f 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -1860,7 +1860,7 @@ megaraid_info(struct Scsi_Host *host) "LSI Logic MegaRAID %s %d commands %d targs %d chans %d luns", adapter->fw_version, adapter->product_info.max_commands, adapter->host->max_id, adapter->host->max_channel, - adapter->host->max_lun); + (u32)adapter->host->max_lun); return buffer; } @@ -1941,8 +1941,8 @@ megaraid_abort_and_reset(adapter_t *adapter, Scsi_Cmnd *cmd, int aor) printk(KERN_WARNING "megaraid: %s cmd=%x <c=%d t=%d l=%d>\n", (aor == SCB_ABORT)? "ABORTING":"RESET", - cmd->cmnd[0], cmd->device->channel, - cmd->device->id, cmd->device->lun); + cmd->cmnd[0], cmd->device->channel, + cmd->device->id, (u32)cmd->device->lun); if(list_empty(&adapter->pending_list)) return FALSE; diff --git a/drivers/scsi/megaraid/mega_common.h b/drivers/scsi/megaraid/mega_common.h index 5ead1283a844..1d037ed52c33 100644 --- a/drivers/scsi/megaraid/mega_common.h +++ b/drivers/scsi/megaraid/mega_common.h @@ -204,7 +204,7 @@ typedef struct { #define SCP2HOSTDATA(scp) SCP2HOST(scp)->hostdata // to soft state #define SCP2CHANNEL(scp) (scp)->device->channel // to channel #define SCP2TARGET(scp) (scp)->device->id // to target -#define SCP2LUN(scp) (scp)->device->lun // to LUN +#define SCP2LUN(scp) (u32)(scp)->device->lun // to LUN // generic macro to convert scsi command and host to controller's soft state #define SCSIHOST2ADAP(host) (((caddr_t *)(host->hostdata))[0]) diff --git a/drivers/scsi/megaraid/megaraid_sas_fusion.c b/drivers/scsi/megaraid/megaraid_sas_fusion.c index 22600419ae9f..3ed03dfab76c 100644 --- a/drivers/scsi/megaraid/megaraid_sas_fusion.c +++ b/drivers/scsi/megaraid/megaraid_sas_fusion.c @@ -1690,7 +1690,7 @@ NonFastPath: MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); } io_request->RaidContext.VirtualDiskTgtId = cpu_to_le16(device_id); - io_request->LUN[1] = scmd->device->lun; + int_to_scsilun(scmd->device->lun, (struct scsi_lun *)io_request->LUN); } /** @@ -1713,7 +1713,7 @@ megasas_build_io_fusion(struct megasas_instance *instance, device_id = MEGASAS_DEV_INDEX(instance, scp); /* Zero out some fields so they don't get reused */ - io_request->LUN[1] = 0; + memset(io_request->LUN, 0x0, 8); io_request->CDB.EEDP32.PrimaryReferenceTag = 0; io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0; io_request->EEDPFlags = 0; diff --git a/drivers/scsi/mesh.c b/drivers/scsi/mesh.c index e8a04ae3276a..7a6160f172ce 100644 --- a/drivers/scsi/mesh.c +++ b/drivers/scsi/mesh.c @@ -1230,7 +1230,7 @@ static void handle_msgin(struct mesh_state *ms) ms->msgphase = msg_out; } else if (code != cmd->device->lun + IDENTIFY_BASE) { printk(KERN_WARNING "mesh: lun mismatch " - "(%d != %d) on reselection from " + "(%d != %llu) on reselection from " "target %d\n", code - IDENTIFY_BASE, cmd->device->lun, ms->conn_tgt); } diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c index 8b88118e20e6..2f262be890c5 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.c +++ b/drivers/scsi/mpt2sas/mpt2sas_base.c @@ -277,7 +277,7 @@ mpt2sas_base_stop_watchdog(struct MPT2SAS_ADAPTER *ioc) ioc->fault_reset_work_q = NULL; spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); if (wq) { - if (!cancel_delayed_work(&ioc->fault_reset_work)) + if (!cancel_delayed_work_sync(&ioc->fault_reset_work)) flush_workqueue(wq); destroy_workqueue(wq); } @@ -1332,53 +1332,35 @@ _base_request_irq(struct MPT2SAS_ADAPTER *ioc, u8 index, u32 vector) static void _base_assign_reply_queues(struct MPT2SAS_ADAPTER *ioc) { - struct adapter_reply_queue *reply_q; - int cpu_id; - int cpu_grouping, loop, grouping, grouping_mod; + unsigned int cpu, nr_cpus, nr_msix, index = 0; if (!_base_is_controller_msix_enabled(ioc)) return; memset(ioc->cpu_msix_table, 0, ioc->cpu_msix_table_sz); - /* when there are more cpus than available msix vectors, - * then group cpus togeather on same irq - */ - if (ioc->cpu_count > ioc->msix_vector_count) { - grouping = ioc->cpu_count / ioc->msix_vector_count; - grouping_mod = ioc->cpu_count % ioc->msix_vector_count; - if (grouping < 2 || (grouping == 2 && !grouping_mod)) - cpu_grouping = 2; - else if (grouping < 4 || (grouping == 4 && !grouping_mod)) - cpu_grouping = 4; - else if (grouping < 8 || (grouping == 8 && !grouping_mod)) - cpu_grouping = 8; - else - cpu_grouping = 16; - } else - cpu_grouping = 0; - - loop = 0; - reply_q = list_entry(ioc->reply_queue_list.next, - struct adapter_reply_queue, list); - for_each_online_cpu(cpu_id) { - if (!cpu_grouping) { - ioc->cpu_msix_table[cpu_id] = reply_q->msix_index; - reply_q = list_entry(reply_q->list.next, - struct adapter_reply_queue, list); - } else { - if (loop < cpu_grouping) { - ioc->cpu_msix_table[cpu_id] = - reply_q->msix_index; - loop++; - } else { - reply_q = list_entry(reply_q->list.next, - struct adapter_reply_queue, list); - ioc->cpu_msix_table[cpu_id] = - reply_q->msix_index; - loop = 1; - } + + nr_cpus = num_online_cpus(); + nr_msix = ioc->reply_queue_count = min(ioc->reply_queue_count, + ioc->facts.MaxMSIxVectors); + if (!nr_msix) + return; + + cpu = cpumask_first(cpu_online_mask); + + do { + unsigned int i, group = nr_cpus / nr_msix; + + if (index < nr_cpus % nr_msix) + group++; + + for (i = 0 ; i < group ; i++) { + ioc->cpu_msix_table[cpu] = index; + cpu = cpumask_next(cpu, cpu_online_mask); } - } + + index++; + + } while (cpu < nr_cpus); } /** @@ -4295,12 +4277,13 @@ mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc) goto out_free_resources; if (ioc->is_warpdrive) { - ioc->reply_post_host_index[0] = - (resource_size_t *)&ioc->chip->ReplyPostHostIndex; + ioc->reply_post_host_index[0] = (resource_size_t __iomem *) + &ioc->chip->ReplyPostHostIndex; for (i = 1; i < ioc->cpu_msix_table_sz; i++) - ioc->reply_post_host_index[i] = (resource_size_t *) - ((u8 *)&ioc->chip->Doorbell + (0x4000 + ((i - 1) + ioc->reply_post_host_index[i] = + (resource_size_t __iomem *) + ((u8 __iomem *)&ioc->chip->Doorbell + (0x4000 + ((i - 1) * 4))); } diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h index fd3b998c75b1..0ac5815a7f91 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_base.h +++ b/drivers/scsi/mpt2sas/mpt2sas_base.h @@ -837,7 +837,7 @@ struct MPT2SAS_ADAPTER { u8 msix_enable; u16 msix_vector_count; u8 *cpu_msix_table; - resource_size_t **reply_post_host_index; + resource_size_t __iomem **reply_post_host_index; u16 cpu_msix_table_sz; u32 ioc_reset_count; MPT2SAS_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds; diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c index 5055f925d2cd..dd461015813f 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_scsih.c +++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c @@ -173,7 +173,7 @@ struct fw_event_work { u8 VP_ID; u8 ignore; u16 event; - void *event_data; + char event_data[0] __aligned(4); }; /* raid transport support */ @@ -1292,7 +1292,8 @@ _scsih_target_alloc(struct scsi_target *starget) unsigned long flags; struct sas_rphy *rphy; - sas_target_priv_data = kzalloc(sizeof(struct scsi_target), GFP_KERNEL); + sas_target_priv_data = kzalloc(sizeof(*sas_target_priv_data), + GFP_KERNEL); if (!sas_target_priv_data) return -ENOMEM; @@ -1406,7 +1407,8 @@ _scsih_slave_alloc(struct scsi_device *sdev) struct _sas_device *sas_device; unsigned long flags; - sas_device_priv_data = kzalloc(sizeof(struct scsi_device), GFP_KERNEL); + sas_device_priv_data = kzalloc(sizeof(*sas_device_priv_data), + GFP_KERNEL); if (!sas_device_priv_data) return -ENOMEM; @@ -2832,7 +2834,6 @@ _scsih_fw_event_free(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work spin_lock_irqsave(&ioc->fw_event_lock, flags); list_del(&fw_event->list); - kfree(fw_event->event_data); kfree(fw_event); spin_unlock_irqrestore(&ioc->fw_event_lock, flags); } @@ -2899,11 +2900,10 @@ _scsih_fw_event_cleanup_queue(struct MPT2SAS_ADAPTER *ioc) return; list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) { - if (cancel_delayed_work(&fw_event->delayed_work)) { + if (cancel_delayed_work_sync(&fw_event->delayed_work)) { _scsih_fw_event_free(ioc, fw_event); continue; } - fw_event->cancel_pending_work = 1; } } @@ -3518,7 +3518,8 @@ _scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc, if (fw_event->event != MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST || fw_event->ignore) continue; - local_event_data = fw_event->event_data; + local_event_data = (Mpi2EventDataSasTopologyChangeList_t *) + fw_event->event_data; if (local_event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED || local_event_data->ExpStatus == @@ -5502,7 +5503,9 @@ _scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, u64 sas_address; unsigned long flags; u8 link_rate, prev_link_rate; - Mpi2EventDataSasTopologyChangeList_t *event_data = fw_event->event_data; + Mpi2EventDataSasTopologyChangeList_t *event_data = + (Mpi2EventDataSasTopologyChangeList_t *) + fw_event->event_data; #ifdef CONFIG_SCSI_MPT2SAS_LOGGING if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) @@ -5697,7 +5700,8 @@ _scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc, u64 sas_address; unsigned long flags; Mpi2EventDataSasDeviceStatusChange_t *event_data = - fw_event->event_data; + (Mpi2EventDataSasDeviceStatusChange_t *) + fw_event->event_data; #ifdef CONFIG_SCSI_MPT2SAS_LOGGING if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) @@ -5792,6 +5796,7 @@ _scsih_sas_enclosure_dev_status_change_event(struct MPT2SAS_ADAPTER *ioc, #ifdef CONFIG_SCSI_MPT2SAS_LOGGING if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) _scsih_sas_enclosure_dev_status_change_event_debug(ioc, + (Mpi2EventDataSasEnclDevStatusChange_t *) fw_event->event_data); #endif } @@ -5816,7 +5821,9 @@ _scsih_sas_broadcast_primitive_event(struct MPT2SAS_ADAPTER *ioc, u32 termination_count; u32 query_count; Mpi2SCSITaskManagementReply_t *mpi_reply; - Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data; + Mpi2EventDataSasBroadcastPrimitive_t *event_data = + (Mpi2EventDataSasBroadcastPrimitive_t *) + fw_event->event_data; u16 ioc_status; unsigned long flags; int r; @@ -5967,7 +5974,9 @@ static void _scsih_sas_discovery_event(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { - Mpi2EventDataSasDiscovery_t *event_data = fw_event->event_data; + Mpi2EventDataSasDiscovery_t *event_data = + (Mpi2EventDataSasDiscovery_t *) + fw_event->event_data; #ifdef CONFIG_SCSI_MPT2SAS_LOGGING if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) { @@ -6355,7 +6364,9 @@ _scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc, Mpi2EventIrConfigElement_t *element; int i; u8 foreign_config; - Mpi2EventDataIrConfigChangeList_t *event_data = fw_event->event_data; + Mpi2EventDataIrConfigChangeList_t *event_data = + (Mpi2EventDataIrConfigChangeList_t *) + fw_event->event_data; #ifdef CONFIG_SCSI_MPT2SAS_LOGGING if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) @@ -6423,7 +6434,9 @@ _scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc, u16 handle; u32 state; int rc; - Mpi2EventDataIrVolume_t *event_data = fw_event->event_data; + Mpi2EventDataIrVolume_t *event_data = + (Mpi2EventDataIrVolume_t *) + fw_event->event_data; if (ioc->shost_recovery) return; @@ -6507,7 +6520,9 @@ _scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t mpi_reply; Mpi2SasDevicePage0_t sas_device_pg0; u32 ioc_status; - Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data; + Mpi2EventDataIrPhysicalDisk_t *event_data = + (Mpi2EventDataIrPhysicalDisk_t *) + fw_event->event_data; u64 sas_address; if (ioc->shost_recovery) @@ -6630,7 +6645,9 @@ static void _scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { - Mpi2EventDataIrOperationStatus_t *event_data = fw_event->event_data; + Mpi2EventDataIrOperationStatus_t *event_data = + (Mpi2EventDataIrOperationStatus_t *) + fw_event->event_data; static struct _raid_device *raid_device; unsigned long flags; u16 handle; @@ -7401,7 +7418,7 @@ _firmware_event_work(struct work_struct *work) struct MPT2SAS_ADAPTER *ioc = fw_event->ioc; /* the queue is being flushed so ignore this event */ - if (ioc->remove_host || fw_event->cancel_pending_work || + if (ioc->remove_host || ioc->pci_error_recovery) { _scsih_fw_event_free(ioc, fw_event); return; @@ -7590,23 +7607,15 @@ mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 msix_index, return; } - fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); - if (!fw_event) { - printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } sz = le16_to_cpu(mpi_reply->EventDataLength) * 4; - fw_event->event_data = kzalloc(sz, GFP_ATOMIC); - if (!fw_event->event_data) { + fw_event = kzalloc(sizeof(*fw_event) + sz, GFP_ATOMIC); + if (!fw_event) { printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, __func__); - kfree(fw_event); return; } - memcpy(fw_event->event_data, mpi_reply->EventData, - sz); + memcpy(fw_event->event_data, mpi_reply->EventData, sz); fw_event->ioc = ioc; fw_event->VF_ID = mpi_reply->VF_ID; fw_event->VP_ID = mpi_reply->VP_ID; @@ -7857,9 +7866,9 @@ _scsih_remove(struct pci_dev *pdev) } sas_remove_host(shost); + scsi_remove_host(shost); mpt2sas_base_detach(ioc); list_del(&ioc->list); - scsi_remove_host(shost); scsi_host_put(shost); } @@ -8200,13 +8209,6 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) } } - if ((scsi_add_host(shost, &pdev->dev))) { - printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - list_del(&ioc->list); - goto out_add_shost_fail; - } - /* register EEDP capabilities with SCSI layer */ if (prot_mask) scsi_host_set_prot(shost, prot_mask); @@ -8248,16 +8250,23 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) } } else ioc->hide_drives = 0; + + if ((scsi_add_host(shost, &pdev->dev))) { + printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + goto out_add_shost_fail; + } + scsi_scan_host(shost); return 0; + out_add_shost_fail: + mpt2sas_base_detach(ioc); out_attach_fail: destroy_workqueue(ioc->firmware_event_thread); out_thread_fail: list_del(&ioc->list); - scsi_remove_host(shost); - out_add_shost_fail: scsi_host_put(shost); return -ENODEV; } diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c index 0cf4f7000f94..93ce2b2baa41 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_base.c +++ b/drivers/scsi/mpt3sas/mpt3sas_base.c @@ -266,7 +266,7 @@ mpt3sas_base_stop_watchdog(struct MPT3SAS_ADAPTER *ioc) ioc->fault_reset_work_q = NULL; spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); if (wq) { - if (!cancel_delayed_work(&ioc->fault_reset_work)) + if (!cancel_delayed_work_sync(&ioc->fault_reset_work)) flush_workqueue(wq); destroy_workqueue(wq); } @@ -1624,66 +1624,35 @@ _base_request_irq(struct MPT3SAS_ADAPTER *ioc, u8 index, u32 vector) static void _base_assign_reply_queues(struct MPT3SAS_ADAPTER *ioc) { - struct adapter_reply_queue *reply_q; - int cpu_id; - int cpu_grouping, loop, grouping, grouping_mod; - int reply_queue; + unsigned int cpu, nr_cpus, nr_msix, index = 0; if (!_base_is_controller_msix_enabled(ioc)) return; memset(ioc->cpu_msix_table, 0, ioc->cpu_msix_table_sz); - /* NUMA Hardware bug workaround - drop to less reply queues */ - if (ioc->reply_queue_count > ioc->facts.MaxMSIxVectors) { - ioc->reply_queue_count = ioc->facts.MaxMSIxVectors; - reply_queue = 0; - list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { - reply_q->msix_index = reply_queue; - if (++reply_queue == ioc->reply_queue_count) - reply_queue = 0; - } - } + nr_cpus = num_online_cpus(); + nr_msix = ioc->reply_queue_count = min(ioc->reply_queue_count, + ioc->facts.MaxMSIxVectors); + if (!nr_msix) + return; - /* when there are more cpus than available msix vectors, - * then group cpus togeather on same irq - */ - if (ioc->cpu_count > ioc->msix_vector_count) { - grouping = ioc->cpu_count / ioc->msix_vector_count; - grouping_mod = ioc->cpu_count % ioc->msix_vector_count; - if (grouping < 2 || (grouping == 2 && !grouping_mod)) - cpu_grouping = 2; - else if (grouping < 4 || (grouping == 4 && !grouping_mod)) - cpu_grouping = 4; - else if (grouping < 8 || (grouping == 8 && !grouping_mod)) - cpu_grouping = 8; - else - cpu_grouping = 16; - } else - cpu_grouping = 0; - - loop = 0; - reply_q = list_entry(ioc->reply_queue_list.next, - struct adapter_reply_queue, list); - for_each_online_cpu(cpu_id) { - if (!cpu_grouping) { - ioc->cpu_msix_table[cpu_id] = reply_q->msix_index; - reply_q = list_entry(reply_q->list.next, - struct adapter_reply_queue, list); - } else { - if (loop < cpu_grouping) { - ioc->cpu_msix_table[cpu_id] = - reply_q->msix_index; - loop++; - } else { - reply_q = list_entry(reply_q->list.next, - struct adapter_reply_queue, list); - ioc->cpu_msix_table[cpu_id] = - reply_q->msix_index; - loop = 1; - } + cpu = cpumask_first(cpu_online_mask); + + do { + unsigned int i, group = nr_cpus / nr_msix; + + if (index < nr_cpus % nr_msix) + group++; + + for (i = 0 ; i < group ; i++) { + ioc->cpu_msix_table[cpu] = index; + cpu = cpumask_next(cpu, cpu_online_mask); } - } + + index++; + + } while (cpu < nr_cpus); } /** diff --git a/drivers/scsi/mpt3sas/mpt3sas_scsih.c b/drivers/scsi/mpt3sas/mpt3sas_scsih.c index 18e713db1d32..7cf48c5c15a7 100644 --- a/drivers/scsi/mpt3sas/mpt3sas_scsih.c +++ b/drivers/scsi/mpt3sas/mpt3sas_scsih.c @@ -112,8 +112,8 @@ MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay"); /* scsi-mid layer global parmeter is max_report_luns, which is 511 */ #define MPT3SAS_MAX_LUN (16895) -static int max_lun = MPT3SAS_MAX_LUN; -module_param(max_lun, int, 0); +static u64 max_lun = MPT3SAS_MAX_LUN; +module_param(max_lun, ullong, 0); MODULE_PARM_DESC(max_lun, " max lun, default=16895 "); @@ -190,7 +190,7 @@ struct fw_event_work { u8 VP_ID; u8 ignore; u16 event; - void *event_data; + char event_data[0] __aligned(4); }; /* raid transport support */ @@ -1163,7 +1163,8 @@ _scsih_target_alloc(struct scsi_target *starget) unsigned long flags; struct sas_rphy *rphy; - sas_target_priv_data = kzalloc(sizeof(struct scsi_target), GFP_KERNEL); + sas_target_priv_data = kzalloc(sizeof(*sas_target_priv_data), + GFP_KERNEL); if (!sas_target_priv_data) return -ENOMEM; @@ -1277,7 +1278,8 @@ _scsih_slave_alloc(struct scsi_device *sdev) struct _sas_device *sas_device; unsigned long flags; - sas_device_priv_data = kzalloc(sizeof(struct scsi_device), GFP_KERNEL); + sas_device_priv_data = kzalloc(sizeof(*sas_device_priv_data), + GFP_KERNEL); if (!sas_device_priv_data) return -ENOMEM; @@ -2490,7 +2492,6 @@ _scsih_fw_event_free(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work spin_lock_irqsave(&ioc->fw_event_lock, flags); list_del(&fw_event->list); - kfree(fw_event->event_data); kfree(fw_event); spin_unlock_irqrestore(&ioc->fw_event_lock, flags); } @@ -2511,12 +2512,10 @@ mpt3sas_send_trigger_data_event(struct MPT3SAS_ADAPTER *ioc, if (ioc->is_driver_loading) return; - fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); + fw_event = kzalloc(sizeof(*fw_event) + sizeof(*event_data), + GFP_ATOMIC); if (!fw_event) return; - fw_event->event_data = kzalloc(sizeof(*event_data), GFP_ATOMIC); - if (!fw_event->event_data) - return; fw_event->event = MPT3SAS_PROCESS_TRIGGER_DIAG; fw_event->ioc = ioc; memcpy(fw_event->event_data, event_data, sizeof(*event_data)); @@ -2582,11 +2581,10 @@ _scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc) return; list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) { - if (cancel_delayed_work(&fw_event->delayed_work)) { + if (cancel_delayed_work_sync(&fw_event->delayed_work)) { _scsih_fw_event_free(ioc, fw_event); continue; } - fw_event->cancel_pending_work = 1; } } @@ -3211,7 +3209,8 @@ _scsih_check_topo_delete_events(struct MPT3SAS_ADAPTER *ioc, if (fw_event->event != MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST || fw_event->ignore) continue; - local_event_data = fw_event->event_data; + local_event_data = (Mpi2EventDataSasTopologyChangeList_t *) + fw_event->event_data; if (local_event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED || local_event_data->ExpStatus == @@ -5043,7 +5042,9 @@ _scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc, u64 sas_address; unsigned long flags; u8 link_rate, prev_link_rate; - Mpi2EventDataSasTopologyChangeList_t *event_data = fw_event->event_data; + Mpi2EventDataSasTopologyChangeList_t *event_data = + (Mpi2EventDataSasTopologyChangeList_t *) + fw_event->event_data; #ifdef CONFIG_SCSI_MPT3SAS_LOGGING if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) @@ -5241,7 +5242,8 @@ _scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc, u64 sas_address; unsigned long flags; Mpi2EventDataSasDeviceStatusChange_t *event_data = - fw_event->event_data; + (Mpi2EventDataSasDeviceStatusChange_t *) + fw_event->event_data; #ifdef CONFIG_SCSI_MPT3SAS_LOGGING if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) @@ -5337,6 +5339,7 @@ _scsih_sas_enclosure_dev_status_change_event(struct MPT3SAS_ADAPTER *ioc, #ifdef CONFIG_SCSI_MPT3SAS_LOGGING if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) _scsih_sas_enclosure_dev_status_change_event_debug(ioc, + (Mpi2EventDataSasEnclDevStatusChange_t *) fw_event->event_data); #endif } @@ -5361,7 +5364,9 @@ _scsih_sas_broadcast_primitive_event(struct MPT3SAS_ADAPTER *ioc, u32 termination_count; u32 query_count; Mpi2SCSITaskManagementReply_t *mpi_reply; - Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data; + Mpi2EventDataSasBroadcastPrimitive_t *event_data = + (Mpi2EventDataSasBroadcastPrimitive_t *) + fw_event->event_data; u16 ioc_status; unsigned long flags; int r; @@ -5513,7 +5518,8 @@ static void _scsih_sas_discovery_event(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { - Mpi2EventDataSasDiscovery_t *event_data = fw_event->event_data; + Mpi2EventDataSasDiscovery_t *event_data = + (Mpi2EventDataSasDiscovery_t *) fw_event->event_data; #ifdef CONFIG_SCSI_MPT3SAS_LOGGING if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) { @@ -5999,7 +6005,9 @@ _scsih_sas_ir_config_change_event(struct MPT3SAS_ADAPTER *ioc, Mpi2EventIrConfigElement_t *element; int i; u8 foreign_config; - Mpi2EventDataIrConfigChangeList_t *event_data = fw_event->event_data; + Mpi2EventDataIrConfigChangeList_t *event_data = + (Mpi2EventDataIrConfigChangeList_t *) + fw_event->event_data; #ifdef CONFIG_SCSI_MPT3SAS_LOGGING if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) @@ -6069,7 +6077,8 @@ _scsih_sas_ir_volume_event(struct MPT3SAS_ADAPTER *ioc, u16 handle; u32 state; int rc; - Mpi2EventDataIrVolume_t *event_data = fw_event->event_data; + Mpi2EventDataIrVolume_t *event_data = + (Mpi2EventDataIrVolume_t *) fw_event->event_data; if (ioc->shost_recovery) return; @@ -6152,7 +6161,8 @@ _scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t mpi_reply; Mpi2SasDevicePage0_t sas_device_pg0; u32 ioc_status; - Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data; + Mpi2EventDataIrPhysicalDisk_t *event_data = + (Mpi2EventDataIrPhysicalDisk_t *) fw_event->event_data; u64 sas_address; if (ioc->shost_recovery) @@ -6272,7 +6282,9 @@ static void _scsih_sas_ir_operation_status_event(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { - Mpi2EventDataIrOperationStatus_t *event_data = fw_event->event_data; + Mpi2EventDataIrOperationStatus_t *event_data = + (Mpi2EventDataIrOperationStatus_t *) + fw_event->event_data; static struct _raid_device *raid_device; unsigned long flags; u16 handle; @@ -7026,7 +7038,7 @@ static void _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) { /* the queue is being flushed so ignore this event */ - if (ioc->remove_host || fw_event->cancel_pending_work || + if (ioc->remove_host || ioc->pci_error_recovery) { _scsih_fw_event_free(ioc, fw_event); return; @@ -7034,7 +7046,9 @@ _mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) switch (fw_event->event) { case MPT3SAS_PROCESS_TRIGGER_DIAG: - mpt3sas_process_trigger_data(ioc, fw_event->event_data); + mpt3sas_process_trigger_data(ioc, + (struct SL_WH_TRIGGERS_EVENT_DATA_T *) + fw_event->event_data); break; case MPT3SAS_REMOVE_UNRESPONDING_DEVICES: while (scsi_host_in_recovery(ioc->shost) || ioc->shost_recovery) @@ -7192,18 +7206,11 @@ mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, return 1; } - fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); - if (!fw_event) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return 1; - } sz = le16_to_cpu(mpi_reply->EventDataLength) * 4; - fw_event->event_data = kzalloc(sz, GFP_ATOMIC); - if (!fw_event->event_data) { + fw_event = kzalloc(sizeof(*fw_event) + sz, GFP_ATOMIC); + if (!fw_event) { pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, __func__); - kfree(fw_event); return 1; } @@ -7431,9 +7438,9 @@ static void _scsih_remove(struct pci_dev *pdev) } sas_remove_host(shost); + scsi_remove_host(shost); mpt3sas_base_detach(ioc); list_del(&ioc->list); - scsi_remove_host(shost); scsi_host_put(shost); } @@ -7801,13 +7808,6 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) } } - if ((scsi_add_host(shost, &pdev->dev))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - list_del(&ioc->list); - goto out_add_shost_fail; - } - /* register EEDP capabilities with SCSI layer */ if (prot_mask > 0) scsi_host_set_prot(shost, prot_mask); @@ -7835,15 +7835,21 @@ _scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) ioc->name, __FILE__, __LINE__, __func__); goto out_attach_fail; } + if ((scsi_add_host(shost, &pdev->dev))) { + pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", + ioc->name, __FILE__, __LINE__, __func__); + list_del(&ioc->list); + goto out_add_shost_fail; + } + scsi_scan_host(shost); return 0; - +out_add_shost_fail: + mpt3sas_base_detach(ioc); out_attach_fail: destroy_workqueue(ioc->firmware_event_thread); out_thread_fail: list_del(&ioc->list); - scsi_remove_host(shost); - out_add_shost_fail: scsi_host_put(shost); return -ENODEV; } diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index 7d014b11df62..a7305ffc359d 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -6633,7 +6633,7 @@ static void ncr_sir_to_redo(struct ncb *np, int num, struct ccb *cp) ** patch requested size into sense command */ cp->sensecmd[0] = 0x03; - cp->sensecmd[1] = cmd->device->lun << 5; + cp->sensecmd[1] = (cmd->device->lun & 0x7) << 5; cp->sensecmd[4] = sizeof(cp->sense_buf); /* diff --git a/drivers/scsi/ncr53c8xx.h b/drivers/scsi/ncr53c8xx.h index 0e008dacf679..02901c54b08b 100644 --- a/drivers/scsi/ncr53c8xx.h +++ b/drivers/scsi/ncr53c8xx.h @@ -264,11 +264,7 @@ #define SCSI_NCR_SG_TABLESIZE (SCSI_NCR_MAX_SCATTER) #define SCSI_NCR_TIMER_INTERVAL (HZ) -#if 1 /* defined CONFIG_SCSI_MULTI_LUN */ #define SCSI_NCR_MAX_LUN (16) -#else -#define SCSI_NCR_MAX_LUN (1) -#endif /* * IO functions definition for big/little endian CPU support. diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c index 0665f9cfdb02..50b086aef178 100644 --- a/drivers/scsi/nsp32.c +++ b/drivers/scsi/nsp32.c @@ -915,7 +915,7 @@ static int nsp32_queuecommand_lck(struct scsi_cmnd *SCpnt, void (*done)(struct s int ret; nsp32_dbg(NSP32_DEBUG_QUEUECOMMAND, - "enter. target: 0x%x LUN: 0x%x cmnd: 0x%x cmndlen: 0x%x " + "enter. target: 0x%x LUN: 0x%llu cmnd: 0x%x cmndlen: 0x%x " "use_sg: 0x%x reqbuf: 0x%lx reqlen: 0x%x", SCpnt->device->id, SCpnt->device->lun, SCpnt->cmnd[0], SCpnt->cmd_len, scsi_sg_count(SCpnt), scsi_sglist(SCpnt), scsi_bufflen(SCpnt)); diff --git a/drivers/scsi/pas16.c b/drivers/scsi/pas16.c index 0d78a4d5576c..80bacb5dc1d4 100644 --- a/drivers/scsi/pas16.c +++ b/drivers/scsi/pas16.c @@ -607,8 +607,6 @@ static int pas16_release(struct Scsi_Host *shost) if (shost->irq) free_irq(shost->irq, shost); NCR5380_exit(shost); - if (shost->dma_channel != 0xff) - free_dma(shost->dma_channel); if (shost->io_port && shost->n_io_port) release_region(shost->io_port, shost->n_io_port); scsi_unregister(shost); diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index 987fbb1b244e..340ceff03823 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -195,7 +195,7 @@ static int nsp_queuecommand_lck(struct scsi_cmnd *SCpnt, nsp_hw_data *data = (nsp_hw_data *)SCpnt->device->host->hostdata; nsp_dbg(NSP_DEBUG_QUEUECOMMAND, - "SCpnt=0x%p target=%d lun=%d sglist=0x%p bufflen=%d sg_count=%d", + "SCpnt=0x%p target=%d lun=%llu sglist=0x%p bufflen=%d sg_count=%d", SCpnt, target, SCpnt->device->lun, scsi_sglist(SCpnt), scsi_bufflen(SCpnt), scsi_sg_count(SCpnt)); //nsp_dbg(NSP_DEBUG_QUEUECOMMAND, "before CurrentSC=0x%p", data->CurrentSC); diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index f5b52731abd9..155f9573021f 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c @@ -558,7 +558,7 @@ SYM53C500_queue_lck(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", SCpnt->cmnd[0], SCpnt->cmd_len, SCpnt->device->id, - SCpnt->device->lun, scsi_bufflen(SCpnt))); + (u8)SCpnt->device->lun, scsi_bufflen(SCpnt))); VDEB(for (i = 0; i < SCpnt->cmd_len; i++) printk("cmd[%d]=%02x ", i, SCpnt->cmnd[i])); diff --git a/drivers/scsi/pm8001/pm8001_ctl.c b/drivers/scsi/pm8001/pm8001_ctl.c index a368d77b8d41..d3a08aea0948 100644 --- a/drivers/scsi/pm8001/pm8001_ctl.c +++ b/drivers/scsi/pm8001/pm8001_ctl.c @@ -397,7 +397,10 @@ static ssize_t pm8001_ctl_bios_version_show(struct device *cdev, payload.func_specific = kzalloc(4096, GFP_KERNEL); if (!payload.func_specific) return -ENOMEM; - PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); + if (PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload)) { + kfree(payload.func_specific); + return -ENOMEM; + } wait_for_completion(&completion); virt_addr = pm8001_ha->memoryMap.region[NVMD].virt_ptr; for (bios_index = BIOSOFFSET; bios_index < BIOS_OFFSET_LIMIT; @@ -614,11 +617,11 @@ static int pm8001_update_flash(struct pm8001_hba_info *pm8001_ha) pm8001_ha->nvmd_completion = &completion; ret = PM8001_CHIP_DISP->fw_flash_update_req(pm8001_ha, payload); + if (ret) + break; wait_for_completion(&completion); - if (ret || (fwControl->retcode > FLASH_UPDATE_IN_PROGRESS)) { + if (fwControl->retcode > FLASH_UPDATE_IN_PROGRESS) { ret = fwControl->retcode; - kfree(ioctlbuffer); - ioctlbuffer = NULL; break; } } diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index a97be015e52e..173831016f5f 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -1346,7 +1346,7 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha, &pMessage) < 0) { PM8001_IO_DBG(pm8001_ha, pm8001_printk("No free mpi buffer\n")); - return -1; + return -ENOMEM; } BUG_ON(!payload); /*Copy to the payload*/ @@ -1751,6 +1751,8 @@ static void pm8001_send_abort_all(struct pm8001_hba_info *pm8001_ha, task_abort.tag = cpu_to_le32(ccb_tag); ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0); + if (ret) + pm8001_tag_free(pm8001_ha, ccb_tag); } @@ -1778,6 +1780,7 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha, res = pm8001_tag_alloc(pm8001_ha, &ccb_tag); if (res) { + sas_free_task(task); PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("cannot allocate tag !!!\n")); return; @@ -1788,14 +1791,14 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha, */ dev = kzalloc(sizeof(struct domain_device), GFP_ATOMIC); if (!dev) { + sas_free_task(task); + pm8001_tag_free(pm8001_ha, ccb_tag); PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Domain device cannot be allocated\n")); - sas_free_task(task); return; - } else { - task->dev = dev; - task->dev->lldd_dev = pm8001_ha_dev; } + task->dev = dev; + task->dev->lldd_dev = pm8001_ha_dev; ccb = &pm8001_ha->ccb_info[ccb_tag]; ccb->device = pm8001_ha_dev; @@ -1821,7 +1824,11 @@ static void pm8001_send_read_log(struct pm8001_hba_info *pm8001_ha, memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis)); res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0); - + if (res) { + sas_free_task(task); + pm8001_tag_free(pm8001_ha, ccb_tag); + kfree(dev); + } } /** @@ -3100,7 +3107,7 @@ void pm8001_mpi_set_dev_state_resp(struct pm8001_hba_info *pm8001_ha, complete(pm8001_dev->setds_completion); ccb->task = NULL; ccb->ccb_tag = 0xFFFFFFFF; - pm8001_ccb_free(pm8001_ha, tag); + pm8001_tag_free(pm8001_ha, tag); } void pm8001_mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) @@ -3119,13 +3126,12 @@ void pm8001_mpi_set_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) } ccb->task = NULL; ccb->ccb_tag = 0xFFFFFFFF; - pm8001_ccb_free(pm8001_ha, tag); + pm8001_tag_free(pm8001_ha, tag); } void pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) { - struct fw_control_ex *fw_control_context; struct get_nvm_data_resp *pPayload = (struct get_nvm_data_resp *)(piomb + 4); u32 tag = le32_to_cpu(pPayload->tag); @@ -3134,7 +3140,6 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) u32 ir_tds_bn_dps_das_nvm = le32_to_cpu(pPayload->ir_tda_bn_dps_das_nvm); void *virt_addr = pm8001_ha->memoryMap.region[NVMD].virt_ptr; - fw_control_context = ccb->fw_control_context; PM8001_MSG_DBG(pm8001_ha, pm8001_printk("Get nvm data complete!\n")); if ((dlen_status & NVMD_STAT) != 0) { @@ -3175,13 +3180,11 @@ pm8001_mpi_get_nvmd_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) pm8001_printk("Get NVMD success, IR=0, dataLen=%d\n", (dlen_status & NVMD_LEN) >> 24)); } - memcpy(fw_control_context->usrAddr, - pm8001_ha->memoryMap.region[NVMD].virt_ptr, - fw_control_context->len); - complete(pm8001_ha->nvmd_completion); + kfree(ccb->fw_control_context); ccb->task = NULL; ccb->ccb_tag = 0xFFFFFFFF; - pm8001_ccb_free(pm8001_ha, tag); + pm8001_tag_free(pm8001_ha, tag); + complete(pm8001_ha->nvmd_completion); } int pm8001_mpi_local_phy_ctl(struct pm8001_hba_info *pm8001_ha, void *piomb) @@ -3588,7 +3591,7 @@ int pm8001_mpi_reg_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) complete(pm8001_dev->dcompletion); ccb->task = NULL; ccb->ccb_tag = 0xFFFFFFFF; - pm8001_ccb_free(pm8001_ha, htag); + pm8001_tag_free(pm8001_ha, htag); return 0; } @@ -3617,15 +3620,11 @@ int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha, void *piomb) { u32 status; - struct fw_control_ex fw_control_context; struct fw_flash_Update_resp *ppayload = (struct fw_flash_Update_resp *)(piomb + 4); u32 tag = le32_to_cpu(ppayload->tag); struct pm8001_ccb_info *ccb = &pm8001_ha->ccb_info[tag]; status = le32_to_cpu(ppayload->status); - memcpy(&fw_control_context, - ccb->fw_control_context, - sizeof(fw_control_context)); switch (status) { case FLASH_UPDATE_COMPLETE_PENDING_REBOOT: PM8001_MSG_DBG(pm8001_ha, @@ -3668,11 +3667,11 @@ int pm8001_mpi_fw_flash_update_resp(struct pm8001_hba_info *pm8001_ha, pm8001_printk("No matched status = %d\n", status)); break; } - ccb->fw_control_context->fw_control->retcode = status; - complete(pm8001_ha->nvmd_completion); + kfree(ccb->fw_control_context); ccb->task = NULL; ccb->ccb_tag = 0xFFFFFFFF; - pm8001_ccb_free(pm8001_ha, tag); + pm8001_tag_free(pm8001_ha, tag); + complete(pm8001_ha->nvmd_completion); return 0; } @@ -4257,7 +4256,11 @@ static int pm8001_chip_smp_req(struct pm8001_hba_info *pm8001_ha, smp_cmd.long_smp_req.long_resp_size = cpu_to_le32((u32)sg_dma_len(&task->smp_task.smp_resp)-4); build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag, &smp_cmd); - pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, (u32 *)&smp_cmd, 0); + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, + (u32 *)&smp_cmd, 0); + if (rc) + goto err_out_2; + return 0; err_out_2: @@ -4398,7 +4401,7 @@ static int pm8001_chip_sata_req(struct pm8001_hba_info *pm8001_ha, /* Check for read log for failed drive and return */ if (sata_cmd.sata_fis.command == 0x2f) { - if (pm8001_ha_dev && ((pm8001_ha_dev->id & NCQ_READ_LOG_FLAG) || + if (((pm8001_ha_dev->id & NCQ_READ_LOG_FLAG) || (pm8001_ha_dev->id & NCQ_ABORT_ALL_FLAG) || (pm8001_ha_dev->id & NCQ_2ND_RLE_FLAG))) { struct task_status_struct *ts; @@ -4789,6 +4792,10 @@ int pm8001_chip_get_nvmd_req(struct pm8001_hba_info *pm8001_ha, break; } rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req, 0); + if (rc) { + kfree(fw_control_context); + pm8001_tag_free(pm8001_ha, tag); + } return rc; } @@ -4869,6 +4876,10 @@ int pm8001_chip_set_nvmd_req(struct pm8001_hba_info *pm8001_ha, break; } rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &nvmd_req, 0); + if (rc) { + kfree(fw_control_context); + pm8001_tag_free(pm8001_ha, tag); + } return rc; } @@ -5061,7 +5072,7 @@ pm8001_chip_sas_re_initialization(struct pm8001_hba_info *pm8001_ha) memset(&payload, 0, sizeof(payload)); rc = pm8001_tag_alloc(pm8001_ha, &tag); if (rc) - return -1; + return -ENOMEM; ccb = &pm8001_ha->ccb_info[tag]; ccb->ccb_tag = tag; circularQ = &pm8001_ha->inbnd_q_tbl[0]; @@ -5070,6 +5081,8 @@ pm8001_chip_sas_re_initialization(struct pm8001_hba_info *pm8001_ha) payload.sata_hol_tmo = cpu_to_le32(80); payload.open_reject_cmdretries_data_retries = cpu_to_le32(0xff00ff); rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + if (rc) + pm8001_tag_free(pm8001_ha, tag); return rc; } diff --git a/drivers/scsi/pm8001/pm8001_init.c b/drivers/scsi/pm8001/pm8001_init.c index e90c89f1d480..e49623a897a7 100644 --- a/drivers/scsi/pm8001/pm8001_init.c +++ b/drivers/scsi/pm8001/pm8001_init.c @@ -246,6 +246,7 @@ static int pm8001_alloc(struct pm8001_hba_info *pm8001_ha, { int i; spin_lock_init(&pm8001_ha->lock); + spin_lock_init(&pm8001_ha->bitmap_lock); PM8001_INIT_DBG(pm8001_ha, pm8001_printk("pm8001_alloc: PHY:%x\n", pm8001_ha->chip->n_phy)); @@ -621,6 +622,8 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) DECLARE_COMPLETION_ONSTACK(completion); struct pm8001_ioctl_payload payload; u16 deviceid; + int rc; + pci_read_config_word(pm8001_ha->pdev, PCI_DEVICE_ID, &deviceid); pm8001_ha->nvmd_completion = &completion; @@ -638,7 +641,16 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) } payload.offset = 0; payload.func_specific = kzalloc(payload.length, GFP_KERNEL); - PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); + if (!payload.func_specific) { + PM8001_INIT_DBG(pm8001_ha, pm8001_printk("mem alloc fail\n")); + return; + } + rc = PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); + if (rc) { + kfree(payload.func_specific); + PM8001_INIT_DBG(pm8001_ha, pm8001_printk("nvmd failed\n")); + return; + } wait_for_completion(&completion); for (i = 0, j = 0; i <= 7; i++, j++) { @@ -661,6 +673,7 @@ static void pm8001_init_sas_add(struct pm8001_hba_info *pm8001_ha) pm8001_printk("phy %d sas_addr = %016llx\n", i, pm8001_ha->phy[i].dev_sas_addr)); } + kfree(payload.func_specific); #else for (i = 0; i < pm8001_ha->chip->n_phy; i++) { pm8001_ha->phy[i].dev_sas_addr = 0x50010c600047f9d0ULL; @@ -684,6 +697,7 @@ static int pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha) /*OPTION ROM FLASH read for the SPC cards */ DECLARE_COMPLETION_ONSTACK(completion); struct pm8001_ioctl_payload payload; + int rc; pm8001_ha->nvmd_completion = &completion; /* SAS ADDRESS read from flash / EEPROM */ @@ -694,7 +708,12 @@ static int pm8001_get_phy_settings_info(struct pm8001_hba_info *pm8001_ha) if (!payload.func_specific) return -ENOMEM; /* Read phy setting values from flash */ - PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); + rc = PM8001_CHIP_DISP->get_nvmd_req(pm8001_ha, &payload); + if (rc) { + kfree(payload.func_specific); + PM8001_INIT_DBG(pm8001_ha, pm8001_printk("nvmd failed\n")); + return -ENOMEM; + } wait_for_completion(&completion); pm8001_set_phy_profile(pm8001_ha, sizeof(u8), payload.func_specific); kfree(payload.func_specific); @@ -744,9 +763,10 @@ static u32 pm8001_setup_msix(struct pm8001_hba_info *pm8001_ha) pm8001_ha->irq_vector[i].irq_id = i; pm8001_ha->irq_vector[i].drv_inst = pm8001_ha; - if (request_irq(pm8001_ha->msix_entries[i].vector, + rc = request_irq(pm8001_ha->msix_entries[i].vector, pm8001_interrupt_handler_msix, flag, - intr_drvname[i], &(pm8001_ha->irq_vector[i]))) { + intr_drvname[i], &(pm8001_ha->irq_vector[i])); + if (rc) { for (j = 0; j < i; j++) free_irq( pm8001_ha->msix_entries[j].vector, @@ -964,6 +984,7 @@ static int pm8001_pci_suspend(struct pci_dev *pdev, pm_message_t state) int i, j; u32 device_state; pm8001_ha = sha->lldd_ha; + sas_suspend_ha(sha); flush_workqueue(pm8001_wq); scsi_block_requests(pm8001_ha->shost); if (!pdev->pm_cap) { @@ -1013,6 +1034,7 @@ static int pm8001_pci_resume(struct pci_dev *pdev) int rc; u8 i = 0, j; u32 device_state; + DECLARE_COMPLETION_ONSTACK(completion); pm8001_ha = sha->lldd_ha; device_state = pdev->current_state; @@ -1033,7 +1055,7 @@ static int pm8001_pci_resume(struct pci_dev *pdev) rc = pci_go_44(pdev); if (rc) goto err_out_disable; - + sas_prep_resume_ha(sha); /* chip soft rst only for spc */ if (pm8001_ha->chip_id == chip_8001) { PM8001_CHIP_DISP->chip_soft_rst(pm8001_ha); @@ -1065,7 +1087,13 @@ static int pm8001_pci_resume(struct pci_dev *pdev) for (i = 1; i < pm8001_ha->number_of_intr; i++) PM8001_CHIP_DISP->interrupt_enable(pm8001_ha, i); } - scsi_unblock_requests(pm8001_ha->shost); + pm8001_ha->flags = PM8001F_RUN_TIME; + for (i = 0; i < pm8001_ha->chip->n_phy; i++) { + pm8001_ha->phy[i].enable_completion = &completion; + PM8001_CHIP_DISP->phy_start_req(pm8001_ha, i); + wait_for_completion(&completion); + } + sas_resume_ha(sha); return 0; err_out_disable: diff --git a/drivers/scsi/pm8001/pm8001_sas.c b/drivers/scsi/pm8001/pm8001_sas.c index 8a44bc92bc78..34cea8291772 100644 --- a/drivers/scsi/pm8001/pm8001_sas.c +++ b/drivers/scsi/pm8001/pm8001_sas.c @@ -58,25 +58,14 @@ static int pm8001_find_tag(struct sas_task *task, u32 *tag) } /** - * pm8001_tag_clear - clear the tags bitmap + * pm8001_tag_free - free the no more needed tag * @pm8001_ha: our hba struct * @tag: the found tag associated with the task */ -static void pm8001_tag_clear(struct pm8001_hba_info *pm8001_ha, u32 tag) -{ - void *bitmap = pm8001_ha->tags; - clear_bit(tag, bitmap); -} - void pm8001_tag_free(struct pm8001_hba_info *pm8001_ha, u32 tag) { - pm8001_tag_clear(pm8001_ha, tag); -} - -static void pm8001_tag_set(struct pm8001_hba_info *pm8001_ha, u32 tag) -{ void *bitmap = pm8001_ha->tags; - set_bit(tag, bitmap); + clear_bit(tag, bitmap); } /** @@ -86,14 +75,18 @@ static void pm8001_tag_set(struct pm8001_hba_info *pm8001_ha, u32 tag) */ inline int pm8001_tag_alloc(struct pm8001_hba_info *pm8001_ha, u32 *tag_out) { - unsigned int index, tag; + unsigned int tag; void *bitmap = pm8001_ha->tags; + unsigned long flags; - index = find_first_zero_bit(bitmap, pm8001_ha->tags_num); - tag = index; - if (tag >= pm8001_ha->tags_num) + spin_lock_irqsave(&pm8001_ha->bitmap_lock, flags); + tag = find_first_zero_bit(bitmap, pm8001_ha->tags_num); + if (tag >= pm8001_ha->tags_num) { + spin_unlock_irqrestore(&pm8001_ha->bitmap_lock, flags); return -SAS_QUEUE_FULL; - pm8001_tag_set(pm8001_ha, tag); + } + set_bit(tag, bitmap); + spin_unlock_irqrestore(&pm8001_ha->bitmap_lock, flags); *tag_out = tag; return 0; } @@ -102,7 +95,7 @@ void pm8001_tag_init(struct pm8001_hba_info *pm8001_ha) { int i; for (i = 0; i < pm8001_ha->tags_num; ++i) - pm8001_tag_clear(pm8001_ha, i); + pm8001_tag_free(pm8001_ha, i); } /** @@ -501,11 +494,6 @@ int pm8001_queue_command(struct sas_task *task, const int num, return pm8001_task_exec(task, num, gfp_flags, 0, NULL); } -void pm8001_ccb_free(struct pm8001_hba_info *pm8001_ha, u32 ccb_idx) -{ - pm8001_tag_clear(pm8001_ha, ccb_idx); -} - /** * pm8001_ccb_task_free - free the sg for ssp and smp command, free the ccb. * @pm8001_ha: our hba card information @@ -542,7 +530,7 @@ void pm8001_ccb_task_free(struct pm8001_hba_info *pm8001_ha, ccb->task = NULL; ccb->ccb_tag = 0xFFFFFFFF; ccb->open_retry = 0; - pm8001_ccb_free(pm8001_ha, ccb_idx); + pm8001_tag_free(pm8001_ha, ccb_idx); } /** diff --git a/drivers/scsi/pm8001/pm8001_sas.h b/drivers/scsi/pm8001/pm8001_sas.h index 1ee06f21803b..f6b2ac59dae4 100644 --- a/drivers/scsi/pm8001/pm8001_sas.h +++ b/drivers/scsi/pm8001/pm8001_sas.h @@ -475,6 +475,7 @@ struct pm8001_hba_info { struct list_head list; unsigned long flags; spinlock_t lock;/* host-wide lock */ + spinlock_t bitmap_lock; struct pci_dev *pdev;/* our device */ struct device *dev; struct pm8001_hba_memspace io_mem[6]; @@ -616,7 +617,6 @@ extern struct workqueue_struct *pm8001_wq; int pm8001_tag_alloc(struct pm8001_hba_info *pm8001_ha, u32 *tag_out); void pm8001_tag_init(struct pm8001_hba_info *pm8001_ha); u32 pm8001_get_ncq_tag(struct sas_task *task, u32 *tag); -void pm8001_ccb_free(struct pm8001_hba_info *pm8001_ha, u32 ccb_idx); void pm8001_ccb_task_free(struct pm8001_hba_info *pm8001_ha, struct sas_task *task, struct pm8001_ccb_info *ccb, u32 ccb_idx); int pm8001_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index d70587f96184..b06443a0db2d 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c @@ -856,6 +856,8 @@ pm80xx_set_thermal_config(struct pm8001_hba_info *pm8001_ha) payload.cfg_pg[1] = (LTEMPHIL << 24) | (RTEMPHIL << 8); rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + if (rc) + pm8001_tag_free(pm8001_ha, tag); return rc; } @@ -936,6 +938,8 @@ pm80xx_set_sas_protocol_timer_config(struct pm8001_hba_info *pm8001_ha) sizeof(SASProtocolTimerConfig_t)); rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + if (rc) + pm8001_tag_free(pm8001_ha, tag); return rc; } @@ -948,7 +952,7 @@ static int pm80xx_get_encrypt_info(struct pm8001_hba_info *pm8001_ha) { u32 scratch3_value; - int ret; + int ret = -1; /* Read encryption status from SCRATCH PAD 3 */ scratch3_value = pm8001_cr32(pm8001_ha, 0, MSGU_SCRATCH_PAD_3); @@ -982,7 +986,7 @@ pm80xx_get_encrypt_info(struct pm8001_hba_info *pm8001_ha) pm8001_ha->encrypt_info.status = 0xFFFFFFFF; pm8001_ha->encrypt_info.cipher_mode = 0; pm8001_ha->encrypt_info.sec_mode = 0; - return 0; + ret = 0; } else if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) == SCRATCH_PAD3_ENC_DIS_ERR) { pm8001_ha->encrypt_info.status = @@ -1004,7 +1008,6 @@ pm80xx_get_encrypt_info(struct pm8001_hba_info *pm8001_ha) scratch3_value, pm8001_ha->encrypt_info.cipher_mode, pm8001_ha->encrypt_info.sec_mode, pm8001_ha->encrypt_info.status)); - ret = -1; } else if ((scratch3_value & SCRATCH_PAD3_ENC_MASK) == SCRATCH_PAD3_ENC_ENA_ERR) { @@ -1028,7 +1031,6 @@ pm80xx_get_encrypt_info(struct pm8001_hba_info *pm8001_ha) scratch3_value, pm8001_ha->encrypt_info.cipher_mode, pm8001_ha->encrypt_info.sec_mode, pm8001_ha->encrypt_info.status)); - ret = -1; } return ret; } @@ -1059,6 +1061,8 @@ static int pm80xx_encrypt_update(struct pm8001_hba_info *pm8001_ha) KEK_MGMT_SUBOP_KEYCARDUPDATE); rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + if (rc) + pm8001_tag_free(pm8001_ha, tag); return rc; } @@ -1383,8 +1387,10 @@ static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha, task->task_done = pm8001_task_done; res = pm8001_tag_alloc(pm8001_ha, &ccb_tag); - if (res) + if (res) { + sas_free_task(task); return; + } ccb = &pm8001_ha->ccb_info[ccb_tag]; ccb->device = pm8001_ha_dev; @@ -1399,7 +1405,10 @@ static void pm80xx_send_abort_all(struct pm8001_hba_info *pm8001_ha, task_abort.tag = cpu_to_le32(ccb_tag); ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &task_abort, 0); - + if (ret) { + sas_free_task(task); + pm8001_tag_free(pm8001_ha, ccb_tag); + } } static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha, @@ -1426,6 +1435,7 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha, res = pm8001_tag_alloc(pm8001_ha, &ccb_tag); if (res) { + sas_free_task(task); PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("cannot allocate tag !!!\n")); return; @@ -1436,15 +1446,16 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha, */ dev = kzalloc(sizeof(struct domain_device), GFP_ATOMIC); if (!dev) { + sas_free_task(task); + pm8001_tag_free(pm8001_ha, ccb_tag); PM8001_FAIL_DBG(pm8001_ha, pm8001_printk("Domain device cannot be allocated\n")); - sas_free_task(task); return; - } else { - task->dev = dev; - task->dev->lldd_dev = pm8001_ha_dev; } + task->dev = dev; + task->dev->lldd_dev = pm8001_ha_dev; + ccb = &pm8001_ha->ccb_info[ccb_tag]; ccb->device = pm8001_ha_dev; ccb->ccb_tag = ccb_tag; @@ -1469,7 +1480,11 @@ static void pm80xx_send_read_log(struct pm8001_hba_info *pm8001_ha, memcpy(&sata_cmd.sata_fis, &fis, sizeof(struct host_to_dev_fis)); res = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &sata_cmd, 0); - + if (res) { + sas_free_task(task); + pm8001_tag_free(pm8001_ha, ccb_tag); + kfree(dev); + } } /** @@ -3815,7 +3830,10 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha, build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag, &smp_cmd, pm8001_ha->smp_exp_mode, length); - pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, (u32 *)&smp_cmd, 0); + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, + (u32 *)&smp_cmd, 0); + if (rc) + goto err_out_2; return 0; err_out_2: @@ -4406,6 +4424,8 @@ static int pm80xx_chip_reg_dev_req(struct pm8001_hba_info *pm8001_ha, SAS_ADDR_SIZE); rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + if (rc) + pm8001_tag_free(pm8001_ha, tag); return rc; } @@ -4484,7 +4504,9 @@ void mpi_set_phy_profile_req(struct pm8001_hba_info *pm8001_ha, payload.reserved[j] = cpu_to_le32(*((u32 *)buf + i)); j++; } - pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &payload, 0); + if (rc) + pm8001_tag_free(pm8001_ha, tag); } void pm8001_set_phy_profile(struct pm8001_hba_info *pm8001_ha, diff --git a/drivers/scsi/pmcraid.c b/drivers/scsi/pmcraid.c index be8ce54f99b2..017f8b9554e5 100644 --- a/drivers/scsi/pmcraid.c +++ b/drivers/scsi/pmcraid.c @@ -237,7 +237,7 @@ static int pmcraid_slave_configure(struct scsi_device *scsi_dev) scsi_dev->host->unique_id, scsi_dev->channel, scsi_dev->id, - scsi_dev->lun); + (u8)scsi_dev->lun); if (RES_IS_GSCSI(res->cfg_entry)) { scsi_dev->allow_restart = 1; diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c index e6e2a30493e6..ef23fabe3924 100644 --- a/drivers/scsi/ps3rom.c +++ b/drivers/scsi/ps3rom.c @@ -78,7 +78,7 @@ static int ps3rom_slave_configure(struct scsi_device *scsi_dev) struct ps3rom_private *priv = shost_priv(scsi_dev->host); struct ps3_storage_device *dev = priv->dev; - dev_dbg(&dev->sbd.core, "%s:%u: id %u, lun %u, channel %u\n", __func__, + dev_dbg(&dev->sbd.core, "%s:%u: id %u, lun %llu, channel %u\n", __func__, __LINE__, scsi_dev->id, scsi_dev->lun, scsi_dev->channel); /* diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index de5d0ae19d83..b64399153135 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -320,8 +320,8 @@ struct srb_iocb { * defined in tsk_mgmt_entry struct * for control_flags field in qla_fw.h. */ + uint64_t lun; uint32_t flags; - uint32_t lun; uint32_t data; struct completion comp; __le16 comp_status; @@ -2529,8 +2529,8 @@ struct isp_operations { void (*disable_intrs) (struct qla_hw_data *); int (*abort_command) (srb_t *); - int (*target_reset) (struct fc_port *, unsigned int, int); - int (*lun_reset) (struct fc_port *, unsigned int, int); + int (*target_reset) (struct fc_port *, uint64_t, int); + int (*lun_reset) (struct fc_port *, uint64_t, int); int (*fabric_login) (struct scsi_qla_host *, uint16_t, uint8_t, uint8_t, uint8_t, uint16_t *, uint8_t); int (*fabric_logout) (struct scsi_qla_host *, uint16_t, uint8_t, diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index d48dea8fab1b..d646540db3ac 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -113,7 +113,7 @@ extern int ql2xenabledif; extern int ql2xenablehba_err_chk; extern int ql2xtargetreset; extern int ql2xdontresethba; -extern unsigned int ql2xmaxlun; +extern uint64_t ql2xmaxlun; extern int ql2xmdcapmask; extern int ql2xmdenable; @@ -212,7 +212,7 @@ extern void qla2x00_build_scsi_iocbs_64(srb_t *, cmd_entry_t *, uint16_t); extern int qla2x00_start_scsi(srb_t *sp); extern int qla24xx_start_scsi(srb_t *sp); int qla2x00_marker(struct scsi_qla_host *, struct req_que *, struct rsp_que *, - uint16_t, uint16_t, uint8_t); + uint16_t, uint64_t, uint8_t); extern int qla2x00_start_sp(srb_t *); extern int qla24xx_dif_start_scsi(srb_t *); extern int qla2x00_start_bidir(srb_t *, struct scsi_qla_host *, uint32_t); @@ -262,10 +262,10 @@ extern int qla2x00_abort_command(srb_t *); extern int -qla2x00_abort_target(struct fc_port *, unsigned int, int); +qla2x00_abort_target(struct fc_port *, uint64_t, int); extern int -qla2x00_lun_reset(struct fc_port *, unsigned int, int); +qla2x00_lun_reset(struct fc_port *, uint64_t, int); extern int qla2x00_get_adapter_id(scsi_qla_host_t *, uint16_t *, uint8_t *, uint8_t *, @@ -339,12 +339,12 @@ qla24xx_get_isp_stats(scsi_qla_host_t *, struct link_statistics *, extern int qla24xx_abort_command(srb_t *); extern int qla24xx_async_abort_command(srb_t *); extern int -qla24xx_abort_target(struct fc_port *, unsigned int, int); +qla24xx_abort_target(struct fc_port *, uint64_t, int); extern int -qla24xx_lun_reset(struct fc_port *, unsigned int, int); +qla24xx_lun_reset(struct fc_port *, uint64_t, int); extern int qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *, unsigned int, - unsigned int, enum nexus_wait_type); + uint64_t, enum nexus_wait_type); extern int qla2x00_system_error(scsi_qla_host_t *); @@ -617,8 +617,8 @@ extern char *qlafx00_fw_version_str(struct scsi_qla_host *, char *); extern irqreturn_t qlafx00_intr_handler(int, void *); extern void qlafx00_enable_intrs(struct qla_hw_data *); extern void qlafx00_disable_intrs(struct qla_hw_data *); -extern int qlafx00_abort_target(fc_port_t *, unsigned int, int); -extern int qlafx00_lun_reset(fc_port_t *, unsigned int, int); +extern int qlafx00_abort_target(fc_port_t *, uint64_t, int); +extern int qlafx00_lun_reset(fc_port_t *, uint64_t, int); extern int qlafx00_start_scsi(srb_t *); extern int qlafx00_abort_isp(scsi_qla_host_t *); extern int qlafx00_iospace_config(struct qla_hw_data *); diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index e2184412617d..46990f4ceb40 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1526,8 +1526,8 @@ try_fce: FCE_SIZE, ha->fce, ha->fce_dma); /* Allocate memory for Fibre Channel Event Buffer. */ - tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma, - GFP_KERNEL); + tc = dma_zalloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma, + GFP_KERNEL); if (!tc) { ql_log(ql_log_warn, vha, 0x00be, "Unable to allocate (%d KB) for FCE.\n", @@ -1535,7 +1535,6 @@ try_fce: goto try_eft; } - memset(tc, 0, FCE_SIZE); rval = qla2x00_enable_fce_trace(vha, tc_dma, FCE_NUM_BUFFERS, ha->fce_mb, &ha->fce_bufs); if (rval) { @@ -1560,8 +1559,8 @@ try_eft: EFT_SIZE, ha->eft, ha->eft_dma); /* Allocate memory for Extended Trace Buffer. */ - tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma, - GFP_KERNEL); + tc = dma_zalloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma, + GFP_KERNEL); if (!tc) { ql_log(ql_log_warn, vha, 0x00c1, "Unable to allocate (%d KB) for EFT.\n", @@ -1569,7 +1568,6 @@ try_eft: goto cont_alloc; } - memset(tc, 0, EFT_SIZE); rval = qla2x00_enable_eft_trace(vha, tc_dma, EFT_NUM_BUFFERS); if (rval) { ql_log(ql_log_warn, vha, 0x00c2, diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 760931529592..150529d98db4 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -520,7 +520,7 @@ qla2x00_start_iocbs(struct scsi_qla_host *vha, struct req_que *req) static int __qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req, struct rsp_que *rsp, uint16_t loop_id, - uint16_t lun, uint8_t type) + uint64_t lun, uint8_t type) { mrk_entry_t *mrk; struct mrk_entry_24xx *mrk24 = NULL; @@ -543,14 +543,13 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req, if (IS_FWI2_CAPABLE(ha)) { mrk24 = (struct mrk_entry_24xx *) mrk; mrk24->nport_handle = cpu_to_le16(loop_id); - mrk24->lun[1] = LSB(lun); - mrk24->lun[2] = MSB(lun); + int_to_scsilun(lun, (struct scsi_lun *)&mrk24->lun); host_to_fcp_swap(mrk24->lun, sizeof(mrk24->lun)); mrk24->vp_index = vha->vp_idx; mrk24->handle = MAKE_HANDLE(req->id, mrk24->handle); } else { SET_TARGET_ID(ha, mrk->target, loop_id); - mrk->lun = cpu_to_le16(lun); + mrk->lun = cpu_to_le16((uint16_t)lun); } } wmb(); @@ -562,7 +561,7 @@ __qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req, int qla2x00_marker(struct scsi_qla_host *vha, struct req_que *req, - struct rsp_que *rsp, uint16_t loop_id, uint16_t lun, + struct rsp_que *rsp, uint16_t loop_id, uint64_t lun, uint8_t type) { int ret; @@ -2047,7 +2046,7 @@ static void qla24xx_tm_iocb(srb_t *sp, struct tsk_mgmt_entry *tsk) { uint32_t flags; - unsigned int lun; + uint64_t lun; struct fc_port *fcport = sp->fcport; scsi_qla_host_t *vha = fcport->vha; struct qla_hw_data *ha = vha->hw; diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index a56825c73c31..550a4a31f51a 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1659,7 +1659,7 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len, if (sense_len) { ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x301c, - "Check condition Sense data, nexus%ld:%d:%d cmd=%p.\n", + "Check condition Sense data, nexus%ld:%d:%llu cmd=%p.\n", sp->fcport->vha->host_no, cp->device->id, cp->device->lun, cp); ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x302b, @@ -2281,7 +2281,7 @@ check_scsi_status: out: if (logit) ql_dbg(ql_dbg_io, fcport->vha, 0x3022, - "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%d " + "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu " "portid=%02x%02x%02x oxid=0x%x cdb=%10phN len=0x%x " "rsp_info=0x%x resid=0x%x fw_resid=0x%x.\n", comp_status, scsi_status, res, vha->host_no, diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 1c33a77db5c2..d9aafc003be2 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -947,7 +947,7 @@ qla2x00_abort_command(srb_t *sp) } int -qla2x00_abort_target(struct fc_port *fcport, unsigned int l, int tag) +qla2x00_abort_target(struct fc_port *fcport, uint64_t l, int tag) { int rval, rval2; mbx_cmd_t mc; @@ -1000,7 +1000,7 @@ qla2x00_abort_target(struct fc_port *fcport, unsigned int l, int tag) } int -qla2x00_lun_reset(struct fc_port *fcport, unsigned int l, int tag) +qla2x00_lun_reset(struct fc_port *fcport, uint64_t l, int tag) { int rval, rval2; mbx_cmd_t mc; @@ -1022,7 +1022,7 @@ qla2x00_lun_reset(struct fc_port *fcport, unsigned int l, int tag) mcp->mb[1] = fcport->loop_id; else mcp->mb[1] = fcport->loop_id << 8; - mcp->mb[2] = l; + mcp->mb[2] = (u32)l; mcp->mb[3] = 0; mcp->mb[9] = vha->vp_idx; @@ -2666,7 +2666,7 @@ struct tsk_mgmt_cmd { static int __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, - unsigned int l, int tag) + uint64_t l, int tag) { int rval, rval2; struct tsk_mgmt_cmd *tsk; @@ -2760,7 +2760,7 @@ __qla24xx_issue_tmf(char *name, uint32_t type, struct fc_port *fcport, } int -qla24xx_abort_target(struct fc_port *fcport, unsigned int l, int tag) +qla24xx_abort_target(struct fc_port *fcport, uint64_t l, int tag) { struct qla_hw_data *ha = fcport->vha->hw; @@ -2771,7 +2771,7 @@ qla24xx_abort_target(struct fc_port *fcport, unsigned int l, int tag) } int -qla24xx_lun_reset(struct fc_port *fcport, unsigned int l, int tag) +qla24xx_lun_reset(struct fc_port *fcport, uint64_t l, int tag) { struct qla_hw_data *ha = fcport->vha->hw; diff --git a/drivers/scsi/qla2xxx/qla_mr.c b/drivers/scsi/qla2xxx/qla_mr.c index abeb3901498b..4775baa8b6a0 100644 --- a/drivers/scsi/qla2xxx/qla_mr.c +++ b/drivers/scsi/qla2xxx/qla_mr.c @@ -726,13 +726,13 @@ qlafx00_disable_intrs(struct qla_hw_data *ha) } int -qlafx00_abort_target(fc_port_t *fcport, unsigned int l, int tag) +qlafx00_abort_target(fc_port_t *fcport, uint64_t l, int tag) { return qla2x00_async_tm_cmd(fcport, TCF_TARGET_RESET, l, tag); } int -qlafx00_lun_reset(fc_port_t *fcport, unsigned int l, int tag) +qlafx00_lun_reset(fc_port_t *fcport, uint64_t l, int tag) { return qla2x00_async_tm_cmd(fcport, TCF_LUN_RESET, l, tag); } @@ -2159,7 +2159,7 @@ qlafx00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t par_sense_len, if (sense_len) { ql_dbg(ql_dbg_io + ql_dbg_buffer, vha, 0x3039, - "Check condition Sense data, nexus%ld:%d:%d cmd=%p.\n", + "Check condition Sense data, nexus%ld:%d:%llu cmd=%p.\n", sp->fcport->vha->host_no, cp->device->id, cp->device->lun, cp); ql_dump_buffer(ql_dbg_io + ql_dbg_buffer, vha, 0x3049, @@ -2524,7 +2524,7 @@ check_scsi_status: if (logit) ql_dbg(ql_dbg_io, fcport->vha, 0x3058, - "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%d " + "FCP command status: 0x%x-0x%x (0x%x) nexus=%ld:%d:%llu " "tgt_id: 0x%x lscsi_status: 0x%x cdb=%10phN len=0x%x " "rsp_info=0x%x resid=0x%x fw_resid=0x%x sense_len=0x%x, " "par_sense_len=0x%x, rsp_info_len=0x%x\n", diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index d96bfb55e57b..be9698d920c2 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -202,8 +202,8 @@ MODULE_PARM_DESC(ql2xdontresethba, " 0 (Default) -- Reset on failure.\n" " 1 -- Do not reset on failure.\n"); -uint ql2xmaxlun = MAX_LUNS; -module_param(ql2xmaxlun, uint, S_IRUGO); +uint64_t ql2xmaxlun = MAX_LUNS; +module_param(ql2xmaxlun, ullong, S_IRUGO); MODULE_PARM_DESC(ql2xmaxlun, "Defines the maximum LU number to register with the SCSI " "midlayer. Default is 65535."); @@ -920,7 +920,8 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) scsi_qla_host_t *vha = shost_priv(cmd->device->host); srb_t *sp; int ret; - unsigned int id, lun; + unsigned int id; + uint64_t lun; unsigned long flags; int rval, wait = 0; struct qla_hw_data *ha = vha->hw; @@ -944,7 +945,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) } ql_dbg(ql_dbg_taskm, vha, 0x8002, - "Aborting from RISC nexus=%ld:%d:%d sp=%p cmd=%p\n", + "Aborting from RISC nexus=%ld:%d:%llu sp=%p cmd=%p\n", vha->host_no, id, lun, sp, cmd); /* Get a reference to the sp and drop the lock.*/ @@ -995,7 +996,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) } ql_log(ql_log_info, vha, 0x801c, - "Abort command issued nexus=%ld:%d:%d -- %d %x.\n", + "Abort command issued nexus=%ld:%d:%llu -- %d %x.\n", vha->host_no, id, lun, wait, ret); return ret; @@ -1003,7 +1004,7 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd) int qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t, - unsigned int l, enum nexus_wait_type type) + uint64_t l, enum nexus_wait_type type) { int cnt, match, status; unsigned long flags; @@ -1060,7 +1061,7 @@ static char *reset_errors[] = { static int __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type, - struct scsi_cmnd *cmd, int (*do_reset)(struct fc_port *, unsigned int, int)) + struct scsi_cmnd *cmd, int (*do_reset)(struct fc_port *, uint64_t, int)) { scsi_qla_host_t *vha = shost_priv(cmd->device->host); fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; @@ -1075,7 +1076,7 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type, return err; ql_log(ql_log_info, vha, 0x8009, - "%s RESET ISSUED nexus=%ld:%d:%d cmd=%p.\n", name, vha->host_no, + "%s RESET ISSUED nexus=%ld:%d:%llu cmd=%p.\n", name, vha->host_no, cmd->device->id, cmd->device->lun, cmd); err = 0; @@ -1100,14 +1101,14 @@ __qla2xxx_eh_generic_reset(char *name, enum nexus_wait_type type, } ql_log(ql_log_info, vha, 0x800e, - "%s RESET SUCCEEDED nexus:%ld:%d:%d cmd=%p.\n", name, + "%s RESET SUCCEEDED nexus:%ld:%d:%llu cmd=%p.\n", name, vha->host_no, cmd->device->id, cmd->device->lun, cmd); return SUCCESS; eh_reset_failed: ql_log(ql_log_info, vha, 0x800f, - "%s RESET FAILED: %s nexus=%ld:%d:%d cmd=%p.\n", name, + "%s RESET FAILED: %s nexus=%ld:%d:%llu cmd=%p.\n", name, reset_errors[err], vha->host_no, cmd->device->id, cmd->device->lun, cmd); return FAILED; @@ -1154,7 +1155,8 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) scsi_qla_host_t *vha = shost_priv(cmd->device->host); fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; int ret = FAILED; - unsigned int id, lun; + unsigned int id; + uint64_t lun; id = cmd->device->id; lun = cmd->device->lun; @@ -1169,7 +1171,7 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) ret = FAILED; ql_log(ql_log_info, vha, 0x8012, - "BUS RESET ISSUED nexus=%ld:%d:%d.\n", vha->host_no, id, lun); + "BUS RESET ISSUED nexus=%ld:%d:%llu.\n", vha->host_no, id, lun); if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) { ql_log(ql_log_fatal, vha, 0x8013, @@ -1193,7 +1195,7 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) eh_bus_reset_done: ql_log(ql_log_warn, vha, 0x802b, - "BUS RESET %s nexus=%ld:%d:%d.\n", + "BUS RESET %s nexus=%ld:%d:%llu.\n", (ret == FAILED) ? "FAILED" : "SUCCEEDED", vha->host_no, id, lun); return ret; @@ -1220,14 +1222,15 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) scsi_qla_host_t *vha = shost_priv(cmd->device->host); struct qla_hw_data *ha = vha->hw; int ret = FAILED; - unsigned int id, lun; + unsigned int id; + uint64_t lun; scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev); id = cmd->device->id; lun = cmd->device->lun; ql_log(ql_log_info, vha, 0x8018, - "ADAPTER RESET ISSUED nexus=%ld:%d:%d.\n", vha->host_no, id, lun); + "ADAPTER RESET ISSUED nexus=%ld:%d:%llu.\n", vha->host_no, id, lun); /* * No point in issuing another reset if one is active. Also do not @@ -1273,7 +1276,7 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) eh_host_reset_lock: ql_log(ql_log_info, vha, 0x8017, - "ADAPTER RESET %s nexus=%ld:%d:%d.\n", + "ADAPTER RESET %s nexus=%ld:%d:%llu.\n", (ret == FAILED) ? "FAILED" : "SUCCEEDED", vha->host_no, id, lun); return ret; @@ -1409,7 +1412,7 @@ static void qla2x00_handle_queue_full(struct scsi_device *sdev, int qdepth) return; ql_dbg(ql_dbg_io, fcport->vha, 0x3029, - "Queue depth adjusted-down to %d for nexus=%ld:%d:%d.\n", + "Queue depth adjusted-down to %d for nexus=%ld:%d:%llu.\n", sdev->queue_depth, fcport->vha->host_no, sdev->id, sdev->lun); } @@ -1432,7 +1435,7 @@ static void qla2x00_adjust_sdev_qdepth_up(struct scsi_device *sdev, int qdepth) scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, qdepth); ql_dbg(ql_dbg_io, vha, 0x302a, - "Queue depth adjusted-up to %d for nexus=%ld:%d:%d.\n", + "Queue depth adjusted-up to %d for nexus=%ld:%d:%llu.\n", sdev->queue_depth, fcport->vha->host_no, sdev->id, sdev->lun); } @@ -2661,14 +2664,19 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) else host->max_cmd_len = MAX_CMDSZ; host->max_channel = MAX_BUSES - 1; - host->max_lun = ql2xmaxlun; + /* Older HBAs support only 16-bit LUNs */ + if (!IS_QLAFX00(ha) && !IS_FWI2_CAPABLE(ha) && + ql2xmaxlun > 0xffff) + host->max_lun = 0xffff; + else + host->max_lun = ql2xmaxlun; host->transportt = qla2xxx_transport_template; sht->vendor_id = (SCSI_NL_VID_TYPE_PCI | PCI_VENDOR_ID_QLOGIC); ql_dbg(ql_dbg_init, base_vha, 0x0033, "max_id=%d this_id=%d " "cmd_per_len=%d unique_id=%d max_cmd_len=%d max_channel=%d " - "max_lun=%d transportt=%p, vendor_id=%llu.\n", host->max_id, + "max_lun=%llu transportt=%p, vendor_id=%llu.\n", host->max_id, host->this_id, host->cmd_per_lun, host->unique_id, host->max_cmd_len, host->max_channel, host->max_lun, host->transportt, sht->vendor_id); diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h index 5f58b451327e..2559144f5475 100644 --- a/drivers/scsi/qla4xxx/ql4_glbl.h +++ b/drivers/scsi/qla4xxx/ql4_glbl.h @@ -23,7 +23,7 @@ void qla4xxx_process_aen(struct scsi_qla_host *ha, uint8_t process_aen); int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host *ha); int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb); int qla4xxx_reset_lun(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry, - int lun); + uint64_t lun); int qla4xxx_reset_target(struct scsi_qla_host *ha, struct ddb_entry *ddb_entry); int qla4xxx_get_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr, @@ -76,7 +76,7 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, uint32_t state, uint32_t conn_error); void qla4xxx_dump_buffer(void *b, uint32_t size); int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, - struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod); + struct ddb_entry *ddb_entry, uint64_t lun, uint16_t mrkr_mod); int qla4xxx_set_flash(struct scsi_qla_host *ha, dma_addr_t dma_addr, uint32_t offset, uint32_t length, uint32_t options); int qla4xxx_mailbox_command(struct scsi_qla_host *ha, uint8_t inCount, diff --git a/drivers/scsi/qla4xxx/ql4_iocb.c b/drivers/scsi/qla4xxx/ql4_iocb.c index e5697ab144d2..08ab6dac226d 100644 --- a/drivers/scsi/qla4xxx/ql4_iocb.c +++ b/drivers/scsi/qla4xxx/ql4_iocb.c @@ -83,7 +83,7 @@ static int qla4xxx_get_req_pkt(struct scsi_qla_host *ha, * This routine issues a marker IOCB. **/ int qla4xxx_send_marker_iocb(struct scsi_qla_host *ha, - struct ddb_entry *ddb_entry, int lun, uint16_t mrkr_mod) + struct ddb_entry *ddb_entry, uint64_t lun, uint16_t mrkr_mod) { struct qla4_marker_entry *marker_entry; unsigned long flags = 0; diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c index 081b6b78d2c6..4f9c0f2be89d 100644 --- a/drivers/scsi/qla4xxx/ql4_isr.c +++ b/drivers/scsi/qla4xxx/ql4_isr.c @@ -26,7 +26,7 @@ static void qla4xxx_copy_sense(struct scsi_qla_host *ha, memset(cmd->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE); sense_len = le16_to_cpu(sts_entry->senseDataByteCnt); if (sense_len == 0) { - DEBUG2(ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%d:%d: %s:" + DEBUG2(ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%d:%llu: %s:" " sense len 0\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun, __func__)); @@ -43,7 +43,7 @@ static void qla4xxx_copy_sense(struct scsi_qla_host *ha, sense_len = min_t(uint16_t, sense_len, IOCB_MAX_SENSEDATA_LEN); memcpy(cmd->sense_buffer, sts_entry->senseData, sense_len); - DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%d: %s: sense key = %x, " + DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%llu: %s: sense key = %x, " "ASL= %02x, ASC/ASCQ = %02x/%02x\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun, __func__, @@ -169,7 +169,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, cmd->result = DID_ERROR << 16; - DEBUG2(printk("scsi%ld:%d:%d:%d: %s: " + DEBUG2(printk("scsi%ld:%d:%d:%llu: %s: " "Mid-layer Data underrun0, " "xferlen = 0x%x, " "residual = 0x%x\n", ha->host_no, @@ -197,7 +197,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, break; case SCS_RESET_OCCURRED: - DEBUG2(printk("scsi%ld:%d:%d:%d: %s: Device RESET occurred\n", + DEBUG2(printk("scsi%ld:%d:%d:%llu: %s: Device RESET occurred\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun, __func__)); @@ -205,7 +205,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, break; case SCS_ABORTED: - DEBUG2(printk("scsi%ld:%d:%d:%d: %s: Abort occurred\n", + DEBUG2(printk("scsi%ld:%d:%d:%llu: %s: Abort occurred\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun, __func__)); @@ -213,7 +213,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, break; case SCS_TIMEOUT: - DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%d: Timeout\n", + DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%llu: Timeout\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun)); @@ -232,7 +232,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, case SCS_DATA_OVERRUN: if ((sts_entry->iscsiFlags & ISCSI_FLAG_RESIDUAL_OVER) || (sts_entry->completionStatus == SCS_DATA_OVERRUN)) { - DEBUG2(printk("scsi%ld:%d:%d:%d: %s: " "Data overrun\n", + DEBUG2(printk("scsi%ld:%d:%d:%llu: %s: " "Data overrun\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun, __func__)); @@ -259,7 +259,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, if (!scsi_status && (scsi_bufflen(cmd) - residual) < cmd->underflow) { DEBUG2(ql4_printk(KERN_INFO, ha, - "scsi%ld:%d:%d:%d: %s: Mid-layer Data underrun, xferlen = 0x%x,residual = 0x%x\n", + "scsi%ld:%d:%d:%llu: %s: Mid-layer Data underrun, xferlen = 0x%x,residual = 0x%x\n", ha->host_no, cmd->device->channel, cmd->device->id, @@ -291,7 +291,7 @@ static void qla4xxx_status_entry(struct scsi_qla_host *ha, */ DEBUG2(ql4_printk(KERN_INFO, ha, - "scsi%ld:%d:%d:%d: %s: Dropped frame(s) detected (0x%x of 0x%x bytes).\n", + "scsi%ld:%d:%d:%llu: %s: Dropped frame(s) detected (0x%x of 0x%x bytes).\n", ha->host_no, cmd->device->channel, cmd->device->id, @@ -313,7 +313,7 @@ check_scsi_status: case SCS_DEVICE_LOGGED_OUT: case SCS_DEVICE_UNAVAILABLE: - DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%d: SCS_DEVICE " + DEBUG2(printk(KERN_INFO "scsi%ld:%d:%d:%llu: SCS_DEVICE " "state: 0x%x\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun, sts_entry->completionStatus)); @@ -333,7 +333,7 @@ check_scsi_status: * SCSI Mid-Layer handles device queue full */ cmd->result = DID_OK << 16 | sts_entry->scsiStatus; - DEBUG2(printk("scsi%ld:%d:%d: %s: QUEUE FULL detected " + DEBUG2(printk("scsi%ld:%d:%llu: %s: QUEUE FULL detected " "compl=%02x, scsi=%02x, state=%02x, iFlags=%02x," " iResp=%02x\n", ha->host_no, cmd->device->id, cmd->device->lun, __func__, diff --git a/drivers/scsi/qla4xxx/ql4_mbx.c b/drivers/scsi/qla4xxx/ql4_mbx.c index 0a3312c6dd6d..fdfae79924ac 100644 --- a/drivers/scsi/qla4xxx/ql4_mbx.c +++ b/drivers/scsi/qla4xxx/ql4_mbx.c @@ -1205,7 +1205,7 @@ int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb) if (mbox_sts[0] != MBOX_STS_COMMAND_COMPLETE) { status = QLA_ERROR; - DEBUG2(printk(KERN_WARNING "scsi%ld:%d:%d: abort task FAILED: " + DEBUG2(printk(KERN_WARNING "scsi%ld:%d:%llu: abort task FAILED: " "mbx0=%04X, mb1=%04X, mb2=%04X, mb3=%04X, mb4=%04X\n", ha->host_no, cmd->device->id, cmd->device->lun, mbox_sts[0], mbox_sts[1], mbox_sts[2], mbox_sts[3], mbox_sts[4])); @@ -1225,14 +1225,14 @@ int qla4xxx_abort_task(struct scsi_qla_host *ha, struct srb *srb) * are valid before calling this routine. **/ int qla4xxx_reset_lun(struct scsi_qla_host * ha, struct ddb_entry * ddb_entry, - int lun) + uint64_t lun) { uint32_t mbox_cmd[MBOX_REG_COUNT]; uint32_t mbox_sts[MBOX_REG_COUNT]; uint32_t scsi_lun[2]; int status = QLA_SUCCESS; - DEBUG2(printk("scsi%ld:%d:%d: lun reset issued\n", ha->host_no, + DEBUG2(printk("scsi%ld:%d:%llu: lun reset issued\n", ha->host_no, ddb_entry->fw_ddb_index, lun)); /* diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c index 320206376206..c5d9564d455c 100644 --- a/drivers/scsi/qla4xxx/ql4_os.c +++ b/drivers/scsi/qla4xxx/ql4_os.c @@ -9223,20 +9223,20 @@ static int qla4xxx_eh_abort(struct scsi_cmnd *cmd) { struct scsi_qla_host *ha = to_qla_host(cmd->device->host); unsigned int id = cmd->device->id; - unsigned int lun = cmd->device->lun; + uint64_t lun = cmd->device->lun; unsigned long flags; struct srb *srb = NULL; int ret = SUCCESS; int wait = 0; - ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%d: Abort command issued cmd=%p, cdb=0x%x\n", + ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%llu: Abort command issued cmd=%p, cdb=0x%x\n", ha->host_no, id, lun, cmd, cmd->cmnd[0]); spin_lock_irqsave(&ha->hardware_lock, flags); srb = (struct srb *) CMD_SP(cmd); if (!srb) { spin_unlock_irqrestore(&ha->hardware_lock, flags); - ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%d: Specified command has already completed.\n", + ql4_printk(KERN_INFO, ha, "scsi%ld:%d:%llu: Specified command has already completed.\n", ha->host_no, id, lun); return SUCCESS; } @@ -9244,11 +9244,11 @@ static int qla4xxx_eh_abort(struct scsi_cmnd *cmd) spin_unlock_irqrestore(&ha->hardware_lock, flags); if (qla4xxx_abort_task(ha, srb) != QLA_SUCCESS) { - DEBUG3(printk("scsi%ld:%d:%d: Abort_task mbx failed.\n", + DEBUG3(printk("scsi%ld:%d:%llu: Abort_task mbx failed.\n", ha->host_no, id, lun)); ret = FAILED; } else { - DEBUG3(printk("scsi%ld:%d:%d: Abort_task mbx success.\n", + DEBUG3(printk("scsi%ld:%d:%llu: Abort_task mbx success.\n", ha->host_no, id, lun)); wait = 1; } @@ -9258,14 +9258,14 @@ static int qla4xxx_eh_abort(struct scsi_cmnd *cmd) /* Wait for command to complete */ if (wait) { if (!qla4xxx_eh_wait_on_command(ha, cmd)) { - DEBUG2(printk("scsi%ld:%d:%d: Abort handler timed out\n", + DEBUG2(printk("scsi%ld:%d:%llu: Abort handler timed out\n", ha->host_no, id, lun)); ret = FAILED; } } ql4_printk(KERN_INFO, ha, - "scsi%ld:%d:%d: Abort command - %s\n", + "scsi%ld:%d:%llu: Abort command - %s\n", ha->host_no, id, lun, (ret == SUCCESS) ? "succeeded" : "failed"); return ret; @@ -9293,7 +9293,7 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd) ret = FAILED; ql4_printk(KERN_INFO, ha, - "scsi%ld:%d:%d:%d: DEVICE RESET ISSUED.\n", ha->host_no, + "scsi%ld:%d:%d:%llu: DEVICE RESET ISSUED.\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun); DEBUG2(printk(KERN_INFO @@ -9323,7 +9323,7 @@ static int qla4xxx_eh_device_reset(struct scsi_cmnd *cmd) goto eh_dev_reset_done; ql4_printk(KERN_INFO, ha, - "scsi(%ld:%d:%d:%d): DEVICE RESET SUCCEEDED.\n", + "scsi(%ld:%d:%d:%llu): DEVICE RESET SUCCEEDED.\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun); @@ -9440,7 +9440,7 @@ static int qla4xxx_eh_host_reset(struct scsi_cmnd *cmd) } ql4_printk(KERN_INFO, ha, - "scsi(%ld:%d:%d:%d): HOST RESET ISSUED.\n", ha->host_no, + "scsi(%ld:%d:%d:%llu): HOST RESET ISSUED.\n", ha->host_no, cmd->device->channel, cmd->device->id, cmd->device->lun); if (qla4xxx_wait_for_hba_online(ha) != QLA_SUCCESS) { diff --git a/drivers/scsi/qlogicfas.c b/drivers/scsi/qlogicfas.c index 13d628b56ff7..a22bb1b40ce2 100644 --- a/drivers/scsi/qlogicfas.c +++ b/drivers/scsi/qlogicfas.c @@ -171,8 +171,6 @@ static int qlogicfas_release(struct Scsi_Host *shost) qlogicfas408_disable_ints(priv); free_irq(shost->irq, shost); } - if (shost->dma_channel != 0xff) - free_dma(shost->dma_channel); if (shost->io_port && shost->n_io_port) release_region(shost->io_port, shost->n_io_port); scsi_host_put(shost); diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index 6d48d30bed05..740ae495aa77 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -959,7 +959,7 @@ static inline void update_can_queue(struct Scsi_Host *host, u_int in_ptr, u_int /* Temporary workaround until bug is found and fixed (one bug has been found already, but fixing it makes things even worse) -jj */ int num_free = QLOGICPTI_REQ_QUEUE_LEN - REQ_QUEUE_DEPTH(in_ptr, out_ptr) - 64; - host->can_queue = host->host_busy + num_free; + host->can_queue = atomic_read(&host->host_busy) + num_free; host->sg_tablesize = QLOGICPTI_MAX_SG(num_free); } diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index 88d46fe6bf98..df3306019a7e 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -72,8 +72,6 @@ #define CREATE_TRACE_POINTS #include <trace/events/scsi.h> -static void scsi_done(struct scsi_cmnd *cmd); - /* * Definitions and constants. */ @@ -124,6 +122,8 @@ static const char *const scsi_device_types[] = { "Bridge controller", "Object storage ", "Automation/Drive ", + "Security Manager ", + "Direct-Access-ZBC", }; /** @@ -235,7 +235,8 @@ fail: * Description: allocate a struct scsi_cmd from host's slab, recycling from the * host's free_list if necessary. */ -struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask) +static struct scsi_cmnd * +__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask) { struct scsi_cmnd *cmd = scsi_host_alloc_command(shost, gfp_mask); @@ -265,7 +266,6 @@ struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *shost, gfp_t gfp_mask) return cmd; } -EXPORT_SYMBOL_GPL(__scsi_get_command); /** * scsi_get_command - Allocate and setup a scsi command block @@ -291,14 +291,13 @@ struct scsi_cmnd *scsi_get_command(struct scsi_device *dev, gfp_t gfp_mask) cmd->jiffies_at_alloc = jiffies; return cmd; } -EXPORT_SYMBOL(scsi_get_command); /** * __scsi_put_command - Free a struct scsi_cmnd * @shost: dev->host * @cmd: Command to free */ -void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd) +static void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd) { unsigned long flags; @@ -314,7 +313,6 @@ void __scsi_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd) if (likely(cmd != NULL)) scsi_host_free_command(shost, cmd); } -EXPORT_SYMBOL(__scsi_put_command); /** * scsi_put_command - Free a scsi command block @@ -334,11 +332,10 @@ void scsi_put_command(struct scsi_cmnd *cmd) list_del_init(&cmd->list); spin_unlock_irqrestore(&cmd->device->list_lock, flags); - cancel_delayed_work(&cmd->abort_work); + BUG_ON(delayed_work_pending(&cmd->abort_work)); __scsi_put_command(cmd->device->host, cmd); } -EXPORT_SYMBOL(scsi_put_command); static struct scsi_host_cmd_pool * scsi_find_host_cmd_pool(struct Scsi_Host *shost) @@ -368,8 +365,8 @@ scsi_alloc_host_cmd_pool(struct Scsi_Host *shost) if (!pool) return NULL; - pool->cmd_name = kasprintf(GFP_KERNEL, "%s_cmd", hostt->name); - pool->sense_name = kasprintf(GFP_KERNEL, "%s_sense", hostt->name); + pool->cmd_name = kasprintf(GFP_KERNEL, "%s_cmd", hostt->proc_name); + pool->sense_name = kasprintf(GFP_KERNEL, "%s_sense", hostt->proc_name); if (!pool->cmd_name || !pool->sense_name) { scsi_free_host_cmd_pool(pool); return NULL; @@ -605,7 +602,7 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition) if (level > 3) scmd_printk(KERN_INFO, cmd, "scsi host busy %d failed %d\n", - cmd->device->host->host_busy, + atomic_read(&cmd->device->host->host_busy), cmd->device->host->host_failed); } } @@ -648,33 +645,24 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) * returns an immediate error upwards, and signals * that the device is no longer present */ cmd->result = DID_NO_CONNECT << 16; - scsi_done(cmd); - /* return 0 (because the command has been processed) */ - goto out; + goto done; } /* Check to see if the scsi lld made this device blocked. */ if (unlikely(scsi_device_blocked(cmd->device))) { - /* + /* * in blocked state, the command is just put back on * the device queue. The suspend state has already * blocked the queue so future requests should not * occur until the device transitions out of the * suspend state. */ - - scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY); - - SCSI_LOG_MLQUEUE(3, printk("queuecommand : device blocked \n")); - - /* - * NOTE: rtn is still zero here because we don't need the - * queue to be plugged on return (it's already stopped) - */ - goto out; + SCSI_LOG_MLQUEUE(3, scmd_printk(KERN_INFO, cmd, + "queuecommand : device blocked\n")); + return SCSI_MLQUEUE_DEVICE_BUSY; } - /* + /* * If SCSI-2 or lower, store the LUN value in cmnd. */ if (cmd->device->scsi_level <= SCSI_2 && @@ -690,57 +678,36 @@ int scsi_dispatch_cmd(struct scsi_cmnd *cmd) * length exceeds what the host adapter can handle. */ if (cmd->cmd_len > cmd->device->host->max_cmd_len) { - SCSI_LOG_MLQUEUE(3, - printk("queuecommand : command too long. " + SCSI_LOG_MLQUEUE(3, scmd_printk(KERN_INFO, cmd, + "queuecommand : command too long. " "cdb_size=%d host->max_cmd_len=%d\n", cmd->cmd_len, cmd->device->host->max_cmd_len)); cmd->result = (DID_ABORT << 16); - - scsi_done(cmd); - goto out; + goto done; } if (unlikely(host->shost_state == SHOST_DEL)) { cmd->result = (DID_NO_CONNECT << 16); - scsi_done(cmd); - } else { - trace_scsi_dispatch_cmd_start(cmd); - cmd->scsi_done = scsi_done; - rtn = host->hostt->queuecommand(host, cmd); + goto done; + } + trace_scsi_dispatch_cmd_start(cmd); + rtn = host->hostt->queuecommand(host, cmd); if (rtn) { trace_scsi_dispatch_cmd_error(cmd, rtn); if (rtn != SCSI_MLQUEUE_DEVICE_BUSY && rtn != SCSI_MLQUEUE_TARGET_BUSY) rtn = SCSI_MLQUEUE_HOST_BUSY; - scsi_queue_insert(cmd, rtn); - - SCSI_LOG_MLQUEUE(3, - printk("queuecommand : request rejected\n")); + SCSI_LOG_MLQUEUE(3, scmd_printk(KERN_INFO, cmd, + "queuecommand : request rejected\n")); } - out: - SCSI_LOG_MLQUEUE(3, printk("leaving scsi_dispatch_cmnd()\n")); return rtn; -} - -/** - * scsi_done - Invoke completion on finished SCSI command. - * @cmd: The SCSI Command for which a low-level device driver (LLDD) gives - * ownership back to SCSI Core -- i.e. the LLDD has finished with it. - * - * Description: This function is the mid-level's (SCSI Core) interrupt routine, - * which regains ownership of the SCSI command (de facto) from a LLDD, and - * calls blk_complete_request() for further processing. - * - * This function is interrupt context safe. - */ -static void scsi_done(struct scsi_cmnd *cmd) -{ - trace_scsi_dispatch_cmd_done(cmd); - blk_complete_request(cmd->request); + done: + cmd->scsi_done(cmd); + return 0; } /** @@ -761,17 +728,16 @@ void scsi_finish_command(struct scsi_cmnd *cmd) scsi_device_unbusy(sdev); - /* - * Clear the flags which say that the device/host is no longer - * capable of accepting new commands. These are set in scsi_queue.c - * for both the queue full condition on a device, and for a - * host full condition on the host. - * - * XXX(hch): What about locking? - */ - shost->host_blocked = 0; - starget->target_blocked = 0; - sdev->device_blocked = 0; + /* + * Clear the flags that say that the device/target/host is no longer + * capable of accepting new commands. + */ + if (atomic_read(&shost->host_blocked)) + atomic_set(&shost->host_blocked, 0); + if (atomic_read(&starget->target_blocked)) + atomic_set(&starget->target_blocked, 0); + if (atomic_read(&sdev->device_blocked)) + atomic_set(&sdev->device_blocked, 0); /* * If we have valid sense information, then some kind of recovery @@ -801,7 +767,6 @@ void scsi_finish_command(struct scsi_cmnd *cmd) } scsi_io_completion(cmd, good_bytes); } -EXPORT_SYMBOL(scsi_finish_command); /** * scsi_adjust_queue_depth - Let low level drivers change a device's queue depth @@ -842,7 +807,7 @@ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags) * is more IO than the LLD's can_queue (so there are not enuogh * tags) request_fn's host queue ready check will handle it. */ - if (!sdev->host->bqt) { + if (!shost_use_blk_mq(sdev->host) && !sdev->host->bqt) { if (blk_queue_tagged(sdev->request_queue) && blk_queue_resize_tags(sdev->request_queue, tags) != 0) goto out; @@ -850,6 +815,10 @@ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags) sdev->queue_depth = tags; switch (tagged) { + case 0: + sdev->ordered_tags = 0; + sdev->simple_tags = 0; + break; case MSG_ORDERED_TAG: sdev->ordered_tags = 1; sdev->simple_tags = 1; @@ -859,13 +828,11 @@ void scsi_adjust_queue_depth(struct scsi_device *sdev, int tagged, int tags) sdev->simple_tags = 1; break; default: + sdev->ordered_tags = 0; + sdev->simple_tags = 0; sdev_printk(KERN_WARNING, sdev, "scsi_adjust_queue_depth, bad queue type, " "disabled\n"); - case 0: - sdev->ordered_tags = sdev->simple_tags = 0; - sdev->queue_depth = tags; - break; } out: spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); @@ -1291,7 +1258,7 @@ EXPORT_SYMBOL(__starget_for_each_device); * really want to use scsi_device_lookup_by_target instead. **/ struct scsi_device *__scsi_device_lookup_by_target(struct scsi_target *starget, - uint lun) + u64 lun) { struct scsi_device *sdev; @@ -1316,7 +1283,7 @@ EXPORT_SYMBOL(__scsi_device_lookup_by_target); * needs to be released with scsi_device_put once you're done with it. **/ struct scsi_device *scsi_device_lookup_by_target(struct scsi_target *starget, - uint lun) + u64 lun) { struct scsi_device *sdev; struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); @@ -1349,7 +1316,7 @@ EXPORT_SYMBOL(scsi_device_lookup_by_target); * really want to use scsi_device_lookup instead. **/ struct scsi_device *__scsi_device_lookup(struct Scsi_Host *shost, - uint channel, uint id, uint lun) + uint channel, uint id, u64 lun) { struct scsi_device *sdev; @@ -1375,7 +1342,7 @@ EXPORT_SYMBOL(__scsi_device_lookup); * needs to be released with scsi_device_put once you're done with it. **/ struct scsi_device *scsi_device_lookup(struct Scsi_Host *shost, - uint channel, uint id, uint lun) + uint channel, uint id, u64 lun) { struct scsi_device *sdev; unsigned long flags; @@ -1396,6 +1363,9 @@ MODULE_LICENSE("GPL"); module_param(scsi_logging_level, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(scsi_logging_level, "a bit mask of logging levels"); +bool scsi_use_blk_mq = false; +module_param_named(use_blk_mq, scsi_use_blk_mq, bool, S_IWUSR | S_IRUGO); + static int __init init_scsi(void) { int error; diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 1328a2621070..d19c0e3c7f48 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c @@ -42,6 +42,10 @@ #include <linux/scatterlist.h> #include <linux/blkdev.h> #include <linux/crc-t10dif.h> +#include <linux/spinlock.h> +#include <linux/interrupt.h> +#include <linux/atomic.h> +#include <linux/hrtimer.h> #include <net/checksum.h> @@ -53,13 +57,16 @@ #include <scsi/scsi_host.h> #include <scsi/scsicam.h> #include <scsi/scsi_eh.h> +#include <scsi/scsi_tcq.h> #include <scsi/scsi_dbg.h> #include "sd.h" #include "scsi_logging.h" -#define SCSI_DEBUG_VERSION "1.82" -static const char * scsi_debug_version_date = "20100324"; +#define SCSI_DEBUG_VERSION "1.84" +static const char *scsi_debug_version_date = "20140706"; + +#define MY_NAME "scsi_debug" /* Additional Sense Code (ASC) */ #define NO_ADDITIONAL_SENSE 0x0 @@ -72,7 +79,11 @@ static const char * scsi_debug_version_date = "20100324"; #define INVALID_COMMAND_OPCODE 0x20 #define INVALID_FIELD_IN_CDB 0x24 #define INVALID_FIELD_IN_PARAM_LIST 0x26 -#define POWERON_RESET 0x29 +#define UA_RESET_ASC 0x29 +#define UA_CHANGED_ASC 0x2a +#define POWER_ON_RESET_ASCQ 0x0 +#define BUS_RESET_ASCQ 0x2 /* scsi bus reset occurred */ +#define MODE_CHANGED_ASCQ 0x1 /* mode parameters changed */ #define SAVING_PARAMS_UNSUP 0x39 #define TRANSPORT_PROBLEM 0x4b #define THRESHOLD_EXCEEDED 0x5d @@ -81,7 +92,6 @@ static const char * scsi_debug_version_date = "20100324"; /* Additional Sense Code Qualifier (ASCQ) */ #define ACK_NAK_TO 0x3 -#define SDEBUG_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */ /* Default values for driver parameters */ #define DEF_NUM_HOST 1 @@ -91,7 +101,7 @@ static const char * scsi_debug_version_date = "20100324"; * (id 0) containing 1 logical unit (lun 0). That is 1 device. */ #define DEF_ATO 1 -#define DEF_DELAY 1 +#define DEF_DELAY 1 /* if > 0 unit is a jiffy */ #define DEF_DEV_SIZE_MB 8 #define DEF_DIF 0 #define DEF_DIX 0 @@ -99,11 +109,13 @@ static const char * scsi_debug_version_date = "20100324"; #define DEF_EVERY_NTH 0 #define DEF_FAKE_RW 0 #define DEF_GUARD 0 +#define DEF_HOST_LOCK 0 #define DEF_LBPU 0 #define DEF_LBPWS 0 #define DEF_LBPWS10 0 #define DEF_LBPRZ 1 #define DEF_LOWEST_ALIGNED 0 +#define DEF_NDELAY 0 /* if > 0 unit is a nanosecond */ #define DEF_NO_LUN_0 0 #define DEF_NUM_PARTS 0 #define DEF_OPTS 0 @@ -113,6 +125,7 @@ static const char * scsi_debug_version_date = "20100324"; #define DEF_REMOVABLE false #define DEF_SCSI_LEVEL 5 /* INQUIRY, byte2 [5->SPC-3] */ #define DEF_SECTOR_SIZE 512 +#define DEF_TAGGED_QUEUING 0 /* 0 | MSG_SIMPLE_TAG | MSG_ORDERED_TAG */ #define DEF_UNMAP_ALIGNMENT 0 #define DEF_UNMAP_GRANULARITY 1 #define DEF_UNMAP_MAX_BLOCKS 0xFFFFFFFF @@ -120,6 +133,7 @@ static const char * scsi_debug_version_date = "20100324"; #define DEF_VIRTUAL_GB 0 #define DEF_VPD_USE_HOSTNO 1 #define DEF_WRITESAME_LENGTH 0xFFFF +#define DELAY_OVERRIDDEN -9999 /* bit mask values for scsi_debug_opts */ #define SCSI_DEBUG_OPT_NOISE 1 @@ -130,7 +144,14 @@ static const char * scsi_debug_version_date = "20100324"; #define SCSI_DEBUG_OPT_DIF_ERR 32 #define SCSI_DEBUG_OPT_DIX_ERR 64 #define SCSI_DEBUG_OPT_MAC_TIMEOUT 128 -#define SCSI_DEBUG_OPT_SHORT_TRANSFER 256 +#define SCSI_DEBUG_OPT_SHORT_TRANSFER 0x100 +#define SCSI_DEBUG_OPT_Q_NOISE 0x200 +#define SCSI_DEBUG_OPT_ALL_TSF 0x400 +#define SCSI_DEBUG_OPT_RARE_TSF 0x800 +#define SCSI_DEBUG_OPT_N_WCE 0x1000 +#define SCSI_DEBUG_OPT_RESET_NOISE 0x2000 +#define SCSI_DEBUG_OPT_NO_CDB_NOISE 0x4000 +#define SCSI_DEBUG_OPT_ALL_NOISE (0x1 | 0x200 | 0x2000) /* When "every_nth" > 0 then modulo "every_nth" commands: * - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set * - a RECOVERED_ERROR is simulated on successful read and write @@ -148,6 +169,19 @@ static const char * scsi_debug_version_date = "20100324"; * writing a new value (other than -1 or 1) to every_nth via sysfs). */ +/* As indicated in SAM-5 and SPC-4 Unit Attentions (UAs)are returned in + * priority order. In the subset implemented here lower numbers have higher + * priority. The UA numbers should be a sequence starting from 0 with + * SDEBUG_NUM_UAS being 1 higher than the highest numbered UA. */ +#define SDEBUG_UA_POR 0 /* Power on, reset, or bus device reset */ +#define SDEBUG_UA_BUS_RESET 1 +#define SDEBUG_UA_MODE_CHANGED 2 +#define SDEBUG_NUM_UAS 3 + +/* for check_readiness() */ +#define UAS_ONLY 1 +#define UAS_TUR 0 + /* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this * sector on read commands: */ #define OPT_MEDIUM_ERR_ADDR 0x1234 /* that's sector 4660 in decimal */ @@ -158,9 +192,19 @@ static const char * scsi_debug_version_date = "20100324"; #define SAM2_LUN_ADDRESS_METHOD 0 #define SAM2_WLUN_REPORT_LUNS 0xc101 -/* Can queue up to this number of commands. Typically commands that - * that have a non-zero delay are queued. */ -#define SCSI_DEBUG_CANQUEUE 255 +/* SCSI_DEBUG_CANQUEUE is the maximum number of commands that can be queued + * (for response) at one time. Can be reduced by max_queue option. Command + * responses are not queued when delay=0 and ndelay=0. The per-device + * DEF_CMD_PER_LUN can be changed via sysfs: + * /sys/class/scsi_device/<h:c:t:l>/device/queue_depth but cannot exceed + * SCSI_DEBUG_CANQUEUE. */ +#define SCSI_DEBUG_CANQUEUE_WORDS 9 /* a WORD is bits in a long */ +#define SCSI_DEBUG_CANQUEUE (SCSI_DEBUG_CANQUEUE_WORDS * BITS_PER_LONG) +#define DEF_CMD_PER_LUN 255 + +#if DEF_CMD_PER_LUN > SCSI_DEBUG_CANQUEUE +#warning "Expect DEF_CMD_PER_LUN <= SCSI_DEBUG_CANQUEUE" +#endif static int scsi_debug_add_host = DEF_NUM_HOST; static int scsi_debug_ato = DEF_ATO; @@ -175,6 +219,8 @@ static unsigned int scsi_debug_guard = DEF_GUARD; static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED; static int scsi_debug_max_luns = DEF_MAX_LUNS; static int scsi_debug_max_queue = SCSI_DEBUG_CANQUEUE; +static atomic_t retired_max_queue; /* if > 0 then was prior max_queue */ +static int scsi_debug_ndelay = DEF_NDELAY; static int scsi_debug_no_lun_0 = DEF_NO_LUN_0; static int scsi_debug_no_uld = 0; static int scsi_debug_num_parts = DEF_NUM_PARTS; @@ -198,8 +244,11 @@ static unsigned int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC; static unsigned int scsi_debug_write_same_length = DEF_WRITESAME_LENGTH; static bool scsi_debug_removable = DEF_REMOVABLE; static bool scsi_debug_clustering; +static bool scsi_debug_host_lock = DEF_HOST_LOCK; -static int scsi_debug_cmnd_count = 0; +static atomic_t sdebug_cmnd_count; +static atomic_t sdebug_completions; +static atomic_t sdebug_a_tsf; /* counter of 'almost' TSFs */ #define DEV_READONLY(TGT) (0) @@ -214,24 +263,23 @@ static int sdebug_sectors_per; /* sectors per cylinder */ #define SDEBUG_MAX_PARTS 4 -#define SDEBUG_SENSE_LEN 32 - #define SCSI_DEBUG_MAX_CMD_LEN 32 static unsigned int scsi_debug_lbp(void) { - return scsi_debug_lbpu | scsi_debug_lbpws | scsi_debug_lbpws10; + return ((0 == scsi_debug_fake_rw) && + (scsi_debug_lbpu | scsi_debug_lbpws | scsi_debug_lbpws10)); } struct sdebug_dev_info { struct list_head dev_list; - unsigned char sense_buff[SDEBUG_SENSE_LEN]; /* weak nexus */ unsigned int channel; unsigned int target; - unsigned int lun; + u64 lun; struct sdebug_host_info *sdbg_host; - unsigned int wlun; - char reset; + u64 wlun; + unsigned long uas_bm[1]; + atomic_t num_in_q; char stopped; char used; }; @@ -249,26 +297,33 @@ struct sdebug_host_info { static LIST_HEAD(sdebug_host_list); static DEFINE_SPINLOCK(sdebug_host_list_lock); -typedef void (* done_funct_t) (struct scsi_cmnd *); + +struct sdebug_hrtimer { /* ... is derived from hrtimer */ + struct hrtimer hrt; /* must be first element */ + int qa_indx; +}; struct sdebug_queued_cmd { - int in_use; - struct timer_list cmnd_timer; - done_funct_t done_funct; + /* in_use flagged by a bit in queued_in_use_bm[] */ + struct timer_list *cmnd_timerp; + struct tasklet_struct *tletp; + struct sdebug_hrtimer *sd_hrtp; struct scsi_cmnd * a_cmnd; - int scsi_result; }; static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE]; +static unsigned long queued_in_use_bm[SCSI_DEBUG_CANQUEUE_WORDS]; + static unsigned char * fake_storep; /* ramdisk storage */ static struct sd_dif_tuple *dif_storep; /* protection info */ static void *map_storep; /* provisioning map */ static unsigned long map_size; -static int num_aborts = 0; -static int num_dev_resets = 0; -static int num_bus_resets = 0; -static int num_host_resets = 0; +static int num_aborts; +static int num_dev_resets; +static int num_target_resets; +static int num_bus_resets; +static int num_host_resets; static int dix_writes; static int dix_reads; static int dif_errors; @@ -276,7 +331,8 @@ static int dif_errors; static DEFINE_SPINLOCK(queued_arr_lock); static DEFINE_RWLOCK(atomic_rw); -static char sdebug_proc_name[] = "scsi_debug"; +static char sdebug_proc_name[] = MY_NAME; +static const char *my_name = MY_NAME; static struct bus_type pseudo_lld_bus; @@ -291,6 +347,12 @@ static const int check_condition_result = static const int illegal_condition_result = (DRIVER_SENSE << 24) | (DID_ABORT << 16) | SAM_STAT_CHECK_CONDITION; +static const int device_qfull_result = + (DID_OK << 16) | (COMMAND_COMPLETE << 8) | SAM_STAT_TASK_SET_FULL; + +static unsigned char caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0, + 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, + 0, 0, 0, 0}; static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0, 0, 0, 0x2, 0x4b}; static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0, @@ -332,19 +394,24 @@ static void sdebug_max_tgts_luns(void) spin_unlock(&sdebug_host_list_lock); } -static void mk_sense_buffer(struct sdebug_dev_info *devip, int key, - int asc, int asq) +static void mk_sense_buffer(struct scsi_cmnd *scp, int key, int asc, int asq) { unsigned char *sbuff; - sbuff = devip->sense_buff; - memset(sbuff, 0, SDEBUG_SENSE_LEN); + sbuff = scp->sense_buffer; + if (!sbuff) { + sdev_printk(KERN_ERR, scp->device, + "%s: sense_buffer is NULL\n", __func__); + return; + } + memset(sbuff, 0, SCSI_SENSE_BUFFERSIZE); scsi_build_sense_buffer(scsi_debug_dsense, sbuff, key, asc, asq); if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: [sense_key,asc,ascq]: " - "[0x%x,0x%x,0x%x]\n", key, asc, asq); + sdev_printk(KERN_INFO, scp->device, + "%s: [sense_key,asc,ascq]: [0x%x,0x%x,0x%x]\n", + my_name, key, asc, asq); } static void get_data_transfer_info(unsigned char *cmd, @@ -409,29 +476,71 @@ static void get_data_transfer_info(unsigned char *cmd, static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg) { if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) { - printk(KERN_INFO "scsi_debug: ioctl: cmd=0x%x\n", cmd); + if (0x1261 == cmd) + sdev_printk(KERN_INFO, dev, + "%s: BLKFLSBUF [0x1261]\n", __func__); + else if (0x5331 == cmd) + sdev_printk(KERN_INFO, dev, + "%s: CDROM_GET_CAPABILITY [0x5331]\n", + __func__); + else + sdev_printk(KERN_INFO, dev, "%s: cmd=0x%x\n", + __func__, cmd); } return -EINVAL; /* return -ENOTTY; // correct return but upsets fdisk */ } -static int check_readiness(struct scsi_cmnd * SCpnt, int reset_only, +static int check_readiness(struct scsi_cmnd *SCpnt, int uas_only, struct sdebug_dev_info * devip) { - if (devip->reset) { - if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: Reporting Unit " - "attention: power on reset\n"); - devip->reset = 0; - mk_sense_buffer(devip, UNIT_ATTENTION, POWERON_RESET, 0); + int k; + bool debug = !!(SCSI_DEBUG_OPT_NOISE & scsi_debug_opts); + + k = find_first_bit(devip->uas_bm, SDEBUG_NUM_UAS); + if (k != SDEBUG_NUM_UAS) { + const char *cp = NULL; + + switch (k) { + case SDEBUG_UA_POR: + mk_sense_buffer(SCpnt, UNIT_ATTENTION, + UA_RESET_ASC, POWER_ON_RESET_ASCQ); + if (debug) + cp = "power on reset"; + break; + case SDEBUG_UA_BUS_RESET: + mk_sense_buffer(SCpnt, UNIT_ATTENTION, + UA_RESET_ASC, BUS_RESET_ASCQ); + if (debug) + cp = "bus reset"; + break; + case SDEBUG_UA_MODE_CHANGED: + mk_sense_buffer(SCpnt, UNIT_ATTENTION, + UA_CHANGED_ASC, MODE_CHANGED_ASCQ); + if (debug) + cp = "mode parameters changed"; + break; + default: + pr_warn("%s: unexpected unit attention code=%d\n", + __func__, k); + if (debug) + cp = "unknown"; + break; + } + clear_bit(k, devip->uas_bm); + if (debug) + sdev_printk(KERN_INFO, SCpnt->device, + "%s reports: Unit attention: %s\n", + my_name, cp); return check_condition_result; } - if ((0 == reset_only) && devip->stopped) { - if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: Reporting Not " - "ready: initializing command required\n"); - mk_sense_buffer(devip, NOT_READY, LOGICAL_UNIT_NOT_READY, + if ((UAS_TUR == uas_only) && devip->stopped) { + mk_sense_buffer(SCpnt, NOT_READY, LOGICAL_UNIT_NOT_READY, 0x2); + if (debug) + sdev_printk(KERN_INFO, SCpnt->device, + "%s reports: Not ready: %s\n", my_name, + "initializing command required"); return check_condition_result; } return 0; @@ -471,8 +580,9 @@ static int fetch_to_dev_buffer(struct scsi_cmnd *scp, unsigned char *arr, static const char * inq_vendor_id = "Linux "; static const char * inq_product_id = "scsi_debug "; -static const char * inq_product_rev = "0004"; +static const char *inq_product_rev = "0184"; /* version less '.' */ +/* Device identification VPD page. Returns number of bytes placed in arr */ static int inquiry_evpd_83(unsigned char * arr, int port_group_id, int target_dev_id, int dev_id_num, const char * dev_id_str, @@ -573,12 +683,14 @@ static unsigned char vpd84_data[] = { 0x22,0x22,0x22,0x0,0xbb,0x2, }; +/* Software interface identification VPD page */ static int inquiry_evpd_84(unsigned char * arr) { memcpy(arr, vpd84_data, sizeof(vpd84_data)); return sizeof(vpd84_data); } +/* Management network addresses VPD page */ static int inquiry_evpd_85(unsigned char * arr) { int num = 0; @@ -713,6 +825,7 @@ static unsigned char vpd89_data[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0xa5,0x51, }; +/* ATA Information VPD page */ static int inquiry_evpd_89(unsigned char * arr) { memcpy(arr, vpd89_data, sizeof(vpd89_data)); @@ -720,7 +833,6 @@ static int inquiry_evpd_89(unsigned char * arr) } -/* Block limits VPD page (SBC-3) */ static unsigned char vpdb0_data[] = { /* from 4th byte */ 0,0,0,4, 0,0,0x4,0, 0,0,0,64, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -728,6 +840,7 @@ static unsigned char vpdb0_data[] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, }; +/* Block limits VPD page (SBC-3) */ static int inquiry_evpd_b0(unsigned char * arr) { unsigned int gran; @@ -811,7 +924,7 @@ static int inquiry_evpd_b2(unsigned char *arr) #define SDEBUG_LONG_INQ_SZ 96 #define SDEBUG_MAX_INQ_ARR_SZ 584 -static int resp_inquiry(struct scsi_cmnd * scp, int target, +static int resp_inquiry(struct scsi_cmnd *scp, int target, struct sdebug_dev_info * devip) { unsigned char pq_pdt; @@ -831,7 +944,7 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target, pq_pdt = (scsi_debug_ptype & 0x1f); arr[0] = pq_pdt; if (0x2 & cmd[1]) { /* CMDDT bit set */ - mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); kfree(arr); return check_condition_result; @@ -917,7 +1030,7 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target, arr[3] = inquiry_evpd_b2(&arr[4]); } else { /* Illegal request, invalid field in cdb */ - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); kfree(arr); return check_condition_result; @@ -963,15 +1076,13 @@ static int resp_requests(struct scsi_cmnd * scp, { unsigned char * sbuff; unsigned char *cmd = (unsigned char *)scp->cmnd; - unsigned char arr[SDEBUG_SENSE_LEN]; + unsigned char arr[SCSI_SENSE_BUFFERSIZE]; int want_dsense; int len = 18; memset(arr, 0, sizeof(arr)); - if (devip->reset == 1) - mk_sense_buffer(devip, 0, NO_ADDITIONAL_SENSE, 0); want_dsense = !!(cmd[1] & 1) || scsi_debug_dsense; - sbuff = devip->sense_buff; + sbuff = scp->sense_buffer; if ((iec_m_pg[2] & 0x4) && (6 == (iec_m_pg[3] & 0xf))) { if (want_dsense) { arr[0] = 0x72; @@ -986,7 +1097,7 @@ static int resp_requests(struct scsi_cmnd * scp, arr[13] = 0xff; /* TEST set and MRIE==6 */ } } else { - memcpy(arr, sbuff, SDEBUG_SENSE_LEN); + memcpy(arr, sbuff, SCSI_SENSE_BUFFERSIZE); if ((cmd[1] & 1) && (! scsi_debug_dsense)) { /* DESC bit set and sense_buff in fixed format */ memset(arr, 0, sizeof(arr)); @@ -997,7 +1108,7 @@ static int resp_requests(struct scsi_cmnd * scp, len = 8; } } - mk_sense_buffer(devip, 0, NO_ADDITIONAL_SENSE, 0); + mk_sense_buffer(scp, 0, NO_ADDITIONAL_SENSE, 0); return fill_from_dev_buffer(scp, arr, len); } @@ -1007,11 +1118,12 @@ static int resp_start_stop(struct scsi_cmnd * scp, unsigned char *cmd = (unsigned char *)scp->cmnd; int power_cond, errsts, start; - if ((errsts = check_readiness(scp, 1, devip))) + errsts = check_readiness(scp, UAS_ONLY, devip); + if (errsts) return errsts; power_cond = (cmd[4] & 0xf0) >> 4; if (power_cond) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } @@ -1038,7 +1150,8 @@ static int resp_readcap(struct scsi_cmnd * scp, unsigned int capac; int errsts; - if ((errsts = check_readiness(scp, 1, devip))) + errsts = check_readiness(scp, UAS_ONLY, devip); + if (errsts) return errsts; /* following just in case virtual_gb changed */ sdebug_capacity = get_sdebug_capacity(); @@ -1069,7 +1182,8 @@ static int resp_readcap16(struct scsi_cmnd * scp, unsigned long long capac; int errsts, k, alloc_len; - if ((errsts = check_readiness(scp, 1, devip))) + errsts = check_readiness(scp, UAS_ONLY, devip); + if (errsts) return errsts; alloc_len = ((cmd[10] << 24) + (cmd[11] << 16) + (cmd[12] << 8) + cmd[13]); @@ -1230,12 +1344,18 @@ static int resp_format_pg(unsigned char * p, int pcontrol, int target) static int resp_caching_pg(unsigned char * p, int pcontrol, int target) { /* Caching page for mode_sense */ - unsigned char caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0, + unsigned char ch_caching_pg[] = {/* 0x8, 18, */ 0x4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + unsigned char d_caching_pg[] = {0x8, 18, 0x14, 0, 0xff, 0xff, 0, 0, 0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0, 0, 0, 0, 0, 0}; + if (SCSI_DEBUG_OPT_N_WCE & scsi_debug_opts) + caching_pg[2] &= ~0x4; /* set WCE=0 (default WCE=1) */ memcpy(p, caching_pg, sizeof(caching_pg)); if (1 == pcontrol) - memset(p + 2, 0, sizeof(caching_pg) - 2); + memcpy(p + 2, ch_caching_pg, sizeof(ch_caching_pg)); + else if (2 == pcontrol) + memcpy(p, d_caching_pg, sizeof(d_caching_pg)); return sizeof(caching_pg); } @@ -1350,7 +1470,8 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target, unsigned char arr[SDEBUG_MAX_MSENSE_SZ]; unsigned char *cmd = (unsigned char *)scp->cmnd; - if ((errsts = check_readiness(scp, 1, devip))) + errsts = check_readiness(scp, UAS_ONLY, devip); + if (errsts) return errsts; dbd = !!(cmd[1] & 0x8); pcontrol = (cmd[2] & 0xc0) >> 6; @@ -1365,8 +1486,7 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target, alloc_len = msense_6 ? cmd[4] : ((cmd[7] << 8) | cmd[8]); memset(arr, 0, SDEBUG_MAX_MSENSE_SZ); if (0x3 == pcontrol) { /* Saving values not supported */ - mk_sense_buffer(devip, ILLEGAL_REQUEST, SAVING_PARAMS_UNSUP, - 0); + mk_sense_buffer(scp, ILLEGAL_REQUEST, SAVING_PARAMS_UNSUP, 0); return check_condition_result; } target_dev_id = ((devip->sdbg_host->shost->host_no + 1) * 2000) + @@ -1422,7 +1542,7 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target, if ((subpcode > 0x0) && (subpcode < 0xff) && (0x19 != pcode)) { /* TODO: Control Extension page */ - mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } @@ -1449,7 +1569,7 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target, break; case 0x19: /* if spc==1 then sas phy, control+discover */ if ((subpcode > 0x2) && (subpcode < 0xff)) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } @@ -1482,14 +1602,14 @@ static int resp_mode_sense(struct scsi_cmnd * scp, int target, } len += resp_iec_m_pg(ap + len, pcontrol, target); } else { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } offset += len; break; default: - mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } @@ -1512,14 +1632,15 @@ static int resp_mode_select(struct scsi_cmnd * scp, int mselect6, unsigned char arr[SDEBUG_MAX_MSELECT_SZ]; unsigned char *cmd = (unsigned char *)scp->cmnd; - if ((errsts = check_readiness(scp, 1, devip))) + errsts = check_readiness(scp, UAS_ONLY, devip); + if (errsts) return errsts; memset(arr, 0, sizeof(arr)); pf = cmd[1] & 0x10; sp = cmd[1] & 0x1; param_len = mselect6 ? cmd[4] : ((cmd[7] << 8) + cmd[8]); if ((0 == pf) || sp || (param_len > SDEBUG_MAX_MSELECT_SZ)) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } @@ -1528,12 +1649,13 @@ static int resp_mode_select(struct scsi_cmnd * scp, int mselect6, return (DID_ERROR << 16); else if ((res < param_len) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) - printk(KERN_INFO "scsi_debug: mode_select: cdb indicated=%d, " - " IO sent=%d bytes\n", param_len, res); + sdev_printk(KERN_INFO, scp->device, + "%s: cdb indicated=%d, IO sent=%d bytes\n", + __func__, param_len, res); md_len = mselect6 ? (arr[0] + 1) : ((arr[0] << 8) + arr[1] + 2); bd_len = mselect6 ? arr[3] : ((arr[6] << 8) + arr[7]); if (md_len > 2) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_PARAM_LIST, 0); return check_condition_result; } @@ -1541,7 +1663,7 @@ static int resp_mode_select(struct scsi_cmnd * scp, int mselect6, mpage = arr[off] & 0x3f; ps = !!(arr[off] & 0x80); if (ps) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_PARAM_LIST, 0); return check_condition_result; } @@ -1549,32 +1671,42 @@ static int resp_mode_select(struct scsi_cmnd * scp, int mselect6, pg_len = spf ? ((arr[off + 2] << 8) + arr[off + 3] + 4) : (arr[off + 1] + 2); if ((pg_len + off) > param_len) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(scp, ILLEGAL_REQUEST, PARAMETER_LIST_LENGTH_ERR, 0); return check_condition_result; } switch (mpage) { + case 0x8: /* Caching Mode page */ + if (caching_pg[1] == arr[off + 1]) { + memcpy(caching_pg + 2, arr + off + 2, + sizeof(caching_pg) - 2); + goto set_mode_changed_ua; + } + break; case 0xa: /* Control Mode page */ if (ctrl_m_pg[1] == arr[off + 1]) { memcpy(ctrl_m_pg + 2, arr + off + 2, sizeof(ctrl_m_pg) - 2); scsi_debug_dsense = !!(ctrl_m_pg[2] & 0x4); - return 0; + goto set_mode_changed_ua; } break; case 0x1c: /* Informational Exceptions Mode page */ if (iec_m_pg[1] == arr[off + 1]) { memcpy(iec_m_pg + 2, arr + off + 2, sizeof(iec_m_pg) - 2); - return 0; + goto set_mode_changed_ua; } break; default: break; } - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_PARAM_LIST, 0); return check_condition_result; +set_mode_changed_ua: + set_bit(SDEBUG_UA_MODE_CHANGED, devip->uas_bm); + return 0; } static int resp_temp_l_pg(unsigned char * arr) @@ -1609,13 +1741,14 @@ static int resp_log_sense(struct scsi_cmnd * scp, unsigned char arr[SDEBUG_MAX_LSENSE_SZ]; unsigned char *cmd = (unsigned char *)scp->cmnd; - if ((errsts = check_readiness(scp, 1, devip))) + errsts = check_readiness(scp, UAS_ONLY, devip); + if (errsts) return errsts; memset(arr, 0, sizeof(arr)); ppc = cmd[1] & 0x2; sp = cmd[1] & 0x1; if (ppc || sp) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } @@ -1640,7 +1773,7 @@ static int resp_log_sense(struct scsi_cmnd * scp, arr[3] = resp_ie_l_pg(arr + 4); break; default: - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } @@ -1673,12 +1806,12 @@ static int resp_log_sense(struct scsi_cmnd * scp, arr[3] = n - 4; break; default: - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } } else { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } @@ -1687,16 +1820,16 @@ static int resp_log_sense(struct scsi_cmnd * scp, min(len, SDEBUG_MAX_INQ_ARR_SZ)); } -static int check_device_access_params(struct sdebug_dev_info *devi, +static int check_device_access_params(struct scsi_cmnd *scp, unsigned long long lba, unsigned int num) { if (lba + num > sdebug_capacity) { - mk_sense_buffer(devi, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, 0); + mk_sense_buffer(scp, ILLEGAL_REQUEST, ADDR_OUT_OF_RANGE, 0); return check_condition_result; } /* transfer length excessive (tie in to block limits VPD page) */ if (num > sdebug_store_sectors) { - mk_sense_buffer(devi, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } return 0; @@ -1704,7 +1837,6 @@ static int check_device_access_params(struct sdebug_dev_info *devi, /* Returns number of bytes copied or -1 if error. */ static int do_device_access(struct scsi_cmnd *scmd, - struct sdebug_dev_info *devi, unsigned long long lba, unsigned int num, int write) { int ret; @@ -1861,13 +1993,12 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec, } static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba, - unsigned int num, struct sdebug_dev_info *devip, - u32 ei_lba) + unsigned int num, u32 ei_lba) { unsigned long iflags; int ret; - ret = check_device_access_params(devip, lba, num); + ret = check_device_access_params(SCpnt, lba, num); if (ret) return ret; @@ -1875,16 +2006,16 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba, (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) && ((lba + num) > OPT_MEDIUM_ERR_ADDR)) { /* claim unrecoverable read error */ - mk_sense_buffer(devip, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0); + mk_sense_buffer(SCpnt, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0); /* set info field and valid bit for fixed descriptor */ - if (0x70 == (devip->sense_buff[0] & 0x7f)) { - devip->sense_buff[0] |= 0x80; /* Valid bit */ + if (0x70 == (SCpnt->sense_buffer[0] & 0x7f)) { + SCpnt->sense_buffer[0] |= 0x80; /* Valid bit */ ret = (lba < OPT_MEDIUM_ERR_ADDR) ? OPT_MEDIUM_ERR_ADDR : (int)lba; - devip->sense_buff[3] = (ret >> 24) & 0xff; - devip->sense_buff[4] = (ret >> 16) & 0xff; - devip->sense_buff[5] = (ret >> 8) & 0xff; - devip->sense_buff[6] = ret & 0xff; + SCpnt->sense_buffer[3] = (ret >> 24) & 0xff; + SCpnt->sense_buffer[4] = (ret >> 16) & 0xff; + SCpnt->sense_buffer[5] = (ret >> 8) & 0xff; + SCpnt->sense_buffer[6] = ret & 0xff; } scsi_set_resid(SCpnt, scsi_bufflen(SCpnt)); return check_condition_result; @@ -1898,12 +2029,12 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba, if (prot_ret) { read_unlock_irqrestore(&atomic_rw, iflags); - mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, prot_ret); + mk_sense_buffer(SCpnt, ABORTED_COMMAND, 0x10, prot_ret); return illegal_condition_result; } } - ret = do_device_access(SCpnt, devip, lba, num, 0); + ret = do_device_access(SCpnt, lba, num, 0); read_unlock_irqrestore(&atomic_rw, iflags); if (ret == -1) return DID_ERROR << 16; @@ -1915,22 +2046,23 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba, void dump_sector(unsigned char *buf, int len) { - int i, j; - - printk(KERN_ERR ">>> Sector Dump <<<\n"); + int i, j, n; + pr_err(">>> Sector Dump <<<\n"); for (i = 0 ; i < len ; i += 16) { - printk(KERN_ERR "%04d: ", i); + char b[128]; - for (j = 0 ; j < 16 ; j++) { + for (j = 0, n = 0; j < 16; j++) { unsigned char c = buf[i+j]; + if (c >= 0x20 && c < 0x7e) - printk(" %c ", buf[i+j]); + n += scnprintf(b + n, sizeof(b) - n, + " %c ", buf[i+j]); else - printk("%02x ", buf[i+j]); + n += scnprintf(b + n, sizeof(b) - n, + "%02x ", buf[i+j]); } - - printk("\n"); + pr_err("%04d: %s\n", i, b); } } @@ -2092,13 +2224,12 @@ static void unmap_region(sector_t lba, unsigned int len) } static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba, - unsigned int num, struct sdebug_dev_info *devip, - u32 ei_lba) + unsigned int num, u32 ei_lba) { unsigned long iflags; int ret; - ret = check_device_access_params(devip, lba, num); + ret = check_device_access_params(SCpnt, lba, num); if (ret) return ret; @@ -2110,12 +2241,13 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba, if (prot_ret) { write_unlock_irqrestore(&atomic_rw, iflags); - mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, prot_ret); + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 0x10, + prot_ret); return illegal_condition_result; } } - ret = do_device_access(SCpnt, devip, lba, num, 1); + ret = do_device_access(SCpnt, lba, num, 1); if (scsi_debug_lbp()) map_region(lba, num); write_unlock_irqrestore(&atomic_rw, iflags); @@ -2123,26 +2255,26 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba, return (DID_ERROR << 16); else if ((ret < (num * scsi_debug_sector_size)) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) - printk(KERN_INFO "scsi_debug: write: cdb indicated=%u, " - " IO sent=%d bytes\n", num * scsi_debug_sector_size, ret); + sdev_printk(KERN_INFO, SCpnt->device, + "%s: write: cdb indicated=%u, IO sent=%d bytes\n", + my_name, num * scsi_debug_sector_size, ret); return 0; } static int resp_write_same(struct scsi_cmnd *scmd, unsigned long long lba, - unsigned int num, struct sdebug_dev_info *devip, - u32 ei_lba, unsigned int unmap) + unsigned int num, u32 ei_lba, unsigned int unmap) { unsigned long iflags; unsigned long long i; int ret; - ret = check_device_access_params(devip, lba, num); + ret = check_device_access_params(scmd, lba, num); if (ret) return ret; if (num > scsi_debug_write_same_length) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, + mk_sense_buffer(scmd, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } @@ -2164,8 +2296,10 @@ static int resp_write_same(struct scsi_cmnd *scmd, unsigned long long lba, return (DID_ERROR << 16); } else if ((ret < (num * scsi_debug_sector_size)) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) - printk(KERN_INFO "scsi_debug: write same: cdb indicated=%u, " - " IO sent=%d bytes\n", num * scsi_debug_sector_size, ret); + sdev_printk(KERN_INFO, scmd->device, + "%s: %s: cdb indicated=%u, IO sent=%d bytes\n", + my_name, "write same", + num * scsi_debug_sector_size, ret); /* Copy first sector to remaining blocks */ for (i = 1 ; i < num ; i++) @@ -2195,7 +2329,7 @@ static int resp_unmap(struct scsi_cmnd * scmd, struct sdebug_dev_info * devip) int ret; unsigned long iflags; - ret = check_readiness(scmd, 1, devip); + ret = check_readiness(scmd, UAS_ONLY, devip); if (ret) return ret; @@ -2221,7 +2355,7 @@ static int resp_unmap(struct scsi_cmnd * scmd, struct sdebug_dev_info * devip) unsigned long long lba = get_unaligned_be64(&desc[i].lba); unsigned int num = get_unaligned_be32(&desc[i].blocks); - ret = check_device_access_params(devip, lba, num); + ret = check_device_access_params(scmd, lba, num); if (ret) goto out; @@ -2247,7 +2381,7 @@ static int resp_get_lba_status(struct scsi_cmnd * scmd, unsigned char arr[SDEBUG_GET_LBA_STATUS_LEN]; int ret; - ret = check_readiness(scmd, 1, devip); + ret = check_readiness(scmd, UAS_ONLY, devip); if (ret) return ret; @@ -2257,7 +2391,7 @@ static int resp_get_lba_status(struct scsi_cmnd * scmd, if (alloc_len < 24) return 0; - ret = check_device_access_params(devip, lba, 1); + ret = check_device_access_params(scmd, lba, 1); if (ret) return ret; @@ -2278,7 +2412,8 @@ static int resp_report_luns(struct scsi_cmnd * scp, struct sdebug_dev_info * devip) { unsigned int alloc_len; - int lun_cnt, i, upper, num, n, wlun, lun; + int lun_cnt, i, upper, num, n; + u64 wlun, lun; unsigned char *cmd = (unsigned char *)scp->cmnd; int select_report = (int)cmd[2]; struct scsi_lun *one_lun; @@ -2287,7 +2422,7 @@ static int resp_report_luns(struct scsi_cmnd * scp, alloc_len = cmd[9] + (cmd[8] << 8) + (cmd[7] << 16) + (cmd[6] << 24); if ((alloc_len < 4) || (select_report > 2)) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, + mk_sense_buffer(scp, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); return check_condition_result; } @@ -2341,7 +2476,7 @@ static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba, /* better not to use temporary buffer. */ buf = kmalloc(scsi_bufflen(scp), GFP_ATOMIC); if (!buf) { - mk_sense_buffer(devip, NOT_READY, + mk_sense_buffer(scp, NOT_READY, LOGICAL_UNIT_COMMUNICATION_FAILURE, 0); return check_condition_result; } @@ -2365,34 +2500,125 @@ static int resp_xdwriteread(struct scsi_cmnd *scp, unsigned long long lba, return 0; } -/* When timer goes off this function is called. */ -static void timer_intr_handler(unsigned long indx) +/* When timer or tasklet goes off this function is called. */ +static void sdebug_q_cmd_complete(unsigned long indx) { - struct sdebug_queued_cmd * sqcp; + int qa_indx; + int retiring = 0; unsigned long iflags; + struct sdebug_queued_cmd *sqcp; + struct scsi_cmnd *scp; + struct sdebug_dev_info *devip; - if (indx >= scsi_debug_max_queue) { - printk(KERN_ERR "scsi_debug:timer_intr_handler: indx too " - "large\n"); + atomic_inc(&sdebug_completions); + qa_indx = indx; + if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) { + pr_err("%s: wild qa_indx=%d\n", __func__, qa_indx); return; } spin_lock_irqsave(&queued_arr_lock, iflags); - sqcp = &queued_arr[(int)indx]; - if (! sqcp->in_use) { - printk(KERN_ERR "scsi_debug:timer_intr_handler: Unexpected " - "interrupt\n"); + sqcp = &queued_arr[qa_indx]; + scp = sqcp->a_cmnd; + if (NULL == scp) { + spin_unlock_irqrestore(&queued_arr_lock, iflags); + pr_err("%s: scp is NULL\n", __func__); + return; + } + devip = (struct sdebug_dev_info *)scp->device->hostdata; + if (devip) + atomic_dec(&devip->num_in_q); + else + pr_err("%s: devip=NULL\n", __func__); + if (atomic_read(&retired_max_queue) > 0) + retiring = 1; + + sqcp->a_cmnd = NULL; + if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) { spin_unlock_irqrestore(&queued_arr_lock, iflags); + pr_err("%s: Unexpected completion\n", __func__); return; } - sqcp->in_use = 0; - if (sqcp->done_funct) { - sqcp->a_cmnd->result = sqcp->scsi_result; - sqcp->done_funct(sqcp->a_cmnd); /* callback to mid level */ + + if (unlikely(retiring)) { /* user has reduced max_queue */ + int k, retval; + + retval = atomic_read(&retired_max_queue); + if (qa_indx >= retval) { + spin_unlock_irqrestore(&queued_arr_lock, iflags); + pr_err("%s: index %d too large\n", __func__, retval); + return; + } + k = find_last_bit(queued_in_use_bm, retval); + if ((k < scsi_debug_max_queue) || (k == retval)) + atomic_set(&retired_max_queue, 0); + else + atomic_set(&retired_max_queue, k + 1); } - sqcp->done_funct = NULL; spin_unlock_irqrestore(&queued_arr_lock, iflags); + scp->scsi_done(scp); /* callback to mid level */ } +/* When high resolution timer goes off this function is called. */ +static enum hrtimer_restart +sdebug_q_cmd_hrt_complete(struct hrtimer *timer) +{ + int qa_indx; + int retiring = 0; + unsigned long iflags; + struct sdebug_hrtimer *sd_hrtp = (struct sdebug_hrtimer *)timer; + struct sdebug_queued_cmd *sqcp; + struct scsi_cmnd *scp; + struct sdebug_dev_info *devip; + + atomic_inc(&sdebug_completions); + qa_indx = sd_hrtp->qa_indx; + if ((qa_indx < 0) || (qa_indx >= SCSI_DEBUG_CANQUEUE)) { + pr_err("%s: wild qa_indx=%d\n", __func__, qa_indx); + goto the_end; + } + spin_lock_irqsave(&queued_arr_lock, iflags); + sqcp = &queued_arr[qa_indx]; + scp = sqcp->a_cmnd; + if (NULL == scp) { + spin_unlock_irqrestore(&queued_arr_lock, iflags); + pr_err("%s: scp is NULL\n", __func__); + goto the_end; + } + devip = (struct sdebug_dev_info *)scp->device->hostdata; + if (devip) + atomic_dec(&devip->num_in_q); + else + pr_err("%s: devip=NULL\n", __func__); + if (atomic_read(&retired_max_queue) > 0) + retiring = 1; + + sqcp->a_cmnd = NULL; + if (!test_and_clear_bit(qa_indx, queued_in_use_bm)) { + spin_unlock_irqrestore(&queued_arr_lock, iflags); + pr_err("%s: Unexpected completion\n", __func__); + goto the_end; + } + + if (unlikely(retiring)) { /* user has reduced max_queue */ + int k, retval; + + retval = atomic_read(&retired_max_queue); + if (qa_indx >= retval) { + spin_unlock_irqrestore(&queued_arr_lock, iflags); + pr_err("%s: index %d too large\n", __func__, retval); + goto the_end; + } + k = find_last_bit(queued_in_use_bm, retval); + if ((k < scsi_debug_max_queue) || (k == retval)) + atomic_set(&retired_max_queue, 0); + else + atomic_set(&retired_max_queue, k + 1); + } + spin_unlock_irqrestore(&queued_arr_lock, iflags); + scp->scsi_done(scp); /* callback to mid level */ +the_end: + return HRTIMER_NORESTART; +} static struct sdebug_dev_info * sdebug_device_create(struct sdebug_host_info *sdbg_host, gfp_t flags) @@ -2418,7 +2644,7 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev) return devip; sdbg_host = *(struct sdebug_host_info **)shost_priv(sdev->host); if (!sdbg_host) { - printk(KERN_ERR "Host info NULL\n"); + pr_err("%s: Host info NULL\n", __func__); return NULL; } list_for_each_entry(devip, &sdbg_host->dev_info_list, dev_list) { @@ -2444,15 +2670,9 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev) open_devip->target = sdev->id; open_devip->lun = sdev->lun; open_devip->sdbg_host = sdbg_host; - open_devip->reset = 1; + atomic_set(&open_devip->num_in_q, 0); + set_bit(SDEBUG_UA_POR, open_devip->uas_bm); open_devip->used = 1; - memset(open_devip->sense_buff, 0, SDEBUG_SENSE_LEN); - if (scsi_debug_dsense) - open_devip->sense_buff[0] = 0x72; - else { - open_devip->sense_buff[0] = 0x70; - open_devip->sense_buff[7] = 0xa; - } if (sdev->lun == SAM2_WLUN_REPORT_LUNS) open_devip->wlun = SAM2_WLUN_REPORT_LUNS & 0xff; @@ -2462,7 +2682,7 @@ static struct sdebug_dev_info * devInfoReg(struct scsi_device * sdev) static int scsi_debug_slave_alloc(struct scsi_device *sdp) { if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %u>\n", + printk(KERN_INFO "scsi_debug: slave_alloc <%u %u %u %llu>\n", sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); queue_flag_set_unlocked(QUEUE_FLAG_BIDI, sdp->request_queue); return 0; @@ -2473,7 +2693,7 @@ static int scsi_debug_slave_configure(struct scsi_device *sdp) struct sdebug_dev_info *devip; if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %u>\n", + printk(KERN_INFO "scsi_debug: slave_configure <%u %u %u %llu>\n", sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); if (sdp->host->max_cmd_len != SCSI_DEBUG_MAX_CMD_LEN) sdp->host->max_cmd_len = SCSI_DEBUG_MAX_CMD_LEN; @@ -2481,10 +2701,11 @@ static int scsi_debug_slave_configure(struct scsi_device *sdp) if (NULL == devip) return 1; /* no resources, will be marked offline */ sdp->hostdata = devip; + sdp->tagged_supported = 1; if (sdp->host->cmd_per_lun) - scsi_adjust_queue_depth(sdp, SDEBUG_TAGGED_QUEUING, - sdp->host->cmd_per_lun); - blk_queue_max_segment_size(sdp->request_queue, 256 * 1024); + scsi_adjust_queue_depth(sdp, DEF_TAGGED_QUEUING, + DEF_CMD_PER_LUN); + blk_queue_max_segment_size(sdp->request_queue, -1U); if (scsi_debug_no_uld) sdp->no_uld_attach = 1; return 0; @@ -2496,7 +2717,7 @@ static void scsi_debug_slave_destroy(struct scsi_device *sdp) (struct sdebug_dev_info *)sdp->hostdata; if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %u>\n", + printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %llu>\n", sdp->host->host_no, sdp->channel, sdp->id, sdp->lun); if (devip) { /* make this slot available for re-use */ @@ -2505,150 +2726,230 @@ static void scsi_debug_slave_destroy(struct scsi_device *sdp) } } -/* Returns 1 if found 'cmnd' and deleted its timer. else returns 0 */ +/* Returns 1 if cmnd found (deletes its timer or tasklet), else returns 0 */ static int stop_queued_cmnd(struct scsi_cmnd *cmnd) { unsigned long iflags; - int k; + int k, qmax, r_qmax; struct sdebug_queued_cmd *sqcp; + struct sdebug_dev_info *devip; spin_lock_irqsave(&queued_arr_lock, iflags); - for (k = 0; k < scsi_debug_max_queue; ++k) { - sqcp = &queued_arr[k]; - if (sqcp->in_use && (cmnd == sqcp->a_cmnd)) { - del_timer_sync(&sqcp->cmnd_timer); - sqcp->in_use = 0; - sqcp->a_cmnd = NULL; - break; + qmax = scsi_debug_max_queue; + r_qmax = atomic_read(&retired_max_queue); + if (r_qmax > qmax) + qmax = r_qmax; + for (k = 0; k < qmax; ++k) { + if (test_bit(k, queued_in_use_bm)) { + sqcp = &queued_arr[k]; + if (cmnd == sqcp->a_cmnd) { + if (scsi_debug_ndelay > 0) { + if (sqcp->sd_hrtp) + hrtimer_cancel( + &sqcp->sd_hrtp->hrt); + } else if (scsi_debug_delay > 0) { + if (sqcp->cmnd_timerp) + del_timer_sync( + sqcp->cmnd_timerp); + } else if (scsi_debug_delay < 0) { + if (sqcp->tletp) + tasklet_kill(sqcp->tletp); + } + __clear_bit(k, queued_in_use_bm); + devip = (struct sdebug_dev_info *) + cmnd->device->hostdata; + if (devip) + atomic_dec(&devip->num_in_q); + sqcp->a_cmnd = NULL; + break; + } } } spin_unlock_irqrestore(&queued_arr_lock, iflags); - return (k < scsi_debug_max_queue) ? 1 : 0; + return (k < qmax) ? 1 : 0; } -/* Deletes (stops) timers of all queued commands */ +/* Deletes (stops) timers or tasklets of all queued commands */ static void stop_all_queued(void) { unsigned long iflags; int k; struct sdebug_queued_cmd *sqcp; + struct sdebug_dev_info *devip; spin_lock_irqsave(&queued_arr_lock, iflags); - for (k = 0; k < scsi_debug_max_queue; ++k) { - sqcp = &queued_arr[k]; - if (sqcp->in_use && sqcp->a_cmnd) { - del_timer_sync(&sqcp->cmnd_timer); - sqcp->in_use = 0; - sqcp->a_cmnd = NULL; + for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) { + if (test_bit(k, queued_in_use_bm)) { + sqcp = &queued_arr[k]; + if (sqcp->a_cmnd) { + if (scsi_debug_ndelay > 0) { + if (sqcp->sd_hrtp) + hrtimer_cancel( + &sqcp->sd_hrtp->hrt); + } else if (scsi_debug_delay > 0) { + if (sqcp->cmnd_timerp) + del_timer_sync( + sqcp->cmnd_timerp); + } else if (scsi_debug_delay < 0) { + if (sqcp->tletp) + tasklet_kill(sqcp->tletp); + } + __clear_bit(k, queued_in_use_bm); + devip = (struct sdebug_dev_info *) + sqcp->a_cmnd->device->hostdata; + if (devip) + atomic_dec(&devip->num_in_q); + sqcp->a_cmnd = NULL; + } } } spin_unlock_irqrestore(&queued_arr_lock, iflags); } -static int scsi_debug_abort(struct scsi_cmnd * SCpnt) +/* Free queued command memory on heap */ +static void free_all_queued(void) { - if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: abort\n"); - ++num_aborts; - stop_queued_cmnd(SCpnt); - return SUCCESS; + unsigned long iflags; + int k; + struct sdebug_queued_cmd *sqcp; + + spin_lock_irqsave(&queued_arr_lock, iflags); + for (k = 0; k < SCSI_DEBUG_CANQUEUE; ++k) { + sqcp = &queued_arr[k]; + kfree(sqcp->cmnd_timerp); + sqcp->cmnd_timerp = NULL; + kfree(sqcp->tletp); + sqcp->tletp = NULL; + kfree(sqcp->sd_hrtp); + sqcp->sd_hrtp = NULL; + } + spin_unlock_irqrestore(&queued_arr_lock, iflags); } -static int scsi_debug_biosparam(struct scsi_device *sdev, - struct block_device * bdev, sector_t capacity, int *info) +static int scsi_debug_abort(struct scsi_cmnd *SCpnt) { - int res; - unsigned char *buf; - - if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: biosparam\n"); - buf = scsi_bios_ptable(bdev); - if (buf) { - res = scsi_partsize(buf, capacity, - &info[2], &info[0], &info[1]); - kfree(buf); - if (! res) - return res; - } - info[0] = sdebug_heads; - info[1] = sdebug_sectors_per; - info[2] = sdebug_cylinders_per; - return 0; + ++num_aborts; + if (SCpnt) { + if (SCpnt->device && + (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)) + sdev_printk(KERN_INFO, SCpnt->device, "%s\n", + __func__); + stop_queued_cmnd(SCpnt); + } + return SUCCESS; } static int scsi_debug_device_reset(struct scsi_cmnd * SCpnt) { struct sdebug_dev_info * devip; - if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: device_reset\n"); ++num_dev_resets; - if (SCpnt) { - devip = devInfoReg(SCpnt->device); + if (SCpnt && SCpnt->device) { + struct scsi_device *sdp = SCpnt->device; + + if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts) + sdev_printk(KERN_INFO, sdp, "%s\n", __func__); + devip = devInfoReg(sdp); if (devip) - devip->reset = 1; + set_bit(SDEBUG_UA_POR, devip->uas_bm); + } + return SUCCESS; +} + +static int scsi_debug_target_reset(struct scsi_cmnd *SCpnt) +{ + struct sdebug_host_info *sdbg_host; + struct sdebug_dev_info *devip; + struct scsi_device *sdp; + struct Scsi_Host *hp; + int k = 0; + + ++num_target_resets; + if (!SCpnt) + goto lie; + sdp = SCpnt->device; + if (!sdp) + goto lie; + if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts) + sdev_printk(KERN_INFO, sdp, "%s\n", __func__); + hp = sdp->host; + if (!hp) + goto lie; + sdbg_host = *(struct sdebug_host_info **)shost_priv(hp); + if (sdbg_host) { + list_for_each_entry(devip, + &sdbg_host->dev_info_list, + dev_list) + if (devip->target == sdp->id) { + set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm); + ++k; + } } + if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts) + sdev_printk(KERN_INFO, sdp, + "%s: %d device(s) found in target\n", __func__, k); +lie: return SUCCESS; } static int scsi_debug_bus_reset(struct scsi_cmnd * SCpnt) { struct sdebug_host_info *sdbg_host; - struct sdebug_dev_info * dev_info; + struct sdebug_dev_info *devip; struct scsi_device * sdp; struct Scsi_Host * hp; + int k = 0; - if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: bus_reset\n"); ++num_bus_resets; - if (SCpnt && ((sdp = SCpnt->device)) && ((hp = sdp->host))) { + if (!(SCpnt && SCpnt->device)) + goto lie; + sdp = SCpnt->device; + if (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts) + sdev_printk(KERN_INFO, sdp, "%s\n", __func__); + hp = sdp->host; + if (hp) { sdbg_host = *(struct sdebug_host_info **)shost_priv(hp); if (sdbg_host) { - list_for_each_entry(dev_info, + list_for_each_entry(devip, &sdbg_host->dev_info_list, - dev_list) - dev_info->reset = 1; + dev_list) { + set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm); + ++k; + } } } + if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts) + sdev_printk(KERN_INFO, sdp, + "%s: %d device(s) found in host\n", __func__, k); +lie: return SUCCESS; } static int scsi_debug_host_reset(struct scsi_cmnd * SCpnt) { struct sdebug_host_info * sdbg_host; - struct sdebug_dev_info * dev_info; + struct sdebug_dev_info *devip; + int k = 0; - if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: host_reset\n"); ++num_host_resets; + if ((SCpnt->device) && (SCSI_DEBUG_OPT_ALL_NOISE & scsi_debug_opts)) + sdev_printk(KERN_INFO, SCpnt->device, "%s\n", __func__); spin_lock(&sdebug_host_list_lock); list_for_each_entry(sdbg_host, &sdebug_host_list, host_list) { - list_for_each_entry(dev_info, &sdbg_host->dev_info_list, - dev_list) - dev_info->reset = 1; + list_for_each_entry(devip, &sdbg_host->dev_info_list, + dev_list) { + set_bit(SDEBUG_UA_BUS_RESET, devip->uas_bm); + ++k; + } } spin_unlock(&sdebug_host_list_lock); stop_all_queued(); + if (SCSI_DEBUG_OPT_RESET_NOISE & scsi_debug_opts) + sdev_printk(KERN_INFO, SCpnt->device, + "%s: %d device(s) found\n", __func__, k); return SUCCESS; } -/* Initializes timers in queued array */ -static void __init init_all_queued(void) -{ - unsigned long iflags; - int k; - struct sdebug_queued_cmd * sqcp; - - spin_lock_irqsave(&queued_arr_lock, iflags); - for (k = 0; k < scsi_debug_max_queue; ++k) { - sqcp = &queued_arr[k]; - init_timer(&sqcp->cmnd_timer); - sqcp->in_use = 0; - sqcp->a_cmnd = NULL; - } - spin_unlock_irqrestore(&queued_arr_lock, iflags); -} - static void __init sdebug_build_parts(unsigned char *ramp, unsigned long store_size) { @@ -2662,8 +2963,8 @@ static void __init sdebug_build_parts(unsigned char *ramp, return; if (scsi_debug_num_parts > SDEBUG_MAX_PARTS) { scsi_debug_num_parts = SDEBUG_MAX_PARTS; - printk(KERN_WARNING "scsi_debug:build_parts: reducing " - "partitions to %d\n", SDEBUG_MAX_PARTS); + pr_warn("%s: reducing partitions to %d\n", __func__, + SDEBUG_MAX_PARTS); } num_sectors = (int)sdebug_store_sectors; sectors_per_part = (num_sectors - sdebug_sectors_per) @@ -2700,62 +3001,130 @@ static void __init sdebug_build_parts(unsigned char *ramp, } } -static int schedule_resp(struct scsi_cmnd * cmnd, - struct sdebug_dev_info * devip, - done_funct_t done, int scsi_result, int delta_jiff) +static int +schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip, + int scsi_result, int delta_jiff) { - if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmnd) { - if (scsi_result) { - struct scsi_device * sdp = cmnd->device; + unsigned long iflags; + int k, num_in_q, tsf, qdepth, inject; + struct sdebug_queued_cmd *sqcp = NULL; + struct scsi_device *sdp = cmnd->device; + + if (NULL == cmnd || NULL == devip) { + pr_warn("%s: called with NULL cmnd or devip pointer\n", + __func__); + /* no particularly good error to report back */ + return SCSI_MLQUEUE_HOST_BUSY; + } + if ((scsi_result) && (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)) + sdev_printk(KERN_INFO, sdp, "%s: non-zero result=0x%x\n", + __func__, scsi_result); + if (delta_jiff == 0) { + /* using same thread to call back mid-layer */ + cmnd->result = scsi_result; + cmnd->scsi_done(cmnd); + return 0; + } - printk(KERN_INFO "scsi_debug: <%u %u %u %u> " - "non-zero result=0x%x\n", sdp->host->host_no, - sdp->channel, sdp->id, sdp->lun, scsi_result); + /* deferred response cases */ + spin_lock_irqsave(&queued_arr_lock, iflags); + num_in_q = atomic_read(&devip->num_in_q); + qdepth = cmnd->device->queue_depth; + k = find_first_zero_bit(queued_in_use_bm, scsi_debug_max_queue); + tsf = 0; + inject = 0; + if ((qdepth > 0) && (num_in_q >= qdepth)) + tsf = 1; + else if ((scsi_debug_every_nth != 0) && + (SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts)) { + if ((num_in_q == (qdepth - 1)) && + (atomic_inc_return(&sdebug_a_tsf) >= + abs(scsi_debug_every_nth))) { + atomic_set(&sdebug_a_tsf, 0); + inject = 1; + tsf = 1; } } - if (cmnd && devip) { - /* simulate autosense by this driver */ - if (SAM_STAT_CHECK_CONDITION == (scsi_result & 0xff)) - memcpy(cmnd->sense_buffer, devip->sense_buff, - (SCSI_SENSE_BUFFERSIZE > SDEBUG_SENSE_LEN) ? - SDEBUG_SENSE_LEN : SCSI_SENSE_BUFFERSIZE); - } - if (delta_jiff <= 0) { - if (cmnd) - cmnd->result = scsi_result; - if (done) - done(cmnd); - return 0; - } else { - unsigned long iflags; - int k; - struct sdebug_queued_cmd * sqcp = NULL; - spin_lock_irqsave(&queued_arr_lock, iflags); - for (k = 0; k < scsi_debug_max_queue; ++k) { - sqcp = &queued_arr[k]; - if (! sqcp->in_use) - break; + /* if (tsf) simulate device reporting SCSI status of TASK SET FULL. + * Might override existing CHECK CONDITION. */ + if (tsf) + scsi_result = device_qfull_result; + if (k >= scsi_debug_max_queue) { + if (SCSI_DEBUG_OPT_ALL_TSF & scsi_debug_opts) + tsf = 1; + spin_unlock_irqrestore(&queued_arr_lock, iflags); + if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) + sdev_printk(KERN_INFO, sdp, + "%s: num_in_q=%d, bypass q, %s%s\n", + __func__, num_in_q, + (inject ? "<inject> " : ""), + (tsf ? "status: TASK SET FULL" : + "report: host busy")); + if (tsf) { + /* queued_arr full so respond in same thread */ + cmnd->result = scsi_result; + cmnd->scsi_done(cmnd); + /* As scsi_done() is called "inline" must return 0 */ + return 0; + } else + return SCSI_MLQUEUE_HOST_BUSY; + } + __set_bit(k, queued_in_use_bm); + atomic_inc(&devip->num_in_q); + sqcp = &queued_arr[k]; + sqcp->a_cmnd = cmnd; + cmnd->result = scsi_result; + spin_unlock_irqrestore(&queued_arr_lock, iflags); + if (delta_jiff > 0) { + if (NULL == sqcp->cmnd_timerp) { + sqcp->cmnd_timerp = kmalloc(sizeof(struct timer_list), + GFP_ATOMIC); + if (NULL == sqcp->cmnd_timerp) + return SCSI_MLQUEUE_HOST_BUSY; + init_timer(sqcp->cmnd_timerp); } - if (k >= scsi_debug_max_queue) { - spin_unlock_irqrestore(&queued_arr_lock, iflags); - printk(KERN_WARNING "scsi_debug: can_queue exceeded\n"); - return 1; /* report busy to mid level */ + sqcp->cmnd_timerp->function = sdebug_q_cmd_complete; + sqcp->cmnd_timerp->data = k; + sqcp->cmnd_timerp->expires = get_jiffies_64() + delta_jiff; + add_timer(sqcp->cmnd_timerp); + } else if (scsi_debug_ndelay > 0) { + ktime_t kt = ktime_set(0, scsi_debug_ndelay); + struct sdebug_hrtimer *sd_hp = sqcp->sd_hrtp; + + if (NULL == sd_hp) { + sd_hp = kmalloc(sizeof(*sd_hp), GFP_ATOMIC); + if (NULL == sd_hp) + return SCSI_MLQUEUE_HOST_BUSY; + sqcp->sd_hrtp = sd_hp; + hrtimer_init(&sd_hp->hrt, CLOCK_MONOTONIC, + HRTIMER_MODE_REL); + sd_hp->hrt.function = sdebug_q_cmd_hrt_complete; + sd_hp->qa_indx = k; } - sqcp->in_use = 1; - sqcp->a_cmnd = cmnd; - sqcp->scsi_result = scsi_result; - sqcp->done_funct = done; - sqcp->cmnd_timer.function = timer_intr_handler; - sqcp->cmnd_timer.data = k; - sqcp->cmnd_timer.expires = jiffies + delta_jiff; - add_timer(&sqcp->cmnd_timer); - spin_unlock_irqrestore(&queued_arr_lock, iflags); - if (cmnd) - cmnd->result = 0; - return 0; + hrtimer_start(&sd_hp->hrt, kt, HRTIMER_MODE_REL); + } else { /* delay < 0 */ + if (NULL == sqcp->tletp) { + sqcp->tletp = kmalloc(sizeof(*sqcp->tletp), + GFP_ATOMIC); + if (NULL == sqcp->tletp) + return SCSI_MLQUEUE_HOST_BUSY; + tasklet_init(sqcp->tletp, + sdebug_q_cmd_complete, k); + } + if (-1 == delta_jiff) + tasklet_hi_schedule(sqcp->tletp); + else + tasklet_schedule(sqcp->tletp); } + if (tsf && (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts)) + sdev_printk(KERN_INFO, sdp, + "%s: num_in_q=%d +1, %s%s\n", __func__, + num_in_q, (inject ? "<inject> " : ""), + "status: TASK SET FULL"); + return 0; } + /* Note: The following macros create attribute files in the /sys/module/scsi_debug/parameters directory. Unfortunately this driver is unaware of a change and cannot trigger auxiliary actions @@ -2773,6 +3142,7 @@ module_param_named(dsense, scsi_debug_dsense, int, S_IRUGO | S_IWUSR); module_param_named(every_nth, scsi_debug_every_nth, int, S_IRUGO | S_IWUSR); module_param_named(fake_rw, scsi_debug_fake_rw, int, S_IRUGO | S_IWUSR); module_param_named(guard, scsi_debug_guard, uint, S_IRUGO); +module_param_named(host_lock, scsi_debug_host_lock, bool, S_IRUGO | S_IWUSR); module_param_named(lbpu, scsi_debug_lbpu, int, S_IRUGO); module_param_named(lbpws, scsi_debug_lbpws, int, S_IRUGO); module_param_named(lbpws10, scsi_debug_lbpws10, int, S_IRUGO); @@ -2780,6 +3150,7 @@ module_param_named(lbprz, scsi_debug_lbprz, int, S_IRUGO); module_param_named(lowest_aligned, scsi_debug_lowest_aligned, int, S_IRUGO); module_param_named(max_luns, scsi_debug_max_luns, int, S_IRUGO | S_IWUSR); module_param_named(max_queue, scsi_debug_max_queue, int, S_IRUGO | S_IWUSR); +module_param_named(ndelay, scsi_debug_ndelay, int, S_IRUGO | S_IWUSR); module_param_named(no_lun_0, scsi_debug_no_lun_0, int, S_IRUGO | S_IWUSR); module_param_named(no_uld, scsi_debug_no_uld, int, S_IRUGO); module_param_named(num_parts, scsi_debug_num_parts, int, S_IRUGO); @@ -2809,7 +3180,7 @@ MODULE_VERSION(SCSI_DEBUG_VERSION); MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)"); MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)"); MODULE_PARM_DESC(clustering, "when set enables larger transfers (def=0)"); -MODULE_PARM_DESC(delay, "# of jiffies to delay response(def=1)"); +MODULE_PARM_DESC(delay, "response delay (def=1 jiffy); 0:imm, -1,-2:tiny"); MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs(def=8)"); MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)"); MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)"); @@ -2817,13 +3188,15 @@ MODULE_PARM_DESC(dsense, "use descriptor sense format(def=0 -> fixed)"); MODULE_PARM_DESC(every_nth, "timeout every nth command(def=0)"); MODULE_PARM_DESC(fake_rw, "fake reads/writes instead of copying (def=0)"); MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)"); +MODULE_PARM_DESC(host_lock, "use host_lock around all commands (def=0)"); MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)"); MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)"); MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)"); MODULE_PARM_DESC(lbprz, "unmapped blocks return 0 on read (def=1)"); MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)"); MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)"); -MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to 255(def))"); +MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to max(def))"); +MODULE_PARM_DESC(ndelay, "response delay in nanoseconds (def=0 -> ignore)"); MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)"); MODULE_PARM_DESC(no_uld, "stop ULD (e.g. sd driver) attaching (def=0))"); MODULE_PARM_DESC(num_parts, "number of partitions(def=0)"); @@ -2854,9 +3227,7 @@ static const char * scsi_debug_info(struct Scsi_Host * shp) return sdebug_info; } -/* scsi_debug_proc_info - * Used if the driver currently has no own support for /proc/scsi - */ +/* 'echo <val> > /proc/scsi/scsi_debug/<host_id>' writes to opts */ static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, int length) { char arr[16]; @@ -2871,27 +3242,49 @@ static int scsi_debug_write_info(struct Scsi_Host *host, char *buffer, int lengt return -EINVAL; scsi_debug_opts = opts; if (scsi_debug_every_nth != 0) - scsi_debug_cmnd_count = 0; + atomic_set(&sdebug_cmnd_count, 0); return length; } +/* Output seen with 'cat /proc/scsi/scsi_debug/<host_id>'. It will be the + * same for each scsi_debug host (if more than one). Some of the counters + * output are not atomics so might be inaccurate in a busy system. */ static int scsi_debug_show_info(struct seq_file *m, struct Scsi_Host *host) { - seq_printf(m, "scsi_debug adapter driver, version " - "%s [%s]\n" - "num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, " - "every_nth=%d(curr:%d)\n" - "delay=%d, max_luns=%d, scsi_level=%d\n" - "sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n" - "number of aborts=%d, device_reset=%d, bus_resets=%d, " - "host_resets=%d\ndix_reads=%d dix_writes=%d dif_errors=%d\n", - SCSI_DEBUG_VERSION, scsi_debug_version_date, scsi_debug_num_tgts, - scsi_debug_dev_size_mb, scsi_debug_opts, scsi_debug_every_nth, - scsi_debug_cmnd_count, scsi_debug_delay, - scsi_debug_max_luns, scsi_debug_scsi_level, - scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads, - sdebug_sectors_per, num_aborts, num_dev_resets, num_bus_resets, - num_host_resets, dix_reads, dix_writes, dif_errors); + int f, l; + char b[32]; + + if (scsi_debug_every_nth > 0) + snprintf(b, sizeof(b), " (curr:%d)", + ((SCSI_DEBUG_OPT_RARE_TSF & scsi_debug_opts) ? + atomic_read(&sdebug_a_tsf) : + atomic_read(&sdebug_cmnd_count))); + else + b[0] = '\0'; + + seq_printf(m, "scsi_debug adapter driver, version %s [%s]\n" + "num_tgts=%d, shared (ram) size=%d MB, opts=0x%x, " + "every_nth=%d%s\n" + "delay=%d, ndelay=%d, max_luns=%d, q_completions=%d\n" + "sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n" + "command aborts=%d; RESETs: device=%d, target=%d, bus=%d, " + "host=%d\ndix_reads=%d dix_writes=%d dif_errors=%d " + "usec_in_jiffy=%lu\n", + SCSI_DEBUG_VERSION, scsi_debug_version_date, + scsi_debug_num_tgts, scsi_debug_dev_size_mb, scsi_debug_opts, + scsi_debug_every_nth, b, scsi_debug_delay, scsi_debug_ndelay, + scsi_debug_max_luns, atomic_read(&sdebug_completions), + scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads, + sdebug_sectors_per, num_aborts, num_dev_resets, + num_target_resets, num_bus_resets, num_host_resets, + dix_reads, dix_writes, dif_errors, TICK_NSEC / 1000); + + f = find_first_bit(queued_in_use_bm, scsi_debug_max_queue); + if (f != scsi_debug_max_queue) { + l = find_last_bit(queued_in_use_bm, scsi_debug_max_queue); + seq_printf(m, " %s BUSY: first,last bits set: %d,%d\n", + "queued_in_use_bm", f, l); + } return 0; } @@ -2899,23 +3292,69 @@ static ssize_t delay_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_delay); } - +/* Returns -EBUSY if delay is being changed and commands are queued */ static ssize_t delay_store(struct device_driver *ddp, const char *buf, size_t count) { - int delay; - char work[20]; - - if (1 == sscanf(buf, "%10s", work)) { - if ((1 == sscanf(work, "%d", &delay)) && (delay >= 0)) { - scsi_debug_delay = delay; - return count; + int delay, res; + + if ((count > 0) && (1 == sscanf(buf, "%d", &delay))) { + res = count; + if (scsi_debug_delay != delay) { + unsigned long iflags; + int k; + + spin_lock_irqsave(&queued_arr_lock, iflags); + k = find_first_bit(queued_in_use_bm, + scsi_debug_max_queue); + if (k != scsi_debug_max_queue) + res = -EBUSY; /* have queued commands */ + else { + scsi_debug_delay = delay; + scsi_debug_ndelay = 0; + } + spin_unlock_irqrestore(&queued_arr_lock, iflags); } + return res; } return -EINVAL; } static DRIVER_ATTR_RW(delay); +static ssize_t ndelay_show(struct device_driver *ddp, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ndelay); +} +/* Returns -EBUSY if ndelay is being changed and commands are queued */ +/* If > 0 and accepted then scsi_debug_delay is set to DELAY_OVERRIDDEN */ +static ssize_t ndelay_store(struct device_driver *ddp, const char *buf, + size_t count) +{ + unsigned long iflags; + int ndelay, res, k; + + if ((count > 0) && (1 == sscanf(buf, "%d", &ndelay)) && + (ndelay >= 0) && (ndelay < 1000000000)) { + res = count; + if (scsi_debug_ndelay != ndelay) { + spin_lock_irqsave(&queued_arr_lock, iflags); + k = find_first_bit(queued_in_use_bm, + scsi_debug_max_queue); + if (k != scsi_debug_max_queue) + res = -EBUSY; /* have queued commands */ + else { + scsi_debug_ndelay = ndelay; + scsi_debug_delay = ndelay ? DELAY_OVERRIDDEN + : DEF_DELAY; + } + spin_unlock_irqrestore(&queued_arr_lock, iflags); + } + return res; + } + return -EINVAL; +} +static DRIVER_ATTR_RW(ndelay); + static ssize_t opts_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "0x%x\n", scsi_debug_opts); @@ -2939,7 +3378,8 @@ static ssize_t opts_store(struct device_driver *ddp, const char *buf, return -EINVAL; opts_done: scsi_debug_opts = opts; - scsi_debug_cmnd_count = 0; + atomic_set(&sdebug_cmnd_count, 0); + atomic_set(&sdebug_a_tsf, 0); return count; } static DRIVER_ATTR_RW(opts); @@ -2988,7 +3428,24 @@ static ssize_t fake_rw_store(struct device_driver *ddp, const char *buf, int n; if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { - scsi_debug_fake_rw = n; + n = (n > 0); + scsi_debug_fake_rw = (scsi_debug_fake_rw > 0); + if (scsi_debug_fake_rw != n) { + if ((0 == n) && (NULL == fake_storep)) { + unsigned long sz = + (unsigned long)scsi_debug_dev_size_mb * + 1048576; + + fake_storep = vmalloc(sz); + if (NULL == fake_storep) { + pr_err("%s: out of memory, 9\n", + __func__); + return -ENOMEM; + } + memset(fake_storep, 0, sz); + } + scsi_debug_fake_rw = n; + } return count; } return -EINVAL; @@ -3053,7 +3510,7 @@ static ssize_t every_nth_store(struct device_driver *ddp, const char *buf, if ((count > 0) && (1 == sscanf(buf, "%d", &nth))) { scsi_debug_every_nth = nth; - scsi_debug_cmnd_count = 0; + atomic_set(&sdebug_cmnd_count, 0); return count; } return -EINVAL; @@ -3082,14 +3539,26 @@ static ssize_t max_queue_show(struct device_driver *ddp, char *buf) { return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_max_queue); } +/* N.B. max_queue can be changed while there are queued commands. In flight + * commands beyond the new max_queue will be completed. */ static ssize_t max_queue_store(struct device_driver *ddp, const char *buf, size_t count) { - int n; + unsigned long iflags; + int n, k; if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n > 0) && (n <= SCSI_DEBUG_CANQUEUE)) { + spin_lock_irqsave(&queued_arr_lock, iflags); + k = find_last_bit(queued_in_use_bm, SCSI_DEBUG_CANQUEUE); scsi_debug_max_queue = n; + if (SCSI_DEBUG_CANQUEUE == k) + atomic_set(&retired_max_queue, 0); + else if (k >= n) + atomic_set(&retired_max_queue, k + 1); + else + atomic_set(&retired_max_queue, 0); + spin_unlock_irqrestore(&queued_arr_lock, iflags); return count; } return -EINVAL; @@ -3234,6 +3703,40 @@ static ssize_t removable_store(struct device_driver *ddp, const char *buf, } static DRIVER_ATTR_RW(removable); +static ssize_t host_lock_show(struct device_driver *ddp, char *buf) +{ + return scnprintf(buf, PAGE_SIZE, "%d\n", !!scsi_debug_host_lock); +} +/* Returns -EBUSY if host_lock is being changed and commands are queued */ +static ssize_t host_lock_store(struct device_driver *ddp, const char *buf, + size_t count) +{ + int n, res; + + if ((count > 0) && (1 == sscanf(buf, "%d", &n)) && (n >= 0)) { + bool new_host_lock = (n > 0); + + res = count; + if (new_host_lock != scsi_debug_host_lock) { + unsigned long iflags; + int k; + + spin_lock_irqsave(&queued_arr_lock, iflags); + k = find_first_bit(queued_in_use_bm, + scsi_debug_max_queue); + if (k != scsi_debug_max_queue) + res = -EBUSY; /* have queued commands */ + else + scsi_debug_host_lock = new_host_lock; + spin_unlock_irqrestore(&queued_arr_lock, iflags); + } + return res; + } + return -EINVAL; +} +static DRIVER_ATTR_RW(host_lock); + + /* Note: The following array creates attribute files in the /sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these files (over those found in the /sys/module/scsi_debug/parameters @@ -3266,6 +3769,8 @@ static struct attribute *sdebug_drv_attrs[] = { &driver_attr_ato.attr, &driver_attr_map.attr, &driver_attr_removable.attr, + &driver_attr_host_lock.attr, + &driver_attr_ndelay.attr, NULL, }; ATTRIBUTE_GROUPS(sdebug_drv); @@ -3279,6 +3784,17 @@ static int __init scsi_debug_init(void) int k; int ret; + atomic_set(&sdebug_cmnd_count, 0); + atomic_set(&sdebug_completions, 0); + atomic_set(&retired_max_queue, 0); + + if (scsi_debug_ndelay >= 1000000000) { + pr_warn("%s: ndelay must be less than 1 second, ignored\n", + __func__); + scsi_debug_ndelay = 0; + } else if (scsi_debug_ndelay > 0) + scsi_debug_delay = DELAY_OVERRIDDEN; + switch (scsi_debug_sector_size) { case 512: case 1024: @@ -3286,7 +3802,7 @@ static int __init scsi_debug_init(void) case 4096: break; default: - printk(KERN_ERR "scsi_debug_init: invalid sector_size %d\n", + pr_err("%s: invalid sector_size %d\n", __func__, scsi_debug_sector_size); return -EINVAL; } @@ -3300,28 +3816,28 @@ static int __init scsi_debug_init(void) break; default: - printk(KERN_ERR "scsi_debug_init: dif must be 0, 1, 2 or 3\n"); + pr_err("%s: dif must be 0, 1, 2 or 3\n", __func__); return -EINVAL; } if (scsi_debug_guard > 1) { - printk(KERN_ERR "scsi_debug_init: guard must be 0 or 1\n"); + pr_err("%s: guard must be 0 or 1\n", __func__); return -EINVAL; } if (scsi_debug_ato > 1) { - printk(KERN_ERR "scsi_debug_init: ato must be 0 or 1\n"); + pr_err("%s: ato must be 0 or 1\n", __func__); return -EINVAL; } if (scsi_debug_physblk_exp > 15) { - printk(KERN_ERR "scsi_debug_init: invalid physblk_exp %u\n", + pr_err("%s: invalid physblk_exp %u\n", __func__, scsi_debug_physblk_exp); return -EINVAL; } if (scsi_debug_lowest_aligned > 0x3fff) { - printk(KERN_ERR "scsi_debug_init: lowest_aligned too big: %u\n", + pr_err("%s: lowest_aligned too big: %u\n", __func__, scsi_debug_lowest_aligned); return -EINVAL; } @@ -3349,14 +3865,16 @@ static int __init scsi_debug_init(void) (sdebug_sectors_per * sdebug_heads); } - fake_storep = vmalloc(sz); - if (NULL == fake_storep) { - printk(KERN_ERR "scsi_debug_init: out of memory, 1\n"); - return -ENOMEM; + if (0 == scsi_debug_fake_rw) { + fake_storep = vmalloc(sz); + if (NULL == fake_storep) { + pr_err("%s: out of memory, 1\n", __func__); + return -ENOMEM; + } + memset(fake_storep, 0, sz); + if (scsi_debug_num_parts > 0) + sdebug_build_parts(fake_storep, sz); } - memset(fake_storep, 0, sz); - if (scsi_debug_num_parts > 0) - sdebug_build_parts(fake_storep, sz); if (scsi_debug_dix) { int dif_size; @@ -3364,11 +3882,11 @@ static int __init scsi_debug_init(void) dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple); dif_storep = vmalloc(dif_size); - printk(KERN_ERR "scsi_debug_init: dif_storep %u bytes @ %p\n", - dif_size, dif_storep); + pr_err("%s: dif_storep %u bytes @ %p\n", __func__, dif_size, + dif_storep); if (dif_storep == NULL) { - printk(KERN_ERR "scsi_debug_init: out of mem. (DIX)\n"); + pr_err("%s: out of mem. (DIX)\n", __func__); ret = -ENOMEM; goto free_vm; } @@ -3390,8 +3908,7 @@ static int __init scsi_debug_init(void) if (scsi_debug_unmap_alignment && scsi_debug_unmap_granularity <= scsi_debug_unmap_alignment) { - printk(KERN_ERR - "%s: ERR: unmap_granularity <= unmap_alignment\n", + pr_err("%s: ERR: unmap_granularity <= unmap_alignment\n", __func__); return -EINVAL; } @@ -3399,11 +3916,10 @@ static int __init scsi_debug_init(void) map_size = lba_to_map_index(sdebug_store_sectors - 1) + 1; map_storep = vmalloc(BITS_TO_LONGS(map_size) * sizeof(long)); - printk(KERN_INFO "scsi_debug_init: %lu provisioning blocks\n", - map_size); + pr_info("%s: %lu provisioning blocks\n", __func__, map_size); if (map_storep == NULL) { - printk(KERN_ERR "scsi_debug_init: out of mem. (MAP)\n"); + pr_err("%s: out of mem. (MAP)\n", __func__); ret = -ENOMEM; goto free_vm; } @@ -3417,39 +3933,35 @@ static int __init scsi_debug_init(void) pseudo_primary = root_device_register("pseudo_0"); if (IS_ERR(pseudo_primary)) { - printk(KERN_WARNING "scsi_debug: root_device_register() error\n"); + pr_warn("%s: root_device_register() error\n", __func__); ret = PTR_ERR(pseudo_primary); goto free_vm; } ret = bus_register(&pseudo_lld_bus); if (ret < 0) { - printk(KERN_WARNING "scsi_debug: bus_register error: %d\n", - ret); + pr_warn("%s: bus_register error: %d\n", __func__, ret); goto dev_unreg; } ret = driver_register(&sdebug_driverfs_driver); if (ret < 0) { - printk(KERN_WARNING "scsi_debug: driver_register error: %d\n", - ret); + pr_warn("%s: driver_register error: %d\n", __func__, ret); goto bus_unreg; } - init_all_queued(); - host_to_add = scsi_debug_add_host; scsi_debug_add_host = 0; for (k = 0; k < host_to_add; k++) { if (sdebug_add_adapter()) { - printk(KERN_ERR "scsi_debug_init: " - "sdebug_add_adapter failed k=%d\n", k); + pr_err("%s: sdebug_add_adapter failed k=%d\n", + __func__, k); break; } } if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) { - printk(KERN_INFO "scsi_debug_init: built %d host(s)\n", - scsi_debug_add_host); + pr_info("%s: built %d host(s)\n", __func__, + scsi_debug_add_host); } return 0; @@ -3472,6 +3984,7 @@ static void __exit scsi_debug_exit(void) int k = scsi_debug_add_host; stop_all_queued(); + free_all_queued(); for (; k; k--) sdebug_remove_adapter(); driver_unregister(&sdebug_driverfs_driver); @@ -3569,8 +4082,8 @@ static void sdebug_remove_adapter(void) --scsi_debug_add_host; } -static -int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done) +static int +scsi_debug_queuecommand(struct scsi_cmnd *SCpnt) { unsigned char *cmd = (unsigned char *) SCpnt->cmnd; int len, k; @@ -3589,32 +4102,34 @@ int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done) int unmap = 0; scsi_set_resid(SCpnt, 0); - if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmd) { - printk(KERN_INFO "scsi_debug: cmd "); - for (k = 0, len = SCpnt->cmd_len; k < len; ++k) - printk("%02x ", (int)cmd[k]); - printk("\n"); - } - - if (target == SCpnt->device->host->hostt->this_id) { - printk(KERN_INFO "scsi_debug: initiator's id used as " - "target!\n"); - return schedule_resp(SCpnt, NULL, done, - DID_NO_CONNECT << 16, 0); + if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && + !(SCSI_DEBUG_OPT_NO_CDB_NOISE & scsi_debug_opts) && cmd) { + char b[120]; + int n; + + len = SCpnt->cmd_len; + if (len > 32) + strcpy(b, "too long, over 32 bytes"); + else { + for (k = 0, n = 0; k < len; ++k) + n += scnprintf(b + n, sizeof(b) - n, "%02x ", + (unsigned int)cmd[k]); + } + sdev_printk(KERN_INFO, SCpnt->device, "%s: cmd %s\n", my_name, + b); } if ((SCpnt->device->lun >= scsi_debug_max_luns) && (SCpnt->device->lun != SAM2_WLUN_REPORT_LUNS)) - return schedule_resp(SCpnt, NULL, done, - DID_NO_CONNECT << 16, 0); + return schedule_resp(SCpnt, NULL, DID_NO_CONNECT << 16, 0); devip = devInfoReg(SCpnt->device); if (NULL == devip) - return schedule_resp(SCpnt, NULL, done, - DID_NO_CONNECT << 16, 0); + return schedule_resp(SCpnt, NULL, DID_NO_CONNECT << 16, 0); if ((scsi_debug_every_nth != 0) && - (++scsi_debug_cmnd_count >= abs(scsi_debug_every_nth))) { - scsi_debug_cmnd_count = 0; + (atomic_inc_return(&sdebug_cmnd_count) >= + abs(scsi_debug_every_nth))) { + atomic_set(&sdebug_cmnd_count, 0); if (scsi_debug_every_nth < -1) scsi_debug_every_nth = -1; if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts) @@ -3645,11 +4160,10 @@ int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done) if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) printk(KERN_INFO "scsi_debug: Opcode: 0x%x " "not supported for wlun\n", *cmd); - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_OPCODE, 0); errsts = check_condition_result; - return schedule_resp(SCpnt, devip, done, errsts, - 0); + return schedule_resp(SCpnt, devip, errsts, 0); } } @@ -3667,7 +4181,7 @@ int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done) errsts = resp_start_stop(SCpnt, devip); break; case ALLOW_MEDIUM_REMOVAL: - errsts = check_readiness(SCpnt, 1, devip); + errsts = check_readiness(SCpnt, UAS_ONLY, devip); if (errsts) break; if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) @@ -3675,23 +4189,23 @@ int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done) cmd[4] ? "inhibited" : "enabled"); break; case SEND_DIAGNOSTIC: /* mandatory */ - errsts = check_readiness(SCpnt, 1, devip); + errsts = check_readiness(SCpnt, UAS_ONLY, devip); break; case TEST_UNIT_READY: /* mandatory */ - delay_override = 1; - errsts = check_readiness(SCpnt, 0, devip); + /* delay_override = 1; */ + errsts = check_readiness(SCpnt, UAS_TUR, devip); break; case RESERVE: - errsts = check_readiness(SCpnt, 1, devip); + errsts = check_readiness(SCpnt, UAS_ONLY, devip); break; case RESERVE_10: - errsts = check_readiness(SCpnt, 1, devip); + errsts = check_readiness(SCpnt, UAS_ONLY, devip); break; case RELEASE: - errsts = check_readiness(SCpnt, 1, devip); + errsts = check_readiness(SCpnt, UAS_ONLY, devip); break; case RELEASE_10: - errsts = check_readiness(SCpnt, 1, devip); + errsts = check_readiness(SCpnt, UAS_ONLY, devip); break; case READ_CAPACITY: errsts = resp_readcap(SCpnt, devip); @@ -3702,20 +4216,20 @@ int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done) else if (cmd[1] == SAI_GET_LBA_STATUS) { if (scsi_debug_lbp() == 0) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_COMMAND_OPCODE, 0); errsts = check_condition_result; } else errsts = resp_get_lba_status(SCpnt, devip); } else { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_OPCODE, 0); errsts = check_condition_result; } break; case MAINTENANCE_IN: if (MI_REPORT_TARGET_PGS != cmd[1]) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_OPCODE, 0); errsts = check_condition_result; break; @@ -3728,7 +4242,7 @@ int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done) /* READ{10,12,16} and DIF Type 2 are natural enemies */ if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && cmd[1] & 0xe0) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_COMMAND_OPCODE, 0); errsts = check_condition_result; break; @@ -3742,7 +4256,7 @@ int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done) /* fall through */ case READ_6: read: - errsts = check_readiness(SCpnt, 0, devip); + errsts = check_readiness(SCpnt, UAS_TUR, devip); if (errsts) break; if (scsi_debug_fake_rw) @@ -3752,20 +4266,21 @@ read: if (inj_short) num /= 2; - errsts = resp_read(SCpnt, lba, num, devip, ei_lba); + errsts = resp_read(SCpnt, lba, num, ei_lba); if (inj_recovered && (0 == errsts)) { - mk_sense_buffer(devip, RECOVERED_ERROR, + mk_sense_buffer(SCpnt, RECOVERED_ERROR, THRESHOLD_EXCEEDED, 0); errsts = check_condition_result; } else if (inj_transport && (0 == errsts)) { - mk_sense_buffer(devip, ABORTED_COMMAND, + mk_sense_buffer(SCpnt, ABORTED_COMMAND, TRANSPORT_PROBLEM, ACK_NAK_TO); errsts = check_condition_result; } else if (inj_dif && (0 == errsts)) { - mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, 1); + /* Logical block guard check failed */ + mk_sense_buffer(SCpnt, ABORTED_COMMAND, 0x10, 1); errsts = illegal_condition_result; } else if (inj_dix && (0 == errsts)) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, 1); + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 0x10, 1); errsts = illegal_condition_result; } break; @@ -3774,7 +4289,7 @@ read: errsts = resp_report_luns(SCpnt, devip); break; case VERIFY: /* 10 byte SBC-2 command */ - errsts = check_readiness(SCpnt, 0, devip); + errsts = check_readiness(SCpnt, UAS_TUR, devip); break; case WRITE_16: case WRITE_12: @@ -3782,7 +4297,7 @@ read: /* WRITE{10,12,16} and DIF Type 2 are natural enemies */ if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION && cmd[1] & 0xe0) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_COMMAND_OPCODE, 0); errsts = check_condition_result; break; @@ -3796,22 +4311,22 @@ read: /* fall through */ case WRITE_6: write: - errsts = check_readiness(SCpnt, 0, devip); + errsts = check_readiness(SCpnt, UAS_TUR, devip); if (errsts) break; if (scsi_debug_fake_rw) break; get_data_transfer_info(cmd, &lba, &num, &ei_lba); - errsts = resp_write(SCpnt, lba, num, devip, ei_lba); + errsts = resp_write(SCpnt, lba, num, ei_lba); if (inj_recovered && (0 == errsts)) { - mk_sense_buffer(devip, RECOVERED_ERROR, + mk_sense_buffer(SCpnt, RECOVERED_ERROR, THRESHOLD_EXCEEDED, 0); errsts = check_condition_result; } else if (inj_dif && (0 == errsts)) { - mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, 1); + mk_sense_buffer(SCpnt, ABORTED_COMMAND, 0x10, 1); errsts = illegal_condition_result; } else if (inj_dix && (0 == errsts)) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, 1); + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, 0x10, 1); errsts = illegal_condition_result; } break; @@ -3820,7 +4335,7 @@ write: if (cmd[1] & 0x8) { if ((*cmd == WRITE_SAME_16 && scsi_debug_lbpws == 0) || (*cmd == WRITE_SAME && scsi_debug_lbpws10 == 0)) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); errsts = check_condition_result; } else @@ -3828,19 +4343,23 @@ write: } if (errsts) break; - errsts = check_readiness(SCpnt, 0, devip); + errsts = check_readiness(SCpnt, UAS_TUR, devip); if (errsts) break; + if (scsi_debug_fake_rw) + break; get_data_transfer_info(cmd, &lba, &num, &ei_lba); - errsts = resp_write_same(SCpnt, lba, num, devip, ei_lba, unmap); + errsts = resp_write_same(SCpnt, lba, num, ei_lba, unmap); break; case UNMAP: - errsts = check_readiness(SCpnt, 0, devip); + errsts = check_readiness(SCpnt, UAS_TUR, devip); if (errsts) break; + if (scsi_debug_fake_rw) + break; if (scsi_debug_unmap_max_desc == 0 || scsi_debug_lbpu == 0) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_COMMAND_OPCODE, 0); errsts = check_condition_result; } else @@ -3861,29 +4380,29 @@ write: break; case SYNCHRONIZE_CACHE: delay_override = 1; - errsts = check_readiness(SCpnt, 0, devip); + errsts = check_readiness(SCpnt, UAS_TUR, devip); break; case WRITE_BUFFER: - errsts = check_readiness(SCpnt, 1, devip); + errsts = check_readiness(SCpnt, UAS_ONLY, devip); break; case XDWRITEREAD_10: if (!scsi_bidi_cmnd(SCpnt)) { - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); errsts = check_condition_result; break; } - errsts = check_readiness(SCpnt, 0, devip); + errsts = check_readiness(SCpnt, UAS_TUR, devip); if (errsts) break; if (scsi_debug_fake_rw) break; get_data_transfer_info(cmd, &lba, &num, &ei_lba); - errsts = resp_read(SCpnt, lba, num, devip, ei_lba); + errsts = resp_read(SCpnt, lba, num, ei_lba); if (errsts) break; - errsts = resp_write(SCpnt, lba, num, devip, ei_lba); + errsts = resp_write(SCpnt, lba, num, ei_lba); if (errsts) break; errsts = resp_xdwriteread(SCpnt, lba, num, devip); @@ -3906,27 +4425,138 @@ write: } } - mk_sense_buffer(devip, ILLEGAL_REQUEST, + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB, 0); errsts = check_condition_result; break; - + case 0x85: + if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) + sdev_printk(KERN_INFO, SCpnt->device, + "%s: ATA PASS-THROUGH(16) not supported\n", my_name); + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, + INVALID_OPCODE, 0); + errsts = check_condition_result; + break; default: if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) - printk(KERN_INFO "scsi_debug: Opcode: 0x%x not " - "supported\n", *cmd); - errsts = check_readiness(SCpnt, 1, devip); + sdev_printk(KERN_INFO, SCpnt->device, + "%s: Opcode: 0x%x not supported\n", + my_name, *cmd); + errsts = check_readiness(SCpnt, UAS_ONLY, devip); if (errsts) break; /* Unit attention takes precedence */ - mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_OPCODE, 0); + mk_sense_buffer(SCpnt, ILLEGAL_REQUEST, INVALID_OPCODE, 0); errsts = check_condition_result; break; } - return schedule_resp(SCpnt, devip, done, errsts, + return schedule_resp(SCpnt, devip, errsts, (delay_override ? 0 : scsi_debug_delay)); } -static DEF_SCSI_QCMD(scsi_debug_queuecommand) +static int +sdebug_queuecommand_lock_or_not(struct Scsi_Host *shost, struct scsi_cmnd *cmd) +{ + if (scsi_debug_host_lock) { + unsigned long iflags; + int rc; + + spin_lock_irqsave(shost->host_lock, iflags); + rc = scsi_debug_queuecommand(cmd); + spin_unlock_irqrestore(shost->host_lock, iflags); + return rc; + } else + return scsi_debug_queuecommand(cmd); +} + +static int +sdebug_change_qdepth(struct scsi_device *sdev, int qdepth, int reason) +{ + int num_in_q = 0; + int bad = 0; + unsigned long iflags; + struct sdebug_dev_info *devip; + + spin_lock_irqsave(&queued_arr_lock, iflags); + devip = (struct sdebug_dev_info *)sdev->hostdata; + if (NULL == devip) { + spin_unlock_irqrestore(&queued_arr_lock, iflags); + return -ENODEV; + } + num_in_q = atomic_read(&devip->num_in_q); + spin_unlock_irqrestore(&queued_arr_lock, iflags); + if (reason == SCSI_QDEPTH_DEFAULT || reason == SCSI_QDEPTH_RAMP_UP) { + if (qdepth < 1) + qdepth = 1; + /* allow to exceed max host queued_arr elements for testing */ + if (qdepth > SCSI_DEBUG_CANQUEUE + 10) + qdepth = SCSI_DEBUG_CANQUEUE + 10; + scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth); + } else if (reason == SCSI_QDEPTH_QFULL) + scsi_track_queue_full(sdev, qdepth); + else + bad = 1; + if (bad) + sdev_printk(KERN_WARNING, sdev, + "%s: unknown reason=0x%x\n", __func__, reason); + if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) { + if (SCSI_QDEPTH_QFULL == reason) + sdev_printk(KERN_INFO, sdev, + "%s: -> %d, num_in_q=%d, reason: queue full\n", + __func__, qdepth, num_in_q); + else { + const char *cp; + + switch (reason) { + case SCSI_QDEPTH_DEFAULT: + cp = "default (sysfs ?)"; + break; + case SCSI_QDEPTH_RAMP_UP: + cp = "ramp up"; + break; + default: + cp = "unknown"; + break; + } + sdev_printk(KERN_INFO, sdev, + "%s: qdepth=%d, num_in_q=%d, reason: %s\n", + __func__, qdepth, num_in_q, cp); + } + } + return sdev->queue_depth; +} + +static int +sdebug_change_qtype(struct scsi_device *sdev, int qtype) +{ + if (sdev->tagged_supported) { + scsi_set_tag_type(sdev, qtype); + if (qtype) + scsi_activate_tcq(sdev, sdev->queue_depth); + else + scsi_deactivate_tcq(sdev, sdev->queue_depth); + } else + qtype = 0; + if (SCSI_DEBUG_OPT_Q_NOISE & scsi_debug_opts) { + const char *cp; + + switch (qtype) { + case 0: + cp = "untagged"; + break; + case MSG_SIMPLE_TAG: + cp = "simple tags"; + break; + case MSG_ORDERED_TAG: + cp = "ordered tags"; + break; + default: + cp = "unknown"; + break; + } + sdev_printk(KERN_INFO, sdev, "%s: to %s\n", __func__, cp); + } + return qtype; +} static struct scsi_host_template sdebug_driver_template = { .show_info = scsi_debug_show_info, @@ -3938,17 +4568,19 @@ static struct scsi_host_template sdebug_driver_template = { .slave_configure = scsi_debug_slave_configure, .slave_destroy = scsi_debug_slave_destroy, .ioctl = scsi_debug_ioctl, - .queuecommand = scsi_debug_queuecommand, + .queuecommand = sdebug_queuecommand_lock_or_not, + .change_queue_depth = sdebug_change_qdepth, + .change_queue_type = sdebug_change_qtype, .eh_abort_handler = scsi_debug_abort, - .eh_bus_reset_handler = scsi_debug_bus_reset, .eh_device_reset_handler = scsi_debug_device_reset, + .eh_target_reset_handler = scsi_debug_target_reset, + .eh_bus_reset_handler = scsi_debug_bus_reset, .eh_host_reset_handler = scsi_debug_host_reset, - .bios_param = scsi_debug_biosparam, .can_queue = SCSI_DEBUG_CANQUEUE, .this_id = 7, - .sg_tablesize = 256, - .cmd_per_lun = 16, - .max_sectors = 0xffff, + .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS, + .cmd_per_lun = DEF_CMD_PER_LUN, + .max_sectors = -1U, .use_clustering = DISABLE_CLUSTERING, .module = THIS_MODULE, }; @@ -4032,8 +4664,7 @@ static int sdebug_driver_probe(struct device * dev) } else scsi_scan_host(hpnt); - - return error; + return error; } static int sdebug_driver_remove(struct device * dev) diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index f969aca0b54e..49014a143c6a 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -222,6 +222,7 @@ static struct { {"PIONEER", "CD-ROM DRM-602X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, {"PIONEER", "CD-ROM DRM-604X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, {"PIONEER", "CD-ROM DRM-624X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, + {"Promise", "VTrak E610f", NULL, BLIST_SPARSELUN | BLIST_NO_RSOC}, {"Promise", "", NULL, BLIST_SPARSELUN}, {"QUANTUM", "XP34301", "1071", BLIST_NOTQ}, {"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN}, diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 7e957918f33f..5db8454474ee 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -59,11 +59,11 @@ static int scsi_try_to_abort_cmd(struct scsi_host_template *, /* called with shost->host_lock held */ void scsi_eh_wakeup(struct Scsi_Host *shost) { - if (shost->host_busy == shost->host_failed) { + if (atomic_read(&shost->host_busy) == shost->host_failed) { trace_scsi_eh_wakeup(shost); wake_up_process(shost->ehandler); - SCSI_LOG_ERROR_RECOVERY(5, - printk("Waking error handler thread\n")); + SCSI_LOG_ERROR_RECOVERY(5, shost_printk(KERN_INFO, shost, + "Waking error handler thread\n")); } } @@ -193,7 +193,7 @@ scsi_abort_command(struct scsi_cmnd *scmd) SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, "scmd %p previous abort failed\n", scmd)); - cancel_delayed_work(&scmd->abort_work); + BUG_ON(delayed_work_pending(&scmd->abort_work)); return FAILED; } @@ -319,8 +319,8 @@ int scsi_block_when_processing_errors(struct scsi_device *sdev) online = scsi_device_online(sdev); - SCSI_LOG_ERROR_RECOVERY(5, printk("%s: rtn: %d\n", __func__, - online)); + SCSI_LOG_ERROR_RECOVERY(5, sdev_printk(KERN_INFO, sdev, + "%s: rtn: %d\n", __func__, online)); return online; } @@ -365,8 +365,9 @@ static inline void scsi_eh_prt_fail_stats(struct Scsi_Host *shost, } } - SCSI_LOG_ERROR_RECOVERY(2, printk("Total of %d commands on %d" - " devices require eh work\n", + SCSI_LOG_ERROR_RECOVERY(2, shost_printk(KERN_INFO, shost, + "Total of %d commands on %d" + " devices require eh work\n", total_failures, devices_failed)); } #endif @@ -738,8 +739,8 @@ static void scsi_eh_done(struct scsi_cmnd *scmd) { struct completion *eh_action; - SCSI_LOG_ERROR_RECOVERY(3, - printk("%s scmd: %p result: %x\n", + SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, + "%s scmd: %p result: %x\n", __func__, scmd, scmd->result)); eh_action = scmd->device->host->eh_action; @@ -758,8 +759,8 @@ static int scsi_try_host_reset(struct scsi_cmnd *scmd) struct Scsi_Host *host = scmd->device->host; struct scsi_host_template *hostt = host->hostt; - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Host RST\n", - __func__)); + SCSI_LOG_ERROR_RECOVERY(3, + shost_printk(KERN_INFO, host, "Snd Host RST\n")); if (!hostt->eh_host_reset_handler) return FAILED; @@ -788,8 +789,8 @@ static int scsi_try_bus_reset(struct scsi_cmnd *scmd) struct Scsi_Host *host = scmd->device->host; struct scsi_host_template *hostt = host->hostt; - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Bus RST\n", - __func__)); + SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, + "%s: Snd Bus RST\n", __func__)); if (!hostt->eh_bus_reset_handler) return FAILED; @@ -1036,8 +1037,8 @@ retry: scsi_log_completion(scmd, rtn); - SCSI_LOG_ERROR_RECOVERY(3, - printk("%s: scmd: %p, timeleft: %ld\n", + SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, + "%s: scmd: %p, timeleft: %ld\n", __func__, scmd, timeleft)); /* @@ -1051,9 +1052,8 @@ retry: */ if (timeleft) { rtn = scsi_eh_completed_normally(scmd); - SCSI_LOG_ERROR_RECOVERY(3, - printk("%s: scsi_eh_completed_normally %x\n", - __func__, rtn)); + SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, + "%s: scsi_eh_completed_normally %x\n", __func__, rtn)); switch (rtn) { case SUCCESS: @@ -1177,9 +1177,9 @@ int scsi_eh_get_sense(struct list_head *work_q, if (rtn != SUCCESS) continue; - SCSI_LOG_ERROR_RECOVERY(3, printk("sense requested for %p" - " result %x\n", scmd, - scmd->result)); + SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, + "sense requested for %p result %x\n", + scmd, scmd->result)); SCSI_LOG_ERROR_RECOVERY(3, scsi_print_sense("bh", scmd)); rtn = scsi_decide_disposition(scmd); @@ -1220,8 +1220,8 @@ retry_tur: rtn = scsi_send_eh_cmnd(scmd, tur_command, 6, scmd->device->eh_timeout, 0); - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: scmd %p rtn %x\n", - __func__, scmd, rtn)); + SCSI_LOG_ERROR_RECOVERY(3, scmd_printk(KERN_INFO, scmd, + "%s: scmd %p rtn %x\n", __func__, scmd, rtn)); switch (rtn) { case NEEDS_RETRY: @@ -1323,16 +1323,16 @@ static int scsi_eh_abort_cmds(struct list_head *work_q, __func__)); return list_empty(work_q); } - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting cmd:" - "0x%p\n", current->comm, - scmd)); + SCSI_LOG_ERROR_RECOVERY(3, + shost_printk(KERN_INFO, shost, + "%s: aborting cmd: 0x%p\n", + current->comm, scmd)); rtn = scsi_try_to_abort_cmd(shost->hostt, scmd); if (rtn == FAILED) { - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting" - " cmd failed:" - "0x%p\n", - current->comm, - scmd)); + SCSI_LOG_ERROR_RECOVERY(3, + shost_printk(KERN_INFO, shost, + "%s: aborting cmd failed: 0x%p\n", + current->comm, scmd)); list_splice_init(&check_list, work_q); return list_empty(work_q); } @@ -1406,8 +1406,10 @@ static int scsi_eh_stu(struct Scsi_Host *shost, if (!stu_scmd) continue; - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending START_UNIT to sdev:" - " 0x%p\n", current->comm, sdev)); + SCSI_LOG_ERROR_RECOVERY(3, + shost_printk(KERN_INFO, shost, + "%s: Sending START_UNIT to sdev: 0x%p\n", + current->comm, sdev)); if (!scsi_eh_try_stu(stu_scmd)) { if (!scsi_device_online(sdev) || @@ -1421,8 +1423,9 @@ static int scsi_eh_stu(struct Scsi_Host *shost, } } else { SCSI_LOG_ERROR_RECOVERY(3, - printk("%s: START_UNIT failed to sdev:" - " 0x%p\n", current->comm, sdev)); + shost_printk(KERN_INFO, shost, + "%s: START_UNIT failed to sdev:" + " 0x%p\n", current->comm, sdev)); } } @@ -1468,9 +1471,10 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost, if (!bdr_scmd) continue; - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending BDR sdev:" - " 0x%p\n", current->comm, - sdev)); + SCSI_LOG_ERROR_RECOVERY(3, + shost_printk(KERN_INFO, shost, + "%s: Sending BDR sdev: 0x%p\n", + current->comm, sdev)); rtn = scsi_try_bus_device_reset(bdr_scmd); if (rtn == SUCCESS || rtn == FAST_IO_FAIL) { if (!scsi_device_online(sdev) || @@ -1485,11 +1489,10 @@ static int scsi_eh_bus_device_reset(struct Scsi_Host *shost, } } } else { - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: BDR" - " failed sdev:" - "0x%p\n", - current->comm, - sdev)); + SCSI_LOG_ERROR_RECOVERY(3, + shost_printk(KERN_INFO, shost, + "%s: BDR failed sdev: 0x%p\n", + current->comm, sdev)); } } @@ -1533,15 +1536,17 @@ static int scsi_eh_target_reset(struct Scsi_Host *shost, scmd = list_entry(tmp_list.next, struct scsi_cmnd, eh_entry); id = scmd_id(scmd); - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending target reset " - "to target %d\n", - current->comm, id)); + SCSI_LOG_ERROR_RECOVERY(3, + shost_printk(KERN_INFO, shost, + "%s: Sending target reset to target %d\n", + current->comm, id)); rtn = scsi_try_target_reset(scmd); if (rtn != SUCCESS && rtn != FAST_IO_FAIL) - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Target reset" - " failed target: " - "%d\n", - current->comm, id)); + SCSI_LOG_ERROR_RECOVERY(3, + shost_printk(KERN_INFO, shost, + "%s: Target reset failed" + " target: %d\n", + current->comm, id)); list_for_each_entry_safe(scmd, next, &tmp_list, eh_entry) { if (scmd_id(scmd) != id) continue; @@ -1605,9 +1610,10 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost, if (!chan_scmd) continue; - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending BRST chan:" - " %d\n", current->comm, - channel)); + SCSI_LOG_ERROR_RECOVERY(3, + shost_printk(KERN_INFO, shost, + "%s: Sending BRST chan: %d\n", + current->comm, channel)); rtn = scsi_try_bus_reset(chan_scmd); if (rtn == SUCCESS || rtn == FAST_IO_FAIL) { list_for_each_entry_safe(scmd, next, work_q, eh_entry) { @@ -1621,10 +1627,10 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost, } } } else { - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: BRST" - " failed chan: %d\n", - current->comm, - channel)); + SCSI_LOG_ERROR_RECOVERY(3, + shost_printk(KERN_INFO, shost, + "%s: BRST failed chan: %d\n", + current->comm, channel)); } } return scsi_eh_test_devices(&check_list, work_q, done_q, 0); @@ -1635,7 +1641,8 @@ static int scsi_eh_bus_reset(struct Scsi_Host *shost, * @work_q: list_head for processed commands. * @done_q: list_head for processed commands. */ -static int scsi_eh_host_reset(struct list_head *work_q, +static int scsi_eh_host_reset(struct Scsi_Host *shost, + struct list_head *work_q, struct list_head *done_q) { struct scsi_cmnd *scmd, *next; @@ -1646,8 +1653,10 @@ static int scsi_eh_host_reset(struct list_head *work_q, scmd = list_entry(work_q->next, struct scsi_cmnd, eh_entry); - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Sending HRST\n" - , current->comm)); + SCSI_LOG_ERROR_RECOVERY(3, + shost_printk(KERN_INFO, shost, + "%s: Sending HRST\n", + current->comm)); rtn = scsi_try_host_reset(scmd); if (rtn == SUCCESS) { @@ -1657,9 +1666,10 @@ static int scsi_eh_host_reset(struct list_head *work_q, scsi_eh_finish_cmd(scmd, done_q); } } else { - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: HRST" - " failed\n", - current->comm)); + SCSI_LOG_ERROR_RECOVERY(3, + shost_printk(KERN_INFO, shost, + "%s: HRST failed\n", + current->comm)); } } return scsi_eh_test_devices(&check_list, work_q, done_q, 1); @@ -1751,9 +1761,8 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd) * up to the top level. */ if (!scsi_device_online(scmd->device)) { - SCSI_LOG_ERROR_RECOVERY(5, printk("%s: device offline - report" - " as SUCCESS\n", - __func__)); + SCSI_LOG_ERROR_RECOVERY(5, scmd_printk(KERN_INFO, scmd, + "%s: device offline - report as SUCCESS\n", __func__)); return SUCCESS; } @@ -1999,8 +2008,7 @@ static void scsi_restart_operations(struct Scsi_Host *shost) * ioctls to queued block devices. */ SCSI_LOG_ERROR_RECOVERY(3, - printk("scsi_eh_%d waking up host to restart\n", - shost->host_no)); + shost_printk(KERN_INFO, shost, "waking up host to restart\n")); spin_lock_irqsave(shost->host_lock, flags); if (scsi_host_set_state(shost, SHOST_RUNNING)) @@ -2047,7 +2055,7 @@ void scsi_eh_ready_devs(struct Scsi_Host *shost, if (!scsi_eh_bus_device_reset(shost, work_q, done_q)) if (!scsi_eh_target_reset(shost, work_q, done_q)) if (!scsi_eh_bus_reset(shost, work_q, done_q)) - if (!scsi_eh_host_reset(work_q, done_q)) + if (!scsi_eh_host_reset(shost, work_q, done_q)) scsi_eh_offline_sdevs(work_q, done_q); } @@ -2066,10 +2074,10 @@ void scsi_eh_flush_done_q(struct list_head *done_q) if (scsi_device_online(scmd->device) && !scsi_noretry_cmd(scmd) && (++scmd->retries <= scmd->allowed)) { - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: flush" - " retry cmd: %p\n", - current->comm, - scmd)); + SCSI_LOG_ERROR_RECOVERY(3, + scmd_printk(KERN_INFO, scmd, + "%s: flush retry cmd: %p\n", + current->comm, scmd)); scsi_queue_insert(scmd, SCSI_MLQUEUE_EH_RETRY); } else { /* @@ -2079,9 +2087,10 @@ void scsi_eh_flush_done_q(struct list_head *done_q) */ if (!scmd->result) scmd->result |= (DRIVER_TIMEOUT << 24); - SCSI_LOG_ERROR_RECOVERY(3, printk("%s: flush finish" - " cmd: %p\n", - current->comm, scmd)); + SCSI_LOG_ERROR_RECOVERY(3, + scmd_printk(KERN_INFO, scmd, + "%s: flush finish cmd: %p\n", + current->comm, scmd)); scsi_finish_command(scmd); } } @@ -2155,19 +2164,22 @@ int scsi_error_handler(void *data) while (!kthread_should_stop()) { set_current_state(TASK_INTERRUPTIBLE); if ((shost->host_failed == 0 && shost->host_eh_scheduled == 0) || - shost->host_failed != shost->host_busy) { + shost->host_failed != atomic_read(&shost->host_busy)) { SCSI_LOG_ERROR_RECOVERY(1, - printk("scsi_eh_%d: sleeping\n", - shost->host_no)); + shost_printk(KERN_INFO, shost, + "scsi_eh_%d: sleeping\n", + shost->host_no)); schedule(); continue; } __set_current_state(TASK_RUNNING); SCSI_LOG_ERROR_RECOVERY(1, - printk("scsi_eh_%d: waking up %d/%d/%d\n", - shost->host_no, shost->host_eh_scheduled, - shost->host_failed, shost->host_busy)); + shost_printk(KERN_INFO, shost, + "scsi_eh_%d: waking up %d/%d/%d\n", + shost->host_no, shost->host_eh_scheduled, + shost->host_failed, + atomic_read(&shost->host_busy))); /* * We have a host that is failing for some reason. Figure out @@ -2201,7 +2213,9 @@ int scsi_error_handler(void *data) __set_current_state(TASK_RUNNING); SCSI_LOG_ERROR_RECOVERY(1, - printk("Error handler scsi_eh_%d exiting\n", shost->host_no)); + shost_printk(KERN_INFO, shost, + "Error handler scsi_eh_%d exiting\n", + shost->host_no)); shost->ehandler = NULL; return 0; } @@ -2362,8 +2376,8 @@ scsi_reset_provider(struct scsi_device *dev, int flag) * suspended while we performed the TMF. */ SCSI_LOG_ERROR_RECOVERY(3, - printk("%s: waking up host to restart after TMF\n", - __func__)); + shost_printk(KERN_INFO, shost, + "waking up host to restart after TMF\n")); wake_up(&shost->host_wait); diff --git a/drivers/scsi/scsi_ioctl.c b/drivers/scsi/scsi_ioctl.c index d9564fb04f62..1aaaf43c6803 100644 --- a/drivers/scsi/scsi_ioctl.c +++ b/drivers/scsi/scsi_ioctl.c @@ -91,12 +91,14 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, int result; struct scsi_sense_hdr sshdr; - SCSI_LOG_IOCTL(1, printk("Trying ioctl with scsi command %d\n", *cmd)); + SCSI_LOG_IOCTL(1, sdev_printk(KERN_INFO, sdev, + "Trying ioctl with scsi command %d\n", *cmd)); result = scsi_execute_req(sdev, cmd, DMA_NONE, NULL, 0, &sshdr, timeout, retries, NULL); - SCSI_LOG_IOCTL(2, printk("Ioctl returned 0x%x\n", result)); + SCSI_LOG_IOCTL(2, sdev_printk(KERN_INFO, sdev, + "Ioctl returned 0x%x\n", result)); if ((driver_byte(result) & DRIVER_SENSE) && (scsi_sense_valid(&sshdr))) { @@ -105,9 +107,11 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, if (cmd[0] == ALLOW_MEDIUM_REMOVAL) sdev->lockable = 0; else - printk(KERN_INFO "ioctl_internal_command: " - "ILLEGAL REQUEST asc=0x%x ascq=0x%x\n", - sshdr.asc, sshdr.ascq); + sdev_printk(KERN_INFO, sdev, + "ioctl_internal_command: " + "ILLEGAL REQUEST " + "asc=0x%x ascq=0x%x\n", + sshdr.asc, sshdr.ascq); break; case NOT_READY: /* This happens if there is no disc in drive */ if (sdev->removable) @@ -127,7 +131,8 @@ static int ioctl_internal_command(struct scsi_device *sdev, char *cmd, } } - SCSI_LOG_IOCTL(2, printk("IOCTL Releasing command\n")); + SCSI_LOG_IOCTL(2, sdev_printk(KERN_INFO, sdev, + "IOCTL Releasing command\n")); return result; } diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 3f50dfcb3227..9c44392b748f 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -1,5 +1,6 @@ /* - * scsi_lib.c Copyright (C) 1999 Eric Youngdale + * Copyright (C) 1999 Eric Youngdale + * Copyright (C) 2014 Christoph Hellwig * * SCSI queueing library. * Initial versions: Eric Youngdale (eric@andante.org). @@ -20,6 +21,7 @@ #include <linux/delay.h> #include <linux/hardirq.h> #include <linux/scatterlist.h> +#include <linux/blk-mq.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> @@ -29,6 +31,8 @@ #include <scsi/scsi_eh.h> #include <scsi/scsi_host.h> +#include <trace/events/scsi.h> + #include "scsi_priv.h" #include "scsi_logging.h" @@ -75,28 +79,12 @@ struct kmem_cache *scsi_sdb_cache; */ #define SCSI_QUEUE_DELAY 3 -/** - * __scsi_queue_insert - private queue insertion - * @cmd: The SCSI command being requeued - * @reason: The reason for the requeue - * @unbusy: Whether the queue should be unbusied - * - * This is a private queue insertion. The public interface - * scsi_queue_insert() always assumes the queue should be unbusied - * because it's always called before the completion. This function is - * for a requeue after completion, which should only occur in this - * file. - */ -static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, int unbusy) +static void +scsi_set_blocked(struct scsi_cmnd *cmd, int reason) { struct Scsi_Host *host = cmd->device->host; struct scsi_device *device = cmd->device; struct scsi_target *starget = scsi_target(device); - struct request_queue *q = device->request_queue; - unsigned long flags; - - SCSI_LOG_MLQUEUE(1, - printk("Inserting command %p into mlqueue\n", cmd)); /* * Set the appropriate busy bit for the device/host. @@ -113,16 +101,52 @@ static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, int unbusy) */ switch (reason) { case SCSI_MLQUEUE_HOST_BUSY: - host->host_blocked = host->max_host_blocked; + atomic_set(&host->host_blocked, host->max_host_blocked); break; case SCSI_MLQUEUE_DEVICE_BUSY: case SCSI_MLQUEUE_EH_RETRY: - device->device_blocked = device->max_device_blocked; + atomic_set(&device->device_blocked, + device->max_device_blocked); break; case SCSI_MLQUEUE_TARGET_BUSY: - starget->target_blocked = starget->max_target_blocked; + atomic_set(&starget->target_blocked, + starget->max_target_blocked); break; } +} + +static void scsi_mq_requeue_cmd(struct scsi_cmnd *cmd) +{ + struct scsi_device *sdev = cmd->device; + struct request_queue *q = cmd->request->q; + + blk_mq_requeue_request(cmd->request); + blk_mq_kick_requeue_list(q); + put_device(&sdev->sdev_gendev); +} + +/** + * __scsi_queue_insert - private queue insertion + * @cmd: The SCSI command being requeued + * @reason: The reason for the requeue + * @unbusy: Whether the queue should be unbusied + * + * This is a private queue insertion. The public interface + * scsi_queue_insert() always assumes the queue should be unbusied + * because it's always called before the completion. This function is + * for a requeue after completion, which should only occur in this + * file. + */ +static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, int unbusy) +{ + struct scsi_device *device = cmd->device; + struct request_queue *q = device->request_queue; + unsigned long flags; + + SCSI_LOG_MLQUEUE(1, scmd_printk(KERN_INFO, cmd, + "Inserting command %p into mlqueue\n", cmd)); + + scsi_set_blocked(cmd, reason); /* * Decrement the counters, since these commands are no longer @@ -138,6 +162,10 @@ static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, int unbusy) * before blk_cleanup_queue() finishes. */ cmd->result = 0; + if (q->mq_ops) { + scsi_mq_requeue_cmd(cmd); + return; + } spin_lock_irqsave(q->queue_lock, flags); blk_requeue_request(q, cmd->request); kblockd_schedule_work(&device->requeue_work); @@ -282,16 +310,26 @@ void scsi_device_unbusy(struct scsi_device *sdev) struct scsi_target *starget = scsi_target(sdev); unsigned long flags; - spin_lock_irqsave(shost->host_lock, flags); - shost->host_busy--; - starget->target_busy--; + atomic_dec(&shost->host_busy); + if (starget->can_queue > 0) + atomic_dec(&starget->target_busy); + if (unlikely(scsi_host_in_recovery(shost) && - (shost->host_failed || shost->host_eh_scheduled))) + (shost->host_failed || shost->host_eh_scheduled))) { + spin_lock_irqsave(shost->host_lock, flags); scsi_eh_wakeup(shost); - spin_unlock(shost->host_lock); - spin_lock(sdev->request_queue->queue_lock); - sdev->device_busy--; - spin_unlock_irqrestore(sdev->request_queue->queue_lock, flags); + spin_unlock_irqrestore(shost->host_lock, flags); + } + + atomic_dec(&sdev->device_busy); +} + +static void scsi_kick_queue(struct request_queue *q) +{ + if (q->mq_ops) + blk_mq_start_hw_queues(q); + else + blk_run_queue(q); } /* @@ -318,7 +356,7 @@ static void scsi_single_lun_run(struct scsi_device *current_sdev) * but in most cases, we will be first. Ideally, each LU on the * target would get some limited time or requests on the target. */ - blk_run_queue(current_sdev->request_queue); + scsi_kick_queue(current_sdev->request_queue); spin_lock_irqsave(shost->host_lock, flags); if (starget->starget_sdev_user) @@ -331,7 +369,7 @@ static void scsi_single_lun_run(struct scsi_device *current_sdev) continue; spin_unlock_irqrestore(shost->host_lock, flags); - blk_run_queue(sdev->request_queue); + scsi_kick_queue(sdev->request_queue); spin_lock_irqsave(shost->host_lock, flags); scsi_device_put(sdev); @@ -340,28 +378,36 @@ static void scsi_single_lun_run(struct scsi_device *current_sdev) spin_unlock_irqrestore(shost->host_lock, flags); } -static inline int scsi_device_is_busy(struct scsi_device *sdev) +static inline bool scsi_device_is_busy(struct scsi_device *sdev) { - if (sdev->device_busy >= sdev->queue_depth || sdev->device_blocked) - return 1; - - return 0; + if (atomic_read(&sdev->device_busy) >= sdev->queue_depth) + return true; + if (atomic_read(&sdev->device_blocked) > 0) + return true; + return false; } -static inline int scsi_target_is_busy(struct scsi_target *starget) +static inline bool scsi_target_is_busy(struct scsi_target *starget) { - return ((starget->can_queue > 0 && - starget->target_busy >= starget->can_queue) || - starget->target_blocked); + if (starget->can_queue > 0) { + if (atomic_read(&starget->target_busy) >= starget->can_queue) + return true; + if (atomic_read(&starget->target_blocked) > 0) + return true; + } + return false; } -static inline int scsi_host_is_busy(struct Scsi_Host *shost) +static inline bool scsi_host_is_busy(struct Scsi_Host *shost) { - if ((shost->can_queue > 0 && shost->host_busy >= shost->can_queue) || - shost->host_blocked || shost->host_self_blocked) - return 1; - - return 0; + if (shost->can_queue > 0 && + atomic_read(&shost->host_busy) >= shost->can_queue) + return true; + if (atomic_read(&shost->host_blocked) > 0) + return true; + if (shost->host_self_blocked) + return true; + return false; } static void scsi_starved_list_run(struct Scsi_Host *shost) @@ -413,7 +459,7 @@ static void scsi_starved_list_run(struct Scsi_Host *shost) continue; spin_unlock_irqrestore(shost->host_lock, flags); - blk_run_queue(slq); + scsi_kick_queue(slq); blk_put_queue(slq); spin_lock_irqsave(shost->host_lock, flags); @@ -444,7 +490,10 @@ static void scsi_run_queue(struct request_queue *q) if (!list_empty(&sdev->host->starved_list)) scsi_starved_list_run(sdev->host); - blk_run_queue(q); + if (q->mq_ops) + blk_mq_start_stopped_hw_queues(q, false); + else + blk_run_queue(q); } void scsi_requeue_run_queue(struct work_struct *work) @@ -542,25 +591,70 @@ static struct scatterlist *scsi_sg_alloc(unsigned int nents, gfp_t gfp_mask) return mempool_alloc(sgp->pool, gfp_mask); } +static void scsi_free_sgtable(struct scsi_data_buffer *sdb, bool mq) +{ + if (mq && sdb->table.nents <= SCSI_MAX_SG_SEGMENTS) + return; + __sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, mq, scsi_sg_free); +} + static int scsi_alloc_sgtable(struct scsi_data_buffer *sdb, int nents, - gfp_t gfp_mask) + gfp_t gfp_mask, bool mq) { + struct scatterlist *first_chunk = NULL; int ret; BUG_ON(!nents); + if (mq) { + if (nents <= SCSI_MAX_SG_SEGMENTS) { + sdb->table.nents = nents; + sg_init_table(sdb->table.sgl, sdb->table.nents); + return 0; + } + first_chunk = sdb->table.sgl; + } + ret = __sg_alloc_table(&sdb->table, nents, SCSI_MAX_SG_SEGMENTS, - gfp_mask, scsi_sg_alloc); + first_chunk, gfp_mask, scsi_sg_alloc); if (unlikely(ret)) - __sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, - scsi_sg_free); - + scsi_free_sgtable(sdb, mq); return ret; } -static void scsi_free_sgtable(struct scsi_data_buffer *sdb) +static void scsi_uninit_cmd(struct scsi_cmnd *cmd) +{ + if (cmd->request->cmd_type == REQ_TYPE_FS) { + struct scsi_driver *drv = scsi_cmd_to_driver(cmd); + + if (drv->uninit_command) + drv->uninit_command(cmd); + } +} + +static void scsi_mq_free_sgtables(struct scsi_cmnd *cmd) { - __sg_free_table(&sdb->table, SCSI_MAX_SG_SEGMENTS, scsi_sg_free); + if (cmd->sdb.table.nents) + scsi_free_sgtable(&cmd->sdb, true); + if (cmd->request->next_rq && cmd->request->next_rq->special) + scsi_free_sgtable(cmd->request->next_rq->special, true); + if (scsi_prot_sg_count(cmd)) + scsi_free_sgtable(cmd->prot_sdb, true); +} + +static void scsi_mq_uninit_cmd(struct scsi_cmnd *cmd) +{ + struct scsi_device *sdev = cmd->device; + unsigned long flags; + + BUG_ON(list_empty(&cmd->list)); + + scsi_mq_free_sgtables(cmd); + scsi_uninit_cmd(cmd); + + spin_lock_irqsave(&sdev->list_lock, flags); + list_del_init(&cmd->list); + spin_unlock_irqrestore(&sdev->list_lock, flags); } /* @@ -579,27 +673,79 @@ static void scsi_free_sgtable(struct scsi_data_buffer *sdb) * the __init_io() function. Primarily this would involve * the scatter-gather table. */ -void scsi_release_buffers(struct scsi_cmnd *cmd) +static void scsi_release_buffers(struct scsi_cmnd *cmd) { if (cmd->sdb.table.nents) - scsi_free_sgtable(&cmd->sdb); + scsi_free_sgtable(&cmd->sdb, false); memset(&cmd->sdb, 0, sizeof(cmd->sdb)); if (scsi_prot_sg_count(cmd)) - scsi_free_sgtable(cmd->prot_sdb); + scsi_free_sgtable(cmd->prot_sdb, false); } -EXPORT_SYMBOL(scsi_release_buffers); static void scsi_release_bidi_buffers(struct scsi_cmnd *cmd) { struct scsi_data_buffer *bidi_sdb = cmd->request->next_rq->special; - scsi_free_sgtable(bidi_sdb); + scsi_free_sgtable(bidi_sdb, false); kmem_cache_free(scsi_sdb_cache, bidi_sdb); cmd->request->next_rq->special = NULL; } +static bool scsi_end_request(struct request *req, int error, + unsigned int bytes, unsigned int bidi_bytes) +{ + struct scsi_cmnd *cmd = req->special; + struct scsi_device *sdev = cmd->device; + struct request_queue *q = sdev->request_queue; + + if (blk_update_request(req, error, bytes)) + return true; + + /* Bidi request must be completed as a whole */ + if (unlikely(bidi_bytes) && + blk_update_request(req->next_rq, error, bidi_bytes)) + return true; + + if (blk_queue_add_random(q)) + add_disk_randomness(req->rq_disk); + + if (req->mq_ctx) { + /* + * In the MQ case the command gets freed by __blk_mq_end_io, + * so we have to do all cleanup that depends on it earlier. + * + * We also can't kick the queues from irq context, so we + * will have to defer it to a workqueue. + */ + scsi_mq_uninit_cmd(cmd); + + __blk_mq_end_io(req, error); + + if (scsi_target(sdev)->single_lun || + !list_empty(&sdev->host->starved_list)) + kblockd_schedule_work(&sdev->requeue_work); + else + blk_mq_start_stopped_hw_queues(q, true); + + put_device(&sdev->sdev_gendev); + } else { + unsigned long flags; + + spin_lock_irqsave(q->queue_lock, flags); + blk_finish_request(req, error); + spin_unlock_irqrestore(q->queue_lock, flags); + + if (bidi_bytes) + scsi_release_bidi_buffers(cmd); + scsi_release_buffers(cmd); + scsi_next_command(cmd); + } + + return false; +} + /** * __scsi_error_from_host_byte - translate SCSI error code into errno * @cmd: SCSI command (unused) @@ -672,7 +818,7 @@ static int __scsi_error_from_host_byte(struct scsi_cmnd *cmd, int result) * be put back on the queue and retried using the same * command as before, possibly after a delay. * - * c) We can call blk_end_request() with -EIO to fail + * 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) @@ -686,7 +832,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) int sense_deferred = 0; enum {ACTION_FAIL, ACTION_REPREP, ACTION_RETRY, ACTION_DELAYED_RETRY} action; - char *description = NULL; unsigned long wait_for = (cmd->allowed + 1) * req->timeout; if (result) { @@ -724,13 +869,9 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) * both sides at once. */ req->next_rq->resid_len = scsi_in(cmd)->resid; - - scsi_release_buffers(cmd); - scsi_release_bidi_buffers(cmd); - - blk_end_request_all(req, 0); - - scsi_next_command(cmd); + if (scsi_end_request(req, 0, blk_rq_bytes(req), + blk_rq_bytes(req->next_rq))) + BUG(); return; } } else if (blk_rq_bytes(req) == 0 && result && !sense_deferred) { @@ -750,9 +891,9 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) * Next deal with any sectors which we were able to correctly * handle. */ - SCSI_LOG_HLCOMPLETE(1, printk("%u sectors total, " - "%d bytes done.\n", - blk_rq_sectors(req), good_bytes)); + SCSI_LOG_HLCOMPLETE(1, scmd_printk(KERN_INFO, cmd, + "%u sectors total, %d bytes done.\n", + blk_rq_sectors(req), good_bytes)); /* * Recovered errors need reporting, but they're always treated @@ -777,15 +918,16 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) /* * If we finished all bytes in the request we are done now. */ - if (!blk_end_request(req, error, good_bytes)) - goto next_command; + if (!scsi_end_request(req, error, good_bytes, 0)) + return; /* * Kill remainder if no retrys. */ if (error && scsi_noretry_cmd(cmd)) { - blk_end_request_all(req, error); - goto next_command; + if (scsi_end_request(req, error, blk_rq_bytes(req), 0)) + BUG(); + return; } /* @@ -811,7 +953,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) * and quietly refuse further access. */ cmd->device->changed = 1; - description = "Media Changed"; action = ACTION_FAIL; } else { /* Must have been a power glitch, or a @@ -839,27 +980,10 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) cmd->device->use_10_for_rw = 0; action = ACTION_REPREP; } else if (sshdr.asc == 0x10) /* DIX */ { - description = "Host Data Integrity Failure"; action = ACTION_FAIL; error = -EILSEQ; /* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */ } else if (sshdr.asc == 0x20 || sshdr.asc == 0x24) { - switch (cmd->cmnd[0]) { - case UNMAP: - description = "Discard failure"; - break; - case WRITE_SAME: - case WRITE_SAME_16: - if (cmd->cmnd[1] & 0x8) - description = "Discard failure"; - else - description = - "Write same failure"; - break; - default: - description = "Invalid command failure"; - break; - } action = ACTION_FAIL; error = -EREMOTEIO; } else @@ -867,10 +991,8 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) break; case ABORTED_COMMAND: action = ACTION_FAIL; - if (sshdr.asc == 0x10) { /* DIF */ - description = "Target Data Integrity Failure"; + if (sshdr.asc == 0x10) /* DIF */ error = -EILSEQ; - } break; case NOT_READY: /* If the device is in the process of becoming @@ -889,57 +1011,52 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) action = ACTION_DELAYED_RETRY; break; default: - description = "Device not ready"; action = ACTION_FAIL; break; } - } else { - description = "Device not ready"; + } else action = ACTION_FAIL; - } break; case VOLUME_OVERFLOW: /* See SSC3rXX or current. */ action = ACTION_FAIL; break; default: - description = "Unhandled sense code"; action = ACTION_FAIL; break; } - } else { - description = "Unhandled error code"; + } else action = ACTION_FAIL; - } if (action != ACTION_FAIL && - time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) { + time_before(cmd->jiffies_at_alloc + wait_for, jiffies)) action = ACTION_FAIL; - description = "Command timed out"; - } switch (action) { case ACTION_FAIL: /* Give up and fail the remainder of the request */ if (!(req->cmd_flags & REQ_QUIET)) { - if (description) - scmd_printk(KERN_INFO, cmd, "%s\n", - description); scsi_print_result(cmd); if (driver_byte(result) & DRIVER_SENSE) scsi_print_sense("", cmd); scsi_print_command(cmd); } - if (!blk_end_request_err(req, error)) - goto next_command; + if (!scsi_end_request(req, error, blk_rq_err_bytes(req), 0)) + return; /*FALLTHRU*/ case ACTION_REPREP: requeue: /* Unprep the request and put it back at the head of the queue. * A new command will be prepared and issued. */ - scsi_release_buffers(cmd); - scsi_requeue_command(q, cmd); + if (q->mq_ops) { + cmd->request->cmd_flags &= ~REQ_DONTPREP; + scsi_mq_uninit_cmd(cmd); + scsi_mq_requeue_cmd(cmd); + } else { + scsi_release_buffers(cmd); + scsi_requeue_command(q, cmd); + } break; case ACTION_RETRY: /* Retry the same command immediately */ @@ -950,11 +1067,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) __scsi_queue_insert(cmd, SCSI_MLQUEUE_DEVICE_BUSY, 0); break; } - return; - -next_command: - scsi_release_buffers(cmd); - scsi_next_command(cmd); } static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb, @@ -966,9 +1078,8 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb, * If sg table allocation fails, requeue request later. */ if (unlikely(scsi_alloc_sgtable(sdb, req->nr_phys_segments, - gfp_mask))) { + gfp_mask, req->mq_ctx != NULL))) return BLKPREP_DEFER; - } /* * Next, walk the list, and fill in the addresses and sizes of @@ -996,21 +1107,29 @@ int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask) { struct scsi_device *sdev = cmd->device; struct request *rq = cmd->request; + bool is_mq = (rq->mq_ctx != NULL); + int error; + + BUG_ON(!rq->nr_phys_segments); - int error = scsi_init_sgtable(rq, &cmd->sdb, gfp_mask); + error = scsi_init_sgtable(rq, &cmd->sdb, gfp_mask); if (error) goto err_exit; if (blk_bidi_rq(rq)) { - struct scsi_data_buffer *bidi_sdb = kmem_cache_zalloc( - scsi_sdb_cache, GFP_ATOMIC); - if (!bidi_sdb) { - error = BLKPREP_DEFER; - goto err_exit; + if (!rq->q->mq_ops) { + struct scsi_data_buffer *bidi_sdb = + kmem_cache_zalloc(scsi_sdb_cache, GFP_ATOMIC); + if (!bidi_sdb) { + error = BLKPREP_DEFER; + goto err_exit; + } + + rq->next_rq->special = bidi_sdb; } - rq->next_rq->special = bidi_sdb; - error = scsi_init_sgtable(rq->next_rq, bidi_sdb, GFP_ATOMIC); + error = scsi_init_sgtable(rq->next_rq, rq->next_rq->special, + GFP_ATOMIC); if (error) goto err_exit; } @@ -1022,7 +1141,7 @@ int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask) BUG_ON(prot_sdb == NULL); ivecs = blk_rq_count_integrity_sg(rq->q, rq->bio); - if (scsi_alloc_sgtable(prot_sdb, ivecs, gfp_mask)) { + if (scsi_alloc_sgtable(prot_sdb, ivecs, gfp_mask, is_mq)) { error = BLKPREP_DEFER; goto err_exit; } @@ -1036,13 +1155,16 @@ int scsi_init_io(struct scsi_cmnd *cmd, gfp_t gfp_mask) cmd->prot_sdb->table.nents = count; } - return BLKPREP_OK ; - + return BLKPREP_OK; err_exit: - scsi_release_buffers(cmd); - cmd->request->special = NULL; - scsi_put_command(cmd); - put_device(&sdev->sdev_gendev); + if (is_mq) { + scsi_mq_free_sgtables(cmd); + } else { + scsi_release_buffers(cmd); + cmd->request->special = NULL; + scsi_put_command(cmd); + put_device(&sdev->sdev_gendev); + } return error; } EXPORT_SYMBOL(scsi_init_io); @@ -1077,7 +1199,7 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev, return cmd; } -int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) +static int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) { struct scsi_cmnd *cmd = req->special; @@ -1088,11 +1210,7 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) * submit a request without an attached bio. */ if (req->bio) { - int ret; - - BUG_ON(!req->nr_phys_segments); - - ret = scsi_init_io(cmd, GFP_ATOMIC); + int ret = scsi_init_io(cmd, GFP_ATOMIC); if (unlikely(ret)) return ret; } else { @@ -1102,25 +1220,16 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) } cmd->cmd_len = req->cmd_len; - if (!blk_rq_bytes(req)) - cmd->sc_data_direction = DMA_NONE; - else if (rq_data_dir(req) == WRITE) - cmd->sc_data_direction = DMA_TO_DEVICE; - else - cmd->sc_data_direction = DMA_FROM_DEVICE; - cmd->transfersize = blk_rq_bytes(req); cmd->allowed = req->retries; return BLKPREP_OK; } -EXPORT_SYMBOL(scsi_setup_blk_pc_cmnd); /* - * Setup a REQ_TYPE_FS command. These are simple read/write request - * from filesystems that still need to be translated to SCSI CDBs from - * the ULD. + * Setup a REQ_TYPE_FS command. These are simple request from filesystems + * that still need to be translated to SCSI CDBs from the ULD. */ -int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) +static int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) { struct scsi_cmnd *cmd = req->special; @@ -1131,15 +1240,30 @@ int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) return ret; } - /* - * Filesystem requests must transfer data. - */ - BUG_ON(!req->nr_phys_segments); - memset(cmd->cmnd, 0, BLK_MAX_CDB); - return scsi_init_io(cmd, GFP_ATOMIC); + return scsi_cmd_to_driver(cmd)->init_command(cmd); +} + +static int scsi_setup_cmnd(struct scsi_device *sdev, struct request *req) +{ + struct scsi_cmnd *cmd = req->special; + + if (!blk_rq_bytes(req)) + cmd->sc_data_direction = DMA_NONE; + else if (rq_data_dir(req) == WRITE) + cmd->sc_data_direction = DMA_TO_DEVICE; + else + cmd->sc_data_direction = DMA_FROM_DEVICE; + + switch (req->cmd_type) { + case REQ_TYPE_FS: + return scsi_setup_fs_cmnd(sdev, req); + case REQ_TYPE_BLOCK_PC: + return scsi_setup_blk_pc_cmnd(sdev, req); + default: + return BLKPREP_KILL; + } } -EXPORT_SYMBOL(scsi_setup_fs_cmnd); static int scsi_prep_state_check(struct scsi_device *sdev, struct request *req) @@ -1218,7 +1342,7 @@ scsi_prep_return(struct request_queue *q, struct request *req, int ret) * queue must be restarted, so we schedule a callback to happen * shortly. */ - if (sdev->device_busy == 0) + if (atomic_read(&sdev->device_busy) == 0) blk_delay_queue(q, SCSI_QUEUE_DELAY); break; default: @@ -1244,26 +1368,14 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) goto out; } - if (req->cmd_type == REQ_TYPE_FS) - ret = scsi_cmd_to_driver(cmd)->init_command(cmd); - else if (req->cmd_type == REQ_TYPE_BLOCK_PC) - ret = scsi_setup_blk_pc_cmnd(sdev, req); - else - ret = BLKPREP_KILL; - + ret = scsi_setup_cmnd(sdev, req); out: return scsi_prep_return(q, req, ret); } static void scsi_unprep_fn(struct request_queue *q, struct request *req) { - if (req->cmd_type == REQ_TYPE_FS) { - struct scsi_cmnd *cmd = req->special; - struct scsi_driver *drv = scsi_cmd_to_driver(cmd); - - if (drv->uninit_command) - drv->uninit_command(cmd); - } + scsi_uninit_cmd(req->special); } /* @@ -1275,99 +1387,144 @@ static void scsi_unprep_fn(struct request_queue *q, struct request *req) static inline int scsi_dev_queue_ready(struct request_queue *q, struct scsi_device *sdev) { - if (sdev->device_busy == 0 && sdev->device_blocked) { + unsigned int busy; + + busy = atomic_inc_return(&sdev->device_busy) - 1; + if (atomic_read(&sdev->device_blocked)) { + if (busy) + goto out_dec; + /* * unblock after device_blocked iterates to zero */ - if (--sdev->device_blocked == 0) { - SCSI_LOG_MLQUEUE(3, - sdev_printk(KERN_INFO, sdev, - "unblocking device at zero depth\n")); - } else { - blk_delay_queue(q, SCSI_QUEUE_DELAY); - return 0; + if (atomic_dec_return(&sdev->device_blocked) > 0) { + /* + * For the MQ case we take care of this in the caller. + */ + if (!q->mq_ops) + blk_delay_queue(q, SCSI_QUEUE_DELAY); + goto out_dec; } + SCSI_LOG_MLQUEUE(3, sdev_printk(KERN_INFO, sdev, + "unblocking device at zero depth\n")); } - if (scsi_device_is_busy(sdev)) - return 0; + + if (busy >= sdev->queue_depth) + goto out_dec; return 1; +out_dec: + atomic_dec(&sdev->device_busy); + return 0; } - /* * scsi_target_queue_ready: checks if there we can send commands to target * @sdev: scsi device on starget to check. - * - * Called with the host lock held. */ static inline int scsi_target_queue_ready(struct Scsi_Host *shost, struct scsi_device *sdev) { struct scsi_target *starget = scsi_target(sdev); + unsigned int busy; if (starget->single_lun) { + spin_lock_irq(shost->host_lock); if (starget->starget_sdev_user && - starget->starget_sdev_user != sdev) + starget->starget_sdev_user != sdev) { + spin_unlock_irq(shost->host_lock); return 0; + } starget->starget_sdev_user = sdev; + spin_unlock_irq(shost->host_lock); } - if (starget->target_busy == 0 && starget->target_blocked) { + if (starget->can_queue <= 0) + return 1; + + busy = atomic_inc_return(&starget->target_busy) - 1; + if (atomic_read(&starget->target_blocked) > 0) { + if (busy) + goto starved; + /* * unblock after target_blocked iterates to zero */ - if (--starget->target_blocked == 0) { - SCSI_LOG_MLQUEUE(3, starget_printk(KERN_INFO, starget, - "unblocking target at zero depth\n")); - } else - return 0; - } + if (atomic_dec_return(&starget->target_blocked) > 0) + goto out_dec; - if (scsi_target_is_busy(starget)) { - list_move_tail(&sdev->starved_entry, &shost->starved_list); - return 0; + SCSI_LOG_MLQUEUE(3, starget_printk(KERN_INFO, starget, + "unblocking target at zero depth\n")); } + if (busy >= starget->can_queue) + goto starved; + return 1; + +starved: + spin_lock_irq(shost->host_lock); + list_move_tail(&sdev->starved_entry, &shost->starved_list); + spin_unlock_irq(shost->host_lock); +out_dec: + if (starget->can_queue > 0) + atomic_dec(&starget->target_busy); + return 0; } /* * scsi_host_queue_ready: if we can send requests to shost, return 1 else * return 0. We must end up running the queue again whenever 0 is * returned, else IO can hang. - * - * Called with host_lock held. */ static inline int scsi_host_queue_ready(struct request_queue *q, struct Scsi_Host *shost, struct scsi_device *sdev) { + unsigned int busy; + if (scsi_host_in_recovery(shost)) return 0; - if (shost->host_busy == 0 && shost->host_blocked) { + + busy = atomic_inc_return(&shost->host_busy) - 1; + if (atomic_read(&shost->host_blocked) > 0) { + if (busy) + goto starved; + /* * unblock after host_blocked iterates to zero */ - if (--shost->host_blocked == 0) { - SCSI_LOG_MLQUEUE(3, - printk("scsi%d unblocking host at zero depth\n", - shost->host_no)); - } else { - return 0; - } - } - if (scsi_host_is_busy(shost)) { - if (list_empty(&sdev->starved_entry)) - list_add_tail(&sdev->starved_entry, &shost->starved_list); - return 0; + if (atomic_dec_return(&shost->host_blocked) > 0) + goto out_dec; + + SCSI_LOG_MLQUEUE(3, + shost_printk(KERN_INFO, shost, + "unblocking host at zero depth\n")); } + if (shost->can_queue > 0 && busy >= shost->can_queue) + goto starved; + if (shost->host_self_blocked) + goto starved; + /* We're OK to process the command, so we can't be starved */ - if (!list_empty(&sdev->starved_entry)) - list_del_init(&sdev->starved_entry); + if (!list_empty(&sdev->starved_entry)) { + spin_lock_irq(shost->host_lock); + if (!list_empty(&sdev->starved_entry)) + list_del_init(&sdev->starved_entry); + spin_unlock_irq(shost->host_lock); + } return 1; + +starved: + spin_lock_irq(shost->host_lock); + if (list_empty(&sdev->starved_entry)) + list_add_tail(&sdev->starved_entry, &shost->starved_list); + spin_unlock_irq(shost->host_lock); +out_dec: + atomic_dec(&shost->host_busy); + return 0; } /* @@ -1430,13 +1587,10 @@ static void scsi_kill_request(struct request *req, struct request_queue *q) * bump busy counts. To bump the counters, we need to dance * with the locks as normal issue path does. */ - sdev->device_busy++; - spin_unlock(sdev->request_queue->queue_lock); - spin_lock(shost->host_lock); - shost->host_busy++; - starget->target_busy++; - spin_unlock(shost->host_lock); - spin_lock(sdev->request_queue->queue_lock); + atomic_inc(&sdev->device_busy); + atomic_inc(&shost->host_busy); + if (starget->can_queue > 0) + atomic_inc(&starget->target_busy); blk_complete_request(req); } @@ -1461,7 +1615,7 @@ static void scsi_softirq_done(struct request *rq) wait_for/HZ); disposition = SUCCESS; } - + scsi_log_completion(cmd, disposition); switch (disposition) { @@ -1480,6 +1634,23 @@ static void scsi_softirq_done(struct request *rq) } } +/** + * scsi_done - Invoke completion on finished SCSI command. + * @cmd: The SCSI Command for which a low-level device driver (LLDD) gives + * ownership back to SCSI Core -- i.e. the LLDD has finished with it. + * + * Description: This function is the mid-level's (SCSI Core) interrupt routine, + * which regains ownership of the SCSI command (de facto) from a LLDD, and + * calls blk_complete_request() for further processing. + * + * This function is interrupt context safe. + */ +static void scsi_done(struct scsi_cmnd *cmd) +{ + trace_scsi_dispatch_cmd_done(cmd); + blk_complete_request(cmd->request); +} + /* * Function: scsi_request_fn() * @@ -1509,11 +1680,11 @@ static void scsi_request_fn(struct request_queue *q) int rtn; /* * get next queueable request. We do this early to make sure - * that the request is fully prepared even if we cannot + * that the request is fully prepared even if we cannot * accept it. */ req = blk_peek_request(q); - if (!req || !scsi_dev_queue_ready(q, sdev)) + if (!req) break; if (unlikely(!scsi_device_online(sdev))) { @@ -1523,15 +1694,16 @@ static void scsi_request_fn(struct request_queue *q) continue; } + if (!scsi_dev_queue_ready(q, sdev)) + break; /* * Remove the request from the request list. */ if (!(blk_queue_tagged(q) && !blk_queue_start_tag(q, req))) blk_start_request(req); - sdev->device_busy++; - spin_unlock(q->queue_lock); + spin_unlock_irq(q->queue_lock); cmd = req->special; if (unlikely(cmd == NULL)) { printk(KERN_CRIT "impossible request in %s.\n" @@ -1541,7 +1713,6 @@ static void scsi_request_fn(struct request_queue *q) blk_dump_rq_flags(req, "foo"); BUG(); } - spin_lock(shost->host_lock); /* * We hit this when the driver is using a host wide @@ -1552,9 +1723,11 @@ static void scsi_request_fn(struct request_queue *q) * a run when a tag is freed. */ if (blk_queue_tagged(q) && !blk_rq_tagged(req)) { + spin_lock_irq(shost->host_lock); if (list_empty(&sdev->starved_entry)) list_add_tail(&sdev->starved_entry, &shost->starved_list); + spin_unlock_irq(shost->host_lock); goto not_ready; } @@ -1562,16 +1735,7 @@ static void scsi_request_fn(struct request_queue *q) goto not_ready; if (!scsi_host_queue_ready(q, shost, sdev)) - goto not_ready; - - scsi_target(sdev)->target_busy++; - shost->host_busy++; - - /* - * XXX(hch): This is rather suboptimal, scsi_dispatch_cmd will - * take the lock again. - */ - spin_unlock_irq(shost->host_lock); + goto host_not_ready; /* * Finally, initialize any error handling parameters, and set up @@ -1582,17 +1746,22 @@ static void scsi_request_fn(struct request_queue *q) /* * Dispatch the command to the low-level driver. */ + cmd->scsi_done = scsi_done; rtn = scsi_dispatch_cmd(cmd); - spin_lock_irq(q->queue_lock); - if (rtn) + if (rtn) { + scsi_queue_insert(cmd, rtn); + spin_lock_irq(q->queue_lock); goto out_delay; + } + spin_lock_irq(q->queue_lock); } return; + host_not_ready: + if (scsi_target(sdev)->can_queue > 0) + atomic_dec(&scsi_target(sdev)->target_busy); not_ready: - spin_unlock_irq(shost->host_lock); - /* * lock q, handle tag, requeue req, and decrement device_busy. We * must return with queue_lock held. @@ -1603,13 +1772,187 @@ static void scsi_request_fn(struct request_queue *q) */ spin_lock_irq(q->queue_lock); blk_requeue_request(q, req); - sdev->device_busy--; + atomic_dec(&sdev->device_busy); out_delay: - if (sdev->device_busy == 0) + if (atomic_read(&sdev->device_busy) && !scsi_device_blocked(sdev)) blk_delay_queue(q, SCSI_QUEUE_DELAY); } -u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost) +static inline int prep_to_mq(int ret) +{ + switch (ret) { + case BLKPREP_OK: + return 0; + case BLKPREP_DEFER: + return BLK_MQ_RQ_QUEUE_BUSY; + default: + return BLK_MQ_RQ_QUEUE_ERROR; + } +} + +static int scsi_mq_prep_fn(struct request *req) +{ + struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req); + struct scsi_device *sdev = req->q->queuedata; + struct Scsi_Host *shost = sdev->host; + unsigned char *sense_buf = cmd->sense_buffer; + struct scatterlist *sg; + + memset(cmd, 0, sizeof(struct scsi_cmnd)); + + req->special = cmd; + + cmd->request = req; + cmd->device = sdev; + cmd->sense_buffer = sense_buf; + + cmd->tag = req->tag; + + req->cmd = req->__cmd; + cmd->cmnd = req->cmd; + cmd->prot_op = SCSI_PROT_NORMAL; + + INIT_LIST_HEAD(&cmd->list); + INIT_DELAYED_WORK(&cmd->abort_work, scmd_eh_abort_handler); + cmd->jiffies_at_alloc = jiffies; + + /* + * XXX: cmd_list lookups are only used by two drivers, try to get + * rid of this list in common code. + */ + spin_lock_irq(&sdev->list_lock); + list_add_tail(&cmd->list, &sdev->cmd_list); + spin_unlock_irq(&sdev->list_lock); + + sg = (void *)cmd + sizeof(struct scsi_cmnd) + shost->hostt->cmd_size; + cmd->sdb.table.sgl = sg; + + if (scsi_host_get_prot(shost)) { + cmd->prot_sdb = (void *)sg + + shost->sg_tablesize * sizeof(struct scatterlist); + memset(cmd->prot_sdb, 0, sizeof(struct scsi_data_buffer)); + + cmd->prot_sdb->table.sgl = + (struct scatterlist *)(cmd->prot_sdb + 1); + } + + if (blk_bidi_rq(req)) { + struct request *next_rq = req->next_rq; + struct scsi_data_buffer *bidi_sdb = blk_mq_rq_to_pdu(next_rq); + + memset(bidi_sdb, 0, sizeof(struct scsi_data_buffer)); + bidi_sdb->table.sgl = + (struct scatterlist *)(bidi_sdb + 1); + + next_rq->special = bidi_sdb; + } + + return scsi_setup_cmnd(sdev, req); +} + +static void scsi_mq_done(struct scsi_cmnd *cmd) +{ + trace_scsi_dispatch_cmd_done(cmd); + blk_mq_complete_request(cmd->request); +} + +static int scsi_queue_rq(struct blk_mq_hw_ctx *hctx, struct request *req) +{ + struct request_queue *q = req->q; + struct scsi_device *sdev = q->queuedata; + struct Scsi_Host *shost = sdev->host; + struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(req); + int ret; + int reason; + + ret = prep_to_mq(scsi_prep_state_check(sdev, req)); + if (ret) + goto out; + + ret = BLK_MQ_RQ_QUEUE_BUSY; + if (!get_device(&sdev->sdev_gendev)) + goto out; + + if (!scsi_dev_queue_ready(q, sdev)) + goto out_put_device; + if (!scsi_target_queue_ready(shost, sdev)) + goto out_dec_device_busy; + if (!scsi_host_queue_ready(q, shost, sdev)) + goto out_dec_target_busy; + + if (!(req->cmd_flags & REQ_DONTPREP)) { + ret = prep_to_mq(scsi_mq_prep_fn(req)); + if (ret) + goto out_dec_host_busy; + req->cmd_flags |= REQ_DONTPREP; + } + + scsi_init_cmd_errh(cmd); + cmd->scsi_done = scsi_mq_done; + + reason = scsi_dispatch_cmd(cmd); + if (reason) { + scsi_set_blocked(cmd, reason); + ret = BLK_MQ_RQ_QUEUE_BUSY; + goto out_dec_host_busy; + } + + return BLK_MQ_RQ_QUEUE_OK; + +out_dec_host_busy: + atomic_dec(&shost->host_busy); +out_dec_target_busy: + if (scsi_target(sdev)->can_queue > 0) + atomic_dec(&scsi_target(sdev)->target_busy); +out_dec_device_busy: + atomic_dec(&sdev->device_busy); +out_put_device: + put_device(&sdev->sdev_gendev); +out: + switch (ret) { + case BLK_MQ_RQ_QUEUE_BUSY: + blk_mq_stop_hw_queue(hctx); + if (atomic_read(&sdev->device_busy) == 0 && + !scsi_device_blocked(sdev)) + blk_mq_delay_queue(hctx, SCSI_QUEUE_DELAY); + break; + case BLK_MQ_RQ_QUEUE_ERROR: + /* + * Make sure to release all allocated ressources when + * we hit an error, as we will never see this command + * again. + */ + if (req->cmd_flags & REQ_DONTPREP) + scsi_mq_uninit_cmd(cmd); + break; + default: + break; + } + return ret; +} + +static int scsi_init_request(void *data, struct request *rq, + unsigned int hctx_idx, unsigned int request_idx, + unsigned int numa_node) +{ + struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq); + + cmd->sense_buffer = kzalloc_node(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL, + numa_node); + if (!cmd->sense_buffer) + return -ENOMEM; + return 0; +} + +static void scsi_exit_request(void *data, struct request *rq, + unsigned int hctx_idx, unsigned int request_idx) +{ + struct scsi_cmnd *cmd = blk_mq_rq_to_pdu(rq); + + kfree(cmd->sense_buffer); +} + +static u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost) { struct device *host_dev; u64 bounce_limit = 0xffffffff; @@ -1629,18 +1972,11 @@ u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost) return bounce_limit; } -EXPORT_SYMBOL(scsi_calculate_bounce_limit); -struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost, - request_fn_proc *request_fn) +static void __scsi_init_queue(struct Scsi_Host *shost, struct request_queue *q) { - struct request_queue *q; struct device *dev = shost->dma_dev; - q = blk_init_queue(request_fn, NULL); - if (!q) - return NULL; - /* * this limit is imposed by hardware restrictions */ @@ -1671,7 +2007,17 @@ struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost, * blk_queue_update_dma_alignment() later. */ blk_queue_dma_alignment(q, 0x03); +} +struct request_queue *__scsi_alloc_queue(struct Scsi_Host *shost, + request_fn_proc *request_fn) +{ + struct request_queue *q; + + q = blk_init_queue(request_fn, NULL); + if (!q) + return NULL; + __scsi_init_queue(shost, q); return q; } EXPORT_SYMBOL(__scsi_alloc_queue); @@ -1692,6 +2038,55 @@ struct request_queue *scsi_alloc_queue(struct scsi_device *sdev) return q; } +static struct blk_mq_ops scsi_mq_ops = { + .map_queue = blk_mq_map_queue, + .queue_rq = scsi_queue_rq, + .complete = scsi_softirq_done, + .timeout = scsi_times_out, + .init_request = scsi_init_request, + .exit_request = scsi_exit_request, +}; + +struct request_queue *scsi_mq_alloc_queue(struct scsi_device *sdev) +{ + sdev->request_queue = blk_mq_init_queue(&sdev->host->tag_set); + if (IS_ERR(sdev->request_queue)) + return NULL; + + sdev->request_queue->queuedata = sdev; + __scsi_init_queue(sdev->host, sdev->request_queue); + return sdev->request_queue; +} + +int scsi_mq_setup_tags(struct Scsi_Host *shost) +{ + unsigned int cmd_size, sgl_size, tbl_size; + + tbl_size = shost->sg_tablesize; + if (tbl_size > SCSI_MAX_SG_SEGMENTS) + tbl_size = SCSI_MAX_SG_SEGMENTS; + sgl_size = tbl_size * sizeof(struct scatterlist); + cmd_size = sizeof(struct scsi_cmnd) + shost->hostt->cmd_size + sgl_size; + if (scsi_host_get_prot(shost)) + cmd_size += sizeof(struct scsi_data_buffer) + sgl_size; + + memset(&shost->tag_set, 0, sizeof(shost->tag_set)); + shost->tag_set.ops = &scsi_mq_ops; + shost->tag_set.nr_hw_queues = 1; + shost->tag_set.queue_depth = shost->can_queue; + shost->tag_set.cmd_size = cmd_size; + shost->tag_set.numa_node = NUMA_NO_NODE; + shost->tag_set.flags = BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_SG_MERGE; + shost->tag_set.driver_data = shost; + + return blk_mq_alloc_tag_set(&shost->tag_set); +} + +void scsi_mq_destroy_tags(struct Scsi_Host *shost) +{ + blk_mq_free_tag_set(&shost->tag_set); +} + /* * Function: scsi_block_requests() * @@ -2147,9 +2542,9 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state) return 0; illegal: - SCSI_LOG_ERROR_RECOVERY(1, + SCSI_LOG_ERROR_RECOVERY(1, sdev_printk(KERN_ERR, sdev, - "Illegal state transition %s->%s\n", + "Illegal state transition %s->%s", scsi_device_state_name(oldstate), scsi_device_state_name(state)) ); @@ -2345,7 +2740,7 @@ scsi_device_quiesce(struct scsi_device *sdev) return err; scsi_run_queue(sdev->request_queue); - while (sdev->device_busy) { + while (atomic_read(&sdev->device_busy)) { msleep_interruptible(200); scsi_run_queue(sdev->request_queue); } @@ -2437,9 +2832,13 @@ scsi_internal_device_block(struct scsi_device *sdev) * block layer from calling the midlayer with this device's * request queue. */ - spin_lock_irqsave(q->queue_lock, flags); - blk_stop_queue(q); - spin_unlock_irqrestore(q->queue_lock, flags); + if (q->mq_ops) { + blk_mq_stop_hw_queues(q); + } else { + spin_lock_irqsave(q->queue_lock, flags); + blk_stop_queue(q); + spin_unlock_irqrestore(q->queue_lock, flags); + } return 0; } @@ -2485,9 +2884,13 @@ scsi_internal_device_unblock(struct scsi_device *sdev, sdev->sdev_state != SDEV_OFFLINE) return -EINVAL; - spin_lock_irqsave(q->queue_lock, flags); - blk_start_queue(q); - spin_unlock_irqrestore(q->queue_lock, flags); + if (q->mq_ops) { + blk_mq_start_stopped_hw_queues(q, false); + } else { + spin_lock_irqsave(q->queue_lock, flags); + blk_start_queue(q); + spin_unlock_irqrestore(q->queue_lock, flags); + } return 0; } diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index 48e5b657e79f..12b8e1bee7f0 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -88,6 +88,9 @@ extern void scsi_next_command(struct scsi_cmnd *cmd); extern void scsi_io_completion(struct scsi_cmnd *, unsigned int); extern void scsi_run_host_queues(struct Scsi_Host *shost); extern struct request_queue *scsi_alloc_queue(struct scsi_device *sdev); +extern struct request_queue *scsi_mq_alloc_queue(struct scsi_device *sdev); +extern int scsi_mq_setup_tags(struct Scsi_Host *shost); +extern void scsi_mq_destroy_tags(struct Scsi_Host *shost); extern int scsi_init_queue(void); extern void scsi_exit_queue(void); struct request_queue; @@ -115,7 +118,7 @@ extern void scsi_exit_procfs(void); extern char scsi_scan_type[]; extern int scsi_complete_async_scans(void); extern int scsi_scan_host_selected(struct Scsi_Host *, unsigned int, - unsigned int, unsigned int, int); + unsigned int, u64, int); extern void scsi_forget_host(struct Scsi_Host *); extern void scsi_rescan_device(struct device *); diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c index 86f0c5d5c116..6fcefa2da503 100644 --- a/drivers/scsi/scsi_proc.c +++ b/drivers/scsi/scsi_proc.c @@ -185,7 +185,7 @@ static int proc_print_scsidevice(struct device *dev, void *data) sdev = to_scsi_device(dev); seq_printf(s, - "Host: scsi%d Channel: %02d Id: %02d Lun: %02d\n Vendor: ", + "Host: scsi%d Channel: %02d Id: %02d Lun: %02llu\n Vendor: ", sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); for (i = 0; i < 8; i++) { if (sdev->vendor[i] >= 0x20) diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index e02b3aab56ce..56675dbbf681 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -81,15 +81,11 @@ static const char *scsi_null_device_strs = "nullnullnullnull"; #define MAX_SCSI_LUNS 512 -#ifdef CONFIG_SCSI_MULTI_LUN -static unsigned int max_scsi_luns = MAX_SCSI_LUNS; -#else -static unsigned int max_scsi_luns = 1; -#endif +static u64 max_scsi_luns = MAX_SCSI_LUNS; -module_param_named(max_luns, max_scsi_luns, uint, S_IRUGO|S_IWUSR); +module_param_named(max_luns, max_scsi_luns, ullong, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(max_luns, - "last scsi LUN (should be between 1 and 2^32-1)"); + "last scsi LUN (should be between 1 and 2^64-1)"); #ifdef CONFIG_SCSI_SCAN_ASYNC #define SCSI_SCAN_TYPE_DEFAULT "async" @@ -198,7 +194,7 @@ static void scsi_unlock_floptical(struct scsi_device *sdev, { unsigned char scsi_cmd[MAX_COMMAND_SIZE]; - printk(KERN_NOTICE "scsi: unlocking floptical drive\n"); + sdev_printk(KERN_NOTICE, sdev, "unlocking floptical drive\n"); scsi_cmd[0] = MODE_SENSE; scsi_cmd[1] = 0; scsi_cmd[2] = 0x2e; @@ -224,7 +220,7 @@ static void scsi_unlock_floptical(struct scsi_device *sdev, * scsi_Device pointer, or NULL on failure. **/ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, - unsigned int lun, void *hostdata) + u64 lun, void *hostdata) { struct scsi_device *sdev; int display_failure_msg = 1, ret; @@ -277,7 +273,10 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget, */ sdev->borken = 1; - sdev->request_queue = scsi_alloc_queue(sdev); + if (shost_use_blk_mq(shost)) + sdev->request_queue = scsi_mq_alloc_queue(sdev); + else + sdev->request_queue = scsi_alloc_queue(sdev); if (!sdev->request_queue) { /* release fn is set up in scsi_sysfs_device_initialise, so * have to free and put manually here */ @@ -600,8 +599,8 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result, HZ / 2 + HZ * scsi_inq_timeout, 3, &resid); - SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: INQUIRY %s " - "with code 0x%x\n", + SCSI_LOG_SCAN_BUS(3, sdev_printk(KERN_INFO, sdev, + "scsi scan: INQUIRY %s with code 0x%x\n", result ? "failed" : "successful", result)); if (result) { @@ -671,9 +670,10 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result, } } else if (pass == 2) { - printk(KERN_INFO "scsi scan: %d byte inquiry failed. " - "Consider BLIST_INQUIRY_36 for this device\n", - try_inquiry_len); + sdev_printk(KERN_INFO, sdev, + "scsi scan: %d byte inquiry failed. " + "Consider BLIST_INQUIRY_36 for this device\n", + try_inquiry_len); /* If this pass failed, the third pass goes back and transfers * the same amount as we successfully got in the first pass. */ @@ -706,8 +706,9 @@ static int scsi_probe_lun(struct scsi_device *sdev, unsigned char *inq_result, * strings. */ if (sdev->inquiry_len < 36) { - printk(KERN_INFO "scsi scan: INQUIRY result too short (%d)," - " using 36\n", sdev->inquiry_len); + sdev_printk(KERN_INFO, sdev, + "scsi scan: INQUIRY result too short (%d)," + " using 36\n", sdev->inquiry_len); sdev->inquiry_len = 36; } @@ -806,29 +807,6 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, sdev->removable = (inq_result[1] & 0x80) >> 7; } - switch (sdev->type) { - case TYPE_RBC: - case TYPE_TAPE: - case TYPE_DISK: - case TYPE_PRINTER: - case TYPE_MOD: - case TYPE_PROCESSOR: - case TYPE_SCANNER: - case TYPE_MEDIUM_CHANGER: - case TYPE_ENCLOSURE: - case TYPE_COMM: - case TYPE_RAID: - case TYPE_OSD: - sdev->writeable = 1; - break; - case TYPE_ROM: - case TYPE_WORM: - sdev->writeable = 0; - break; - default: - printk(KERN_INFO "scsi: unknown device type %d\n", sdev->type); - } - if (sdev->type == TYPE_RBC || sdev->type == TYPE_ROM) { /* RBC and MMC devices can return SCSI-3 compliance and yet * still not support REPORT LUNS, so make them act as @@ -922,6 +900,12 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, if (*bflags & BLIST_USE_10_BYTE_MS) sdev->use_10_for_ms = 1; + /* some devices don't like REPORT SUPPORTED OPERATION CODES + * and will simply timeout causing sd_mod init to take a very + * very long time */ + if (*bflags & BLIST_NO_RSOC) + sdev->no_report_opcodes = 1; + /* set the device running here so that slave configure * may do I/O */ ret = scsi_device_set_state(sdev, SDEV_RUNNING); @@ -950,7 +934,9 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result, sdev->eh_timeout = SCSI_DEFAULT_EH_TIMEOUT; - if (*bflags & BLIST_SKIP_VPD_PAGES) + if (*bflags & BLIST_TRY_VPD_PAGES) + sdev->try_vpd_pages = 1; + else if (*bflags & BLIST_SKIP_VPD_PAGES) sdev->skip_vpd_pages = 1; transport_configure_device(&sdev->sdev_gendev); @@ -1032,7 +1018,7 @@ static unsigned char *scsi_inq_str(unsigned char *buf, unsigned char *inq, * SCSI_SCAN_LUN_PRESENT: a new scsi_device was allocated and initialized **/ static int scsi_probe_and_add_lun(struct scsi_target *starget, - uint lun, int *bflagsp, + u64 lun, int *bflagsp, struct scsi_device **sdevp, int rescan, void *hostdata) { @@ -1048,7 +1034,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, sdev = scsi_device_lookup_by_target(starget, lun); if (sdev) { if (rescan || !scsi_device_created(sdev)) { - SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO + SCSI_LOG_SCAN_BUS(3, sdev_printk(KERN_INFO, sdev, "scsi scan: device exists on %s\n", dev_name(&sdev->sdev_gendev))); if (sdevp) @@ -1135,7 +1121,7 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, if (((result[0] >> 5) == 1 || starget->pdt_1f_for_no_lun) && (result[0] & 0x1f) == 0x1f && !scsi_is_wlun(lun)) { - SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO + SCSI_LOG_SCAN_BUS(3, sdev_printk(KERN_INFO, sdev, "scsi scan: peripheral device type" " of 31, no device added\n")); res = SCSI_SCAN_TARGET_PRESENT; @@ -1185,11 +1171,12 @@ static int scsi_probe_and_add_lun(struct scsi_target *starget, static void scsi_sequential_lun_scan(struct scsi_target *starget, int bflags, int scsi_level, int rescan) { - unsigned int sparse_lun, lun, max_dev_lun; + uint max_dev_lun; + u64 sparse_lun, lun; struct Scsi_Host *shost = dev_to_shost(starget->dev.parent); - SCSI_LOG_SCAN_BUS(3, printk(KERN_INFO "scsi scan: Sequential scan of" - "%s\n", dev_name(&starget->dev))); + SCSI_LOG_SCAN_BUS(3, starget_printk(KERN_INFO, starget, + "scsi scan: Sequential scan\n")); max_dev_lun = min(max_scsi_luns, shost->max_lun); /* @@ -1239,6 +1226,12 @@ static void scsi_sequential_lun_scan(struct scsi_target *starget, max_dev_lun = min(8U, max_dev_lun); /* + * Stop scanning at 255 unless BLIST_SCSI3LUN + */ + if (!(bflags & BLIST_SCSI3LUN)) + max_dev_lun = min(256U, max_dev_lun); + + /* * We have already scanned LUN 0, so start at LUN 1. Keep scanning * until we reach the max, or no LUN is found and we are not * sparse_lun. @@ -1260,24 +1253,25 @@ static void scsi_sequential_lun_scan(struct scsi_target *starget, * truncation before using this function. * * Notes: - * The struct scsi_lun is assumed to be four levels, with each level - * effectively containing a SCSI byte-ordered (big endian) short; the - * addressing bits of each level are ignored (the highest two bits). * For a description of the LUN format, post SCSI-3 see the SCSI * Architecture Model, for SCSI-3 see the SCSI Controller Commands. * - * Given a struct scsi_lun of: 0a 04 0b 03 00 00 00 00, this function returns - * the integer: 0x0b030a04 + * Given a struct scsi_lun of: d2 04 0b 03 00 00 00 00, this function + * returns the integer: 0x0b03d204 + * + * This encoding will return a standard integer LUN for LUNs smaller + * than 256, which typically use a single level LUN structure with + * addressing method 0. **/ -int scsilun_to_int(struct scsi_lun *scsilun) +u64 scsilun_to_int(struct scsi_lun *scsilun) { int i; - unsigned int lun; + u64 lun; lun = 0; for (i = 0; i < sizeof(lun); i += 2) - lun = lun | (((scsilun->scsi_lun[i] << 8) | - scsilun->scsi_lun[i + 1]) << (i * 8)); + lun = lun | (((u64)scsilun->scsi_lun[i] << ((i + 1) * 8)) | + ((u64)scsilun->scsi_lun[i + 1] << (i * 8))); return lun; } EXPORT_SYMBOL(scsilun_to_int); @@ -1291,16 +1285,13 @@ EXPORT_SYMBOL(scsilun_to_int); * Reverts the functionality of the scsilun_to_int, which packed * an 8-byte lun value into an int. This routine unpacks the int * back into the lun value. - * Note: the scsilun_to_int() routine does not truly handle all - * 8bytes of the lun value. This functions restores only as much - * as was set by the routine. * * Notes: - * Given an integer : 0x0b030a04, this function returns a - * scsi_lun of : struct scsi_lun of: 0a 04 0b 03 00 00 00 00 + * Given an integer : 0x0b03d204, this function returns a + * struct scsi_lun of: d2 04 0b 03 00 00 00 00 * **/ -void int_to_scsilun(unsigned int lun, struct scsi_lun *scsilun) +void int_to_scsilun(u64 lun, struct scsi_lun *scsilun) { int i; @@ -1340,7 +1331,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, char devname[64]; unsigned char scsi_cmd[MAX_COMMAND_SIZE]; unsigned int length; - unsigned int lun; + u64 lun; unsigned int num_luns; unsigned int retries; int result; @@ -1430,17 +1421,19 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, * a retry. */ for (retries = 0; retries < 3; retries++) { - SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: Sending" - " REPORT LUNS to %s (try %d)\n", devname, + SCSI_LOG_SCAN_BUS(3, sdev_printk (KERN_INFO, sdev, + "scsi scan: Sending REPORT LUNS to (try %d)\n", retries)); result = scsi_execute_req(sdev, scsi_cmd, DMA_FROM_DEVICE, lun_data, length, &sshdr, SCSI_TIMEOUT + 4 * HZ, 3, NULL); - SCSI_LOG_SCAN_BUS(3, printk (KERN_INFO "scsi scan: REPORT LUNS" - " %s (try %d) result 0x%x\n", result - ? "failed" : "successful", retries, result)); + SCSI_LOG_SCAN_BUS(3, sdev_printk (KERN_INFO, sdev, + "scsi scan: REPORT LUNS" + " %s (try %d) result 0x%x\n", + result ? "failed" : "successful", + retries, result)); if (result == 0) break; else if (scsi_sense_valid(&sshdr)) { @@ -1466,10 +1459,11 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, num_luns = (length / sizeof(struct scsi_lun)); if (num_luns > max_scsi_report_luns) { - printk(KERN_WARNING "scsi: On %s only %d (max_scsi_report_luns)" - " of %d luns reported, try increasing" - " max_scsi_report_luns.\n", devname, - max_scsi_report_luns, num_luns); + sdev_printk(KERN_WARNING, sdev, + "Only %d (max_scsi_report_luns)" + " of %d luns reported, try increasing" + " max_scsi_report_luns.\n", + max_scsi_report_luns, num_luns); num_luns = max_scsi_report_luns; } @@ -1483,27 +1477,10 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, for (lunp = &lun_data[1]; lunp <= &lun_data[num_luns]; lunp++) { lun = scsilun_to_int(lunp); - /* - * Check if the unused part of lunp is non-zero, and so - * does not fit in lun. - */ - if (memcmp(&lunp->scsi_lun[sizeof(lun)], "\0\0\0\0", 4)) { - int i; - - /* - * Output an error displaying the LUN in byte order, - * this differs from what linux would print for the - * integer LUN value. - */ - printk(KERN_WARNING "scsi: %s lun 0x", devname); - data = (char *)lunp->scsi_lun; - for (i = 0; i < sizeof(struct scsi_lun); i++) - printk("%02x", data[i]); - printk(" has a LUN larger than currently supported.\n"); - } else if (lun > sdev->host->max_lun) { - printk(KERN_WARNING "scsi: %s lun%d has a LUN larger" - " than allowed by the host adapter\n", - devname, lun); + if (lun > sdev->host->max_lun) { + sdev_printk(KERN_WARNING, sdev, + "lun%llu has a LUN larger than" + " allowed by the host adapter\n", lun); } else { int res; @@ -1515,8 +1492,8 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, */ sdev_printk(KERN_ERR, sdev, "Unexpected response" - " from lun %d while scanning, scan" - " aborted\n", lun); + " from lun %llu while scanning, scan" + " aborted\n", (unsigned long long)lun); break; } } @@ -1535,7 +1512,7 @@ static int scsi_report_lun_scan(struct scsi_target *starget, int bflags, } struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, - uint id, uint lun, void *hostdata) + uint id, u64 lun, void *hostdata) { struct scsi_device *sdev = ERR_PTR(-ENODEV); struct device *parent = &shost->shost_gendev; @@ -1571,7 +1548,7 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, EXPORT_SYMBOL(__scsi_add_device); int scsi_add_device(struct Scsi_Host *host, uint channel, - uint target, uint lun) + uint target, u64 lun) { struct scsi_device *sdev = __scsi_add_device(host, channel, target, lun, NULL); @@ -1600,7 +1577,7 @@ void scsi_rescan_device(struct device *dev) EXPORT_SYMBOL(scsi_rescan_device); static void __scsi_scan_target(struct device *parent, unsigned int channel, - unsigned int id, unsigned int lun, int rescan) + unsigned int id, u64 lun, int rescan) { struct Scsi_Host *shost = dev_to_shost(parent); int bflags = 0; @@ -1668,7 +1645,7 @@ static void __scsi_scan_target(struct device *parent, unsigned int channel, * sequential scan of LUNs on the target id. **/ void scsi_scan_target(struct device *parent, unsigned int channel, - unsigned int id, unsigned int lun, int rescan) + unsigned int id, u64 lun, int rescan) { struct Scsi_Host *shost = dev_to_shost(parent); @@ -1688,7 +1665,7 @@ void scsi_scan_target(struct device *parent, unsigned int channel, EXPORT_SYMBOL(scsi_scan_target); static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, - unsigned int id, unsigned int lun, int rescan) + unsigned int id, u64 lun, int rescan) { uint order_id; @@ -1719,10 +1696,10 @@ static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel, } int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, - unsigned int id, unsigned int lun, int rescan) + unsigned int id, u64 lun, int rescan) { SCSI_LOG_SCAN_BUS(3, shost_printk (KERN_INFO, shost, - "%s: <%u:%u:%u>\n", + "%s: <%u:%u:%llu>\n", __func__, channel, id, lun)); if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) || @@ -1781,8 +1758,7 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) return NULL; if (shost->async_scan) { - printk("%s called twice for host %d", __func__, - shost->host_no); + shost_printk(KERN_INFO, shost, "%s called twice\n", __func__); dump_stack(); return NULL; } @@ -1835,8 +1811,7 @@ static void scsi_finish_async_scan(struct async_scan_data *data) mutex_lock(&shost->scan_mutex); if (!shost->async_scan) { - printk("%s called twice for host %d", __func__, - shost->host_no); + shost_printk(KERN_INFO, shost, "%s called twice\n", __func__); dump_stack(); mutex_unlock(&shost->scan_mutex); return; diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index 074e8cc30955..406b3038bbad 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -80,7 +80,7 @@ const char *scsi_host_state_name(enum scsi_host_state state) return name; } -static int check_set(unsigned int *val, char *src) +static int check_set(unsigned long long *val, char *src) { char *last; @@ -90,7 +90,7 @@ static int check_set(unsigned int *val, char *src) /* * Doesn't check for int overflow */ - *val = simple_strtoul(src, &last, 0); + *val = simple_strtoull(src, &last, 0); if (*last != '\0') return 1; } @@ -99,11 +99,11 @@ static int check_set(unsigned int *val, char *src) static int scsi_scan(struct Scsi_Host *shost, const char *str) { - char s1[15], s2[15], s3[15], junk; - unsigned int channel, id, lun; + char s1[15], s2[15], s3[17], junk; + unsigned long long channel, id, lun; int res; - res = sscanf(str, "%10s %10s %10s %c", s1, s2, s3, &junk); + res = sscanf(str, "%10s %10s %16s %c", s1, s2, s3, &junk); if (res != 3) return -EINVAL; if (check_set(&channel, s1)) @@ -333,8 +333,8 @@ store_shost_eh_deadline(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(eh_deadline, S_IRUGO | S_IWUSR, show_shost_eh_deadline, store_shost_eh_deadline); +shost_rd_attr(use_blk_mq, "%d\n"); shost_rd_attr(unique_id, "%u\n"); -shost_rd_attr(host_busy, "%hu\n"); shost_rd_attr(cmd_per_lun, "%hd\n"); shost_rd_attr(can_queue, "%hd\n"); shost_rd_attr(sg_tablesize, "%hu\n"); @@ -344,7 +344,16 @@ shost_rd_attr(prot_capabilities, "%u\n"); shost_rd_attr(prot_guard_type, "%hd\n"); shost_rd_attr2(proc_name, hostt->proc_name, "%s\n"); +static ssize_t +show_host_busy(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(dev); + return snprintf(buf, 20, "%d\n", atomic_read(&shost->host_busy)); +} +static DEVICE_ATTR(host_busy, S_IRUGO, show_host_busy, NULL); + static struct attribute *scsi_sysfs_shost_attrs[] = { + &dev_attr_use_blk_mq.attr, &dev_attr_unique_id.attr, &dev_attr_host_busy.attr, &dev_attr_cmd_per_lun.attr, @@ -577,14 +586,30 @@ static int scsi_sdev_check_buf_bit(const char *buf) /* * Create the actual show/store functions and data structures. */ -sdev_rd_attr (device_blocked, "%d\n"); -sdev_rd_attr (device_busy, "%d\n"); sdev_rd_attr (type, "%d\n"); sdev_rd_attr (scsi_level, "%d\n"); sdev_rd_attr (vendor, "%.8s\n"); sdev_rd_attr (model, "%.16s\n"); sdev_rd_attr (rev, "%.4s\n"); +static ssize_t +sdev_show_device_busy(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct scsi_device *sdev = to_scsi_device(dev); + return snprintf(buf, 20, "%d\n", atomic_read(&sdev->device_busy)); +} +static DEVICE_ATTR(device_busy, S_IRUGO, sdev_show_device_busy, NULL); + +static ssize_t +sdev_show_device_blocked(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct scsi_device *sdev = to_scsi_device(dev); + return snprintf(buf, 20, "%d\n", atomic_read(&sdev->device_blocked)); +} +static DEVICE_ATTR(device_blocked, S_IRUGO, sdev_show_device_blocked, NULL); + /* * TODO: can we make these symlinks to the block layer ones? */ @@ -1230,13 +1255,13 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev) device_initialize(&sdev->sdev_gendev); sdev->sdev_gendev.bus = &scsi_bus_type; sdev->sdev_gendev.type = &scsi_dev_type; - dev_set_name(&sdev->sdev_gendev, "%d:%d:%d:%d", + dev_set_name(&sdev->sdev_gendev, "%d:%d:%d:%llu", sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); device_initialize(&sdev->sdev_dev); sdev->sdev_dev.parent = get_device(&sdev->sdev_gendev); sdev->sdev_dev.class = &sdev_class; - dev_set_name(&sdev->sdev_dev, "%d:%d:%d:%d", + dev_set_name(&sdev->sdev_dev, "%d:%d:%d:%llu", sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); sdev->scsi_level = starget->scsi_level; transport_setup_device(&sdev->sdev_gendev); diff --git a/drivers/scsi/scsi_tgt_if.c b/drivers/scsi/scsi_tgt_if.c deleted file mode 100644 index 6209110f295d..000000000000 --- a/drivers/scsi/scsi_tgt_if.c +++ /dev/null @@ -1,399 +0,0 @@ -/* - * SCSI target kernel/user interface functions - * - * Copyright (C) 2005 FUJITA Tomonori <tomof@acm.org> - * Copyright (C) 2005 Mike Christie <michaelc@cs.wisc.edu> - * - * 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. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ -#include <linux/miscdevice.h> -#include <linux/gfp.h> -#include <linux/file.h> -#include <linux/export.h> -#include <net/tcp.h> -#include <scsi/scsi.h> -#include <scsi/scsi_cmnd.h> -#include <scsi/scsi_device.h> -#include <scsi/scsi_host.h> -#include <scsi/scsi_tgt.h> -#include <scsi/scsi_tgt_if.h> - -#include <asm/cacheflush.h> - -#include "scsi_tgt_priv.h" - -#if TGT_RING_SIZE < PAGE_SIZE -# define TGT_RING_SIZE PAGE_SIZE -#endif - -#define TGT_RING_PAGES (TGT_RING_SIZE >> PAGE_SHIFT) -#define TGT_EVENT_PER_PAGE (PAGE_SIZE / sizeof(struct tgt_event)) -#define TGT_MAX_EVENTS (TGT_EVENT_PER_PAGE * TGT_RING_PAGES) - -struct tgt_ring { - u32 tr_idx; - unsigned long tr_pages[TGT_RING_PAGES]; - spinlock_t tr_lock; -}; - -/* tx_ring : kernel->user, rx_ring : user->kernel */ -static struct tgt_ring tx_ring, rx_ring; -static DECLARE_WAIT_QUEUE_HEAD(tgt_poll_wait); - -static inline void tgt_ring_idx_inc(struct tgt_ring *ring) -{ - if (ring->tr_idx == TGT_MAX_EVENTS - 1) - ring->tr_idx = 0; - else - ring->tr_idx++; -} - -static struct tgt_event *tgt_head_event(struct tgt_ring *ring, u32 idx) -{ - u32 pidx, off; - - pidx = idx / TGT_EVENT_PER_PAGE; - off = idx % TGT_EVENT_PER_PAGE; - - return (struct tgt_event *) - (ring->tr_pages[pidx] + sizeof(struct tgt_event) * off); -} - -static int tgt_uspace_send_event(u32 type, struct tgt_event *p) -{ - struct tgt_event *ev; - struct tgt_ring *ring = &tx_ring; - unsigned long flags; - int err = 0; - - spin_lock_irqsave(&ring->tr_lock, flags); - - ev = tgt_head_event(ring, ring->tr_idx); - if (!ev->hdr.status) - tgt_ring_idx_inc(ring); - else - err = -BUSY; - - spin_unlock_irqrestore(&ring->tr_lock, flags); - - if (err) - return err; - - memcpy(ev, p, sizeof(*ev)); - ev->hdr.type = type; - mb(); - ev->hdr.status = 1; - - flush_dcache_page(virt_to_page(ev)); - - wake_up_interruptible(&tgt_poll_wait); - - return 0; -} - -int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, u64 itn_id, - struct scsi_lun *lun, u64 tag) -{ - struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); - struct tgt_event ev; - int err; - - memset(&ev, 0, sizeof(ev)); - ev.p.cmd_req.host_no = shost->host_no; - ev.p.cmd_req.itn_id = itn_id; - ev.p.cmd_req.data_len = scsi_bufflen(cmd); - memcpy(ev.p.cmd_req.scb, cmd->cmnd, sizeof(ev.p.cmd_req.scb)); - memcpy(ev.p.cmd_req.lun, lun, sizeof(ev.p.cmd_req.lun)); - ev.p.cmd_req.attribute = cmd->tag; - ev.p.cmd_req.tag = tag; - - dprintk("%p %d %u %x %llx\n", cmd, shost->host_no, - ev.p.cmd_req.data_len, cmd->tag, - (unsigned long long) ev.p.cmd_req.tag); - - err = tgt_uspace_send_event(TGT_KEVENT_CMD_REQ, &ev); - if (err) - eprintk("tx buf is full, could not send\n"); - - return err; -} - -int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 itn_id, u64 tag) -{ - struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); - struct tgt_event ev; - int err; - - memset(&ev, 0, sizeof(ev)); - ev.p.cmd_done.host_no = shost->host_no; - ev.p.cmd_done.itn_id = itn_id; - ev.p.cmd_done.tag = tag; - ev.p.cmd_done.result = cmd->result; - - dprintk("%p %d %llu %u %x\n", cmd, shost->host_no, - (unsigned long long) ev.p.cmd_req.tag, - ev.p.cmd_req.data_len, cmd->tag); - - err = tgt_uspace_send_event(TGT_KEVENT_CMD_DONE, &ev); - if (err) - eprintk("tx buf is full, could not send\n"); - - return err; -} - -int scsi_tgt_uspace_send_tsk_mgmt(int host_no, u64 itn_id, int function, - u64 tag, struct scsi_lun *scsilun, void *data) -{ - struct tgt_event ev; - int err; - - memset(&ev, 0, sizeof(ev)); - ev.p.tsk_mgmt_req.host_no = host_no; - ev.p.tsk_mgmt_req.itn_id = itn_id; - ev.p.tsk_mgmt_req.function = function; - ev.p.tsk_mgmt_req.tag = tag; - memcpy(ev.p.tsk_mgmt_req.lun, scsilun, sizeof(ev.p.tsk_mgmt_req.lun)); - ev.p.tsk_mgmt_req.mid = (u64) (unsigned long) data; - - dprintk("%d %x %llx %llx\n", host_no, function, (unsigned long long) tag, - (unsigned long long) ev.p.tsk_mgmt_req.mid); - - err = tgt_uspace_send_event(TGT_KEVENT_TSK_MGMT_REQ, &ev); - if (err) - eprintk("tx buf is full, could not send\n"); - - return err; -} - -int scsi_tgt_uspace_send_it_nexus_request(int host_no, u64 itn_id, - int function, char *initiator_id) -{ - struct tgt_event ev; - int err; - - memset(&ev, 0, sizeof(ev)); - ev.p.it_nexus_req.host_no = host_no; - ev.p.it_nexus_req.function = function; - ev.p.it_nexus_req.itn_id = itn_id; - if (initiator_id) - strncpy(ev.p.it_nexus_req.initiator_id, initiator_id, - sizeof(ev.p.it_nexus_req.initiator_id)); - - dprintk("%d %x %llx\n", host_no, function, (unsigned long long)itn_id); - - err = tgt_uspace_send_event(TGT_KEVENT_IT_NEXUS_REQ, &ev); - if (err) - eprintk("tx buf is full, could not send\n"); - - return err; -} - -static int event_recv_msg(struct tgt_event *ev) -{ - int err = 0; - - switch (ev->hdr.type) { - case TGT_UEVENT_CMD_RSP: - err = scsi_tgt_kspace_exec(ev->p.cmd_rsp.host_no, - ev->p.cmd_rsp.itn_id, - ev->p.cmd_rsp.result, - ev->p.cmd_rsp.tag, - ev->p.cmd_rsp.uaddr, - ev->p.cmd_rsp.len, - ev->p.cmd_rsp.sense_uaddr, - ev->p.cmd_rsp.sense_len, - ev->p.cmd_rsp.rw); - break; - case TGT_UEVENT_TSK_MGMT_RSP: - err = scsi_tgt_kspace_tsk_mgmt(ev->p.tsk_mgmt_rsp.host_no, - ev->p.tsk_mgmt_rsp.itn_id, - ev->p.tsk_mgmt_rsp.mid, - ev->p.tsk_mgmt_rsp.result); - break; - case TGT_UEVENT_IT_NEXUS_RSP: - err = scsi_tgt_kspace_it_nexus_rsp(ev->p.it_nexus_rsp.host_no, - ev->p.it_nexus_rsp.itn_id, - ev->p.it_nexus_rsp.result); - break; - default: - eprintk("unknown type %d\n", ev->hdr.type); - err = -EINVAL; - } - - return err; -} - -static ssize_t tgt_write(struct file *file, const char __user * buffer, - size_t count, loff_t * ppos) -{ - struct tgt_event *ev; - struct tgt_ring *ring = &rx_ring; - - while (1) { - ev = tgt_head_event(ring, ring->tr_idx); - /* do we need this? */ - flush_dcache_page(virt_to_page(ev)); - - if (!ev->hdr.status) - break; - - tgt_ring_idx_inc(ring); - event_recv_msg(ev); - ev->hdr.status = 0; - }; - - return count; -} - -static unsigned int tgt_poll(struct file * file, struct poll_table_struct *wait) -{ - struct tgt_event *ev; - struct tgt_ring *ring = &tx_ring; - unsigned long flags; - unsigned int mask = 0; - u32 idx; - - poll_wait(file, &tgt_poll_wait, wait); - - spin_lock_irqsave(&ring->tr_lock, flags); - - idx = ring->tr_idx ? ring->tr_idx - 1 : TGT_MAX_EVENTS - 1; - ev = tgt_head_event(ring, idx); - if (ev->hdr.status) - mask |= POLLIN | POLLRDNORM; - - spin_unlock_irqrestore(&ring->tr_lock, flags); - - return mask; -} - -static int uspace_ring_map(struct vm_area_struct *vma, unsigned long addr, - struct tgt_ring *ring) -{ - int i, err; - - for (i = 0; i < TGT_RING_PAGES; i++) { - struct page *page = virt_to_page(ring->tr_pages[i]); - err = vm_insert_page(vma, addr, page); - if (err) - return err; - addr += PAGE_SIZE; - } - - return 0; -} - -static int tgt_mmap(struct file *filp, struct vm_area_struct *vma) -{ - unsigned long addr; - int err; - - if (vma->vm_pgoff) - return -EINVAL; - - if (vma->vm_end - vma->vm_start != TGT_RING_SIZE * 2) { - eprintk("mmap size must be %lu, not %lu \n", - TGT_RING_SIZE * 2, vma->vm_end - vma->vm_start); - return -EINVAL; - } - - addr = vma->vm_start; - err = uspace_ring_map(vma, addr, &tx_ring); - if (err) - return err; - err = uspace_ring_map(vma, addr + TGT_RING_SIZE, &rx_ring); - - return err; -} - -static int tgt_open(struct inode *inode, struct file *file) -{ - tx_ring.tr_idx = rx_ring.tr_idx = 0; - - return 0; -} - -static const struct file_operations tgt_fops = { - .owner = THIS_MODULE, - .open = tgt_open, - .poll = tgt_poll, - .write = tgt_write, - .mmap = tgt_mmap, - .llseek = noop_llseek, -}; - -static struct miscdevice tgt_miscdev = { - .minor = MISC_DYNAMIC_MINOR, - .name = "tgt", - .fops = &tgt_fops, -}; - -static void tgt_ring_exit(struct tgt_ring *ring) -{ - int i; - - for (i = 0; i < TGT_RING_PAGES; i++) - free_page(ring->tr_pages[i]); -} - -static int tgt_ring_init(struct tgt_ring *ring) -{ - int i; - - spin_lock_init(&ring->tr_lock); - - for (i = 0; i < TGT_RING_PAGES; i++) { - ring->tr_pages[i] = get_zeroed_page(GFP_KERNEL); - if (!ring->tr_pages[i]) { - eprintk("out of memory\n"); - return -ENOMEM; - } - } - - return 0; -} - -void scsi_tgt_if_exit(void) -{ - tgt_ring_exit(&tx_ring); - tgt_ring_exit(&rx_ring); - misc_deregister(&tgt_miscdev); -} - -int scsi_tgt_if_init(void) -{ - int err; - - err = tgt_ring_init(&tx_ring); - if (err) - return err; - - err = tgt_ring_init(&rx_ring); - if (err) - goto free_tx_ring; - - err = misc_register(&tgt_miscdev); - if (err) - goto free_rx_ring; - - return 0; -free_rx_ring: - tgt_ring_exit(&rx_ring); -free_tx_ring: - tgt_ring_exit(&tx_ring); - - return err; -} diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c deleted file mode 100644 index e51add05fb8d..000000000000 --- a/drivers/scsi/scsi_tgt_lib.c +++ /dev/null @@ -1,661 +0,0 @@ -/* - * SCSI target lib functions - * - * Copyright (C) 2005 Mike Christie <michaelc@cs.wisc.edu> - * Copyright (C) 2005 FUJITA Tomonori <tomof@acm.org> - * - * 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. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ -#include <linux/blkdev.h> -#include <linux/hash.h> -#include <linux/module.h> -#include <linux/pagemap.h> -#include <linux/slab.h> -#include <scsi/scsi.h> -#include <scsi/scsi_cmnd.h> -#include <scsi/scsi_device.h> -#include <scsi/scsi_host.h> -#include <scsi/scsi_transport.h> -#include <scsi/scsi_tgt.h> - -#include "scsi_tgt_priv.h" - -static struct workqueue_struct *scsi_tgtd; -static struct kmem_cache *scsi_tgt_cmd_cache; - -/* - * TODO: this struct will be killed when the block layer supports large bios - * and James's work struct code is in - */ -struct scsi_tgt_cmd { - /* TODO replace work with James b's code */ - struct work_struct work; - /* TODO fix limits of some drivers */ - struct bio *bio; - - struct list_head hash_list; - struct request *rq; - u64 itn_id; - u64 tag; -}; - -#define TGT_HASH_ORDER 4 -#define cmd_hashfn(tag) hash_long((unsigned long) (tag), TGT_HASH_ORDER) - -struct scsi_tgt_queuedata { - struct Scsi_Host *shost; - struct list_head cmd_hash[1 << TGT_HASH_ORDER]; - spinlock_t cmd_hash_lock; -}; - -/* - * Function: scsi_host_get_command() - * - * Purpose: Allocate and setup a scsi command block and blk request - * - * Arguments: shost - scsi host - * data_dir - dma data dir - * gfp_mask- allocator flags - * - * Returns: The allocated scsi command structure. - * - * This should be called by target LLDs to get a command. - */ -struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *shost, - enum dma_data_direction data_dir, - gfp_t gfp_mask) -{ - int write = (data_dir == DMA_TO_DEVICE); - struct request *rq; - struct scsi_cmnd *cmd; - struct scsi_tgt_cmd *tcmd; - - /* Bail if we can't get a reference to the device */ - if (!get_device(&shost->shost_gendev)) - return NULL; - - tcmd = kmem_cache_alloc(scsi_tgt_cmd_cache, GFP_ATOMIC); - if (!tcmd) - goto put_dev; - - /* - * The blk helpers are used to the READ/WRITE requests - * transferring data from a initiator point of view. Since - * we are in target mode we want the opposite. - */ - rq = blk_get_request(shost->uspace_req_q, !write, gfp_mask); - if (!rq) - goto free_tcmd; - - cmd = __scsi_get_command(shost, gfp_mask); - if (!cmd) - goto release_rq; - - cmd->sc_data_direction = data_dir; - cmd->jiffies_at_alloc = jiffies; - cmd->request = rq; - - cmd->cmnd = rq->cmd; - - rq->special = cmd; - rq->cmd_type = REQ_TYPE_SPECIAL; - rq->cmd_flags |= REQ_TYPE_BLOCK_PC; - rq->end_io_data = tcmd; - - tcmd->rq = rq; - - return cmd; - -release_rq: - blk_put_request(rq); -free_tcmd: - kmem_cache_free(scsi_tgt_cmd_cache, tcmd); -put_dev: - put_device(&shost->shost_gendev); - return NULL; - -} -EXPORT_SYMBOL_GPL(scsi_host_get_command); - -/* - * Function: scsi_host_put_command() - * - * Purpose: Free a scsi command block - * - * Arguments: shost - scsi host - * cmd - command block to free - * - * Returns: Nothing. - * - * Notes: The command must not belong to any lists. - */ -void scsi_host_put_command(struct Scsi_Host *shost, struct scsi_cmnd *cmd) -{ - struct request_queue *q = shost->uspace_req_q; - struct request *rq = cmd->request; - struct scsi_tgt_cmd *tcmd = rq->end_io_data; - unsigned long flags; - - kmem_cache_free(scsi_tgt_cmd_cache, tcmd); - - spin_lock_irqsave(q->queue_lock, flags); - __blk_put_request(q, rq); - spin_unlock_irqrestore(q->queue_lock, flags); - - __scsi_put_command(shost, cmd); - put_device(&shost->shost_gendev); -} -EXPORT_SYMBOL_GPL(scsi_host_put_command); - -static void cmd_hashlist_del(struct scsi_cmnd *cmd) -{ - struct request_queue *q = cmd->request->q; - struct scsi_tgt_queuedata *qdata = q->queuedata; - unsigned long flags; - struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; - - spin_lock_irqsave(&qdata->cmd_hash_lock, flags); - list_del(&tcmd->hash_list); - spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); -} - -static void scsi_unmap_user_pages(struct scsi_tgt_cmd *tcmd) -{ - blk_rq_unmap_user(tcmd->bio); -} - -static void scsi_tgt_cmd_destroy(struct work_struct *work) -{ - struct scsi_tgt_cmd *tcmd = - container_of(work, struct scsi_tgt_cmd, work); - struct scsi_cmnd *cmd = tcmd->rq->special; - - dprintk("cmd %p %d %u\n", cmd, cmd->sc_data_direction, - rq_data_dir(cmd->request)); - scsi_unmap_user_pages(tcmd); - tcmd->rq->bio = NULL; - scsi_host_put_command(scsi_tgt_cmd_to_host(cmd), cmd); -} - -static void init_scsi_tgt_cmd(struct request *rq, struct scsi_tgt_cmd *tcmd, - u64 itn_id, u64 tag) -{ - struct scsi_tgt_queuedata *qdata = rq->q->queuedata; - unsigned long flags; - struct list_head *head; - - tcmd->itn_id = itn_id; - tcmd->tag = tag; - tcmd->bio = NULL; - INIT_WORK(&tcmd->work, scsi_tgt_cmd_destroy); - spin_lock_irqsave(&qdata->cmd_hash_lock, flags); - head = &qdata->cmd_hash[cmd_hashfn(tag)]; - list_add(&tcmd->hash_list, head); - spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); -} - -/* - * scsi_tgt_alloc_queue - setup queue used for message passing - * shost: scsi host - * - * This should be called by the LLD after host allocation. - * And will be released when the host is released. - */ -int scsi_tgt_alloc_queue(struct Scsi_Host *shost) -{ - struct scsi_tgt_queuedata *queuedata; - struct request_queue *q; - int err, i; - - /* - * Do we need to send a netlink event or should uspace - * just respond to the hotplug event? - */ - q = __scsi_alloc_queue(shost, NULL); - if (!q) - return -ENOMEM; - - queuedata = kzalloc(sizeof(*queuedata), GFP_KERNEL); - if (!queuedata) { - err = -ENOMEM; - goto cleanup_queue; - } - queuedata->shost = shost; - q->queuedata = queuedata; - - /* - * this is a silly hack. We should probably just queue as many - * command as is recvd to userspace. uspace can then make - * sure we do not overload the HBA - */ - q->nr_requests = shost->can_queue; - /* - * We currently only support software LLDs so this does - * not matter for now. Do we need this for the cards we support? - * If so we should make it a host template value. - */ - blk_queue_dma_alignment(q, 0); - shost->uspace_req_q = q; - - for (i = 0; i < ARRAY_SIZE(queuedata->cmd_hash); i++) - INIT_LIST_HEAD(&queuedata->cmd_hash[i]); - spin_lock_init(&queuedata->cmd_hash_lock); - - return 0; - -cleanup_queue: - blk_cleanup_queue(q); - return err; -} -EXPORT_SYMBOL_GPL(scsi_tgt_alloc_queue); - -void scsi_tgt_free_queue(struct Scsi_Host *shost) -{ - int i; - unsigned long flags; - struct request_queue *q = shost->uspace_req_q; - struct scsi_cmnd *cmd; - struct scsi_tgt_queuedata *qdata = q->queuedata; - struct scsi_tgt_cmd *tcmd, *n; - LIST_HEAD(cmds); - - spin_lock_irqsave(&qdata->cmd_hash_lock, flags); - - for (i = 0; i < ARRAY_SIZE(qdata->cmd_hash); i++) { - list_for_each_entry_safe(tcmd, n, &qdata->cmd_hash[i], - hash_list) - list_move(&tcmd->hash_list, &cmds); - } - - spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); - - while (!list_empty(&cmds)) { - tcmd = list_entry(cmds.next, struct scsi_tgt_cmd, hash_list); - list_del(&tcmd->hash_list); - cmd = tcmd->rq->special; - - shost->hostt->eh_abort_handler(cmd); - scsi_tgt_cmd_destroy(&tcmd->work); - } -} -EXPORT_SYMBOL_GPL(scsi_tgt_free_queue); - -struct Scsi_Host *scsi_tgt_cmd_to_host(struct scsi_cmnd *cmd) -{ - struct scsi_tgt_queuedata *queue = cmd->request->q->queuedata; - return queue->shost; -} -EXPORT_SYMBOL_GPL(scsi_tgt_cmd_to_host); - -/* - * scsi_tgt_queue_command - queue command for userspace processing - * @cmd: scsi command - * @scsilun: scsi lun - * @tag: unique value to identify this command for tmf - */ -int scsi_tgt_queue_command(struct scsi_cmnd *cmd, u64 itn_id, - struct scsi_lun *scsilun, u64 tag) -{ - struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; - int err; - - init_scsi_tgt_cmd(cmd->request, tcmd, itn_id, tag); - err = scsi_tgt_uspace_send_cmd(cmd, itn_id, scsilun, tag); - if (err) - cmd_hashlist_del(cmd); - - return err; -} -EXPORT_SYMBOL_GPL(scsi_tgt_queue_command); - -/* - * This is run from a interrupt handler normally and the unmap - * needs process context so we must queue - */ -static void scsi_tgt_cmd_done(struct scsi_cmnd *cmd) -{ - struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; - - dprintk("cmd %p %u\n", cmd, rq_data_dir(cmd->request)); - - scsi_tgt_uspace_send_status(cmd, tcmd->itn_id, tcmd->tag); - - scsi_release_buffers(cmd); - - queue_work(scsi_tgtd, &tcmd->work); -} - -static int scsi_tgt_transfer_response(struct scsi_cmnd *cmd) -{ - struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); - int err; - - dprintk("cmd %p %u\n", cmd, rq_data_dir(cmd->request)); - - err = shost->hostt->transfer_response(cmd, scsi_tgt_cmd_done); - switch (err) { - case SCSI_MLQUEUE_HOST_BUSY: - case SCSI_MLQUEUE_DEVICE_BUSY: - return -EAGAIN; - } - return 0; -} - -/* TODO: test this crap and replace bio_map_user with new interface maybe */ -static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd, - unsigned long uaddr, unsigned int len, int rw) -{ - struct request_queue *q = cmd->request->q; - struct request *rq = cmd->request; - int err; - - dprintk("%lx %u\n", uaddr, len); - err = blk_rq_map_user(q, rq, NULL, (void *)uaddr, len, GFP_KERNEL); - if (err) { - /* - * TODO: need to fixup sg_tablesize, max_segment_size, - * max_sectors, etc for modern HW and software drivers - * where this value is bogus. - * - * TODO2: we can alloc a reserve buffer of max size - * we can handle and do the slow copy path for really large - * IO. - */ - eprintk("Could not handle request of size %u.\n", len); - return err; - } - - tcmd->bio = rq->bio; - err = scsi_init_io(cmd, GFP_KERNEL); - if (err) { - scsi_release_buffers(cmd); - goto unmap_rq; - } - /* - * we use REQ_TYPE_BLOCK_PC so scsi_init_io doesn't set the - * length for us. - */ - cmd->sdb.length = blk_rq_bytes(rq); - - return 0; - -unmap_rq: - scsi_unmap_user_pages(tcmd); - return err; -} - -static int scsi_tgt_copy_sense(struct scsi_cmnd *cmd, unsigned long uaddr, - unsigned len) -{ - char __user *p = (char __user *) uaddr; - - if (copy_from_user(cmd->sense_buffer, p, - min_t(unsigned, SCSI_SENSE_BUFFERSIZE, len))) { - printk(KERN_ERR "Could not copy the sense buffer\n"); - return -EIO; - } - return 0; -} - -static int scsi_tgt_abort_cmd(struct Scsi_Host *shost, struct scsi_cmnd *cmd) -{ - struct scsi_tgt_cmd *tcmd; - int err; - - err = shost->hostt->eh_abort_handler(cmd); - if (err) - eprintk("fail to abort %p\n", cmd); - - tcmd = cmd->request->end_io_data; - scsi_tgt_cmd_destroy(&tcmd->work); - return err; -} - -static struct request *tgt_cmd_hash_lookup(struct request_queue *q, u64 tag) -{ - struct scsi_tgt_queuedata *qdata = q->queuedata; - struct request *rq = NULL; - struct list_head *head; - struct scsi_tgt_cmd *tcmd; - unsigned long flags; - - head = &qdata->cmd_hash[cmd_hashfn(tag)]; - spin_lock_irqsave(&qdata->cmd_hash_lock, flags); - list_for_each_entry(tcmd, head, hash_list) { - if (tcmd->tag == tag) { - rq = tcmd->rq; - list_del(&tcmd->hash_list); - break; - } - } - spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); - - return rq; -} - -int scsi_tgt_kspace_exec(int host_no, u64 itn_id, int result, u64 tag, - unsigned long uaddr, u32 len, unsigned long sense_uaddr, - u32 sense_len, u8 rw) -{ - struct Scsi_Host *shost; - struct scsi_cmnd *cmd; - struct request *rq; - struct scsi_tgt_cmd *tcmd; - int err = 0; - - dprintk("%d %llu %d %u %lx %u\n", host_no, (unsigned long long) tag, - result, len, uaddr, rw); - - /* TODO: replace with a O(1) alg */ - shost = scsi_host_lookup(host_no); - if (!shost) { - printk(KERN_ERR "Could not find host no %d\n", host_no); - return -EINVAL; - } - - if (!shost->uspace_req_q) { - printk(KERN_ERR "Not target scsi host %d\n", host_no); - goto done; - } - - rq = tgt_cmd_hash_lookup(shost->uspace_req_q, tag); - if (!rq) { - printk(KERN_ERR "Could not find tag %llu\n", - (unsigned long long) tag); - err = -EINVAL; - goto done; - } - cmd = rq->special; - - dprintk("cmd %p scb %x result %d len %d bufflen %u %u %x\n", - cmd, cmd->cmnd[0], result, len, scsi_bufflen(cmd), - rq_data_dir(rq), cmd->cmnd[0]); - - if (result == TASK_ABORTED) { - scsi_tgt_abort_cmd(shost, cmd); - goto done; - } - /* - * store the userspace values here, the working values are - * in the request_* values - */ - tcmd = cmd->request->end_io_data; - cmd->result = result; - - if (cmd->result == SAM_STAT_CHECK_CONDITION) - scsi_tgt_copy_sense(cmd, sense_uaddr, sense_len); - - if (len) { - err = scsi_map_user_pages(rq->end_io_data, cmd, uaddr, len, rw); - if (err) { - /* - * user-space daemon bugs or OOM - * TODO: we can do better for OOM. - */ - struct scsi_tgt_queuedata *qdata; - struct list_head *head; - unsigned long flags; - - eprintk("cmd %p ret %d uaddr %lx len %d rw %d\n", - cmd, err, uaddr, len, rw); - - qdata = shost->uspace_req_q->queuedata; - head = &qdata->cmd_hash[cmd_hashfn(tcmd->tag)]; - - spin_lock_irqsave(&qdata->cmd_hash_lock, flags); - list_add(&tcmd->hash_list, head); - spin_unlock_irqrestore(&qdata->cmd_hash_lock, flags); - - goto done; - } - } - err = scsi_tgt_transfer_response(cmd); -done: - scsi_host_put(shost); - return err; -} - -int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *shost, u64 itn_id, - int function, u64 tag, struct scsi_lun *scsilun, - void *data) -{ - int err; - - /* TODO: need to retry if this fails. */ - err = scsi_tgt_uspace_send_tsk_mgmt(shost->host_no, itn_id, - function, tag, scsilun, data); - if (err < 0) - eprintk("The task management request lost!\n"); - return err; -} -EXPORT_SYMBOL_GPL(scsi_tgt_tsk_mgmt_request); - -int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 itn_id, u64 mid, int result) -{ - struct Scsi_Host *shost; - int err = -EINVAL; - - dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid); - - shost = scsi_host_lookup(host_no); - if (!shost) { - printk(KERN_ERR "Could not find host no %d\n", host_no); - return err; - } - - if (!shost->uspace_req_q) { - printk(KERN_ERR "Not target scsi host %d\n", host_no); - goto done; - } - - err = shost->transportt->tsk_mgmt_response(shost, itn_id, mid, result); -done: - scsi_host_put(shost); - return err; -} - -int scsi_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, - char *initiator) -{ - int err; - - /* TODO: need to retry if this fails. */ - err = scsi_tgt_uspace_send_it_nexus_request(shost->host_no, itn_id, 0, - initiator); - if (err < 0) - eprintk("The i_t_neuxs request lost, %d %llx!\n", - shost->host_no, (unsigned long long)itn_id); - return err; -} -EXPORT_SYMBOL_GPL(scsi_tgt_it_nexus_create); - -int scsi_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) -{ - int err; - - /* TODO: need to retry if this fails. */ - err = scsi_tgt_uspace_send_it_nexus_request(shost->host_no, - itn_id, 1, NULL); - if (err < 0) - eprintk("The i_t_neuxs request lost, %d %llx!\n", - shost->host_no, (unsigned long long)itn_id); - return err; -} -EXPORT_SYMBOL_GPL(scsi_tgt_it_nexus_destroy); - -int scsi_tgt_kspace_it_nexus_rsp(int host_no, u64 itn_id, int result) -{ - struct Scsi_Host *shost; - int err = -EINVAL; - - dprintk("%d %d%llx\n", host_no, result, (unsigned long long)itn_id); - - shost = scsi_host_lookup(host_no); - if (!shost) { - printk(KERN_ERR "Could not find host no %d\n", host_no); - return err; - } - - if (!shost->uspace_req_q) { - printk(KERN_ERR "Not target scsi host %d\n", host_no); - goto done; - } - - err = shost->transportt->it_nexus_response(shost, itn_id, result); -done: - scsi_host_put(shost); - return err; -} - -static int __init scsi_tgt_init(void) -{ - int err; - - scsi_tgt_cmd_cache = KMEM_CACHE(scsi_tgt_cmd, 0); - if (!scsi_tgt_cmd_cache) - return -ENOMEM; - - scsi_tgtd = alloc_workqueue("scsi_tgtd", 0, 1); - if (!scsi_tgtd) { - err = -ENOMEM; - goto free_kmemcache; - } - - err = scsi_tgt_if_init(); - if (err) - goto destroy_wq; - - return 0; - -destroy_wq: - destroy_workqueue(scsi_tgtd); -free_kmemcache: - kmem_cache_destroy(scsi_tgt_cmd_cache); - return err; -} - -static void __exit scsi_tgt_exit(void) -{ - destroy_workqueue(scsi_tgtd); - scsi_tgt_if_exit(); - kmem_cache_destroy(scsi_tgt_cmd_cache); -} - -module_init(scsi_tgt_init); -module_exit(scsi_tgt_exit); - -MODULE_DESCRIPTION("SCSI target core"); -MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/scsi_tgt_priv.h b/drivers/scsi/scsi_tgt_priv.h deleted file mode 100644 index fe4c62177f78..000000000000 --- a/drivers/scsi/scsi_tgt_priv.h +++ /dev/null @@ -1,32 +0,0 @@ -struct scsi_cmnd; -struct scsi_lun; -struct Scsi_Host; -struct task_struct; - -/* tmp - will replace with SCSI logging stuff */ -#define eprintk(fmt, args...) \ -do { \ - printk("%s(%d) " fmt, __func__, __LINE__, ##args); \ -} while (0) - -#define dprintk(fmt, args...) -/* #define dprintk eprintk */ - -extern void scsi_tgt_if_exit(void); -extern int scsi_tgt_if_init(void); - -extern int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, u64 it_nexus_id, - struct scsi_lun *lun, u64 tag); -extern int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 it_nexus_id, - u64 tag); -extern int scsi_tgt_kspace_exec(int host_no, u64 it_nexus_id, int result, u64 tag, - unsigned long uaddr, u32 len, - unsigned long sense_uaddr, u32 sense_len, u8 rw); -extern int scsi_tgt_uspace_send_tsk_mgmt(int host_no, u64 it_nexus_id, - int function, u64 tag, - struct scsi_lun *scsilun, void *data); -extern int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 it_nexus_id, - u64 mid, int result); -extern int scsi_tgt_uspace_send_it_nexus_request(int host_no, u64 it_nexus_id, - int function, char *initiator); -extern int scsi_tgt_kspace_it_nexus_rsp(int host_no, u64 it_nexus_id, int result); diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 521f5838594b..5d6f348eb3d8 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -39,7 +39,6 @@ #include <scsi/scsi_netlink_fc.h> #include <scsi/scsi_bsg_fc.h> #include "scsi_priv.h" -#include "scsi_transport_fc_internal.h" static int fc_queue_work(struct Scsi_Host *, struct work_struct *); static void fc_vport_sched_delete(struct work_struct *work); @@ -262,6 +261,10 @@ static const struct { { FC_PORTSPEED_8GBIT, "8 Gbit" }, { FC_PORTSPEED_16GBIT, "16 Gbit" }, { FC_PORTSPEED_32GBIT, "32 Gbit" }, + { FC_PORTSPEED_20GBIT, "20 Gbit" }, + { FC_PORTSPEED_40GBIT, "40 Gbit" }, + { FC_PORTSPEED_50GBIT, "50 Gbit" }, + { FC_PORTSPEED_100GBIT, "100 Gbit" }, { FC_PORTSPEED_NOT_NEGOTIATED, "Not Negotiated" }, }; fc_bitfield_name_search(port_speed, fc_port_speed_names) @@ -2089,7 +2092,7 @@ fc_timed_out(struct scsi_cmnd *scmd) * on the rport. */ static void -fc_user_scan_tgt(struct Scsi_Host *shost, uint channel, uint id, uint lun) +fc_user_scan_tgt(struct Scsi_Host *shost, uint channel, uint id, u64 lun) { struct fc_rport *rport; unsigned long flags; @@ -2121,7 +2124,7 @@ fc_user_scan_tgt(struct Scsi_Host *shost, uint channel, uint id, uint lun) * object as the parent. */ static int -fc_user_scan(struct Scsi_Host *shost, uint channel, uint id, uint lun) +fc_user_scan(struct Scsi_Host *shost, uint channel, uint id, u64 lun) { uint chlo, chhi; uint tgtlo, tgthi; @@ -3008,10 +3011,6 @@ fc_remote_port_delete(struct fc_rport *rport) spin_unlock_irqrestore(shost->host_lock, flags); - if (rport->roles & FC_PORT_ROLE_FCP_INITIATOR && - shost->active_mode & MODE_TARGET) - fc_tgt_it_nexus_destroy(shost, (unsigned long)rport); - scsi_target_block(&rport->dev); /* see if we need to kill io faster than waiting for device loss */ @@ -3052,7 +3051,6 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles) struct fc_host_attrs *fc_host = shost_to_fc_host(shost); unsigned long flags; int create = 0; - int ret; spin_lock_irqsave(shost->host_lock, flags); if (roles & FC_PORT_ROLE_FCP_TARGET) { @@ -3061,12 +3059,6 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles) create = 1; } else if (!(rport->roles & FC_PORT_ROLE_FCP_TARGET)) create = 1; - } else if (shost->active_mode & MODE_TARGET) { - ret = fc_tgt_it_nexus_create(shost, (unsigned long)rport, - (char *)&rport->node_name); - if (ret) - printk(KERN_ERR "FC Remore Port tgt nexus failed %d\n", - ret); } rport->roles = roles; diff --git a/drivers/scsi/scsi_transport_fc_internal.h b/drivers/scsi/scsi_transport_fc_internal.h deleted file mode 100644 index e7bfbe751c1f..000000000000 --- a/drivers/scsi/scsi_transport_fc_internal.h +++ /dev/null @@ -1,26 +0,0 @@ -#include <scsi/scsi_tgt.h> - -#ifdef CONFIG_SCSI_FC_TGT_ATTRS -static inline int fc_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, - char *initiator) -{ - return scsi_tgt_it_nexus_create(shost, itn_id, initiator); -} - -static inline int fc_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) -{ - return scsi_tgt_it_nexus_destroy(shost, itn_id); -} -#else -static inline int fc_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, - char *initiator) -{ - return 0; -} - -static inline int fc_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) -{ - return 0; -} - -#endif diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 0102a2d70dd8..b481e62a12cc 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -1780,7 +1780,7 @@ EXPORT_SYMBOL_GPL(iscsi_scan_finished); struct iscsi_scan_data { unsigned int channel; unsigned int id; - unsigned int lun; + u64 lun; }; static int iscsi_user_scan_session(struct device *dev, void *data) @@ -1827,7 +1827,7 @@ user_scan_exit: } static int iscsi_user_scan(struct Scsi_Host *shost, uint channel, - uint id, uint lun) + uint id, u64 lun) { struct iscsi_scan_data scan_data; @@ -3059,7 +3059,7 @@ iscsi_get_chap(struct iscsi_transport *transport, struct nlmsghdr *nlh) evchap->u.get_chap.host_no = ev->u.get_chap.host_no; evchap->u.get_chap.chap_tbl_idx = ev->u.get_chap.chap_tbl_idx; evchap->u.get_chap.num_entries = ev->u.get_chap.num_entries; - buf = (char *) ((char *)evchap + sizeof(*evchap)); + buf = (char *)evchap + sizeof(*evchap); memset(buf, 0, chap_buf_size); err = transport->get_chap(shost, ev->u.get_chap.chap_tbl_idx, @@ -3463,7 +3463,7 @@ iscsi_get_host_stats(struct iscsi_transport *transport, struct nlmsghdr *nlh) evhost_stats->type = nlh->nlmsg_type; evhost_stats->u.get_host_stats.host_no = ev->u.get_host_stats.host_no; - buf = (char *)((char *)evhost_stats + sizeof(*evhost_stats)); + buf = (char *)evhost_stats + sizeof(*evhost_stats); memset(buf, 0, host_stats_size); err = transport->get_host_stats(shost, buf, host_stats_size); diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index c341f855fadc..9a058194b9bd 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c @@ -1705,7 +1705,7 @@ EXPORT_SYMBOL(scsi_is_sas_rphy); */ static int sas_user_scan(struct Scsi_Host *shost, uint channel, - uint id, uint lun) + uint id, u64 lun) { struct sas_host_attrs *sas_host = to_sas_host_attrs(shost); struct sas_rphy *rphy; diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c index 13e898332e45..43fea2219f83 100644 --- a/drivers/scsi/scsi_transport_srp.c +++ b/drivers/scsi/scsi_transport_srp.c @@ -33,7 +33,6 @@ #include <scsi/scsi_transport.h> #include <scsi/scsi_transport_srp.h> #include "scsi_priv.h" -#include "scsi_transport_srp_internal.h" struct srp_host_attrs { atomic_t next_port_id; @@ -746,18 +745,6 @@ struct srp_rport *srp_rport_add(struct Scsi_Host *shost, return ERR_PTR(ret); } - if (shost->active_mode & MODE_TARGET && - ids->roles == SRP_RPORT_ROLE_INITIATOR) { - ret = srp_tgt_it_nexus_create(shost, (unsigned long)rport, - rport->port_id); - if (ret) { - device_del(&rport->dev); - transport_destroy_device(&rport->dev); - put_device(&rport->dev); - return ERR_PTR(ret); - } - } - transport_add_device(&rport->dev); transport_configure_device(&rport->dev); @@ -774,11 +761,6 @@ EXPORT_SYMBOL_GPL(srp_rport_add); void srp_rport_del(struct srp_rport *rport) { struct device *dev = &rport->dev; - struct Scsi_Host *shost = dev_to_shost(dev->parent); - - if (shost->active_mode & MODE_TARGET && - rport->roles == SRP_RPORT_ROLE_INITIATOR) - srp_tgt_it_nexus_destroy(shost, (unsigned long)rport); transport_remove_device(dev); device_del(dev); diff --git a/drivers/scsi/scsi_transport_srp_internal.h b/drivers/scsi/scsi_transport_srp_internal.h deleted file mode 100644 index 8a79747f9f3d..000000000000 --- a/drivers/scsi/scsi_transport_srp_internal.h +++ /dev/null @@ -1,25 +0,0 @@ -#include <scsi/scsi_tgt.h> - -#ifdef CONFIG_SCSI_SRP_TGT_ATTRS -static inline int srp_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, - char *initiator) -{ - return scsi_tgt_it_nexus_create(shost, itn_id, initiator); -} - -static inline int srp_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) -{ - return scsi_tgt_it_nexus_destroy(shost, itn_id); -} - -#else -static inline int srp_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, - char *initiator) -{ - return 0; -} -static inline int srp_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) -{ - return 0; -} -#endif diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 6825eda1114a..2c2041ca4b70 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -134,6 +134,19 @@ static const char *sd_cache_types[] = { "write back, no read (daft)" }; +static void sd_set_flush_flag(struct scsi_disk *sdkp) +{ + unsigned flush = 0; + + if (sdkp->WCE) { + flush |= REQ_FLUSH; + if (sdkp->DPOFUA) + flush |= REQ_FUA; + } + + blk_queue_flush(sdkp->disk->queue, flush); +} + static ssize_t cache_type_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -177,6 +190,7 @@ cache_type_store(struct device *dev, struct device_attribute *attr, if (sdkp->cache_override) { sdkp->WCE = wce; sdkp->RCD = rcd; + sd_set_flush_flag(sdkp); return count; } @@ -677,8 +691,10 @@ static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode) * Will issue either UNMAP or WRITE SAME(16) depending on preference * indicated by target device. **/ -static int sd_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) +static int sd_setup_discard_cmnd(struct scsi_cmnd *cmd) { + struct request *rq = cmd->request; + struct scsi_device *sdp = cmd->device; struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); sector_t sector = blk_rq_pos(rq); unsigned int nr_sectors = blk_rq_sectors(rq); @@ -690,9 +706,6 @@ static int sd_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) sector >>= ilog2(sdp->sector_size) - 9; nr_sectors >>= ilog2(sdp->sector_size) - 9; - rq->timeout = SD_TIMEOUT; - - memset(rq->cmd, 0, rq->cmd_len); page = alloc_page(GFP_ATOMIC | __GFP_ZERO); if (!page) @@ -702,9 +715,9 @@ static int sd_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) case SD_LBP_UNMAP: buf = page_address(page); - rq->cmd_len = 10; - rq->cmd[0] = UNMAP; - rq->cmd[8] = 24; + cmd->cmd_len = 10; + cmd->cmnd[0] = UNMAP; + cmd->cmnd[8] = 24; put_unaligned_be16(6 + 16, &buf[0]); put_unaligned_be16(16, &buf[2]); @@ -715,23 +728,23 @@ static int sd_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) break; case SD_LBP_WS16: - rq->cmd_len = 16; - rq->cmd[0] = WRITE_SAME_16; - rq->cmd[1] = 0x8; /* UNMAP */ - put_unaligned_be64(sector, &rq->cmd[2]); - put_unaligned_be32(nr_sectors, &rq->cmd[10]); + cmd->cmd_len = 16; + cmd->cmnd[0] = WRITE_SAME_16; + cmd->cmnd[1] = 0x8; /* UNMAP */ + put_unaligned_be64(sector, &cmd->cmnd[2]); + put_unaligned_be32(nr_sectors, &cmd->cmnd[10]); len = sdkp->device->sector_size; break; case SD_LBP_WS10: case SD_LBP_ZERO: - rq->cmd_len = 10; - rq->cmd[0] = WRITE_SAME; + cmd->cmd_len = 10; + cmd->cmnd[0] = WRITE_SAME; if (sdkp->provisioning_mode == SD_LBP_WS10) - rq->cmd[1] = 0x8; /* UNMAP */ - put_unaligned_be32(sector, &rq->cmd[2]); - put_unaligned_be16(nr_sectors, &rq->cmd[7]); + cmd->cmnd[1] = 0x8; /* UNMAP */ + put_unaligned_be32(sector, &cmd->cmnd[2]); + put_unaligned_be16(nr_sectors, &cmd->cmnd[7]); len = sdkp->device->sector_size; break; @@ -742,8 +755,21 @@ static int sd_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) } rq->completion_data = page; + rq->timeout = SD_TIMEOUT; + + cmd->transfersize = len; + cmd->allowed = SD_MAX_RETRIES; + + /* + * Initially __data_len is set to the amount of data that needs to be + * transferred to the target. This amount depends on whether WRITE SAME + * or UNMAP is being used. After the scatterlist has been mapped by + * scsi_init_io() we set __data_len to the size of the area to be + * discarded on disk. This allows us to report completion on the full + * amount of blocks described by the request. + */ blk_add_request_payload(rq, page, len); - ret = scsi_setup_blk_pc_cmnd(sdp, rq); + ret = scsi_init_io(cmd, GFP_ATOMIC); rq->__data_len = nr_bytes; out: @@ -785,14 +811,15 @@ out: /** * sd_setup_write_same_cmnd - write the same data to multiple blocks - * @sdp: scsi device to operate one - * @rq: Request to prepare + * @cmd: command to prepare * * Will issue either WRITE SAME(10) or WRITE SAME(16) depending on * preference indicated by target device. **/ -static int sd_setup_write_same_cmnd(struct scsi_device *sdp, struct request *rq) +static int sd_setup_write_same_cmnd(struct scsi_cmnd *cmd) { + struct request *rq = cmd->request; + struct scsi_device *sdp = cmd->device; struct scsi_disk *sdkp = scsi_disk(rq->rq_disk); struct bio *bio = rq->bio; sector_t sector = blk_rq_pos(rq); @@ -808,53 +835,56 @@ static int sd_setup_write_same_cmnd(struct scsi_device *sdp, struct request *rq) sector >>= ilog2(sdp->sector_size) - 9; nr_sectors >>= ilog2(sdp->sector_size) - 9; - rq->__data_len = sdp->sector_size; rq->timeout = SD_WRITE_SAME_TIMEOUT; - memset(rq->cmd, 0, rq->cmd_len); if (sdkp->ws16 || sector > 0xffffffff || nr_sectors > 0xffff) { - rq->cmd_len = 16; - rq->cmd[0] = WRITE_SAME_16; - put_unaligned_be64(sector, &rq->cmd[2]); - put_unaligned_be32(nr_sectors, &rq->cmd[10]); + cmd->cmd_len = 16; + cmd->cmnd[0] = WRITE_SAME_16; + put_unaligned_be64(sector, &cmd->cmnd[2]); + put_unaligned_be32(nr_sectors, &cmd->cmnd[10]); } else { - rq->cmd_len = 10; - rq->cmd[0] = WRITE_SAME; - put_unaligned_be32(sector, &rq->cmd[2]); - put_unaligned_be16(nr_sectors, &rq->cmd[7]); + cmd->cmd_len = 10; + cmd->cmnd[0] = WRITE_SAME; + put_unaligned_be32(sector, &cmd->cmnd[2]); + put_unaligned_be16(nr_sectors, &cmd->cmnd[7]); } - ret = scsi_setup_blk_pc_cmnd(sdp, rq); - rq->__data_len = nr_bytes; + cmd->transfersize = sdp->sector_size; + cmd->allowed = SD_MAX_RETRIES; + /* + * For WRITE_SAME the data transferred in the DATA IN buffer is + * different from the amount of data actually written to the target. + * + * We set up __data_len to the amount of data transferred from the + * DATA IN buffer so that blk_rq_map_sg set up the proper S/G list + * to transfer a single sector of data first, but then reset it to + * the amount of data to be written right after so that the I/O path + * knows how much to actually write. + */ + rq->__data_len = sdp->sector_size; + ret = scsi_init_io(cmd, GFP_ATOMIC); + rq->__data_len = nr_bytes; return ret; } -static int scsi_setup_flush_cmnd(struct scsi_device *sdp, struct request *rq) +static int sd_setup_flush_cmnd(struct scsi_cmnd *cmd) { - rq->timeout *= SD_FLUSH_TIMEOUT_MULTIPLIER; - rq->retries = SD_MAX_RETRIES; - rq->cmd[0] = SYNCHRONIZE_CACHE; - rq->cmd_len = 10; - - return scsi_setup_blk_pc_cmnd(sdp, rq); -} + struct request *rq = cmd->request; -static void sd_uninit_command(struct scsi_cmnd *SCpnt) -{ - struct request *rq = SCpnt->request; + /* flush requests don't perform I/O, zero the S/G table */ + memset(&cmd->sdb, 0, sizeof(cmd->sdb)); - if (rq->cmd_flags & REQ_DISCARD) - __free_page(rq->completion_data); + cmd->cmnd[0] = SYNCHRONIZE_CACHE; + cmd->cmd_len = 10; + cmd->transfersize = 0; + cmd->allowed = SD_MAX_RETRIES; - if (SCpnt->cmnd != rq->cmd) { - mempool_free(SCpnt->cmnd, sd_cdb_pool); - SCpnt->cmnd = NULL; - SCpnt->cmd_len = 0; - } + rq->timeout = rq->q->rq_timeout * SD_FLUSH_TIMEOUT_MULTIPLIER; + return BLKPREP_OK; } -static int sd_init_command(struct scsi_cmnd *SCpnt) +static int sd_setup_read_write_cmnd(struct scsi_cmnd *SCpnt) { struct request *rq = SCpnt->request; struct scsi_device *sdp = SCpnt->device; @@ -866,21 +896,7 @@ static int sd_init_command(struct scsi_cmnd *SCpnt) int ret, host_dif; unsigned char protect; - /* - * Discard request come in as REQ_TYPE_FS but we turn them into - * block PC requests to make life easier. - */ - if (rq->cmd_flags & REQ_DISCARD) { - ret = sd_setup_discard_cmnd(sdp, rq); - goto out; - } else if (rq->cmd_flags & REQ_WRITE_SAME) { - ret = sd_setup_write_same_cmnd(sdp, rq); - goto out; - } else if (rq->cmd_flags & REQ_FLUSH) { - ret = scsi_setup_flush_cmnd(sdp, rq); - goto out; - } - ret = scsi_setup_fs_cmnd(sdp, rq); + ret = scsi_init_io(SCpnt, GFP_ATOMIC); if (ret != BLKPREP_OK) goto out; SCpnt = rq->special; @@ -976,18 +992,13 @@ static int sd_init_command(struct scsi_cmnd *SCpnt) } } if (rq_data_dir(rq) == WRITE) { - if (!sdp->writeable) { - goto out; - } SCpnt->cmnd[0] = WRITE_6; - SCpnt->sc_data_direction = DMA_TO_DEVICE; if (blk_integrity_rq(rq)) sd_dif_prepare(rq, block, sdp->sector_size); } else if (rq_data_dir(rq) == READ) { SCpnt->cmnd[0] = READ_6; - SCpnt->sc_data_direction = DMA_FROM_DEVICE; } else { scmd_printk(KERN_ERR, SCpnt, "Unknown command %llx\n", (unsigned long long) rq->cmd_flags); goto out; @@ -1042,7 +1053,7 @@ static int sd_init_command(struct scsi_cmnd *SCpnt) SCpnt->cmnd[29] = (unsigned char) (this_count >> 16) & 0xff; SCpnt->cmnd[30] = (unsigned char) (this_count >> 8) & 0xff; SCpnt->cmnd[31] = (unsigned char) this_count & 0xff; - } else if (sdp->use_16_for_rw) { + } else if (sdp->use_16_for_rw || (this_count > 0xffff)) { SCpnt->cmnd[0] += READ_16 - READ_6; SCpnt->cmnd[1] = protect | ((rq->cmd_flags & REQ_FUA) ? 0x8 : 0); SCpnt->cmnd[2] = sizeof(block) > 4 ? (unsigned char) (block >> 56) & 0xff : 0; @@ -1061,9 +1072,6 @@ static int sd_init_command(struct scsi_cmnd *SCpnt) } else if ((this_count > 0xff) || (block > 0x1fffff) || scsi_device_protection(SCpnt->device) || SCpnt->device->use_10_for_rw) { - if (this_count > 0xffff) - this_count = 0xffff; - SCpnt->cmnd[0] += READ_10 - READ_6; SCpnt->cmnd[1] = protect | ((rq->cmd_flags & REQ_FUA) ? 0x8 : 0); SCpnt->cmnd[2] = (unsigned char) (block >> 24) & 0xff; @@ -1116,6 +1124,34 @@ static int sd_init_command(struct scsi_cmnd *SCpnt) return ret; } +static int sd_init_command(struct scsi_cmnd *cmd) +{ + struct request *rq = cmd->request; + + if (rq->cmd_flags & REQ_DISCARD) + return sd_setup_discard_cmnd(cmd); + else if (rq->cmd_flags & REQ_WRITE_SAME) + return sd_setup_write_same_cmnd(cmd); + else if (rq->cmd_flags & REQ_FLUSH) + return sd_setup_flush_cmnd(cmd); + else + return sd_setup_read_write_cmnd(cmd); +} + +static void sd_uninit_command(struct scsi_cmnd *SCpnt) +{ + struct request *rq = SCpnt->request; + + if (rq->cmd_flags & REQ_DISCARD) + __free_page(rq->completion_data); + + if (SCpnt->cmnd != rq->cmd) { + mempool_free(SCpnt->cmnd, sd_cdb_pool); + SCpnt->cmnd = NULL; + SCpnt->cmd_len = 0; + } +} + /** * sd_open - open a scsi disk device * @inode: only i_rdev member may be used @@ -2225,7 +2261,11 @@ got_data: } } - sdp->use_16_for_rw = (sdkp->capacity > 0xffffffff); + if (sdkp->capacity > 0xffffffff) { + sdp->use_16_for_rw = 1; + sdkp->max_xfer_blocks = SD_MAX_XFER_BLOCKS; + } else + sdkp->max_xfer_blocks = SD_DEF_XFER_BLOCKS; /* Rescale capacity to 512-byte units */ if (sector_size == 4096) @@ -2540,6 +2580,7 @@ static void sd_read_block_limits(struct scsi_disk *sdkp) { unsigned int sector_sz = sdkp->device->sector_size; const int vpd_len = 64; + u32 max_xfer_length; unsigned char *buffer = kmalloc(vpd_len, GFP_KERNEL); if (!buffer || @@ -2547,6 +2588,10 @@ static void sd_read_block_limits(struct scsi_disk *sdkp) scsi_get_vpd_page(sdkp->device, 0xb0, buffer, vpd_len)) goto out; + max_xfer_length = get_unaligned_be32(&buffer[8]); + if (max_xfer_length) + sdkp->max_xfer_blocks = max_xfer_length; + blk_queue_io_min(sdkp->disk->queue, get_unaligned_be16(&buffer[6]) * sector_sz); blk_queue_io_opt(sdkp->disk->queue, @@ -2681,6 +2726,11 @@ static void sd_read_write_same(struct scsi_disk *sdkp, unsigned char *buffer) static int sd_try_extended_inquiry(struct scsi_device *sdp) { + /* Attempt VPD inquiry if the device blacklist explicitly calls + * for it. + */ + if (sdp->try_vpd_pages) + return 1; /* * Although VPD inquiries can go to SCSI-2 type devices, * some USB ones crash on receiving them, and the pages @@ -2701,7 +2751,7 @@ static int sd_revalidate_disk(struct gendisk *disk) struct scsi_disk *sdkp = scsi_disk(disk); struct scsi_device *sdp = sdkp->device; unsigned char *buffer; - unsigned flush = 0; + unsigned int max_xfer; SCSI_LOG_HLQUEUE(3, sd_printk(KERN_INFO, sdkp, "sd_revalidate_disk\n")); @@ -2747,14 +2797,12 @@ static int sd_revalidate_disk(struct gendisk *disk) * We now have all cache related info, determine how we deal * with flush requests. */ - if (sdkp->WCE) { - flush |= REQ_FLUSH; - if (sdkp->DPOFUA) - flush |= REQ_FUA; - } - - blk_queue_flush(sdkp->disk->queue, flush); + sd_set_flush_flag(sdkp); + max_xfer = min_not_zero(queue_max_hw_sectors(sdkp->disk->queue), + sdkp->max_xfer_blocks); + max_xfer <<= ilog2(sdp->sector_size) - 9; + blk_queue_max_hw_sectors(sdkp->disk->queue, max_xfer); set_capacity(disk, sdkp->capacity); sd_config_write_same(sdkp); kfree(buffer); @@ -3208,12 +3256,14 @@ static int __init init_sd(void) 0, 0, NULL); if (!sd_cdb_cache) { printk(KERN_ERR "sd: can't init extended cdb cache\n"); + err = -ENOMEM; goto err_out_class; } sd_cdb_pool = mempool_create_slab_pool(SD_MEMPOOL_SIZE, sd_cdb_cache); if (!sd_cdb_pool) { printk(KERN_ERR "sd: can't init extended cdb pool\n"); + err = -ENOMEM; goto err_out_cache; } diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h index 620871efbf0a..4c3ab8377fd3 100644 --- a/drivers/scsi/sd.h +++ b/drivers/scsi/sd.h @@ -44,6 +44,8 @@ enum { }; enum { + SD_DEF_XFER_BLOCKS = 0xffff, + SD_MAX_XFER_BLOCKS = 0xffffffff, SD_MAX_WS10_BLOCKS = 0xffff, SD_MAX_WS16_BLOCKS = 0x7fffff, }; @@ -64,6 +66,7 @@ struct scsi_disk { struct gendisk *disk; atomic_t openers; sector_t capacity; /* size in 512-byte sectors */ + u32 max_xfer_blocks; u32 max_ws_blocks; u32 max_unmap_blocks; u32 unmap_granularity; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 53268aaba559..01cf88888797 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -7,9 +7,7 @@ * Original driver (sg.c): * Copyright (C) 1992 Lawrence Foard * Version 2 and 3 extensions to driver: - * Copyright (C) 1998 - 2005 Douglas Gilbert - * - * Modified 19-JAN-1998 Richard Gooch <rgooch@atnf.csiro.au> Devfs support + * Copyright (C) 1998 - 2014 Douglas Gilbert * * 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 @@ -18,11 +16,11 @@ * */ -static int sg_version_num = 30534; /* 2 digits for each component */ -#define SG_VERSION_STR "3.5.34" +static int sg_version_num = 30536; /* 2 digits for each component */ +#define SG_VERSION_STR "3.5.36" /* - * D. P. Gilbert (dgilbert@interlog.com, dougg@triode.net.au), notes: + * D. P. Gilbert (dgilbert@interlog.com), notes: * - scsi logging is available via SCSI_LOG_TIMEOUT macros. First * the kernel/module needs to be built with CONFIG_SCSI_LOGGING * (otherwise the macros compile to empty statements). @@ -51,6 +49,7 @@ static int sg_version_num = 30534; /* 2 digits for each component */ #include <linux/delay.h> #include <linux/blktrace_api.h> #include <linux/mutex.h> +#include <linux/atomic.h> #include <linux/ratelimit.h> #include "scsi.h" @@ -64,7 +63,7 @@ static int sg_version_num = 30534; /* 2 digits for each component */ #ifdef CONFIG_SCSI_PROC_FS #include <linux/proc_fs.h> -static char *sg_version_date = "20061027"; +static char *sg_version_date = "20140603"; static int sg_proc_init(void); static void sg_proc_cleanup(void); @@ -74,6 +73,12 @@ static void sg_proc_cleanup(void); #define SG_MAX_DEVS 32768 +/* SG_MAX_CDB_SIZE should be 260 (spc4r37 section 3.1.30) however the type + * of sg_io_hdr::cmd_len can only represent 255. All SCSI commands greater + * than 16 bytes are "variable length" whose length is a multiple of 4 + */ +#define SG_MAX_CDB_SIZE 252 + /* * Suppose you want to calculate the formula muldiv(x,m,d)=int(x * m / d) * Then when using 32 bit integers x * m may overflow during the calculation. @@ -102,18 +107,16 @@ static int scatter_elem_sz_prev = SG_SCATTER_SZ; #define SG_SECTOR_SZ 512 -static int sg_add(struct device *, struct class_interface *); -static void sg_remove(struct device *, struct class_interface *); - -static DEFINE_SPINLOCK(sg_open_exclusive_lock); +static int sg_add_device(struct device *, struct class_interface *); +static void sg_remove_device(struct device *, struct class_interface *); static DEFINE_IDR(sg_index_idr); static DEFINE_RWLOCK(sg_index_lock); /* Also used to lock file descriptor list for device */ static struct class_interface sg_interface = { - .add_dev = sg_add, - .remove_dev = sg_remove, + .add_dev = sg_add_device, + .remove_dev = sg_remove_device, }; typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info */ @@ -146,8 +149,7 @@ typedef struct sg_request { /* SG_MAX_QUEUE requests outstanding per file */ } Sg_request; typedef struct sg_fd { /* holds the state of a file descriptor */ - /* sfd_siblings is protected by sg_index_lock */ - struct list_head sfd_siblings; + struct list_head sfd_siblings; /* protected by device's sfd_lock */ struct sg_device *parentdp; /* owning device */ wait_queue_head_t read_wait; /* queue read until command done */ rwlock_t rq_list_lock; /* protect access to list in req_arr */ @@ -161,7 +163,7 @@ typedef struct sg_fd { /* holds the state of a file descriptor */ char low_dma; /* as in parent but possibly overridden to 1 */ char force_packid; /* 1 -> pack_id input to read(), 0 -> ignored */ char cmd_q; /* 1 -> allow command queuing, 0 -> don't */ - char next_cmd_len; /* 0 -> automatic (def), >0 -> use on next write() */ + unsigned char next_cmd_len; /* 0: automatic, >0: use on next write() */ char keep_orphan; /* 0 -> drop orphan (def), 1 -> keep for read() */ char mmap_called; /* 0 -> mmap() never called on this fd */ struct kref f_ref; @@ -170,14 +172,15 @@ typedef struct sg_fd { /* holds the state of a file descriptor */ typedef struct sg_device { /* holds the state of each scsi generic device */ struct scsi_device *device; - wait_queue_head_t o_excl_wait; /* queue open() when O_EXCL in use */ + wait_queue_head_t open_wait; /* queue open() when O_EXCL present */ + struct mutex open_rel_lock; /* held when in open() or release() */ int sg_tablesize; /* adapter's max scatter-gather table size */ u32 index; /* device index number */ - /* sfds is protected by sg_index_lock */ struct list_head sfds; - volatile char detached; /* 0->attached, 1->detached pending removal */ - /* exclude protected by sg_open_exclusive_lock */ - char exclude; /* opened for exclusive access */ + rwlock_t sfd_lock; /* protect access to sfd list */ + atomic_t detaching; /* 0->device usable, 1->device detaching */ + bool exclude; /* 1->open(O_EXCL) succeeded and is active */ + int open_cnt; /* count of opens (perhaps < num(sfds) ) */ char sgdebug; /* 0->off, 1->sense, 9->dump dev, 10-> all devs */ struct gendisk *disk; struct cdev * cdev; /* char_dev [sysfs: /sys/cdev/major/sg<n>] */ @@ -197,24 +200,28 @@ static ssize_t sg_new_write(Sg_fd *sfp, struct file *file, static int sg_common_write(Sg_fd * sfp, Sg_request * srp, unsigned char *cmnd, int timeout, int blocking); static int sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer); -static void sg_remove_scat(Sg_scatter_hold * schp); +static void sg_remove_scat(Sg_fd * sfp, Sg_scatter_hold * schp); static void sg_build_reserve(Sg_fd * sfp, int req_size); static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size); static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp); -static Sg_fd *sg_add_sfp(Sg_device * sdp, int dev); +static Sg_fd *sg_add_sfp(Sg_device * sdp); static void sg_remove_sfp(struct kref *); static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id); static Sg_request *sg_add_request(Sg_fd * sfp); static int sg_remove_request(Sg_fd * sfp, Sg_request * srp); static int sg_res_in_use(Sg_fd * sfp); static Sg_device *sg_get_dev(int dev); -static void sg_put_dev(Sg_device *sdp); +static void sg_device_destroy(struct kref *kref); #define SZ_SG_HEADER sizeof(struct sg_header) #define SZ_SG_IO_HDR sizeof(sg_io_hdr_t) #define SZ_SG_IOVEC sizeof(sg_iovec_t) #define SZ_SG_REQ_INFO sizeof(sg_req_info_t) +#define sg_printk(prefix, sdp, fmt, a...) \ + sdev_printk(prefix, (sdp)->device, "[%s] " fmt, \ + (sdp)->disk->disk_name, ##a) + static int sg_allow_access(struct file *filp, unsigned char *cmd) { struct sg_fd *sfp = filp->private_data; @@ -225,38 +232,43 @@ static int sg_allow_access(struct file *filp, unsigned char *cmd) return blk_verify_command(cmd, filp->f_mode & FMODE_WRITE); } -static int get_exclude(Sg_device *sdp) -{ - unsigned long flags; - int ret; - - spin_lock_irqsave(&sg_open_exclusive_lock, flags); - ret = sdp->exclude; - spin_unlock_irqrestore(&sg_open_exclusive_lock, flags); - return ret; -} - -static int set_exclude(Sg_device *sdp, char val) +static int +open_wait(Sg_device *sdp, int flags) { - unsigned long flags; - - spin_lock_irqsave(&sg_open_exclusive_lock, flags); - sdp->exclude = val; - spin_unlock_irqrestore(&sg_open_exclusive_lock, flags); - return val; -} + int retval = 0; -static int sfds_list_empty(Sg_device *sdp) -{ - unsigned long flags; - int ret; + if (flags & O_EXCL) { + while (sdp->open_cnt > 0) { + mutex_unlock(&sdp->open_rel_lock); + retval = wait_event_interruptible(sdp->open_wait, + (atomic_read(&sdp->detaching) || + !sdp->open_cnt)); + mutex_lock(&sdp->open_rel_lock); + + if (retval) /* -ERESTARTSYS */ + return retval; + if (atomic_read(&sdp->detaching)) + return -ENODEV; + } + } else { + while (sdp->exclude) { + mutex_unlock(&sdp->open_rel_lock); + retval = wait_event_interruptible(sdp->open_wait, + (atomic_read(&sdp->detaching) || + !sdp->exclude)); + mutex_lock(&sdp->open_rel_lock); + + if (retval) /* -ERESTARTSYS */ + return retval; + if (atomic_read(&sdp->detaching)) + return -ENODEV; + } + } - read_lock_irqsave(&sg_index_lock, flags); - ret = list_empty(&sdp->sfds); - read_unlock_irqrestore(&sg_index_lock, flags); - return ret; + return retval; } +/* Returns 0 on success, else a negated errno value */ static int sg_open(struct inode *inode, struct file *filp) { @@ -265,17 +277,17 @@ sg_open(struct inode *inode, struct file *filp) struct request_queue *q; Sg_device *sdp; Sg_fd *sfp; - int res; int retval; nonseekable_open(inode, filp); - SCSI_LOG_TIMEOUT(3, printk("sg_open: dev=%d, flags=0x%x\n", dev, flags)); + if ((flags & O_EXCL) && (O_RDONLY == (flags & O_ACCMODE))) + return -EPERM; /* Can't lock it with read only access */ sdp = sg_get_dev(dev); - if (IS_ERR(sdp)) { - retval = PTR_ERR(sdp); - sdp = NULL; - goto sg_put; - } + if (IS_ERR(sdp)) + return PTR_ERR(sdp); + + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, + "sg_open: flags=0x%x\n", flags)); /* This driver's module count bumped by fops_get in <linux/fs.h> */ /* Prevent the device driver from vanishing while we sleep */ @@ -287,6 +299,9 @@ sg_open(struct inode *inode, struct file *filp) if (retval) goto sdp_put; + /* scsi_block_when_processing_errors() may block so bypass + * check if O_NONBLOCK. Permits SCSI commands to be issued + * during error recovery. Tread carefully. */ if (!((flags & O_NONBLOCK) || scsi_block_when_processing_errors(sdp->device))) { retval = -ENXIO; @@ -294,65 +309,65 @@ sg_open(struct inode *inode, struct file *filp) goto error_out; } - if (flags & O_EXCL) { - if (O_RDONLY == (flags & O_ACCMODE)) { - retval = -EPERM; /* Can't lock it with read only access */ - goto error_out; - } - if (!sfds_list_empty(sdp) && (flags & O_NONBLOCK)) { - retval = -EBUSY; - goto error_out; - } - res = wait_event_interruptible(sdp->o_excl_wait, - ((!sfds_list_empty(sdp) || get_exclude(sdp)) ? 0 : set_exclude(sdp, 1))); - if (res) { - retval = res; /* -ERESTARTSYS because signal hit process */ - goto error_out; - } - } else if (get_exclude(sdp)) { /* some other fd has an exclusive lock on dev */ - if (flags & O_NONBLOCK) { - retval = -EBUSY; - goto error_out; - } - res = wait_event_interruptible(sdp->o_excl_wait, !get_exclude(sdp)); - if (res) { - retval = res; /* -ERESTARTSYS because signal hit process */ - goto error_out; + mutex_lock(&sdp->open_rel_lock); + if (flags & O_NONBLOCK) { + if (flags & O_EXCL) { + if (sdp->open_cnt > 0) { + retval = -EBUSY; + goto error_mutex_locked; + } + } else { + if (sdp->exclude) { + retval = -EBUSY; + goto error_mutex_locked; + } } + } else { + retval = open_wait(sdp, flags); + if (retval) /* -ERESTARTSYS or -ENODEV */ + goto error_mutex_locked; } - if (sdp->detached) { - retval = -ENODEV; - goto error_out; - } - if (sfds_list_empty(sdp)) { /* no existing opens on this device */ + + /* N.B. at this point we are holding the open_rel_lock */ + if (flags & O_EXCL) + sdp->exclude = true; + + if (sdp->open_cnt < 1) { /* no existing opens */ sdp->sgdebug = 0; q = sdp->device->request_queue; sdp->sg_tablesize = queue_max_segments(q); } - if ((sfp = sg_add_sfp(sdp, dev))) - filp->private_data = sfp; - else { - if (flags & O_EXCL) { - set_exclude(sdp, 0); /* undo if error */ - wake_up_interruptible(&sdp->o_excl_wait); - } - retval = -ENOMEM; - goto error_out; + sfp = sg_add_sfp(sdp); + if (IS_ERR(sfp)) { + retval = PTR_ERR(sfp); + goto out_undo; } + + filp->private_data = sfp; + sdp->open_cnt++; + mutex_unlock(&sdp->open_rel_lock); + retval = 0; -error_out: - if (retval) { - scsi_autopm_put_device(sdp->device); -sdp_put: - scsi_device_put(sdp->device); - } sg_put: - if (sdp) - sg_put_dev(sdp); + kref_put(&sdp->d_ref, sg_device_destroy); return retval; + +out_undo: + if (flags & O_EXCL) { + sdp->exclude = false; /* undo if error */ + wake_up_interruptible(&sdp->open_wait); + } +error_mutex_locked: + mutex_unlock(&sdp->open_rel_lock); +error_out: + scsi_autopm_put_device(sdp->device); +sdp_put: + scsi_device_put(sdp->device); + goto sg_put; } -/* Following function was formerly called 'sg_close' */ +/* Release resources associated with a successful sg_open() + * Returns 0 on success, else a negated errno value */ static int sg_release(struct inode *inode, struct file *filp) { @@ -361,13 +376,22 @@ sg_release(struct inode *inode, struct file *filp) if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) return -ENXIO; - SCSI_LOG_TIMEOUT(3, printk("sg_release: %s\n", sdp->disk->disk_name)); - - set_exclude(sdp, 0); - wake_up_interruptible(&sdp->o_excl_wait); + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, "sg_release\n")); + mutex_lock(&sdp->open_rel_lock); scsi_autopm_put_device(sdp->device); kref_put(&sfp->f_ref, sg_remove_sfp); + sdp->open_cnt--; + + /* possibly many open()s waiting on exlude clearing, start many; + * only open(O_EXCL)s wait on 0==open_cnt so only start one */ + if (sdp->exclude) { + sdp->exclude = false; + wake_up_interruptible_all(&sdp->open_wait); + } else if (0 == sdp->open_cnt) { + wake_up_interruptible(&sdp->open_wait); + } + mutex_unlock(&sdp->open_rel_lock); return 0; } @@ -384,8 +408,8 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) return -ENXIO; - SCSI_LOG_TIMEOUT(3, printk("sg_read: %s, count=%d\n", - sdp->disk->disk_name, (int) count)); + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, + "sg_read: count=%d\n", (int) count)); if (!access_ok(VERIFY_WRITE, buf, count)) return -EFAULT; @@ -419,7 +443,7 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) } srp = sg_get_rq_mark(sfp, req_pack_id); if (!srp) { /* now wait on packet to arrive */ - if (sdp->detached) { + if (atomic_read(&sdp->detaching)) { retval = -ENODEV; goto free_old_hdr; } @@ -428,9 +452,9 @@ sg_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) goto free_old_hdr; } retval = wait_event_interruptible(sfp->read_wait, - (sdp->detached || + (atomic_read(&sdp->detaching) || (srp = sg_get_rq_mark(sfp, req_pack_id)))); - if (sdp->detached) { + if (atomic_read(&sdp->detaching)) { retval = -ENODEV; goto free_old_hdr; } @@ -566,13 +590,13 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) Sg_request *srp; struct sg_header old_hdr; sg_io_hdr_t *hp; - unsigned char cmnd[MAX_COMMAND_SIZE]; + unsigned char cmnd[SG_MAX_CDB_SIZE]; if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) return -ENXIO; - SCSI_LOG_TIMEOUT(3, printk("sg_write: %s, count=%d\n", - sdp->disk->disk_name, (int) count)); - if (sdp->detached) + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, + "sg_write: count=%d\n", (int) count)); + if (atomic_read(&sdp->detaching)) return -ENODEV; if (!((filp->f_flags & O_NONBLOCK) || scsi_block_when_processing_errors(sdp->device))) @@ -592,18 +616,13 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) return -EIO; /* The minimum scsi command length is 6 bytes. */ if (!(srp = sg_add_request(sfp))) { - SCSI_LOG_TIMEOUT(1, printk("sg_write: queue full\n")); + SCSI_LOG_TIMEOUT(1, sg_printk(KERN_INFO, sdp, + "sg_write: queue full\n")); return -EDOM; } buf += SZ_SG_HEADER; __get_user(opcode, buf); if (sfp->next_cmd_len > 0) { - if (sfp->next_cmd_len > MAX_COMMAND_SIZE) { - SCSI_LOG_TIMEOUT(1, printk("sg_write: command length too long\n")); - sfp->next_cmd_len = 0; - sg_remove_request(sfp, srp); - return -EIO; - } cmd_size = sfp->next_cmd_len; sfp->next_cmd_len = 0; /* reset so only this write() effected */ } else { @@ -611,7 +630,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) if ((opcode >= 0xc0) && old_hdr.twelve_byte) cmd_size = 12; } - SCSI_LOG_TIMEOUT(4, printk( + SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sdp, "sg_write: scsi opcode=0x%02x, cmd_size=%d\n", (int) opcode, cmd_size)); /* Determine buffer size. */ input_size = count - cmd_size; @@ -675,7 +694,7 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf, int k; Sg_request *srp; sg_io_hdr_t *hp; - unsigned char cmnd[MAX_COMMAND_SIZE]; + unsigned char cmnd[SG_MAX_CDB_SIZE]; int timeout; unsigned long ul_timeout; @@ -686,7 +705,8 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf, sfp->cmd_q = 1; /* when sg_io_hdr seen, set command queuing on */ if (!(srp = sg_add_request(sfp))) { - SCSI_LOG_TIMEOUT(1, printk("sg_new_write: queue full\n")); + SCSI_LOG_TIMEOUT(1, sg_printk(KERN_INFO, sfp->parentdp, + "sg_new_write: queue full\n")); return -EDOM; } srp->sg_io_owned = sg_io_owned; @@ -743,7 +763,7 @@ static int sg_common_write(Sg_fd * sfp, Sg_request * srp, unsigned char *cmnd, int timeout, int blocking) { - int k, data_dir; + int k, data_dir, at_head; Sg_device *sdp = sfp->parentdp; sg_io_hdr_t *hp = &srp->header; @@ -755,16 +775,18 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, hp->host_status = 0; hp->driver_status = 0; hp->resid = 0; - SCSI_LOG_TIMEOUT(4, printk("sg_common_write: scsi opcode=0x%02x, cmd_size=%d\n", - (int) cmnd[0], (int) hp->cmd_len)); + SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sfp->parentdp, + "sg_common_write: scsi opcode=0x%02x, cmd_size=%d\n", + (int) cmnd[0], (int) hp->cmd_len)); k = sg_start_req(srp, cmnd); if (k) { - SCSI_LOG_TIMEOUT(1, printk("sg_common_write: start_req err=%d\n", k)); + SCSI_LOG_TIMEOUT(1, sg_printk(KERN_INFO, sfp->parentdp, + "sg_common_write: start_req err=%d\n", k)); sg_finish_rem_req(srp); return k; /* probably out of space --> ENOMEM */ } - if (sdp->detached) { + if (atomic_read(&sdp->detaching)) { if (srp->bio) blk_end_request_all(srp->rq, -EIO); sg_finish_rem_req(srp); @@ -787,11 +809,16 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp, break; } hp->duration = jiffies_to_msecs(jiffies); + if (hp->interface_id != '\0' && /* v3 (or later) interface */ + (SG_FLAG_Q_AT_TAIL & hp->flags)) + at_head = 0; + else + at_head = 1; srp->rq->timeout = timeout; kref_get(&sfp->f_ref); /* sg_rq_end_io() does kref_put(). */ blk_execute_rq_nowait(sdp->device->request_queue, sdp->disk, - srp->rq, 1, sg_rq_end_io); + srp->rq, at_head, sg_rq_end_io); return 0; } @@ -806,6 +833,15 @@ static int srp_done(Sg_fd *sfp, Sg_request *srp) return ret; } +static int max_sectors_bytes(struct request_queue *q) +{ + unsigned int max_sectors = queue_max_sectors(q); + + max_sectors = min_t(unsigned int, max_sectors, INT_MAX >> 9); + + return max_sectors << 9; +} + static long sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) { @@ -820,13 +856,13 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) return -ENXIO; - SCSI_LOG_TIMEOUT(3, printk("sg_ioctl: %s, cmd=0x%x\n", - sdp->disk->disk_name, (int) cmd_in)); + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, + "sg_ioctl: cmd=0x%x\n", (int) cmd_in)); read_only = (O_RDWR != (filp->f_flags & O_ACCMODE)); switch (cmd_in) { case SG_IO: - if (sdp->detached) + if (atomic_read(&sdp->detaching)) return -ENODEV; if (!scsi_block_when_processing_errors(sdp->device)) return -ENXIO; @@ -837,8 +873,8 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) if (result < 0) return result; result = wait_event_interruptible(sfp->read_wait, - (srp_done(sfp, srp) || sdp->detached)); - if (sdp->detached) + (srp_done(sfp, srp) || atomic_read(&sdp->detaching))); + if (atomic_read(&sdp->detaching)) return -ENODEV; write_lock_irq(&sfp->rq_list_lock); if (srp->done) { @@ -873,11 +909,11 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) sfp->low_dma = 1; if ((0 == sfp->low_dma) && (0 == sg_res_in_use(sfp))) { val = (int) sfp->reserve.bufflen; - sg_remove_scat(&sfp->reserve); + sg_remove_scat(sfp, &sfp->reserve); sg_build_reserve(sfp, val); } } else { - if (sdp->detached) + if (atomic_read(&sdp->detaching)) return -ENODEV; sfp->low_dma = sdp->device->host->unchecked_isa_dma; } @@ -890,7 +926,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) else { sg_scsi_id_t __user *sg_idp = p; - if (sdp->detached) + if (atomic_read(&sdp->detaching)) return -ENODEV; __put_user((int) sdp->device->host->host_no, &sg_idp->host_no); @@ -945,17 +981,17 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) if (val < 0) return -EINVAL; val = min_t(int, val, - queue_max_sectors(sdp->device->request_queue) * 512); + max_sectors_bytes(sdp->device->request_queue)); if (val != sfp->reserve.bufflen) { if (sg_res_in_use(sfp) || sfp->mmap_called) return -EBUSY; - sg_remove_scat(&sfp->reserve); + sg_remove_scat(sfp, &sfp->reserve); sg_build_reserve(sfp, val); } return 0; case SG_GET_RESERVED_SIZE: val = min_t(int, sfp->reserve.bufflen, - queue_max_sectors(sdp->device->request_queue) * 512); + max_sectors_bytes(sdp->device->request_queue)); return put_user(val, ip); case SG_SET_COMMAND_Q: result = get_user(val, ip); @@ -1032,11 +1068,11 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) return result; } case SG_EMULATED_HOST: - if (sdp->detached) + if (atomic_read(&sdp->detaching)) return -ENODEV; return put_user(sdp->device->host->hostt->emulated, ip); case SG_SCSI_RESET: - if (sdp->detached) + if (atomic_read(&sdp->detaching)) return -ENODEV; if (filp->f_flags & O_NONBLOCK) { if (scsi_host_in_recovery(sdp->device->host)) @@ -1069,7 +1105,7 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) return (scsi_reset_provider(sdp->device, val) == SUCCESS) ? 0 : -EIO; case SCSI_IOCTL_SEND_COMMAND: - if (sdp->detached) + if (atomic_read(&sdp->detaching)) return -ENODEV; if (read_only) { unsigned char opcode = WRITE_6; @@ -1091,11 +1127,11 @@ sg_ioctl(struct file *filp, unsigned int cmd_in, unsigned long arg) case SCSI_IOCTL_GET_BUS_NUMBER: case SCSI_IOCTL_PROBE_HOST: case SG_GET_TRANSFORM: - if (sdp->detached) + if (atomic_read(&sdp->detaching)) return -ENODEV; return scsi_ioctl(sdp->device, cmd_in, p); case BLKSECTGET: - return put_user(queue_max_sectors(sdp->device->request_queue) * 512, + return put_user(max_sectors_bytes(sdp->device->request_queue), ip); case BLKTRACESETUP: return blk_trace_setup(sdp->device->request_queue, @@ -1165,15 +1201,15 @@ sg_poll(struct file *filp, poll_table * wait) } read_unlock_irqrestore(&sfp->rq_list_lock, iflags); - if (sdp->detached) + if (atomic_read(&sdp->detaching)) res |= POLLHUP; else if (!sfp->cmd_q) { if (0 == count) res |= POLLOUT | POLLWRNORM; } else if (count < SG_MAX_QUEUE) res |= POLLOUT | POLLWRNORM; - SCSI_LOG_TIMEOUT(3, printk("sg_poll: %s, res=0x%x\n", - sdp->disk->disk_name, (int) res)); + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, + "sg_poll: res=0x%x\n", (int) res)); return res; } @@ -1185,8 +1221,8 @@ sg_fasync(int fd, struct file *filp, int mode) if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) return -ENXIO; - SCSI_LOG_TIMEOUT(3, printk("sg_fasync: %s, mode=%d\n", - sdp->disk->disk_name, mode)); + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, + "sg_fasync: mode=%d\n", mode)); return fasync_helper(fd, filp, mode, &sfp->async_qp); } @@ -1205,8 +1241,9 @@ sg_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) offset = vmf->pgoff << PAGE_SHIFT; if (offset >= rsv_schp->bufflen) return VM_FAULT_SIGBUS; - SCSI_LOG_TIMEOUT(3, printk("sg_vma_fault: offset=%lu, scatg=%d\n", - offset, rsv_schp->k_use_sg)); + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sfp->parentdp, + "sg_vma_fault: offset=%lu, scatg=%d\n", + offset, rsv_schp->k_use_sg)); sa = vma->vm_start; length = 1 << (PAGE_SHIFT + rsv_schp->page_order); for (k = 0; k < rsv_schp->k_use_sg && sa < vma->vm_end; k++) { @@ -1241,8 +1278,9 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma) if ((!filp) || (!vma) || (!(sfp = (Sg_fd *) filp->private_data))) return -ENXIO; req_sz = vma->vm_end - vma->vm_start; - SCSI_LOG_TIMEOUT(3, printk("sg_mmap starting, vm_start=%p, len=%d\n", - (void *) vma->vm_start, (int) req_sz)); + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sfp->parentdp, + "sg_mmap starting, vm_start=%p, len=%d\n", + (void *) vma->vm_start, (int) req_sz)); if (vma->vm_pgoff) return -EINVAL; /* want no offset */ rsv_schp = &sfp->reserve; @@ -1264,7 +1302,8 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma) return 0; } -static void sg_rq_end_io_usercontext(struct work_struct *work) +static void +sg_rq_end_io_usercontext(struct work_struct *work) { struct sg_request *srp = container_of(work, struct sg_request, ew.work); struct sg_fd *sfp = srp->parentfp; @@ -1277,7 +1316,8 @@ static void sg_rq_end_io_usercontext(struct work_struct *work) * This function is a "bottom half" handler that is called by the mid * level when a command is completed (or has failed). */ -static void sg_rq_end_io(struct request *rq, int uptodate) +static void +sg_rq_end_io(struct request *rq, int uptodate) { struct sg_request *srp = rq->end_io_data; Sg_device *sdp; @@ -1295,15 +1335,16 @@ static void sg_rq_end_io(struct request *rq, int uptodate) return; sdp = sfp->parentdp; - if (unlikely(sdp->detached)) - printk(KERN_INFO "sg_rq_end_io: device detached\n"); + if (unlikely(atomic_read(&sdp->detaching))) + pr_info("%s: device detaching\n", __func__); sense = rq->sense; result = rq->errors; resid = rq->resid_len; - SCSI_LOG_TIMEOUT(4, printk("sg_cmd_done: %s, pack_id=%d, res=0x%x\n", - sdp->disk->disk_name, srp->header.pack_id, result)); + SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sdp, + "sg_cmd_done: pack_id=%d, res=0x%x\n", + srp->header.pack_id, result)); srp->header.resid = resid; ms = jiffies_to_msecs(jiffies); srp->header.duration = (ms > srp->header.duration) ? @@ -1319,7 +1360,7 @@ static void sg_rq_end_io(struct request *rq, int uptodate) if ((sdp->sgdebug > 0) && ((CHECK_CONDITION == srp->header.masked_status) || (COMMAND_TERMINATED == srp->header.masked_status))) - __scsi_print_sense("sg_cmd_done", sense, + __scsi_print_sense(__func__, sense, SCSI_SENSE_BUFFERSIZE); /* Following if statement is a patch supplied by Eric Youngdale */ @@ -1378,7 +1419,8 @@ static struct class *sg_sysfs_class; static int sg_sysfs_valid = 0; -static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) +static Sg_device * +sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) { struct request_queue *q = scsidp->request_queue; Sg_device *sdp; @@ -1388,7 +1430,8 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) sdp = kzalloc(sizeof(Sg_device), GFP_KERNEL); if (!sdp) { - printk(KERN_WARNING "kmalloc Sg_device failure\n"); + sdev_printk(KERN_WARNING, scsidp, "%s: kmalloc Sg_device " + "failure\n", __func__); return ERR_PTR(-ENOMEM); } @@ -1403,20 +1446,25 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) scsidp->type, SG_MAX_DEVS - 1); error = -ENODEV; } else { - printk(KERN_WARNING - "idr allocation Sg_device failure: %d\n", error); + sdev_printk(KERN_WARNING, scsidp, "%s: idr " + "allocation Sg_device failure: %d\n", + __func__, error); } goto out_unlock; } k = error; - SCSI_LOG_TIMEOUT(3, printk("sg_alloc: dev=%d \n", k)); + SCSI_LOG_TIMEOUT(3, sdev_printk(KERN_INFO, scsidp, + "sg_alloc: dev=%d \n", k)); sprintf(disk->disk_name, "sg%d", k); disk->first_minor = k; sdp->disk = disk; sdp->device = scsidp; + mutex_init(&sdp->open_rel_lock); INIT_LIST_HEAD(&sdp->sfds); - init_waitqueue_head(&sdp->o_excl_wait); + init_waitqueue_head(&sdp->open_wait); + atomic_set(&sdp->detaching, 0); + rwlock_init(&sdp->sfd_lock); sdp->sg_tablesize = queue_max_segments(q); sdp->index = k; kref_init(&sdp->d_ref); @@ -1434,7 +1482,7 @@ out_unlock: } static int -sg_add(struct device *cl_dev, struct class_interface *cl_intf) +sg_add_device(struct device *cl_dev, struct class_interface *cl_intf) { struct scsi_device *scsidp = to_scsi_device(cl_dev->parent); struct gendisk *disk; @@ -1445,7 +1493,7 @@ sg_add(struct device *cl_dev, struct class_interface *cl_intf) disk = alloc_disk(1); if (!disk) { - printk(KERN_WARNING "alloc_disk failed\n"); + pr_warn("%s: alloc_disk failed\n", __func__); return -ENOMEM; } disk->major = SCSI_GENERIC_MAJOR; @@ -1453,7 +1501,7 @@ sg_add(struct device *cl_dev, struct class_interface *cl_intf) error = -ENOMEM; cdev = cdev_alloc(); if (!cdev) { - printk(KERN_WARNING "cdev_alloc failed\n"); + pr_warn("%s: cdev_alloc failed\n", __func__); goto out; } cdev->owner = THIS_MODULE; @@ -1461,7 +1509,7 @@ sg_add(struct device *cl_dev, struct class_interface *cl_intf) sdp = sg_alloc(disk, scsidp); if (IS_ERR(sdp)) { - printk(KERN_WARNING "sg_alloc failed\n"); + pr_warn("%s: sg_alloc failed\n", __func__); error = PTR_ERR(sdp); goto out; } @@ -1479,22 +1527,20 @@ sg_add(struct device *cl_dev, struct class_interface *cl_intf) sdp->index), sdp, "%s", disk->disk_name); if (IS_ERR(sg_class_member)) { - printk(KERN_ERR "sg_add: " - "device_create failed\n"); + pr_err("%s: device_create failed\n", __func__); error = PTR_ERR(sg_class_member); goto cdev_add_err; } error = sysfs_create_link(&scsidp->sdev_gendev.kobj, &sg_class_member->kobj, "generic"); if (error) - printk(KERN_ERR "sg_add: unable to make symlink " - "'generic' back to sg%d\n", sdp->index); + pr_err("%s: unable to make symlink 'generic' back " + "to sg%d\n", __func__, sdp->index); } else - printk(KERN_WARNING "sg_add: sg_sys Invalid\n"); + pr_warn("%s: sg_sys Invalid\n", __func__); - sdev_printk(KERN_NOTICE, scsidp, - "Attached scsi generic sg%d type %d\n", sdp->index, - scsidp->type); + sdev_printk(KERN_NOTICE, scsidp, "Attached scsi generic sg%d " + "type %d\n", sdp->index, scsidp->type); dev_set_drvdata(cl_dev, sdp); @@ -1513,7 +1559,8 @@ out: return error; } -static void sg_device_destroy(struct kref *kref) +static void +sg_device_destroy(struct kref *kref) { struct sg_device *sdp = container_of(kref, struct sg_device, d_ref); unsigned long flags; @@ -1528,40 +1575,45 @@ static void sg_device_destroy(struct kref *kref) write_unlock_irqrestore(&sg_index_lock, flags); SCSI_LOG_TIMEOUT(3, - printk("sg_device_destroy: %s\n", - sdp->disk->disk_name)); + sg_printk(KERN_INFO, sdp, "sg_device_destroy\n")); put_disk(sdp->disk); kfree(sdp); } -static void sg_remove(struct device *cl_dev, struct class_interface *cl_intf) +static void +sg_remove_device(struct device *cl_dev, struct class_interface *cl_intf) { struct scsi_device *scsidp = to_scsi_device(cl_dev->parent); Sg_device *sdp = dev_get_drvdata(cl_dev); unsigned long iflags; Sg_fd *sfp; + int val; - if (!sdp || sdp->detached) + if (!sdp) return; + /* want sdp->detaching non-zero as soon as possible */ + val = atomic_inc_return(&sdp->detaching); + if (val > 1) + return; /* only want to do following once per device */ - SCSI_LOG_TIMEOUT(3, printk("sg_remove: %s\n", sdp->disk->disk_name)); + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, + "%s\n", __func__)); - /* Need a write lock to set sdp->detached. */ - write_lock_irqsave(&sg_index_lock, iflags); - sdp->detached = 1; + read_lock_irqsave(&sdp->sfd_lock, iflags); list_for_each_entry(sfp, &sdp->sfds, sfd_siblings) { - wake_up_interruptible(&sfp->read_wait); + wake_up_interruptible_all(&sfp->read_wait); kill_fasync(&sfp->async_qp, SIGPOLL, POLL_HUP); } - write_unlock_irqrestore(&sg_index_lock, iflags); + wake_up_interruptible_all(&sdp->open_wait); + read_unlock_irqrestore(&sdp->sfd_lock, iflags); sysfs_remove_link(&scsidp->sdev_gendev.kobj, "generic"); device_destroy(sg_sysfs_class, MKDEV(SCSI_GENERIC_MAJOR, sdp->index)); cdev_del(sdp->cdev); sdp->cdev = NULL; - sg_put_dev(sdp); + kref_put(&sdp->d_ref, sg_device_destroy); } module_param_named(scatter_elem_sz, scatter_elem_sz, int, S_IRUGO | S_IWUSR); @@ -1631,7 +1683,8 @@ exit_sg(void) idr_destroy(&sg_index_idr); } -static int sg_start_req(Sg_request *srp, unsigned char *cmd) +static int +sg_start_req(Sg_request *srp, unsigned char *cmd) { int res; struct request *rq; @@ -1645,15 +1698,28 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) struct request_queue *q = sfp->parentdp->device->request_queue; struct rq_map_data *md, map_data; int rw = hp->dxfer_direction == SG_DXFER_TO_DEV ? WRITE : READ; + unsigned char *long_cmdp = NULL; - SCSI_LOG_TIMEOUT(4, printk(KERN_INFO "sg_start_req: dxfer_len=%d\n", - dxfer_len)); + SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sfp->parentdp, + "sg_start_req: dxfer_len=%d\n", + dxfer_len)); + + if (hp->cmd_len > BLK_MAX_CDB) { + long_cmdp = kzalloc(hp->cmd_len, GFP_KERNEL); + if (!long_cmdp) + return -ENOMEM; + } rq = blk_get_request(q, rw, GFP_ATOMIC); - if (!rq) + if (!rq) { + kfree(long_cmdp); return -ENOMEM; + } blk_rq_set_block_pc(rq); + + if (hp->cmd_len > BLK_MAX_CDB) + rq->cmd = long_cmdp; memcpy(rq->cmd, cmd, hp->cmd_len); rq->cmd_len = hp->cmd_len; @@ -1726,25 +1792,30 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd) return res; } -static int sg_finish_rem_req(Sg_request * srp) +static int +sg_finish_rem_req(Sg_request *srp) { int ret = 0; Sg_fd *sfp = srp->parentfp; Sg_scatter_hold *req_schp = &srp->data; - SCSI_LOG_TIMEOUT(4, printk("sg_finish_rem_req: res_used=%d\n", (int) srp->res_used)); + SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sfp->parentdp, + "sg_finish_rem_req: res_used=%d\n", + (int) srp->res_used)); if (srp->rq) { if (srp->bio) ret = blk_rq_unmap_user(srp->bio); + if (srp->rq->cmd != srp->rq->__cmd) + kfree(srp->rq->cmd); blk_put_request(srp->rq); } if (srp->res_used) sg_unlink_reserve(sfp, srp); else - sg_remove_scat(req_schp); + sg_remove_scat(sfp, req_schp); sg_remove_request(sfp, srp); @@ -1778,8 +1849,9 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size) ++blk_size; /* don't know why */ /* round request up to next highest SG_SECTOR_SZ byte boundary */ blk_size = ALIGN(blk_size, SG_SECTOR_SZ); - SCSI_LOG_TIMEOUT(4, printk("sg_build_indirect: buff_size=%d, blk_size=%d\n", - buff_size, blk_size)); + SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sfp->parentdp, + "sg_build_indirect: buff_size=%d, blk_size=%d\n", + buff_size, blk_size)); /* N.B. ret_sz carried into this block ... */ mx_sc_elems = sg_build_sgat(schp, sfp, sg_tablesize); @@ -1822,14 +1894,16 @@ retry: } } - SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k=%d, num=%d, " - "ret_sz=%d\n", k, num, ret_sz)); + SCSI_LOG_TIMEOUT(5, sg_printk(KERN_INFO, sfp->parentdp, + "sg_build_indirect: k=%d, num=%d, ret_sz=%d\n", + k, num, ret_sz)); } /* end of for loop */ schp->page_order = order; schp->k_use_sg = k; - SCSI_LOG_TIMEOUT(5, printk("sg_build_indirect: k_use_sg=%d, " - "rem_sz=%d\n", k, rem_sz)); + SCSI_LOG_TIMEOUT(5, sg_printk(KERN_INFO, sfp->parentdp, + "sg_build_indirect: k_use_sg=%d, rem_sz=%d\n", + k, rem_sz)); schp->bufflen = blk_size; if (rem_sz > 0) /* must have failed */ @@ -1846,17 +1920,19 @@ out: } static void -sg_remove_scat(Sg_scatter_hold * schp) +sg_remove_scat(Sg_fd * sfp, Sg_scatter_hold * schp) { - SCSI_LOG_TIMEOUT(4, printk("sg_remove_scat: k_use_sg=%d\n", schp->k_use_sg)); + SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sfp->parentdp, + "sg_remove_scat: k_use_sg=%d\n", schp->k_use_sg)); if (schp->pages && schp->sglist_len > 0) { if (!schp->dio_in_use) { int k; for (k = 0; k < schp->k_use_sg && schp->pages[k]; k++) { - SCSI_LOG_TIMEOUT(5, printk( - "sg_remove_scat: k=%d, pg=0x%p\n", - k, schp->pages[k])); + SCSI_LOG_TIMEOUT(5, + sg_printk(KERN_INFO, sfp->parentdp, + "sg_remove_scat: k=%d, pg=0x%p\n", + k, schp->pages[k])); __free_pages(schp->pages[k], schp->page_order); } @@ -1872,8 +1948,9 @@ sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer) Sg_scatter_hold *schp = &srp->data; int k, num; - SCSI_LOG_TIMEOUT(4, printk("sg_read_oxfer: num_read_xfer=%d\n", - num_read_xfer)); + SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, srp->parentfp->parentdp, + "sg_read_oxfer: num_read_xfer=%d\n", + num_read_xfer)); if ((!outp) || (num_read_xfer <= 0)) return 0; @@ -1903,14 +1980,15 @@ sg_build_reserve(Sg_fd * sfp, int req_size) { Sg_scatter_hold *schp = &sfp->reserve; - SCSI_LOG_TIMEOUT(4, printk("sg_build_reserve: req_size=%d\n", req_size)); + SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sfp->parentdp, + "sg_build_reserve: req_size=%d\n", req_size)); do { if (req_size < PAGE_SIZE) req_size = PAGE_SIZE; if (0 == sg_build_indirect(schp, sfp, req_size)) return; else - sg_remove_scat(schp); + sg_remove_scat(sfp, schp); req_size >>= 1; /* divide by 2 */ } while (req_size > (PAGE_SIZE / 2)); } @@ -1923,7 +2001,8 @@ sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size) int k, num, rem; srp->res_used = 1; - SCSI_LOG_TIMEOUT(4, printk("sg_link_reserve: size=%d\n", size)); + SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, sfp->parentdp, + "sg_link_reserve: size=%d\n", size)); rem = size; num = 1 << (PAGE_SHIFT + rsv_schp->page_order); @@ -1941,7 +2020,8 @@ sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size) } if (k >= rsv_schp->k_use_sg) - SCSI_LOG_TIMEOUT(1, printk("sg_link_reserve: BAD size\n")); + SCSI_LOG_TIMEOUT(1, sg_printk(KERN_INFO, sfp->parentdp, + "sg_link_reserve: BAD size\n")); } static void @@ -1949,8 +2029,9 @@ sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp) { Sg_scatter_hold *req_schp = &srp->data; - SCSI_LOG_TIMEOUT(4, printk("sg_unlink_reserve: req->k_use_sg=%d\n", - (int) req_schp->k_use_sg)); + SCSI_LOG_TIMEOUT(4, sg_printk(KERN_INFO, srp->parentfp->parentdp, + "sg_unlink_reserve: req->k_use_sg=%d\n", + (int) req_schp->k_use_sg)); req_schp->k_use_sg = 0; req_schp->bufflen = 0; req_schp->pages = NULL; @@ -2055,7 +2136,7 @@ sg_remove_request(Sg_fd * sfp, Sg_request * srp) } static Sg_fd * -sg_add_sfp(Sg_device * sdp, int dev) +sg_add_sfp(Sg_device * sdp) { Sg_fd *sfp; unsigned long iflags; @@ -2063,7 +2144,7 @@ sg_add_sfp(Sg_device * sdp, int dev) sfp = kzalloc(sizeof(*sfp), GFP_ATOMIC | __GFP_NOWARN); if (!sfp) - return NULL; + return ERR_PTR(-ENOMEM); init_waitqueue_head(&sfp->read_wait); rwlock_init(&sfp->rq_list_lock); @@ -2077,25 +2158,33 @@ sg_add_sfp(Sg_device * sdp, int dev) sfp->cmd_q = SG_DEF_COMMAND_Q; sfp->keep_orphan = SG_DEF_KEEP_ORPHAN; sfp->parentdp = sdp; - write_lock_irqsave(&sg_index_lock, iflags); + write_lock_irqsave(&sdp->sfd_lock, iflags); + if (atomic_read(&sdp->detaching)) { + write_unlock_irqrestore(&sdp->sfd_lock, iflags); + return ERR_PTR(-ENODEV); + } list_add_tail(&sfp->sfd_siblings, &sdp->sfds); - write_unlock_irqrestore(&sg_index_lock, iflags); - SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p\n", sfp)); + write_unlock_irqrestore(&sdp->sfd_lock, iflags); + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, + "sg_add_sfp: sfp=0x%p\n", sfp)); if (unlikely(sg_big_buff != def_reserved_size)) sg_big_buff = def_reserved_size; bufflen = min_t(int, sg_big_buff, - queue_max_sectors(sdp->device->request_queue) * 512); + max_sectors_bytes(sdp->device->request_queue)); sg_build_reserve(sfp, bufflen); - SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: bufflen=%d, k_use_sg=%d\n", - sfp->reserve.bufflen, sfp->reserve.k_use_sg)); + SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, + "sg_add_sfp: bufflen=%d, k_use_sg=%d\n", + sfp->reserve.bufflen, + sfp->reserve.k_use_sg)); kref_get(&sdp->d_ref); __module_get(THIS_MODULE); return sfp; } -static void sg_remove_sfp_usercontext(struct work_struct *work) +static void +sg_remove_sfp_usercontext(struct work_struct *work) { struct sg_fd *sfp = container_of(work, struct sg_fd, ew.work); struct sg_device *sdp = sfp->parentdp; @@ -2105,34 +2194,32 @@ static void sg_remove_sfp_usercontext(struct work_struct *work) sg_finish_rem_req(sfp->headrp); if (sfp->reserve.bufflen > 0) { - SCSI_LOG_TIMEOUT(6, - printk("sg_remove_sfp: bufflen=%d, k_use_sg=%d\n", + SCSI_LOG_TIMEOUT(6, sg_printk(KERN_INFO, sdp, + "sg_remove_sfp: bufflen=%d, k_use_sg=%d\n", (int) sfp->reserve.bufflen, (int) sfp->reserve.k_use_sg)); - sg_remove_scat(&sfp->reserve); + sg_remove_scat(sfp, &sfp->reserve); } - SCSI_LOG_TIMEOUT(6, - printk("sg_remove_sfp: %s, sfp=0x%p\n", - sdp->disk->disk_name, - sfp)); + SCSI_LOG_TIMEOUT(6, sg_printk(KERN_INFO, sdp, + "sg_remove_sfp: sfp=0x%p\n", sfp)); kfree(sfp); scsi_device_put(sdp->device); - sg_put_dev(sdp); + kref_put(&sdp->d_ref, sg_device_destroy); module_put(THIS_MODULE); } -static void sg_remove_sfp(struct kref *kref) +static void +sg_remove_sfp(struct kref *kref) { struct sg_fd *sfp = container_of(kref, struct sg_fd, f_ref); struct sg_device *sdp = sfp->parentdp; unsigned long iflags; - write_lock_irqsave(&sg_index_lock, iflags); + write_lock_irqsave(&sdp->sfd_lock, iflags); list_del(&sfp->sfd_siblings); - write_unlock_irqrestore(&sg_index_lock, iflags); - wake_up_interruptible(&sdp->o_excl_wait); + write_unlock_irqrestore(&sdp->sfd_lock, iflags); INIT_WORK(&sfp->ew.work, sg_remove_sfp_usercontext); schedule_work(&sfp->ew.work); @@ -2183,7 +2270,8 @@ static Sg_device *sg_lookup_dev(int dev) return idr_find(&sg_index_idr, dev); } -static Sg_device *sg_get_dev(int dev) +static Sg_device * +sg_get_dev(int dev) { struct sg_device *sdp; unsigned long flags; @@ -2192,8 +2280,8 @@ static Sg_device *sg_get_dev(int dev) sdp = sg_lookup_dev(dev); if (!sdp) sdp = ERR_PTR(-ENXIO); - else if (sdp->detached) { - /* If sdp->detached, then the refcount may already be 0, in + else if (atomic_read(&sdp->detaching)) { + /* If sdp->detaching, then the refcount may already be 0, in * which case it would be a bug to do kref_get(). */ sdp = ERR_PTR(-ENODEV); @@ -2204,11 +2292,6 @@ static Sg_device *sg_get_dev(int dev) return sdp; } -static void sg_put_dev(struct sg_device *sdp) -{ - kref_put(&sdp->d_ref, sg_device_destroy); -} - #ifdef CONFIG_SCSI_PROC_FS static struct proc_dir_entry *sg_proc_sgp = NULL; @@ -2425,8 +2508,7 @@ static int sg_proc_single_open_version(struct inode *inode, struct file *file) static int sg_proc_seq_show_devhdr(struct seq_file *s, void *v) { - seq_printf(s, "host\tchan\tid\tlun\ttype\topens\tqdepth\tbusy\t" - "online\n"); + seq_puts(s, "host\tchan\tid\tlun\ttype\topens\tqdepth\tbusy\tonline\n"); return 0; } @@ -2482,16 +2564,19 @@ static int sg_proc_seq_show_dev(struct seq_file *s, void *v) read_lock_irqsave(&sg_index_lock, iflags); sdp = it ? sg_lookup_dev(it->index) : NULL; - if (sdp && (scsidp = sdp->device) && (!sdp->detached)) - seq_printf(s, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", + if ((NULL == sdp) || (NULL == sdp->device) || + (atomic_read(&sdp->detaching))) + seq_puts(s, "-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\n"); + else { + scsidp = sdp->device; + seq_printf(s, "%d\t%d\t%d\t%llu\t%d\t%d\t%d\t%d\t%d\n", scsidp->host->host_no, scsidp->channel, scsidp->id, scsidp->lun, (int) scsidp->type, 1, (int) scsidp->queue_depth, - (int) scsidp->device_busy, + (int) atomic_read(&scsidp->device_busy), (int) scsi_device_online(scsidp)); - else - seq_printf(s, "-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\n"); + } read_unlock_irqrestore(&sg_index_lock, iflags); return 0; } @@ -2510,11 +2595,12 @@ static int sg_proc_seq_show_devstrs(struct seq_file *s, void *v) read_lock_irqsave(&sg_index_lock, iflags); sdp = it ? sg_lookup_dev(it->index) : NULL; - if (sdp && (scsidp = sdp->device) && (!sdp->detached)) + scsidp = sdp ? sdp->device : NULL; + if (sdp && scsidp && (!atomic_read(&sdp->detaching))) seq_printf(s, "%8.8s\t%16.16s\t%4.4s\n", scsidp->vendor, scsidp->model, scsidp->rev); else - seq_printf(s, "<no active device>\n"); + seq_puts(s, "<no active device>\n"); read_unlock_irqrestore(&sg_index_lock, iflags); return 0; } @@ -2559,12 +2645,12 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp) else cp = " "; } - seq_printf(s, cp); + seq_puts(s, cp); blen = srp->data.bufflen; usg = srp->data.k_use_sg; - seq_printf(s, srp->done ? - ((1 == srp->done) ? "rcv:" : "fin:") - : "act:"); + seq_puts(s, srp->done ? + ((1 == srp->done) ? "rcv:" : "fin:") + : "act:"); seq_printf(s, " id=%d blen=%d", srp->header.pack_id, blen); if (srp->done) @@ -2580,7 +2666,7 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp) (int) srp->data.cmd_opcode); } if (0 == m) - seq_printf(s, " No requests active\n"); + seq_puts(s, " No requests active\n"); read_unlock(&fp->rq_list_lock); } } @@ -2596,31 +2682,34 @@ static int sg_proc_seq_show_debug(struct seq_file *s, void *v) Sg_device *sdp; unsigned long iflags; - if (it && (0 == it->index)) { - seq_printf(s, "max_active_device=%d(origin 1)\n", - (int)it->max); - seq_printf(s, " def_reserved_size=%d\n", sg_big_buff); - } + if (it && (0 == it->index)) + seq_printf(s, "max_active_device=%d def_reserved_size=%d\n", + (int)it->max, sg_big_buff); read_lock_irqsave(&sg_index_lock, iflags); sdp = it ? sg_lookup_dev(it->index) : NULL; - if (sdp && !list_empty(&sdp->sfds)) { - struct scsi_device *scsidp = sdp->device; - + if (NULL == sdp) + goto skip; + read_lock(&sdp->sfd_lock); + if (!list_empty(&sdp->sfds)) { seq_printf(s, " >>> device=%s ", sdp->disk->disk_name); - if (sdp->detached) - seq_printf(s, "detached pending close "); - else - seq_printf - (s, "scsi%d chan=%d id=%d lun=%d em=%d", - scsidp->host->host_no, - scsidp->channel, scsidp->id, - scsidp->lun, - scsidp->host->hostt->emulated); - seq_printf(s, " sg_tablesize=%d excl=%d\n", - sdp->sg_tablesize, get_exclude(sdp)); + if (atomic_read(&sdp->detaching)) + seq_puts(s, "detaching pending close "); + else if (sdp->device) { + struct scsi_device *scsidp = sdp->device; + + seq_printf(s, "%d:%d:%d:%llu em=%d", + scsidp->host->host_no, + scsidp->channel, scsidp->id, + scsidp->lun, + scsidp->host->hostt->emulated); + } + seq_printf(s, " sg_tablesize=%d excl=%d open_cnt=%d\n", + sdp->sg_tablesize, sdp->exclude, sdp->open_cnt); sg_proc_debug_helper(s, sdp); } + read_unlock(&sdp->sfd_lock); +skip: read_unlock_irqrestore(&sg_index_lock, iflags); return 0; } diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 93cbd36c990b..7eeb93627beb 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -292,8 +292,8 @@ do_tur: if (!cd->tur_changed) { if (cd->get_event_changed) { if (cd->tur_mismatch++ > 8) { - sdev_printk(KERN_WARNING, cd->device, - "GET_EVENT and TUR disagree continuously, suppress GET_EVENT events\n"); + sr_printk(KERN_WARNING, cd, + "GET_EVENT and TUR disagree continuously, suppress GET_EVENT events\n"); cd->ignore_get_event = true; } } else { @@ -322,7 +322,7 @@ static int sr_done(struct scsi_cmnd *SCpnt) struct scsi_cd *cd = scsi_cd(SCpnt->request->rq_disk); #ifdef DEBUG - printk("sr.c done: %x\n", result); + scmd_printk(KERN_INFO, SCpnt, "done: %x\n", result); #endif /* @@ -385,10 +385,9 @@ static int sr_init_command(struct scsi_cmnd *SCpnt) int block = 0, this_count, s_size; struct scsi_cd *cd; struct request *rq = SCpnt->request; - struct scsi_device *sdp = SCpnt->device; int ret; - ret = scsi_setup_fs_cmnd(sdp, rq); + ret = scsi_init_io(SCpnt, GFP_ATOMIC); if (ret != BLKPREP_OK) goto out; SCpnt = rq->special; @@ -398,13 +397,14 @@ static int sr_init_command(struct scsi_cmnd *SCpnt) * is used for a killable error condition */ ret = BLKPREP_KILL; - SCSI_LOG_HLQUEUE(1, printk("Doing sr request, dev = %s, block = %d\n", - cd->disk->disk_name, block)); + SCSI_LOG_HLQUEUE(1, scmd_printk(KERN_INFO, SCpnt, + "Doing sr request, block = %d\n", block)); if (!cd->device || !scsi_device_online(cd->device)) { - SCSI_LOG_HLQUEUE(2, printk("Finishing %u sectors\n", - blk_rq_sectors(rq))); - SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt)); + SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, + "Finishing %u sectors\n", blk_rq_sectors(rq))); + SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, + "Retry with 0x%p\n", SCpnt)); goto out; } @@ -425,7 +425,8 @@ static int sr_init_command(struct scsi_cmnd *SCpnt) if (!in_interrupt()) sr_set_blocklength(cd, 2048); else - printk("sr: can't switch blocksize: in interrupt\n"); + scmd_printk(KERN_INFO, SCpnt, + "can't switch blocksize: in interrupt\n"); } if (s_size != 512 && s_size != 1024 && s_size != 2048) { @@ -434,14 +435,12 @@ static int sr_init_command(struct scsi_cmnd *SCpnt) } if (rq_data_dir(rq) == WRITE) { - if (!cd->device->writeable) + if (!cd->writeable) goto out; SCpnt->cmnd[0] = WRITE_10; - SCpnt->sc_data_direction = DMA_TO_DEVICE; - cd->cdi.media_written = 1; + cd->cdi.media_written = 1; } else if (rq_data_dir(rq) == READ) { SCpnt->cmnd[0] = READ_10; - SCpnt->sc_data_direction = DMA_FROM_DEVICE; } else { blk_dump_rq_flags(rq, "Unknown sr command"); goto out; @@ -475,11 +474,11 @@ static int sr_init_command(struct scsi_cmnd *SCpnt) this_count = (scsi_bufflen(SCpnt) >> 9) / (s_size >> 9); - SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%u 512 byte blocks.\n", - cd->cdi.name, - (rq_data_dir(rq) == WRITE) ? + SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, + "%s %d/%u 512 byte blocks.\n", + (rq_data_dir(rq) == WRITE) ? "writing" : "reading", - this_count, blk_rq_sectors(rq))); + this_count, blk_rq_sectors(rq))); SCpnt->cmnd[1] = 0; block = (unsigned int)blk_rq_pos(rq) / (s_size >> 9); @@ -810,8 +809,8 @@ static void get_sectorsize(struct scsi_cd *cd) case 512: break; default: - printk("%s: unsupported sector size %d.\n", - cd->cdi.name, sector_size); + sr_printk(KERN_INFO, cd, + "unsupported sector size %d.", sector_size); cd->capacity = 0; } @@ -853,7 +852,7 @@ static void get_capabilities(struct scsi_cd *cd) /* allocate transfer buffer */ buffer = kmalloc(512, GFP_KERNEL | GFP_DMA); if (!buffer) { - printk(KERN_ERR "sr: out of memory.\n"); + sr_printk(KERN_ERR, cd, "out of memory.\n"); return; } @@ -872,7 +871,7 @@ static void get_capabilities(struct scsi_cd *cd) CDC_SELECT_DISC | CDC_SELECT_SPEED | CDC_MRW | CDC_MRW_W | CDC_RAM); kfree(buffer); - printk("%s: scsi-1 drive\n", cd->cdi.name); + sr_printk(KERN_INFO, cd, "scsi-1 drive"); return; } @@ -881,22 +880,23 @@ static void get_capabilities(struct scsi_cd *cd) cd->readcd_known = 1; cd->readcd_cdda = buffer[n + 5] & 0x01; /* print some capability bits */ - printk("%s: scsi3-mmc drive: %dx/%dx %s%s%s%s%s%s\n", cd->cdi.name, - ((buffer[n + 14] << 8) + buffer[n + 15]) / 176, - cd->cdi.speed, - buffer[n + 3] & 0x01 ? "writer " : "", /* CD Writer */ - buffer[n + 3] & 0x20 ? "dvd-ram " : "", - buffer[n + 2] & 0x02 ? "cd/rw " : "", /* can read rewriteable */ - buffer[n + 4] & 0x20 ? "xa/form2 " : "", /* can read xa/from2 */ - buffer[n + 5] & 0x01 ? "cdda " : "", /* can read audio data */ - loadmech[buffer[n + 6] >> 5]); + sr_printk(KERN_INFO, cd, + "scsi3-mmc drive: %dx/%dx %s%s%s%s%s%s\n", + ((buffer[n + 14] << 8) + buffer[n + 15]) / 176, + cd->cdi.speed, + buffer[n + 3] & 0x01 ? "writer " : "", /* CD Writer */ + buffer[n + 3] & 0x20 ? "dvd-ram " : "", + buffer[n + 2] & 0x02 ? "cd/rw " : "", /* can read rewriteable */ + buffer[n + 4] & 0x20 ? "xa/form2 " : "", /* can read xa/from2 */ + buffer[n + 5] & 0x01 ? "cdda " : "", /* can read audio data */ + loadmech[buffer[n + 6] >> 5]); if ((buffer[n + 6] >> 5) == 0) /* caddy drives can't close tray... */ cd->cdi.mask |= CDC_CLOSE_TRAY; if ((buffer[n + 2] & 0x8) == 0) /* not a DVD drive */ cd->cdi.mask |= CDC_DVD; - if ((buffer[n + 3] & 0x20) == 0) + if ((buffer[n + 3] & 0x20) == 0) /* can't write DVD-RAM media */ cd->cdi.mask |= CDC_DVD_RAM; if ((buffer[n + 3] & 0x10) == 0) @@ -927,7 +927,7 @@ static void get_capabilities(struct scsi_cd *cd) */ if ((cd->cdi.mask & (CDC_DVD_RAM | CDC_MRW_W | CDC_RAM | CDC_CD_RW)) != (CDC_DVD_RAM | CDC_MRW_W | CDC_RAM | CDC_CD_RW)) { - cd->device->writeable = 1; + cd->writeable = 1; } kfree(buffer); @@ -935,7 +935,7 @@ static void get_capabilities(struct scsi_cd *cd) /* * sr_packet() is the entry point for the generic commands generated - * by the Uniform CD-ROM layer. + * by the Uniform CD-ROM layer. */ static int sr_packet(struct cdrom_device_info *cdi, struct packet_command *cgc) diff --git a/drivers/scsi/sr.h b/drivers/scsi/sr.h index 37c8f6b17510..1d1f6f416c59 100644 --- a/drivers/scsi/sr.h +++ b/drivers/scsi/sr.h @@ -36,6 +36,7 @@ typedef struct scsi_cd { struct scsi_device *device; unsigned int vendor; /* vendor code, see sr_vendor.c */ unsigned long ms_offset; /* for reading multisession-CD's */ + unsigned writeable : 1; unsigned use:1; /* is this device still supportable */ unsigned xa_flag:1; /* CD has XA sectors ? */ unsigned readcd_known:1; /* drive supports READ_CD (0xbe) */ @@ -55,6 +56,10 @@ typedef struct scsi_cd { struct gendisk *disk; } Scsi_CD; +#define sr_printk(prefix, cd, fmt, a...) \ + sdev_printk(prefix, (cd)->device, "[%s] " fmt, \ + (cd)->cdi.name, ##a) + int sr_do_ioctl(Scsi_CD *, struct packet_command *); int sr_lock_door(struct cdrom_device_info *, int); diff --git a/drivers/scsi/sr_ioctl.c b/drivers/scsi/sr_ioctl.c index a3911c39ea50..6389fcff12ec 100644 --- a/drivers/scsi/sr_ioctl.c +++ b/drivers/scsi/sr_ioctl.c @@ -36,7 +36,6 @@ module_param(xa_test, int, S_IRUGO | S_IWUSR); * the status of the unchecked_isa_dma flag in the host structure */ #define SR_GFP_DMA(cd) (((cd)->device->host->unchecked_isa_dma) ? GFP_DMA : 0) - static int sr_read_tochdr(struct cdrom_device_info *cdi, struct cdrom_tochdr *tochdr) { @@ -219,7 +218,8 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc) case UNIT_ATTENTION: SDev->changed = 1; if (!cgc->quiet) - printk(KERN_INFO "%s: disc change detected.\n", cd->cdi.name); + sr_printk(KERN_INFO, cd, + "disc change detected.\n"); if (retries++ < 10) goto retry; err = -ENOMEDIUM; @@ -229,7 +229,8 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc) sshdr.ascq == 0x01) { /* sense: Logical unit is in process of becoming ready */ if (!cgc->quiet) - printk(KERN_INFO "%s: CDROM not ready yet.\n", cd->cdi.name); + sr_printk(KERN_INFO, cd, + "CDROM not ready yet.\n"); if (retries++ < 10) { /* sleep 2 sec and try again */ ssleep(2); @@ -241,7 +242,9 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc) } } if (!cgc->quiet) - printk(KERN_INFO "%s: CDROM not ready. Make sure there is a disc in the drive.\n", cd->cdi.name); + sr_printk(KERN_INFO, cd, + "CDROM not ready. Make sure there " + "is a disc in the drive.\n"); #ifdef DEBUG scsi_print_sense_hdr("sr", &sshdr); #endif @@ -259,7 +262,8 @@ int sr_do_ioctl(Scsi_CD *cd, struct packet_command *cgc) #endif break; default: - printk(KERN_ERR "%s: CDROM (ioctl) error, command: ", cd->cdi.name); + sr_printk(KERN_ERR, cd, + "CDROM (ioctl) error, command: "); __scsi_print_command(cgc->cmd); scsi_print_sense_hdr("sr", &sshdr); err = -EIO; @@ -491,8 +495,8 @@ static int sr_read_cd(Scsi_CD *cd, unsigned char *dest, int lba, int format, int struct packet_command cgc; #ifdef DEBUG - printk("%s: sr_read_cd lba=%d format=%d blksize=%d\n", - cd->cdi.name, lba, format, blksize); + sr_printk(KERN_INFO, cd, "sr_read_cd lba=%d format=%d blksize=%d\n", + lba, format, blksize); #endif memset(&cgc, 0, sizeof(struct packet_command)); @@ -539,7 +543,8 @@ static int sr_read_sector(Scsi_CD *cd, int lba, int blksize, unsigned char *dest if (-EDRIVE_CANT_DO_THIS != rc) return rc; cd->readcd_known = 0; - printk("CDROM does'nt support READ CD (0xbe) command\n"); + sr_printk(KERN_INFO, cd, + "CDROM does'nt support READ CD (0xbe) command\n"); /* fall & retry the other way */ } /* ... if this fails, we switch the blocksize using MODE SELECT */ @@ -548,7 +553,8 @@ static int sr_read_sector(Scsi_CD *cd, int lba, int blksize, unsigned char *dest return rc; } #ifdef DEBUG - printk("%s: sr_read_sector lba=%d blksize=%d\n", cd->cdi.name, lba, blksize); + sr_printk(KERN_INFO, cd, "sr_read_sector lba=%d blksize=%d\n", + lba, blksize); #endif memset(&cgc, 0, sizeof(struct packet_command)); @@ -592,7 +598,7 @@ int sr_is_xa(Scsi_CD *cd) } kfree(raw_sector); #ifdef DEBUG - printk("%s: sr_is_xa: %d\n", cd->cdi.name, is_xa); + sr_printk(KERN_INFO, cd, "sr_is_xa: %d\n", is_xa); #endif return is_xa; } diff --git a/drivers/scsi/sr_vendor.c b/drivers/scsi/sr_vendor.c index 92cc2efb25d7..11a238cb2222 100644 --- a/drivers/scsi/sr_vendor.c +++ b/drivers/scsi/sr_vendor.c @@ -123,7 +123,7 @@ int sr_set_blocklength(Scsi_CD *cd, int blocklength) return -ENOMEM; #ifdef DEBUG - printk("%s: MODE SELECT 0x%x/%d\n", cd->cdi.name, density, blocklength); + sr_printk(KERN_INFO, cd, "MODE SELECT 0x%x/%d\n", density, blocklength); #endif memset(&cgc, 0, sizeof(struct packet_command)); cgc.cmd[0] = MODE_SELECT; @@ -144,8 +144,9 @@ int sr_set_blocklength(Scsi_CD *cd, int blocklength) } #ifdef DEBUG else - printk("%s: switching blocklength to %d bytes failed\n", - cd->cdi.name, blocklength); + sr_printk(KERN_INFO, cd, + "switching blocklength to %d bytes failed\n", + blocklength); #endif kfree(buffer); return rc; @@ -190,8 +191,8 @@ int sr_cd_check(struct cdrom_device_info *cdi) if (rc != 0) break; if ((buffer[0] << 8) + buffer[1] < 0x0a) { - printk(KERN_INFO "%s: Hmm, seems the drive " - "doesn't support multisession CD's\n", cd->cdi.name); + sr_printk(KERN_INFO, cd, "Hmm, seems the drive " + "doesn't support multisession CD's\n"); no_multi = 1; break; } @@ -218,9 +219,9 @@ int sr_cd_check(struct cdrom_device_info *cdi) if (rc != 0) break; if (buffer[14] != 0 && buffer[14] != 0xb0) { - printk(KERN_INFO "%s: Hmm, seems the cdrom " - "doesn't support multisession CD's\n", - cd->cdi.name); + sr_printk(KERN_INFO, cd, "Hmm, seems the cdrom " + "doesn't support multisession CD's\n"); + no_multi = 1; break; } @@ -245,9 +246,8 @@ int sr_cd_check(struct cdrom_device_info *cdi) cgc.timeout = VENDOR_TIMEOUT; rc = sr_do_ioctl(cd, &cgc); if (rc == -EINVAL) { - printk(KERN_INFO "%s: Hmm, seems the drive " - "doesn't support multisession CD's\n", - cd->cdi.name); + sr_printk(KERN_INFO, cd, "Hmm, seems the drive " + "doesn't support multisession CD's\n"); no_multi = 1; break; } @@ -277,8 +277,8 @@ int sr_cd_check(struct cdrom_device_info *cdi) break; } if ((rc = buffer[2]) == 0) { - printk(KERN_WARNING - "%s: No finished session\n", cd->cdi.name); + sr_printk(KERN_WARNING, cd, + "No finished session\n"); break; } cgc.cmd[0] = READ_TOC; /* Read TOC */ @@ -301,9 +301,9 @@ int sr_cd_check(struct cdrom_device_info *cdi) default: /* should not happen */ - printk(KERN_WARNING - "%s: unknown vendor code (%i), not initialized ?\n", - cd->cdi.name, cd->vendor); + sr_printk(KERN_WARNING, cd, + "unknown vendor code (%i), not initialized ?\n", + cd->vendor); sector = 0; no_multi = 1; break; @@ -321,8 +321,8 @@ int sr_cd_check(struct cdrom_device_info *cdi) #ifdef DEBUG if (sector) - printk(KERN_DEBUG "%s: multisession offset=%lu\n", - cd->cdi.name, sector); + sr_printk(KERN_DEBUG, cd, "multisession offset=%lu\n", + sector); #endif kfree(buffer); return rc; diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 14eb4b256a03..aff9689de0f7 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -58,11 +58,11 @@ static const char *verstr = "20101219"; is defined and non-zero. */ #define DEBUG 0 +#define ST_DEB_MSG KERN_NOTICE #if DEBUG /* The message level for the debug messages is currently set to KERN_NOTICE so that people can easily see the messages. Later when the debugging messages in the drivers are more widely classified, this may be changed to KERN_DEBUG. */ -#define ST_DEB_MSG KERN_NOTICE #define DEB(a) a #define DEBC(a) if (debugging) { a ; } #else @@ -305,6 +305,15 @@ static inline char *tape_name(struct scsi_tape *tape) return tape->disk->disk_name; } +#define st_printk(prefix, t, fmt, a...) \ + sdev_printk(prefix, (t)->device, "%s: " fmt, \ + tape_name(t), ##a) +#ifdef DEBUG +#define DEBC_printk(t, fmt, a...) \ + if (debugging) { st_printk(ST_DEB_MSG, t, fmt, ##a ); } +#else +#define DEBC_printk(t, fmt, a...) +#endif static void st_analyze_sense(struct st_request *SRpnt, struct st_cmdstatus *s) { @@ -358,21 +367,20 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt) else scode = 0; - DEB( - if (debugging) { - printk(ST_DEB_MSG "%s: Error: %x, cmd: %x %x %x %x %x %x\n", - name, result, - SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2], - SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]); + DEB( + if (debugging) { + st_printk(ST_DEB_MSG, STp, + "Error: %x, cmd: %x %x %x %x %x %x\n", result, + SRpnt->cmd[0], SRpnt->cmd[1], SRpnt->cmd[2], + SRpnt->cmd[3], SRpnt->cmd[4], SRpnt->cmd[5]); if (cmdstatp->have_sense) __scsi_print_sense(name, SRpnt->sense, SCSI_SENSE_BUFFERSIZE); } ) /* end DEB */ if (!debugging) { /* Abnormal conditions for tape */ if (!cmdstatp->have_sense) - printk(KERN_WARNING - "%s: Error %x (driver bt 0x%x, host bt 0x%x).\n", - name, result, driver_byte(result), - host_byte(result)); + st_printk(KERN_WARNING, STp, + "Error %x (driver bt 0x%x, host bt 0x%x).\n", + result, driver_byte(result), host_byte(result)); else if (cmdstatp->have_sense && scode != NO_SENSE && scode != RECOVERED_ERROR && @@ -411,7 +419,7 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt) STp->recover_count++; STp->recover_reg++; - DEB( + DEB( if (debugging) { if (SRpnt->cmd[0] == READ_6) stp = "read"; @@ -419,8 +427,9 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt) stp = "write"; else stp = "ioctl"; - printk(ST_DEB_MSG "%s: Recovered %s error (%d).\n", name, stp, - STp->recover_count); + st_printk(ST_DEB_MSG, STp, + "Recovered %s error (%d).\n", + stp, STp->recover_count); } ) /* end DEB */ if (cmdstatp->flags == 0) @@ -437,8 +446,8 @@ static struct st_request *st_allocate_request(struct scsi_tape *stp) if (streq) streq->stp = stp; else { - DEBC(printk(KERN_ERR "%s: Can't get SCSI request.\n", - tape_name(stp));); + st_printk(KERN_ERR, stp, + "Can't get SCSI request.\n"); if (signal_pending(current)) stp->buffer->syscall_result = -EINTR; else @@ -525,8 +534,8 @@ st_do_scsi(struct st_request * SRpnt, struct scsi_tape * STp, unsigned char *cmd /* if async, make sure there's no command outstanding */ if (!do_wait && ((STp->buffer)->last_SRpnt)) { - printk(KERN_ERR "%s: Async command already active.\n", - tape_name(STp)); + st_printk(KERN_ERR, STp, + "Async command already active.\n"); if (signal_pending(current)) (STp->buffer)->syscall_result = (-EINTR); else @@ -597,12 +606,12 @@ static int write_behind_check(struct scsi_tape * STp) if (!STbuffer->writing) return 0; - DEB( + DEB( if (STp->write_pending) STp->nbr_waits++; else STp->nbr_finished++; - ) /* end DEB */ + ) /* end DEB */ wait_for_completion(&(STp->wait)); SRpnt = STbuffer->last_SRpnt; @@ -639,8 +648,9 @@ static int write_behind_check(struct scsi_tape * STp) STbuffer->writing = 0; DEB(if (debugging && retval) - printk(ST_DEB_MSG "%s: Async write error %x, return value %d.\n", - tape_name(STp), STbuffer->cmdstat.midlevel_result, retval);) /* end DEB */ + st_printk(ST_DEB_MSG, STp, + "Async write error %x, return value %d.\n", + STbuffer->cmdstat.midlevel_result, retval);) /* end DEB */ return retval; } @@ -662,8 +672,8 @@ static int cross_eof(struct scsi_tape * STp, int forward) cmd[2] = cmd[3] = cmd[4] = 0xff; /* -1 filemarks */ cmd[5] = 0; - DEBC(printk(ST_DEB_MSG "%s: Stepping over filemark %s.\n", - tape_name(STp), forward ? "forward" : "backward")); + DEBC_printk(STp, "Stepping over filemark %s.\n", + forward ? "forward" : "backward"); SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE, STp->device->request_queue->rq_timeout, @@ -675,8 +685,9 @@ static int cross_eof(struct scsi_tape * STp, int forward) SRpnt = NULL; if ((STp->buffer)->cmdstat.midlevel_result != 0) - printk(KERN_ERR "%s: Stepping over filemark %s failed.\n", - tape_name(STp), forward ? "forward" : "backward"); + st_printk(KERN_ERR, STp, + "Stepping over filemark %s failed.\n", + forward ? "forward" : "backward"); return (STp->buffer)->syscall_result; } @@ -699,8 +710,7 @@ static int st_flush_write_buffer(struct scsi_tape * STp) if (STp->dirty == 1) { transfer = STp->buffer->buffer_bytes; - DEBC(printk(ST_DEB_MSG "%s: Flushing %d bytes.\n", - tape_name(STp), transfer)); + DEBC_printk(STp, "Flushing %d bytes.\n", transfer); memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = WRITE_6; @@ -732,8 +742,7 @@ static int st_flush_write_buffer(struct scsi_tape * STp) STps->drv_block += blks; result = (-ENOSPC); } else { - printk(KERN_ERR "%s: Error on flush.\n", - tape_name(STp)); + st_printk(KERN_ERR, STp, "Error on flush.\n"); STps->drv_block = (-1); result = (-EIO); } @@ -811,7 +820,6 @@ static int set_mode_densblk(struct scsi_tape * STp, struct st_modedef * STm) { int set_it = 0; unsigned long arg; - char *name = tape_name(STp); if (!STp->density_changed && STm->default_density >= 0 && @@ -830,9 +838,10 @@ static int set_mode_densblk(struct scsi_tape * STp, struct st_modedef * STm) arg |= STp->block_size; if (set_it && st_int_ioctl(STp, SET_DENS_AND_BLK, arg)) { - printk(KERN_WARNING - "%s: Can't set default block size to %d bytes and density %x.\n", - name, STm->default_blksize, STm->default_density); + st_printk(KERN_WARNING, STp, + "Can't set default block size to %d bytes " + "and density %x.\n", + STm->default_blksize, STm->default_density); if (modes_defined) return (-EINVAL); } @@ -844,12 +853,9 @@ static int set_mode_densblk(struct scsi_tape * STp, struct st_modedef * STm) static int do_door_lock(struct scsi_tape * STp, int do_lock) { int retval, cmd; - DEB(char *name = tape_name(STp);) - cmd = do_lock ? SCSI_IOCTL_DOORLOCK : SCSI_IOCTL_DOORUNLOCK; - DEBC(printk(ST_DEB_MSG "%s: %socking drive door.\n", name, - do_lock ? "L" : "Unl")); + DEBC_printk(STp, "%socking drive door.\n", do_lock ? "L" : "Unl"); retval = scsi_ioctl(STp->device, cmd, NULL); if (!retval) { STp->door_locked = do_lock ? ST_LOCKED_EXPLICIT : ST_UNLOCKED; @@ -976,15 +982,14 @@ static int check_tape(struct scsi_tape *STp, struct file *filp) struct st_request *SRpnt = NULL; struct st_modedef *STm; struct st_partstat *STps; - char *name = tape_name(STp); struct inode *inode = file_inode(filp); int mode = TAPE_MODE(inode); STp->ready = ST_READY; if (mode != STp->current_mode) { - DEBC(printk(ST_DEB_MSG "%s: Mode change from %d to %d.\n", - name, STp->current_mode, mode)); + DEBC_printk(STp, "Mode change from %d to %d.\n", + STp->current_mode, mode); new_session = 1; STp->current_mode = mode; } @@ -1055,13 +1060,12 @@ static int check_tape(struct scsi_tape *STp, struct file *filp) STp->min_block = ((STp->buffer)->b_data[4] << 8) | (STp->buffer)->b_data[5]; if ( DEB( debugging || ) !STp->inited) - printk(KERN_INFO - "%s: Block limits %d - %d bytes.\n", name, - STp->min_block, STp->max_block); + st_printk(KERN_INFO, STp, + "Block limits %d - %d bytes.\n", + STp->min_block, STp->max_block); } else { STp->min_block = STp->max_block = (-1); - DEBC(printk(ST_DEB_MSG "%s: Can't read block limits.\n", - name)); + DEBC_printk(STp, "Can't read block limits.\n"); } } @@ -1078,56 +1082,58 @@ static int check_tape(struct scsi_tape *STp, struct file *filp) } if ((STp->buffer)->syscall_result != 0) { - DEBC(printk(ST_DEB_MSG "%s: No Mode Sense.\n", name)); + DEBC_printk(STp, "No Mode Sense.\n"); STp->block_size = ST_DEFAULT_BLOCK; /* Educated guess (?) */ (STp->buffer)->syscall_result = 0; /* Prevent error propagation */ STp->drv_write_prot = 0; } else { - DEBC(printk(ST_DEB_MSG - "%s: Mode sense. Length %d, medium %x, WBS %x, BLL %d\n", - name, - (STp->buffer)->b_data[0], (STp->buffer)->b_data[1], - (STp->buffer)->b_data[2], (STp->buffer)->b_data[3])); + DEBC_printk(STp,"Mode sense. Length %d, " + "medium %x, WBS %x, BLL %d\n", + (STp->buffer)->b_data[0], + (STp->buffer)->b_data[1], + (STp->buffer)->b_data[2], + (STp->buffer)->b_data[3]); if ((STp->buffer)->b_data[3] >= 8) { STp->drv_buffer = ((STp->buffer)->b_data[2] >> 4) & 7; STp->density = (STp->buffer)->b_data[4]; STp->block_size = (STp->buffer)->b_data[9] * 65536 + (STp->buffer)->b_data[10] * 256 + (STp->buffer)->b_data[11]; - DEBC(printk(ST_DEB_MSG - "%s: Density %x, tape length: %x, drv buffer: %d\n", - name, STp->density, (STp->buffer)->b_data[5] * 65536 + - (STp->buffer)->b_data[6] * 256 + (STp->buffer)->b_data[7], - STp->drv_buffer)); + DEBC_printk(STp, "Density %x, tape length: %x, " + "drv buffer: %d\n", + STp->density, + (STp->buffer)->b_data[5] * 65536 + + (STp->buffer)->b_data[6] * 256 + + (STp->buffer)->b_data[7], + STp->drv_buffer); } STp->drv_write_prot = ((STp->buffer)->b_data[2] & 0x80) != 0; if (!STp->drv_buffer && STp->immediate_filemark) { - printk(KERN_WARNING - "%s: non-buffered tape: disabling writing immediate filemarks\n", - name); + st_printk(KERN_WARNING, STp, + "non-buffered tape: disabling " + "writing immediate filemarks\n"); STp->immediate_filemark = 0; } } st_release_request(SRpnt); SRpnt = NULL; - STp->inited = 1; + STp->inited = 1; if (STp->block_size > 0) (STp->buffer)->buffer_blocks = - (STp->buffer)->buffer_size / STp->block_size; + (STp->buffer)->buffer_size / STp->block_size; else (STp->buffer)->buffer_blocks = 1; (STp->buffer)->buffer_bytes = (STp->buffer)->read_pointer = 0; - DEBC(printk(ST_DEB_MSG - "%s: Block size: %d, buffer size: %d (%d blocks).\n", name, - STp->block_size, (STp->buffer)->buffer_size, - (STp->buffer)->buffer_blocks)); + DEBC_printk(STp, "Block size: %d, buffer size: %d (%d blocks).\n", + STp->block_size, (STp->buffer)->buffer_size, + (STp->buffer)->buffer_blocks); if (STp->drv_write_prot) { STp->write_prot = 1; - DEBC(printk(ST_DEB_MSG "%s: Write protected\n", name)); + DEBC_printk(STp, "Write protected\n"); if (do_wait && ((st_flags & O_ACCMODE) == O_WRONLY || @@ -1141,8 +1147,7 @@ static int check_tape(struct scsi_tape *STp, struct file *filp) /* This code is reached when the device is opened for the first time after the driver has been initialized with tape in the drive and the partition support has been enabled. */ - DEBC(printk(ST_DEB_MSG - "%s: Updating partition number in status.\n", name)); + DEBC_printk(STp, "Updating partition number in status.\n"); if ((STp->partition = find_partition(STp)) < 0) { retval = STp->partition; goto err_out; @@ -1160,9 +1165,10 @@ static int check_tape(struct scsi_tape *STp, struct file *filp) if (STp->default_drvbuffer != 0xff) { if (st_int_ioctl(STp, MTSETDRVBUFFER, STp->default_drvbuffer)) - printk(KERN_WARNING - "%s: Can't set default drive buffering to %d.\n", - name, STp->default_drvbuffer); + st_printk(KERN_WARNING, STp, + "Can't set default drive " + "buffering to %d.\n", + STp->default_drvbuffer); } } @@ -1182,7 +1188,6 @@ static int st_open(struct inode *inode, struct file *filp) struct scsi_tape *STp; struct st_partstat *STps; int dev = TAPE_NR(inode); - char *name; /* * We really want to do nonseekable_open(inode, filp); here, but some @@ -1196,13 +1201,12 @@ static int st_open(struct inode *inode, struct file *filp) } filp->private_data = STp; - name = tape_name(STp); spin_lock(&st_use_lock); if (STp->in_use) { spin_unlock(&st_use_lock); scsi_tape_put(STp); - DEB( printk(ST_DEB_MSG "%s: Device already in use.\n", name); ) + DEBC_printk(STp, "Device already in use.\n"); return (-EBUSY); } @@ -1222,8 +1226,8 @@ static int st_open(struct inode *inode, struct file *filp) /* See that we have at least a one page buffer available */ if (!enlarge_buffer(STp->buffer, PAGE_SIZE, STp->restr_dma)) { - printk(KERN_WARNING "%s: Can't allocate one page tape buffer.\n", - name); + st_printk(KERN_WARNING, STp, + "Can't allocate one page tape buffer.\n"); retval = (-EOVERFLOW); goto err_out; } @@ -1279,7 +1283,6 @@ static int st_flush(struct file *filp, fl_owner_t id) struct scsi_tape *STp = filp->private_data; struct st_modedef *STm = &(STp->modes[STp->current_mode]); struct st_partstat *STps = &(STp->ps[STp->partition]); - char *name = tape_name(STp); if (file_count(filp) > 1) return 0; @@ -1292,24 +1295,25 @@ static int st_flush(struct file *filp, fl_owner_t id) if (STp->can_partitions && (result2 = switch_partition(STp)) < 0) { - DEBC(printk(ST_DEB_MSG - "%s: switch_partition at close failed.\n", name)); + DEBC_printk(STp, "switch_partition at close failed.\n"); if (result == 0) result = result2; goto out; } DEBC( if (STp->nbr_requests) - printk(KERN_DEBUG "%s: Number of r/w requests %d, dio used in %d, pages %d.\n", - name, STp->nbr_requests, STp->nbr_dio, STp->nbr_pages)); + st_printk(KERN_DEBUG, STp, + "Number of r/w requests %d, dio used in %d, " + "pages %d.\n", STp->nbr_requests, STp->nbr_dio, + STp->nbr_pages)); if (STps->rw == ST_WRITING && !STp->pos_unknown) { struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat; - DEBC(printk(ST_DEB_MSG "%s: Async write waits %d, finished %d.\n", - name, STp->nbr_waits, STp->nbr_finished); - ) - +#if DEBUG + DEBC_printk(STp, "Async write waits %d, finished %d.\n", + STp->nbr_waits, STp->nbr_finished); +#endif memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = WRITE_FILEMARKS; if (STp->immediate_filemark) @@ -1343,13 +1347,13 @@ static int st_flush(struct file *filp, fl_owner_t id) else { /* Write error */ st_release_request(SRpnt); SRpnt = NULL; - printk(KERN_ERR "%s: Error on write filemark.\n", name); + st_printk(KERN_ERR, STp, + "Error on write filemark.\n"); if (result == 0) result = (-EIO); } - DEBC(printk(ST_DEB_MSG "%s: Buffer flushed, %d EOF(s) written\n", - name, cmd[4])); + DEBC_printk(STp, "Buffer flushed, %d EOF(s) written\n", cmd[4]); } else if (!STp->rew_at_close) { STps = &(STp->ps[STp->partition]); if (!STm->sysv || STps->rw != ST_READING) { @@ -1447,9 +1451,10 @@ static ssize_t rw_checks(struct scsi_tape *STp, struct file *filp, size_t count) if (count == 0) goto out; - DEB( + DEB( if (!STp->in_use) { - printk(ST_DEB_MSG "%s: Incorrect device.\n", tape_name(STp)); + st_printk(ST_DEB_MSG, STp, + "Incorrect device.\n"); retval = (-EIO); goto out; } ) /* end DEB */ @@ -1519,8 +1524,9 @@ static int setup_buffering(struct scsi_tape *STp, const char __user *buf, if (bufsize > STbp->buffer_size && !enlarge_buffer(STbp, bufsize, STp->restr_dma)) { - printk(KERN_WARNING "%s: Can't allocate %d byte tape buffer.\n", - tape_name(STp), bufsize); + st_printk(KERN_WARNING, STp, + "Can't allocate %d byte tape buffer.\n", + bufsize); retval = (-EOVERFLOW); goto out; } @@ -1563,7 +1569,6 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) struct st_modedef *STm; struct st_partstat *STps; struct st_buffer *STbp; - char *name = tape_name(STp); if (mutex_lock_interruptible(&STp->lock)) return -ERESTARTSYS; @@ -1574,8 +1579,8 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) /* Write must be integral number of blocks */ if (STp->block_size != 0 && (count % STp->block_size) != 0) { - printk(KERN_WARNING "%s: Write not multiple of tape block size.\n", - name); + st_printk(KERN_WARNING, STp, + "Write not multiple of tape block size.\n"); retval = (-EINVAL); goto out; } @@ -1601,8 +1606,8 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) if (STm->default_compression != ST_DONT_TOUCH && !(STp->compression_changed)) { if (st_compression(STp, (STm->default_compression == ST_YES))) { - printk(KERN_WARNING "%s: Can't set default compression.\n", - name); + st_printk(KERN_WARNING, STp, + "Can't set default compression.\n"); if (modes_defined) { retval = (-EINVAL); goto out; @@ -1723,7 +1728,7 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) if (STbp->syscall_result != 0) { struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat; - DEBC(printk(ST_DEB_MSG "%s: Error on write:\n", name)); + DEBC_printk(STp, "Error on write:\n"); if (cmdstatp->have_sense && (cmdstatp->flags & SENSE_EOM)) { scode = cmdstatp->sense_hdr.sense_key; if (cmdstatp->remainder_valid) @@ -1750,9 +1755,9 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) if (STp->block_size == 0 || undone > 0 || count == 0) retval = (-ENOSPC); /* EOM within current request */ - DEBC(printk(ST_DEB_MSG - "%s: EOM with %d bytes unwritten.\n", - name, (int)count)); + DEBC_printk(STp, "EOM with %d " + "bytes unwritten.\n", + (int)count); } else { /* EOT within data buffered earlier (possible only in fixed block mode without direct i/o) */ @@ -1765,9 +1770,10 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) STp->block_size; } STps->eof = ST_EOM_OK; - DEBC(printk(ST_DEB_MSG - "%s: Retry write of %d bytes at EOM.\n", - name, STp->buffer->buffer_bytes)); + DEBC_printk(STp, "Retry " + "write of %d " + "bytes at EOM.\n", + STp->buffer->buffer_bytes); goto retry_write; } else { @@ -1778,9 +1784,8 @@ st_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos) STps->eof = ST_EOM_ERROR; STps->drv_block = (-1); /* Too cautious? */ retval = (-EIO); /* EOM for old data */ - DEBC(printk(ST_DEB_MSG - "%s: EOM with lost data.\n", - name)); + DEBC_printk(STp, "EOM with " + "lost data.\n"); } } } else { @@ -1839,7 +1844,6 @@ static long read_tape(struct scsi_tape *STp, long count, struct st_partstat *STps; struct st_buffer *STbp; int retval = 0; - char *name = tape_name(STp); if (count == 0) return 0; @@ -1891,12 +1895,12 @@ static long read_tape(struct scsi_tape *STp, long count, struct st_cmdstatus *cmdstatp = &STp->buffer->cmdstat; retval = 1; - DEBC(printk(ST_DEB_MSG "%s: Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n", - name, - SRpnt->sense[0], SRpnt->sense[1], - SRpnt->sense[2], SRpnt->sense[3], - SRpnt->sense[4], SRpnt->sense[5], - SRpnt->sense[6], SRpnt->sense[7])); + DEBC_printk(STp, + "Sense: %2x %2x %2x %2x %2x %2x %2x %2x\n", + SRpnt->sense[0], SRpnt->sense[1], + SRpnt->sense[2], SRpnt->sense[3], + SRpnt->sense[4], SRpnt->sense[5], + SRpnt->sense[6], SRpnt->sense[7]); if (cmdstatp->have_sense) { if (cmdstatp->sense_hdr.sense_key == BLANK_CHECK) @@ -1913,23 +1917,27 @@ static long read_tape(struct scsi_tape *STp, long count, transfer = bytes; if (cmdstatp->flags & SENSE_ILI) { /* ILI */ - if (STp->block_size == 0) { - if (transfer <= 0) { - if (transfer < 0) - printk(KERN_NOTICE - "%s: Failed to read %d byte block with %d byte transfer.\n", - name, bytes - transfer, bytes); - if (STps->drv_block >= 0) - STps->drv_block += 1; - STbp->buffer_bytes = 0; - return (-ENOMEM); - } + if (STp->block_size == 0 && + transfer < 0) { + st_printk(KERN_NOTICE, STp, + "Failed to read %d " + "byte block with %d " + "byte transfer.\n", + bytes - transfer, + bytes); + if (STps->drv_block >= 0) + STps->drv_block += 1; + STbp->buffer_bytes = 0; + return (-ENOMEM); + } else if (STp->block_size == 0) { STbp->buffer_bytes = bytes - transfer; } else { st_release_request(SRpnt); SRpnt = *aSRpnt = NULL; if (transfer == blks) { /* We did not get anything, error */ - printk(KERN_NOTICE "%s: Incorrect block size.\n", name); + st_printk(KERN_NOTICE, STp, + "Incorrect " + "block size.\n"); if (STps->drv_block >= 0) STps->drv_block += blks - transfer + 1; st_int_ioctl(STp, MTBSR, 1); @@ -1938,9 +1946,11 @@ static long read_tape(struct scsi_tape *STp, long count, /* We have some data, deliver it */ STbp->buffer_bytes = (blks - transfer) * STp->block_size; - DEBC(printk(ST_DEB_MSG - "%s: ILI but enough data received %ld %d.\n", - name, count, STbp->buffer_bytes)); + DEBC_printk(STp, "ILI but " + "enough data " + "received %ld " + "%d.\n", count, + STbp->buffer_bytes); if (STps->drv_block >= 0) STps->drv_block += 1; if (st_int_ioctl(STp, MTBSR, 1)) @@ -1956,9 +1966,9 @@ static long read_tape(struct scsi_tape *STp, long count, else STbp->buffer_bytes = bytes - transfer * STp->block_size; - DEBC(printk(ST_DEB_MSG - "%s: EOF detected (%d bytes read).\n", - name, STbp->buffer_bytes)); + DEBC_printk(STp, "EOF detected (%d " + "bytes read).\n", + STbp->buffer_bytes); } else if (cmdstatp->flags & SENSE_EOM) { if (STps->eof == ST_FM) STps->eof = ST_EOD_1; @@ -1970,20 +1980,20 @@ static long read_tape(struct scsi_tape *STp, long count, STbp->buffer_bytes = bytes - transfer * STp->block_size; - DEBC(printk(ST_DEB_MSG "%s: EOM detected (%d bytes read).\n", - name, STbp->buffer_bytes)); + DEBC_printk(STp, "EOM detected (%d " + "bytes read).\n", + STbp->buffer_bytes); } } - /* end of EOF, EOM, ILI test */ + /* end of EOF, EOM, ILI test */ else { /* nonzero sense key */ - DEBC(printk(ST_DEB_MSG - "%s: Tape error while reading.\n", name)); + DEBC_printk(STp, "Tape error while reading.\n"); STps->drv_block = (-1); if (STps->eof == ST_FM && cmdstatp->sense_hdr.sense_key == BLANK_CHECK) { - DEBC(printk(ST_DEB_MSG - "%s: Zero returned for first BLANK CHECK after EOF.\n", - name)); + DEBC_printk(STp, "Zero returned for " + "first BLANK CHECK " + "after EOF.\n"); STps->eof = ST_EOD_2; /* First BLANK_CHECK after FM */ } else /* Some other extended sense code */ retval = (-EIO); @@ -1992,13 +2002,13 @@ static long read_tape(struct scsi_tape *STp, long count, if (STbp->buffer_bytes < 0) /* Caused by bogus sense data */ STbp->buffer_bytes = 0; } - /* End of extended sense test */ + /* End of extended sense test */ else { /* Non-extended sense */ retval = STbp->syscall_result; } } - /* End of error handling */ + /* End of error handling */ else { /* Read successful */ STbp->buffer_bytes = bytes; if (STp->sili) /* In fixed block mode residual is always zero here */ @@ -2028,7 +2038,6 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) struct st_modedef *STm; struct st_partstat *STps; struct st_buffer *STbp = STp->buffer; - DEB( char *name = tape_name(STp); ) if (mutex_lock_interruptible(&STp->lock)) return -ERESTARTSYS; @@ -2053,11 +2062,12 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) goto out; STps->rw = ST_READING; } - DEB( + DEB( if (debugging && STps->eof != ST_NOEOF) - printk(ST_DEB_MSG "%s: EOF/EOM flag up (%d). Bytes %d\n", name, - STps->eof, STbp->buffer_bytes); - ) /* end DEB */ + st_printk(ST_DEB_MSG, STp, + "EOF/EOM flag up (%d). Bytes %d\n", + STps->eof, STbp->buffer_bytes); + ) /* end DEB */ retval = setup_buffering(STp, buf, count, 1); if (retval) @@ -2104,13 +2114,13 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) /* Move the data from driver buffer to user buffer */ if (STbp->buffer_bytes > 0) { - DEB( + DEB( if (debugging && STps->eof != ST_NOEOF) - printk(ST_DEB_MSG - "%s: EOF up (%d). Left %d, needed %d.\n", name, - STps->eof, STbp->buffer_bytes, - (int)(count - total)); - ) /* end DEB */ + st_printk(ST_DEB_MSG, STp, + "EOF up (%d). Left %d, needed %d.\n", + STps->eof, STbp->buffer_bytes, + (int)(count - total)); + ) /* end DEB */ transfer = STbp->buffer_bytes < count - total ? STbp->buffer_bytes : count - total; if (!do_dio) { @@ -2166,26 +2176,30 @@ st_read(struct file *filp, char __user *buf, size_t count, loff_t * ppos) DEB( /* Set the driver options */ -static void st_log_options(struct scsi_tape * STp, struct st_modedef * STm, char *name) +static void st_log_options(struct scsi_tape * STp, struct st_modedef * STm) { if (debugging) { - printk(KERN_INFO - "%s: Mode %d options: buffer writes: %d, async writes: %d, read ahead: %d\n", - name, STp->current_mode, STm->do_buffer_writes, STm->do_async_writes, - STm->do_read_ahead); - printk(KERN_INFO - "%s: can bsr: %d, two FMs: %d, fast mteom: %d, auto lock: %d,\n", - name, STp->can_bsr, STp->two_fm, STp->fast_mteom, STp->do_auto_lock); - printk(KERN_INFO - "%s: defs for wr: %d, no block limits: %d, partitions: %d, s2 log: %d\n", - name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions, - STp->scsi2_logical); - printk(KERN_INFO - "%s: sysv: %d nowait: %d sili: %d nowait_filemark: %d\n", - name, STm->sysv, STp->immediate, STp->sili, - STp->immediate_filemark); - printk(KERN_INFO "%s: debugging: %d\n", - name, debugging); + st_printk(KERN_INFO, STp, + "Mode %d options: buffer writes: %d, " + "async writes: %d, read ahead: %d\n", + STp->current_mode, STm->do_buffer_writes, + STm->do_async_writes, STm->do_read_ahead); + st_printk(KERN_INFO, STp, + " can bsr: %d, two FMs: %d, " + "fast mteom: %d, auto lock: %d,\n", + STp->can_bsr, STp->two_fm, STp->fast_mteom, + STp->do_auto_lock); + st_printk(KERN_INFO, STp, + " defs for wr: %d, no block limits: %d, " + "partitions: %d, s2 log: %d\n", + STm->defaults_for_writes, STp->omit_blklims, + STp->can_partitions, STp->scsi2_logical); + st_printk(KERN_INFO, STp, + " sysv: %d nowait: %d sili: %d " + "nowait_filemark: %d\n", + STm->sysv, STp->immediate, STp->sili, + STp->immediate_filemark); + st_printk(KERN_INFO, STp, " debugging: %d\n", debugging); } } ) @@ -2196,7 +2210,6 @@ static int st_set_options(struct scsi_tape *STp, long options) int value; long code; struct st_modedef *STm; - char *name = tape_name(STp); struct cdev *cd0, *cd1; struct device *d0, *d1; @@ -2212,9 +2225,8 @@ static int st_set_options(struct scsi_tape *STp, long options) STm->devs[0] = d0; STm->devs[1] = d1; modes_defined = 1; - DEBC(printk(ST_DEB_MSG - "%s: Initialized mode %d definition from mode 0\n", - name, STp->current_mode)); + DEBC_printk(STp, "Initialized mode %d definition from mode 0\n", + STp->current_mode); } code = options & MT_ST_OPTIONS; @@ -2236,7 +2248,7 @@ static int st_set_options(struct scsi_tape *STp, long options) STm->sysv = (options & MT_ST_SYSV) != 0; STp->sili = (options & MT_ST_SILI) != 0; DEB( debugging = (options & MT_ST_DEBUGGING) != 0; - st_log_options(STp, STm, name); ) + st_log_options(STp, STm); ) } else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) { value = (code == MT_ST_SETBOOLEANS); if ((options & MT_ST_BUFFER_WRITES) != 0) @@ -2270,21 +2282,21 @@ static int st_set_options(struct scsi_tape *STp, long options) STm->sysv = value; if ((options & MT_ST_SILI) != 0) STp->sili = value; - DEB( + DEB( if ((options & MT_ST_DEBUGGING) != 0) debugging = value; - st_log_options(STp, STm, name); ) + st_log_options(STp, STm); ) } else if (code == MT_ST_WRITE_THRESHOLD) { /* Retained for compatibility */ } else if (code == MT_ST_DEF_BLKSIZE) { value = (options & ~MT_ST_OPTIONS); if (value == ~MT_ST_OPTIONS) { STm->default_blksize = (-1); - DEBC( printk(KERN_INFO "%s: Default block size disabled.\n", name)); + DEBC_printk(STp, "Default block size disabled.\n"); } else { STm->default_blksize = value; - DEBC( printk(KERN_INFO "%s: Default block size set to %d bytes.\n", - name, STm->default_blksize)); + DEBC_printk(STp,"Default block size set to " + "%d bytes.\n", STm->default_blksize); if (STp->ready == ST_READY) { STp->blksize_changed = 0; set_mode_densblk(STp, STm); @@ -2294,13 +2306,13 @@ static int st_set_options(struct scsi_tape *STp, long options) value = (options & ~MT_ST_OPTIONS); if ((value & MT_ST_SET_LONG_TIMEOUT) != 0) { STp->long_timeout = (value & ~MT_ST_SET_LONG_TIMEOUT) * HZ; - DEBC( printk(KERN_INFO "%s: Long timeout set to %d seconds.\n", name, - (value & ~MT_ST_SET_LONG_TIMEOUT))); + DEBC_printk(STp, "Long timeout set to %d seconds.\n", + (value & ~MT_ST_SET_LONG_TIMEOUT)); } else { blk_queue_rq_timeout(STp->device->request_queue, value * HZ); - DEBC( printk(KERN_INFO "%s: Normal timeout set to %d seconds.\n", - name, value) ); + DEBC_printk(STp, "Normal timeout set to %d seconds.\n", + value); } } else if (code == MT_ST_SET_CLN) { value = (options & ~MT_ST_OPTIONS) & 0xff; @@ -2311,21 +2323,21 @@ static int st_set_options(struct scsi_tape *STp, long options) STp->cln_mode = value; STp->cln_sense_mask = (options >> 8) & 0xff; STp->cln_sense_value = (options >> 16) & 0xff; - printk(KERN_INFO - "%s: Cleaning request mode %d, mask %02x, value %02x\n", - name, value, STp->cln_sense_mask, STp->cln_sense_value); + st_printk(KERN_INFO, STp, + "Cleaning request mode %d, mask %02x, value %02x\n", + value, STp->cln_sense_mask, STp->cln_sense_value); } else if (code == MT_ST_DEF_OPTIONS) { code = (options & ~MT_ST_CLEAR_DEFAULT); value = (options & MT_ST_CLEAR_DEFAULT); if (code == MT_ST_DEF_DENSITY) { if (value == MT_ST_CLEAR_DEFAULT) { STm->default_density = (-1); - DEBC( printk(KERN_INFO "%s: Density default disabled.\n", - name)); + DEBC_printk(STp, + "Density default disabled.\n"); } else { STm->default_density = value & 0xff; - DEBC( printk(KERN_INFO "%s: Density default set to %x\n", - name, STm->default_density)); + DEBC_printk(STp, "Density default set to %x\n", + STm->default_density); if (STp->ready == ST_READY) { STp->density_changed = 0; set_mode_densblk(STp, STm); @@ -2334,31 +2346,33 @@ static int st_set_options(struct scsi_tape *STp, long options) } else if (code == MT_ST_DEF_DRVBUFFER) { if (value == MT_ST_CLEAR_DEFAULT) { STp->default_drvbuffer = 0xff; - DEBC( printk(KERN_INFO - "%s: Drive buffer default disabled.\n", name)); + DEBC_printk(STp, + "Drive buffer default disabled.\n"); } else { STp->default_drvbuffer = value & 7; - DEBC( printk(KERN_INFO - "%s: Drive buffer default set to %x\n", - name, STp->default_drvbuffer)); + DEBC_printk(STp, + "Drive buffer default set to %x\n", + STp->default_drvbuffer); if (STp->ready == ST_READY) st_int_ioctl(STp, MTSETDRVBUFFER, STp->default_drvbuffer); } } else if (code == MT_ST_DEF_COMPRESSION) { if (value == MT_ST_CLEAR_DEFAULT) { STm->default_compression = ST_DONT_TOUCH; - DEBC( printk(KERN_INFO - "%s: Compression default disabled.\n", name)); + DEBC_printk(STp, + "Compression default disabled.\n"); } else { if ((value & 0xff00) != 0) { STp->c_algo = (value & 0xff00) >> 8; - DEBC( printk(KERN_INFO "%s: Compression algorithm set to 0x%x.\n", - name, STp->c_algo)); + DEBC_printk(STp, "Compression " + "algorithm set to 0x%x.\n", + STp->c_algo); } if ((value & 0xff) != 0xff) { STm->default_compression = (value & 1 ? ST_YES : ST_NO); - DEBC( printk(KERN_INFO "%s: Compression default set to %x\n", - name, (value & 1))); + DEBC_printk(STp, "Compression default " + "set to %x\n", + (value & 1)); if (STp->ready == ST_READY) { STp->compression_changed = 0; st_compression(STp, (STm->default_compression == ST_YES)); @@ -2473,7 +2487,6 @@ static int st_compression(struct scsi_tape * STp, int state) int retval; int mpoffs; /* Offset to mode page start */ unsigned char *b_data = (STp->buffer)->b_data; - DEB( char *name = tape_name(STp); ) if (STp->ready != ST_READY) return (-EIO); @@ -2481,18 +2494,17 @@ static int st_compression(struct scsi_tape * STp, int state) /* Read the current page contents */ retval = read_mode_page(STp, COMPRESSION_PAGE, 0); if (retval) { - DEBC(printk(ST_DEB_MSG "%s: Compression mode page not supported.\n", - name)); + DEBC_printk(STp, "Compression mode page not supported.\n"); return (-EIO); } mpoffs = MODE_HEADER_LENGTH + b_data[MH_OFF_BDESCS_LENGTH]; - DEBC(printk(ST_DEB_MSG "%s: Compression state is %d.\n", name, - (b_data[mpoffs + CP_OFF_DCE_DCC] & DCE_MASK ? 1 : 0))); + DEBC_printk(STp, "Compression state is %d.\n", + (b_data[mpoffs + CP_OFF_DCE_DCC] & DCE_MASK ? 1 : 0)); /* Check if compression can be changed */ if ((b_data[mpoffs + CP_OFF_DCE_DCC] & DCC_MASK) == 0) { - DEBC(printk(ST_DEB_MSG "%s: Compression not supported.\n", name)); + DEBC_printk(STp, "Compression not supported.\n"); return (-EIO); } @@ -2510,11 +2522,10 @@ static int st_compression(struct scsi_tape * STp, int state) retval = write_mode_page(STp, COMPRESSION_PAGE, 0); if (retval) { - DEBC(printk(ST_DEB_MSG "%s: Compression change failed.\n", name)); + DEBC_printk(STp, "Compression change failed.\n"); return (-EIO); } - DEBC(printk(ST_DEB_MSG "%s: Compression state changed to %d.\n", - name, state)); + DEBC_printk(STp, "Compression state changed to %d.\n", state); STp->compression_changed = 1; return 0; @@ -2525,7 +2536,6 @@ static int st_compression(struct scsi_tape * STp, int state) static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_code) { int retval = (-EIO), timeout; - DEB( char *name = tape_name(STp); ) unsigned char cmd[MAX_COMMAND_SIZE]; struct st_partstat *STps; struct st_request *SRpnt; @@ -2546,9 +2556,9 @@ static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_cod */ if (load_code >= 1 + MT_ST_HPLOADER_OFFSET && load_code <= 6 + MT_ST_HPLOADER_OFFSET) { - DEBC(printk(ST_DEB_MSG "%s: Enhanced %sload slot %2d.\n", - name, (cmd[4]) ? "" : "un", - load_code - MT_ST_HPLOADER_OFFSET)); + DEBC_printk(STp, " Enhanced %sload slot %2d.\n", + (cmd[4]) ? "" : "un", + load_code - MT_ST_HPLOADER_OFFSET); cmd[3] = load_code - MT_ST_HPLOADER_OFFSET; /* MediaID field of C1553A */ } if (STp->immediate) { @@ -2560,9 +2570,9 @@ static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_cod DEBC( if (!load_code) - printk(ST_DEB_MSG "%s: Unloading tape.\n", name); + st_printk(ST_DEB_MSG, STp, "Unloading tape.\n"); else - printk(ST_DEB_MSG "%s: Loading tape.\n", name); + st_printk(ST_DEB_MSG, STp, "Loading tape.\n"); ); SRpnt = st_do_scsi(NULL, STp, cmd, 0, DMA_NONE, @@ -2597,17 +2607,24 @@ static int do_load_unload(struct scsi_tape *STp, struct file *filp, int load_cod #if DEBUG #define ST_DEB_FORWARD 0 #define ST_DEB_BACKWARD 1 -static void deb_space_print(char *name, int direction, char *units, unsigned char *cmd) +static void deb_space_print(struct scsi_tape *STp, int direction, char *units, unsigned char *cmd) { s32 sc; + if (!debugging) + return; + sc = cmd[2] & 0x80 ? 0xff000000 : 0; sc |= (cmd[2] << 16) | (cmd[3] << 8) | cmd[4]; if (direction) sc = -sc; - printk(ST_DEB_MSG "%s: Spacing tape %s over %d %s.\n", name, - direction ? "backward" : "forward", sc, units); + st_printk(ST_DEB_MSG, STp, "Spacing tape %s over %d %s.\n", + direction ? "backward" : "forward", sc, units); } +#else +#define ST_DEB_FORWARD 0 +#define ST_DEB_BACKWARD 1 +static void deb_space_print(struct scsi_tape *STp, int direction, char *units, unsigned char *cmd) {} #endif @@ -2623,7 +2640,6 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon struct st_partstat *STps; int fileno, blkno, at_sm, undone; int datalen = 0, direction = DMA_NONE; - char *name = tape_name(STp); WARN_ON(STp->buffer->do_dio != 0); if (STp->ready != ST_READY) { @@ -2648,7 +2664,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon cmd[2] = (arg >> 16); cmd[3] = (arg >> 8); cmd[4] = arg; - DEBC(deb_space_print(name, ST_DEB_FORWARD, "filemarks", cmd);) + deb_space_print(STp, ST_DEB_FORWARD, "filemarks", cmd); if (fileno >= 0) fileno += arg; blkno = 0; @@ -2663,7 +2679,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon cmd[2] = (ltmp >> 16); cmd[3] = (ltmp >> 8); cmd[4] = ltmp; - DEBC(deb_space_print(name, ST_DEB_BACKWARD, "filemarks", cmd);) + deb_space_print(STp, ST_DEB_BACKWARD, "filemarks", cmd); if (fileno >= 0) fileno -= arg; blkno = (-1); /* We can't know the block number */ @@ -2675,7 +2691,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon cmd[2] = (arg >> 16); cmd[3] = (arg >> 8); cmd[4] = arg; - DEBC(deb_space_print(name, ST_DEB_FORWARD, "blocks", cmd);) + deb_space_print(STp, ST_DEB_FORWARD, "blocks", cmd); if (blkno >= 0) blkno += arg; at_sm &= (arg == 0); @@ -2687,7 +2703,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon cmd[2] = (ltmp >> 16); cmd[3] = (ltmp >> 8); cmd[4] = ltmp; - DEBC(deb_space_print(name, ST_DEB_BACKWARD, "blocks", cmd);) + deb_space_print(STp, ST_DEB_BACKWARD, "blocks", cmd); if (blkno >= 0) blkno -= arg; at_sm &= (arg == 0); @@ -2698,7 +2714,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon cmd[2] = (arg >> 16); cmd[3] = (arg >> 8); cmd[4] = arg; - DEBC(deb_space_print(name, ST_DEB_FORWARD, "setmarks", cmd);) + deb_space_print(STp, ST_DEB_FORWARD, "setmarks", cmd); if (arg != 0) { blkno = fileno = (-1); at_sm = 1; @@ -2711,7 +2727,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon cmd[2] = (ltmp >> 16); cmd[3] = (ltmp >> 8); cmd[4] = ltmp; - DEBC(deb_space_print(name, ST_DEB_BACKWARD, "setmarks", cmd);) + deb_space_print(STp, ST_DEB_BACKWARD, "setmarks", cmd); if (arg != 0) { blkno = fileno = (-1); at_sm = 1; @@ -2732,13 +2748,19 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon cmd[3] = (arg >> 8); cmd[4] = arg; timeout = STp->device->request_queue->rq_timeout; - DEBC( - if (cmd_in != MTWSM) - printk(ST_DEB_MSG "%s: Writing %d filemarks.\n", name, - cmd[2] * 65536 + cmd[3] * 256 + cmd[4]); - else - printk(ST_DEB_MSG "%s: Writing %d setmarks.\n", name, - cmd[2] * 65536 + cmd[3] * 256 + cmd[4]); + DEBC( + if (cmd_in != MTWSM) + st_printk(ST_DEB_MSG, STp, + "Writing %d filemarks.\n", + cmd[2] * 65536 + + cmd[3] * 256 + + cmd[4]); + else + st_printk(ST_DEB_MSG, STp, + "Writing %d setmarks.\n", + cmd[2] * 65536 + + cmd[3] * 256 + + cmd[4]); ) if (fileno >= 0) fileno += arg; @@ -2751,11 +2773,11 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon cmd[1] = 1; /* Don't wait for completion */ timeout = STp->device->request_queue->rq_timeout; } - DEBC(printk(ST_DEB_MSG "%s: Rewinding tape.\n", name)); + DEBC_printk(STp, "Rewinding tape.\n"); fileno = blkno = at_sm = 0; break; case MTNOP: - DEBC(printk(ST_DEB_MSG "%s: No op on tape.\n", name)); + DEBC_printk(STp, "No op on tape.\n"); return 0; /* Should do something ? */ break; case MTRETEN: @@ -2765,7 +2787,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon timeout = STp->device->request_queue->rq_timeout; } cmd[4] = 3; - DEBC(printk(ST_DEB_MSG "%s: Retensioning tape.\n", name)); + DEBC_printk(STp, "Retensioning tape.\n"); fileno = blkno = at_sm = 0; break; case MTEOM: @@ -2783,8 +2805,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon fileno = (-1); cmd[0] = SPACE; cmd[1] = 3; - DEBC(printk(ST_DEB_MSG "%s: Spacing to end of recorded medium.\n", - name)); + DEBC_printk(STp, "Spacing to end of recorded medium.\n"); blkno = -1; at_sm = 0; break; @@ -2800,7 +2821,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon else timeout = STp->long_timeout * 8; - DEBC(printk(ST_DEB_MSG "%s: Erasing tape.\n", name)); + DEBC_printk(STp, "Erasing tape.\n"); fileno = blkno = at_sm = 0; break; case MTSETBLK: /* Set block length */ @@ -2815,7 +2836,7 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon STp->max_block > 0 && ((arg & MT_ST_BLKSIZE_MASK) < STp->min_block || (arg & MT_ST_BLKSIZE_MASK) > STp->max_block)) { - printk(KERN_WARNING "%s: Illegal block size.\n", name); + st_printk(KERN_WARNING, STp, "Illegal block size.\n"); return (-EINVAL); } cmd[0] = MODE_SELECT; @@ -2848,21 +2869,21 @@ static int st_int_ioctl(struct scsi_tape *STp, unsigned int cmd_in, unsigned lon (STp->buffer)->b_data[10] = (ltmp >> 8); (STp->buffer)->b_data[11] = ltmp; timeout = STp->device->request_queue->rq_timeout; - DEBC( + DEBC( if (cmd_in == MTSETBLK || cmd_in == SET_DENS_AND_BLK) - printk(ST_DEB_MSG - "%s: Setting block size to %d bytes.\n", name, - (STp->buffer)->b_data[9] * 65536 + - (STp->buffer)->b_data[10] * 256 + - (STp->buffer)->b_data[11]); + st_printk(ST_DEB_MSG, STp, + "Setting block size to %d bytes.\n", + (STp->buffer)->b_data[9] * 65536 + + (STp->buffer)->b_data[10] * 256 + + (STp->buffer)->b_data[11]); if (cmd_in == MTSETDENSITY || cmd_in == SET_DENS_AND_BLK) - printk(ST_DEB_MSG - "%s: Setting density code to %x.\n", name, - (STp->buffer)->b_data[4]); + st_printk(ST_DEB_MSG, STp, + "Setting density code to %x.\n", + (STp->buffer)->b_data[4]); if (cmd_in == MTSETDRVBUFFER) - printk(ST_DEB_MSG - "%s: Setting drive buffer code to %d.\n", name, - ((STp->buffer)->b_data[2] >> 4) & 7); + st_printk(ST_DEB_MSG, STp, + "Setting drive buffer code to %d.\n", + ((STp->buffer)->b_data[2] >> 4) & 7); ) break; default: @@ -3019,7 +3040,6 @@ static int get_location(struct scsi_tape *STp, unsigned int *block, int *partiti int result; unsigned char scmd[MAX_COMMAND_SIZE]; struct st_request *SRpnt; - DEB( char *name = tape_name(STp); ) if (STp->ready != ST_READY) return (-EIO); @@ -3043,7 +3063,7 @@ static int get_location(struct scsi_tape *STp, unsigned int *block, int *partiti (STp->device->scsi_level >= SCSI_2 && ((STp->buffer)->b_data[0] & 4) != 0)) { *block = *partition = 0; - DEBC(printk(ST_DEB_MSG "%s: Can't read tape position.\n", name)); + DEBC_printk(STp, " Can't read tape position.\n"); result = (-EIO); } else { result = 0; @@ -3062,8 +3082,8 @@ static int get_location(struct scsi_tape *STp, unsigned int *block, int *partiti (STp->buffer)->b_data[1] == 0) /* BOP of partition 0 */ STp->ps[0].drv_block = STp->ps[0].drv_file = 0; } - DEBC(printk(ST_DEB_MSG "%s: Got tape pos. blk %d part %d.\n", name, - *block, *partition)); + DEBC_printk(STp, "Got tape pos. blk %d part %d.\n", + *block, *partition); } st_release_request(SRpnt); SRpnt = NULL; @@ -3083,15 +3103,14 @@ static int set_location(struct scsi_tape *STp, unsigned int block, int partition int timeout; unsigned char scmd[MAX_COMMAND_SIZE]; struct st_request *SRpnt; - DEB( char *name = tape_name(STp); ) if (STp->ready != ST_READY) return (-EIO); timeout = STp->long_timeout; STps = &(STp->ps[STp->partition]); - DEBC(printk(ST_DEB_MSG "%s: Setting block to %d and partition to %d.\n", - name, block, partition)); + DEBC_printk(STp, "Setting block to %d and partition to %d.\n", + block, partition); DEB(if (partition < 0) return (-EIO); ) @@ -3105,9 +3124,9 @@ static int set_location(struct scsi_tape *STp, unsigned int block, int partition else { STps->last_block_valid = 1; STps->last_block_visited = blk; - DEBC(printk(ST_DEB_MSG - "%s: Visited block %d for partition %d saved.\n", - name, blk, STp->partition)); + DEBC_printk(STp, "Visited block %d for " + "partition %d saved.\n", + blk, STp->partition); } } @@ -3129,9 +3148,9 @@ static int set_location(struct scsi_tape *STp, unsigned int block, int partition if (STp->partition != partition) { scmd[1] |= 2; scmd[8] = partition; - DEBC(printk(ST_DEB_MSG - "%s: Trying to change partition from %d to %d\n", - name, STp->partition, partition)); + DEBC_printk(STp, "Trying to change partition " + "from %d to %d\n", STp->partition, + partition); } } if (STp->immediate) { @@ -3222,7 +3241,6 @@ static int switch_partition(struct scsi_tape *STp) static int nbr_partitions(struct scsi_tape *STp) { int result; - DEB( char *name = tape_name(STp); ) if (STp->ready != ST_READY) return (-EIO); @@ -3230,13 +3248,12 @@ static int nbr_partitions(struct scsi_tape *STp) result = read_mode_page(STp, PART_PAGE, 1); if (result) { - DEBC(printk(ST_DEB_MSG "%s: Can't read medium partition page.\n", - name)); + DEBC_printk(STp, "Can't read medium partition page.\n"); result = (-EIO); } else { result = (STp->buffer)->b_data[MODE_HEADER_LENGTH + PP_OFF_NBR_ADD_PARTS] + 1; - DEBC(printk(ST_DEB_MSG "%s: Number of partitions %d.\n", name, result)); + DEBC_printk(STp, "Number of partitions %d.\n", result); } return result; @@ -3264,21 +3281,20 @@ static int nbr_partitions(struct scsi_tape *STp) */ static int partition_tape(struct scsi_tape *STp, int size) { - char *name = tape_name(STp); int result; int pgo, psd_cnt, psdo; unsigned char *bp; result = read_mode_page(STp, PART_PAGE, 0); if (result) { - DEBC(printk(ST_DEB_MSG "%s: Can't read partition mode page.\n", name)); + DEBC_printk(STp, "Can't read partition mode page.\n"); return result; } /* The mode page is in the buffer. Let's modify it and write it. */ bp = (STp->buffer)->b_data; pgo = MODE_HEADER_LENGTH + bp[MH_OFF_BDESCS_LENGTH]; - DEBC(printk(ST_DEB_MSG "%s: Partition page length is %d bytes.\n", - name, bp[pgo + MP_OFF_PAGE_LENGTH] + 2)); + DEBC_printk(STp, "Partition page length is %d bytes.\n", + bp[pgo + MP_OFF_PAGE_LENGTH] + 2); psd_cnt = (bp[pgo + MP_OFF_PAGE_LENGTH] + 2 - PART_PAGE_FIXED_LENGTH) / 2; psdo = pgo + PART_PAGE_FIXED_LENGTH; @@ -3288,25 +3304,23 @@ static int partition_tape(struct scsi_tape *STp, int size) } memset(bp + psdo, 0, bp[pgo + PP_OFF_NBR_ADD_PARTS] * 2); - DEBC(printk("%s: psd_cnt %d, max.parts %d, nbr_parts %d\n", name, + DEBC_printk(STp, "psd_cnt %d, max.parts %d, nbr_parts %d\n", psd_cnt, bp[pgo + PP_OFF_MAX_ADD_PARTS], - bp[pgo + PP_OFF_NBR_ADD_PARTS])); + bp[pgo + PP_OFF_NBR_ADD_PARTS]); if (size <= 0) { bp[pgo + PP_OFF_NBR_ADD_PARTS] = 0; if (psd_cnt <= bp[pgo + PP_OFF_MAX_ADD_PARTS]) bp[pgo + MP_OFF_PAGE_LENGTH] = 6; - DEBC(printk(ST_DEB_MSG "%s: Formatting tape with one partition.\n", - name)); + DEBC_printk(STp, "Formatting tape with one partition.\n"); } else { bp[psdo] = (size >> 8) & 0xff; bp[psdo + 1] = size & 0xff; bp[pgo + 3] = 1; if (bp[pgo + MP_OFF_PAGE_LENGTH] < 8) bp[pgo + MP_OFF_PAGE_LENGTH] = 8; - DEBC(printk(ST_DEB_MSG - "%s: Formatting tape with two partitions (1 = %d MB).\n", - name, size)); + DEBC_printk(STp, "Formatting tape with two partitions " + "(1 = %d MB).\n", size); } bp[pgo + PP_OFF_PART_UNITS] = 0; bp[pgo + PP_OFF_RESERVED] = 0; @@ -3314,7 +3328,7 @@ static int partition_tape(struct scsi_tape *STp, int size) result = write_mode_page(STp, PART_PAGE, 1); if (result) { - printk(KERN_INFO "%s: Partitioning of tape failed.\n", name); + st_printk(KERN_INFO, STp, "Partitioning of tape failed.\n"); result = (-EIO); } @@ -3332,15 +3346,14 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) struct scsi_tape *STp = file->private_data; struct st_modedef *STm; struct st_partstat *STps; - char *name = tape_name(STp); void __user *p = (void __user *)arg; if (mutex_lock_interruptible(&STp->lock)) return -ERESTARTSYS; - DEB( + DEB( if (debugging && !STp->in_use) { - printk(ST_DEB_MSG "%s: Incorrect device.\n", name); + st_printk(ST_DEB_MSG, STp, "Incorrect device.\n"); retval = (-EIO); goto out; } ) /* end DEB */ @@ -3378,8 +3391,8 @@ static long st_ioctl(struct file *file, unsigned int cmd_in, unsigned long arg) } if (mtc.mt_op == MTSETDRVBUFFER && !capable(CAP_SYS_ADMIN)) { - printk(KERN_WARNING - "%s: MTSETDRVBUFFER only allowed for root.\n", name); + st_printk(KERN_WARNING, STp, + "MTSETDRVBUFFER only allowed for root.\n"); retval = (-EPERM); goto out; } @@ -4087,7 +4100,8 @@ static int st_probe(struct device *dev) return -ENODEV; if ((stp = st_incompatible(SDp))) { sdev_printk(KERN_INFO, SDp, "Found incompatible tape\n"); - printk(KERN_INFO "st: The suggested driver is %s.\n", stp); + sdev_printk(KERN_INFO, SDp, + "st: The suggested driver is %s.\n", stp); return -ENODEV; } @@ -4096,20 +4110,23 @@ static int st_probe(struct device *dev) i = st_max_sg_segs; buffer = new_tape_buffer((SDp->host)->unchecked_isa_dma, i); if (buffer == NULL) { - printk(KERN_ERR - "st: Can't allocate new tape buffer. Device not attached.\n"); + sdev_printk(KERN_ERR, SDp, + "st: Can't allocate new tape buffer. " + "Device not attached.\n"); goto out; } disk = alloc_disk(1); if (!disk) { - printk(KERN_ERR "st: out of memory. Device not attached.\n"); + sdev_printk(KERN_ERR, SDp, + "st: out of memory. Device not attached.\n"); goto out_buffer_free; } tpnt = kzalloc(sizeof(struct scsi_tape), GFP_ATOMIC); if (tpnt == NULL) { - printk(KERN_ERR "st: Can't allocate device descriptor.\n"); + sdev_printk(KERN_ERR, SDp, + "st: Can't allocate device descriptor.\n"); goto out_put_disk; } kref_init(&tpnt->kref); diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c index 9969fa1ef7c4..fecac5d03fdd 100644 --- a/drivers/scsi/storvsc_drv.c +++ b/drivers/scsi/storvsc_drv.c @@ -33,6 +33,7 @@ #include <linux/device.h> #include <linux/hyperv.h> #include <linux/mempool.h> +#include <linux/blkdev.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> #include <scsi/scsi_host.h> @@ -326,21 +327,23 @@ MODULE_PARM_DESC(storvsc_ringbuffer_size, "Ring buffer size (bytes)"); */ static int storvsc_timeout = 180; +static int msft_blist_flags = BLIST_TRY_VPD_PAGES; + #define STORVSC_MAX_IO_REQUESTS 200 static void storvsc_on_channel_callback(void *context); -/* - * In Hyper-V, each port/path/target maps to 1 scsi host adapter. In - * reality, the path/target is not used (ie always set to 0) so our - * scsi host adapter essentially has 1 bus with 1 target that contains - * up to 256 luns. - */ -#define STORVSC_MAX_LUNS_PER_TARGET 64 -#define STORVSC_MAX_TARGETS 1 -#define STORVSC_MAX_CHANNELS 1 +#define STORVSC_MAX_LUNS_PER_TARGET 255 +#define STORVSC_MAX_TARGETS 2 +#define STORVSC_MAX_CHANNELS 8 +#define STORVSC_FC_MAX_LUNS_PER_TARGET 255 +#define STORVSC_FC_MAX_TARGETS 128 +#define STORVSC_FC_MAX_CHANNELS 8 +#define STORVSC_IDE_MAX_LUNS_PER_TARGET 64 +#define STORVSC_IDE_MAX_TARGETS 1 +#define STORVSC_IDE_MAX_CHANNELS 1 struct storvsc_cmd_request { struct list_head entry; @@ -1017,6 +1020,13 @@ static void storvsc_handle_error(struct vmscsi_request *vm_srb, case ATA_12: set_host_byte(scmnd, DID_PASSTHROUGH); break; + /* + * On Some Windows hosts TEST_UNIT_READY command can return + * SRB_STATUS_ERROR, let the upper level code deal with it + * based on the sense information. + */ + case TEST_UNIT_READY: + break; default: set_host_byte(scmnd, DID_TARGET_FAILURE); } @@ -1441,6 +1451,14 @@ static int storvsc_device_configure(struct scsi_device *sdevice) sdevice->no_write_same = 1; + /* + * Add blist flags to permit the reading of the VPD pages even when + * the target may claim SPC-2 compliance. MSFT targets currently + * claim SPC-2 compliance while they implement post SPC-2 features. + * With this patch we can correctly handle WRITE_SAME_16 issues. + */ + sdevice->sdev_bflags |= msft_blist_flags; + return 0; } @@ -1518,6 +1536,16 @@ static int storvsc_host_reset_handler(struct scsi_cmnd *scmnd) return SUCCESS; } +/* + * The host guarantees to respond to each command, although I/O latencies might + * be unbounded on Azure. Reset the timer unconditionally to give the host a + * chance to perform EH. + */ +static enum blk_eh_timer_return storvsc_eh_timed_out(struct scsi_cmnd *scmnd) +{ + return BLK_EH_RESET_TIMER; +} + static bool storvsc_scsi_cmd_ok(struct scsi_cmnd *scmnd) { bool allowed = true; @@ -1553,9 +1581,19 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) struct vmscsi_request *vm_srb; struct stor_mem_pools *memp = scmnd->device->hostdata; - if (!storvsc_scsi_cmd_ok(scmnd)) { - scmnd->scsi_done(scmnd); - return 0; + if (vmstor_current_major <= VMSTOR_WIN8_MAJOR) { + /* + * On legacy hosts filter unimplemented commands. + * Future hosts are expected to correctly handle + * unsupported commands. Furthermore, it is + * possible that some of the currently + * unsupported commands maybe supported in + * future versions of the host. + */ + if (!storvsc_scsi_cmd_ok(scmnd)) { + scmnd->scsi_done(scmnd); + return 0; + } } request_size = sizeof(struct storvsc_cmd_request); @@ -1580,26 +1618,24 @@ static int storvsc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *scmnd) vm_srb = &cmd_request->vstor_packet.vm_srb; vm_srb->win8_extension.time_out_value = 60; + vm_srb->win8_extension.srb_flags |= + (SRB_FLAGS_QUEUE_ACTION_ENABLE | + SRB_FLAGS_DISABLE_SYNCH_TRANSFER); /* Build the SRB */ switch (scmnd->sc_data_direction) { case DMA_TO_DEVICE: vm_srb->data_in = WRITE_TYPE; vm_srb->win8_extension.srb_flags |= SRB_FLAGS_DATA_OUT; - vm_srb->win8_extension.srb_flags |= - (SRB_FLAGS_QUEUE_ACTION_ENABLE | - SRB_FLAGS_DISABLE_SYNCH_TRANSFER); break; case DMA_FROM_DEVICE: vm_srb->data_in = READ_TYPE; vm_srb->win8_extension.srb_flags |= SRB_FLAGS_DATA_IN; - vm_srb->win8_extension.srb_flags |= - (SRB_FLAGS_QUEUE_ACTION_ENABLE | - SRB_FLAGS_DISABLE_SYNCH_TRANSFER); break; default: vm_srb->data_in = UNKNOWN_TYPE; - vm_srb->win8_extension.srb_flags = 0; + vm_srb->win8_extension.srb_flags |= (SRB_FLAGS_DATA_IN | + SRB_FLAGS_DATA_OUT); break; } @@ -1687,11 +1723,11 @@ static struct scsi_host_template scsi_driver = { .bios_param = storvsc_get_chs, .queuecommand = storvsc_queuecommand, .eh_host_reset_handler = storvsc_host_reset_handler, + .eh_timed_out = storvsc_eh_timed_out, .slave_alloc = storvsc_device_alloc, .slave_destroy = storvsc_device_destroy, .slave_configure = storvsc_device_configure, - .cmd_per_lun = 1, - /* 64 max_queue * 1 target */ + .cmd_per_lun = 255, .can_queue = STORVSC_MAX_IO_REQUESTS*STORVSC_MAX_TARGETS, .this_id = -1, /* no use setting to 0 since ll_blk_rw reset it to 1 */ @@ -1743,19 +1779,25 @@ static int storvsc_probe(struct hv_device *device, * set state to properly communicate with the host. */ - if (vmbus_proto_version == VERSION_WIN8) { - sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; - vmscsi_size_delta = 0; - vmstor_current_major = VMSTOR_WIN8_MAJOR; - vmstor_current_minor = VMSTOR_WIN8_MINOR; - } else { + switch (vmbus_proto_version) { + case VERSION_WS2008: + case VERSION_WIN7: sense_buffer_size = PRE_WIN8_STORVSC_SENSE_BUFFER_SIZE; vmscsi_size_delta = sizeof(struct vmscsi_win8_extension); vmstor_current_major = VMSTOR_WIN7_MAJOR; vmstor_current_minor = VMSTOR_WIN7_MINOR; + break; + default: + sense_buffer_size = POST_WIN7_STORVSC_SENSE_BUFFER_SIZE; + vmscsi_size_delta = 0; + vmstor_current_major = VMSTOR_WIN8_MAJOR; + vmstor_current_minor = VMSTOR_WIN8_MINOR; + break; } - + if (dev_id->driver_data == SFC_GUID) + scsi_driver.can_queue = (STORVSC_MAX_IO_REQUESTS * + STORVSC_FC_MAX_TARGETS); host = scsi_host_alloc(&scsi_driver, sizeof(struct hv_host_device)); if (!host) @@ -1789,12 +1831,25 @@ static int storvsc_probe(struct hv_device *device, host_dev->path = stor_device->path_id; host_dev->target = stor_device->target_id; - /* max # of devices per target */ - host->max_lun = STORVSC_MAX_LUNS_PER_TARGET; - /* max # of targets per channel */ - host->max_id = STORVSC_MAX_TARGETS; - /* max # of channels */ - host->max_channel = STORVSC_MAX_CHANNELS - 1; + switch (dev_id->driver_data) { + case SFC_GUID: + host->max_lun = STORVSC_FC_MAX_LUNS_PER_TARGET; + host->max_id = STORVSC_FC_MAX_TARGETS; + host->max_channel = STORVSC_FC_MAX_CHANNELS - 1; + break; + + case SCSI_GUID: + host->max_lun = STORVSC_MAX_LUNS_PER_TARGET; + host->max_id = STORVSC_MAX_TARGETS; + host->max_channel = STORVSC_MAX_CHANNELS - 1; + break; + + default: + host->max_lun = STORVSC_IDE_MAX_LUNS_PER_TARGET; + host->max_id = STORVSC_IDE_MAX_TARGETS; + host->max_channel = STORVSC_IDE_MAX_CHANNELS - 1; + break; + } /* max cmd length */ host->max_cmd_len = STORVSC_MAX_CMD_LEN; diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c index 88220794cc98..1a2367a1b1f2 100644 --- a/drivers/scsi/sun3_NCR5380.c +++ b/drivers/scsi/sun3_NCR5380.c @@ -355,17 +355,18 @@ static void __init init_tags( void ) static int is_lun_busy(struct scsi_cmnd *cmd, int should_be_tagged) { + u8 lun = cmd->device->lun; SETUP_HOSTDATA(cmd->device->host); - if (hostdata->busy[cmd->device->id] & (1 << cmd->device->lun)) + if (hostdata->busy[cmd->device->id] & (1 << lun)) return( 1 ); if (!should_be_tagged || !setup_use_tagged_queuing || !cmd->device->tagged_supported) return( 0 ); - if (TagAlloc[cmd->device->id][cmd->device->lun].nr_allocated >= - TagAlloc[cmd->device->id][cmd->device->lun].queue_size ) { + if (TagAlloc[cmd->device->id][lun].nr_allocated >= + TagAlloc[cmd->device->id][lun].queue_size ) { dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d: no free tags\n", - H_NO(cmd), cmd->device->id, cmd->device->lun ); + H_NO(cmd), cmd->device->id, lun ); return( 1 ); } return( 0 ); @@ -379,6 +380,7 @@ static int is_lun_busy(struct scsi_cmnd *cmd, int should_be_tagged) static void cmd_get_tag(struct scsi_cmnd *cmd, int should_be_tagged) { + u8 lun = cmd->device->lun; SETUP_HOSTDATA(cmd->device->host); /* If we or the target don't support tagged queuing, allocate the LUN for @@ -387,19 +389,19 @@ static void cmd_get_tag(struct scsi_cmnd *cmd, int should_be_tagged) if (!should_be_tagged || !setup_use_tagged_queuing || !cmd->device->tagged_supported) { cmd->tag = TAG_NONE; - hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); + hostdata->busy[cmd->device->id] |= (1 << lun); dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d now allocated by untagged " - "command\n", H_NO(cmd), cmd->device->id, cmd->device->lun ); + "command\n", H_NO(cmd), cmd->device->id, lun ); } else { - TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun]; + TAG_ALLOC *ta = &TagAlloc[cmd->device->id][lun]; cmd->tag = find_first_zero_bit( &ta->allocated, MAX_TAGS ); set_bit( cmd->tag, &ta->allocated ); ta->nr_allocated++; dprintk(NDEBUG_TAGS, "scsi%d: using tag %d for target %d lun %d " "(now %d tags in use)\n", - H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun, + H_NO(cmd), cmd->tag, cmd->device->id, lun, ta->nr_allocated ); } } @@ -411,23 +413,24 @@ static void cmd_get_tag(struct scsi_cmnd *cmd, int should_be_tagged) static void cmd_free_tag(struct scsi_cmnd *cmd) { + u8 lun = cmd->device->lun; SETUP_HOSTDATA(cmd->device->host); if (cmd->tag == TAG_NONE) { - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); + hostdata->busy[cmd->device->id] &= ~(1 << lun); dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d untagged cmd finished\n", - H_NO(cmd), cmd->device->id, cmd->device->lun ); + H_NO(cmd), cmd->device->id, lun ); } else if (cmd->tag >= MAX_TAGS) { printk(KERN_NOTICE "scsi%d: trying to free bad tag %d!\n", H_NO(cmd), cmd->tag ); } else { - TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun]; + TAG_ALLOC *ta = &TagAlloc[cmd->device->id][lun]; clear_bit( cmd->tag, &ta->allocated ); ta->nr_allocated--; dprintk(NDEBUG_TAGS, "scsi%d: freed tag %d for target %d lun %d\n", - H_NO(cmd), cmd->tag, cmd->device->id, cmd->device->lun ); + H_NO(cmd), cmd->tag, cmd->device->id, lun ); } } @@ -659,7 +662,7 @@ static void lprint_Scsi_Cmnd(Scsi_Cmnd *cmd) { int i, s; unsigned char *command; - printk("scsi%d: destination target %d, lun %d\n", + printk("scsi%d: destination target %d, lun %llu\n", H_NO(cmd), cmd->device->id, cmd->device->lun); printk(KERN_CONT " command = "); command = cmd->cmnd; @@ -705,7 +708,7 @@ static void show_Scsi_Cmnd(Scsi_Cmnd *cmd, struct seq_file *m) { int i, s; unsigned char *command; - seq_printf(m, "scsi%d: destination target %d, lun %d\n", + seq_printf(m, "scsi%d: destination target %d, lun %llu\n", H_NO(cmd), cmd->device->id, cmd->device->lun); seq_printf(m, " command = "); command = cmd->cmnd; @@ -1007,7 +1010,7 @@ static void NCR5380_main (struct work_struct *bl) prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp) ) { if (prev != tmp) - dprintk(NDEBUG_LISTS, "MAIN tmp=%p target=%d busy=%d lun=%d\n", tmp, tmp->device->id, hostdata->busy[tmp->device->id], tmp->device->lun); + dprintk(NDEBUG_LISTS, "MAIN tmp=%p target=%d busy=%d lun=%llu\n", tmp, tmp->device->id, hostdata->busy[tmp->device->id], tmp->device->lun); /* When we find one, remove it from the issue queue. */ /* ++guenther: possible race with Falcon locking */ if ( @@ -1038,7 +1041,7 @@ static void NCR5380_main (struct work_struct *bl) * issue queue so we can keep trying. */ dprintk(NDEBUG_MAIN, "scsi%d: main(): command for target %d " - "lun %d removed from issue_queue\n", + "lun %llu removed from issue_queue\n", HOSTNO, tmp->device->id, tmp->device->lun); /* * REQUEST SENSE commands are issued without tagged @@ -2020,7 +2023,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) * accesses to this device will use the * polled-IO. */ printk(KERN_NOTICE "scsi%d: switching target %d " - "lun %d to slow handshake\n", HOSTNO, + "lun %llu to slow handshake\n", HOSTNO, cmd->device->id, cmd->device->lun); cmd->device->borken = 1; NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | @@ -2078,7 +2081,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) /* Accept message by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); - dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %d linked command " + dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %llu linked command " "complete.\n", HOSTNO, cmd->device->id, cmd->device->lun); /* Enable reselect interrupts */ @@ -2090,7 +2093,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) */ if (!cmd->next_link) { - printk(KERN_NOTICE "scsi%d: target %d lun %d " + printk(KERN_NOTICE "scsi%d: target %d lun %llu " "linked command complete, no next_link\n", HOSTNO, cmd->device->id, cmd->device->lun); sink = 1; @@ -2103,7 +2106,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) * and don't free it! */ cmd->next_link->tag = cmd->tag; cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); - dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %d linked request " + dprintk(NDEBUG_LINKED, "scsi%d: target %d lun %llu linked request " "done, calling scsi_done().\n", HOSTNO, cmd->device->id, cmd->device->lun); #ifdef NCR5380_STATS @@ -2118,7 +2121,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) /* Accept message by clearing ACK */ NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE); hostdata->connected = NULL; - dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d, lun %d " + dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d, lun %llu " "completed\n", HOSTNO, cmd->device->id, cmd->device->lun); #ifdef SUPPORT_TAGS cmd_free_tag( cmd ); @@ -2132,7 +2135,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) /* ++Andreas: the mid level code knows about QUEUE_FULL now. */ TAG_ALLOC *ta = &TagAlloc[cmd->device->id][cmd->device->lun]; - dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d returned " + dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %llu returned " "QUEUE_FULL after %d commands\n", HOSTNO, cmd->device->id, cmd->device->lun, ta->nr_allocated); @@ -2228,7 +2231,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) cmd->device->tagged_supported = 0; hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); cmd->tag = TAG_NONE; - dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %d rejected " + dprintk(NDEBUG_TAGS, "scsi%d: target %d lun %llu rejected " "QUEUE_TAG message; tagged queuing " "disabled\n", HOSTNO, cmd->device->id, cmd->device->lun); @@ -2245,7 +2248,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) hostdata->connected = NULL; hostdata->disconnected_queue = cmd; local_irq_restore(flags); - dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d lun %d was " + dprintk(NDEBUG_QUEUES, "scsi%d: command for target %d lun %llu was " "moved from connected to the " "disconnected_queue\n", HOSTNO, cmd->device->id, cmd->device->lun); @@ -2349,12 +2352,12 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) printk("\n"); } else if (tmp != EXTENDED_MESSAGE) printk(KERN_DEBUG "scsi%d: rejecting unknown " - "message %02x from target %d, lun %d\n", + "message %02x from target %d, lun %llu\n", HOSTNO, tmp, cmd->device->id, cmd->device->lun); else printk(KERN_DEBUG "scsi%d: rejecting unknown " "extended message " - "code %02x, length %d from target %d, lun %d\n", + "code %02x, length %d from target %d, lun %llu\n", HOSTNO, extended_msg[1], extended_msg[0], cmd->device->id, cmd->device->lun); @@ -2576,7 +2579,7 @@ static void NCR5380_reselect (struct Scsi_Host *instance) #endif hostdata->connected = tmp; - dprintk(NDEBUG_RESELECTION, "scsi%d: nexus established, target = %d, lun = %d, tag = %d\n", + dprintk(NDEBUG_RESELECTION, "scsi%d: nexus established, target = %d, lun = %llu, tag = %d\n", HOSTNO, tmp->device->id, tmp->device->lun, tmp->tag); } diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c index 6d3ee1ab6362..e59e6f96b725 100644 --- a/drivers/scsi/sym53c8xx_2/sym_glue.c +++ b/drivers/scsi/sym53c8xx_2/sym_glue.c @@ -851,7 +851,7 @@ static void sym53c8xx_slave_destroy(struct scsi_device *sdev) * so let's try to stop all on-going I/O. */ starget_printk(KERN_WARNING, tp->starget, - "Removing busy LCB (%d)\n", sdev->lun); + "Removing busy LCB (%d)\n", (u8)sdev->lun); sym_reset_scsi_bus(np, 1); } diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h index 5a80cbac3f92..a141b1758033 100644 --- a/drivers/scsi/sym53c8xx_2/sym_hipd.h +++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h @@ -581,7 +581,7 @@ struct sym_pmc { #define sym_lp(tp, lun) (!lun) ? (tp)->lun0p : NULL #else #define sym_lp(tp, lun) \ - (!lun) ? (tp)->lun0p : (tp)->lunmp ? (tp)->lunmp[(lun)] : NULL + (!lun) ? (tp)->lun0p : (tp)->lunmp ? (tp)->lunmp[((u8)lun)] : NULL #endif /* diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c index b006cf789ba1..764575726c85 100644 --- a/drivers/scsi/tmscsim.c +++ b/drivers/scsi/tmscsim.c @@ -621,7 +621,7 @@ dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_sr { dc390_freetag (pDCB, pSRB); DEBUG0(printk ("DC390: Interrupt during Start SCSI (target %02i-%02i)\n", - scmd->device->id, scmd->device->lun)); + scmd->device->id, (u8)scmd->device->lun)); pSRB->SRBState = SRB_READY; //DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); pACB->SelLost++; @@ -1726,7 +1726,7 @@ dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* } else { SET_RES_DRV(pcmd->result, DRIVER_SENSE); //pSRB->ScsiCmdLen = (u8) (pSRB->Segment1[0] >> 8); - DEBUG0 (printk ("DC390: RETRY (%02x), target %02i-%02i\n", pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun)); + DEBUG0 (printk ("DC390: RETRY (%02x), target %02i-%02i\n", pcmd->cmnd[0], pcmd->device->id, (u8)pcmd->device->lun)); pSRB->TotalXferredLen = 0; SET_RES_DID(pcmd->result, DID_SOFT_ERROR); } @@ -1746,7 +1746,7 @@ dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* else if (status == SAM_STAT_TASK_SET_FULL) { scsi_track_queue_full(pcmd->device, pDCB->GoingSRBCnt - 1); - DEBUG0 (printk ("DC390: RETRY (%02x), target %02i-%02i\n", pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun)); + DEBUG0 (printk ("DC390: RETRY (%02x), target %02i-%02i\n", pcmd->cmnd[0], pcmd->device->id, (u8)pcmd->device->lun)); pSRB->TotalXferredLen = 0; SET_RES_DID(pcmd->result, DID_SOFT_ERROR); } diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c index 5a03bb3bcfef..4e76fe863fc4 100644 --- a/drivers/scsi/u14-34f.c +++ b/drivers/scsi/u14-34f.c @@ -1285,14 +1285,14 @@ static int u14_34f_queuecommand_lck(struct scsi_cmnd *SCpnt, void (*done)(struct cpp->cpp_index = i; SCpnt->host_scribble = (unsigned char *) &cpp->cpp_index; - if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d.\n", + if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%llu.\n", BN(j), i, SCpnt->device->channel, SCpnt->device->id, - SCpnt->device->lun); + (u8)SCpnt->device->lun); cpp->opcode = OP_SCSI; cpp->channel = SCpnt->device->channel; cpp->target = SCpnt->device->id; - cpp->lun = SCpnt->device->lun; + cpp->lun = (u8)SCpnt->device->lun; cpp->SCpnt = SCpnt; cpp->cdb_len = SCpnt->cmd_len; memcpy(cpp->cdb, SCpnt->cmnd, SCpnt->cmd_len); @@ -1663,10 +1663,10 @@ static int reorder(unsigned int j, unsigned long cursec, if (link_statistics && (overlap || !(flushcount % link_statistics))) for (n = 0; n < n_ready; n++) { k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; - printk("%s %d.%d:%d mb %d fc %d nr %d sec %ld ns %u"\ + printk("%s %d.%d:%llu mb %d fc %d nr %d sec %ld ns %u"\ " cur %ld s:%c r:%c rev:%c in:%c ov:%c xd %d.\n", (ihdlr ? "ihdlr" : "qcomm"), SCpnt->channel, SCpnt->target, - SCpnt->lun, k, flushcount, n_ready, + (u8)SCpnt->lun, k, flushcount, n_ready, blk_rq_pos(SCpnt->request), blk_rq_sectors(SCpnt->request), cursec, YESNO(s), YESNO(r), YESNO(rev), YESNO(input_only), YESNO(overlap), cpp->xdir); diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index f42d1cee652a..fafcf5e354c6 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -41,7 +41,8 @@ #define MAX_CDB_SIZE 16 #define GENERAL_UPIU_REQUEST_SIZE 32 -#define QUERY_DESC_MAX_SIZE 256 +#define QUERY_DESC_MAX_SIZE 255 +#define QUERY_DESC_MIN_SIZE 2 #define QUERY_OSF_SIZE (GENERAL_UPIU_REQUEST_SIZE - \ (sizeof(struct utp_upiu_header))) @@ -117,6 +118,41 @@ enum attr_idn { QUERY_ATTR_IDN_EE_STATUS = 0x0E, }; +/* Descriptor idn for Query requests */ +enum desc_idn { + QUERY_DESC_IDN_DEVICE = 0x0, + QUERY_DESC_IDN_CONFIGURAION = 0x1, + QUERY_DESC_IDN_UNIT = 0x2, + QUERY_DESC_IDN_RFU_0 = 0x3, + QUERY_DESC_IDN_INTERCONNECT = 0x4, + QUERY_DESC_IDN_STRING = 0x5, + QUERY_DESC_IDN_RFU_1 = 0x6, + QUERY_DESC_IDN_GEOMETRY = 0x7, + QUERY_DESC_IDN_POWER = 0x8, + QUERY_DESC_IDN_RFU_2 = 0x9, +}; + +#define UNIT_DESC_MAX_SIZE 0x22 +/* Unit descriptor parameters offsets in bytes*/ +enum unit_desc_param { + UNIT_DESC_PARAM_LEN = 0x0, + UNIT_DESC_PARAM_TYPE = 0x1, + UNIT_DESC_PARAM_UNIT_INDEX = 0x2, + UNIT_DESC_PARAM_LU_ENABLE = 0x3, + UNIT_DESC_PARAM_BOOT_LUN_ID = 0x4, + UNIT_DESC_PARAM_LU_WR_PROTECT = 0x5, + UNIT_DESC_PARAM_LU_Q_DEPTH = 0x6, + UNIT_DESC_PARAM_MEM_TYPE = 0x8, + UNIT_DESC_PARAM_DATA_RELIABILITY = 0x9, + UNIT_DESC_PARAM_LOGICAL_BLK_SIZE = 0xA, + UNIT_DESC_PARAM_LOGICAL_BLK_COUNT = 0xB, + UNIT_DESC_PARAM_ERASE_BLK_SIZE = 0x13, + UNIT_DESC_PARAM_PROVISIONING_TYPE = 0x17, + UNIT_DESC_PARAM_PHY_MEM_RSRC_CNT = 0x18, + UNIT_DESC_PARAM_CTX_CAPABILITIES = 0x20, + UNIT_DESC_PARAM_LARGE_UNIT_SIZE_M1 = 0x22, +}; + /* Exception event mask values */ enum { MASK_EE_STATUS = 0xFFFF, diff --git a/drivers/scsi/ufs/ufshcd-pci.c b/drivers/scsi/ufs/ufshcd-pci.c index 8b9531204c2b..c007a7a69c28 100644 --- a/drivers/scsi/ufs/ufshcd-pci.c +++ b/drivers/scsi/ufs/ufshcd-pci.c @@ -135,26 +135,6 @@ static void ufshcd_pci_remove(struct pci_dev *pdev) } /** - * ufshcd_set_dma_mask - Set dma mask based on the controller - * addressing capability - * @pdev: PCI device structure - * - * Returns 0 for success, non-zero for failure - */ -static int ufshcd_set_dma_mask(struct pci_dev *pdev) -{ - int err; - - if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) - && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) - return 0; - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (!err) - err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); - return err; -} - -/** * ufshcd_pci_probe - probe routine of the driver * @pdev: pointer to PCI device handle * @id: PCI device id @@ -184,12 +164,6 @@ ufshcd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) mmio_base = pcim_iomap_table(pdev)[0]; - err = ufshcd_set_dma_mask(pdev); - if (err) { - dev_err(&pdev->dev, "set dma mask failed\n"); - return err; - } - err = ufshcd_init(&pdev->dev, &hba, mmio_base, pdev->irq); if (err) { dev_err(&pdev->dev, "Initialization failed\n"); diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 0c2877251251..ba27215b8034 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -110,6 +110,8 @@ static void ufshcd_tmc_handler(struct ufs_hba *hba); static void ufshcd_async_scan(void *data, async_cookie_t cookie); static int ufshcd_reset_and_restore(struct ufs_hba *hba); static int ufshcd_clear_tm_cmd(struct ufs_hba *hba, int tag); +static int ufshcd_read_sdev_qdepth(struct ufs_hba *hba, + struct scsi_device *sdev); /* * ufshcd_wait_for_register - wait for register value to change @@ -446,30 +448,35 @@ static inline void ufshcd_copy_sense_data(struct ufshcd_lrb *lrbp) * @lrb - pointer to local reference block */ static -void ufshcd_copy_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) +int ufshcd_copy_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) { struct ufs_query_res *query_res = &hba->dev_cmd.query.response; - /* Get the UPIU response */ - query_res->response = ufshcd_get_rsp_upiu_result(lrbp->ucd_rsp_ptr) >> - UPIU_RSP_CODE_OFFSET; - memcpy(&query_res->upiu_res, &lrbp->ucd_rsp_ptr->qr, QUERY_OSF_SIZE); - /* Get the descriptor */ if (lrbp->ucd_rsp_ptr->qr.opcode == UPIU_QUERY_OPCODE_READ_DESC) { - u8 *descp = (u8 *)&lrbp->ucd_rsp_ptr + + u8 *descp = (u8 *)lrbp->ucd_rsp_ptr + GENERAL_UPIU_REQUEST_SIZE; - u16 len; + u16 resp_len; + u16 buf_len; /* data segment length */ - len = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_2) & + resp_len = be32_to_cpu(lrbp->ucd_rsp_ptr->header.dword_2) & MASK_QUERY_DATA_SEG_LEN; - - memcpy(hba->dev_cmd.query.descriptor, descp, - min_t(u16, len, QUERY_DESC_MAX_SIZE)); + buf_len = be16_to_cpu( + hba->dev_cmd.query.request.upiu_req.length); + if (likely(buf_len >= resp_len)) { + memcpy(hba->dev_cmd.query.descriptor, descp, resp_len); + } else { + dev_warn(hba->dev, + "%s: Response size is bigger than buffer", + __func__); + return -EINVAL; + } } + + return 0; } /** @@ -797,11 +804,9 @@ static void ufshcd_prepare_utp_query_req_upiu(struct ufs_hba *hba, QUERY_OSF_SIZE); /* Copy the Descriptor */ - if ((len > 0) && (query->request.upiu_req.opcode == - UPIU_QUERY_OPCODE_WRITE_DESC)) { - memcpy(descp, query->descriptor, - min_t(u16, len, QUERY_DESC_MAX_SIZE)); - } + if (query->request.upiu_req.opcode == UPIU_QUERY_OPCODE_WRITE_DESC) + memcpy(descp, query->descriptor, len); + } static inline void ufshcd_prepare_utp_nop_upiu(struct ufshcd_lrb *lrbp) @@ -980,6 +985,17 @@ ufshcd_clear_cmd(struct ufs_hba *hba, int tag) return err; } +static int +ufshcd_check_query_response(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) +{ + struct ufs_query_res *query_res = &hba->dev_cmd.query.response; + + /* Get the UPIU response */ + query_res->response = ufshcd_get_rsp_upiu_result(lrbp->ucd_rsp_ptr) >> + UPIU_RSP_CODE_OFFSET; + return query_res->response; +} + /** * ufshcd_dev_cmd_completion() - handles device management command responses * @hba: per adapter instance @@ -1002,7 +1018,9 @@ ufshcd_dev_cmd_completion(struct ufs_hba *hba, struct ufshcd_lrb *lrbp) } break; case UPIU_TRANSACTION_QUERY_RSP: - ufshcd_copy_query_response(hba, lrbp); + err = ufshcd_check_query_response(hba, lrbp); + if (!err) + err = ufshcd_copy_query_response(hba, lrbp); break; case UPIU_TRANSACTION_REJECT_UPIU: /* TODO: handle Reject UPIU Response */ @@ -1134,6 +1152,30 @@ out_put_tag: } /** + * ufshcd_init_query() - init the query response and request parameters + * @hba: per-adapter instance + * @request: address of the request pointer to be initialized + * @response: address of the response pointer to be initialized + * @opcode: operation to perform + * @idn: flag idn to access + * @index: LU number to access + * @selector: query/flag/descriptor further identification + */ +static inline void ufshcd_init_query(struct ufs_hba *hba, + struct ufs_query_req **request, struct ufs_query_res **response, + enum query_opcode opcode, u8 idn, u8 index, u8 selector) +{ + *request = &hba->dev_cmd.query.request; + *response = &hba->dev_cmd.query.response; + memset(*request, 0, sizeof(struct ufs_query_req)); + memset(*response, 0, sizeof(struct ufs_query_res)); + (*request)->upiu_req.opcode = opcode; + (*request)->upiu_req.idn = idn; + (*request)->upiu_req.index = index; + (*request)->upiu_req.selector = selector; +} + +/** * ufshcd_query_flag() - API function for sending flag query requests * hba: per-adapter instance * query_opcode: flag query to perform @@ -1145,17 +1187,15 @@ out_put_tag: static int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode, enum flag_idn idn, bool *flag_res) { - struct ufs_query_req *request; - struct ufs_query_res *response; - int err; + struct ufs_query_req *request = NULL; + struct ufs_query_res *response = NULL; + int err, index = 0, selector = 0; BUG_ON(!hba); mutex_lock(&hba->dev_cmd.lock); - request = &hba->dev_cmd.query.request; - response = &hba->dev_cmd.query.response; - memset(request, 0, sizeof(struct ufs_query_req)); - memset(response, 0, sizeof(struct ufs_query_res)); + ufshcd_init_query(hba, &request, &response, opcode, idn, index, + selector); switch (opcode) { case UPIU_QUERY_OPCODE_SET_FLAG: @@ -1180,12 +1220,8 @@ static int ufshcd_query_flag(struct ufs_hba *hba, enum query_opcode opcode, err = -EINVAL; goto out_unlock; } - request->upiu_req.opcode = opcode; - request->upiu_req.idn = idn; - /* Send query request */ - err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, - QUERY_REQ_TIMEOUT); + err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT); if (err) { dev_err(hba->dev, @@ -1217,8 +1253,8 @@ out_unlock: static int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode, enum attr_idn idn, u8 index, u8 selector, u32 *attr_val) { - struct ufs_query_req *request; - struct ufs_query_res *response; + struct ufs_query_req *request = NULL; + struct ufs_query_res *response = NULL; int err; BUG_ON(!hba); @@ -1231,10 +1267,8 @@ static int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode, } mutex_lock(&hba->dev_cmd.lock); - request = &hba->dev_cmd.query.request; - response = &hba->dev_cmd.query.response; - memset(request, 0, sizeof(struct ufs_query_req)); - memset(response, 0, sizeof(struct ufs_query_res)); + ufshcd_init_query(hba, &request, &response, opcode, idn, index, + selector); switch (opcode) { case UPIU_QUERY_OPCODE_WRITE_ATTR: @@ -1251,14 +1285,7 @@ static int ufshcd_query_attr(struct ufs_hba *hba, enum query_opcode opcode, goto out_unlock; } - request->upiu_req.opcode = opcode; - request->upiu_req.idn = idn; - request->upiu_req.index = index; - request->upiu_req.selector = selector; - - /* Send query request */ - err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, - QUERY_REQ_TIMEOUT); + err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT); if (err) { dev_err(hba->dev, "%s: opcode 0x%.2x for idn %d failed, err = %d\n", @@ -1275,6 +1302,82 @@ out: } /** + * ufshcd_query_descriptor - API function for sending descriptor requests + * hba: per-adapter instance + * opcode: attribute opcode + * idn: attribute idn to access + * index: index field + * selector: selector field + * desc_buf: the buffer that contains the descriptor + * buf_len: length parameter passed to the device + * + * Returns 0 for success, non-zero in case of failure. + * The buf_len parameter will contain, on return, the length parameter + * received on the response. + */ +static int ufshcd_query_descriptor(struct ufs_hba *hba, + enum query_opcode opcode, enum desc_idn idn, u8 index, + u8 selector, u8 *desc_buf, int *buf_len) +{ + struct ufs_query_req *request = NULL; + struct ufs_query_res *response = NULL; + int err; + + BUG_ON(!hba); + + if (!desc_buf) { + dev_err(hba->dev, "%s: descriptor buffer required for opcode 0x%x\n", + __func__, opcode); + err = -EINVAL; + goto out; + } + + if (*buf_len <= QUERY_DESC_MIN_SIZE || *buf_len > QUERY_DESC_MAX_SIZE) { + dev_err(hba->dev, "%s: descriptor buffer size (%d) is out of range\n", + __func__, *buf_len); + err = -EINVAL; + goto out; + } + + mutex_lock(&hba->dev_cmd.lock); + ufshcd_init_query(hba, &request, &response, opcode, idn, index, + selector); + hba->dev_cmd.query.descriptor = desc_buf; + request->upiu_req.length = cpu_to_be16(*buf_len); + + switch (opcode) { + case UPIU_QUERY_OPCODE_WRITE_DESC: + request->query_func = UPIU_QUERY_FUNC_STANDARD_WRITE_REQUEST; + break; + case UPIU_QUERY_OPCODE_READ_DESC: + request->query_func = UPIU_QUERY_FUNC_STANDARD_READ_REQUEST; + break; + default: + dev_err(hba->dev, + "%s: Expected query descriptor opcode but got = 0x%.2x\n", + __func__, opcode); + err = -EINVAL; + goto out_unlock; + } + + err = ufshcd_exec_dev_cmd(hba, DEV_CMD_TYPE_QUERY, QUERY_REQ_TIMEOUT); + + if (err) { + dev_err(hba->dev, "%s: opcode 0x%.2x for idn %d failed, err = %d\n", + __func__, opcode, idn, err); + goto out_unlock; + } + + hba->dev_cmd.query.descriptor = NULL; + *buf_len = be16_to_cpu(response->upiu_res.length); + +out_unlock: + mutex_unlock(&hba->dev_cmd.lock); +out: + return err; +} + +/** * ufshcd_memory_alloc - allocate memory for host memory space data structures * @hba: per adapter instance * @@ -1878,6 +1981,7 @@ static int ufshcd_verify_dev_init(struct ufs_hba *hba) static int ufshcd_slave_alloc(struct scsi_device *sdev) { struct ufs_hba *hba; + int lun_qdepth; hba = shost_priv(sdev->host); sdev->tagged_supported = 1; @@ -1889,14 +1993,68 @@ static int ufshcd_slave_alloc(struct scsi_device *sdev) /* allow SCSI layer to restart the device in case of errors */ sdev->allow_restart = 1; - /* - * Inform SCSI Midlayer that the LUN queue depth is same as the - * controller queue depth. If a LUN queue depth is less than the - * controller queue depth and if the LUN reports - * SAM_STAT_TASK_SET_FULL, the LUN queue depth will be adjusted - * with scsi_adjust_queue_depth. - */ - scsi_activate_tcq(sdev, hba->nutrs); + /* REPORT SUPPORTED OPERATION CODES is not supported */ + sdev->no_report_opcodes = 1; + + lun_qdepth = ufshcd_read_sdev_qdepth(hba, sdev); + if (lun_qdepth <= 0) + /* eventually, we can figure out the real queue depth */ + lun_qdepth = hba->nutrs; + else + lun_qdepth = min_t(int, lun_qdepth, hba->nutrs); + + dev_dbg(hba->dev, "%s: activate tcq with queue depth %d\n", + __func__, lun_qdepth); + scsi_activate_tcq(sdev, lun_qdepth); + + return 0; +} + +/** + * ufshcd_change_queue_depth - change queue depth + * @sdev: pointer to SCSI device + * @depth: required depth to set + * @reason: reason for changing the depth + * + * Change queue depth according to the reason and make sure + * the max. limits are not crossed. + */ +static int ufshcd_change_queue_depth(struct scsi_device *sdev, + int depth, int reason) +{ + struct ufs_hba *hba = shost_priv(sdev->host); + + if (depth > hba->nutrs) + depth = hba->nutrs; + + switch (reason) { + case SCSI_QDEPTH_DEFAULT: + case SCSI_QDEPTH_RAMP_UP: + if (!sdev->tagged_supported) + depth = 1; + scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth); + break; + case SCSI_QDEPTH_QFULL: + scsi_track_queue_full(sdev, depth); + break; + default: + return -EOPNOTSUPP; + } + + return depth; +} + +/** + * ufshcd_slave_configure - adjust SCSI device configurations + * @sdev: pointer to SCSI device + */ +static int ufshcd_slave_configure(struct scsi_device *sdev) +{ + struct request_queue *q = sdev->request_queue; + + blk_queue_update_dma_pad(q, PRDT_DATA_BYTE_COUNT_PAD - 1); + blk_queue_max_segment_size(q, PRDT_DATA_BYTE_COUNT_MAX); + return 0; } @@ -1953,42 +2111,6 @@ static int ufshcd_task_req_compl(struct ufs_hba *hba, u32 index, u8 *resp) } /** - * ufshcd_adjust_lun_qdepth - Update LUN queue depth if device responds with - * SAM_STAT_TASK_SET_FULL SCSI command status. - * @cmd: pointer to SCSI command - */ -static void ufshcd_adjust_lun_qdepth(struct scsi_cmnd *cmd) -{ - struct ufs_hba *hba; - int i; - int lun_qdepth = 0; - - hba = shost_priv(cmd->device->host); - - /* - * LUN queue depth can be obtained by counting outstanding commands - * on the LUN. - */ - for (i = 0; i < hba->nutrs; i++) { - if (test_bit(i, &hba->outstanding_reqs)) { - - /* - * Check if the outstanding command belongs - * to the LUN which reported SAM_STAT_TASK_SET_FULL. - */ - if (cmd->device->lun == hba->lrb[i].lun) - lun_qdepth++; - } - } - - /* - * LUN queue depth will be total outstanding commands, except the - * command for which the LUN reported SAM_STAT_TASK_SET_FULL. - */ - scsi_adjust_queue_depth(cmd->device, MSG_SIMPLE_TAG, lun_qdepth - 1); -} - -/** * ufshcd_scsi_cmd_status - Update SCSI command result based on SCSI status * @lrb: pointer to local reference block of completed command * @scsi_status: SCSI command status @@ -2009,12 +2131,6 @@ ufshcd_scsi_cmd_status(struct ufshcd_lrb *lrbp, int scsi_status) scsi_status; break; case SAM_STAT_TASK_SET_FULL: - /* - * If a LUN reports SAM_STAT_TASK_SET_FULL, then the LUN queue - * depth needs to be adjusted to the exact number of - * outstanding commands the LUN can handle at any given time. - */ - ufshcd_adjust_lun_qdepth(lrbp->cmd); case SAM_STAT_BUSY: case SAM_STAT_TASK_ABORTED: ufshcd_copy_sense_data(lrbp); @@ -2134,47 +2250,42 @@ static void ufshcd_transfer_req_compl(struct ufs_hba *hba) u32 tr_doorbell; int result; int index; - bool int_aggr_reset = false; + + /* Resetting interrupt aggregation counters first and reading the + * DOOR_BELL afterward allows us to handle all the completed requests. + * In order to prevent other interrupts starvation the DB is read once + * after reset. The down side of this solution is the possibility of + * false interrupt if device completes another request after resetting + * aggregation and before reading the DB. + */ + ufshcd_reset_intr_aggr(hba); tr_doorbell = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); completed_reqs = tr_doorbell ^ hba->outstanding_reqs; - for (index = 0; index < hba->nutrs; index++) { - if (test_bit(index, &completed_reqs)) { - lrbp = &hba->lrb[index]; - cmd = lrbp->cmd; - /* - * Don't skip resetting interrupt aggregation counters - * if a regular command is present. - */ - int_aggr_reset |= !lrbp->intr_cmd; - - if (cmd) { - result = ufshcd_transfer_rsp_status(hba, lrbp); - scsi_dma_unmap(cmd); - cmd->result = result; - /* Mark completed command as NULL in LRB */ - lrbp->cmd = NULL; - clear_bit_unlock(index, &hba->lrb_in_use); - /* Do not touch lrbp after scsi done */ - cmd->scsi_done(cmd); - } else if (lrbp->command_type == - UTP_CMD_TYPE_DEV_MANAGE) { - if (hba->dev_cmd.complete) - complete(hba->dev_cmd.complete); - } - } /* end of if */ - } /* end of for */ + for_each_set_bit(index, &completed_reqs, hba->nutrs) { + lrbp = &hba->lrb[index]; + cmd = lrbp->cmd; + if (cmd) { + result = ufshcd_transfer_rsp_status(hba, lrbp); + scsi_dma_unmap(cmd); + cmd->result = result; + /* Mark completed command as NULL in LRB */ + lrbp->cmd = NULL; + clear_bit_unlock(index, &hba->lrb_in_use); + /* Do not touch lrbp after scsi done */ + cmd->scsi_done(cmd); + } else if (lrbp->command_type == UTP_CMD_TYPE_DEV_MANAGE) { + if (hba->dev_cmd.complete) + complete(hba->dev_cmd.complete); + } + } /* clear corresponding bits of completed commands */ hba->outstanding_reqs ^= completed_reqs; /* we might have free'd some tags above */ wake_up(&hba->dev_cmd.tag_wq); - - /* Reset interrupt aggregation counters */ - if (int_aggr_reset) - ufshcd_reset_intr_aggr(hba); } /** @@ -2779,6 +2890,7 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) int poll_cnt; u8 resp = 0xF; struct ufshcd_lrb *lrbp; + u32 reg; host = cmd->device->host; hba = shost_priv(host); @@ -2788,6 +2900,13 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) if (!(test_bit(tag, &hba->outstanding_reqs))) goto out; + reg = ufshcd_readl(hba, REG_UTP_TRANSFER_REQ_DOOR_BELL); + if (!(reg & (1 << tag))) { + dev_err(hba->dev, + "%s: cmd was completed, but without a notifying intr, tag = %d", + __func__, tag); + } + lrbp = &hba->lrb[tag]; for (poll_cnt = 100; poll_cnt; poll_cnt--) { err = ufshcd_issue_tm_cmd(hba, lrbp->lun, lrbp->task_tag, @@ -2796,8 +2915,6 @@ static int ufshcd_abort(struct scsi_cmnd *cmd) /* cmd pending in the device */ break; } else if (!err && resp == UPIU_TASK_MANAGEMENT_FUNC_COMPL) { - u32 reg; - /* * cmd not pending in the device, check if it is * in transition. @@ -2971,6 +3088,38 @@ static int ufshcd_eh_host_reset_handler(struct scsi_cmnd *cmd) } /** + * ufshcd_read_sdev_qdepth - read the lun command queue depth + * @hba: Pointer to adapter instance + * @sdev: pointer to SCSI device + * + * Return in case of success the lun's queue depth else error. + */ +static int ufshcd_read_sdev_qdepth(struct ufs_hba *hba, + struct scsi_device *sdev) +{ + int ret; + int buff_len = UNIT_DESC_MAX_SIZE; + u8 desc_buf[UNIT_DESC_MAX_SIZE]; + + ret = ufshcd_query_descriptor(hba, UPIU_QUERY_OPCODE_READ_DESC, + QUERY_DESC_IDN_UNIT, sdev->lun, 0, desc_buf, &buff_len); + + if (ret || (buff_len < UNIT_DESC_PARAM_LU_Q_DEPTH)) { + dev_err(hba->dev, + "%s:Failed reading unit descriptor. len = %d ret = %d" + , __func__, buff_len, ret); + if (!ret) + ret = -EINVAL; + + goto out; + } + + ret = desc_buf[UNIT_DESC_PARAM_LU_Q_DEPTH] & 0xFF; +out: + return ret; +} + +/** * ufshcd_async_scan - asynchronous execution for link startup * @data: data pointer to pass to this function * @cookie: cookie data @@ -3012,7 +3161,9 @@ static struct scsi_host_template ufshcd_driver_template = { .proc_name = UFSHCD, .queuecommand = ufshcd_queuecommand, .slave_alloc = ufshcd_slave_alloc, + .slave_configure = ufshcd_slave_configure, .slave_destroy = ufshcd_slave_destroy, + .change_queue_depth = ufshcd_change_queue_depth, .eh_abort_handler = ufshcd_abort, .eh_device_reset_handler = ufshcd_eh_device_reset_handler, .eh_host_reset_handler = ufshcd_eh_host_reset_handler, @@ -3110,6 +3261,22 @@ void ufshcd_remove(struct ufs_hba *hba) EXPORT_SYMBOL_GPL(ufshcd_remove); /** + * ufshcd_set_dma_mask - Set dma mask based on the controller + * addressing capability + * @hba: per adapter instance + * + * Returns 0 for success, non-zero for failure + */ +static int ufshcd_set_dma_mask(struct ufs_hba *hba) +{ + if (hba->capabilities & MASK_64_ADDRESSING_SUPPORT) { + if (!dma_set_mask_and_coherent(hba->dev, DMA_BIT_MASK(64))) + return 0; + } + return dma_set_mask_and_coherent(hba->dev, DMA_BIT_MASK(32)); +} + +/** * ufshcd_init - Driver initialization routine * @dev: pointer to device handle * @hba_handle: driver private handle @@ -3160,6 +3327,12 @@ int ufshcd_init(struct device *dev, struct ufs_hba **hba_handle, /* Get Interrupt bit mask per version */ hba->intr_mask = ufshcd_get_intr_mask(hba); + err = ufshcd_set_dma_mask(hba); + if (err) { + dev_err(hba->dev, "set dma mask failed\n"); + goto out_disable; + } + /* Allocate memory for host memory space */ err = ufshcd_memory_alloc(hba); if (err) { diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h index 9abc7e32b43d..e1b844bc9460 100644 --- a/drivers/scsi/ufs/ufshci.h +++ b/drivers/scsi/ufs/ufshci.h @@ -296,6 +296,11 @@ enum { MASK_OCS = 0x0F, }; +/* The maximum length of the data byte count field in the PRDT is 256KB */ +#define PRDT_DATA_BYTE_COUNT_MAX (256 * 1024) +/* The granularity of the data byte count field in the PRDT is 32-bit */ +#define PRDT_DATA_BYTE_COUNT_PAD 4 + /** * struct ufshcd_sg_entry - UFSHCI PRD Entry * @base_addr: Lower 32bit physical address DW-0 diff --git a/drivers/scsi/virtio_scsi.c b/drivers/scsi/virtio_scsi.c index 308256b5e4cb..eee1bc0b506e 100644 --- a/drivers/scsi/virtio_scsi.c +++ b/drivers/scsi/virtio_scsi.c @@ -27,6 +27,8 @@ #include <scsi/scsi_host.h> #include <scsi/scsi_device.h> #include <scsi/scsi_cmnd.h> +#include <scsi/scsi_tcq.h> +#include <linux/seqlock.h> #define VIRTIO_SCSI_MEMPOOL_SZ 64 #define VIRTIO_SCSI_EVENT_LEN 8 @@ -75,18 +77,16 @@ struct virtio_scsi_vq { * queue, and also lets the driver optimize the IRQ affinity for the virtqueues * (each virtqueue's affinity is set to the CPU that "owns" the queue). * - * tgt_lock is held to serialize reading and writing req_vq. Reading req_vq - * could be done locklessly, but we do not do it yet. + * tgt_seq is held to serialize reading and writing req_vq. * * Decrements of reqs are never concurrent with writes of req_vq: before the * decrement reqs will be != 0; after the decrement the virtqueue completion * routine will not use the req_vq so it can be changed by a new request. - * Thus they can happen outside the tgt_lock, provided of course we make reqs + * Thus they can happen outside the tgt_seq, provided of course we make reqs * an atomic_t. */ struct virtio_scsi_target_state { - /* This spinlock never held at the same time as vq_lock. */ - spinlock_t tgt_lock; + seqcount_t tgt_seq; /* Count of outstanding requests. */ atomic_t reqs; @@ -559,19 +559,33 @@ static struct virtio_scsi_vq *virtscsi_pick_vq(struct virtio_scsi *vscsi, unsigned long flags; u32 queue_num; - spin_lock_irqsave(&tgt->tgt_lock, flags); + local_irq_save(flags); + if (atomic_inc_return(&tgt->reqs) > 1) { + unsigned long seq; + + do { + seq = read_seqcount_begin(&tgt->tgt_seq); + vq = tgt->req_vq; + } while (read_seqcount_retry(&tgt->tgt_seq, seq)); + } else { + /* no writes can be concurrent because of atomic_t */ + write_seqcount_begin(&tgt->tgt_seq); + + /* keep previous req_vq if a reader just arrived */ + if (unlikely(atomic_read(&tgt->reqs) > 1)) { + vq = tgt->req_vq; + goto unlock; + } - if (atomic_inc_return(&tgt->reqs) > 1) - vq = tgt->req_vq; - else { queue_num = smp_processor_id(); while (unlikely(queue_num >= vscsi->num_queues)) queue_num -= vscsi->num_queues; - tgt->req_vq = vq = &vscsi->req_vqs[queue_num]; + unlock: + write_seqcount_end(&tgt->tgt_seq); } + local_irq_restore(flags); - spin_unlock_irqrestore(&tgt->tgt_lock, flags); return vq; } @@ -641,6 +655,36 @@ static int virtscsi_device_reset(struct scsi_cmnd *sc) return virtscsi_tmf(vscsi, cmd); } +/** + * virtscsi_change_queue_depth() - Change a virtscsi target's queue depth + * @sdev: Virtscsi target whose queue depth to change + * @qdepth: New queue depth + * @reason: Reason for the queue depth change. + */ +static int virtscsi_change_queue_depth(struct scsi_device *sdev, + int qdepth, + int reason) +{ + struct Scsi_Host *shost = sdev->host; + int max_depth = shost->cmd_per_lun; + + switch (reason) { + case SCSI_QDEPTH_QFULL: /* Drop qdepth in response to BUSY state */ + scsi_track_queue_full(sdev, qdepth); + break; + case SCSI_QDEPTH_RAMP_UP: /* Raise qdepth after BUSY state resolved */ + case SCSI_QDEPTH_DEFAULT: /* Manual change via sysfs */ + scsi_adjust_queue_depth(sdev, + scsi_get_tag_type(sdev), + min(max_depth, qdepth)); + break; + default: + return -EOPNOTSUPP; + } + + return sdev->queue_depth; +} + static int virtscsi_abort(struct scsi_cmnd *sc) { struct virtio_scsi *vscsi = shost_priv(sc->device->host); @@ -667,14 +711,17 @@ static int virtscsi_abort(struct scsi_cmnd *sc) static int virtscsi_target_alloc(struct scsi_target *starget) { + struct Scsi_Host *sh = dev_to_shost(starget->dev.parent); + struct virtio_scsi *vscsi = shost_priv(sh); + struct virtio_scsi_target_state *tgt = kmalloc(sizeof(*tgt), GFP_KERNEL); if (!tgt) return -ENOMEM; - spin_lock_init(&tgt->tgt_lock); + seqcount_init(&tgt->tgt_seq); atomic_set(&tgt->reqs, 0); - tgt->req_vq = NULL; + tgt->req_vq = &vscsi->req_vqs[0]; starget->hostdata = tgt; return 0; @@ -693,6 +740,7 @@ static struct scsi_host_template virtscsi_host_template_single = { .this_id = -1, .cmd_size = sizeof(struct virtio_scsi_cmd), .queuecommand = virtscsi_queuecommand_single, + .change_queue_depth = virtscsi_change_queue_depth, .eh_abort_handler = virtscsi_abort, .eh_device_reset_handler = virtscsi_device_reset, @@ -710,6 +758,7 @@ static struct scsi_host_template virtscsi_host_template_multi = { .this_id = -1, .cmd_size = sizeof(struct virtio_scsi_cmd), .queuecommand = virtscsi_queuecommand_multi, + .change_queue_depth = virtscsi_change_queue_depth, .eh_abort_handler = virtscsi_abort, .eh_device_reset_handler = virtscsi_device_reset, diff --git a/drivers/scsi/vmw_pvscsi.c b/drivers/scsi/vmw_pvscsi.c index c88e1468aad7..598f65efaaec 100644 --- a/drivers/scsi/vmw_pvscsi.c +++ b/drivers/scsi/vmw_pvscsi.c @@ -1194,7 +1194,7 @@ static int pvscsi_setup_msix(const struct pvscsi_adapter *adapter, struct msix_entry entry = { 0, PVSCSI_VECTOR_COMPLETION }; int ret; - ret = pci_enable_msix(adapter->dev, &entry, 1); + ret = pci_enable_msix_exact(adapter->dev, &entry, 1); if (ret) return ret; diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c index 41883a87931d..c0506de4f3b6 100644 --- a/drivers/scsi/wd33c93.c +++ b/drivers/scsi/wd33c93.c @@ -502,7 +502,8 @@ wd33c93_execute(struct Scsi_Host *instance) cmd = (struct scsi_cmnd *) hostdata->input_Q; prev = NULL; while (cmd) { - if (!(hostdata->busy[cmd->device->id] & (1 << cmd->device->lun))) + if (!(hostdata->busy[cmd->device->id] & + (1 << (cmd->device->lun & 0xff)))) break; prev = cmd; cmd = (struct scsi_cmnd *) cmd->host_scribble; @@ -593,10 +594,10 @@ wd33c93_execute(struct Scsi_Host *instance) write_wd33c93(regs, WD_SOURCE_ID, ((cmd->SCp.phase) ? SRCID_ER : 0)); - write_wd33c93(regs, WD_TARGET_LUN, cmd->device->lun); + write_wd33c93(regs, WD_TARGET_LUN, (u8)cmd->device->lun); write_wd33c93(regs, WD_SYNCHRONOUS_TRANSFER, hostdata->sync_xfer[cmd->device->id]); - hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); + hostdata->busy[cmd->device->id] |= (1 << (cmd->device->lun & 0xFF)); if ((hostdata->level2 == L2_NONE) || (hostdata->sync_stat[cmd->device->id] == SS_UNSET)) { @@ -862,7 +863,7 @@ wd33c93_intr(struct Scsi_Host *instance) } cmd->result = DID_NO_CONNECT << 16; - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); + hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff)); hostdata->state = S_UNCONNECTED; cmd->scsi_done(cmd); @@ -895,7 +896,7 @@ wd33c93_intr(struct Scsi_Host *instance) /* construct an IDENTIFY message with correct disconnect bit */ - hostdata->outgoing_msg[0] = (0x80 | 0x00 | cmd->device->lun); + hostdata->outgoing_msg[0] = IDENTIFY(0, cmd->device->lun); if (cmd->SCp.phase) hostdata->outgoing_msg[0] |= 0x40; @@ -1179,7 +1180,7 @@ wd33c93_intr(struct Scsi_Host *instance) lun = read_wd33c93(regs, WD_TARGET_LUN); DB(DB_INTR, printk(":%d.%d", cmd->SCp.Status, lun)) hostdata->connected = NULL; - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); + hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff)); hostdata->state = S_UNCONNECTED; if (cmd->SCp.Status == ILLEGAL_STATUS_BYTE) cmd->SCp.Status = lun; @@ -1268,7 +1269,7 @@ wd33c93_intr(struct Scsi_Host *instance) } DB(DB_INTR, printk("UNEXP_DISC")) hostdata->connected = NULL; - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); + hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff)); hostdata->state = S_UNCONNECTED; if (cmd->cmnd[0] == REQUEST_SENSE && cmd->SCp.Status != GOOD) cmd->result = @@ -1300,7 +1301,7 @@ wd33c93_intr(struct Scsi_Host *instance) switch (hostdata->state) { case S_PRE_CMP_DISC: hostdata->connected = NULL; - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); + hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff)); hostdata->state = S_UNCONNECTED; DB(DB_INTR, printk(":%d", cmd->SCp.Status)) if (cmd->cmnd[0] == REQUEST_SENSE @@ -1353,7 +1354,7 @@ wd33c93_intr(struct Scsi_Host *instance) if (hostdata->selecting) { cmd = (struct scsi_cmnd *) hostdata->selecting; hostdata->selecting = NULL; - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); + hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff)); cmd->host_scribble = (uchar *) hostdata->input_Q; hostdata->input_Q = cmd; @@ -1365,7 +1366,7 @@ wd33c93_intr(struct Scsi_Host *instance) if (cmd) { if (phs == 0x00) { hostdata->busy[cmd->device->id] &= - ~(1 << cmd->device->lun); + ~(1 << (cmd->device->lun & 0xff)); cmd->host_scribble = (uchar *) hostdata->input_Q; hostdata->input_Q = cmd; @@ -1448,7 +1449,7 @@ wd33c93_intr(struct Scsi_Host *instance) cmd = (struct scsi_cmnd *) hostdata->disconnected_Q; patch = NULL; while (cmd) { - if (id == cmd->device->id && lun == cmd->device->lun) + if (id == cmd->device->id && lun == (u8)cmd->device->lun) break; patch = cmd; cmd = (struct scsi_cmnd *) cmd->host_scribble; @@ -1459,7 +1460,7 @@ wd33c93_intr(struct Scsi_Host *instance) if (!cmd) { printk ("---TROUBLE: target %d.%d not in disconnect queue---", - id, lun); + id, (u8)lun); spin_unlock_irqrestore(&hostdata->lock, flags); return; } @@ -1705,7 +1706,7 @@ wd33c93_abort(struct scsi_cmnd * cmd) sr = read_wd33c93(regs, WD_SCSI_STATUS); printk("asr=%02x, sr=%02x.", asr, sr); - hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); + hostdata->busy[cmd->device->id] &= ~(1 << (cmd->device->lun & 0xff)); hostdata->connected = NULL; hostdata->state = S_UNCONNECTED; cmd->result = DID_ABORT << 16; @@ -2169,7 +2170,7 @@ wd33c93_show_info(struct seq_file *m, struct Scsi_Host *instance) seq_printf(m, "\nconnected: "); if (hd->connected) { cmd = (struct scsi_cmnd *) hd->connected; - seq_printf(m, " %d:%d(%02x)", + seq_printf(m, " %d:%llu(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]); } } @@ -2177,7 +2178,7 @@ wd33c93_show_info(struct seq_file *m, struct Scsi_Host *instance) seq_printf(m, "\ninput_Q: "); cmd = (struct scsi_cmnd *) hd->input_Q; while (cmd) { - seq_printf(m, " %d:%d(%02x)", + seq_printf(m, " %d:%llu(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]); cmd = (struct scsi_cmnd *) cmd->host_scribble; } @@ -2186,7 +2187,7 @@ wd33c93_show_info(struct seq_file *m, struct Scsi_Host *instance) seq_printf(m, "\ndisconnected_Q:"); cmd = (struct scsi_cmnd *) hd->disconnected_Q; while (cmd) { - seq_printf(m, " %d:%d(%02x)", + seq_printf(m, " %d:%llu(%02x)", cmd->device->id, cmd->device->lun, cmd->cmnd[0]); cmd = (struct scsi_cmnd *) cmd->host_scribble; } |