Commit d9027470 authored by Gwendal Grignou's avatar Gwendal Grignou Committed by Jeff Garzik

[libata] Add ATA transport class

This is a scheleton for libata transport class.
All information is read only, exporting information from libata:
- ata_port class: one per ATA port
- ata_link class: one per ATA port or 15 for SATA Port Multiplier
- ata_device class: up to 2 for PATA link, usually one for SATA.
Signed-off-by: default avatarGwendal Grignou <gwendal@google.com>
Reviewed-by: default avatarGrant Grundler <grundler@google.com>
Signed-off-by: default avatarJeff Garzik <jgarzik@redhat.com>
parent f6f94e2a
What: /sys/class/ata_...
Date: August 2008
Contact: Gwendal Grignou<gwendal@google.com>
Description:
Provide a place in sysfs for storing the ATA topology of the system. This allows
retrieving various information about ATA objects.
Files under /sys/class/ata_port
-------------------------------
For each port, a directory ataX is created where X is the ata_port_id of
the port. The device parent is the ata host device.
idle_irq (read)
Number of IRQ received by the port while idle [some ata HBA only].
nr_pmp_links (read)
If a SATA Port Multiplier (PM) is connected, number of link behind it.
Files under /sys/class/ata_link
-------------------------------
Behind each port, there is a ata_link. If there is a SATA PM in the
topology, 15 ata_link objects are created.
If a link is behind a port, the directory name is linkX, where X is
ata_port_id of the port.
If a link is behind a PM, its name is linkX.Y where X is ata_port_id
of the parent port and Y the PM port.
hw_sata_spd_limit
Maximum speed supported by the connected SATA device.
sata_spd_limit
Maximum speed imposed by libata.
sata_spd
Current speed of the link [1.5, 3Gps,...].
Files under /sys/class/ata_device
---------------------------------
Behind each link, up to two ata device are created.
The name of the directory is devX[.Y].Z where:
- X is ata_port_id of the port where the device is connected,
- Y the port of the PM if any, and
- Z the device id: for PATA, there is usually 2 devices [0,1],
only 1 for SATA.
class
Device class. Can be "ata" for disk, "atapi" for packet device,
"pmp" for PM, or "none" if no device was found behind the link.
dma_mode
Transfer modes supported by the device when in DMA mode.
Mostly used by PATA device.
pio_mode
Transfer modes supported by the device when in PIO mode.
Mostly used by PATA device.
xfer_mode
Current transfer mode.
id
Cached result of IDENTIFY command, as described in ATA8 7.16 and 7.17.
Only valid if the device is not a PM.
gscr
Cached result of the dump of PM GSCR register.
Valid registers are:
0: SATA_PMP_GSCR_PROD_ID,
1: SATA_PMP_GSCR_REV,
2: SATA_PMP_GSCR_PORT_INFO,
32: SATA_PMP_GSCR_ERROR,
33: SATA_PMP_GSCR_ERROR_EN,
64: SATA_PMP_GSCR_FEAT,
96: SATA_PMP_GSCR_FEAT_EN,
130: SATA_PMP_GSCR_SII_GPIO
Only valid if the device is a PM.
spdn_cnt
Number of time libata decided to lower the speed of link due to errors.
ering
Formatted output of the error ring of the device.
...@@ -99,7 +99,7 @@ obj-$(CONFIG_ATA_GENERIC) += ata_generic.o ...@@ -99,7 +99,7 @@ obj-$(CONFIG_ATA_GENERIC) += ata_generic.o
# Should be last libata driver # Should be last libata driver
obj-$(CONFIG_PATA_LEGACY) += pata_legacy.o obj-$(CONFIG_PATA_LEGACY) += pata_legacy.o
libata-objs := libata-core.o libata-scsi.o libata-eh.o libata-objs := libata-core.o libata-scsi.o libata-eh.o libata-transport.o
libata-$(CONFIG_ATA_SFF) += libata-sff.o libata-$(CONFIG_ATA_SFF) += libata-sff.o
libata-$(CONFIG_SATA_PMP) += libata-pmp.o libata-$(CONFIG_SATA_PMP) += libata-pmp.o
libata-$(CONFIG_ATA_ACPI) += libata-acpi.o libata-$(CONFIG_ATA_ACPI) += libata-acpi.o
...@@ -68,7 +68,7 @@ ...@@ -68,7 +68,7 @@
#include <linux/ratelimit.h> #include <linux/ratelimit.h>
#include "libata.h" #include "libata.h"
#include "libata-transport.h"
/* debounce timing parameters in msecs { interval, duration, timeout } */ /* debounce timing parameters in msecs { interval, duration, timeout } */
const unsigned long sata_deb_timing_normal[] = { 5, 100, 2000 }; const unsigned long sata_deb_timing_normal[] = { 5, 100, 2000 };
...@@ -1017,7 +1017,7 @@ const char *ata_mode_string(unsigned long xfer_mask) ...@@ -1017,7 +1017,7 @@ const char *ata_mode_string(unsigned long xfer_mask)
return "<n/a>"; return "<n/a>";
} }
static const char *sata_spd_string(unsigned int spd) const char *sata_spd_string(unsigned int spd)
{ {
static const char * const spd_str[] = { static const char * const spd_str[] = {
"1.5 Gbps", "1.5 Gbps",
...@@ -5517,7 +5517,8 @@ void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp) ...@@ -5517,7 +5517,8 @@ void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp)
int i; int i;
/* clear everything except for devices */ /* clear everything except for devices */
memset(link, 0, offsetof(struct ata_link, device[0])); memset((void *)link + ATA_LINK_CLEAR_BEGIN, 0,
ATA_LINK_CLEAR_END - ATA_LINK_CLEAR_BEGIN);
link->ap = ap; link->ap = ap;
link->pmp = pmp; link->pmp = pmp;
...@@ -5591,7 +5592,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host) ...@@ -5591,7 +5592,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
ap = kzalloc(sizeof(*ap), GFP_KERNEL); ap = kzalloc(sizeof(*ap), GFP_KERNEL);
if (!ap) if (!ap)
return NULL; return NULL;
ap->pflags |= ATA_PFLAG_INITIALIZING; ap->pflags |= ATA_PFLAG_INITIALIZING;
ap->lock = &host->lock; ap->lock = &host->lock;
ap->print_id = -1; ap->print_id = -1;
...@@ -6093,9 +6094,18 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) ...@@ -6093,9 +6094,18 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
for (i = 0; i < host->n_ports; i++) for (i = 0; i < host->n_ports; i++)
host->ports[i]->print_id = ata_print_id++; host->ports[i]->print_id = ata_print_id++;
/* Create associated sysfs transport objects */
for (i = 0; i < host->n_ports; i++) {
rc = ata_tport_add(host->dev,host->ports[i]);
if (rc) {
goto err_tadd;
}
}
rc = ata_scsi_add_hosts(host, sht); rc = ata_scsi_add_hosts(host, sht);
if (rc) if (rc)
return rc; goto err_tadd;
/* associate with ACPI nodes */ /* associate with ACPI nodes */
ata_acpi_associate(host); ata_acpi_associate(host);
...@@ -6136,6 +6146,13 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) ...@@ -6136,6 +6146,13 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
} }
return 0; return 0;
err_tadd:
while (--i >= 0) {
ata_tport_delete(host->ports[i]);
}
return rc;
} }
/** /**
...@@ -6226,6 +6243,13 @@ static void ata_port_detach(struct ata_port *ap) ...@@ -6226,6 +6243,13 @@ static void ata_port_detach(struct ata_port *ap)
cancel_rearming_delayed_work(&ap->hotplug_task); cancel_rearming_delayed_work(&ap->hotplug_task);
skip_eh: skip_eh:
if (ap->pmp_link) {
int i;
for (i = 0; i < SATA_PMP_MAX_PORTS; i++)
ata_tlink_delete(&ap->pmp_link[i]);
}
ata_tport_delete(ap);
/* remove the associated SCSI host */ /* remove the associated SCSI host */
scsi_remove_host(ap->scsi_host); scsi_remove_host(ap->scsi_host);
} }
...@@ -6542,7 +6566,7 @@ static void __init ata_parse_force_param(void) ...@@ -6542,7 +6566,7 @@ static void __init ata_parse_force_param(void)
static int __init ata_init(void) static int __init ata_init(void)
{ {
int rc = -ENOMEM; int rc;
ata_parse_force_param(); ata_parse_force_param();
...@@ -6552,12 +6576,25 @@ static int __init ata_init(void) ...@@ -6552,12 +6576,25 @@ static int __init ata_init(void)
return rc; return rc;
} }
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"); printk(KERN_DEBUG "libata version " DRV_VERSION " loaded.\n");
return 0; return 0;
err_out:
return rc;
} }
static void __exit ata_exit(void) static void __exit ata_exit(void)
{ {
ata_release_transport(ata_scsi_transport_template);
libata_transport_exit();
ata_sff_exit(); ata_sff_exit();
kfree(ata_force_tbl); kfree(ata_force_tbl);
} }
......
...@@ -57,6 +57,7 @@ enum { ...@@ -57,6 +57,7 @@ enum {
/* error flags */ /* error flags */
ATA_EFLAG_IS_IO = (1 << 0), ATA_EFLAG_IS_IO = (1 << 0),
ATA_EFLAG_DUBIOUS_XFER = (1 << 1), ATA_EFLAG_DUBIOUS_XFER = (1 << 1),
ATA_EFLAG_OLD_ER = (1 << 31),
/* error categories */ /* error categories */
ATA_ECAT_NONE = 0, ATA_ECAT_NONE = 0,
...@@ -396,14 +397,9 @@ static struct ata_ering_entry *ata_ering_top(struct ata_ering *ering) ...@@ -396,14 +397,9 @@ static struct ata_ering_entry *ata_ering_top(struct ata_ering *ering)
return NULL; return NULL;
} }
static void ata_ering_clear(struct ata_ering *ering) int ata_ering_map(struct ata_ering *ering,
{ int (*map_fn)(struct ata_ering_entry *, void *),
memset(ering, 0, sizeof(*ering)); void *arg)
}
static int ata_ering_map(struct ata_ering *ering,
int (*map_fn)(struct ata_ering_entry *, void *),
void *arg)
{ {
int idx, rc = 0; int idx, rc = 0;
struct ata_ering_entry *ent; struct ata_ering_entry *ent;
...@@ -422,6 +418,17 @@ static int ata_ering_map(struct ata_ering *ering, ...@@ -422,6 +418,17 @@ static int ata_ering_map(struct ata_ering *ering,
return rc; return rc;
} }
int ata_ering_clear_cb(struct ata_ering_entry *ent, void *void_arg)
{
ent->eflags |= ATA_EFLAG_OLD_ER;
return 0;
}
static void ata_ering_clear(struct ata_ering *ering)
{
ata_ering_map(ering, ata_ering_clear_cb, NULL);
}
static unsigned int ata_eh_dev_action(struct ata_device *dev) static unsigned int ata_eh_dev_action(struct ata_device *dev)
{ {
struct ata_eh_context *ehc = &dev->link->eh_context; struct ata_eh_context *ehc = &dev->link->eh_context;
...@@ -572,19 +579,19 @@ void ata_scsi_error(struct Scsi_Host *host) ...@@ -572,19 +579,19 @@ void ata_scsi_error(struct Scsi_Host *host)
int nr_timedout = 0; int nr_timedout = 0;
spin_lock_irqsave(ap->lock, flags); spin_lock_irqsave(ap->lock, flags);
/* This must occur under the ap->lock as we don't want /* This must occur under the ap->lock as we don't want
a polled recovery to race the real interrupt handler a polled recovery to race the real interrupt handler
The lost_interrupt handler checks for any completed but The lost_interrupt handler checks for any completed but
non-notified command and completes much like an IRQ handler. non-notified command and completes much like an IRQ handler.
We then fall into the error recovery code which will treat We then fall into the error recovery code which will treat
this as if normal completion won the race */ this as if normal completion won the race */
if (ap->ops->lost_interrupt) if (ap->ops->lost_interrupt)
ap->ops->lost_interrupt(ap); ap->ops->lost_interrupt(ap);
list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) { list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) {
struct ata_queued_cmd *qc; struct ata_queued_cmd *qc;
...@@ -628,7 +635,7 @@ void ata_scsi_error(struct Scsi_Host *host) ...@@ -628,7 +635,7 @@ void ata_scsi_error(struct Scsi_Host *host)
ap->eh_tries = ATA_EH_MAX_TRIES; ap->eh_tries = ATA_EH_MAX_TRIES;
} else } else
spin_unlock_wait(ap->lock); spin_unlock_wait(ap->lock);
/* If we timed raced normal completion and there is nothing to /* If we timed raced normal completion and there is nothing to
recover nr_timedout == 0 why exactly are we doing error recovery ? */ recover nr_timedout == 0 why exactly are we doing error recovery ? */
...@@ -1755,7 +1762,7 @@ static int speed_down_verdict_cb(struct ata_ering_entry *ent, void *void_arg) ...@@ -1755,7 +1762,7 @@ static int speed_down_verdict_cb(struct ata_ering_entry *ent, void *void_arg)
struct speed_down_verdict_arg *arg = void_arg; struct speed_down_verdict_arg *arg = void_arg;
int cat; int cat;
if (ent->timestamp < arg->since) if ((ent->eflags & ATA_EFLAG_OLD_ER) || (ent->timestamp < arg->since))
return -1; return -1;
cat = ata_eh_categorize_error(ent->eflags, ent->err_mask, cat = ata_eh_categorize_error(ent->eflags, ent->err_mask,
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include <linux/libata.h> #include <linux/libata.h>
#include <linux/slab.h> #include <linux/slab.h>
#include "libata.h" #include "libata.h"
#include "libata-transport.h"
const struct ata_port_operations sata_pmp_port_ops = { const struct ata_port_operations sata_pmp_port_ops = {
.inherits = &sata_port_ops, .inherits = &sata_port_ops,
...@@ -312,10 +313,10 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info) ...@@ -312,10 +313,10 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info)
return rc; return rc;
} }
static int sata_pmp_init_links(struct ata_port *ap, int nr_ports) static int sata_pmp_init_links (struct ata_port *ap, int nr_ports)
{ {
struct ata_link *pmp_link = ap->pmp_link; struct ata_link *pmp_link = ap->pmp_link;
int i; int i, err;
if (!pmp_link) { if (!pmp_link) {
pmp_link = kzalloc(sizeof(pmp_link[0]) * SATA_PMP_MAX_PORTS, pmp_link = kzalloc(sizeof(pmp_link[0]) * SATA_PMP_MAX_PORTS,
...@@ -327,6 +328,13 @@ static int sata_pmp_init_links(struct ata_port *ap, int nr_ports) ...@@ -327,6 +328,13 @@ static int sata_pmp_init_links(struct ata_port *ap, int nr_ports)
ata_link_init(ap, &pmp_link[i], i); ata_link_init(ap, &pmp_link[i], i);
ap->pmp_link = pmp_link; ap->pmp_link = pmp_link;
for (i = 0; i < SATA_PMP_MAX_PORTS; i++) {
err = ata_tlink_add(&pmp_link[i]);
if (err) {
goto err_tlink;
}
}
} }
for (i = 0; i < nr_ports; i++) { for (i = 0; i < nr_ports; i++) {
...@@ -339,6 +347,12 @@ static int sata_pmp_init_links(struct ata_port *ap, int nr_ports) ...@@ -339,6 +347,12 @@ static int sata_pmp_init_links(struct ata_port *ap, int nr_ports)
} }
return 0; return 0;
err_tlink:
while (--i >= 0)
ata_tlink_delete(&pmp_link[i]);
kfree(pmp_link);
ap->pmp_link = NULL;
return err;
} }
static void sata_pmp_quirks(struct ata_port *ap) static void sata_pmp_quirks(struct ata_port *ap)
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include "libata.h" #include "libata.h"
#include "libata-transport.h"
#define SECTOR_SIZE 512 #define SECTOR_SIZE 512
#define ATA_SCSI_RBUF_SIZE 4096 #define ATA_SCSI_RBUF_SIZE 4096
...@@ -64,9 +65,6 @@ static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap, ...@@ -64,9 +65,6 @@ static struct ata_device *__ata_scsi_find_dev(struct ata_port *ap,
const struct scsi_device *scsidev); const struct scsi_device *scsidev);
static struct ata_device *ata_scsi_find_dev(struct ata_port *ap, static struct ata_device *ata_scsi_find_dev(struct ata_port *ap,
const struct scsi_device *scsidev); const struct scsi_device *scsidev);
static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
unsigned int id, unsigned int lun);
#define RW_RECOVERY_MPAGE 0x1 #define RW_RECOVERY_MPAGE 0x1
#define RW_RECOVERY_MPAGE_LEN 12 #define RW_RECOVERY_MPAGE_LEN 12
...@@ -106,17 +104,6 @@ static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = { ...@@ -106,17 +104,6 @@ static const u8 def_control_mpage[CONTROL_MPAGE_LEN] = {
0, 30 /* extended self test time, see 05-359r1 */ 0, 30 /* extended self test time, see 05-359r1 */
}; };
/*
* libata transport template. libata doesn't do real transport stuff.
* It just needs the eh_timed_out hook.
*/
static struct scsi_transport_template ata_scsi_transport_template = {
.eh_strategy_handler = ata_scsi_error,
.eh_timed_out = ata_scsi_timed_out,
.user_scan = ata_scsi_user_scan,
};
static const struct { static const struct {
enum link_pm value; enum link_pm value;
const char *name; const char *name;
...@@ -3334,7 +3321,7 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht) ...@@ -3334,7 +3321,7 @@ int ata_scsi_add_hosts(struct ata_host *host, struct scsi_host_template *sht)
*(struct ata_port **)&shost->hostdata[0] = ap; *(struct ata_port **)&shost->hostdata[0] = ap;
ap->scsi_host = shost; ap->scsi_host = shost;
shost->transportt = &ata_scsi_transport_template; shost->transportt = ata_scsi_transport_template;
shost->unique_id = ap->print_id; shost->unique_id = ap->print_id;
shost->max_id = 16; shost->max_id = 16;
shost->max_lun = 1; shost->max_lun = 1;
...@@ -3616,8 +3603,8 @@ void ata_scsi_hotplug(struct work_struct *work) ...@@ -3616,8 +3603,8 @@ void ata_scsi_hotplug(struct work_struct *work)
* RETURNS: * RETURNS:
* Zero. * Zero.
*/ */
static int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel, int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
unsigned int id, unsigned int lun) unsigned int id, unsigned int lun)
{ {
struct ata_port *ap = ata_shost_to_port(shost); struct ata_port *ap = ata_shost_to_port(shost);
unsigned long flags; unsigned long flags;
......
This diff is collapsed.
#ifndef _LIBATA_TRANSPORT_H
#define _LIBATA_TRANSPORT_H
extern struct scsi_transport_template *ata_scsi_transport_template;
int ata_tlink_add(struct ata_link *link);
void ata_tlink_delete(struct ata_link *link);
int ata_tport_add(struct device *parent, struct ata_port *ap);
void ata_tport_delete(struct ata_port *ap);
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
...@@ -102,6 +102,7 @@ extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg); ...@@ -102,6 +102,7 @@ extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
extern struct ata_port *ata_port_alloc(struct ata_host *host); extern struct ata_port *ata_port_alloc(struct ata_host *host);
extern void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy); extern void ata_dev_enable_pm(struct ata_device *dev, enum link_pm policy);
extern void ata_lpm_schedule(struct ata_port *ap, enum link_pm); extern void ata_lpm_schedule(struct ata_port *ap, enum link_pm);
extern const char *sata_spd_string(unsigned int spd);
/* libata-acpi.c */ /* libata-acpi.c */
#ifdef CONFIG_ATA_ACPI #ifdef CONFIG_ATA_ACPI
...@@ -137,6 +138,9 @@ extern void ata_scsi_hotplug(struct work_struct *work); ...@@ -137,6 +138,9 @@ extern void ata_scsi_hotplug(struct work_struct *work);
extern void ata_schedule_scsi_eh(struct Scsi_Host *shost); extern void ata_schedule_scsi_eh(struct Scsi_Host *shost);
extern void ata_scsi_dev_rescan(struct work_struct *work); extern void ata_scsi_dev_rescan(struct work_struct *work);
extern int ata_bus_probe(struct ata_port *ap); extern int ata_bus_probe(struct ata_port *ap);
extern int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
unsigned int id, unsigned int lun);
/* libata-eh.c */ /* libata-eh.c */
extern unsigned long ata_internal_cmd_timeout(struct ata_device *dev, u8 cmd); extern unsigned long ata_internal_cmd_timeout(struct ata_device *dev, u8 cmd);
...@@ -164,6 +168,9 @@ extern int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset, ...@@ -164,6 +168,9 @@ extern int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
ata_postreset_fn_t postreset, ata_postreset_fn_t postreset,
struct ata_link **r_failed_disk); struct ata_link **r_failed_disk);
extern void ata_eh_finish(struct ata_port *ap); extern void ata_eh_finish(struct ata_port *ap);
extern int ata_ering_map(struct ata_ering *ering,
int (*map_fn)(struct ata_ering_entry *, void *),
void *arg);
/* libata-pmp.c */ /* libata-pmp.c */
#ifdef CONFIG_SATA_PMP #ifdef CONFIG_SATA_PMP
......
...@@ -604,6 +604,7 @@ struct ata_device { ...@@ -604,6 +604,7 @@ struct ata_device {
union acpi_object *gtf_cache; union acpi_object *gtf_cache;
unsigned int gtf_filter; unsigned int gtf_filter;
#endif #endif
struct device tdev;
/* n_sector is CLEAR_BEGIN, read comment above CLEAR_BEGIN */ /* n_sector is CLEAR_BEGIN, read comment above CLEAR_BEGIN */
u64 n_sectors; /* size of device, if ATA */ u64 n_sectors; /* size of device, if ATA */
u64 n_native_sectors; /* native size, if ATA */ u64 n_native_sectors; /* native size, if ATA */
...@@ -690,6 +691,7 @@ struct ata_link { ...@@ -690,6 +691,7 @@ struct ata_link {
struct ata_port *ap; struct ata_port *ap;
int pmp; /* port multiplier port # */ int pmp; /* port multiplier port # */
struct device tdev;
unsigned int active_tag; /* active tag on this link */ unsigned int active_tag; /* active tag on this link */
u32 sactive; /* active NCQ commands */ u32 sactive; /* active NCQ commands */
...@@ -707,6 +709,8 @@ struct ata_link { ...@@ -707,6 +709,8 @@ struct ata_link {
struct ata_device device[ATA_MAX_DEVICES]; struct ata_device device[ATA_MAX_DEVICES];
}; };
#define ATA_LINK_CLEAR_BEGIN offsetof(struct ata_link, active_tag)
#define ATA_LINK_CLEAR_END offsetof(struct ata_link, device[0])
struct ata_port { struct ata_port {
struct Scsi_Host *scsi_host; /* our co-allocated scsi host */ struct Scsi_Host *scsi_host; /* our co-allocated scsi host */
...@@ -752,6 +756,7 @@ struct ata_port { ...@@ -752,6 +756,7 @@ struct ata_port {
struct ata_port_stats stats; struct ata_port_stats stats;
struct ata_host *host; struct ata_host *host;
struct device *dev; struct device *dev;
struct device tdev;
struct mutex scsi_scan_mutex; struct mutex scsi_scan_mutex;
struct delayed_work hotplug_task; struct delayed_work hotplug_task;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment