aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/libata.h
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2008-07-31 04:02:43 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-09-29 00:25:28 -0400
commitb1c72916abbdd0a55015c87358536ca0ebaf6735 (patch)
tree1064fe92f2c3600dd6587c880d907020896b3348 /include/linux/libata.h
parentb5b3fa386b8f96c7fa92e507e5deddc2637924b4 (diff)
libata: implement slave_link
Explanation taken from the comment of ata_slave_link_init(). In libata, a port contains links and a link contains devices. There is single host link but if a PMP is attached to it, there can be multiple fan-out links. On SATA, there's usually a single device connected to a link but PATA and SATA controllers emulating TF based interface can have two - master and slave. However, there are a few controllers which don't fit into this abstraction too well - SATA controllers which emulate TF interface with both master and slave devices but also have separate SCR register sets for each device. These controllers need separate links for physical link handling (e.g. onlineness, link speed) but should be treated like a traditional M/S controller for everything else (e.g. command issue, softreset). slave_link is libata's way of handling this class of controllers without impacting core layer too much. For anything other than physical link handling, the default host link is used for both master and slave. For physical link handling, separate @ap->slave_link is used. All dirty details are implemented inside libata core layer. From LLD's POV, the only difference is that prereset, hardreset and postreset are called once more for the slave link, so the reset sequence looks like the following. prereset(M) -> prereset(S) -> hardreset(M) -> hardreset(S) -> softreset(M) -> postreset(M) -> postreset(S) Note that softreset is called only for the master. Softreset resets both M/S by definition, so SRST on master should handle both (the standard method will work just fine). As slave_link excludes PMP support and only code paths which deal with the attributes of physical link are affected, all the changes are localized to libata.h, libata-core.c and libata-eh.c. * ata_is_host_link() updated so that slave_link is considered as host link too. * iterator extended to iterate over the slave_link when using the underbarred version. * force param handling updated such that devno 16 is mapped to the slave link/device. * ata_link_on/offline() updated to return the combined result from master and slave link. ata_phys_link_on/offline() are the direct versions. * EH autopsy and report are performed separately for master slave links. Reset is udpated to implement the above described reset sequence. Except for reset update, most changes are minor, many of them just modifying dev->link to ata_dev_phys_link(dev) or using phys online test instead. After this update, LLDs can take full advantage of per-dev SCR registers by simply turning on slave link. Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Diffstat (limited to 'include/linux/libata.h')
-rw-r--r--include/linux/libata.h8
1 files changed, 5 insertions, 3 deletions
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 0c7e6f3c28eb..244ff601559a 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -690,7 +690,8 @@ struct ata_port {
690 unsigned int qc_active; 690 unsigned int qc_active;
691 int nr_active_links; /* #links with active qcs */ 691 int nr_active_links; /* #links with active qcs */
692 692
693 struct ata_link link; /* host default link */ 693 struct ata_link link; /* host default link */
694 struct ata_link *slave_link; /* see ata_slave_link_init() */
694 695
695 int nr_pmp_links; /* nr of available PMP links */ 696 int nr_pmp_links; /* nr of available PMP links */
696 struct ata_link *pmp_link; /* array of PMP links */ 697 struct ata_link *pmp_link; /* array of PMP links */
@@ -897,6 +898,7 @@ extern void ata_port_disable(struct ata_port *);
897extern struct ata_host *ata_host_alloc(struct device *dev, int max_ports); 898extern struct ata_host *ata_host_alloc(struct device *dev, int max_ports);
898extern struct ata_host *ata_host_alloc_pinfo(struct device *dev, 899extern struct ata_host *ata_host_alloc_pinfo(struct device *dev,
899 const struct ata_port_info * const * ppi, int n_ports); 900 const struct ata_port_info * const * ppi, int n_ports);
901extern int ata_slave_link_init(struct ata_port *ap);
900extern int ata_host_start(struct ata_host *host); 902extern int ata_host_start(struct ata_host *host);
901extern int ata_host_register(struct ata_host *host, 903extern int ata_host_register(struct ata_host *host,
902 struct scsi_host_template *sht); 904 struct scsi_host_template *sht);
@@ -1136,7 +1138,7 @@ static inline bool sata_pmp_attached(struct ata_port *ap)
1136 1138
1137static inline int ata_is_host_link(const struct ata_link *link) 1139static inline int ata_is_host_link(const struct ata_link *link)
1138{ 1140{
1139 return link == &link->ap->link; 1141 return link == &link->ap->link || link == link->ap->slave_link;
1140} 1142}
1141#else /* CONFIG_SATA_PMP */ 1143#else /* CONFIG_SATA_PMP */
1142static inline bool sata_pmp_supported(struct ata_port *ap) 1144static inline bool sata_pmp_supported(struct ata_port *ap)
@@ -1169,7 +1171,7 @@ static inline int sata_srst_pmp(struct ata_link *link)
1169 printk("%sata%u: "fmt, lv, (ap)->print_id , ##args) 1171 printk("%sata%u: "fmt, lv, (ap)->print_id , ##args)
1170 1172
1171#define ata_link_printk(link, lv, fmt, args...) do { \ 1173#define ata_link_printk(link, lv, fmt, args...) do { \
1172 if (sata_pmp_attached((link)->ap)) \ 1174 if (sata_pmp_attached((link)->ap) || (link)->ap->slave_link) \
1173 printk("%sata%u.%02u: "fmt, lv, (link)->ap->print_id, \ 1175 printk("%sata%u.%02u: "fmt, lv, (link)->ap->print_id, \
1174 (link)->pmp , ##args); \ 1176 (link)->pmp , ##args); \
1175 else \ 1177 else \