diff --git a/Documentation/devicetree/bindings/ata/baikal,bt1-ahci.yaml b/Documentation/devicetree/bindings/ata/baikal,bt1-ahci.yaml deleted file mode 100644 index 9b7ca4759bd7..000000000000 --- a/Documentation/devicetree/bindings/ata/baikal,bt1-ahci.yaml +++ /dev/null @@ -1,115 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -%YAML 1.2 ---- -$id: http://devicetree.org/schemas/ata/baikal,bt1-ahci.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: Baikal-T1 SoC AHCI SATA controller - -maintainers: - - Serge Semin - -description: - AHCI SATA controller embedded into the Baikal-T1 SoC is based on the - DWC AHCI SATA v4.10a IP-core. - -allOf: - - $ref: snps,dwc-ahci-common.yaml# - -properties: - compatible: - const: baikal,bt1-ahci - - clocks: - items: - - description: Peripheral APB bus clock - - description: Application AXI BIU clock - - description: SATA Ports reference clock - - clock-names: - items: - - const: pclk - - const: aclk - - const: ref - - resets: - items: - - description: Application AXI BIU domain reset - - description: SATA Ports clock domain reset - - reset-names: - items: - - const: arst - - const: ref - - ports-implemented: - maximum: 0x3 - -patternProperties: - "^sata-port@[0-1]$": - $ref: /schemas/ata/snps,dwc-ahci-common.yaml#/$defs/dwc-ahci-port - - properties: - reg: - minimum: 0 - maximum: 1 - - snps,tx-ts-max: - $ref: /schemas/types.yaml#/definitions/uint32 - description: - Due to having AXI3 bus interface utilized the maximum Tx DMA - transaction size can't exceed 16 beats (AxLEN[3:0]). - enum: [ 1, 2, 4, 8, 16 ] - - snps,rx-ts-max: - $ref: /schemas/types.yaml#/definitions/uint32 - description: - Due to having AXI3 bus interface utilized the maximum Rx DMA - transaction size can't exceed 16 beats (AxLEN[3:0]). - enum: [ 1, 2, 4, 8, 16 ] - - unevaluatedProperties: false - -required: - - compatible - - reg - - interrupts - - clocks - - clock-names - - resets - -unevaluatedProperties: false - -examples: - - | - sata@1f050000 { - compatible = "baikal,bt1-ahci"; - reg = <0x1f050000 0x2000>; - #address-cells = <1>; - #size-cells = <0>; - - interrupts = <0 64 4>; - - clocks = <&ccu_sys 1>, <&ccu_axi 2>, <&sata_ref_clk>; - clock-names = "pclk", "aclk", "ref"; - - resets = <&ccu_axi 2>, <&ccu_sys 0>; - reset-names = "arst", "ref"; - - ports-implemented = <0x3>; - - sata-port@0 { - reg = <0>; - - snps,tx-ts-max = <4>; - snps,rx-ts-max = <4>; - }; - - sata-port@1 { - reg = <1>; - - snps,tx-ts-max = <4>; - snps,rx-ts-max = <4>; - }; - }; -... diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 2349bca136e0..fff305ec1e78 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig @@ -194,7 +194,6 @@ config AHCI_DM816 config AHCI_DWC tristate "Synopsys DWC AHCI SATA support" select SATA_HOST - select MFD_SYSCON if (MIPS_BAIKAL_T1 || COMPILE_TEST) help This option enables support for the Synopsys DWC AHCI SATA controller implementation. diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 293b7fb216b5..9e8b6319025c 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h @@ -357,7 +357,6 @@ struct ahci_host_priv { * If platform uses PHYs. There is a 1:1 relation between the port number and * the PHY position in this array. */ - struct phy **phys; unsigned nports; /* Number of ports */ void *plat_data; /* Other platform data */ unsigned int irq; /* interrupt line */ @@ -379,6 +378,8 @@ struct ahci_host_priv { /* only required for per-port MSI(-X) support */ int (*get_irq_vector)(struct ata_host *host, int port); + + struct phy *phys[] __counted_by(nports); }; /* diff --git a/drivers/ata/ahci_dwc.c b/drivers/ata/ahci_dwc.c index 64abf865bb67..feb8a8539b8e 100644 --- a/drivers/ata/ahci_dwc.c +++ b/drivers/ata/ahci_dwc.c @@ -13,12 +13,10 @@ #include #include #include -#include #include #include #include #include -#include #include "ahci.h" @@ -92,20 +90,6 @@ #define AHCI_DWC_PORT_PHYCR 0x74 #define AHCI_DWC_PORT_PHYSR 0x78 -/* Baikal-T1 AHCI SATA specific registers */ -#define AHCI_BT1_HOST_PHYCR AHCI_DWC_HOST_GPCR -#define AHCI_BT1_HOST_MPLM_MASK GENMASK(29, 23) -#define AHCI_BT1_HOST_LOSDT_MASK GENMASK(22, 20) -#define AHCI_BT1_HOST_CRR BIT(19) -#define AHCI_BT1_HOST_CRW BIT(18) -#define AHCI_BT1_HOST_CRCD BIT(17) -#define AHCI_BT1_HOST_CRCA BIT(16) -#define AHCI_BT1_HOST_CRDI_MASK GENMASK(15, 0) - -#define AHCI_BT1_HOST_PHYSR AHCI_DWC_HOST_GPSR -#define AHCI_BT1_HOST_CRA BIT(16) -#define AHCI_BT1_HOST_CRDO_MASK GENMASK(15, 0) - struct ahci_dwc_plat_data { unsigned int pflags; unsigned int hflags; @@ -122,39 +106,6 @@ struct ahci_dwc_host_priv { u32 dmacr[AHCI_MAX_PORTS]; }; -static int ahci_bt1_init(struct ahci_host_priv *hpriv) -{ - struct ahci_dwc_host_priv *dpriv = hpriv->plat_data; - int ret; - - /* APB, application and reference clocks are required */ - if (!ahci_platform_find_clk(hpriv, "pclk") || - !ahci_platform_find_clk(hpriv, "aclk") || - !ahci_platform_find_clk(hpriv, "ref")) { - dev_err(&dpriv->pdev->dev, "No system clocks specified\n"); - return -EINVAL; - } - - /* - * Fully reset the SATA AXI and ref clocks domain to ensure the state - * machine is working from scratch especially if the reference clocks - * source has been changed. - */ - ret = ahci_platform_assert_rsts(hpriv); - if (ret) { - dev_err(&dpriv->pdev->dev, "Couldn't assert the resets\n"); - return ret; - } - - ret = ahci_platform_deassert_rsts(hpriv); - if (ret) { - dev_err(&dpriv->pdev->dev, "Couldn't de-assert the resets\n"); - return ret; - } - - return 0; -} - static struct ahci_host_priv *ahci_dwc_get_resources(struct platform_device *pdev) { struct ahci_dwc_host_priv *dpriv; @@ -457,15 +408,9 @@ static struct ahci_dwc_plat_data ahci_dwc_plat = { .pflags = AHCI_PLATFORM_GET_RESETS, }; -static struct ahci_dwc_plat_data ahci_bt1_plat = { - .pflags = AHCI_PLATFORM_GET_RESETS | AHCI_PLATFORM_RST_TRIGGER, - .init = ahci_bt1_init, -}; - static const struct of_device_id ahci_dwc_of_match[] = { { .compatible = "snps,dwc-ahci", &ahci_dwc_plat }, { .compatible = "snps,spear-ahci", &ahci_dwc_plat }, - { .compatible = "baikal,bt1-ahci", &ahci_bt1_plat }, {}, }; MODULE_DEVICE_TABLE(of, ahci_dwc_of_match); diff --git a/drivers/ata/libahci_platform.c b/drivers/ata/libahci_platform.c index f37247e7a5cb..6e072d681341 100644 --- a/drivers/ata/libahci_platform.c +++ b/drivers/ata/libahci_platform.c @@ -482,15 +482,29 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev, struct ahci_host_priv *hpriv; u32 mask_port_map = 0; u32 max_port; + int nports; if (!devres_open_group(dev, NULL, GFP_KERNEL)) return ERR_PTR(-ENOMEM); - hpriv = devres_alloc(ahci_platform_put_resources, sizeof(*hpriv), + /* find maximum port id for allocating structures */ + max_port = ahci_platform_find_max_port_id(dev); + /* + * Set nports according to maximum port id. Clamp at + * AHCI_MAX_PORTS, warning message for invalid port id + * is generated later. + * When DT has no sub-nodes max_port is 0, nports is 1, + * in order to be able to use the + * ahci_platform_[en|dis]able_[phys|regulators] functions. + */ + nports = min(AHCI_MAX_PORTS, max_port + 1); + hpriv = devres_alloc(ahci_platform_put_resources, struct_size(hpriv, phys, nports), GFP_KERNEL); if (!hpriv) goto err_out; + hpriv->nports = nports; + devres_add(dev, hpriv); /* @@ -573,23 +587,6 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev, goto err_out; } - /* find maximum port id for allocating structures */ - max_port = ahci_platform_find_max_port_id(dev); - /* - * Set nports according to maximum port id. Clamp at - * AHCI_MAX_PORTS, warning message for invalid port id - * is generated later. - * When DT has no sub-nodes max_port is 0, nports is 1, - * in order to be able to use the - * ahci_platform_[en|dis]able_[phys|regulators] functions. - */ - hpriv->nports = min(AHCI_MAX_PORTS, max_port + 1); - - hpriv->phys = devm_kcalloc(dev, hpriv->nports, sizeof(*hpriv->phys), GFP_KERNEL); - if (!hpriv->phys) { - rc = -ENOMEM; - goto err_out; - } /* * We cannot use devm_ here, since ahci_platform_put_resources() uses * target_pwrs after devm_ have freed memory diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 374993031895..e76d15411e2a 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5151,8 +5151,13 @@ void ata_qc_issue(struct ata_queued_cmd *qc) struct ata_link *link = qc->dev->link; u8 prot = qc->tf.protocol; - /* Make sure only one non-NCQ command is outstanding. */ - WARN_ON_ONCE(ata_tag_valid(link->active_tag)); + /* + * Make sure we have a valid tag and that only one non-NCQ command is + * outstanding. + */ + if (WARN_ON_ONCE(!ata_tag_valid(qc->tag)) || + WARN_ON_ONCE(ata_tag_valid(link->active_tag))) + goto sys_err; if (ata_is_ncq(prot)) { WARN_ON_ONCE(link->sactive & (1 << qc->hw_tag)); @@ -6773,23 +6778,14 @@ static int __init ata_init(void) } libata_transport_init(); - ata_scsi_transport_template = ata_attach_transport(); - if (!ata_scsi_transport_template) { - ata_sff_exit(); - rc = -ENOMEM; - goto err_out; - } printk(KERN_DEBUG "libata version " DRV_VERSION " loaded.\n"); - return 0; -err_out: - return rc; + return 0; } static void __exit ata_exit(void) { - ata_release_transport(ata_scsi_transport_template); libata_transport_exit(); ata_sff_exit(); ata_free_force_param(); diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 23be85418b3b..9a4b67b90b17 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -560,21 +560,27 @@ void ata_scsi_error(struct Scsi_Host *host) { struct ata_port *ap = ata_shost_to_port(host); unsigned long flags; + int nr_timedout; LIST_HEAD(eh_work_q); spin_lock_irqsave(host->host_lock, flags); list_splice_init(&host->eh_cmd_q, &eh_work_q); spin_unlock_irqrestore(host->host_lock, flags); - ata_scsi_cmd_error_handler(host, ap, &eh_work_q); + /* + * First check what errors we got with ata_scsi_cmd_error_handler(). + * If we had no command timeouts and EH is not scheduled for this port, + * meaning that we do not have any failed command, then there is no + * need to go through the full port error handling. We only need to + * flush the completed commands we have. + */ + nr_timedout = ata_scsi_cmd_error_handler(host, ap, &eh_work_q); + if (nr_timedout || ata_port_eh_scheduled(ap)) + ata_scsi_port_error_handler(host, ap); + else + scsi_eh_flush_done_q(&ap->eh_done_q); - /* If we timed raced normal completion and there is nothing to - recover nr_timedout == 0 why exactly are we doing error recovery ? */ - ata_scsi_port_error_handler(host, ap); - - /* finish or retry handled scmd's and clean up */ WARN_ON(!list_empty(&eh_work_q)); - } /** @@ -586,9 +592,11 @@ void ata_scsi_error(struct Scsi_Host *host) * process the given list of commands and return those finished to the * ap->eh_done_q. This function is the first part of the libata error * handler which processes a given list of failed commands. + * + * Return the number of commands that timed out. */ -void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap, - struct list_head *eh_work_q) +int ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap, + struct list_head *eh_work_q) { int i; unsigned long flags; @@ -695,6 +703,8 @@ void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap, ap->eh_tries = ATA_EH_MAX_TRIES; spin_unlock_irqrestore(ap->lock, flags); + + return nr_timedout; } EXPORT_SYMBOL(ata_scsi_cmd_error_handler); @@ -3171,7 +3181,7 @@ int ata_eh_reset(struct ata_link *link, int classify, sata_scr_read(link, SCR_STATUS, &sstatus)) rc = -ERESTART; - if (try >= max_tries) { + if (try >= max_tries || rc == -ENODEV) { /* * Thaw host port even if reset failed, so that the port * can be retried on the next phy event. This risks diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c index b9d635088f5f..2ee54d60ea4b 100644 --- a/drivers/ata/libata-sata.c +++ b/drivers/ata/libata-sata.c @@ -1378,15 +1378,13 @@ EXPORT_SYMBOL_GPL(ata_sas_sdev_configure); int ata_sas_queuecmd(struct scsi_cmnd *cmd, struct ata_port *ap) { - int rc = 0; - if (likely(ata_dev_enabled(ap->link.device))) - rc = __ata_scsi_queuecmd(cmd, ap->link.device); - else { - cmd->result = (DID_BAD_TARGET << 16); - scsi_done(cmd); - } - return rc; + return __ata_scsi_queuecmd(cmd, ap->link.device); + + cmd->result = (DID_BAD_TARGET << 16); + scsi_done(cmd); + + return 0; } EXPORT_SYMBOL_GPL(ata_sas_queuecmd); diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 3b65df914ebb..f44612e269a4 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c @@ -1649,12 +1649,16 @@ nothing_to_do: return 1; } -static void ata_qc_done(struct ata_queued_cmd *qc) +static void ata_scsi_qc_done(struct ata_queued_cmd *qc, bool set_result, + u32 scmd_result) { struct scsi_cmnd *cmd = qc->scsicmd; void (*done)(struct scsi_cmnd *) = qc->scsidone; ata_qc_free(qc); + + if (set_result) + cmd->result = scmd_result; done(cmd); } @@ -1685,24 +1689,19 @@ void ata_scsi_deferred_qc_work(struct work_struct *work) void ata_scsi_requeue_deferred_qc(struct ata_port *ap) { struct ata_queued_cmd *qc = ap->deferred_qc; - struct scsi_cmnd *scmd; lockdep_assert_held(ap->lock); /* * If we have a deferred qc when a reset occurs or NCQ commands fail, * do not try to be smart about what to do with this deferred command - * and simply retry it by completing it with DID_SOFT_ERROR. + * and simply requeue it by completing it with DID_REQUEUE. */ - if (!qc) - return; - - scmd = qc->scsicmd; - ap->deferred_qc = NULL; - cancel_work(&ap->deferred_qc_work); - ata_qc_free(qc); - scmd->result = (DID_SOFT_ERROR << 16); - scsi_done(scmd); + if (qc) { + ap->deferred_qc = NULL; + cancel_work(&ap->deferred_qc_work); + ata_scsi_qc_done(qc, true, DID_REQUEUE << 16); + } } static void ata_scsi_schedule_deferred_qc(struct ata_port *ap) @@ -1758,7 +1757,7 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) ata_scsi_set_sense_information(qc); } - ata_qc_done(qc); + ata_scsi_qc_done(qc, false, 0); ata_scsi_schedule_deferred_qc(ap); } @@ -2917,17 +2916,15 @@ static void atapi_qc_complete(struct ata_queued_cmd *qc) if (qc->cdb[0] == ALLOW_MEDIUM_REMOVAL && qc->dev->sdev) qc->dev->sdev->locked = 0; - qc->scsicmd->result = SAM_STAT_CHECK_CONDITION; - ata_qc_done(qc); + ata_scsi_qc_done(qc, true, SAM_STAT_CHECK_CONDITION); return; } /* successful completion path */ if (cmd->cmnd[0] == INQUIRY && (cmd->cmnd[1] & 0x03) == 0) atapi_fixup_inquiry(cmd); - cmd->result = SAM_STAT_GOOD; - ata_qc_done(qc); + ata_scsi_qc_done(qc, true, SAM_STAT_GOOD); } /** * atapi_xlat - Initialize PACKET taskfile @@ -3576,28 +3573,13 @@ invalid_opcode: return 1; } -/** - * ata_scsiop_maint_in - Simulate a subset of MAINTENANCE_IN - * @dev: Target device. - * @cmd: SCSI command of interest. - * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. - * - * Yields a subset to satisfy scsi_report_opcode() - * - * LOCKING: - * spin_lock_irqsave(host lock) - */ -static unsigned int ata_scsiop_maint_in(struct ata_device *dev, - struct scsi_cmnd *cmd, u8 *rbuf) +static unsigned int ata_scsi_report_supported_opcodes(struct ata_device *dev, + struct scsi_cmnd *cmd, + u8 *rbuf) { u8 *cdb = cmd->cmnd; u8 supported = 0, cdlp = 0, rwcdlp = 0; - if ((cdb[1] & 0x1f) != MI_REPORT_SUPPORTED_OPERATION_CODES) { - ata_scsi_set_invalid_field(dev, cmd, 1, 0xff); - return 0; - } - if (cdb[2] != 1 && cdb[2] != 3) { ata_dev_warn(dev, "invalid command format %d\n", cdb[2]); ata_scsi_set_invalid_field(dev, cmd, 2, 0xff); @@ -3677,6 +3659,32 @@ static unsigned int ata_scsiop_maint_in(struct ata_device *dev, return 4; } +/** + * ata_scsiop_maint_in - Simulate a subset of MAINTENANCE_IN + * @dev: Target device. + * @cmd: SCSI command of interest. + * @rbuf: Response buffer, to which simulated SCSI cmd output is sent. + * + * Yields a subset to satisfy scsi_report_opcode() + * + * LOCKING: + * spin_lock_irqsave(host lock) + */ +static unsigned int ata_scsiop_maint_in(struct ata_device *dev, + struct scsi_cmnd *cmd, u8 *rbuf) +{ + u8 *cdb = cmd->cmnd; + u8 service_action = cdb[1] & 0x1f; + + switch (service_action) { + case MI_REPORT_SUPPORTED_OPERATION_CODES: + return ata_scsi_report_supported_opcodes(dev, cmd, rbuf); + default: + ata_scsi_set_invalid_field(dev, cmd, 1, 0xff); + return 0; + } +} + /** * ata_scsi_report_zones_complete - convert ATA output * @qc: command structure returning the data @@ -4424,6 +4432,79 @@ static inline ata_xlat_func_t ata_get_xlat_func(struct ata_device *dev, u8 cmd) return NULL; } +/** + * ata_scsi_simulate - simulate SCSI command on ATA device + * @dev: the target device + * @cmd: SCSI command being sent to device. + * + * Interprets and directly executes a select list of SCSI commands + * that can be handled internally. + * + * LOCKING: + * spin_lock_irqsave(host lock) + */ +static void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) +{ + const u8 *scsicmd = cmd->cmnd; + u8 tmp8; + + switch (scsicmd[0]) { + case INQUIRY: + ata_scsi_rbuf_fill(dev, cmd, ata_scsiop_inquiry); + break; + + case MODE_SENSE: + case MODE_SENSE_10: + ata_scsi_rbuf_fill(dev, cmd, ata_scsiop_mode_sense); + break; + + case READ_CAPACITY: + case SERVICE_ACTION_IN_16: + ata_scsi_rbuf_fill(dev, cmd, ata_scsiop_read_cap); + break; + + case REPORT_LUNS: + ata_scsi_rbuf_fill(dev, cmd, ata_scsiop_report_luns); + break; + + case REQUEST_SENSE: + ata_scsi_set_sense(dev, cmd, 0, 0, 0); + break; + + /* if we reach this, then writeback caching is disabled, + * turning this into a no-op. + */ + case SYNCHRONIZE_CACHE: + case SYNCHRONIZE_CACHE_16: + fallthrough; + + /* no-op's, complete with success */ + case REZERO_UNIT: + case SEEK_6: + case SEEK_10: + case TEST_UNIT_READY: + break; + + case SEND_DIAGNOSTIC: + tmp8 = scsicmd[1] & ~(1 << 3); + if (tmp8 != 0x4 || scsicmd[3] || scsicmd[4]) + ata_scsi_set_invalid_field(dev, cmd, 1, 0xff); + break; + + case MAINTENANCE_IN: + ata_scsi_rbuf_fill(dev, cmd, ata_scsiop_maint_in); + break; + + /* all other commands */ + default: + ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x20, 0x0); + /* "Invalid command operation code" */ + break; + } + + scsi_done(cmd); +} + enum scsi_qc_status __ata_scsi_queuecmd(struct scsi_cmnd *scmd, struct ata_device *dev) { @@ -4526,80 +4607,6 @@ enum scsi_qc_status ata_scsi_queuecmd(struct Scsi_Host *shost, } EXPORT_SYMBOL_GPL(ata_scsi_queuecmd); -/** - * ata_scsi_simulate - simulate SCSI command on ATA device - * @dev: the target device - * @cmd: SCSI command being sent to device. - * - * Interprets and directly executes a select list of SCSI commands - * that can be handled internally. - * - * LOCKING: - * spin_lock_irqsave(host lock) - */ - -void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd) -{ - const u8 *scsicmd = cmd->cmnd; - u8 tmp8; - - switch(scsicmd[0]) { - case INQUIRY: - ata_scsi_rbuf_fill(dev, cmd, ata_scsiop_inquiry); - break; - - case MODE_SENSE: - case MODE_SENSE_10: - ata_scsi_rbuf_fill(dev, cmd, ata_scsiop_mode_sense); - break; - - case READ_CAPACITY: - case SERVICE_ACTION_IN_16: - ata_scsi_rbuf_fill(dev, cmd, ata_scsiop_read_cap); - break; - - case REPORT_LUNS: - ata_scsi_rbuf_fill(dev, cmd, ata_scsiop_report_luns); - break; - - case REQUEST_SENSE: - ata_scsi_set_sense(dev, cmd, 0, 0, 0); - break; - - /* if we reach this, then writeback caching is disabled, - * turning this into a no-op. - */ - case SYNCHRONIZE_CACHE: - case SYNCHRONIZE_CACHE_16: - fallthrough; - - /* no-op's, complete with success */ - case REZERO_UNIT: - case SEEK_6: - case SEEK_10: - case TEST_UNIT_READY: - break; - - case SEND_DIAGNOSTIC: - tmp8 = scsicmd[1] & ~(1 << 3); - if (tmp8 != 0x4 || scsicmd[3] || scsicmd[4]) - ata_scsi_set_invalid_field(dev, cmd, 1, 0xff); - break; - - case MAINTENANCE_IN: - ata_scsi_rbuf_fill(dev, cmd, ata_scsiop_maint_in); - break; - - /* all other commands */ - default: - ata_scsi_set_sense(dev, cmd, ILLEGAL_REQUEST, 0x20, 0x0); - /* "Invalid command operation code" */ - break; - } - - scsi_done(cmd); -} - int ata_scsi_add_hosts(struct ata_host *host, const struct scsi_host_template *sht) { int i, rc; @@ -4617,7 +4624,7 @@ int ata_scsi_add_hosts(struct ata_host *host, const struct scsi_host_template *s *(struct ata_port **)&shost->hostdata[0] = ap; ap->scsi_host = shost; - shost->transportt = ata_scsi_transport_template; + shost->transportt = &ata_scsi_transportt; shost->unique_id = ap->print_id; shost->max_id = 16; shost->max_lun = 1; diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c index 2099d94c4f68..95862dc34419 100644 --- a/drivers/ata/libata-transport.c +++ b/drivers/ata/libata-transport.c @@ -37,33 +37,10 @@ #include "libata.h" #include "libata-transport.h" -#define ATA_PORT_ATTRS 3 -#define ATA_LINK_ATTRS 3 -#define ATA_DEV_ATTRS 9 - -struct scsi_transport_template; -struct scsi_transport_template *ata_scsi_transport_template; - -struct ata_internal { - struct scsi_transport_template t; - - struct device_attribute private_port_attrs[ATA_PORT_ATTRS]; - struct device_attribute private_link_attrs[ATA_LINK_ATTRS]; - struct device_attribute private_dev_attrs[ATA_DEV_ATTRS]; - - struct transport_container link_attr_cont; - struct transport_container dev_attr_cont; - - /* - * The array of null terminated pointers to attributes - * needed by scsi_sysfs.c - */ - struct device_attribute *link_attrs[ATA_LINK_ATTRS + 1]; - struct device_attribute *port_attrs[ATA_PORT_ATTRS + 1]; - struct device_attribute *dev_attrs[ATA_DEV_ATTRS + 1]; -}; -#define to_ata_internal(tmpl) container_of(tmpl, struct ata_internal, t) - +static int ata_tlink_match(struct attribute_container *cont, + struct device *dev); +static int ata_tdev_match(struct attribute_container *cont, + struct device *dev); #define tdev_to_device(d) \ container_of((d), struct ata_device, tdev) @@ -80,13 +57,6 @@ struct ata_internal { #define transport_class_to_port(dev) \ tdev_to_port((dev)->parent) -/* - * Hack to allow attributes of the same name in different objects. - */ -#define ATA_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \ - struct device_attribute device_attr_##_prefix##_##_name = \ - __ATTR(_name,_mode,_show,_store) - #define ata_bitfield_name_match(title, table) \ static ssize_t \ get_ata_##title##_names(u32 table_key, char *buf) \ @@ -214,6 +184,17 @@ ata_port_simple_attr(stats.idle_irq, idle_irq, "%ld\n", unsigned long); /* We want the port_no sysfs attibute to start at 1 (ap->port_no starts at 0) */ ata_port_simple_attr(port_no + 1, port_no, "%u\n", unsigned int); +static const struct attribute *const ata_port_attr_attrs[] = { + &dev_attr_nr_pmp_links.attr, + &dev_attr_idle_irq.attr, + &dev_attr_port_no.attr, + NULL +}; + +static const struct attribute_group ata_port_attr_group = { + .attrs_const = ata_port_attr_attrs, +}; + static DECLARE_TRANSPORT_CLASS(ata_port_class, "ata_port", NULL, NULL, NULL); @@ -240,7 +221,7 @@ static int ata_tport_match(struct attribute_container *cont, { if (!ata_is_port(dev)) return 0; - return &ata_scsi_transport_template->host_attrs.ac == cont; + return &ata_scsi_transportt.host_attrs.ac == cont; } /** @@ -496,6 +477,23 @@ show_ata_dev_trim(struct device *dev, static DEVICE_ATTR(trim, S_IRUGO, show_ata_dev_trim, NULL); +static const struct attribute *const ata_device_attr_attrs[] = { + &dev_attr_class.attr, + &dev_attr_pio_mode.attr, + &dev_attr_dma_mode.attr, + &dev_attr_xfer_mode.attr, + &dev_attr_spdn_cnt.attr, + &dev_attr_ering.attr, + &dev_attr_id.attr, + &dev_attr_gscr.attr, + &dev_attr_trim.attr, + NULL +}; + +static const struct attribute_group ata_device_attr_group = { + .attrs_const = ata_device_attr_attrs, +}; + static DECLARE_TRANSPORT_CLASS(ata_dev_class, "ata_device", NULL, NULL, NULL); @@ -515,16 +513,6 @@ static bool ata_is_ata_dev(const struct device *dev) return dev->release == ata_tdev_release; } -static int ata_tdev_match(struct attribute_container *cont, - struct device *dev) -{ - struct ata_internal *i = to_ata_internal(ata_scsi_transport_template); - - if (!ata_is_ata_dev(dev)) - return 0; - return &i->dev_attr_cont.ac == cont; -} - /** * ata_tdev_free -- free an ATA transport device * @dev: struct ata_device owning the transport device to free @@ -626,6 +614,17 @@ ata_link_linkspeed_attr(hw_sata_spd_limit, fls); ata_link_linkspeed_attr(sata_spd_limit, fls); ata_link_linkspeed_attr(sata_spd, noop); +static const struct attribute *const ata_link_attr_attrs[] = { + &dev_attr_hw_sata_spd_limit.attr, + &dev_attr_sata_spd_limit.attr, + &dev_attr_sata_spd.attr, + NULL +}; + +static const struct attribute_group ata_link_attr_group = { + .attrs_const = ata_link_attr_attrs, +}; + static DECLARE_TRANSPORT_CLASS(ata_link_class, "ata_link", NULL, NULL, NULL); @@ -645,16 +644,6 @@ static bool ata_is_link(const struct device *dev) return dev->release == ata_tlink_release; } -static int ata_tlink_match(struct attribute_container *cont, - struct device *dev) -{ - struct ata_internal *i = to_ata_internal(ata_scsi_transport_template); - - if (!ata_is_link(dev)) - return 0; - return &i->link_attr_cont.ac == cont; -} - /** * ata_tlink_delete -- remove an ATA link transport device * @link: struct ata_link owning the link transport device to remove @@ -730,101 +719,49 @@ int ata_tlink_add(struct ata_link *link) return error; } +struct scsi_transport_template ata_scsi_transportt = { + .eh_strategy_handler = ata_scsi_error, + .user_scan = ata_scsi_user_scan, + + .host_attrs.ac.class = &ata_port_class.class, + .host_attrs.ac.grp = &ata_port_attr_group, + .host_attrs.ac.match = ata_tport_match, +}; + +static struct transport_container ata_link_attr_cont = { + .ac.class = &ata_link_class.class, + .ac.grp = &ata_link_attr_group, + .ac.match = ata_tlink_match, +}; + +static struct transport_container ata_dev_attr_cont = { + .ac.class = &ata_dev_class.class, + .ac.grp = &ata_device_attr_group, + .ac.match = ata_tdev_match, +}; + +static int ata_tlink_match(struct attribute_container *cont, + struct device *dev) +{ + if (!ata_is_link(dev)) + return 0; + + return &ata_link_attr_cont.ac == cont; +} + +static int ata_tdev_match(struct attribute_container *cont, + struct device *dev) +{ + if (!ata_is_ata_dev(dev)) + return 0; + + return &ata_dev_attr_cont.ac == cont; +} + /* * Setup / Teardown code */ -#define SETUP_TEMPLATE(attrb, field, perm, test) \ - i->private_##attrb[count] = dev_attr_##field; \ - i->private_##attrb[count].attr.mode = perm; \ - i->attrb[count] = &i->private_##attrb[count]; \ - if (test) \ - count++ - -#define SETUP_LINK_ATTRIBUTE(field) \ - SETUP_TEMPLATE(link_attrs, field, S_IRUGO, 1) - -#define SETUP_PORT_ATTRIBUTE(field) \ - SETUP_TEMPLATE(port_attrs, field, S_IRUGO, 1) - -#define SETUP_DEV_ATTRIBUTE(field) \ - SETUP_TEMPLATE(dev_attrs, field, S_IRUGO, 1) - -/** - * ata_attach_transport -- instantiate ATA transport template - */ -struct scsi_transport_template *ata_attach_transport(void) -{ - struct ata_internal *i; - int count; - - i = kzalloc_obj(struct ata_internal); - if (!i) - return NULL; - - i->t.eh_strategy_handler = ata_scsi_error; - i->t.user_scan = ata_scsi_user_scan; - - i->t.host_attrs.ac.attrs = &i->port_attrs[0]; - i->t.host_attrs.ac.class = &ata_port_class.class; - i->t.host_attrs.ac.match = ata_tport_match; - transport_container_register(&i->t.host_attrs); - - i->link_attr_cont.ac.class = &ata_link_class.class; - i->link_attr_cont.ac.attrs = &i->link_attrs[0]; - i->link_attr_cont.ac.match = ata_tlink_match; - transport_container_register(&i->link_attr_cont); - - i->dev_attr_cont.ac.class = &ata_dev_class.class; - i->dev_attr_cont.ac.attrs = &i->dev_attrs[0]; - i->dev_attr_cont.ac.match = ata_tdev_match; - transport_container_register(&i->dev_attr_cont); - - count = 0; - SETUP_PORT_ATTRIBUTE(nr_pmp_links); - SETUP_PORT_ATTRIBUTE(idle_irq); - SETUP_PORT_ATTRIBUTE(port_no); - BUG_ON(count > ATA_PORT_ATTRS); - i->port_attrs[count] = NULL; - - count = 0; - SETUP_LINK_ATTRIBUTE(hw_sata_spd_limit); - SETUP_LINK_ATTRIBUTE(sata_spd_limit); - SETUP_LINK_ATTRIBUTE(sata_spd); - BUG_ON(count > ATA_LINK_ATTRS); - i->link_attrs[count] = NULL; - - count = 0; - SETUP_DEV_ATTRIBUTE(class); - SETUP_DEV_ATTRIBUTE(pio_mode); - SETUP_DEV_ATTRIBUTE(dma_mode); - SETUP_DEV_ATTRIBUTE(xfer_mode); - SETUP_DEV_ATTRIBUTE(spdn_cnt); - SETUP_DEV_ATTRIBUTE(ering); - SETUP_DEV_ATTRIBUTE(id); - SETUP_DEV_ATTRIBUTE(gscr); - SETUP_DEV_ATTRIBUTE(trim); - BUG_ON(count > ATA_DEV_ATTRS); - i->dev_attrs[count] = NULL; - - return &i->t; -} - -/** - * ata_release_transport -- release ATA transport template instance - * @t: transport template instance - */ -void ata_release_transport(struct scsi_transport_template *t) -{ - struct ata_internal *i = to_ata_internal(t); - - transport_container_unregister(&i->t.host_attrs); - transport_container_unregister(&i->link_attr_cont); - transport_container_unregister(&i->dev_attr_cont); - - kfree(i); -} - __init int libata_transport_init(void) { int error; @@ -838,6 +775,11 @@ __init int libata_transport_init(void) error = transport_class_register(&ata_dev_class); if (error) goto out_unregister_port; + + transport_container_register(&ata_scsi_transportt.host_attrs); + transport_container_register(&ata_link_attr_cont); + transport_container_register(&ata_dev_attr_cont); + return 0; out_unregister_port: @@ -851,6 +793,10 @@ __init int libata_transport_init(void) void __exit libata_transport_exit(void) { + transport_container_unregister(&ata_scsi_transportt.host_attrs); + transport_container_unregister(&ata_link_attr_cont); + transport_container_unregister(&ata_dev_attr_cont); + transport_class_unregister(&ata_link_class); transport_class_unregister(&ata_port_class); transport_class_unregister(&ata_dev_class); diff --git a/drivers/ata/libata-transport.h b/drivers/ata/libata-transport.h index 50cd2cbe8eea..629ac843a873 100644 --- a/drivers/ata/libata-transport.h +++ b/drivers/ata/libata-transport.h @@ -3,14 +3,11 @@ #define _LIBATA_TRANSPORT_H -extern struct scsi_transport_template *ata_scsi_transport_template; +extern struct scsi_transport_template ata_scsi_transportt; int ata_tlink_add(struct ata_link *link); void ata_tlink_delete(struct ata_link *link); -struct scsi_transport_template *ata_attach_transport(void); -void ata_release_transport(struct scsi_transport_template *t); - __init int libata_transport_init(void); void __exit libata_transport_exit(void); #endif diff --git a/drivers/ata/pata_arasan_cf.c b/drivers/ata/pata_arasan_cf.c index 514d549286b5..b1e281b64f57 100644 --- a/drivers/ata/pata_arasan_cf.c +++ b/drivers/ata/pata_arasan_cf.c @@ -380,7 +380,7 @@ static inline int wait4buf(struct arasan_cf_dev *acdev) if (!wait_for_completion_timeout(&acdev->cf_completion, TIMEOUT)) { u32 rw = acdev->qc->tf.flags & ATA_TFLAG_WRITE; - dev_err(acdev->host->dev, "%s TimeOut", rw ? "write" : "read"); + dev_err(acdev->host->dev, "%s TimeOut\n", rw ? "write" : "read"); return -ETIMEDOUT; } @@ -474,7 +474,7 @@ static int sg_xfer(struct arasan_cf_dev *acdev, struct scatterlist *sg) dma_len = min(xfer_cnt, FIFO_SIZE); ret = dma_xfer(acdev, src, dest, dma_len); if (ret) { - dev_err(acdev->host->dev, "dma failed"); + dev_err(acdev->host->dev, "dma failed\n"); goto fail; } diff --git a/include/linux/libata.h b/include/linux/libata.h index 00346ce3af5e..5c085ef4eda7 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -1205,7 +1205,6 @@ extern unsigned int ata_do_dev_read_id(struct ata_device *dev, struct ata_taskfile *tf, __le16 *id); extern void ata_qc_complete(struct ata_queued_cmd *qc); extern u64 ata_qc_get_active(struct ata_port *ap); -extern void ata_scsi_simulate(struct ata_device *dev, struct scsi_cmnd *cmd); extern int ata_std_bios_param(struct scsi_device *sdev, struct gendisk *unused, sector_t capacity, int geom[]); @@ -1226,7 +1225,8 @@ extern int ata_ncq_prio_enable(struct ata_port *ap, struct scsi_device *sdev, extern struct ata_device *ata_dev_pair(struct ata_device *adev); int ata_set_mode(struct ata_link *link, struct ata_device **r_failed_dev); extern void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap); -extern void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap, struct list_head *eh_q); +int ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap, + struct list_head *eh_q); /* * SATA specific code - drivers/ata/libata-sata.c