Merge tag 'ata-7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux

Pull ata updates from Niklas Cassel:

 - Misc code cleanups related to tag checking and tag command completion
   (Damien)

 - Remove Baikal bt1-ahci DT binding since the upstreaming for this SoC
   is not going to be finalized (Andy)

 - Only call the libata port error handler from the SCSI error handler
   if there were command timeouts or if EH was scheduled for the port
   (Damien)

 - Refactor ata_scsiop_maint_in() to more clearly show that there is
   only one service action implemented for the MAINTENANCE IN command
   (me)

 - Clean up the handling of sysfs attributes exposed by libata (Heiner)

 - Let libahci_platform use a flexible array member for platform PHYs to
   avoid multiple allocations (Rosen)

 - Do not retry reset if the device has been removed/hot-unplugged
   (Igor)

 - Add missing newlines to error prints in pata_arasan_cf driver (Haoyu)

 - Use the correct SCSI host byte when completing deferred ATA
   PASS-THROUGH commands, to avoid the SCSI mid-layer from failing the
   commands instead of requeuing (Igor)

* tag 'ata-7.1-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/libata/linux:
  ata: libata-scsi: fix requeue of deferred ATA PASS-THROUGH commands
  ata: pata_arasan_cf: fix missing newline in dev_err() messages
  ata: libata-transport: remove static variable ata_scsi_transport_template
  ata: libata-transport: split struct ata_internal
  ata: libata-transport: use static struct ata_transport_internal to simplify match functions
  ata: libata-transport: inline ata_attach|release_transport
  ata: libata-transport: instantiate struct ata_internal statically
  ata: libata-eh: Do not retry reset if the device is gone
  ata: libahci_platform: use flex array for platform PHYs
  ata: libata-transport: remove redundant dynamic sysfs attributes
  ata: libata-scsi: refactor ata_scsiop_maint_in()
  ata: libata-eh: avoid unnecessary calls to ata_scsi_port_error_handler()
  ata: ahci-dwc: Remove not-going-to-be-supported code for Baikal SoC
  ata: libata-scsi: rename and improve ata_qc_done()
  ata: libata-scsi: make ata_scsi_simulate() static
  ata: libata-scsi: simplify ata_scsi_requeue_deferred_qc()
  ata: libata-sata: simplify ata_sas_queuecmd()
  ata: libata-core: improve tag checks in ata_qc_issue()
This commit is contained in:
Linus Torvalds
2026-04-15 15:03:01 -07:00
13 changed files with 265 additions and 484 deletions

View File

@@ -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 <fancer.lancer@gmail.com>
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>;
};
};
...

View File

@@ -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.

View File

@@ -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);
};
/*

View File

@@ -13,12 +13,10 @@
#include <linux/kernel.h>
#include <linux/libata.h>
#include <linux/log2.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
#include <linux/regmap.h>
#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);

View File

@@ -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

View File

@@ -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();

View File

@@ -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

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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