aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libsas
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-10-28 19:44:18 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-10-28 19:44:18 -0400
commitec7ae517537ae5c7b0b2cd7f562dfa3e7a05b954 (patch)
treee6b0c64a51a7c0aa0efd09d4f7a80872e3b1657a /drivers/scsi/libsas
parent97d2eb13a019ec09cc1a7ea2d3705c0b117b3c0d (diff)
parent590134fa78fbdbe5fea78c7ae0b2c3364bc9572f (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6: (204 commits) [SCSI] qla4xxx: export address/port of connection (fix udev disk names) [SCSI] ipr: Fix BUG on adapter dump timeout [SCSI] megaraid_sas: Fix instance access in megasas_reset_timer [SCSI] hpsa: change confusing message to be more clear [SCSI] iscsi class: fix vlan configuration [SCSI] qla4xxx: fix data alignment and use nl helpers [SCSI] iscsi class: fix link local mispelling [SCSI] iscsi class: Replace iscsi_get_next_target_id with IDA [SCSI] aacraid: use lower snprintf() limit [SCSI] lpfc 8.3.27: Change driver version to 8.3.27 [SCSI] lpfc 8.3.27: T10 additions for SLI4 [SCSI] lpfc 8.3.27: Fix queue allocation failure recovery [SCSI] lpfc 8.3.27: Change algorithm for getting physical port name [SCSI] lpfc 8.3.27: Changed worst case mailbox timeout [SCSI] lpfc 8.3.27: Miscellanous logic and interface fixes [SCSI] megaraid_sas: Changelog and version update [SCSI] megaraid_sas: Add driver workaround for PERC5/1068 kdump kernel panic [SCSI] megaraid_sas: Add multiple MSI-X vector/multiple reply queue support [SCSI] megaraid_sas: Add support for MegaRAID 9360/9380 12GB/s controllers [SCSI] megaraid_sas: Clear FUSION_IN_RESET before enabling interrupts ...
Diffstat (limited to 'drivers/scsi/libsas')
-rw-r--r--drivers/scsi/libsas/sas_discover.c13
-rw-r--r--drivers/scsi/libsas/sas_expander.c37
-rw-r--r--drivers/scsi/libsas/sas_host_smp.c103
-rw-r--r--drivers/scsi/libsas/sas_init.c43
-rw-r--r--drivers/scsi/libsas/sas_scsi_host.c145
5 files changed, 234 insertions, 107 deletions
diff --git a/drivers/scsi/libsas/sas_discover.c b/drivers/scsi/libsas/sas_discover.c
index f5831930df9b..54a5199ceb56 100644
--- a/drivers/scsi/libsas/sas_discover.c
+++ b/drivers/scsi/libsas/sas_discover.c
@@ -219,17 +219,20 @@ out_err2:
219 219
220/* ---------- Device registration and unregistration ---------- */ 220/* ---------- Device registration and unregistration ---------- */
221 221
222static inline void sas_unregister_common_dev(struct domain_device *dev) 222static void sas_unregister_common_dev(struct asd_sas_port *port, struct domain_device *dev)
223{ 223{
224 sas_notify_lldd_dev_gone(dev); 224 sas_notify_lldd_dev_gone(dev);
225 if (!dev->parent) 225 if (!dev->parent)
226 dev->port->port_dev = NULL; 226 dev->port->port_dev = NULL;
227 else 227 else
228 list_del_init(&dev->siblings); 228 list_del_init(&dev->siblings);
229
230 spin_lock_irq(&port->dev_list_lock);
229 list_del_init(&dev->dev_list_node); 231 list_del_init(&dev->dev_list_node);
232 spin_unlock_irq(&port->dev_list_lock);
230} 233}
231 234
232void sas_unregister_dev(struct domain_device *dev) 235void sas_unregister_dev(struct asd_sas_port *port, struct domain_device *dev)
233{ 236{
234 if (dev->rphy) { 237 if (dev->rphy) {
235 sas_remove_children(&dev->rphy->dev); 238 sas_remove_children(&dev->rphy->dev);
@@ -241,15 +244,15 @@ void sas_unregister_dev(struct domain_device *dev)
241 kfree(dev->ex_dev.ex_phy); 244 kfree(dev->ex_dev.ex_phy);
242 dev->ex_dev.ex_phy = NULL; 245 dev->ex_dev.ex_phy = NULL;
243 } 246 }
244 sas_unregister_common_dev(dev); 247 sas_unregister_common_dev(port, dev);
245} 248}
246 249
247void sas_unregister_domain_devices(struct asd_sas_port *port) 250void sas_unregister_domain_devices(struct asd_sas_port *port)
248{ 251{
249 struct domain_device *dev, *n; 252 struct domain_device *dev, *n;
250 253
251 list_for_each_entry_safe_reverse(dev,n,&port->dev_list,dev_list_node) 254 list_for_each_entry_safe_reverse(dev, n, &port->dev_list, dev_list_node)
252 sas_unregister_dev(dev); 255 sas_unregister_dev(port, dev);
253 256
254 port->port->rphy = NULL; 257 port->port->rphy = NULL;
255 258
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c
index 16ad97df5ba6..1b831c55ec6e 100644
--- a/drivers/scsi/libsas/sas_expander.c
+++ b/drivers/scsi/libsas/sas_expander.c
@@ -199,6 +199,8 @@ static void sas_set_ex_phy(struct domain_device *dev, int phy_id,
199 phy->virtual = dr->virtual; 199 phy->virtual = dr->virtual;
200 phy->last_da_index = -1; 200 phy->last_da_index = -1;
201 201
202 phy->phy->identify.sas_address = SAS_ADDR(phy->attached_sas_addr);
203 phy->phy->identify.device_type = phy->attached_dev_type;
202 phy->phy->identify.initiator_port_protocols = phy->attached_iproto; 204 phy->phy->identify.initiator_port_protocols = phy->attached_iproto;
203 phy->phy->identify.target_port_protocols = phy->attached_tproto; 205 phy->phy->identify.target_port_protocols = phy->attached_tproto;
204 phy->phy->identify.phy_identifier = phy_id; 206 phy->phy->identify.phy_identifier = phy_id;
@@ -329,6 +331,7 @@ static void ex_assign_report_general(struct domain_device *dev,
329 dev->ex_dev.ex_change_count = be16_to_cpu(rg->change_count); 331 dev->ex_dev.ex_change_count = be16_to_cpu(rg->change_count);
330 dev->ex_dev.max_route_indexes = be16_to_cpu(rg->route_indexes); 332 dev->ex_dev.max_route_indexes = be16_to_cpu(rg->route_indexes);
331 dev->ex_dev.num_phys = min(rg->num_phys, (u8)MAX_EXPANDER_PHYS); 333 dev->ex_dev.num_phys = min(rg->num_phys, (u8)MAX_EXPANDER_PHYS);
334 dev->ex_dev.t2t_supp = rg->t2t_supp;
332 dev->ex_dev.conf_route_table = rg->conf_route_table; 335 dev->ex_dev.conf_route_table = rg->conf_route_table;
333 dev->ex_dev.configuring = rg->configuring; 336 dev->ex_dev.configuring = rg->configuring;
334 memcpy(dev->ex_dev.enclosure_logical_id, rg->enclosure_logical_id, 8); 337 memcpy(dev->ex_dev.enclosure_logical_id, rg->enclosure_logical_id, 8);
@@ -751,7 +754,10 @@ static struct domain_device *sas_ex_discover_end_dev(
751 out_list_del: 754 out_list_del:
752 sas_rphy_free(child->rphy); 755 sas_rphy_free(child->rphy);
753 child->rphy = NULL; 756 child->rphy = NULL;
757
758 spin_lock_irq(&parent->port->dev_list_lock);
754 list_del(&child->dev_list_node); 759 list_del(&child->dev_list_node);
760 spin_unlock_irq(&parent->port->dev_list_lock);
755 out_free: 761 out_free:
756 sas_port_delete(phy->port); 762 sas_port_delete(phy->port);
757 out_err: 763 out_err:
@@ -1133,15 +1139,17 @@ static void sas_print_parent_topology_bug(struct domain_device *child,
1133 }; 1139 };
1134 struct domain_device *parent = child->parent; 1140 struct domain_device *parent = child->parent;
1135 1141
1136 sas_printk("%s ex %016llx phy 0x%x <--> %s ex %016llx phy 0x%x " 1142 sas_printk("%s ex %016llx (T2T supp:%d) phy 0x%x <--> %s ex %016llx "
1137 "has %c:%c routing link!\n", 1143 "(T2T supp:%d) phy 0x%x has %c:%c routing link!\n",
1138 1144
1139 ex_type[parent->dev_type], 1145 ex_type[parent->dev_type],
1140 SAS_ADDR(parent->sas_addr), 1146 SAS_ADDR(parent->sas_addr),
1147 parent->ex_dev.t2t_supp,
1141 parent_phy->phy_id, 1148 parent_phy->phy_id,
1142 1149
1143 ex_type[child->dev_type], 1150 ex_type[child->dev_type],
1144 SAS_ADDR(child->sas_addr), 1151 SAS_ADDR(child->sas_addr),
1152 child->ex_dev.t2t_supp,
1145 child_phy->phy_id, 1153 child_phy->phy_id,
1146 1154
1147 ra_char[parent_phy->routing_attr], 1155 ra_char[parent_phy->routing_attr],
@@ -1238,10 +1246,15 @@ static int sas_check_parent_topology(struct domain_device *child)
1238 sas_print_parent_topology_bug(child, parent_phy, child_phy); 1246 sas_print_parent_topology_bug(child, parent_phy, child_phy);
1239 res = -ENODEV; 1247 res = -ENODEV;
1240 } 1248 }
1241 } else if (parent_phy->routing_attr == TABLE_ROUTING && 1249 } else if (parent_phy->routing_attr == TABLE_ROUTING) {
1242 child_phy->routing_attr != SUBTRACTIVE_ROUTING) { 1250 if (child_phy->routing_attr == SUBTRACTIVE_ROUTING ||
1243 sas_print_parent_topology_bug(child, parent_phy, child_phy); 1251 (child_phy->routing_attr == TABLE_ROUTING &&
1244 res = -ENODEV; 1252 child_ex->t2t_supp && parent_ex->t2t_supp)) {
1253 /* All good */;
1254 } else {
1255 sas_print_parent_topology_bug(child, parent_phy, child_phy);
1256 res = -ENODEV;
1257 }
1245 } 1258 }
1246 break; 1259 break;
1247 case FANOUT_DEV: 1260 case FANOUT_DEV:
@@ -1729,7 +1742,7 @@ out:
1729 return res; 1742 return res;
1730} 1743}
1731 1744
1732static void sas_unregister_ex_tree(struct domain_device *dev) 1745static void sas_unregister_ex_tree(struct asd_sas_port *port, struct domain_device *dev)
1733{ 1746{
1734 struct expander_device *ex = &dev->ex_dev; 1747 struct expander_device *ex = &dev->ex_dev;
1735 struct domain_device *child, *n; 1748 struct domain_device *child, *n;
@@ -1738,11 +1751,11 @@ static void sas_unregister_ex_tree(struct domain_device *dev)
1738 child->gone = 1; 1751 child->gone = 1;
1739 if (child->dev_type == EDGE_DEV || 1752 if (child->dev_type == EDGE_DEV ||
1740 child->dev_type == FANOUT_DEV) 1753 child->dev_type == FANOUT_DEV)
1741 sas_unregister_ex_tree(child); 1754 sas_unregister_ex_tree(port, child);
1742 else 1755 else
1743 sas_unregister_dev(child); 1756 sas_unregister_dev(port, child);
1744 } 1757 }
1745 sas_unregister_dev(dev); 1758 sas_unregister_dev(port, dev);
1746} 1759}
1747 1760
1748static void sas_unregister_devs_sas_addr(struct domain_device *parent, 1761static void sas_unregister_devs_sas_addr(struct domain_device *parent,
@@ -1759,9 +1772,9 @@ static void sas_unregister_devs_sas_addr(struct domain_device *parent,
1759 child->gone = 1; 1772 child->gone = 1;
1760 if (child->dev_type == EDGE_DEV || 1773 if (child->dev_type == EDGE_DEV ||
1761 child->dev_type == FANOUT_DEV) 1774 child->dev_type == FANOUT_DEV)
1762 sas_unregister_ex_tree(child); 1775 sas_unregister_ex_tree(parent->port, child);
1763 else 1776 else
1764 sas_unregister_dev(child); 1777 sas_unregister_dev(parent->port, child);
1765 break; 1778 break;
1766 } 1779 }
1767 } 1780 }
diff --git a/drivers/scsi/libsas/sas_host_smp.c b/drivers/scsi/libsas/sas_host_smp.c
index 04ad8dd1a74c..e1aa17840c5b 100644
--- a/drivers/scsi/libsas/sas_host_smp.c
+++ b/drivers/scsi/libsas/sas_host_smp.c
@@ -51,6 +51,91 @@ static void sas_host_smp_discover(struct sas_ha_struct *sas_ha, u8 *resp_data,
51 resp_data[15] = rphy->identify.target_port_protocols; 51 resp_data[15] = rphy->identify.target_port_protocols;
52} 52}
53 53
54/**
55 * to_sas_gpio_gp_bit - given the gpio frame data find the byte/bit position of 'od'
56 * @od: od bit to find
57 * @data: incoming bitstream (from frame)
58 * @index: requested data register index (from frame)
59 * @count: total number of registers in the bitstream (from frame)
60 * @bit: bit position of 'od' in the returned byte
61 *
62 * returns NULL if 'od' is not in 'data'
63 *
64 * From SFF-8485 v0.7:
65 * "In GPIO_TX[1], bit 0 of byte 3 contains the first bit (i.e., OD0.0)
66 * and bit 7 of byte 0 contains the 32nd bit (i.e., OD10.1).
67 *
68 * In GPIO_TX[2], bit 0 of byte 3 contains the 33rd bit (i.e., OD10.2)
69 * and bit 7 of byte 0 contains the 64th bit (i.e., OD21.0)."
70 *
71 * The general-purpose (raw-bitstream) RX registers have the same layout
72 * although 'od' is renamed 'id' for 'input data'.
73 *
74 * SFF-8489 defines the behavior of the LEDs in response to the 'od' values.
75 */
76static u8 *to_sas_gpio_gp_bit(unsigned int od, u8 *data, u8 index, u8 count, u8 *bit)
77{
78 unsigned int reg;
79 u8 byte;
80
81 /* gp registers start at index 1 */
82 if (index == 0)
83 return NULL;
84
85 index--; /* make index 0-based */
86 if (od < index * 32)
87 return NULL;
88
89 od -= index * 32;
90 reg = od >> 5;
91
92 if (reg >= count)
93 return NULL;
94
95 od &= (1 << 5) - 1;
96 byte = 3 - (od >> 3);
97 *bit = od & ((1 << 3) - 1);
98
99 return &data[reg * 4 + byte];
100}
101
102int try_test_sas_gpio_gp_bit(unsigned int od, u8 *data, u8 index, u8 count)
103{
104 u8 *byte;
105 u8 bit;
106
107 byte = to_sas_gpio_gp_bit(od, data, index, count, &bit);
108 if (!byte)
109 return -1;
110
111 return (*byte >> bit) & 1;
112}
113EXPORT_SYMBOL(try_test_sas_gpio_gp_bit);
114
115static int sas_host_smp_write_gpio(struct sas_ha_struct *sas_ha, u8 *resp_data,
116 u8 reg_type, u8 reg_index, u8 reg_count,
117 u8 *req_data)
118{
119 struct sas_internal *i = to_sas_internal(sas_ha->core.shost->transportt);
120 int written;
121
122 if (i->dft->lldd_write_gpio == NULL) {
123 resp_data[2] = SMP_RESP_FUNC_UNK;
124 return 0;
125 }
126
127 written = i->dft->lldd_write_gpio(sas_ha, reg_type, reg_index,
128 reg_count, req_data);
129
130 if (written < 0) {
131 resp_data[2] = SMP_RESP_FUNC_FAILED;
132 written = 0;
133 } else
134 resp_data[2] = SMP_RESP_FUNC_ACC;
135
136 return written;
137}
138
54static void sas_report_phy_sata(struct sas_ha_struct *sas_ha, u8 *resp_data, 139static void sas_report_phy_sata(struct sas_ha_struct *sas_ha, u8 *resp_data,
55 u8 phy_id) 140 u8 phy_id)
56{ 141{
@@ -230,9 +315,23 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
230 /* Can't implement; hosts have no routes */ 315 /* Can't implement; hosts have no routes */
231 break; 316 break;
232 317
233 case SMP_WRITE_GPIO_REG: 318 case SMP_WRITE_GPIO_REG: {
234 /* FIXME: need GPIO support in the transport class */ 319 /* SFF-8485 v0.7 */
320 const int base_frame_size = 11;
321 int to_write = req_data[4];
322
323 if (blk_rq_bytes(req) < base_frame_size + to_write * 4 ||
324 req->resid_len < base_frame_size + to_write * 4) {
325 resp_data[2] = SMP_RESP_INV_FRM_LEN;
326 break;
327 }
328
329 to_write = sas_host_smp_write_gpio(sas_ha, resp_data, req_data[2],
330 req_data[3], to_write, &req_data[8]);
331 req->resid_len -= base_frame_size + to_write * 4;
332 rsp->resid_len -= 8;
235 break; 333 break;
334 }
236 335
237 case SMP_CONF_ROUTE_INFO: 336 case SMP_CONF_ROUTE_INFO:
238 /* Can't implement; hosts have no routes */ 337 /* Can't implement; hosts have no routes */
diff --git a/drivers/scsi/libsas/sas_init.c b/drivers/scsi/libsas/sas_init.c
index 2dc55343f671..d81c3b1989f7 100644
--- a/drivers/scsi/libsas/sas_init.c
+++ b/drivers/scsi/libsas/sas_init.c
@@ -37,7 +37,32 @@
37 37
38#include "../scsi_sas_internal.h" 38#include "../scsi_sas_internal.h"
39 39
40struct kmem_cache *sas_task_cache; 40static struct kmem_cache *sas_task_cache;
41
42struct sas_task *sas_alloc_task(gfp_t flags)
43{
44 struct sas_task *task = kmem_cache_zalloc(sas_task_cache, flags);
45
46 if (task) {
47 INIT_LIST_HEAD(&task->list);
48 spin_lock_init(&task->task_state_lock);
49 task->task_state_flags = SAS_TASK_STATE_PENDING;
50 init_timer(&task->timer);
51 init_completion(&task->completion);
52 }
53
54 return task;
55}
56EXPORT_SYMBOL_GPL(sas_alloc_task);
57
58void sas_free_task(struct sas_task *task)
59{
60 if (task) {
61 BUG_ON(!list_empty(&task->list));
62 kmem_cache_free(sas_task_cache, task);
63 }
64}
65EXPORT_SYMBOL_GPL(sas_free_task);
41 66
42/*------------ SAS addr hash -----------*/ 67/*------------ SAS addr hash -----------*/
43void sas_hash_addr(u8 *hashed, const u8 *sas_addr) 68void sas_hash_addr(u8 *hashed, const u8 *sas_addr)
@@ -152,10 +177,15 @@ int sas_unregister_ha(struct sas_ha_struct *sas_ha)
152 177
153static int sas_get_linkerrors(struct sas_phy *phy) 178static int sas_get_linkerrors(struct sas_phy *phy)
154{ 179{
155 if (scsi_is_sas_phy_local(phy)) 180 if (scsi_is_sas_phy_local(phy)) {
156 /* FIXME: we have no local phy stats 181 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
157 * gathering at this time */ 182 struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost);
158 return -EINVAL; 183 struct asd_sas_phy *asd_phy = sas_ha->sas_phy[phy->number];
184 struct sas_internal *i =
185 to_sas_internal(sas_ha->core.shost->transportt);
186
187 return i->dft->lldd_control_phy(asd_phy, PHY_FUNC_GET_EVENTS, NULL);
188 }
159 189
160 return sas_smp_get_phy_events(phy); 190 return sas_smp_get_phy_events(phy);
161} 191}
@@ -293,8 +323,7 @@ EXPORT_SYMBOL_GPL(sas_domain_release_transport);
293 323
294static int __init sas_class_init(void) 324static int __init sas_class_init(void)
295{ 325{
296 sas_task_cache = kmem_cache_create("sas_task", sizeof(struct sas_task), 326 sas_task_cache = KMEM_CACHE(sas_task, SLAB_HWCACHE_ALIGN);
297 0, SLAB_HWCACHE_ALIGN, NULL);
298 if (!sas_task_cache) 327 if (!sas_task_cache)
299 return -ENOMEM; 328 return -ENOMEM;
300 329
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c
index eeba76cdf774..b2c4a7731656 100644
--- a/drivers/scsi/libsas/sas_scsi_host.c
+++ b/drivers/scsi/libsas/sas_scsi_host.c
@@ -182,79 +182,56 @@ int sas_queue_up(struct sas_task *task)
182 return 0; 182 return 0;
183} 183}
184 184
185/** 185int sas_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
186 * sas_queuecommand -- Enqueue a command for processing
187 * @parameters: See SCSI Core documentation
188 *
189 * Note: XXX: Remove the host unlock/lock pair when SCSI Core can
190 * call us without holding an IRQ spinlock...
191 */
192static int sas_queuecommand_lck(struct scsi_cmnd *cmd,
193 void (*scsi_done)(struct scsi_cmnd *))
194 __releases(host->host_lock)
195 __acquires(dev->sata_dev.ap->lock)
196 __releases(dev->sata_dev.ap->lock)
197 __acquires(host->host_lock)
198{ 186{
199 int res = 0;
200 struct domain_device *dev = cmd_to_domain_dev(cmd);
201 struct Scsi_Host *host = cmd->device->host;
202 struct sas_internal *i = to_sas_internal(host->transportt); 187 struct sas_internal *i = to_sas_internal(host->transportt);
188 struct domain_device *dev = cmd_to_domain_dev(cmd);
189 struct sas_ha_struct *sas_ha = dev->port->ha;
190 struct sas_task *task;
191 int res = 0;
203 192
204 spin_unlock_irq(host->host_lock); 193 /* If the device fell off, no sense in issuing commands */
194 if (dev->gone) {
195 cmd->result = DID_BAD_TARGET << 16;
196 goto out_done;
197 }
205 198
206 { 199 if (dev_is_sata(dev)) {
207 struct sas_ha_struct *sas_ha = dev->port->ha; 200 unsigned long flags;
208 struct sas_task *task;
209
210 /* If the device fell off, no sense in issuing commands */
211 if (dev->gone) {
212 cmd->result = DID_BAD_TARGET << 16;
213 scsi_done(cmd);
214 goto out;
215 }
216 201
217 if (dev_is_sata(dev)) { 202 spin_lock_irqsave(dev->sata_dev.ap->lock, flags);
218 unsigned long flags; 203 res = ata_sas_queuecmd(cmd, dev->sata_dev.ap);
204 spin_unlock_irqrestore(dev->sata_dev.ap->lock, flags);
205 return res;
206 }
219 207
220 spin_lock_irqsave(dev->sata_dev.ap->lock, flags); 208 task = sas_create_task(cmd, dev, GFP_ATOMIC);
221 res = ata_sas_queuecmd(cmd, dev->sata_dev.ap); 209 if (!task)
222 spin_unlock_irqrestore(dev->sata_dev.ap->lock, flags); 210 return SCSI_MLQUEUE_HOST_BUSY;
223 goto out;
224 }
225 211
226 res = -ENOMEM; 212 /* Queue up, Direct Mode or Task Collector Mode. */
227 task = sas_create_task(cmd, dev, GFP_ATOMIC); 213 if (sas_ha->lldd_max_execute_num < 2)
228 if (!task) 214 res = i->dft->lldd_execute_task(task, 1, GFP_ATOMIC);
229 goto out; 215 else
216 res = sas_queue_up(task);
230 217
231 cmd->scsi_done = scsi_done; 218 if (res)
232 /* Queue up, Direct Mode or Task Collector Mode. */ 219 goto out_free_task;
233 if (sas_ha->lldd_max_execute_num < 2) 220 return 0;
234 res = i->dft->lldd_execute_task(task, 1, GFP_ATOMIC);
235 else
236 res = sas_queue_up(task);
237 221
238 /* Examine */ 222out_free_task:
239 if (res) { 223 SAS_DPRINTK("lldd_execute_task returned: %d\n", res);
240 SAS_DPRINTK("lldd_execute_task returned: %d\n", res); 224 ASSIGN_SAS_TASK(cmd, NULL);
241 ASSIGN_SAS_TASK(cmd, NULL); 225 sas_free_task(task);
242 sas_free_task(task); 226 if (res == -SAS_QUEUE_FULL)
243 if (res == -SAS_QUEUE_FULL) { 227 cmd->result = DID_SOFT_ERROR << 16; /* retry */
244 cmd->result = DID_SOFT_ERROR << 16; /* retry */ 228 else
245 res = 0; 229 cmd->result = DID_ERROR << 16;
246 scsi_done(cmd); 230out_done:
247 } 231 cmd->scsi_done(cmd);
248 goto out; 232 return 0;
249 }
250 }
251out:
252 spin_lock_irq(host->host_lock);
253 return res;
254} 233}
255 234
256DEF_SCSI_QCMD(sas_queuecommand)
257
258static void sas_eh_finish_cmd(struct scsi_cmnd *cmd) 235static void sas_eh_finish_cmd(struct scsi_cmnd *cmd)
259{ 236{
260 struct sas_task *task = TO_SAS_TASK(cmd); 237 struct sas_task *task = TO_SAS_TASK(cmd);
@@ -784,8 +761,7 @@ int sas_target_alloc(struct scsi_target *starget)
784 return 0; 761 return 0;
785} 762}
786 763
787#define SAS_DEF_QD 32 764#define SAS_DEF_QD 256
788#define SAS_MAX_QD 64
789 765
790int sas_slave_configure(struct scsi_device *scsi_dev) 766int sas_slave_configure(struct scsi_device *scsi_dev)
791{ 767{
@@ -825,34 +801,41 @@ void sas_slave_destroy(struct scsi_device *scsi_dev)
825 struct domain_device *dev = sdev_to_domain_dev(scsi_dev); 801 struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
826 802
827 if (dev_is_sata(dev)) 803 if (dev_is_sata(dev))
828 dev->sata_dev.ap->link.device[0].class = ATA_DEV_NONE; 804 sas_to_ata_dev(dev)->class = ATA_DEV_NONE;
829} 805}
830 806
831int sas_change_queue_depth(struct scsi_device *scsi_dev, int new_depth, 807int sas_change_queue_depth(struct scsi_device *sdev, int depth, int reason)
832 int reason)
833{ 808{
834 int res = min(new_depth, SAS_MAX_QD); 809 struct domain_device *dev = sdev_to_domain_dev(sdev);
835 810
836 if (reason != SCSI_QDEPTH_DEFAULT) 811 if (dev_is_sata(dev))
812 return __ata_change_queue_depth(dev->sata_dev.ap, sdev, depth,
813 reason);
814
815 switch (reason) {
816 case SCSI_QDEPTH_DEFAULT:
817 case SCSI_QDEPTH_RAMP_UP:
818 if (!sdev->tagged_supported)
819 depth = 1;
820 scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
821 break;
822 case SCSI_QDEPTH_QFULL:
823 scsi_track_queue_full(sdev, depth);
824 break;
825 default:
837 return -EOPNOTSUPP; 826 return -EOPNOTSUPP;
838
839 if (scsi_dev->tagged_supported)
840 scsi_adjust_queue_depth(scsi_dev, scsi_get_tag_type(scsi_dev),
841 res);
842 else {
843 struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
844 sas_printk("device %llx LUN %x queue depth changed to 1\n",
845 SAS_ADDR(dev->sas_addr),
846 scsi_dev->lun);
847 scsi_adjust_queue_depth(scsi_dev, 0, 1);
848 res = 1;
849 } 827 }
850 828
851 return res; 829 return depth;
852} 830}
853 831
854int sas_change_queue_type(struct scsi_device *scsi_dev, int qt) 832int sas_change_queue_type(struct scsi_device *scsi_dev, int qt)
855{ 833{
834 struct domain_device *dev = sdev_to_domain_dev(scsi_dev);
835
836 if (dev_is_sata(dev))
837 return -EINVAL;
838
856 if (!scsi_dev->tagged_supported) 839 if (!scsi_dev->tagged_supported)
857 return 0; 840 return 0;
858 841