* [RFC 0/2] libata: support SATA devices on SAS HBAs
@ 2005-10-03 21:56 Brian King
2005-10-03 21:58 ` [RFC 1/2] libata: configurable host_set lock Brian King
` (2 more replies)
0 siblings, 3 replies; 38+ messages in thread
From: Brian King @ 2005-10-03 21:56 UTC (permalink / raw)
To: linux-ide
The following patches enhance libata to allow SAS device drivers
to utilize libata to talk to SATA devices. It introduces some
new APIs which allow libata to be used without allocating a
virtual scsi host. This is just a snapshot of what I've
come up with at this point and I figured I would post it to
see if I was heading in a reasonable direction or not, so
don't expect the code below to do anything useful at this point
as it is untested.
New APIs:
ata_sas_port_alloc - Allocate an ata_port
ata_sas_port_init - Initialize an ata_port (probe bus, etc)
ata_sas_port_destroy - Free an ata_port allocated by ata_sas_port_alloc
ata_sas_slave_configure - configure scsi device
ata_sas_queuecmd - queue a scsi command, similar to ata_scsi_queuecomand
These new APIs can be used either directly by a SAS LLDD or could be used
by the SAS transport class.
Possible usage for a SAS LLDD would be:
scsi_scan_host
slave_alloc
ata_sas_port_alloc
ata_sas_port_init
slave_configure
ata_sas_slave_configure
Commands received by the LLDD for SATA devices would call ata_sas_queuecmd.
Device teardown would occur with:
slave_destroy
ata_sas_port_destroy
--
Brian King
eServer Storage I/O
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 38+ messages in thread* [RFC 1/2] libata: configurable host_set lock 2005-10-03 21:56 [RFC 0/2] libata: support SATA devices on SAS HBAs Brian King @ 2005-10-03 21:58 ` Brian King 2005-10-03 21:58 ` [RFC 2/2] libata: support SATA devices on SAS HBAs Brian King 2005-10-04 9:56 ` [RFC 0/2] " Jeff Garzik 2 siblings, 0 replies; 38+ messages in thread From: Brian King @ 2005-10-03 21:58 UTC (permalink / raw) To: brking; +Cc: linux-ide [-- Attachment #1: Type: text/plain, Size: 0 bytes --] [-- Attachment #2: libata_lock_change.patch --] [-- Type: text/plain, Size: 5949 bytes --] Allow the spinlock used by libata to be overridden. Signed-off-by: Brian King <brking@us.ibm.com> --- linux-2.6-bjking1/drivers/scsi/libata-core.c | 41 +++++++++++++-------------- linux-2.6-bjking1/include/linux/libata.h | 8 ++++- 2 files changed, 28 insertions(+), 21 deletions(-) diff -puN include/linux/libata.h~libata_lock_change include/linux/libata.h --- linux-2.6/include/linux/libata.h~libata_lock_change 2005-09-26 14:22:57.000000000 -0500 +++ linux-2.6-bjking1/include/linux/libata.h 2005-09-26 14:22:57.000000000 -0500 @@ -214,7 +214,8 @@ struct ata_probe_ent { }; struct ata_host_set { - spinlock_t lock; + spinlock_t *lock; + spinlock_t default_lock; struct device *dev; unsigned long irq; void __iomem *mmio_base; @@ -669,4 +670,9 @@ static inline int ata_try_flush_cache(st ata_id_has_flush_ext(dev->id); } +static inline void ata_assign_lock(struct ata_host_set *host_set, spinlock_t *lock) +{ + host_set->lock = lock; +} + #endif /* __LINUX_LIBATA_H__ */ diff -puN drivers/scsi/libata-core.c~libata_lock_change drivers/scsi/libata-core.c --- linux-2.6/drivers/scsi/libata-core.c~libata_lock_change 2005-09-26 14:22:57.000000000 -0500 +++ linux-2.6-bjking1/drivers/scsi/libata-core.c 2005-09-26 14:22:57.000000000 -0500 @@ -308,9 +308,9 @@ static inline void ata_exec(struct ata_p unsigned long flags; DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command); - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->host_set->lock, flags); ap->ops->exec_command(ap, tf); - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->host_set->lock, flags); } /** @@ -1179,9 +1179,9 @@ retry: qc->waiting = &wait; qc->complete_fn = ata_qc_complete_noop; - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->host_set->lock, flags); rc = ata_qc_issue(qc); - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->host_set->lock, flags); if (rc) goto err_out; @@ -2131,9 +2131,9 @@ static void ata_dev_set_xfermode(struct qc->waiting = &wait; qc->complete_fn = ata_qc_complete_noop; - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->host_set->lock, flags); rc = ata_qc_issue(qc); - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->host_set->lock, flags); if (rc) ata_port_disable(ap); @@ -2404,11 +2404,11 @@ void ata_poll_qc_complete(struct ata_que struct ata_port *ap = qc->ap; unsigned long flags; - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->host_set->lock, flags); ap->flags &= ~ATA_FLAG_NOINTR; ata_irq_on(ap); ata_qc_complete(qc, drv_stat); - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->host_set->lock, flags); } /** @@ -2962,9 +2962,9 @@ static void atapi_request_sense(struct a qc->waiting = &wait; qc->complete_fn = ata_qc_complete_noop; - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->host_set->lock, flags); rc = ata_qc_issue(qc); - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->host_set->lock, flags); if (rc) ata_port_disable(ap); @@ -3010,9 +3010,9 @@ static void ata_qc_timeout(struct ata_qu if (!(cmd->eh_eflags & SCSI_EH_CANCEL_CMD)) { /* finish completing original command */ - spin_lock_irqsave(&host_set->lock, flags); + spin_lock_irqsave(host_set->lock, flags); __ata_qc_complete(qc); - spin_unlock_irqrestore(&host_set->lock, flags); + spin_unlock_irqrestore(host_set->lock, flags); atapi_request_sense(ap, dev, cmd); @@ -3023,7 +3023,7 @@ static void ata_qc_timeout(struct ata_qu } } - spin_lock_irqsave(&host_set->lock, flags); + spin_lock_irqsave(host_set->lock, flags); /* hack alert! We cannot use the supplied completion * function from inside the ->eh_strategy_handler() thread. @@ -3059,7 +3059,7 @@ static void ata_qc_timeout(struct ata_qu break; } - spin_unlock_irqrestore(&host_set->lock, flags); + spin_unlock_irqrestore(host_set->lock, flags); out: DPRINTK("EXIT\n"); @@ -3726,7 +3726,7 @@ irqreturn_t ata_interrupt (int irq, void unsigned long flags; /* TODO: make _irqsave conditional on x86 PCI IDE legacy mode */ - spin_lock_irqsave(&host_set->lock, flags); + spin_lock_irqsave(host_set->lock, flags); for (i = 0; i < host_set->n_ports; i++) { struct ata_port *ap; @@ -3743,7 +3743,7 @@ irqreturn_t ata_interrupt (int irq, void } } - spin_unlock_irqrestore(&host_set->lock, flags); + spin_unlock_irqrestore(host_set->lock, flags); return IRQ_RETVAL(handled); } @@ -3796,12 +3796,12 @@ static void atapi_packet_task(void *_dat * interrupt handler shouldn't be invoked before we're * finished. Hence, the following locking. */ - spin_lock_irqsave(&ap->host_set->lock, flags); + spin_lock_irqsave(ap->host_set->lock, flags); ap->flags &= ~ATA_FLAG_NOINTR; ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1); if (qc->tf.protocol == ATA_PROT_ATAPI_DMA) ap->ops->bmdma_start(qc); /* initiate bmdma */ - spin_unlock_irqrestore(&ap->host_set->lock, flags); + spin_unlock_irqrestore(ap->host_set->lock, flags); } else { ata_data_xfer(ap, qc->cdb, ap->cdb_len, 1); @@ -3916,7 +3916,7 @@ static void ata_host_init(struct ata_por host->unique_id = ata_unique_id++; host->max_cmd_len = 12; - scsi_assign_lock(host, &host_set->lock); + scsi_assign_lock(host, host_set->lock); ap->flags = ATA_FLAG_PORT_DISABLED; ap->id = host->unique_id; @@ -4026,7 +4026,8 @@ int ata_device_add(struct ata_probe_ent if (!host_set) return 0; memset(host_set, 0, sizeof(struct ata_host_set) + (ent->n_ports * sizeof(void *))); - spin_lock_init(&host_set->lock); + spin_lock_init(&host_set->default_lock); + ata_assign_lock(host_set, &host_set->default_lock); host_set->dev = dev; host_set->n_ports = ent->n_ports; _ ^ permalink raw reply [flat|nested] 38+ messages in thread
* [RFC 2/2] libata: support SATA devices on SAS HBAs 2005-10-03 21:56 [RFC 0/2] libata: support SATA devices on SAS HBAs Brian King 2005-10-03 21:58 ` [RFC 1/2] libata: configurable host_set lock Brian King @ 2005-10-03 21:58 ` Brian King 2005-10-04 9:56 ` [RFC 0/2] " Jeff Garzik 2 siblings, 0 replies; 38+ messages in thread From: Brian King @ 2005-10-03 21:58 UTC (permalink / raw) To: brking; +Cc: linux-ide [-- Attachment #1: Type: text/plain, Size: 0 bytes --] [-- Attachment #2: libata_sas.patch --] [-- Type: text/plain, Size: 12553 bytes --] The following patch enhances libata to allow SAS device drivers to utilize libata to talk to SATA devices. It introduces some new APIs which allow libata to be used without allocating a virtual scsi host. This is just a snapshot of what I've come up with at this point and I figured I would post it to see if I was heading in a reasonable direction or not, so don't expect the code below to do anything useful at this point as it is untested. New APIs: ata_sas_port_alloc - Allocate an ata_port ata_sas_port_init - Initialize an ata_port (probe bus, etc) ata_sas_port_destroy - Free an ata_port allocated by ata_sas_port_alloc ata_sas_slave_configure - configure scsi device ata_sas_queuecmd - queue a scsi command, similar to ata_scsi_queuecomand These new APIs can be used either directly by a SAS LLDD or could be used by the SAS transport class. Possible usage for a SAS LLDD would be: scsi_scan_host slave_alloc ata_sas_port_alloc ata_sas_port_init slave_configure ata_sas_slave_configure Commands received by the LLDD for SATA devices would call ata_sas_queuecmd. Device teardown would occur with: slave_destroy ata_sas_port_destroy Signed-off-by: Brian King <brking@us.ibm.com> --- linux-2.6-bjking1/drivers/scsi/libata-core.c | 32 ++-- linux-2.6-bjking1/drivers/scsi/libata-scsi.c | 213 +++++++++++++++++++++++---- linux-2.6-bjking1/drivers/scsi/libata.h | 7 linux-2.6-bjking1/include/linux/libata.h | 8 + 4 files changed, 222 insertions(+), 38 deletions(-) diff -puN drivers/scsi/libata-scsi.c~libata_sas drivers/scsi/libata-scsi.c --- linux-2.6/drivers/scsi/libata-scsi.c~libata_sas 2005-09-26 14:23:01.000000000 -0500 +++ linux-2.6-bjking1/drivers/scsi/libata-scsi.c 2005-09-26 14:23:01.000000000 -0500 @@ -325,6 +325,30 @@ void ata_to_sense_error(struct ata_queue } } +static void ata_scsi_sdev_config(struct scsi_device *sdev) +{ + sdev->use_10_for_rw = 1; + sdev->use_10_for_ms = 1; +} + +static void ata_scsi_dev_config(struct scsi_device *sdev, + struct ata_device *dev) +{ + /* TODO: 1024 is an arbitrary number, not the + * hardware maximum. This should be increased to + * 65534 when Jens Axboe's patch for dynamically + * determining max_sectors is merged. + */ + if ((dev->flags & ATA_DFLAG_LBA48) && + ((dev->flags & ATA_DFLAG_LOCK_SECTORS) == 0)) { + /* + * do not overwrite sdev->host->max_sectors, since + * other drives on this host may not support LBA48 + */ + blk_queue_max_sectors(sdev->request_queue, 2048); + } +} + /** * ata_scsi_slave_config - Set SCSI device attributes * @sdev: SCSI device to examine @@ -339,9 +363,7 @@ void ata_to_sense_error(struct ata_queue int ata_scsi_slave_config(struct scsi_device *sdev) { - sdev->use_10_for_rw = 1; - sdev->use_10_for_ms = 1; - + ata_scsi_sdev_config(sdev); blk_queue_max_phys_segments(sdev->request_queue, LIBATA_MAX_PRD); if (sdev->id < ATA_MAX_DEVICES) { @@ -351,19 +373,7 @@ int ata_scsi_slave_config(struct scsi_de ap = (struct ata_port *) &sdev->host->hostdata[0]; dev = &ap->device[sdev->id]; - /* TODO: 1024 is an arbitrary number, not the - * hardware maximum. This should be increased to - * 65534 when Jens Axboe's patch for dynamically - * determining max_sectors is merged. - */ - if ((dev->flags & ATA_DFLAG_LBA48) && - ((dev->flags & ATA_DFLAG_LOCK_SECTORS) == 0)) { - /* - * do not overwrite sdev->host->max_sectors, since - * other drives on this host may not support LBA48 - */ - blk_queue_max_sectors(sdev->request_queue, 2048); - } + ata_scsi_dev_config(sdev, dev); } return 0; /* scsi layer doesn't check return value, sigh */ @@ -1541,6 +1551,21 @@ static inline void ata_scsi_dump_cdb(str #endif } +static void __ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), + struct ata_port *ap, struct ata_device *dev) +{ + if (dev->class == ATA_DEV_ATA) { + ata_xlat_func_t xlat_func = ata_get_xlat_func(dev, + cmd->cmnd[0]); + + if (xlat_func) + ata_scsi_translate(ap, dev, cmd, done, xlat_func); + else + ata_scsi_simulate(dev->id, cmd, done); + } else + ata_scsi_translate(ap, dev, cmd, done, atapi_xlat); +} + /** * ata_scsi_queuecmd - Issue SCSI cdb to libata-managed device * @cmd: SCSI command to be sent @@ -1577,16 +1602,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd * goto out_unlock; } - if (dev->class == ATA_DEV_ATA) { - ata_xlat_func_t xlat_func = ata_get_xlat_func(dev, - cmd->cmnd[0]); - - if (xlat_func) - ata_scsi_translate(ap, dev, cmd, done, xlat_func); - else - ata_scsi_simulate(dev->id, cmd, done); - } else - ata_scsi_translate(ap, dev, cmd, done, atapi_xlat); + __ata_scsi_queuecmd(cmd, done, ap, dev); out_unlock: return 0; @@ -1678,3 +1694,148 @@ void ata_scsi_simulate(u16 *id, } } +/** + * ata_sas_port_alloc - Allocate port for a SAS attached SATA device + * @sdev: SCSI device to allocate port for + * @pdev: PCI device that the scsi device is attached to + * @port_info: Information from low-level host driver + * + * LOCKING: + * PCI/etc. bus probe sem. + * + * RETURNS: + * ata_port pointer on success / NULL on failure. + */ + +struct ata_port *ata_sas_port_alloc(struct scsi_device *sdev, + struct pci_dev *pdev, + struct ata_port_info *port_info) +{ + struct ata_port *ap = kzalloc(sizeof(*ap) + sizeof(void *), GFP_KERNEL); + struct ata_host_set *host_set = kzalloc(sizeof(*host_set), GFP_KERNEL); + + if (!ap || !host_set) { + kfree(ap); + kfree(host_set); + return NULL; + } + + host_set->dev = &pdev->dev; + host_set->n_ports = 1; + host_set->ops = port_info->port_ops; + host_set->ports[0] = ap; + ata_assign_lock(host_set, sdev->host->host_lock); + + ap->host_set = host_set; + ap->ops = port_info->port_ops; + ap->flags = port_info->host_flags; + ap->pio_mask = port_info->pio_mask; + ap->mwdma_mask = port_info->mwdma_mask; + ap->udma_mask = port_info->udma_mask; + ap->cbl = ATA_CBL_SATA; + ap->active_tag = ATA_TAG_POISON; + ap->last_ctl = 0xFF; + return ap; +} +EXPORT_SYMBOL_GPL(ata_sas_port_alloc); + +static void ata_sas_port_free(struct ata_port *ap) +{ + kfree(ap->host_set); + kfree(ap); +} + +/** + * ata_sas_port_init - Initialize a SATA device + * @ap: SATA port to initialize + * + * LOCKING: + * PCI/etc. bus probe sem. + * + * RETURNS: + * Zero on success, non-zero on error. + */ + +int ata_sas_port_init(struct ata_port *ap) +{ + int rc = ap->ops->port_start(ap); + + if (!rc) + rc = ata_bus_probe(ap); + + return rc; +} +EXPORT_SYMBOL_GPL(ata_sas_port_init); + +/** + * ata_sas_port_destroy - Destroy a SATA port allocated by ata_sas_port_alloc + * @ap: SATA port to destroy + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + */ + +void ata_sas_port_destroy(struct ata_port *ap) +{ + if (ap) { + ap->ops->port_stop(ap); + ata_sas_port_free(ap); + } +} +EXPORT_SYMBOL_GPL(ata_sas_port_destroy); + +/** + * ata_sas_slave_configure - Default slave_config routine for libata devices + * @sdev: SCSI device to configure + * @ap: ATA port to which SCSI device is attached + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * Zero. + */ + +int ata_sas_slave_configure(struct scsi_device *sdev, struct ata_port *ap) +{ + ata_scsi_sdev_config(sdev); + ata_scsi_dev_config(sdev, ap->device); + if (ata_dev_knobble(ap)) + blk_queue_max_sectors(sdev->request_queue, ATA_MAX_SECTORS); + return 0; +} +EXPORT_SYMBOL_GPL(ata_sas_slave_configure); + +/** + * ata_sas_queuecmd - Issue SCSI cdb to libata-managed device + * @cmd: SCSI command to be sent + * @done: Completion function, called when command is complete + * @ap: ATA port to which the command is being sent + * + * LOCKING: + * spin_lock_irqsave(host_set lock) + * + * RETURNS: + * Zero. + */ + +int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), + struct ata_port *ap) +{ + if (unlikely(!ata_dev_present(ap->device))) { + cmd->result = (DID_BAD_TARGET << 16); + done(cmd); + return 0; + } + + if (cmd->cmd_len > ap->cdb_len) { + cmd->result = (DID_ABORT << 16); + done(cmd); + return 0; + } + + __ata_scsi_queuecmd(cmd, done, ap, ap->device); + return 0; +} +EXPORT_SYMBOL_GPL(ata_sas_queuecmd); diff -puN drivers/scsi/libata-core.c~libata_sas drivers/scsi/libata-core.c --- linux-2.6/drivers/scsi/libata-core.c~libata_sas 2005-09-26 14:23:01.000000000 -0500 +++ linux-2.6-bjking1/drivers/scsi/libata-core.c 2005-09-26 14:23:01.000000000 -0500 @@ -1106,6 +1106,21 @@ static inline void ata_dump_id(struct at dev->id[93]); } +static void ata_set_cdb_len(struct ata_port *ap, unsigned int cdb_len) +{ + ap->cdb_len = cdb_len; + if (ap->host) + ap->host->max_cmd_len = cdb_len; +} + +static void ata_set_max_sectors(struct ata_port *ap, unsigned int max_sectors) +{ + if (ap->host) { + ap->host->max_sectors = ATA_MAX_SECTORS; + ap->host->hostt->max_sectors = ATA_MAX_SECTORS; + } +} + /** * ata_dev_identify - obtain IDENTIFY x DEVICE page * @ap: port on which device we wish to probe resides @@ -1269,7 +1284,7 @@ retry: dev->n_sectors = ata_id_u32(dev->id, 60); } - ap->host->max_cmd_len = 16; + ata_set_cdb_len(ap, 16); /* print device info to dmesg */ printk(KERN_INFO "ata%u: dev %u ATA, max %s, %Lu sectors:%s\n", @@ -1289,8 +1304,8 @@ retry: printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id); goto err_out_nosup; } - ap->cdb_len = (unsigned int) rc; - ap->host->max_cmd_len = (unsigned char) ap->cdb_len; + + ata_set_cdb_len(ap, rc); /* print device info to dmesg */ printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n", @@ -1309,12 +1324,6 @@ err_out: DPRINTK("EXIT, err\n"); } - -static inline u8 ata_dev_knobble(struct ata_port *ap) -{ - return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(ap->device->id))); -} - /** * ata_dev_config - Run device specific handlers and check for * SATA->PATA bridges @@ -1331,8 +1340,7 @@ void ata_dev_config(struct ata_port *ap, printk(KERN_INFO "ata%u(%u): applying bridge limits\n", ap->id, ap->device->devno); ap->udma_mask &= ATA_UDMA5; - ap->host->max_sectors = ATA_MAX_SECTORS; - ap->host->hostt->max_sectors = ATA_MAX_SECTORS; + ata_set_max_sectors(ap, ATA_MAX_SECTORS); ap->device->flags |= ATA_DFLAG_LOCK_SECTORS; } @@ -1355,7 +1363,7 @@ void ata_dev_config(struct ata_port *ap, * Zero on success, non-zero on error. */ -static int ata_bus_probe(struct ata_port *ap) +int ata_bus_probe(struct ata_port *ap) { unsigned int i, found = 0; diff -puN drivers/scsi/libata.h~libata_sas drivers/scsi/libata.h --- linux-2.6/drivers/scsi/libata.h~libata_sas 2005-09-26 14:23:01.000000000 -0500 +++ linux-2.6-bjking1/drivers/scsi/libata.h 2005-09-26 14:23:01.000000000 -0500 @@ -79,6 +79,8 @@ extern void ata_scsi_badcmd(struct scsi_ extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, unsigned int (*actor) (struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen)); +extern int ata_bus_probe(struct ata_port *ap); +extern int ata_sas_port_init(struct ata_port *ap); static inline void ata_bad_scsiop(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { @@ -90,4 +92,9 @@ static inline void ata_bad_cdb(struct sc ata_scsi_badcmd(cmd, done, 0x24, 0x00); } +static inline u8 ata_dev_knobble(struct ata_port *ap) +{ + return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(ap->device->id))); +} + #endif /* __LIBATA_H__ */ diff -puN include/linux/libata.h~libata_sas include/linux/libata.h --- linux-2.6/include/linux/libata.h~libata_sas 2005-09-26 14:23:01.000000000 -0500 +++ linux-2.6-bjking1/include/linux/libata.h 2005-09-26 14:23:01.000000000 -0500 @@ -400,6 +400,14 @@ extern int ata_scsi_ioctl(struct scsi_de extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); extern int ata_scsi_error(struct Scsi_Host *host); extern int ata_scsi_release(struct Scsi_Host *host); +extern void ata_sas_port_destroy(struct ata_port *ap); +extern struct ata_port *ata_sas_port_alloc(struct scsi_device *sdev, + struct pci_dev *pdev, + struct ata_port_info *port_info); +extern int ata_sas_port_init(struct ata_port *ap); +extern int ata_sas_slave_configure(struct scsi_device *sdev, struct ata_port *ap); +extern int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), + struct ata_port *ap); extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); /* * Default driver ops implementations _ ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [RFC 0/2] libata: support SATA devices on SAS HBAs 2005-10-03 21:56 [RFC 0/2] libata: support SATA devices on SAS HBAs Brian King 2005-10-03 21:58 ` [RFC 1/2] libata: configurable host_set lock Brian King 2005-10-03 21:58 ` [RFC 2/2] libata: support SATA devices on SAS HBAs Brian King @ 2005-10-04 9:56 ` Jeff Garzik 2005-10-04 10:22 ` Bartlomiej Zolnierkiewicz 2 siblings, 1 reply; 38+ messages in thread From: Jeff Garzik @ 2005-10-04 9:56 UTC (permalink / raw) To: brking; +Cc: linux-ide Brian King wrote: > The following patches enhance libata to allow SAS device drivers > to utilize libata to talk to SATA devices. It introduces some > new APIs which allow libata to be used without allocating a > virtual scsi host. This is just a snapshot of what I've > come up with at this point and I figured I would post it to > see if I was heading in a reasonable direction or not, so > don't expect the code below to do anything useful at this point > as it is untested. hmmmm, neat. My gut feeling feeling says a slightly better direction might be warranted, but I'll have to think a bit to put that feeling towords. * One thought is the desire to allocate a single ata_host_set for the HBA, rather than avoiding ata_host_set. * Another thought is the locking scheme -- Christoph once poked me about libata's use of scsi_assign_lock(), which I rather like but he didn't :) So by the transitive(?) property, if libata's locking is useful, then your solution is probably OK. And vice versa. * I also wonder if there isn't any severe leakage or oops somewhere, because you don't really use ata_host_set, just ata_port. But note again, these are 6am thoughts, not in-depth analysis. Jeff ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [RFC 0/2] libata: support SATA devices on SAS HBAs 2005-10-04 9:56 ` [RFC 0/2] " Jeff Garzik @ 2005-10-04 10:22 ` Bartlomiej Zolnierkiewicz 2005-10-04 20:56 ` Bartlomiej Zolnierkiewicz 0 siblings, 1 reply; 38+ messages in thread From: Bartlomiej Zolnierkiewicz @ 2005-10-04 10:22 UTC (permalink / raw) To: Jeff Garzik; +Cc: brking, linux-ide On 10/4/05, Jeff Garzik <jgarzik@pobox.com> wrote: > Brian King wrote: > > The following patches enhance libata to allow SAS device drivers > > to utilize libata to talk to SATA devices. It introduces some > > new APIs which allow libata to be used without allocating a > > virtual scsi host. This is just a snapshot of what I've > > come up with at this point and I figured I would post it to > > see if I was heading in a reasonable direction or not, so > > don't expect the code below to do anything useful at this point > > as it is untested. > > hmmmm, neat. My gut feeling feeling says a slightly better direction > might be warranted, but I'll have to think a bit to put that feeling > towords. > > * One thought is the desire to allocate a single ata_host_set for the > HBA, rather than avoiding ata_host_set. For SAS we should definitely avoid ata_host_set. > * Another thought is the locking scheme -- Christoph once poked me about > libata's use of scsi_assign_lock(), which I rather like but he didn't :) > So by the transitive(?) property, if libata's locking is useful, then > your solution is probably OK. And vice versa. host_set->lock is not useful for SAS et all and libata can be easily fixed to not require it for SAS (I'll make a patch later). > * I also wonder if there isn't any severe leakage or oops somewhere, > because you don't really use ata_host_set, just ata_port. > > But note again, these are 6am thoughts, not in-depth analysis. :) Bartlomiej ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [RFC 0/2] libata: support SATA devices on SAS HBAs 2005-10-04 10:22 ` Bartlomiej Zolnierkiewicz @ 2005-10-04 20:56 ` Bartlomiej Zolnierkiewicz 2005-10-05 20:59 ` Jeff Garzik 0 siblings, 1 reply; 38+ messages in thread From: Bartlomiej Zolnierkiewicz @ 2005-10-04 20:56 UTC (permalink / raw) To: Jeff Garzik; +Cc: brking, linux-ide [-- Attachment #1: Type: text/plain, Size: 1751 bytes --] On 10/4/05, Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> wrote: > On 10/4/05, Jeff Garzik <jgarzik@pobox.com> wrote: > > Brian King wrote: > > > The following patches enhance libata to allow SAS device drivers > > > to utilize libata to talk to SATA devices. It introduces some > > > new APIs which allow libata to be used without allocating a > > > virtual scsi host. This is just a snapshot of what I've > > > come up with at this point and I figured I would post it to > > > see if I was heading in a reasonable direction or not, so > > > don't expect the code below to do anything useful at this point > > > as it is untested. > > > > hmmmm, neat. My gut feeling feeling says a slightly better direction > > might be warranted, but I'll have to think a bit to put that feeling > > towords. > > > > * One thought is the desire to allocate a single ata_host_set for the > > HBA, rather than avoiding ata_host_set. > > For SAS we should definitely avoid ata_host_set. > > > * Another thought is the locking scheme -- Christoph once poked me about > > libata's use of scsi_assign_lock(), which I rather like but he didn't :) > > So by the transitive(?) property, if libata's locking is useful, then > > your solution is probably OK. And vice versa. > > host_set->lock is not useful for SAS et all and libata can > be easily fixed to not require it for SAS (I'll make a patch later). Attached (sorry for that but I needed to push it through gmail). Please note that all other usages of host_set->lock are dependent on existence of hardware (S)ATA port which is simply not a case for SAS. We can also avoid using host_set entirely by allowing SAS layer to only register struct ata_port. Thanks, Bartlomiej [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #2: libata-qc_transport.patch --] [-- Type: text/x-patch; name="libata-qc_transport.patch", Size: 10383 bytes --] [PATCH] libata: add ops->qc_transport for SAS * add ->qc_transport to struct ata_port_operations * add default ata_qc_transport() and update all host drivers Thanks to this change we won't have to depend on host_set and host_set->lock for devices attached to SAS HBAs. Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Index: libata-dev/drivers/scsi/libata-core.c =================================================================== --- libata-dev.orig/drivers/scsi/libata-core.c +++ libata-dev/drivers/scsi/libata-core.c @@ -1138,7 +1138,6 @@ static void ata_dev_identify(struct ata_ unsigned int using_edd; DECLARE_COMPLETION(wait); struct ata_queued_cmd *qc; - unsigned long flags; int rc; if (!ata_dev_present(dev)) { @@ -1179,9 +1178,7 @@ retry: qc->waiting = &wait; qc->complete_fn = ata_qc_complete_noop; - spin_lock_irqsave(&ap->host_set->lock, flags); - rc = ata_qc_issue(qc); - spin_unlock_irqrestore(&ap->host_set->lock, flags); + rc = ap->ops->qc_transport(qc); if (rc) goto err_out; @@ -2114,7 +2111,6 @@ static void ata_dev_set_xfermode(struct DECLARE_COMPLETION(wait); struct ata_queued_cmd *qc; int rc; - unsigned long flags; /* set up set-features taskfile */ DPRINTK("set features - xfer mode\n"); @@ -2131,9 +2127,7 @@ static void ata_dev_set_xfermode(struct qc->waiting = &wait; qc->complete_fn = ata_qc_complete_noop; - spin_lock_irqsave(&ap->host_set->lock, flags); - rc = ata_qc_issue(qc); - spin_unlock_irqrestore(&ap->host_set->lock, flags); + rc = ap->ops->qc_transport(qc); if (rc) ata_port_disable(ap); @@ -2933,7 +2927,6 @@ static void atapi_request_sense(struct a { DECLARE_COMPLETION(wait); struct ata_queued_cmd *qc; - unsigned long flags; int rc; DPRINTK("ATAPI request sense\n"); @@ -2962,9 +2955,7 @@ static void atapi_request_sense(struct a qc->waiting = &wait; qc->complete_fn = ata_qc_complete_noop; - spin_lock_irqsave(&ap->host_set->lock, flags); - rc = ata_qc_issue(qc); - spin_unlock_irqrestore(&ap->host_set->lock, flags); + rc = ap->ops->qc_transport(qc); if (rc) ata_port_disable(ap); @@ -3321,6 +3312,29 @@ err_out: return -1; } +/** + * ata_qc_transport - transport taskfile to device + * @qc: command to issue to device + * + * LOCKING: + * Obtains host_set lock. + * + * RETURNS: + * Zero on success, negative on error. + */ + +int ata_qc_transport(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + unsigned long flags; + int rc; + + spin_lock_irqsave(&ap->host_set->lock, flags); + rc = ata_qc_issue(qc); + spin_unlock_irqrestore(&ap->host_set->lock, flags); + + return rc; +} /** * ata_qc_issue_prot - issue taskfile to device in proto-dependent manner @@ -4593,6 +4607,7 @@ EXPORT_SYMBOL_GPL(ata_host_set_remove); EXPORT_SYMBOL_GPL(ata_sg_init); EXPORT_SYMBOL_GPL(ata_sg_init_one); EXPORT_SYMBOL_GPL(ata_qc_complete); +EXPORT_SYMBOL_GPL(ata_qc_transport); EXPORT_SYMBOL_GPL(ata_qc_issue_prot); EXPORT_SYMBOL_GPL(ata_eng_timeout); EXPORT_SYMBOL_GPL(ata_tf_load); Index: libata-dev/include/linux/libata.h =================================================================== --- libata-dev.orig/include/linux/libata.h +++ libata-dev/include/linux/libata.h @@ -352,6 +352,7 @@ struct ata_port_operations { void (*qc_prep) (struct ata_queued_cmd *qc); int (*qc_issue) (struct ata_queued_cmd *qc); + int (*qc_transport) (struct ata_queued_cmd *qc); void (*eng_timeout) (struct ata_port *ap); @@ -419,6 +420,7 @@ extern void ata_host_stop (struct ata_ho extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs); extern void ata_qc_prep(struct ata_queued_cmd *qc); extern int ata_qc_issue_prot(struct ata_queued_cmd *qc); +extern int ata_qc_transport(struct ata_queued_cmd *qc); extern void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen); extern void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg, Index: libata-dev/drivers/scsi/ahci.c =================================================================== --- libata-dev.orig/drivers/scsi/ahci.c +++ libata-dev/drivers/scsi/ahci.c @@ -230,6 +230,7 @@ static struct ata_port_operations ahci_o .qc_prep = ahci_qc_prep, .qc_issue = ahci_qc_issue, + .qc_transport = ata_qc_transport, .eng_timeout = ahci_eng_timeout, Index: libata-dev/drivers/scsi/ata_piix.c =================================================================== --- libata-dev.orig/drivers/scsi/ata_piix.c +++ libata-dev/drivers/scsi/ata_piix.c @@ -166,6 +166,7 @@ static struct ata_port_operations piix_p .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, + .qc_transport = ata_qc_transport, .eng_timeout = ata_eng_timeout, @@ -194,6 +195,7 @@ static struct ata_port_operations piix_s .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, + .qc_transport = ata_qc_transport, .eng_timeout = ata_eng_timeout, Index: libata-dev/drivers/scsi/sata_mv.c =================================================================== --- libata-dev.orig/drivers/scsi/sata_mv.c +++ libata-dev/drivers/scsi/sata_mv.c @@ -223,6 +223,7 @@ static struct ata_port_operations mv_ops .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, + .qc_transport = ata_qc_transport, .eng_timeout = ata_eng_timeout, Index: libata-dev/drivers/scsi/sata_nv.c =================================================================== --- libata-dev.orig/drivers/scsi/sata_nv.c +++ libata-dev/drivers/scsi/sata_nv.c @@ -252,6 +252,7 @@ static struct ata_port_operations nv_ops .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, + .qc_transport = ata_qc_transport, .eng_timeout = ata_eng_timeout, .irq_handler = nv_interrupt, .irq_clear = ata_bmdma_irq_clear, Index: libata-dev/drivers/scsi/sata_promise.c =================================================================== --- libata-dev.orig/drivers/scsi/sata_promise.c +++ libata-dev/drivers/scsi/sata_promise.c @@ -125,6 +125,7 @@ static struct ata_port_operations pdc_sa .qc_prep = pdc_qc_prep, .qc_issue = pdc_qc_issue_prot, + .qc_transport = ata_qc_transport, .eng_timeout = pdc_eng_timeout, .irq_handler = pdc_interrupt, .irq_clear = pdc_irq_clear, @@ -148,6 +149,7 @@ static struct ata_port_operations pdc_pa .qc_prep = pdc_qc_prep, .qc_issue = pdc_qc_issue_prot, + .qc_transport = ata_qc_transport, .eng_timeout = pdc_eng_timeout, .irq_handler = pdc_interrupt, .irq_clear = pdc_irq_clear, Index: libata-dev/drivers/scsi/sata_qstor.c =================================================================== --- libata-dev.orig/drivers/scsi/sata_qstor.c +++ libata-dev/drivers/scsi/sata_qstor.c @@ -156,6 +156,7 @@ static struct ata_port_operations qs_ata .phy_reset = qs_phy_reset, .qc_prep = qs_qc_prep, .qc_issue = qs_qc_issue, + .qc_transport = ata_qc_transport, .eng_timeout = qs_eng_timeout, .irq_handler = qs_intr, .irq_clear = qs_irq_clear, Index: libata-dev/drivers/scsi/sata_sil.c =================================================================== --- libata-dev.orig/drivers/scsi/sata_sil.c +++ libata-dev/drivers/scsi/sata_sil.c @@ -166,6 +166,7 @@ static struct ata_port_operations sil_op .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, + .qc_transport = ata_qc_transport, .eng_timeout = ata_eng_timeout, .irq_handler = ata_interrupt, .irq_clear = ata_bmdma_irq_clear, Index: libata-dev/drivers/scsi/sata_sis.c =================================================================== --- libata-dev.orig/drivers/scsi/sata_sis.c +++ libata-dev/drivers/scsi/sata_sis.c @@ -116,6 +116,7 @@ static struct ata_port_operations sis_op .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, + .qc_transport = ata_qc_transport, .eng_timeout = ata_eng_timeout, .irq_handler = ata_interrupt, .irq_clear = ata_bmdma_irq_clear, Index: libata-dev/drivers/scsi/sata_svw.c =================================================================== --- libata-dev.orig/drivers/scsi/sata_svw.c +++ libata-dev/drivers/scsi/sata_svw.c @@ -311,6 +311,7 @@ static struct ata_port_operations k2_sat .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, + .qc_transport = ata_qc_transport, .eng_timeout = ata_eng_timeout, .irq_handler = ata_interrupt, .irq_clear = ata_bmdma_irq_clear, Index: libata-dev/drivers/scsi/sata_sx4.c =================================================================== --- libata-dev.orig/drivers/scsi/sata_sx4.c +++ libata-dev/drivers/scsi/sata_sx4.c @@ -206,6 +206,7 @@ static struct ata_port_operations pdc_20 .phy_reset = pdc_20621_phy_reset, .qc_prep = pdc20621_qc_prep, .qc_issue = pdc20621_qc_issue_prot, + .qc_transport = ata_qc_transport, .eng_timeout = pdc_eng_timeout, .irq_handler = pdc20621_interrupt, .irq_clear = pdc20621_irq_clear, Index: libata-dev/drivers/scsi/sata_uli.c =================================================================== --- libata-dev.orig/drivers/scsi/sata_uli.c +++ libata-dev/drivers/scsi/sata_uli.c @@ -107,6 +107,7 @@ static struct ata_port_operations uli_op .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, + .qc_transport = ata_qc_transport, .eng_timeout = ata_eng_timeout, Index: libata-dev/drivers/scsi/sata_via.c =================================================================== --- libata-dev.orig/drivers/scsi/sata_via.c +++ libata-dev/drivers/scsi/sata_via.c @@ -127,6 +127,7 @@ static struct ata_port_operations svia_s .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, + .qc_transport = ata_qc_transport, .eng_timeout = ata_eng_timeout, Index: libata-dev/drivers/scsi/sata_vsc.c =================================================================== --- libata-dev.orig/drivers/scsi/sata_vsc.c +++ libata-dev/drivers/scsi/sata_vsc.c @@ -245,6 +245,7 @@ static struct ata_port_operations vsc_sa .bmdma_status = ata_bmdma_status, .qc_prep = ata_qc_prep, .qc_issue = ata_qc_issue_prot, + .qc_transport = ata_qc_transport, .eng_timeout = ata_eng_timeout, .irq_handler = vsc_sata_interrupt, .irq_clear = ata_bmdma_irq_clear, ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [RFC 0/2] libata: support SATA devices on SAS HBAs 2005-10-04 20:56 ` Bartlomiej Zolnierkiewicz @ 2005-10-05 20:59 ` Jeff Garzik 2005-10-24 22:17 ` [PATCH " Brian King 2005-10-25 17:57 ` [RFC " Brian King 0 siblings, 2 replies; 38+ messages in thread From: Jeff Garzik @ 2005-10-05 20:59 UTC (permalink / raw) To: Bartlomiej Zolnierkiewicz; +Cc: brking, linux-ide Bartlomiej Zolnierkiewicz wrote: > [PATCH] libata: add ops->qc_transport for SAS > > * add ->qc_transport to struct ata_port_operations > * add default ata_qc_transport() and update all host drivers > > Thanks to this change we won't have to depend on host_set > and host_set->lock for devices attached to SAS HBAs. > > Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> Seems sane at a quick glance, though I'm a bit disappointed we have to add yet another level of indirection to the hot path. You made a good point, though, by pointing out that all the ata_qc_xxx stuff is essentially completely inside a single lock domain. Other notes: There may be other dependencies such as wanting to reference the struct device pointer in host_set and similar details that need handling. Also, I was planning to move some of the ata_port_ops into a separate host_set ops, since they (hooks such as ->irq_clear or ->host_stop) are really host-wide hooks, not per-port hooks. Jeff ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 0/2] libata: support SATA devices on SAS HBAs 2005-10-05 20:59 ` Jeff Garzik @ 2005-10-24 22:17 ` Brian King 2005-10-24 22:19 ` [PATCH 1/2] libata: Remove dependence on host_set->dev for SAS Brian King ` (2 more replies) 2005-10-25 17:57 ` [RFC " Brian King 1 sibling, 3 replies; 38+ messages in thread From: Brian King @ 2005-10-24 22:17 UTC (permalink / raw) To: Jeff Garzik; +Cc: Bartlomiej Zolnierkiewicz, linux-ide, linux-scsi The following patches enhance libata to allow SAS device drivers to utilize libata to talk to SATA devices. It introduces some new APIs which allow libata to be used without allocating a virtual scsi host. In the context of SAS, a struct ata_port is not a physical port, but rather becomes a virtual construct. Since my last post, I have removed the dependence on the host_set struct. The following two patches depend on the qc_transport patch: http://marc.theaimsgroup.com/?l=linux-ide&m=112845939215286&w=2 The API is the same as the last time I posted it to linux-ide, but here is the description again: New APIs: ata_sas_port_alloc - Allocate an ata_port ata_sas_port_init - Initialize an ata_port (probe device, etc) ata_sas_port_destroy - Free an ata_port allocated by ata_sas_port_alloc ata_sas_slave_configure - configure scsi device ata_sas_queuecmd - queue a scsi command, similar to ata_scsi_queuecomand These new APIs can be used either directly by a SAS LLDD or could be used by the SAS transport class. Possible usage for a SAS LLDD would be: scsi_scan_host slave_alloc ata_sas_port_alloc ata_sas_port_init slave_configure ata_sas_slave_configure Commands received by the LLDD for SATA devices would call ata_sas_queuecmd. Device teardown would occur with: slave_destroy ata_sas_port_destroy -- Brian King eServer Storage I/O IBM Linux Technology Center ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 1/2] libata: Remove dependence on host_set->dev for SAS 2005-10-24 22:17 ` [PATCH " Brian King @ 2005-10-24 22:19 ` Brian King 2005-10-25 17:53 ` Jeff Garzik 2005-10-24 22:20 ` [PATCH 2/2] libata: Add support for SATA attachment to SAS adapters Brian King 2005-10-25 12:59 ` [PATCH 0/2] libata: support SATA devices on SAS HBAs Luben Tuikov 2 siblings, 1 reply; 38+ messages in thread From: Brian King @ 2005-10-24 22:19 UTC (permalink / raw) To: brking; +Cc: Jeff Garzik, Bartlomiej Zolnierkiewicz, linux-ide, linux-scsi [-- Attachment #1: Type: text/plain, Size: 0 bytes --] [-- Attachment #2: libata_host_set_dev.patch --] [-- Type: text/plain, Size: 2970 bytes --] Remove some of the dependence on the host_set struct in preparation for supporting SAS HBAs. Adds a struct device pointer to the ata_port struct. This patch depends on the qc_transport patch: http://marc.theaimsgroup.com/?l=linux-ide&m=112845939215286&w=2 Signed-off-by: Brian King <brking@us.ibm.com> --- linux-2.6-bjking1/drivers/scsi/libata-core.c | 13 +++++++------ linux-2.6-bjking1/include/linux/libata.h | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) diff -puN include/linux/libata.h~libata_host_set_dev include/linux/libata.h --- linux-2.6/include/linux/libata.h~libata_host_set_dev 2005-10-24 15:04:22.000000000 -0500 +++ linux-2.6-bjking1/include/linux/libata.h 2005-10-24 15:04:22.000000000 -0500 @@ -315,6 +315,7 @@ struct ata_port { struct ata_host_stats stats; struct ata_host_set *host_set; + struct device *dev; struct work_struct packet_task; diff -puN drivers/scsi/libata-core.c~libata_host_set_dev drivers/scsi/libata-core.c --- linux-2.6/drivers/scsi/libata-core.c~libata_host_set_dev 2005-10-24 15:04:22.000000000 -0500 +++ linux-2.6-bjking1/drivers/scsi/libata-core.c 2005-10-24 15:04:22.000000000 -0500 @@ -2162,9 +2162,9 @@ static void ata_sg_clean(struct ata_queu DPRINTK("unmapping %u sg elements\n", qc->n_elem); if (qc->flags & ATA_QCFLAG_SG) - dma_unmap_sg(ap->host_set->dev, sg, qc->n_elem, dir); + dma_unmap_sg(ap->dev, sg, qc->n_elem, dir); else - dma_unmap_single(ap->host_set->dev, sg_dma_address(&sg[0]), + dma_unmap_single(ap->dev, sg_dma_address(&sg[0]), sg_dma_len(&sg[0]), dir); qc->flags &= ~ATA_QCFLAG_DMAMAP; @@ -2335,7 +2335,7 @@ static int ata_sg_setup_one(struct ata_q struct scatterlist *sg = qc->sg; dma_addr_t dma_address; - dma_address = dma_map_single(ap->host_set->dev, qc->buf_virt, + dma_address = dma_map_single(ap->dev, qc->buf_virt, sg->length, dir); if (dma_mapping_error(dma_address)) return -1; @@ -2373,7 +2373,7 @@ static int ata_sg_setup(struct ata_queue assert(qc->flags & ATA_QCFLAG_SG); dir = qc->dma_dir; - n_elem = dma_map_sg(ap->host_set->dev, sg, qc->n_elem, dir); + n_elem = dma_map_sg(ap->dev, sg, qc->n_elem, dir); if (n_elem < 1) return -1; @@ -3845,7 +3845,7 @@ err_out: int ata_port_start (struct ata_port *ap) { - struct device *dev = ap->host_set->dev; + struct device *dev = ap->dev; ap->prd = dma_alloc_coherent(dev, ATA_PRD_TBL_SZ, &ap->prd_dma, GFP_KERNEL); if (!ap->prd) @@ -3870,7 +3870,7 @@ int ata_port_start (struct ata_port *ap) void ata_port_stop (struct ata_port *ap) { - struct device *dev = ap->host_set->dev; + struct device *dev = ap->dev; dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma); } @@ -3937,6 +3937,7 @@ static void ata_host_init(struct ata_por ap->host = host; ap->ctl = ATA_DEVCTL_OBS; ap->host_set = host_set; + ap->dev = ent->dev; ap->port_no = port_no; ap->hard_port_no = ent->legacy_mode ? ent->hard_port_no : port_no; _ ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 1/2] libata: Remove dependence on host_set->dev for SAS 2005-10-24 22:19 ` [PATCH 1/2] libata: Remove dependence on host_set->dev for SAS Brian King @ 2005-10-25 17:53 ` Jeff Garzik 2005-10-25 19:30 ` Brian King 0 siblings, 1 reply; 38+ messages in thread From: Jeff Garzik @ 2005-10-25 17:53 UTC (permalink / raw) To: brking; +Cc: Bartlomiej Zolnierkiewicz, linux-ide, linux-scsi Brian King wrote: > Remove some of the dependence on the host_set struct > in preparation for supporting SAS HBAs. Adds a struct device > pointer to the ata_port struct. > > This patch depends on the qc_transport patch: > > http://marc.theaimsgroup.com/?l=linux-ide&m=112845939215286&w=2 > > Signed-off-by: Brian King <brking@us.ibm.com> > --- > > linux-2.6-bjking1/drivers/scsi/libata-core.c | 13 +++++++------ > linux-2.6-bjking1/include/linux/libata.h | 1 + > 2 files changed, 8 insertions(+), 6 deletions(-) > > diff -puN include/linux/libata.h~libata_host_set_dev include/linux/libata.h > --- linux-2.6/include/linux/libata.h~libata_host_set_dev 2005-10-24 15:04:22.000000000 -0500 > +++ linux-2.6-bjking1/include/linux/libata.h 2005-10-24 15:04:22.000000000 -0500 > @@ -315,6 +315,7 @@ struct ata_port { > > struct ata_host_stats stats; > struct ata_host_set *host_set; > + struct device *dev; > > struct work_struct packet_task; > Patch seems basically OK. But taking this patch to its conclusion means deleting 'dev' from struct ata_host_set too... I wonder what breakage will result from that? Jeff ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 1/2] libata: Remove dependence on host_set->dev for SAS 2005-10-25 17:53 ` Jeff Garzik @ 2005-10-25 19:30 ` Brian King 2005-10-25 19:43 ` Jeff Garzik 0 siblings, 1 reply; 38+ messages in thread From: Brian King @ 2005-10-25 19:30 UTC (permalink / raw) To: Jeff Garzik; +Cc: Bartlomiej Zolnierkiewicz, linux-ide, linux-scsi Jeff Garzik wrote: > Brian King wrote: > >>Remove some of the dependence on the host_set struct >>in preparation for supporting SAS HBAs. Adds a struct device >>pointer to the ata_port struct. >> >>This patch depends on the qc_transport patch: >> >>http://marc.theaimsgroup.com/?l=linux-ide&m=112845939215286&w=2 >> >>Signed-off-by: Brian King <brking@us.ibm.com> >>--- >> >> linux-2.6-bjking1/drivers/scsi/libata-core.c | 13 +++++++------ >> linux-2.6-bjking1/include/linux/libata.h | 1 + >> 2 files changed, 8 insertions(+), 6 deletions(-) >> >>diff -puN include/linux/libata.h~libata_host_set_dev include/linux/libata.h >>--- linux-2.6/include/linux/libata.h~libata_host_set_dev 2005-10-24 15:04:22.000000000 -0500 >>+++ linux-2.6-bjking1/include/linux/libata.h 2005-10-24 15:04:22.000000000 -0500 >>@@ -315,6 +315,7 @@ struct ata_port { >> >> struct ata_host_stats stats; >> struct ata_host_set *host_set; >>+ struct device *dev; >> >> struct work_struct packet_task; >> > > > Patch seems basically OK. But taking this patch to its conclusion means > deleting 'dev' from struct ata_host_set too... I wonder what breakage > will result from that? It breaks ata_pci_host_stop: void ata_pci_host_stop (struct ata_host_set *host_set) { struct pci_dev *pdev = to_pci_dev(host_set->dev); pci_iounmap(pdev, host_set->mmio_base); } I could poke into the first port here to get the 'dev', but I didn't particularly like that. I also thought about changing the prototype for host_set to pass in the 'dev' pointer, but wasn't sure that would work for the non PCI case. Or, we just live with the duplication... -- Brian King eServer Storage I/O IBM Linux Technology Center ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 1/2] libata: Remove dependence on host_set->dev for SAS 2005-10-25 19:30 ` Brian King @ 2005-10-25 19:43 ` Jeff Garzik 2005-10-25 22:48 ` Luben Tuikov 0 siblings, 1 reply; 38+ messages in thread From: Jeff Garzik @ 2005-10-25 19:43 UTC (permalink / raw) To: brking; +Cc: Bartlomiej Zolnierkiewicz, linux-ide, linux-scsi Brian King wrote: > Or, we just live with the duplication... That may be the best practical solution. I wonder, additionally, if we need to be getting a reference each time we store the pointer. Traditionally the struct device object lifetime has always been entirely within the bus device lifetime, but with this new work that may need rethinking. Jeff ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 1/2] libata: Remove dependence on host_set->dev for SAS 2005-10-25 19:43 ` Jeff Garzik @ 2005-10-25 22:48 ` Luben Tuikov 2005-10-27 16:05 ` Brian King 0 siblings, 1 reply; 38+ messages in thread From: Luben Tuikov @ 2005-10-25 22:48 UTC (permalink / raw) To: Jeff Garzik; +Cc: brking, Bartlomiej Zolnierkiewicz, linux-ide, linux-scsi On 10/25/05 15:43, Jeff Garzik wrote: > Brian King wrote: > >>Or, we just live with the duplication... > > > That may be the best practical solution. > > I wonder, additionally, if we need to be getting a reference each time > we store the pointer. Traditionally the struct device object lifetime > has always been entirely within the bus device lifetime, but with this > new work that may need rethinking. Would it be a good idea to abstract most of this in say something like struct satl_device_struct { -- data... ; /* The registering entity calls this for SATL to translate to an ATA task(s) and execute. Filled in by the SATL Layer. */ int (*execute_scsi_task)(struct satl_device_struct *, struct scsi_cmnd *); /* SATL layer calls this to send an ata_task to the device. Filled in by the registering entity. */ int (*execute_ata_task)(struct satl_device_struct *, struct ata_task *); -- recovery methods common to SATA-over-anything; filled in by registering \ entity }; (ata task to be properly constructed: FIS, sg lists, etc.) Then libata-scsi would only have to export two (2) functions: int satl_register_device(struct satl_device_struct *); void satl_unregister_device(struct satl_device_struct *); EXPORT_SYMBOL_GPL(satl_register_device); EXPORT_SYMBOL_GPL(satl_unregister_device); And the rest are in the struct satl_device_struct for which translation is being provided. Thus, error handling can also be "commonalized" as per the entity registering for the service. The whole point is to have this at device level as opposed to libata's port level. Plus it simplifies the code of entities registering for this service. <I was going to draw ascii art, but ran out of time> Luben -- http://linux.adaptec.com/sas/ http://www.adaptec.com/sas/ ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 1/2] libata: Remove dependence on host_set->dev for SAS 2005-10-25 22:48 ` Luben Tuikov @ 2005-10-27 16:05 ` Brian King 2005-10-27 20:15 ` Luben Tuikov 2005-11-24 0:53 ` Douglas Gilbert 0 siblings, 2 replies; 38+ messages in thread From: Brian King @ 2005-10-27 16:05 UTC (permalink / raw) To: Luben Tuikov Cc: Jeff Garzik, Bartlomiej Zolnierkiewicz, linux-ide, linux-scsi Luben Tuikov wrote: > Would it be a good idea to abstract most of this in > say something like > > struct satl_device_struct { > -- data... ; > > /* The registering entity calls this for SATL to translate > to an ATA task(s) and execute. Filled in by the SATL Layer. */ > int (*execute_scsi_task)(struct satl_device_struct *, struct scsi_cmnd *); > > /* SATL layer calls this to send an ata_task to the device. > Filled in by the registering entity. */ > int (*execute_ata_task)(struct satl_device_struct *, struct ata_task *); > > -- recovery methods common to SATA-over-anything; filled in by registering > \ entity > }; > > (ata task to be properly constructed: FIS, sg lists, etc.) > > Then libata-scsi would only have to export two (2) functions: > > int satl_register_device(struct satl_device_struct *); > void satl_unregister_device(struct satl_device_struct *); > > EXPORT_SYMBOL_GPL(satl_register_device); > EXPORT_SYMBOL_GPL(satl_unregister_device); Where would you be calling satl_register_device in your SAS class? It looks like this would force libata to be the one to attach the ULD, which would also force it to create a separate scsi_host for each device, which is something I wanted to avoid. I think you really need a libata API that the LLDD can call from its queuecommand function to translate and send a command, which then calls back into the LLDD to send the FIS to the hardware. This allows for all SAS/SATA devices under the same HBA to show up under the same scsi_host. Brian -- Brian King eServer Storage I/O IBM Linux Technology Center ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 1/2] libata: Remove dependence on host_set->dev for SAS 2005-10-27 16:05 ` Brian King @ 2005-10-27 20:15 ` Luben Tuikov 2005-11-24 0:53 ` Douglas Gilbert 1 sibling, 0 replies; 38+ messages in thread From: Luben Tuikov @ 2005-10-27 20:15 UTC (permalink / raw) To: brking; +Cc: Jeff Garzik, Bartlomiej Zolnierkiewicz, linux-ide, linux-scsi On 10/27/05 12:05, Brian King wrote: > Luben Tuikov wrote: > >>Would it be a good idea to abstract most of this in >>say something like >> >> struct satl_device_struct { >> -- data... ; >> >> /* The registering entity calls this for SATL to translate >> to an ATA task(s) and execute. Filled in by the SATL Layer. */ >> int (*execute_scsi_task)(struct satl_device_struct *, struct scsi_cmnd *); >> >> /* SATL layer calls this to send an ata_task to the device. >> Filled in by the registering entity. */ >> int (*execute_ata_task)(struct satl_device_struct *, struct ata_task *); >> >> -- recovery methods common to SATA-over-anything; filled in by registering >> \ entity >> }; >> >>(ata task to be properly constructed: FIS, sg lists, etc.) >> >>Then libata-scsi would only have to export two (2) functions: >> >>int satl_register_device(struct satl_device_struct *); >>void satl_unregister_device(struct satl_device_struct *); >> >>EXPORT_SYMBOL_GPL(satl_register_device); >>EXPORT_SYMBOL_GPL(satl_unregister_device); > > > Where would you be calling satl_register_device in your SAS class? Just before you register the device with SCSI Core. > It looks like this would force libata to be the one to attach the ULD, > which would also force it to create a separate scsi_host for each > device, which is something I wanted to avoid. I think you really need a The opposite. The service provided by SATL would be just translation, similarly to the SAT spec. It happens at device level, not port level as it is done in libata. It doesn't care about hosts, etc. There will be only one host. The whole point of all this is that neither SATL nor the entity registering for service care about hosts or what-not. Translation is done at device level. It goes like this: "Here is a scsi command to be executed, and here is how you send tasks to the ATA device. Translate for me please." > libata API that the LLDD can call from its queuecommand function > to translate and send a command, which then calls back into the LLDD > to send the FIS to the hardware. This allows for all SAS/SATA devices > under the same HBA to show up under the same scsi_host. You'd also be able to do the same thing using this infrastructure, since translation happens at device level. How and where it is represented "above" is the caller's (the one who registers with the service) responsibility. So, for example, using the SAS Transport Layer/Stack, when SCSI Core calls the queuecommand() method, we check if it is a SATA device and if it is we call execute_scsi_task() which was filled in by SATL upon registration (satl_register_device()). SATL does whatever is necessary to simulate this command, calling execute_ata_task() one or more times. execute_ata_task() was filled in by the entity registering for this service (say, the SAS Transport Layer). Like so: struct satl_device_struct *satl_dev = xalloc(one); satl_dev->execute_ata_task = our_execute_ata_task_func; satl_dev->... = ...; satl_register_device(satl_dev); /* Now satl_dev->execute_scsi_task was filled in by SATL, and points to a SATL function which would do translation for the device regsitered.*/ In queuecommand(): if (dev->dev_type == SATA_DEV) dev->satl_dev->execute_scsi_task(dev->satl_dev, scsi_cmnd); else /* dispatch to SAS layer -- current code */ One thing which may change is that execute_scsi_task() may want to take something more abstracted like say satl_scsi_task, whereby the completion method is in the struct -- similarly to the way it is done in struct sas_task in include/scsi/sas/sas_task.h::178. Notice how object oriented this is. Other function stubs which would live in struct satl_device_struct is the two device resets (depending on the type of device) and a few more, so that recovery is abstracted away similarly. Then the entity registering for the service fills those in if it has them or if it can implement them. Luben -- http://linux.adaptec.com/sas/ http://www.adaptec.com/sas/ ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 1/2] libata: Remove dependence on host_set->dev for SAS 2005-10-27 16:05 ` Brian King 2005-10-27 20:15 ` Luben Tuikov @ 2005-11-24 0:53 ` Douglas Gilbert 2005-11-24 1:07 ` Jeff Garzik 2005-11-29 22:13 ` Brian King 1 sibling, 2 replies; 38+ messages in thread From: Douglas Gilbert @ 2005-11-24 0:53 UTC (permalink / raw) To: brking Cc: Luben Tuikov, Jeff Garzik, Bartlomiej Zolnierkiewicz, linux-ide, linux-scsi, t.schorpp Brian King wrote: > Luben Tuikov wrote: > >>Would it be a good idea to abstract most of this in >>say something like >> >> struct satl_device_struct { >> -- data... ; >> >> /* The registering entity calls this for SATL to translate >> to an ATA task(s) and execute. Filled in by the SATL Layer. */ >> int (*execute_scsi_task)(struct satl_device_struct *, struct scsi_cmnd *); >> >> /* SATL layer calls this to send an ata_task to the device. >> Filled in by the registering entity. */ >> int (*execute_ata_task)(struct satl_device_struct *, struct ata_task *); >> >> -- recovery methods common to SATA-over-anything; filled in by registering >> \ entity >> }; >> >>(ata task to be properly constructed: FIS, sg lists, etc.) >> >>Then libata-scsi would only have to export two (2) functions: >> >>int satl_register_device(struct satl_device_struct *); >>void satl_unregister_device(struct satl_device_struct *); >> >>EXPORT_SYMBOL_GPL(satl_register_device); >>EXPORT_SYMBOL_GPL(satl_unregister_device); > > > Where would you be calling satl_register_device in your SAS class? > > It looks like this would force libata to be the one to attach the ULD, > which would also force it to create a separate scsi_host for each > device, which is something I wanted to avoid. I think you really need a > libata API that the LLDD can call from its queuecommand function > to translate and send a command, which then calls back into the LLDD > to send the FIS to the hardware. This allows for all SAS/SATA devices > under the same HBA to show up under the same scsi_host. Brian, I don't think a SATL is that easy. One SCSI command can translate into zero or more ATA commands. If it translates to multiple commands, then there is the possibility of an error prior to the last in the sequence of ATA commands (how to report; rollback needed ?). The SATL needs to hold state and needs a service thread if it is to support the IMMED bit on some commands (e.g. START STOP UNIT). libata still has a ways to go to catch up to SAT rev 7 but has made some good progress lately with the addition of the ATA pass through commands (lk 2.6.15-rc1 and onward). smartmontools (just prior to 5.34) now works with '-d ata' on libata-connected SATA disks. The '-d ata' ** overrides the guess of a SCSI disk based on the device node (e.g. /dev/sda) and uses the HDIO_DRIVE_CMD and HDIO_DRIVE_TASK ioctls. The absence of support for the HDIO_DRIVE_TASKFILE ioctl means that "selective" self-test can't be done. I'm not sure if moving smartmontools to the ATA PASS THROUGH SCSI commands will win back the "selective" self-test capability. Anyway, going to those ATA PASS THROUGH SCSI commands seems the correct way to go for smartmontools. ** smartmontools has some magic in the device detection area for 3ware controllers, which amounts to a proprietary ATA command pass through (plus some device addressing). Doug Gilbert ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 1/2] libata: Remove dependence on host_set->dev for SAS 2005-11-24 0:53 ` Douglas Gilbert @ 2005-11-24 1:07 ` Jeff Garzik 2005-11-24 8:12 ` Bartlomiej Zolnierkiewicz 2005-11-29 22:13 ` Brian King 1 sibling, 1 reply; 38+ messages in thread From: Jeff Garzik @ 2005-11-24 1:07 UTC (permalink / raw) To: dougg Cc: brking, Luben Tuikov, Bartlomiej Zolnierkiewicz, linux-ide, linux-scsi, t.schorpp Douglas Gilbert wrote: > I don't think a SATL is that easy. One SCSI command can > translate into zero or more ATA commands. If it translates > to multiple commands, then there is the possibility of an > error prior to the last in the sequence of ATA commands > (how to report; rollback needed ?). The SATL needs to hold > state and needs a service thread if it is to support the > IMMED bit on some commands (e.g. START STOP UNIT). It needs a conceptual service thread, not necessarily an explicit one. With REQUEST SENSE, I've demonstrated how to report errors with each step in the sequence. With demo patches I've posted, I've demonstrated (using qc->private_data) how to hold state. > libata still has a ways to go to catch up to SAT rev 7 > but has made some good progress lately with the addition > of the ATA pass through commands (lk 2.6.15-rc1 and onward). > smartmontools (just prior to 5.34) now works with '-d ata' > on libata-connected SATA disks. The '-d ata' ** overrides > the guess of a SCSI disk based on the device node (e.g. > /dev/sda) and uses the HDIO_DRIVE_CMD and HDIO_DRIVE_TASK > ioctls. The absence of support for the HDIO_DRIVE_TASKFILE > ioctl means that "selective" self-test can't be done. > I'm not sure if moving smartmontools to the ATA PASS THROUGH > SCSI commands will win back the "selective" self-test > capability. Anyway, going to those ATA PASS THROUGH SCSI ATA passthru can do anything the legacy IDE ioctls can do (and more). Jeff ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 1/2] libata: Remove dependence on host_set->dev for SAS 2005-11-24 1:07 ` Jeff Garzik @ 2005-11-24 8:12 ` Bartlomiej Zolnierkiewicz 2005-12-02 2:05 ` Jeff Garzik 0 siblings, 1 reply; 38+ messages in thread From: Bartlomiej Zolnierkiewicz @ 2005-11-24 8:12 UTC (permalink / raw) To: Jeff Garzik; +Cc: dougg, brking, Luben Tuikov, linux-ide, linux-scsi, t.schorpp On 11/24/05, Jeff Garzik <jgarzik@pobox.com> wrote: > Douglas Gilbert wrote: > > I don't think a SATL is that easy. One SCSI command can > > translate into zero or more ATA commands. If it translates > > to multiple commands, then there is the possibility of an > > error prior to the last in the sequence of ATA commands > > (how to report; rollback needed ?). The SATL needs to hold > > state and needs a service thread if it is to support the > > IMMED bit on some commands (e.g. START STOP UNIT). > > It needs a conceptual service thread, not necessarily an explicit one. > > With REQUEST SENSE, I've demonstrated how to report errors with each > step in the sequence. With demo patches I've posted, I've demonstrated > (using qc->private_data) how to hold state. > > > > libata still has a ways to go to catch up to SAT rev 7 > > but has made some good progress lately with the addition > > of the ATA pass through commands (lk 2.6.15-rc1 and onward). > > smartmontools (just prior to 5.34) now works with '-d ata' > > on libata-connected SATA disks. The '-d ata' ** overrides > > the guess of a SCSI disk based on the device node (e.g. > > /dev/sda) and uses the HDIO_DRIVE_CMD and HDIO_DRIVE_TASK > > ioctls. The absence of support for the HDIO_DRIVE_TASKFILE > > ioctl means that "selective" self-test can't be done. > > I'm not sure if moving smartmontools to the ATA PASS THROUGH > > SCSI commands will win back the "selective" self-test > > capability. Anyway, going to those ATA PASS THROUGH SCSI > > ATA passthru can do anything the legacy IDE ioctls can do (and more). [ definitely ATA passthru is the way to go but... ] discrete taskfiles? multi-PIO? setting transfer speed? and if you are talking about IDE ioctls there is (unfortunately) much more than HDIO_DRIVE_[CMD,TASK,TASKFILE] >From extra things that it can do I see support for LBA48 transfers, is there anything more? Bartlomiej ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 1/2] libata: Remove dependence on host_set->dev for SAS 2005-11-24 8:12 ` Bartlomiej Zolnierkiewicz @ 2005-12-02 2:05 ` Jeff Garzik 2005-12-02 8:07 ` Bartlomiej Zolnierkiewicz 0 siblings, 1 reply; 38+ messages in thread From: Jeff Garzik @ 2005-12-02 2:05 UTC (permalink / raw) To: Bartlomiej Zolnierkiewicz Cc: dougg, brking, Luben Tuikov, linux-ide, linux-scsi, t.schorpp Bartlomiej Zolnierkiewicz wrote: > On 11/24/05, Jeff Garzik <jgarzik@pobox.com> wrote: > >>Douglas Gilbert wrote: >> >>>I don't think a SATL is that easy. One SCSI command can >>>translate into zero or more ATA commands. If it translates >>>to multiple commands, then there is the possibility of an >>>error prior to the last in the sequence of ATA commands >>>(how to report; rollback needed ?). The SATL needs to hold >>>state and needs a service thread if it is to support the >>>IMMED bit on some commands (e.g. START STOP UNIT). >> >>It needs a conceptual service thread, not necessarily an explicit one. >> >>With REQUEST SENSE, I've demonstrated how to report errors with each >>step in the sequence. With demo patches I've posted, I've demonstrated >>(using qc->private_data) how to hold state. >> >> >> >>>libata still has a ways to go to catch up to SAT rev 7 >>>but has made some good progress lately with the addition >>>of the ATA pass through commands (lk 2.6.15-rc1 and onward). >>>smartmontools (just prior to 5.34) now works with '-d ata' >>>on libata-connected SATA disks. The '-d ata' ** overrides >>>the guess of a SCSI disk based on the device node (e.g. >>>/dev/sda) and uses the HDIO_DRIVE_CMD and HDIO_DRIVE_TASK >>>ioctls. The absence of support for the HDIO_DRIVE_TASKFILE >>>ioctl means that "selective" self-test can't be done. >>>I'm not sure if moving smartmontools to the ATA PASS THROUGH >>>SCSI commands will win back the "selective" self-test >>>capability. Anyway, going to those ATA PASS THROUGH SCSI >> >>ATA passthru can do anything the legacy IDE ioctls can do (and more). > > > [ definitely ATA passthru is the way to go but... ] > > discrete taskfiles? what is this? > multi-PIO? what is this? multi-sector PIO, such as READ MULTIPLE SECTORS? ATA passthru can do that. > setting transfer speed? That's not a limitation of passthru, but a limitation of the driver. I don't yet see the value... Jeff ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 1/2] libata: Remove dependence on host_set->dev for SAS 2005-12-02 2:05 ` Jeff Garzik @ 2005-12-02 8:07 ` Bartlomiej Zolnierkiewicz 2005-12-02 10:28 ` Douglas Gilbert 0 siblings, 1 reply; 38+ messages in thread From: Bartlomiej Zolnierkiewicz @ 2005-12-02 8:07 UTC (permalink / raw) To: Jeff Garzik; +Cc: dougg, brking, Luben Tuikov, linux-ide, linux-scsi, t.schorpp On 12/2/05, Jeff Garzik <jgarzik@pobox.com> wrote: > Bartlomiej Zolnierkiewicz wrote: > > On 11/24/05, Jeff Garzik <jgarzik@pobox.com> wrote: > > > >>Douglas Gilbert wrote: > >> > >>>I don't think a SATL is that easy. One SCSI command can > >>>translate into zero or more ATA commands. If it translates > >>>to multiple commands, then there is the possibility of an > >>>error prior to the last in the sequence of ATA commands > >>>(how to report; rollback needed ?). The SATL needs to hold > >>>state and needs a service thread if it is to support the > >>>IMMED bit on some commands (e.g. START STOP UNIT). > >> > >>It needs a conceptual service thread, not necessarily an explicit one. > >> > >>With REQUEST SENSE, I've demonstrated how to report errors with each > >>step in the sequence. With demo patches I've posted, I've demonstrated > >>(using qc->private_data) how to hold state. > >> > >> > >> > >>>libata still has a ways to go to catch up to SAT rev 7 > >>>but has made some good progress lately with the addition > >>>of the ATA pass through commands (lk 2.6.15-rc1 and onward). > >>>smartmontools (just prior to 5.34) now works with '-d ata' > >>>on libata-connected SATA disks. The '-d ata' ** overrides > >>>the guess of a SCSI disk based on the device node (e.g. > >>>/dev/sda) and uses the HDIO_DRIVE_CMD and HDIO_DRIVE_TASK > >>>ioctls. The absence of support for the HDIO_DRIVE_TASKFILE > >>>ioctl means that "selective" self-test can't be done. > >>>I'm not sure if moving smartmontools to the ATA PASS THROUGH > >>>SCSI commands will win back the "selective" self-test > >>>capability. Anyway, going to those ATA PASS THROUGH SCSI > >> > >>ATA passthru can do anything the legacy IDE ioctls can do (and more). > > > > > > [ definitely ATA passthru is the way to go but... ] > > > > discrete taskfiles? > > what is this? flagged taskfiles yes, this is a low priority but your statement is oversimplification and I don't even mentioned other "IDE ioctl", so: ATA passthru can do anything _important_ that legacy IDE ioctls can do (write cache [dis,en]abling?) > > multi-PIO? > > what is this? multi-sector PIO, such as READ MULTIPLE SECTORS? ATA short for multi sector-sector PIO > passthru can do that. not in the mainline, I've just checked libata-dev and it is OK > > setting transfer speed? > > That's not a limitation of passthru, but a limitation of the driver. I > don't yet see the value... Same for me... Bartlomiej ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 1/2] libata: Remove dependence on host_set->dev for SAS 2005-12-02 8:07 ` Bartlomiej Zolnierkiewicz @ 2005-12-02 10:28 ` Douglas Gilbert 2005-12-02 10:48 ` Jeff Garzik 0 siblings, 1 reply; 38+ messages in thread From: Douglas Gilbert @ 2005-12-02 10:28 UTC (permalink / raw) To: Bartlomiej Zolnierkiewicz Cc: Jeff Garzik, brking, Luben Tuikov, linux-ide, linux-scsi, t.schorpp Bartlomiej Zolnierkiewicz wrote: > On 12/2/05, Jeff Garzik <jgarzik@pobox.com> wrote: > >>Bartlomiej Zolnierkiewicz wrote: >> >>>On 11/24/05, Jeff Garzik <jgarzik@pobox.com> wrote: >>> >>> >>>>Douglas Gilbert wrote: >>>> >>>> >>>>>I don't think a SATL is that easy. One SCSI command can >>>>>translate into zero or more ATA commands. If it translates >>>>>to multiple commands, then there is the possibility of an >>>>>error prior to the last in the sequence of ATA commands >>>>>(how to report; rollback needed ?). The SATL needs to hold >>>>>state and needs a service thread if it is to support the >>>>>IMMED bit on some commands (e.g. START STOP UNIT). >>>> >>>>It needs a conceptual service thread, not necessarily an explicit one. >>>> >>>>With REQUEST SENSE, I've demonstrated how to report errors with each >>>>step in the sequence. With demo patches I've posted, I've demonstrated >>>>(using qc->private_data) how to hold state. >>>> >>>> >>>> >>>> >>>>>libata still has a ways to go to catch up to SAT rev 7 >>>>>but has made some good progress lately with the addition >>>>>of the ATA pass through commands (lk 2.6.15-rc1 and onward). >>>>>smartmontools (just prior to 5.34) now works with '-d ata' >>>>>on libata-connected SATA disks. The '-d ata' ** overrides >>>>>the guess of a SCSI disk based on the device node (e.g. >>>>>/dev/sda) and uses the HDIO_DRIVE_CMD and HDIO_DRIVE_TASK >>>>>ioctls. The absence of support for the HDIO_DRIVE_TASKFILE >>>>>ioctl means that "selective" self-test can't be done. >>>>>I'm not sure if moving smartmontools to the ATA PASS THROUGH >>>>>SCSI commands will win back the "selective" self-test >>>>>capability. Anyway, going to those ATA PASS THROUGH SCSI >>>> >>>>ATA passthru can do anything the legacy IDE ioctls can do (and more). >>> >>> >>>[ definitely ATA passthru is the way to go but... ] >>> >>>discrete taskfiles? >> >>what is this? > > > flagged taskfiles > > yes, this is a low priority but your statement is oversimplification > and I don't even mentioned other "IDE ioctl", so: > > ATA passthru can do anything _important_ that legacy IDE ioctls > can do (write cache [dis,en]abling?) > > >>>multi-PIO? >> >>what is this? multi-sector PIO, such as READ MULTIPLE SECTORS? ATA > > > short for multi sector-sector PIO > > >>passthru can do that. > > > not in the mainline, I've just checked libata-dev and it is OK > > >>>setting transfer speed? >> >>That's not a limitation of passthru, but a limitation of the driver. I >>don't yet see the value... > > > Same for me... I noticed that the protocol field in the ATA_12 and ATA_16 pass through commands included hard reset, SRST and device reset. Would it be useful to implement these? Doug Gilbert ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 1/2] libata: Remove dependence on host_set->dev for SAS 2005-12-02 10:28 ` Douglas Gilbert @ 2005-12-02 10:48 ` Jeff Garzik 0 siblings, 0 replies; 38+ messages in thread From: Jeff Garzik @ 2005-12-02 10:48 UTC (permalink / raw) To: dougg Cc: Bartlomiej Zolnierkiewicz, brking, Luben Tuikov, linux-ide, linux-scsi, t.schorpp Douglas Gilbert wrote: > I noticed that the protocol field in the ATA_12 and > ATA_16 pass through commands included hard reset, > SRST and device reset. Would it be useful to implement > these? Yes, at least SRST should be implemented. Jeff ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 1/2] libata: Remove dependence on host_set->dev for SAS 2005-11-24 0:53 ` Douglas Gilbert 2005-11-24 1:07 ` Jeff Garzik @ 2005-11-29 22:13 ` Brian King 1 sibling, 0 replies; 38+ messages in thread From: Brian King @ 2005-11-29 22:13 UTC (permalink / raw) To: dougg Cc: Luben Tuikov, Jeff Garzik, Bartlomiej Zolnierkiewicz, linux-ide, linux-scsi, t.schorpp Douglas Gilbert wrote: > Brian King wrote: >> I think you really need a >> libata API that the LLDD can call from its queuecommand function >> to translate and send a command, which then calls back into the LLDD >> to send the FIS to the hardware. This allows for all SAS/SATA devices >> under the same HBA to show up under the same scsi_host. > > Brian, > I don't think a SATL is that easy. That is essentially the API that libata has today. Existing SATA drivers have a queuecommand routine that invokes a libata API to send a taskfile to the hardware. > One SCSI command can > translate into zero or more ATA commands. If it translates > to multiple commands, then there is the possibility of an > error prior to the last in the sequence of ATA commands > (how to report; rollback needed ?). The SATL needs to hold > state and needs a service thread if it is to support the > IMMED bit on some commands (e.g. START STOP UNIT). I guess I don't see these problems as unique to SATA drives attached via a SAS adapter, which is what my patchset is trying to implement, but rather general libata issues. Reading Jeff's response, it sounds like the service thread issue is already being worked in another manner. Brian -- Brian King eServer Storage I/O IBM Linux Technology Center ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 2/2] libata: Add support for SATA attachment to SAS adapters 2005-10-24 22:17 ` [PATCH " Brian King 2005-10-24 22:19 ` [PATCH 1/2] libata: Remove dependence on host_set->dev for SAS Brian King @ 2005-10-24 22:20 ` Brian King 2005-10-25 17:58 ` Jeff Garzik 2005-10-25 12:59 ` [PATCH 0/2] libata: support SATA devices on SAS HBAs Luben Tuikov 2 siblings, 1 reply; 38+ messages in thread From: Brian King @ 2005-10-24 22:20 UTC (permalink / raw) To: brking; +Cc: Jeff Garzik, Bartlomiej Zolnierkiewicz, linux-ide, linux-scsi [-- Attachment #1: Type: text/plain, Size: 0 bytes --] [-- Attachment #2: libata_sas.patch --] [-- Type: text/plain, Size: 11795 bytes --] The following patch enhances libata to allow SAS device drivers to utilize libata to talk to SATA devices. It introduces some new APIs which allow libata to be used without allocating a virtual scsi host. Since the last time I posted this code, I have removed all dependence on the ata_host_set struct. New APIs: ata_sas_port_alloc - Allocate an ata_port ata_sas_port_init - Initialize an ata_port (probe device, etc) ata_sas_port_destroy - Free an ata_port allocated by ata_sas_port_alloc ata_sas_slave_configure - configure scsi device ata_sas_queuecmd - queue a scsi command, similar to ata_scsi_queuecomand These new APIs can be used either directly by a SAS LLDD or could be used by the SAS transport class. Possible usage for a SAS LLDD would be: scsi_scan_host slave_alloc ata_sas_port_alloc ata_sas_port_init slave_configure ata_sas_slave_configure Commands received by the LLDD for SATA devices would call ata_sas_queuecmd. Device teardown would occur with: slave_destroy ata_sas_port_destroy Signed-off-by: Brian King <brking@us.ibm.com> --- linux-2.6-bjking1/drivers/scsi/libata-core.c | 32 ++-- linux-2.6-bjking1/drivers/scsi/libata-scsi.c | 191 +++++++++++++++++++++++---- linux-2.6-bjking1/drivers/scsi/libata.h | 7 linux-2.6-bjking1/include/linux/libata.h | 7 4 files changed, 199 insertions(+), 38 deletions(-) diff -puN drivers/scsi/libata-scsi.c~libata_sas drivers/scsi/libata-scsi.c --- linux-2.6/drivers/scsi/libata-scsi.c~libata_sas 2005-10-24 15:08:27.000000000 -0500 +++ linux-2.6-bjking1/drivers/scsi/libata-scsi.c 2005-10-24 16:53:48.000000000 -0500 @@ -325,6 +325,30 @@ void ata_to_sense_error(struct ata_queue } } +static void ata_scsi_sdev_config(struct scsi_device *sdev) +{ + sdev->use_10_for_rw = 1; + sdev->use_10_for_ms = 1; +} + +static void ata_scsi_dev_config(struct scsi_device *sdev, + struct ata_device *dev) +{ + /* TODO: 1024 is an arbitrary number, not the + * hardware maximum. This should be increased to + * 65534 when Jens Axboe's patch for dynamically + * determining max_sectors is merged. + */ + if ((dev->flags & ATA_DFLAG_LBA48) && + ((dev->flags & ATA_DFLAG_LOCK_SECTORS) == 0)) { + /* + * do not overwrite sdev->host->max_sectors, since + * other drives on this host may not support LBA48 + */ + blk_queue_max_sectors(sdev->request_queue, 2048); + } +} + /** * ata_scsi_slave_config - Set SCSI device attributes * @sdev: SCSI device to examine @@ -339,9 +363,7 @@ void ata_to_sense_error(struct ata_queue int ata_scsi_slave_config(struct scsi_device *sdev) { - sdev->use_10_for_rw = 1; - sdev->use_10_for_ms = 1; - + ata_scsi_sdev_config(sdev); blk_queue_max_phys_segments(sdev->request_queue, LIBATA_MAX_PRD); if (sdev->id < ATA_MAX_DEVICES) { @@ -351,19 +373,7 @@ int ata_scsi_slave_config(struct scsi_de ap = (struct ata_port *) &sdev->host->hostdata[0]; dev = &ap->device[sdev->id]; - /* TODO: 1024 is an arbitrary number, not the - * hardware maximum. This should be increased to - * 65534 when Jens Axboe's patch for dynamically - * determining max_sectors is merged. - */ - if ((dev->flags & ATA_DFLAG_LBA48) && - ((dev->flags & ATA_DFLAG_LOCK_SECTORS) == 0)) { - /* - * do not overwrite sdev->host->max_sectors, since - * other drives on this host may not support LBA48 - */ - blk_queue_max_sectors(sdev->request_queue, 2048); - } + ata_scsi_dev_config(sdev, dev); } return 0; /* scsi layer doesn't check return value, sigh */ @@ -1541,6 +1551,21 @@ static inline void ata_scsi_dump_cdb(str #endif } +static void __ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), + struct ata_port *ap, struct ata_device *dev) +{ + if (dev->class == ATA_DEV_ATA) { + ata_xlat_func_t xlat_func = ata_get_xlat_func(dev, + cmd->cmnd[0]); + + if (xlat_func) + ata_scsi_translate(ap, dev, cmd, done, xlat_func); + else + ata_scsi_simulate(dev->id, cmd, done); + } else + ata_scsi_translate(ap, dev, cmd, done, atapi_xlat); +} + /** * ata_scsi_queuecmd - Issue SCSI cdb to libata-managed device * @cmd: SCSI command to be sent @@ -1577,16 +1602,7 @@ int ata_scsi_queuecmd(struct scsi_cmnd * goto out_unlock; } - if (dev->class == ATA_DEV_ATA) { - ata_xlat_func_t xlat_func = ata_get_xlat_func(dev, - cmd->cmnd[0]); - - if (xlat_func) - ata_scsi_translate(ap, dev, cmd, done, xlat_func); - else - ata_scsi_simulate(dev->id, cmd, done); - } else - ata_scsi_translate(ap, dev, cmd, done, atapi_xlat); + __ata_scsi_queuecmd(cmd, done, ap, dev); out_unlock: return 0; @@ -1678,3 +1694,126 @@ void ata_scsi_simulate(u16 *id, } } +/** + * ata_sas_port_alloc - Allocate port for a SAS attached SATA device + * @pdev: PCI device that the scsi device is attached to + * @port_info: Information from low-level host driver + * + * LOCKING: + * PCI/etc. bus probe sem. + * + * RETURNS: + * ata_port pointer on success / NULL on failure. + */ + +struct ata_port *ata_sas_port_alloc(struct pci_dev *pdev, + struct ata_port_info *port_info) +{ + struct ata_port *ap = kzalloc(sizeof(*ap), GFP_KERNEL); + + if (!ap) + return NULL; + + ap->dev = &pdev->dev; + ap->ops = port_info->port_ops; + ap->flags = port_info->host_flags; + ap->pio_mask = port_info->pio_mask; + ap->mwdma_mask = port_info->mwdma_mask; + ap->udma_mask = port_info->udma_mask; + ap->cbl = ATA_CBL_SATA; + ap->active_tag = ATA_TAG_POISON; + ap->last_ctl = 0xFF; + return ap; +} +EXPORT_SYMBOL_GPL(ata_sas_port_alloc); + +static void ata_sas_port_free(struct ata_port *ap) +{ + kfree(ap); +} + +/** + * ata_sas_port_init - Initialize a SATA device + * @ap: SATA port to initialize + * + * LOCKING: + * PCI/etc. bus probe sem. + * + * RETURNS: + * Zero on success, non-zero on error. + */ + +int ata_sas_port_init(struct ata_port *ap) +{ + int rc = ap->ops->port_start(ap); + + if (!rc) + rc = ata_bus_probe(ap); + + return rc; +} +EXPORT_SYMBOL_GPL(ata_sas_port_init); + +/** + * ata_sas_port_destroy - Destroy a SATA port allocated by ata_sas_port_alloc + * @ap: SATA port to destroy + * + */ + +void ata_sas_port_destroy(struct ata_port *ap) +{ + if (ap) { + ap->ops->port_stop(ap); + ata_sas_port_free(ap); + } +} +EXPORT_SYMBOL_GPL(ata_sas_port_destroy); + +/** + * ata_sas_slave_configure - Default slave_config routine for libata devices + * @sdev: SCSI device to configure + * @ap: ATA port to which SCSI device is attached + * + * RETURNS: + * Zero. + */ + +int ata_sas_slave_configure(struct scsi_device *sdev, struct ata_port *ap) +{ + ata_scsi_sdev_config(sdev); + ata_scsi_dev_config(sdev, ap->device); + if (ata_dev_knobble(ap)) + blk_queue_max_sectors(sdev->request_queue, ATA_MAX_SECTORS); + return 0; +} +EXPORT_SYMBOL_GPL(ata_sas_slave_configure); + +/** + * ata_sas_queuecmd - Issue SCSI cdb to libata-managed device + * @cmd: SCSI command to be sent + * @done: Completion function, called when command is complete + * @ap: ATA port to which the command is being sent + * + * RETURNS: + * Zero. + */ + +int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), + struct ata_port *ap) +{ + if (unlikely(!ata_dev_present(ap->device))) { + cmd->result = (DID_BAD_TARGET << 16); + done(cmd); + return 0; + } + + if (cmd->cmd_len > ap->cdb_len) { + cmd->result = (DID_ABORT << 16); + done(cmd); + return 0; + } + + __ata_scsi_queuecmd(cmd, done, ap, ap->device); + return 0; +} +EXPORT_SYMBOL_GPL(ata_sas_queuecmd); diff -puN drivers/scsi/libata-core.c~libata_sas drivers/scsi/libata-core.c --- linux-2.6/drivers/scsi/libata-core.c~libata_sas 2005-10-24 15:08:27.000000000 -0500 +++ linux-2.6-bjking1/drivers/scsi/libata-core.c 2005-10-24 15:08:27.000000000 -0500 @@ -1106,6 +1106,21 @@ static inline void ata_dump_id(struct at dev->id[93]); } +static void ata_set_cdb_len(struct ata_port *ap, unsigned int cdb_len) +{ + ap->cdb_len = cdb_len; + if (ap->host) + ap->host->max_cmd_len = cdb_len; +} + +static void ata_set_max_sectors(struct ata_port *ap, unsigned int max_sectors) +{ + if (ap->host) { + ap->host->max_sectors = ATA_MAX_SECTORS; + ap->host->hostt->max_sectors = ATA_MAX_SECTORS; + } +} + /** * ata_dev_identify - obtain IDENTIFY x DEVICE page * @ap: port on which device we wish to probe resides @@ -1266,7 +1281,7 @@ retry: dev->n_sectors = ata_id_u32(dev->id, 60); } - ap->host->max_cmd_len = 16; + ata_set_cdb_len(ap, 16); /* print device info to dmesg */ printk(KERN_INFO "ata%u: dev %u ATA, max %s, %Lu sectors:%s\n", @@ -1286,8 +1301,8 @@ retry: printk(KERN_WARNING "ata%u: unsupported CDB len\n", ap->id); goto err_out_nosup; } - ap->cdb_len = (unsigned int) rc; - ap->host->max_cmd_len = (unsigned char) ap->cdb_len; + + ata_set_cdb_len(ap, rc); /* print device info to dmesg */ printk(KERN_INFO "ata%u: dev %u ATAPI, max %s\n", @@ -1306,12 +1321,6 @@ err_out: DPRINTK("EXIT, err\n"); } - -static inline u8 ata_dev_knobble(struct ata_port *ap) -{ - return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(ap->device->id))); -} - /** * ata_dev_config - Run device specific handlers and check for * SATA->PATA bridges @@ -1328,8 +1337,7 @@ void ata_dev_config(struct ata_port *ap, printk(KERN_INFO "ata%u(%u): applying bridge limits\n", ap->id, ap->device->devno); ap->udma_mask &= ATA_UDMA5; - ap->host->max_sectors = ATA_MAX_SECTORS; - ap->host->hostt->max_sectors = ATA_MAX_SECTORS; + ata_set_max_sectors(ap, ATA_MAX_SECTORS); ap->device->flags |= ATA_DFLAG_LOCK_SECTORS; } @@ -1352,7 +1360,7 @@ void ata_dev_config(struct ata_port *ap, * Zero on success, non-zero on error. */ -static int ata_bus_probe(struct ata_port *ap) +int ata_bus_probe(struct ata_port *ap) { unsigned int i, found = 0; diff -puN drivers/scsi/libata.h~libata_sas drivers/scsi/libata.h --- linux-2.6/drivers/scsi/libata.h~libata_sas 2005-10-24 15:08:27.000000000 -0500 +++ linux-2.6-bjking1/drivers/scsi/libata.h 2005-10-24 15:08:27.000000000 -0500 @@ -79,6 +79,8 @@ extern void ata_scsi_badcmd(struct scsi_ extern void ata_scsi_rbuf_fill(struct ata_scsi_args *args, unsigned int (*actor) (struct ata_scsi_args *args, u8 *rbuf, unsigned int buflen)); +extern int ata_bus_probe(struct ata_port *ap); +extern int ata_sas_port_init(struct ata_port *ap); static inline void ata_bad_scsiop(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { @@ -90,4 +92,9 @@ static inline void ata_bad_cdb(struct sc ata_scsi_badcmd(cmd, done, 0x24, 0x00); } +static inline u8 ata_dev_knobble(struct ata_port *ap) +{ + return ((ap->cbl == ATA_CBL_SATA) && (!ata_id_is_sata(ap->device->id))); +} + #endif /* __LIBATA_H__ */ diff -puN include/linux/libata.h~libata_sas include/linux/libata.h --- linux-2.6/include/linux/libata.h~libata_sas 2005-10-24 15:08:27.000000000 -0500 +++ linux-2.6-bjking1/include/linux/libata.h 2005-10-24 15:08:27.000000000 -0500 @@ -401,6 +401,13 @@ extern int ata_scsi_ioctl(struct scsi_de extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); extern int ata_scsi_error(struct Scsi_Host *host); extern int ata_scsi_release(struct Scsi_Host *host); +extern void ata_sas_port_destroy(struct ata_port *ap); +extern struct ata_port *ata_sas_port_alloc(struct pci_dev *pdev, + struct ata_port_info *port_info); +extern int ata_sas_port_init(struct ata_port *ap); +extern int ata_sas_slave_configure(struct scsi_device *sdev, struct ata_port *ap); +extern int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), + struct ata_port *ap); extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); /* * Default driver ops implementations _ ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 2/2] libata: Add support for SATA attachment to SAS adapters 2005-10-24 22:20 ` [PATCH 2/2] libata: Add support for SATA attachment to SAS adapters Brian King @ 2005-10-25 17:58 ` Jeff Garzik 0 siblings, 0 replies; 38+ messages in thread From: Jeff Garzik @ 2005-10-25 17:58 UTC (permalink / raw) To: brking; +Cc: Bartlomiej Zolnierkiewicz, linux-ide, linux-scsi Brian King wrote: > +/** > + * ata_sas_port_alloc - Allocate port for a SAS attached SATA device > + * @pdev: PCI device that the scsi device is attached to > + * @port_info: Information from low-level host driver > + * > + * LOCKING: > + * PCI/etc. bus probe sem. > + * > + * RETURNS: > + * ata_port pointer on success / NULL on failure. > + */ > + > +struct ata_port *ata_sas_port_alloc(struct pci_dev *pdev, > + struct ata_port_info *port_info) > +{ > + struct ata_port *ap = kzalloc(sizeof(*ap), GFP_KERNEL); > + > + if (!ap) > + return NULL; > + > + ap->dev = &pdev->dev; > + ap->ops = port_info->port_ops; > + ap->flags = port_info->host_flags; > + ap->pio_mask = port_info->pio_mask; > + ap->mwdma_mask = port_info->mwdma_mask; > + ap->udma_mask = port_info->udma_mask; > + ap->cbl = ATA_CBL_SATA; > + ap->active_tag = ATA_TAG_POISON; > + ap->last_ctl = 0xFF; > + return ap; > +} > +EXPORT_SYMBOL_GPL(ata_sas_port_alloc); > + > +static void ata_sas_port_free(struct ata_port *ap) > +{ > + kfree(ap); > +} > + > +/** > + * ata_sas_port_init - Initialize a SATA device > + * @ap: SATA port to initialize > + * > + * LOCKING: > + * PCI/etc. bus probe sem. > + * > + * RETURNS: > + * Zero on success, non-zero on error. > + */ > + > +int ata_sas_port_init(struct ata_port *ap) > +{ > + int rc = ap->ops->port_start(ap); > + > + if (!rc) > + rc = ata_bus_probe(ap); > + > + return rc; > +} > +EXPORT_SYMBOL_GPL(ata_sas_port_init); > + > +/** > + * ata_sas_port_destroy - Destroy a SATA port allocated by ata_sas_port_alloc > + * @ap: SATA port to destroy > + * > + */ > + > +void ata_sas_port_destroy(struct ata_port *ap) > +{ > + if (ap) { > + ap->ops->port_stop(ap); > + ata_sas_port_free(ap); > + } > +} > +EXPORT_SYMBOL_GPL(ata_sas_port_destroy); > + > +/** > + * ata_sas_slave_configure - Default slave_config routine for libata devices > + * @sdev: SCSI device to configure > + * @ap: ATA port to which SCSI device is attached > + * > + * RETURNS: > + * Zero. > + */ > + > +int ata_sas_slave_configure(struct scsi_device *sdev, struct ata_port *ap) > +{ > + ata_scsi_sdev_config(sdev); > + ata_scsi_dev_config(sdev, ap->device); > + if (ata_dev_knobble(ap)) > + blk_queue_max_sectors(sdev->request_queue, ATA_MAX_SECTORS); > + return 0; > +} > +EXPORT_SYMBOL_GPL(ata_sas_slave_configure); > + > +/** > + * ata_sas_queuecmd - Issue SCSI cdb to libata-managed device > + * @cmd: SCSI command to be sent > + * @done: Completion function, called when command is complete > + * @ap: ATA port to which the command is being sent > + * > + * RETURNS: > + * Zero. > + */ > + > +int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), > + struct ata_port *ap) > +{ > + if (unlikely(!ata_dev_present(ap->device))) { > + cmd->result = (DID_BAD_TARGET << 16); > + done(cmd); > + return 0; > + } > + > + if (cmd->cmd_len > ap->cdb_len) { > + cmd->result = (DID_ABORT << 16); > + done(cmd); > + return 0; > + } > + > + __ata_scsi_queuecmd(cmd, done, ap, ap->device); > + return 0; > +} I'm still thinking about these functions, so it would be nice to split them up into a third patch. That would allow me to apply the other cleanups in this patch. Jeff ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 0/2] libata: support SATA devices on SAS HBAs 2005-10-24 22:17 ` [PATCH " Brian King 2005-10-24 22:19 ` [PATCH 1/2] libata: Remove dependence on host_set->dev for SAS Brian King 2005-10-24 22:20 ` [PATCH 2/2] libata: Add support for SATA attachment to SAS adapters Brian King @ 2005-10-25 12:59 ` Luben Tuikov 2005-10-25 13:39 ` Brian King 2 siblings, 1 reply; 38+ messages in thread From: Luben Tuikov @ 2005-10-25 12:59 UTC (permalink / raw) To: brking; +Cc: Jeff Garzik, Bartlomiej Zolnierkiewicz, linux-ide, linux-scsi On 10/24/05 18:17, Brian King wrote: > The following patches enhance libata to allow SAS device drivers > to utilize libata to talk to SATA devices. It introduces some > new APIs which allow libata to be used without allocating a > virtual scsi host. In the context of SAS, a struct ata_port > is not a physical port, but rather becomes a virtual construct. > > Since my last post, I have removed the dependence on the host_set > struct. The following two patches depend on the qc_transport patch: > > http://marc.theaimsgroup.com/?l=linux-ide&m=112845939215286&w=2 > > The API is the same as the last time I posted it to linux-ide, > but here is the description again: > > New APIs: > > ata_sas_port_alloc - Allocate an ata_port > ata_sas_port_init - Initialize an ata_port (probe device, etc) > ata_sas_port_destroy - Free an ata_port allocated by ata_sas_port_alloc > ata_sas_slave_configure - configure scsi device > ata_sas_queuecmd - queue a scsi command, similar to ata_scsi_queuecomand > > These new APIs can be used either directly by a SAS LLDD or could be used > by the SAS transport class. > > Possible usage for a SAS LLDD would be: > > scsi_scan_host > slave_alloc > ata_sas_port_alloc > ata_sas_port_init > slave_configure > ata_sas_slave_configure > > Commands received by the LLDD for SATA devices would call ata_sas_queuecmd. > > Device teardown would occur with: > > slave_destroy > ata_sas_port_destroy Hey Brian, That's admireable effort. Is there a git tree I can pull from which has these patches? (I don't mind using the patches themselves as well.) I'll take a look indepth and comment further. Thanks, Luben -- http://linux.adaptec.com/sas/ http://www.adaptec.com/sas/ ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 0/2] libata: support SATA devices on SAS HBAs 2005-10-25 12:59 ` [PATCH 0/2] libata: support SATA devices on SAS HBAs Luben Tuikov @ 2005-10-25 13:39 ` Brian King 2005-10-25 13:40 ` Luben Tuikov 0 siblings, 1 reply; 38+ messages in thread From: Brian King @ 2005-10-25 13:39 UTC (permalink / raw) To: Luben Tuikov Cc: Jeff Garzik, Bartlomiej Zolnierkiewicz, linux-ide, linux-scsi Luben Tuikov wrote: > On 10/24/05 18:17, Brian King wrote: > >>The following patches enhance libata to allow SAS device drivers >>to utilize libata to talk to SATA devices. It introduces some >>new APIs which allow libata to be used without allocating a >>virtual scsi host. In the context of SAS, a struct ata_port >>is not a physical port, but rather becomes a virtual construct. >> >>Since my last post, I have removed the dependence on the host_set >>struct. The following two patches depend on the qc_transport patch: >> >>http://marc.theaimsgroup.com/?l=linux-ide&m=112845939215286&w=2 >> >>The API is the same as the last time I posted it to linux-ide, >>but here is the description again: >> >>New APIs: >> >>ata_sas_port_alloc - Allocate an ata_port >>ata_sas_port_init - Initialize an ata_port (probe device, etc) >>ata_sas_port_destroy - Free an ata_port allocated by ata_sas_port_alloc >>ata_sas_slave_configure - configure scsi device >>ata_sas_queuecmd - queue a scsi command, similar to ata_scsi_queuecomand >> >>These new APIs can be used either directly by a SAS LLDD or could be used >>by the SAS transport class. >> >>Possible usage for a SAS LLDD would be: >> >>scsi_scan_host >> slave_alloc >> ata_sas_port_alloc >> ata_sas_port_init >> slave_configure >> ata_sas_slave_configure >> >>Commands received by the LLDD for SATA devices would call ata_sas_queuecmd. >> >>Device teardown would occur with: >> >>slave_destroy >> ata_sas_port_destroy > > > Hey Brian, > > That's admireable effort. Is there a git tree I can pull from which has > these patches? (I don't mind using the patches themselves as well.) > > I'll take a look indepth and comment further. > > Thanks, > Luben Hey Luben, I don't have a git tree setup, just the three patches. Brian -- Brian King eServer Storage I/O IBM Linux Technology Center ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 0/2] libata: support SATA devices on SAS HBAs 2005-10-25 13:39 ` Brian King @ 2005-10-25 13:40 ` Luben Tuikov 2005-10-25 13:53 ` Brian King 0 siblings, 1 reply; 38+ messages in thread From: Luben Tuikov @ 2005-10-25 13:40 UTC (permalink / raw) To: brking; +Cc: Jeff Garzik, Bartlomiej Zolnierkiewicz, linux-ide, linux-scsi On 10/25/05 09:39, Brian King wrote: > Luben Tuikov wrote: > >>On 10/24/05 18:17, Brian King wrote: >> >> >>>The following patches enhance libata to allow SAS device drivers >>>to utilize libata to talk to SATA devices. It introduces some >>>new APIs which allow libata to be used without allocating a >>>virtual scsi host. In the context of SAS, a struct ata_port >>>is not a physical port, but rather becomes a virtual construct. >>> >>>Since my last post, I have removed the dependence on the host_set >>>struct. The following two patches depend on the qc_transport patch: >>> >>>http://marc.theaimsgroup.com/?l=linux-ide&m=112845939215286&w=2 >>> >>>The API is the same as the last time I posted it to linux-ide, >>>but here is the description again: >>> >>>New APIs: >>> >>>ata_sas_port_alloc - Allocate an ata_port >>>ata_sas_port_init - Initialize an ata_port (probe device, etc) >>>ata_sas_port_destroy - Free an ata_port allocated by ata_sas_port_alloc >>>ata_sas_slave_configure - configure scsi device >>>ata_sas_queuecmd - queue a scsi command, similar to ata_scsi_queuecomand >>> >>>These new APIs can be used either directly by a SAS LLDD or could be used >>>by the SAS transport class. >>> >>>Possible usage for a SAS LLDD would be: >>> >>>scsi_scan_host >>> slave_alloc >>> ata_sas_port_alloc >>> ata_sas_port_init >>> slave_configure >>> ata_sas_slave_configure >>> >>>Commands received by the LLDD for SATA devices would call ata_sas_queuecmd. >>> >>>Device teardown would occur with: >>> >>>slave_destroy >>> ata_sas_port_destroy >> >> >>Hey Brian, >> >>That's admireable effort. Is there a git tree I can pull from which has >>these patches? (I don't mind using the patches themselves as well.) >> >>I'll take a look indepth and comment further. >> >>Thanks, >> Luben > > > Hey Luben, > > I don't have a git tree setup, just the three patches. I assume you've tested them already on the SAS Transport Layer? Luben -- http://linux.adaptec.com/sas/ http://www.adaptec.com/sas/ ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 0/2] libata: support SATA devices on SAS HBAs 2005-10-25 13:40 ` Luben Tuikov @ 2005-10-25 13:53 ` Brian King 2005-10-25 14:08 ` Luben Tuikov 0 siblings, 1 reply; 38+ messages in thread From: Brian King @ 2005-10-25 13:53 UTC (permalink / raw) To: Luben Tuikov Cc: Jeff Garzik, Bartlomiej Zolnierkiewicz, linux-ide, linux-scsi Luben Tuikov wrote: >>>Hey Brian, >>> >>>That's admireable effort. Is there a git tree I can pull from which has >>>these patches? (I don't mind using the patches themselves as well.) >>> >>>I'll take a look indepth and comment further. >>> >>>Thanks, >>> Luben >> >> >>Hey Luben, >> >>I don't have a git tree setup, just the three patches. > > > I assume you've tested them already on the SAS Transport Layer? Unfortunately, no. My primary goal is to have an API I can use in the ipr LLDD, which is a RAID adapter which will talk SPI, SAS, and SATA. I am still trying to get the patches tested in my environment, but since there has been some discussion on the list about others needing the same function I figured I would share what I have with a wider audience. Thanks, Brian -- Brian King eServer Storage I/O IBM Linux Technology Center ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 0/2] libata: support SATA devices on SAS HBAs 2005-10-25 13:53 ` Brian King @ 2005-10-25 14:08 ` Luben Tuikov 2005-10-25 14:27 ` Brian King 0 siblings, 1 reply; 38+ messages in thread From: Luben Tuikov @ 2005-10-25 14:08 UTC (permalink / raw) To: brking; +Cc: Jeff Garzik, Bartlomiej Zolnierkiewicz, linux-ide, linux-scsi On 10/25/05 09:53, Brian King wrote: > Unfortunately, no. My primary goal is to have an API I can use > in the ipr LLDD, which is a RAID adapter which will talk > SPI, SAS, and SATA. Hm, that's very cool. > I am still trying to get the patches tested > in my environment, but since there has been some discussion on the > list about others needing the same function I figured I would share > what I have with a wider audience. That's great. Keep me posted on how it fares in your environment. I'll also give them a try. I think that there will be quite a few things that the ipr driver and the SAS Transport Layer would set in exactly the same way, like say, the device id, DMA (rate), etc. Those commonalities can be abstracted away later I guess. If you have a patch introducing this patch to ipr, send it to me please. Thanks, Luben -- http://linux.adaptec.com/sas/ http://www.adaptec.com/sas/ ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 0/2] libata: support SATA devices on SAS HBAs 2005-10-25 14:08 ` Luben Tuikov @ 2005-10-25 14:27 ` Brian King 2005-10-25 17:51 ` Jeff Garzik 0 siblings, 1 reply; 38+ messages in thread From: Brian King @ 2005-10-25 14:27 UTC (permalink / raw) To: Luben Tuikov Cc: Jeff Garzik, Bartlomiej Zolnierkiewicz, linux-ide, linux-scsi [-- Attachment #1: Type: text/plain, Size: 1096 bytes --] Luben Tuikov wrote: > On 10/25/05 09:53, Brian King wrote: >>I am still trying to get the patches tested >>in my environment, but since there has been some discussion on the >>list about others needing the same function I figured I would share >>what I have with a wider audience. > > > That's great. Keep me posted on how it fares in your environment. > I'll also give them a try. > > I think that there will be quite a few things that the ipr driver > and the SAS Transport Layer would set in exactly the same way, > like say, the device id, DMA (rate), etc. Those commonalities can be > abstracted away later I guess. > > If you have a patch introducing this patch to ipr, send it to me please. Here is the ipr patch. Its queued up behind a bunch of other ipr patches I'm getting ready to push, and it won't apply without them. I uploaded the whole patchset to sourceforge, so you can just apply the whole set and have a working tree. http://prdownloads.sourceforge.net/iprdd/ipr-sas-patches.tgz?download Thanks Brian -- Brian King eServer Storage I/O IBM Linux Technology Center [-- Attachment #2: ipr_sata_with_libata_changes.patch --] [-- Type: text/plain, Size: 24448 bytes --] Adds support to attach SATA devices to SAS adapters. Signed-off-by: Brian King <brking@us.ibm.com> --- linux-2.6-bjking1/drivers/scsi/Kconfig | 1 linux-2.6-bjking1/drivers/scsi/Makefile | 2 linux-2.6-bjking1/drivers/scsi/ipr.c | 477 ++++++++++++++++++++++++++++---- linux-2.6-bjking1/drivers/scsi/ipr.h | 85 +++++ 4 files changed, 516 insertions(+), 49 deletions(-) diff -puN drivers/scsi/ipr.h~ipr_sata_with_libata_changes drivers/scsi/ipr.h --- linux-2.6/drivers/scsi/ipr.h~ipr_sata_with_libata_changes 2005-10-25 09:15:49.000000000 -0500 +++ linux-2.6-bjking1/drivers/scsi/ipr.h 2005-10-25 09:15:49.000000000 -0500 @@ -45,6 +45,7 @@ * This can be adjusted at runtime through sysfs device attributes. */ #define IPR_MAX_CMD_PER_LUN 6 +#define IPR_MAX_CMD_PER_ATA_LUN 1 /* * IPR_NUM_BASE_CMD_BLKS: This defines the maximum number of @@ -144,6 +145,7 @@ #define IPR_LUN_RESET 0x40 #define IPR_TARGET_RESET 0x20 #define IPR_BUS_RESET 0x10 +#define IPR_HARDWARE_RESET 0x80 #define IPR_ID_HOST_RR_Q 0xC4 #define IPR_QUERY_IOA_CONFIG 0xC5 #define IPR_CANCEL_ALL_REQUESTS 0xCE @@ -294,7 +296,13 @@ struct ipr_std_inq_data { }__attribute__ ((packed)); struct ipr_config_table_entry { - u8 service_level; + u8 proto; +#define IPR_PROTO_SPI 0x00 +#define IPR_PROTO_SATA 0x02 +#define IPR_PROTO_SATA_ATAPI 0x03 +#define IPR_PROTO_SAS 0x04 +#define IPR_PROTO_SAS_STP 0x06 +#define IPR_PROTO_SAS_STP_ATAPI 0x07 u8 array_id; u8 flags; #define IPR_IS_IOA_RESOURCE 0x80 @@ -306,6 +314,7 @@ struct ipr_config_table_entry { #define IPR_SUBTYPE_AF_DASD 0 #define IPR_SUBTYPE_GENERIC_SCSI 1 #define IPR_SUBTYPE_VOLUME_SET 2 +#define IPR_SUBTYPE_GENERIC_ATA 4 #define IPR_QUEUEING_MODEL(res) ((((res)->cfgte.flags) & 0x70) >> 4) #define IPR_QUEUE_FROZEN_MODEL 0 @@ -372,6 +381,37 @@ struct ipr_cmd_pkt { __be16 timeout; }__attribute__ ((packed, aligned(4))); +struct ipr_ioarcb_ata_regs { + u8 flags; +#define IPR_ATA_FLAG_PACKET_CMD 0x80 +#define IPR_ATA_FLAG_XFER_TYPE_DMA 0x40 +#define IPR_ATA_FLAG_STATUS_ON_GOOD_COMPLETION 0x20 + u8 reserved[3]; + + __be16 data; + u8 feature; + u8 nsect; + u8 lbal; + u8 lbam; + u8 lbah; + u8 device; + u8 command; + u8 reserved2[3]; + u8 hob_feature; + u8 hob_nsect; + u8 hob_lbal; + u8 hob_lbam; + u8 hob_lbah; + u8 ctl; +}__attribute__ ((packed, aligned(4))); + +struct ipr_ioarcb_add_data { + union { + struct ipr_ioarcb_ata_regs regs; + __be32 add_cmd_parms[10]; + }u; +}__attribute__ ((packed, aligned(4))); + /* IOA Request Control Block 128 bytes */ struct ipr_ioarcb { __be32 ioarcb_host_pci_addr; @@ -396,7 +436,7 @@ struct ipr_ioarcb { struct ipr_cmd_pkt cmd_pkt; __be32 add_cmd_parms_len; - __be32 add_cmd_parms[10]; + struct ipr_ioarcb_add_data add_data;; }__attribute__((packed, aligned (4))); struct ipr_ioadl_desc { @@ -432,6 +472,21 @@ struct ipr_ioasa_gpdd { __be32 ioa_data[2]; }__attribute__((packed, aligned (4))); +struct ipr_ioasa_gata { + u8 error; + u8 nsect; /* Interrupt reason */ + u8 lbal; + u8 lbam; + u8 lbah; + u8 device; + u8 status; + u8 alt_status; /* ATA CTL */ + u8 hob_nsect; + u8 hob_lbal; + u8 hob_lbam; + u8 hob_lbah; +}__attribute__((packed, aligned (4))); + struct ipr_auto_sense { __be16 auto_sense_len; __be16 ioa_data_len; @@ -473,6 +528,7 @@ struct ipr_ioasa { struct ipr_ioasa_vset vset; struct ipr_ioasa_af_dasd dasd; struct ipr_ioasa_gpdd gpdd; + struct ipr_ioasa_gata gata; } u; struct ipr_auto_sense auto_sense; @@ -789,6 +845,13 @@ struct ipr_bus_attributes { u32 max_xfer_rate; }; +struct ipr_sata_port { + struct ata_port *ap; + struct ipr_resource_entry *res; + struct ipr_ioa_cfg *ioa_cfg; + struct ipr_ioasa_gata ioasa; +}; + struct ipr_resource_entry { struct ipr_config_table_entry cfgte; u8 needs_sync_complete:1; @@ -798,6 +861,7 @@ struct ipr_resource_entry { u8 resetting_device:1; struct scsi_device *sdev; + struct ipr_sata_port *sata_port; struct list_head queue; }; @@ -1025,6 +1089,7 @@ struct ipr_cmnd { struct ipr_ioadl_desc ioadl[IPR_NUM_IOADL_ENTRIES]; struct list_head queue; struct scsi_cmnd *scsi_cmd; + struct ata_queued_cmd *qc; struct completion completion; struct timer_list timer; void (*done) (struct ipr_cmnd *); @@ -1302,6 +1367,22 @@ static inline int ipr_is_gscsi(struct ip } /** + * ipr_is_gata - Determine if a resource is a generic ATA resource + * @res: resource entry struct + * + * Return value: + * 1 if GATA / 0 if not GATA + **/ +static inline int ipr_is_gata(struct ipr_resource_entry *res) +{ + if (!ipr_is_ioa_resource(res) && + IPR_RES_SUBTYPE(res) == IPR_SUBTYPE_GENERIC_ATA) + return 1; + else + return 0; +} + +/** * ipr_is_naca_model - Determine if a resource is using NACA queueing model * @res: resource entry struct * diff -puN drivers/scsi/ipr.c~ipr_sata_with_libata_changes drivers/scsi/ipr.c --- linux-2.6/drivers/scsi/ipr.c~ipr_sata_with_libata_changes 2005-10-25 09:15:49.000000000 -0500 +++ linux-2.6-bjking1/drivers/scsi/ipr.c 2005-10-25 09:15:49.000000000 -0500 @@ -71,6 +71,8 @@ #include <linux/firmware.h> #include <linux/module.h> #include <linux/moduleparam.h> +#include "scsi_typedefs.h" +#include <linux/libata.h> #include <asm/io.h> #include <asm/irq.h> #include <asm/processor.h> @@ -821,6 +823,7 @@ static void ipr_init_res_entry(struct ip res->del_from_ml = 0; res->resetting_device = 0; res->sdev = NULL; + res->sata_port = NULL; } /** @@ -3043,6 +3046,17 @@ static int ipr_free_dump(struct ipr_ioa_ **/ static int ipr_change_queue_depth(struct scsi_device *sdev, int qdepth) { + struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *)sdev->host->hostdata; + struct ipr_resource_entry *res; + unsigned long lock_flags = 0; + + spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); + res = (struct ipr_resource_entry *)sdev->hostdata; + + if (res && ipr_is_gata(res) && qdepth > IPR_MAX_CMD_PER_ATA_LUN) + qdepth = IPR_MAX_CMD_PER_ATA_LUN; + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth); return sdev->queue_depth; } @@ -3169,6 +3183,8 @@ static void ipr_slave_destroy(struct scs struct ipr_resource_entry *res; struct ipr_ioa_cfg *ioa_cfg; unsigned long lock_flags = 0; + struct ipr_sata_port *sata_port = NULL; + struct ata_port *ap = NULL; ioa_cfg = (struct ipr_ioa_cfg *) sdev->host->hostdata; @@ -3177,8 +3193,14 @@ static void ipr_slave_destroy(struct scs if (res) { sdev->hostdata = NULL; res->sdev = NULL; + sata_port = res->sata_port; + res->sata_port = NULL; + if (sata_port) + ap = sata_port->ap; } spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + kfree(sata_port); + ata_sas_port_destroy(ap); } /** @@ -3211,12 +3233,92 @@ static int ipr_slave_configure(struct sc } if (IPR_IS_DASD_DEVICE(res->cfgte.std_inq_data)) sdev->allow_restart = 1; - scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); + if (ipr_is_gata(res)) { + scsi_adjust_queue_depth(sdev, 0, IPR_MAX_CMD_PER_ATA_LUN); + ata_sas_slave_configure(sdev, res->sata_port->ap); + } else { + scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); + } } spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); return 0; } +static struct ata_port_info sata_port_info; + +/** + * ipr_ata_slave_alloc - Prepare for commands to a SATA device + * @sdev: scsi device struct + * + * This function allocates an ATA port and initializes the SATA + * device so that future commands sent through queuecommand will + * work. + * + * Return value: + * 0 on success + **/ +static int ipr_ata_slave_alloc(struct scsi_device *sdev) +{ + struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *) sdev->host->hostdata; + struct ata_port *ap; + struct ipr_sata_port *sata_port; + struct ipr_resource_entry *res; + unsigned long lock_flags; + int rc = -ENXIO; + + sata_port = kzalloc(sizeof(*sata_port), GFP_KERNEL); + if (!sata_port) { + ipr_slave_destroy(sdev); + return -ENOMEM; + } + + ap = ata_sas_port_alloc(ioa_cfg->pdev, &sata_port_info); + if (!ap) { + kfree(sata_port); + ipr_slave_destroy(sdev); + return -ENOMEM; + } + + spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); + res = sdev->hostdata; + if (res && ipr_is_gata(res)) { + sata_port->ap = ap; + sata_port->ioa_cfg = ioa_cfg; + sata_port->res = res; + ap->private_data = sata_port; + res->sata_port = sata_port; + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + rc = ata_sas_port_init(ap); + } else + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + + if (rc) + ipr_slave_destroy(sdev); + return rc; +} + +/** + * ipr_find_sdev - Find device based on bus/target/lun. + * @sdev: scsi device struct + * + * Return value: + * resource entry pointer if found / NULL if not found + **/ +static struct ipr_resource_entry *ipr_find_sdev(struct scsi_device *sdev) +{ + struct ipr_ioa_cfg *ioa_cfg = (struct ipr_ioa_cfg *) sdev->host->hostdata; + struct ipr_resource_entry *res; + + list_for_each_entry(res, &ioa_cfg->used_res_q, queue) { + if ((res->cfgte.res_addr.bus == sdev->channel) && + (res->cfgte.res_addr.target == sdev->id) && + (res->cfgte.res_addr.lun == sdev->lun)) + return res; + } + + return NULL; +} + /** * ipr_slave_alloc - Prepare for commands to a device. * @sdev: scsi device struct @@ -3240,18 +3342,18 @@ static int ipr_slave_alloc(struct scsi_d spin_lock_irqsave(ioa_cfg->host->host_lock, lock_flags); - list_for_each_entry(res, &ioa_cfg->used_res_q, queue) { - if ((res->cfgte.res_addr.bus == sdev->channel) && - (res->cfgte.res_addr.target == sdev->id) && - (res->cfgte.res_addr.lun == sdev->lun)) { - res->sdev = sdev; - res->add_to_ml = 0; - res->in_erp = 0; - sdev->hostdata = res; - if (!ipr_is_naca_model(res)) - res->needs_sync_complete = 1; - rc = 0; - break; + res = ipr_find_sdev(sdev); + if (res) { + res->sdev = sdev; + res->add_to_ml = 0; + res->in_erp = 0; + sdev->hostdata = res; + if (!ipr_is_naca_model(res)) + res->needs_sync_complete = 1; + rc = 0; + if (ipr_is_gata(res)) { + spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); + return ipr_ata_slave_alloc(sdev); } } @@ -3350,6 +3452,7 @@ static int __ipr_eh_dev_reset(struct scs cmd_pkt->request_type = IPR_RQTYPE_IOACMD; cmd_pkt->cdb[0] = IPR_RESET_DEVICE; + /* xxx SATA - issue hard reset if soft reset fails? */ ipr_sdev_err(scsi_cmd->device, "Resetting device\n"); ipr_send_blocking_cmd(ipr_cmd, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT); @@ -3426,6 +3529,7 @@ static void ipr_abort_timeout(struct ipr struct ipr_cmnd *reset_cmd; struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; struct ipr_cmd_pkt *cmd_pkt; + struct ipr_resource_entry *res = ipr_cmd->u.sdev->hostdata; unsigned long lock_flags = 0; ENTER; @@ -3443,7 +3547,8 @@ static void ipr_abort_timeout(struct ipr cmd_pkt = &reset_cmd->ioarcb.cmd_pkt; cmd_pkt->request_type = IPR_RQTYPE_IOACMD; cmd_pkt->cdb[0] = IPR_RESET_DEVICE; - cmd_pkt->cdb[2] = IPR_RESET_TYPE_SELECT | IPR_BUS_RESET; + if (!res || !ipr_is_gata(res)) + cmd_pkt->cdb[2] = IPR_RESET_TYPE_SELECT | IPR_BUS_RESET; ipr_do_req(reset_cmd, ipr_bus_reset_done, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT); spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags); @@ -3476,9 +3581,7 @@ static int ipr_cancel_op(struct scsi_cmn * This will force the mid-layer to call ipr_eh_host_reset, * which will then go to sleep and wait for the reset to complete */ - if (ioa_cfg->in_reset_reload || ioa_cfg->ioa_is_dead) - return FAILED; - if (!res || (!ipr_is_gscsi(res) && !ipr_is_vset_device(res))) + if (ioa_cfg->in_reset_reload || ioa_cfg->ioa_is_dead || !res) return FAILED; list_for_each_entry(ipr_cmd, &ioa_cfg->pending_q, queue) { @@ -3676,6 +3779,46 @@ static irqreturn_t ipr_isr(int irq, void } /** + * ipr_build_mapped_ioadl - Build a scatter/gather list + * @ipr_cmd: ipr command struct + * @sglist: scatter/gather list + * @len: total transfer length + * @dma_dir: direction of transfer + * + **/ +static void ipr_build_mapped_ioadl(struct ipr_cmnd *ipr_cmd, + struct scatterlist *sglist, int len, int dma_dir) +{ + int i; + u32 ioadl_flags = 0; + struct ipr_ioarcb *ioarcb = &ipr_cmd->ioarcb; + struct ipr_ioadl_desc *ioadl = ipr_cmd->ioadl; + + if (dma_dir == DMA_TO_DEVICE) { + ioadl_flags = IPR_IOADL_FLAGS_WRITE; + ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ; + ioarcb->write_data_transfer_length = cpu_to_be32(len); + ioarcb->write_ioadl_len = + cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg); + } else if (dma_dir == DMA_FROM_DEVICE) { + ioadl_flags = IPR_IOADL_FLAGS_READ; + ioarcb->read_data_transfer_length = cpu_to_be32(len); + ioarcb->read_ioadl_len = + cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg); + } + + for (i = 0; i < ipr_cmd->dma_use_sg; i++) { + ioadl[i].flags_and_data_len = + cpu_to_be32(ioadl_flags | sg_dma_len(&sglist[i])); + ioadl[i].address = + cpu_to_be32(sg_dma_address(&sglist[i])); + } + + ioadl[i-1].flags_and_data_len |= + cpu_to_be32(IPR_IOADL_FLAGS_LAST); +} + +/** * ipr_build_ioadl - Build a scatter/gather list and map the buffer * @ioa_cfg: ioa config struct * @ipr_cmd: ipr command struct @@ -3686,8 +3829,7 @@ static irqreturn_t ipr_isr(int irq, void static int ipr_build_ioadl(struct ipr_ioa_cfg *ioa_cfg, struct ipr_cmnd *ipr_cmd) { - int i; - struct scatterlist *sglist; + int rc = 0; u32 length; u32 ioadl_flags = 0; struct scsi_cmnd *scsi_cmd = ipr_cmd->scsi_cmd; @@ -3705,34 +3847,13 @@ static int ipr_build_ioadl(struct ipr_io scsi_cmd->use_sg, scsi_cmd->sc_data_direction); - if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) { - ioadl_flags = IPR_IOADL_FLAGS_WRITE; - ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_WRITE_NOT_READ; - ioarcb->write_data_transfer_length = cpu_to_be32(length); - ioarcb->write_ioadl_len = - cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg); - } else if (scsi_cmd->sc_data_direction == DMA_FROM_DEVICE) { - ioadl_flags = IPR_IOADL_FLAGS_READ; - ioarcb->read_data_transfer_length = cpu_to_be32(length); - ioarcb->read_ioadl_len = - cpu_to_be32(sizeof(struct ipr_ioadl_desc) * ipr_cmd->dma_use_sg); - } - - sglist = scsi_cmd->request_buffer; - - for (i = 0; i < ipr_cmd->dma_use_sg; i++) { - ioadl[i].flags_and_data_len = - cpu_to_be32(ioadl_flags | sg_dma_len(&sglist[i])); - ioadl[i].address = - cpu_to_be32(sg_dma_address(&sglist[i])); + if (unlikely(ipr_cmd->dma_use_sg == 0)) { + dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n"); + return -1; } - if (likely(ipr_cmd->dma_use_sg)) { - ioadl[i-1].flags_and_data_len |= - cpu_to_be32(IPR_IOADL_FLAGS_LAST); - return 0; - } else - dev_err(&ioa_cfg->pdev->dev, "pci_map_sg failed!\n"); + ipr_build_mapped_ioadl(ipr_cmd, scsi_cmd->request_buffer, + length, scsi_cmd->sc_data_direction); } else { if (scsi_cmd->sc_data_direction == DMA_TO_DEVICE) { ioadl_flags = IPR_IOADL_FLAGS_WRITE; @@ -3759,7 +3880,7 @@ static int ipr_build_ioadl(struct ipr_io dev_err(&ioa_cfg->pdev->dev, "pci_map_single failed!\n"); } - return -1; + return rc; } /** @@ -4231,6 +4352,29 @@ static void ipr_scsi_done(struct ipr_cmn } /** + * ipr_sata_done - done function for SATA commands + * @ipr_cmd: ipr command struct + * + * This function is invoked by the interrupt handler for + * ops generated by the SCSI mid-layer to SATA devices + * + * Return value: + * none + **/ +static void ipr_sata_done(struct ipr_cmnd *ipr_cmd) +{ + struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg; + struct ata_queued_cmd *qc = ipr_cmd->qc; + struct ipr_sata_port *sata_port = qc->ap->private_data; + u8 status; + + memcpy(&sata_port->ioasa, &ipr_cmd->ioasa.u.gata, sizeof(sata_port->ioasa)); + status = ata_chk_status(qc->ap); + list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); + ata_qc_complete(qc, status); +} + +/** * ipr_save_ioafp_mode_select - Save adapters mode select data * @ioa_cfg: ioa config struct * @scsi_cmd: scsi command struct @@ -4304,6 +4448,9 @@ static int ipr_queuecommand(struct scsi_ return 0; } + if (ipr_is_gata(res)) + return ata_sas_queuecmd(scsi_cmd, done, res->sata_port->ap); + ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg); ioarcb = &ipr_cmd->ioarcb; list_add_tail(&ipr_cmd->queue, &ioa_cfg->pending_q); @@ -4398,6 +4545,244 @@ static struct scsi_host_template driver_ .proc_name = IPR_NAME }; +static void ipr_ata_qc_prep(struct ata_queued_cmd *qc) { } +static int ipr_ata_port_start(struct ata_port *ap) { return 0; } +static void ipr_ata_port_stop(struct ata_port *ap) { } +static void ipr_ata_bmdma_stop(struct ata_queued_cmd *qc) { } +static u8 ipr_ata_bmdma_status(struct ata_port *ap) { return 0; } + +/** + * __ipr_ata_phy_reset - Issue a PHY reset to a SATA device + * @ap: ata port to reset + * + **/ +static void __ipr_ata_phy_reset(struct ata_port *ap) +{ + struct ipr_cmnd *ipr_cmd; + struct ipr_cmd_pkt *cmd_pkt; + struct ipr_sata_port *sata_port = ap->private_data; + struct ipr_ioa_cfg *ioa_cfg = sata_port->ioa_cfg; + + ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg); + ipr_cmd->ioarcb.res_handle = sata_port->res->cfgte.res_handle; + cmd_pkt = &ipr_cmd->ioarcb.cmd_pkt; + cmd_pkt->request_type = IPR_RQTYPE_IOACMD; + cmd_pkt->cdb[0] = IPR_RESET_DEVICE; + cmd_pkt->cdb[2] = IPR_HARDWARE_RESET; + ipr_send_blocking_cmd(ipr_cmd, ipr_timeout, IPR_DEVICE_RESET_TIMEOUT); + memcpy(&sata_port->ioasa, &ipr_cmd->ioasa.u.gata, sizeof(sata_port->ioasa)); + list_add_tail(&ipr_cmd->queue, &ioa_cfg->free_q); +} + +/** + * ipr_ata_phy_reset - libata phy_reset handler + * @ap: ata port to reset + * + * Return value: + * none + **/ +static void ipr_ata_phy_reset(struct ata_port *ap) +{ + unsigned long flags; + struct ipr_sata_port *sata_port = ap->private_data; + struct ipr_ioa_cfg *ioa_cfg = sata_port->ioa_cfg; + + spin_lock_irqsave(ioa_cfg->host->host_lock, flags); + while(!ioa_cfg->in_reset_reload) { + spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); + wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload); + spin_lock_irqsave(ioa_cfg->host->host_lock, flags); + } + + if (!ioa_cfg->allow_cmds) { + spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); + return; + } + + __ipr_ata_phy_reset(ap); + + if (sata_port->res) { + switch(sata_port->res->cfgte.proto) { + case IPR_PROTO_SATA: + case IPR_PROTO_SAS_STP: + if (ata_chk_status(ap) == 0) + ap->ops->port_disable(ap); + else + ap->device[0].class = ATA_DEV_ATA; + break; + case IPR_PROTO_SATA_ATAPI: + case IPR_PROTO_SAS_STP_ATAPI: + ap->device[0].class = ATA_DEV_ATAPI; + break; + default: + ap->ops->port_disable(ap); + break; + }; + } + + spin_unlock_irqrestore(ioa_cfg->host->host_lock, flags); +} + +/** + * ipr_copy_sata_tf - Copy a SATA taskfile to an IOA data structure + * @regs: destination + * @tf: source ATA taskfile + * + * Return value: + * none + **/ +static void ipr_copy_sata_tf(struct ipr_ioarcb_ata_regs *regs, + struct ata_taskfile *tf) +{ + regs->feature = tf->feature; + regs->nsect = tf->nsect; + regs->lbal = tf->lbal; + regs->lbam = tf->lbam; + regs->lbah = tf->lbah; + regs->device = tf->device; + regs->command = tf->command; + regs->hob_feature = tf->hob_feature; + regs->hob_nsect = tf->hob_nsect; + regs->hob_lbal = tf->hob_lbal; + regs->hob_lbam = tf->hob_lbam; + regs->hob_lbah = tf->hob_lbah; + regs->ctl = tf->ctl; +} + +/** + * ipr_qc_issue - Issue a SATA qc to a device + * @qc: queued command + * + * Return value: + * 0 if success + **/ +static int ipr_qc_issue(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct ipr_sata_port *sata_port = ap->private_data; + struct ipr_resource_entry *res = sata_port->res; + struct ipr_ioa_cfg *ioa_cfg = sata_port->ioa_cfg; + struct ipr_cmnd *ipr_cmd; + struct ipr_ioarcb *ioarcb; + struct ipr_ioarcb_ata_regs *regs; + + if (unlikely(!ioa_cfg->allow_cmds || ioa_cfg->ioa_is_dead || !res)) + return -EIO; + + ipr_cmd = ipr_get_free_ipr_cmnd(ioa_cfg); + ioarcb = &ipr_cmd->ioarcb; + regs = &ioarcb->add_data.u.regs; + + memset(&ioarcb->add_data, 0, sizeof(ioarcb->add_data)); + ioarcb->add_cmd_parms_len = cpu_to_be32(sizeof(ioarcb->add_data.u.regs)); + + list_add_tail(&ipr_cmd->queue, &ioa_cfg->pending_q); + ipr_cmd->qc = qc; + ipr_cmd->done = ipr_sata_done; + ipr_cmd->ioarcb.res_handle = res->cfgte.res_handle; + ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_NO_LINK_DESC; + ioarcb->cmd_pkt.flags_hi |= IPR_FLAGS_HI_NO_ULEN_CHK; + ipr_cmd->dma_use_sg = qc->n_elem; + + ipr_build_mapped_ioadl(ipr_cmd, qc->sg, qc->nbytes, qc->dma_dir); + ipr_trc_hook(ipr_cmd, IPR_TRACE_START, IPR_GET_PHYS_LOC(res->cfgte.res_addr)); + regs->flags |= IPR_ATA_FLAG_STATUS_ON_GOOD_COMPLETION; + ipr_copy_sata_tf(regs, &qc->tf); + + switch (qc->tf.protocol) { + case ATA_PROT_NODATA: + case ATA_PROT_PIO: + break; + + case ATA_PROT_DMA: + regs->flags |= IPR_ATA_FLAG_XFER_TYPE_DMA; + break; + + case ATA_PROT_ATAPI: + case ATA_PROT_ATAPI_NODATA: + regs->flags |= IPR_ATA_FLAG_PACKET_CMD; + break; + + case ATA_PROT_ATAPI_DMA: + regs->flags |= IPR_ATA_FLAG_PACKET_CMD; + regs->flags |= IPR_ATA_FLAG_XFER_TYPE_DMA; + break; + + default: + WARN_ON(1); + return -1; + } + + mb(); + writel(be32_to_cpu(ioarcb->ioarcb_host_pci_addr), + ioa_cfg->regs.ioarrin_reg); + return 0; +} + +/** + * ipr_ata_check_status - Return last ATA status + * @ap: ATA port + * + * Return value: + * ATA status + **/ +static u8 ipr_ata_check_status(struct ata_port *ap) +{ + struct ipr_sata_port *sata_port = ap->private_data; + return sata_port->ioasa.status; +} + +/** + * ipr_ata_check_altstatus - Return last ATA altstatus + * @ap: ATA port + * + * Return value: + * Alt ATA status + **/ +static u8 ipr_ata_check_altstatus(struct ata_port *ap) +{ + struct ipr_sata_port *sata_port = ap->private_data; + return sata_port->ioasa.alt_status; +} + +/** + * ipr_ata_check_err - Return last error status + * @ap: ATA port + * + * Return value: + * ATA error status + **/ +static u8 ipr_ata_check_err(struct ata_port *ap) +{ + struct ipr_sata_port *sata_port = ap->private_data; + return sata_port->ioasa.error; +} + +static struct ata_port_operations ipr_sata_ops = { + .port_disable = ata_port_disable, + .check_status = ipr_ata_check_status, + .check_altstatus = ipr_ata_check_altstatus, + .check_err = ipr_ata_check_err, + .dev_select = ata_noop_dev_select, + .phy_reset = ipr_ata_phy_reset, + .qc_prep = ipr_ata_qc_prep, + .qc_issue = ipr_qc_issue, + .port_start = ipr_ata_port_start, + .port_stop = ipr_ata_port_stop, + .bmdma_stop = ipr_ata_bmdma_stop, + .bmdma_status = ipr_ata_bmdma_status, +}; + +static struct ata_port_info sata_port_info = { + .sht = &driver_template, + .host_flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SATA_RESET | + ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA, /* xxx */ + .pio_mask = 0x10, /* pio4 */ + .mwdma_mask = 0x07, + .udma_mask = 0x7f, /* udma0-6 */ + .port_ops = &ipr_sata_ops +}; + #ifdef CONFIG_PPC_PSERIES static const u16 ipr_blocked_processors[] = { PV_NORTHSTAR, diff -puN drivers/scsi/Kconfig~ipr_sata_with_libata_changes drivers/scsi/Kconfig --- linux-2.6/drivers/scsi/Kconfig~ipr_sata_with_libata_changes 2005-10-25 09:15:49.000000000 -0500 +++ linux-2.6-bjking1/drivers/scsi/Kconfig 2005-10-25 09:15:49.000000000 -0500 @@ -1071,6 +1071,7 @@ config SCSI_IPR tristate "IBM Power Linux RAID adapter support" depends on PCI && SCSI select FW_LOADER + select SCSI_SATA ---help--- This driver supports the IBM Power Linux family RAID adapters. This includes IBM pSeries 5712, 5703, 5709, and 570A, as well diff -puN drivers/scsi/Makefile~ipr_sata_with_libata_changes drivers/scsi/Makefile --- linux-2.6/drivers/scsi/Makefile~ipr_sata_with_libata_changes 2005-10-25 09:15:49.000000000 -0500 +++ linux-2.6-bjking1/drivers/scsi/Makefile 2005-10-25 09:15:49.000000000 -0500 @@ -122,7 +122,7 @@ obj-$(CONFIG_SCSI_FCAL) += fcal.o obj-$(CONFIG_SCSI_CPQFCTS) += cpqfc.o obj-$(CONFIG_SCSI_LASI700) += 53c700.o lasi700.o obj-$(CONFIG_SCSI_NSP32) += nsp32.o -obj-$(CONFIG_SCSI_IPR) += ipr.o +obj-$(CONFIG_SCSI_IPR) += libata.o ipr.o obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsi/ obj-$(CONFIG_SCSI_SATA_AHCI) += libata.o ahci.o obj-$(CONFIG_SCSI_SATA_SVW) += libata.o sata_svw.o _ ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 0/2] libata: support SATA devices on SAS HBAs 2005-10-25 14:27 ` Brian King @ 2005-10-25 17:51 ` Jeff Garzik 0 siblings, 0 replies; 38+ messages in thread From: Jeff Garzik @ 2005-10-25 17:51 UTC (permalink / raw) To: brking; +Cc: Luben Tuikov, Bartlomiej Zolnierkiewicz, linux-ide, linux-scsi Brian King wrote: > Here is the ipr patch. Its queued up behind a bunch of other ipr patches > I'm getting ready to push, and it won't apply without them. > I uploaded the whole patchset to sourceforge, so you can just apply the whole > set and have a working tree. > > http://prdownloads.sourceforge.net/iprdd/ipr-sas-patches.tgz?download Looks pretty sane to me... Jeff ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [RFC 0/2] libata: support SATA devices on SAS HBAs 2005-10-05 20:59 ` Jeff Garzik 2005-10-24 22:17 ` [PATCH " Brian King @ 2005-10-25 17:57 ` Brian King 2005-10-25 18:07 ` Jeff Garzik 1 sibling, 1 reply; 38+ messages in thread From: Brian King @ 2005-10-25 17:57 UTC (permalink / raw) To: Jeff Garzik; +Cc: Bartlomiej Zolnierkiewicz, linux-ide Jeff Garzik wrote: > Bartlomiej Zolnierkiewicz wrote: > >>[PATCH] libata: add ops->qc_transport for SAS >> >>* add ->qc_transport to struct ata_port_operations >>* add default ata_qc_transport() and update all host drivers >> >>Thanks to this change we won't have to depend on host_set >>and host_set->lock for devices attached to SAS HBAs. >> >>Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> > > > > Seems sane at a quick glance, though I'm a bit disappointed we have to > add yet another level of indirection to the hot path. > > You made a good point, though, by pointing out that all the ata_qc_xxx > stuff is essentially completely inside a single lock domain. > > Other notes: There may be other dependencies such as wanting to > reference the struct device pointer in host_set and similar details that > need handling. Also, I was planning to move some of the ata_port_ops > into a separate host_set ops, since they (hooks such as ->irq_clear or > ->host_stop) are really host-wide hooks, not per-port hooks. Jeff, Is this patch on its way into one of your trees, or should I just pick it up add it to my libata SAS patchset so you can just grab the whole patchset once it is ready? Brian -- Brian King eServer Storage I/O IBM Linux Technology Center ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [RFC 0/2] libata: support SATA devices on SAS HBAs 2005-10-25 17:57 ` [RFC " Brian King @ 2005-10-25 18:07 ` Jeff Garzik 0 siblings, 0 replies; 38+ messages in thread From: Jeff Garzik @ 2005-10-25 18:07 UTC (permalink / raw) To: brking; +Cc: Bartlomiej Zolnierkiewicz, linux-ide Brian King wrote: > Is this patch on its way into one of your trees, or should I just pick > it up add it to my libata SAS patchset so you can just grab the whole > patchset once it is ready? For now let's let it live in your patchset... Jeff ^ permalink raw reply [flat|nested] 38+ messages in thread
* [PATCH 2/2] libata: Add support for SATA attachment to SAS adapters
@ 2006-07-13 13:35 Brian King
2006-07-20 14:17 ` Brian King
2006-08-03 21:25 ` Jeff Garzik
0 siblings, 2 replies; 38+ messages in thread
From: Brian King @ 2006-07-13 13:35 UTC (permalink / raw)
To: jgarzik; +Cc: linux-ide, linux-scsi, brking
The following patch enhances libata to allow SAS device drivers
to utilize libata to talk to SATA devices. It introduces some
new APIs which allow libata to be used without allocating a
virtual scsi host.
New APIs:
ata_sas_port_alloc - Allocate an ata_port
ata_sas_port_init - Initialize an ata_port (probe device, etc)
ata_sas_port_destroy - Free an ata_port allocated by ata_sas_port_alloc
ata_sas_slave_configure - configure scsi device
ata_sas_queuecmd - queue a scsi command, similar to ata_scsi_queuecomand
These new APIs can be used either directly by a SAS LLDD or could be used
by the SAS transport class.
Possible usage for a SAS LLDD would be:
scsi_scan_host
target_alloc
ata_sas_port_alloc
slave_alloc
ata_sas_port_init
slave_configure
ata_sas_slave_configure
Commands received by the LLDD for SATA devices would call ata_sas_queuecmd.
Device teardown would occur with:
slave_destroy
port_disable
target_destroy
ata_sas_port_destroy
Acked-by: Jeff Garzik <jgarzik@pobox.com>
Signed-off-by: Brian King <brking@us.ibm.com>
---
drivers/scsi/libata-core.c | 4 -
drivers/scsi/libata-scsi.c | 166 +++++++++++++++++++++++++++++++++++++++++++++
drivers/scsi/libata.h | 2
include/linux/libata.h | 9 ++
4 files changed, 179 insertions(+), 2 deletions(-)
diff -puN drivers/scsi/libata-scsi.c~libata_sas drivers/scsi/libata-scsi.c
--- libata-dev/drivers/scsi/libata-scsi.c~libata_sas 2006-07-09 13:07:22.000000000 -0500
+++ libata-dev-bjking1/drivers/scsi/libata-scsi.c 2006-07-09 13:07:22.000000000 -0500
@@ -3158,3 +3158,169 @@ void ata_scsi_dev_rescan(void *data)
scsi_rescan_device(&(dev->sdev->sdev_gendev));
}
}
+
+/**
+ * ata_sas_port_alloc - Allocate port for a SAS attached SATA device
+ * @pdev: PCI device that the scsi device is attached to
+ * @port_info: Information from low-level host driver
+ * @host: SCSI host that the scsi device is attached to
+ *
+ * LOCKING:
+ * PCI/etc. bus probe sem.
+ *
+ * RETURNS:
+ * ata_port pointer on success / NULL on failure.
+ */
+
+struct ata_port *ata_sas_port_alloc(struct ata_host_set *host_set,
+ struct ata_port_info *port_info,
+ struct Scsi_Host *host)
+{
+ struct ata_port *ap = kzalloc(sizeof(*ap), GFP_KERNEL);
+ int i;
+
+ if (!ap)
+ return NULL;
+
+ ap->dev = host_set->dev;
+ ap->host_set = host_set;
+ ap->id = ata_unique_id++;
+ ap->lock = host->host_lock;
+ ap->ops = port_info->port_ops;
+ ap->flags = port_info->host_flags | ATA_FLAG_DISABLED;
+ ap->pio_mask = port_info->pio_mask;
+ ap->mwdma_mask = port_info->mwdma_mask;
+ ap->udma_mask = port_info->udma_mask;
+ ap->cbl = ATA_CBL_SATA;
+ ap->sata_spd_limit = UINT_MAX;
+ ap->active_tag = ATA_TAG_POISON;
+ ap->last_ctl = 0xFF;
+ INIT_WORK(&ap->port_task, NULL, NULL);
+ INIT_WORK(&ap->hotplug_task, ata_scsi_hotplug, ap);
+ INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan, ap);
+ INIT_LIST_HEAD(&ap->eh_done_q);
+ init_waitqueue_head(&ap->eh_wait_q);
+
+ for (i = 0; i < ATA_MAX_DEVICES; i++) {
+ struct ata_device *dev = &ap->device[i];
+ dev->ap = ap;
+ dev->devno = i;
+ ata_dev_init(dev);
+ }
+
+ return ap;
+}
+EXPORT_SYMBOL_GPL(ata_sas_port_alloc);
+
+/**
+ * ata_sas_port_start - Set port up for dma.
+ * @ap: Port to initialize
+ *
+ * Called just after data structures for each port are
+ * initialized. Allocates DMA pad.
+ *
+ * May be used as the port_start() entry in ata_port_operations.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+int ata_sas_port_start(struct ata_port *ap)
+{
+ return ata_pad_alloc(ap, ap->dev);
+}
+EXPORT_SYMBOL_GPL(ata_sas_port_start);
+
+/**
+ * ata_port_stop - Undo ata_sas_port_start()
+ * @ap: Port to shut down
+ *
+ * Frees the DMA pad.
+ *
+ * May be used as the port_stop() entry in ata_port_operations.
+ *
+ * LOCKING:
+ * Inherited from caller.
+ */
+
+void ata_sas_port_stop(struct ata_port *ap)
+{
+ ata_pad_free(ap, ap->dev);
+}
+EXPORT_SYMBOL_GPL(ata_sas_port_stop);
+
+/**
+ * ata_sas_port_init - Initialize a SATA device
+ * @ap: SATA port to initialize
+ *
+ * LOCKING:
+ * PCI/etc. bus probe sem.
+ *
+ * RETURNS:
+ * Zero on success, non-zero on error.
+ */
+
+int ata_sas_port_init(struct ata_port *ap)
+{
+ int rc = ap->ops->port_start(ap);
+
+ if (!rc)
+ rc = ata_bus_probe(ap);
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(ata_sas_port_init);
+
+/**
+ * ata_sas_port_destroy - Destroy a SATA port allocated by ata_sas_port_alloc
+ * @ap: SATA port to destroy
+ *
+ */
+
+void ata_sas_port_destroy(struct ata_port *ap)
+{
+ ap->ops->port_stop(ap);
+ kfree(ap);
+}
+EXPORT_SYMBOL_GPL(ata_sas_port_destroy);
+
+/**
+ * ata_sas_slave_configure - Default slave_config routine for libata devices
+ * @sdev: SCSI device to configure
+ * @ap: ATA port to which SCSI device is attached
+ *
+ * RETURNS:
+ * Zero.
+ */
+
+int ata_sas_slave_configure(struct scsi_device *sdev, struct ata_port *ap)
+{
+ ata_scsi_sdev_config(sdev);
+ ata_scsi_dev_config(sdev, ap->device);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ata_sas_slave_configure);
+
+/**
+ * ata_sas_queuecmd - Issue SCSI cdb to libata-managed device
+ * @cmd: SCSI command to be sent
+ * @done: Completion function, called when command is complete
+ * @ap: ATA port to which the command is being sent
+ *
+ * RETURNS:
+ * Zero.
+ */
+
+int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *),
+ struct ata_port *ap)
+{
+ ata_scsi_dump_cdb(ap, cmd);
+
+ if (likely(ata_scsi_dev_enabled(ap->device)))
+ __ata_scsi_queuecmd(cmd, done, ap->device);
+ else {
+ cmd->result = (DID_BAD_TARGET << 16);
+ done(cmd);
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(ata_sas_queuecmd);
diff -puN drivers/scsi/libata.h~libata_sas drivers/scsi/libata.h
--- libata-dev/drivers/scsi/libata.h~libata_sas 2006-07-09 13:07:22.000000000 -0500
+++ libata-dev-bjking1/drivers/scsi/libata.h 2006-07-09 13:07:22.000000000 -0500
@@ -43,6 +43,7 @@ extern struct workqueue_struct *ata_aux_
extern int atapi_enabled;
extern int atapi_dmadir;
extern int libata_fua;
+extern unsigned int ata_unique_id;
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev);
extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc);
extern void ata_dev_disable(struct ata_device *dev);
@@ -107,6 +108,7 @@ extern void ata_scsi_rbuf_fill(struct at
u8 *rbuf, unsigned int buflen));
extern void ata_schedule_scsi_eh(struct Scsi_Host *shost);
extern void ata_scsi_dev_rescan(void *data);
+extern int ata_bus_probe(struct ata_port *ap);
/* libata-eh.c */
extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd);
diff -puN include/linux/libata.h~libata_sas include/linux/libata.h
--- libata-dev/include/linux/libata.h~libata_sas 2006-07-09 13:07:22.000000000 -0500
+++ libata-dev-bjking1/include/linux/libata.h 2006-07-09 13:07:22.000000000 -0500
@@ -689,6 +689,15 @@ extern int ata_scsi_detect(struct scsi_h
extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg);
extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *));
extern int ata_scsi_release(struct Scsi_Host *host);
+extern void ata_sas_port_destroy(struct ata_port *);
+extern struct ata_port *ata_sas_port_alloc(struct ata_host_set *,
+ struct ata_port_info *, struct Scsi_Host *);
+extern int ata_sas_port_init(struct ata_port *);
+extern int ata_sas_port_start(struct ata_port *ap);
+extern void ata_sas_port_stop(struct ata_port *ap);
+extern int ata_sas_slave_configure(struct scsi_device *, struct ata_port *);
+extern int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *),
+ struct ata_port *ap);
extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
extern int sata_scr_valid(struct ata_port *ap);
extern int sata_scr_read(struct ata_port *ap, int reg, u32 *val);
diff -puN drivers/scsi/libata-core.c~libata_sas drivers/scsi/libata-core.c
--- libata-dev/drivers/scsi/libata-core.c~libata_sas 2006-07-09 13:07:22.000000000 -0500
+++ libata-dev-bjking1/drivers/scsi/libata-core.c 2006-07-09 13:07:22.000000000 -0500
@@ -70,7 +70,7 @@ static unsigned int ata_dev_init_params(
static unsigned int ata_dev_set_xfermode(struct ata_device *dev);
static void ata_dev_xfermask(struct ata_device *dev);
-static unsigned int ata_unique_id = 1;
+unsigned int ata_unique_id = 1;
static struct workqueue_struct *ata_wq;
struct workqueue_struct *ata_aux_wq;
@@ -1528,7 +1528,7 @@ err_out_nosup:
* Zero on success, negative errno otherwise.
*/
-static int ata_bus_probe(struct ata_port *ap)
+int ata_bus_probe(struct ata_port *ap)
{
unsigned int classes[ATA_MAX_DEVICES];
int tries[ATA_MAX_DEVICES];
_
^ permalink raw reply [flat|nested] 38+ messages in thread* Re: [PATCH 2/2] libata: Add support for SATA attachment to SAS adapters 2006-07-13 13:35 [PATCH 2/2] libata: Add support for SATA attachment to SAS adapters Brian King @ 2006-07-20 14:17 ` Brian King 2006-07-28 14:01 ` Brian King 2006-08-03 21:25 ` Jeff Garzik 1 sibling, 1 reply; 38+ messages in thread From: Brian King @ 2006-07-20 14:17 UTC (permalink / raw) To: Brian King; +Cc: jgarzik, linux-ide, linux-scsi Jeff, Do you have any comments on my latest patches? What can I do to help get this support merged into libata? Here are some test results for the patchset: 1. sg3utils test to SATA/ATAPI device * Perform the following sg3utils commands to a SATA device: o sg_get_config o sginfo o sg_inq o sg_readcap 2. SATA error injection * Use sg_reset to initiate a PHY reset to a SATA device and verify the host recovers. * Use sysfs to reset the ipr adapter. This will cause the SATA device to receive an out of band PHY reset. Use sg_inq to issue an INQUIRY to the device. Verify error handling gets invoked and the system recovers. 3. stress_cd / internal CD/DVD exerciser (run for > 12 hours) 4. SLAB_DEBUG * Run with memory tainting enabled. 5. SATA add/remove device * Use sysfs to delete a SATA device from SCSI core, which will also cause the associated ATA port to get deleted. * Use sysfs to rescan for the SATA device. Verify the SATA device shows up again. * Verify no unexpected errors are logged. 6. SATA queue_depth * Use sysfs and attempt to change the queue depth of a SATA device. * Verify the queue depth stays at 1. I would be happy to run any additional testcases. Thanks, Brian Brian King wrote: > The following patch enhances libata to allow SAS device drivers > to utilize libata to talk to SATA devices. It introduces some > new APIs which allow libata to be used without allocating a > virtual scsi host. > > New APIs: > > ata_sas_port_alloc - Allocate an ata_port > ata_sas_port_init - Initialize an ata_port (probe device, etc) > ata_sas_port_destroy - Free an ata_port allocated by ata_sas_port_alloc > ata_sas_slave_configure - configure scsi device > ata_sas_queuecmd - queue a scsi command, similar to ata_scsi_queuecomand > > These new APIs can be used either directly by a SAS LLDD or could be used > by the SAS transport class. > > Possible usage for a SAS LLDD would be: > > scsi_scan_host > target_alloc > ata_sas_port_alloc > slave_alloc > ata_sas_port_init > slave_configure > ata_sas_slave_configure > > Commands received by the LLDD for SATA devices would call ata_sas_queuecmd. > > Device teardown would occur with: > > slave_destroy > port_disable > target_destroy > ata_sas_port_destroy > > Acked-by: Jeff Garzik <jgarzik@pobox.com> > Signed-off-by: Brian King <brking@us.ibm.com> > --- > > drivers/scsi/libata-core.c | 4 - > drivers/scsi/libata-scsi.c | 166 +++++++++++++++++++++++++++++++++++++++++++++ > drivers/scsi/libata.h | 2 > include/linux/libata.h | 9 ++ > 4 files changed, 179 insertions(+), 2 deletions(-) > > diff -puN drivers/scsi/libata-scsi.c~libata_sas drivers/scsi/libata-scsi.c > --- libata-dev/drivers/scsi/libata-scsi.c~libata_sas 2006-07-09 13:07:22.000000000 -0500 > +++ libata-dev-bjking1/drivers/scsi/libata-scsi.c 2006-07-09 13:07:22.000000000 -0500 > @@ -3158,3 +3158,169 @@ void ata_scsi_dev_rescan(void *data) > scsi_rescan_device(&(dev->sdev->sdev_gendev)); > } > } > + > +/** > + * ata_sas_port_alloc - Allocate port for a SAS attached SATA device > + * @pdev: PCI device that the scsi device is attached to > + * @port_info: Information from low-level host driver > + * @host: SCSI host that the scsi device is attached to > + * > + * LOCKING: > + * PCI/etc. bus probe sem. > + * > + * RETURNS: > + * ata_port pointer on success / NULL on failure. > + */ > + > +struct ata_port *ata_sas_port_alloc(struct ata_host_set *host_set, > + struct ata_port_info *port_info, > + struct Scsi_Host *host) > +{ > + struct ata_port *ap = kzalloc(sizeof(*ap), GFP_KERNEL); > + int i; > + > + if (!ap) > + return NULL; > + > + ap->dev = host_set->dev; > + ap->host_set = host_set; > + ap->id = ata_unique_id++; > + ap->lock = host->host_lock; > + ap->ops = port_info->port_ops; > + ap->flags = port_info->host_flags | ATA_FLAG_DISABLED; > + ap->pio_mask = port_info->pio_mask; > + ap->mwdma_mask = port_info->mwdma_mask; > + ap->udma_mask = port_info->udma_mask; > + ap->cbl = ATA_CBL_SATA; > + ap->sata_spd_limit = UINT_MAX; > + ap->active_tag = ATA_TAG_POISON; > + ap->last_ctl = 0xFF; > + INIT_WORK(&ap->port_task, NULL, NULL); > + INIT_WORK(&ap->hotplug_task, ata_scsi_hotplug, ap); > + INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan, ap); > + INIT_LIST_HEAD(&ap->eh_done_q); > + init_waitqueue_head(&ap->eh_wait_q); > + > + for (i = 0; i < ATA_MAX_DEVICES; i++) { > + struct ata_device *dev = &ap->device[i]; > + dev->ap = ap; > + dev->devno = i; > + ata_dev_init(dev); > + } > + > + return ap; > +} > +EXPORT_SYMBOL_GPL(ata_sas_port_alloc); > + > +/** > + * ata_sas_port_start - Set port up for dma. > + * @ap: Port to initialize > + * > + * Called just after data structures for each port are > + * initialized. Allocates DMA pad. > + * > + * May be used as the port_start() entry in ata_port_operations. > + * > + * LOCKING: > + * Inherited from caller. > + */ > +int ata_sas_port_start(struct ata_port *ap) > +{ > + return ata_pad_alloc(ap, ap->dev); > +} > +EXPORT_SYMBOL_GPL(ata_sas_port_start); > + > +/** > + * ata_port_stop - Undo ata_sas_port_start() > + * @ap: Port to shut down > + * > + * Frees the DMA pad. > + * > + * May be used as the port_stop() entry in ata_port_operations. > + * > + * LOCKING: > + * Inherited from caller. > + */ > + > +void ata_sas_port_stop(struct ata_port *ap) > +{ > + ata_pad_free(ap, ap->dev); > +} > +EXPORT_SYMBOL_GPL(ata_sas_port_stop); > + > +/** > + * ata_sas_port_init - Initialize a SATA device > + * @ap: SATA port to initialize > + * > + * LOCKING: > + * PCI/etc. bus probe sem. > + * > + * RETURNS: > + * Zero on success, non-zero on error. > + */ > + > +int ata_sas_port_init(struct ata_port *ap) > +{ > + int rc = ap->ops->port_start(ap); > + > + if (!rc) > + rc = ata_bus_probe(ap); > + > + return rc; > +} > +EXPORT_SYMBOL_GPL(ata_sas_port_init); > + > +/** > + * ata_sas_port_destroy - Destroy a SATA port allocated by ata_sas_port_alloc > + * @ap: SATA port to destroy > + * > + */ > + > +void ata_sas_port_destroy(struct ata_port *ap) > +{ > + ap->ops->port_stop(ap); > + kfree(ap); > +} > +EXPORT_SYMBOL_GPL(ata_sas_port_destroy); > + > +/** > + * ata_sas_slave_configure - Default slave_config routine for libata devices > + * @sdev: SCSI device to configure > + * @ap: ATA port to which SCSI device is attached > + * > + * RETURNS: > + * Zero. > + */ > + > +int ata_sas_slave_configure(struct scsi_device *sdev, struct ata_port *ap) > +{ > + ata_scsi_sdev_config(sdev); > + ata_scsi_dev_config(sdev, ap->device); > + return 0; > +} > +EXPORT_SYMBOL_GPL(ata_sas_slave_configure); > + > +/** > + * ata_sas_queuecmd - Issue SCSI cdb to libata-managed device > + * @cmd: SCSI command to be sent > + * @done: Completion function, called when command is complete > + * @ap: ATA port to which the command is being sent > + * > + * RETURNS: > + * Zero. > + */ > + > +int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), > + struct ata_port *ap) > +{ > + ata_scsi_dump_cdb(ap, cmd); > + > + if (likely(ata_scsi_dev_enabled(ap->device))) > + __ata_scsi_queuecmd(cmd, done, ap->device); > + else { > + cmd->result = (DID_BAD_TARGET << 16); > + done(cmd); > + } > + return 0; > +} > +EXPORT_SYMBOL_GPL(ata_sas_queuecmd); > diff -puN drivers/scsi/libata.h~libata_sas drivers/scsi/libata.h > --- libata-dev/drivers/scsi/libata.h~libata_sas 2006-07-09 13:07:22.000000000 -0500 > +++ libata-dev-bjking1/drivers/scsi/libata.h 2006-07-09 13:07:22.000000000 -0500 > @@ -43,6 +43,7 @@ extern struct workqueue_struct *ata_aux_ > extern int atapi_enabled; > extern int atapi_dmadir; > extern int libata_fua; > +extern unsigned int ata_unique_id; > extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev); > extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); > extern void ata_dev_disable(struct ata_device *dev); > @@ -107,6 +108,7 @@ extern void ata_scsi_rbuf_fill(struct at > u8 *rbuf, unsigned int buflen)); > extern void ata_schedule_scsi_eh(struct Scsi_Host *shost); > extern void ata_scsi_dev_rescan(void *data); > +extern int ata_bus_probe(struct ata_port *ap); > > /* libata-eh.c */ > extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); > diff -puN include/linux/libata.h~libata_sas include/linux/libata.h > --- libata-dev/include/linux/libata.h~libata_sas 2006-07-09 13:07:22.000000000 -0500 > +++ libata-dev-bjking1/include/linux/libata.h 2006-07-09 13:07:22.000000000 -0500 > @@ -689,6 +689,15 @@ extern int ata_scsi_detect(struct scsi_h > extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); > extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); > extern int ata_scsi_release(struct Scsi_Host *host); > +extern void ata_sas_port_destroy(struct ata_port *); > +extern struct ata_port *ata_sas_port_alloc(struct ata_host_set *, > + struct ata_port_info *, struct Scsi_Host *); > +extern int ata_sas_port_init(struct ata_port *); > +extern int ata_sas_port_start(struct ata_port *ap); > +extern void ata_sas_port_stop(struct ata_port *ap); > +extern int ata_sas_slave_configure(struct scsi_device *, struct ata_port *); > +extern int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), > + struct ata_port *ap); > extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); > extern int sata_scr_valid(struct ata_port *ap); > extern int sata_scr_read(struct ata_port *ap, int reg, u32 *val); > diff -puN drivers/scsi/libata-core.c~libata_sas drivers/scsi/libata-core.c > --- libata-dev/drivers/scsi/libata-core.c~libata_sas 2006-07-09 13:07:22.000000000 -0500 > +++ libata-dev-bjking1/drivers/scsi/libata-core.c 2006-07-09 13:07:22.000000000 -0500 > @@ -70,7 +70,7 @@ static unsigned int ata_dev_init_params( > static unsigned int ata_dev_set_xfermode(struct ata_device *dev); > static void ata_dev_xfermask(struct ata_device *dev); > > -static unsigned int ata_unique_id = 1; > +unsigned int ata_unique_id = 1; > static struct workqueue_struct *ata_wq; > > struct workqueue_struct *ata_aux_wq; > @@ -1528,7 +1528,7 @@ err_out_nosup: > * Zero on success, negative errno otherwise. > */ > > -static int ata_bus_probe(struct ata_port *ap) > +int ata_bus_probe(struct ata_port *ap) > { > unsigned int classes[ATA_MAX_DEVICES]; > int tries[ATA_MAX_DEVICES]; > _ ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 2/2] libata: Add support for SATA attachment to SAS adapters 2006-07-20 14:17 ` Brian King @ 2006-07-28 14:01 ` Brian King 0 siblings, 0 replies; 38+ messages in thread From: Brian King @ 2006-07-28 14:01 UTC (permalink / raw) To: Brian King; +Cc: jgarzik, linux-ide, linux-scsi Ping Brian King wrote: > Jeff, > > Do you have any comments on my latest patches? What can I do to > help get this support merged into libata? > > > Here are some test results for the patchset: > > 1. sg3utils test to SATA/ATAPI device > * Perform the following sg3utils commands to a SATA device: > o sg_get_config > o sginfo > o sg_inq > o sg_readcap > 2. SATA error injection > * Use sg_reset to initiate a PHY reset to a SATA device and verify > the host recovers. > * Use sysfs to reset the ipr adapter. This will cause the SATA device > to receive an out of band PHY reset. Use sg_inq to issue an INQUIRY > to the device. Verify error handling gets invoked and the system > recovers. > 3. stress_cd / internal CD/DVD exerciser (run for > 12 hours) > 4. SLAB_DEBUG > * Run with memory tainting enabled. > 5. SATA add/remove device > * Use sysfs to delete a SATA device from SCSI core, which will also > cause the associated ATA port to get deleted. > * Use sysfs to rescan for the SATA device. Verify the SATA device > shows up again. > * Verify no unexpected errors are logged. > 6. SATA queue_depth > * Use sysfs and attempt to change the queue depth of a SATA device. > * Verify the queue depth stays at 1. > > I would be happy to run any additional testcases. > > Thanks, > > Brian > > > Brian King wrote: >> The following patch enhances libata to allow SAS device drivers >> to utilize libata to talk to SATA devices. It introduces some >> new APIs which allow libata to be used without allocating a >> virtual scsi host. >> >> New APIs: >> >> ata_sas_port_alloc - Allocate an ata_port >> ata_sas_port_init - Initialize an ata_port (probe device, etc) >> ata_sas_port_destroy - Free an ata_port allocated by ata_sas_port_alloc >> ata_sas_slave_configure - configure scsi device >> ata_sas_queuecmd - queue a scsi command, similar to ata_scsi_queuecomand >> >> These new APIs can be used either directly by a SAS LLDD or could be used >> by the SAS transport class. >> >> Possible usage for a SAS LLDD would be: >> >> scsi_scan_host >> target_alloc >> ata_sas_port_alloc >> slave_alloc >> ata_sas_port_init >> slave_configure >> ata_sas_slave_configure >> >> Commands received by the LLDD for SATA devices would call ata_sas_queuecmd. >> >> Device teardown would occur with: >> >> slave_destroy >> port_disable >> target_destroy >> ata_sas_port_destroy >> >> Acked-by: Jeff Garzik <jgarzik@pobox.com> >> Signed-off-by: Brian King <brking@us.ibm.com> >> --- >> >> drivers/scsi/libata-core.c | 4 - >> drivers/scsi/libata-scsi.c | 166 +++++++++++++++++++++++++++++++++++++++++++++ >> drivers/scsi/libata.h | 2 >> include/linux/libata.h | 9 ++ >> 4 files changed, 179 insertions(+), 2 deletions(-) >> >> diff -puN drivers/scsi/libata-scsi.c~libata_sas drivers/scsi/libata-scsi.c >> --- libata-dev/drivers/scsi/libata-scsi.c~libata_sas 2006-07-09 13:07:22.000000000 -0500 >> +++ libata-dev-bjking1/drivers/scsi/libata-scsi.c 2006-07-09 13:07:22.000000000 -0500 >> @@ -3158,3 +3158,169 @@ void ata_scsi_dev_rescan(void *data) >> scsi_rescan_device(&(dev->sdev->sdev_gendev)); >> } >> } >> + >> +/** >> + * ata_sas_port_alloc - Allocate port for a SAS attached SATA device >> + * @pdev: PCI device that the scsi device is attached to >> + * @port_info: Information from low-level host driver >> + * @host: SCSI host that the scsi device is attached to >> + * >> + * LOCKING: >> + * PCI/etc. bus probe sem. >> + * >> + * RETURNS: >> + * ata_port pointer on success / NULL on failure. >> + */ >> + >> +struct ata_port *ata_sas_port_alloc(struct ata_host_set *host_set, >> + struct ata_port_info *port_info, >> + struct Scsi_Host *host) >> +{ >> + struct ata_port *ap = kzalloc(sizeof(*ap), GFP_KERNEL); >> + int i; >> + >> + if (!ap) >> + return NULL; >> + >> + ap->dev = host_set->dev; >> + ap->host_set = host_set; >> + ap->id = ata_unique_id++; >> + ap->lock = host->host_lock; >> + ap->ops = port_info->port_ops; >> + ap->flags = port_info->host_flags | ATA_FLAG_DISABLED; >> + ap->pio_mask = port_info->pio_mask; >> + ap->mwdma_mask = port_info->mwdma_mask; >> + ap->udma_mask = port_info->udma_mask; >> + ap->cbl = ATA_CBL_SATA; >> + ap->sata_spd_limit = UINT_MAX; >> + ap->active_tag = ATA_TAG_POISON; >> + ap->last_ctl = 0xFF; >> + INIT_WORK(&ap->port_task, NULL, NULL); >> + INIT_WORK(&ap->hotplug_task, ata_scsi_hotplug, ap); >> + INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan, ap); >> + INIT_LIST_HEAD(&ap->eh_done_q); >> + init_waitqueue_head(&ap->eh_wait_q); >> + >> + for (i = 0; i < ATA_MAX_DEVICES; i++) { >> + struct ata_device *dev = &ap->device[i]; >> + dev->ap = ap; >> + dev->devno = i; >> + ata_dev_init(dev); >> + } >> + >> + return ap; >> +} >> +EXPORT_SYMBOL_GPL(ata_sas_port_alloc); >> + >> +/** >> + * ata_sas_port_start - Set port up for dma. >> + * @ap: Port to initialize >> + * >> + * Called just after data structures for each port are >> + * initialized. Allocates DMA pad. >> + * >> + * May be used as the port_start() entry in ata_port_operations. >> + * >> + * LOCKING: >> + * Inherited from caller. >> + */ >> +int ata_sas_port_start(struct ata_port *ap) >> +{ >> + return ata_pad_alloc(ap, ap->dev); >> +} >> +EXPORT_SYMBOL_GPL(ata_sas_port_start); >> + >> +/** >> + * ata_port_stop - Undo ata_sas_port_start() >> + * @ap: Port to shut down >> + * >> + * Frees the DMA pad. >> + * >> + * May be used as the port_stop() entry in ata_port_operations. >> + * >> + * LOCKING: >> + * Inherited from caller. >> + */ >> + >> +void ata_sas_port_stop(struct ata_port *ap) >> +{ >> + ata_pad_free(ap, ap->dev); >> +} >> +EXPORT_SYMBOL_GPL(ata_sas_port_stop); >> + >> +/** >> + * ata_sas_port_init - Initialize a SATA device >> + * @ap: SATA port to initialize >> + * >> + * LOCKING: >> + * PCI/etc. bus probe sem. >> + * >> + * RETURNS: >> + * Zero on success, non-zero on error. >> + */ >> + >> +int ata_sas_port_init(struct ata_port *ap) >> +{ >> + int rc = ap->ops->port_start(ap); >> + >> + if (!rc) >> + rc = ata_bus_probe(ap); >> + >> + return rc; >> +} >> +EXPORT_SYMBOL_GPL(ata_sas_port_init); >> + >> +/** >> + * ata_sas_port_destroy - Destroy a SATA port allocated by ata_sas_port_alloc >> + * @ap: SATA port to destroy >> + * >> + */ >> + >> +void ata_sas_port_destroy(struct ata_port *ap) >> +{ >> + ap->ops->port_stop(ap); >> + kfree(ap); >> +} >> +EXPORT_SYMBOL_GPL(ata_sas_port_destroy); >> + >> +/** >> + * ata_sas_slave_configure - Default slave_config routine for libata devices >> + * @sdev: SCSI device to configure >> + * @ap: ATA port to which SCSI device is attached >> + * >> + * RETURNS: >> + * Zero. >> + */ >> + >> +int ata_sas_slave_configure(struct scsi_device *sdev, struct ata_port *ap) >> +{ >> + ata_scsi_sdev_config(sdev); >> + ata_scsi_dev_config(sdev, ap->device); >> + return 0; >> +} >> +EXPORT_SYMBOL_GPL(ata_sas_slave_configure); >> + >> +/** >> + * ata_sas_queuecmd - Issue SCSI cdb to libata-managed device >> + * @cmd: SCSI command to be sent >> + * @done: Completion function, called when command is complete >> + * @ap: ATA port to which the command is being sent >> + * >> + * RETURNS: >> + * Zero. >> + */ >> + >> +int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), >> + struct ata_port *ap) >> +{ >> + ata_scsi_dump_cdb(ap, cmd); >> + >> + if (likely(ata_scsi_dev_enabled(ap->device))) >> + __ata_scsi_queuecmd(cmd, done, ap->device); >> + else { >> + cmd->result = (DID_BAD_TARGET << 16); >> + done(cmd); >> + } >> + return 0; >> +} >> +EXPORT_SYMBOL_GPL(ata_sas_queuecmd); >> diff -puN drivers/scsi/libata.h~libata_sas drivers/scsi/libata.h >> --- libata-dev/drivers/scsi/libata.h~libata_sas 2006-07-09 13:07:22.000000000 -0500 >> +++ libata-dev-bjking1/drivers/scsi/libata.h 2006-07-09 13:07:22.000000000 -0500 >> @@ -43,6 +43,7 @@ extern struct workqueue_struct *ata_aux_ >> extern int atapi_enabled; >> extern int atapi_dmadir; >> extern int libata_fua; >> +extern unsigned int ata_unique_id; >> extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev); >> extern int ata_rwcmd_protocol(struct ata_queued_cmd *qc); >> extern void ata_dev_disable(struct ata_device *dev); >> @@ -107,6 +108,7 @@ extern void ata_scsi_rbuf_fill(struct at >> u8 *rbuf, unsigned int buflen)); >> extern void ata_schedule_scsi_eh(struct Scsi_Host *shost); >> extern void ata_scsi_dev_rescan(void *data); >> +extern int ata_bus_probe(struct ata_port *ap); >> >> /* libata-eh.c */ >> extern enum scsi_eh_timer_return ata_scsi_timed_out(struct scsi_cmnd *cmd); >> diff -puN include/linux/libata.h~libata_sas include/linux/libata.h >> --- libata-dev/include/linux/libata.h~libata_sas 2006-07-09 13:07:22.000000000 -0500 >> +++ libata-dev-bjking1/include/linux/libata.h 2006-07-09 13:07:22.000000000 -0500 >> @@ -689,6 +689,15 @@ extern int ata_scsi_detect(struct scsi_h >> extern int ata_scsi_ioctl(struct scsi_device *dev, int cmd, void __user *arg); >> extern int ata_scsi_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)); >> extern int ata_scsi_release(struct Scsi_Host *host); >> +extern void ata_sas_port_destroy(struct ata_port *); >> +extern struct ata_port *ata_sas_port_alloc(struct ata_host_set *, >> + struct ata_port_info *, struct Scsi_Host *); >> +extern int ata_sas_port_init(struct ata_port *); >> +extern int ata_sas_port_start(struct ata_port *ap); >> +extern void ata_sas_port_stop(struct ata_port *ap); >> +extern int ata_sas_slave_configure(struct scsi_device *, struct ata_port *); >> +extern int ata_sas_queuecmd(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *), >> + struct ata_port *ap); >> extern unsigned int ata_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); >> extern int sata_scr_valid(struct ata_port *ap); >> extern int sata_scr_read(struct ata_port *ap, int reg, u32 *val); >> diff -puN drivers/scsi/libata-core.c~libata_sas drivers/scsi/libata-core.c >> --- libata-dev/drivers/scsi/libata-core.c~libata_sas 2006-07-09 13:07:22.000000000 -0500 >> +++ libata-dev-bjking1/drivers/scsi/libata-core.c 2006-07-09 13:07:22.000000000 -0500 >> @@ -70,7 +70,7 @@ static unsigned int ata_dev_init_params( >> static unsigned int ata_dev_set_xfermode(struct ata_device *dev); >> static void ata_dev_xfermask(struct ata_device *dev); >> >> -static unsigned int ata_unique_id = 1; >> +unsigned int ata_unique_id = 1; >> static struct workqueue_struct *ata_wq; >> >> struct workqueue_struct *ata_aux_wq; >> @@ -1528,7 +1528,7 @@ err_out_nosup: >> * Zero on success, negative errno otherwise. >> */ >> >> -static int ata_bus_probe(struct ata_port *ap) >> +int ata_bus_probe(struct ata_port *ap) >> { >> unsigned int classes[ATA_MAX_DEVICES]; >> int tries[ATA_MAX_DEVICES]; >> _ > -- Brian King eServer Storage I/O IBM Linux Technology Center ^ permalink raw reply [flat|nested] 38+ messages in thread
* Re: [PATCH 2/2] libata: Add support for SATA attachment to SAS adapters 2006-07-13 13:35 [PATCH 2/2] libata: Add support for SATA attachment to SAS adapters Brian King 2006-07-20 14:17 ` Brian King @ 2006-08-03 21:25 ` Jeff Garzik 1 sibling, 0 replies; 38+ messages in thread From: Jeff Garzik @ 2006-08-03 21:25 UTC (permalink / raw) To: Brian King; +Cc: linux-ide, linux-scsi You shouldn't be duplicating all that init code from ata_host_init(). Fix that issue (presumably by factoring out common code), and I'll apply this SAS<->SATA attachment API patchset. Jeff ^ permalink raw reply [flat|nested] 38+ messages in thread
end of thread, other threads:[~2006-08-03 21:25 UTC | newest] Thread overview: 38+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2005-10-03 21:56 [RFC 0/2] libata: support SATA devices on SAS HBAs Brian King 2005-10-03 21:58 ` [RFC 1/2] libata: configurable host_set lock Brian King 2005-10-03 21:58 ` [RFC 2/2] libata: support SATA devices on SAS HBAs Brian King 2005-10-04 9:56 ` [RFC 0/2] " Jeff Garzik 2005-10-04 10:22 ` Bartlomiej Zolnierkiewicz 2005-10-04 20:56 ` Bartlomiej Zolnierkiewicz 2005-10-05 20:59 ` Jeff Garzik 2005-10-24 22:17 ` [PATCH " Brian King 2005-10-24 22:19 ` [PATCH 1/2] libata: Remove dependence on host_set->dev for SAS Brian King 2005-10-25 17:53 ` Jeff Garzik 2005-10-25 19:30 ` Brian King 2005-10-25 19:43 ` Jeff Garzik 2005-10-25 22:48 ` Luben Tuikov 2005-10-27 16:05 ` Brian King 2005-10-27 20:15 ` Luben Tuikov 2005-11-24 0:53 ` Douglas Gilbert 2005-11-24 1:07 ` Jeff Garzik 2005-11-24 8:12 ` Bartlomiej Zolnierkiewicz 2005-12-02 2:05 ` Jeff Garzik 2005-12-02 8:07 ` Bartlomiej Zolnierkiewicz 2005-12-02 10:28 ` Douglas Gilbert 2005-12-02 10:48 ` Jeff Garzik 2005-11-29 22:13 ` Brian King 2005-10-24 22:20 ` [PATCH 2/2] libata: Add support for SATA attachment to SAS adapters Brian King 2005-10-25 17:58 ` Jeff Garzik 2005-10-25 12:59 ` [PATCH 0/2] libata: support SATA devices on SAS HBAs Luben Tuikov 2005-10-25 13:39 ` Brian King 2005-10-25 13:40 ` Luben Tuikov 2005-10-25 13:53 ` Brian King 2005-10-25 14:08 ` Luben Tuikov 2005-10-25 14:27 ` Brian King 2005-10-25 17:51 ` Jeff Garzik 2005-10-25 17:57 ` [RFC " Brian King 2005-10-25 18:07 ` Jeff Garzik -- strict thread matches above, loose matches on Subject: below -- 2006-07-13 13:35 [PATCH 2/2] libata: Add support for SATA attachment to SAS adapters Brian King 2006-07-20 14:17 ` Brian King 2006-07-28 14:01 ` Brian King 2006-08-03 21:25 ` Jeff Garzik
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).