diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-28 19:44:18 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-28 19:44:18 -0400 |
commit | ec7ae517537ae5c7b0b2cd7f562dfa3e7a05b954 (patch) | |
tree | e6b0c64a51a7c0aa0efd09d4f7a80872e3b1657a /drivers/scsi/libsas | |
parent | 97d2eb13a019ec09cc1a7ea2d3705c0b117b3c0d (diff) | |
parent | 590134fa78fbdbe5fea78c7ae0b2c3364bc9572f (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.c | 13 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_expander.c | 37 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_host_smp.c | 103 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_init.c | 43 | ||||
-rw-r--r-- | drivers/scsi/libsas/sas_scsi_host.c | 145 |
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 | ||
222 | static inline void sas_unregister_common_dev(struct domain_device *dev) | 222 | static 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 | ||
232 | void sas_unregister_dev(struct domain_device *dev) | 235 | void 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 | ||
247 | void sas_unregister_domain_devices(struct asd_sas_port *port) | 250 | void 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 | ||
1732 | static void sas_unregister_ex_tree(struct domain_device *dev) | 1745 | static 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 | ||
1748 | static void sas_unregister_devs_sas_addr(struct domain_device *parent, | 1761 | static 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 | */ | ||
76 | static 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 | |||
102 | int 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 | } | ||
113 | EXPORT_SYMBOL(try_test_sas_gpio_gp_bit); | ||
114 | |||
115 | static 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 | |||
54 | static void sas_report_phy_sata(struct sas_ha_struct *sas_ha, u8 *resp_data, | 139 | static 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 | ||
40 | struct kmem_cache *sas_task_cache; | 40 | static struct kmem_cache *sas_task_cache; |
41 | |||
42 | struct 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 | } | ||
56 | EXPORT_SYMBOL_GPL(sas_alloc_task); | ||
57 | |||
58 | void 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 | } | ||
65 | EXPORT_SYMBOL_GPL(sas_free_task); | ||
41 | 66 | ||
42 | /*------------ SAS addr hash -----------*/ | 67 | /*------------ SAS addr hash -----------*/ |
43 | void sas_hash_addr(u8 *hashed, const u8 *sas_addr) | 68 | void 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 | ||
153 | static int sas_get_linkerrors(struct sas_phy *phy) | 178 | static 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 | ||
294 | static int __init sas_class_init(void) | 324 | static 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 | /** | 185 | int 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 | */ | ||
192 | static 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 */ | 222 | out_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); | 230 | out_done: |
247 | } | 231 | cmd->scsi_done(cmd); |
248 | goto out; | 232 | return 0; |
249 | } | ||
250 | } | ||
251 | out: | ||
252 | spin_lock_irq(host->host_lock); | ||
253 | return res; | ||
254 | } | 233 | } |
255 | 234 | ||
256 | DEF_SCSI_QCMD(sas_queuecommand) | ||
257 | |||
258 | static void sas_eh_finish_cmd(struct scsi_cmnd *cmd) | 235 | static 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 | ||
790 | int sas_slave_configure(struct scsi_device *scsi_dev) | 766 | int 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 | ||
831 | int sas_change_queue_depth(struct scsi_device *scsi_dev, int new_depth, | 807 | int 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 | ||
854 | int sas_change_queue_type(struct scsi_device *scsi_dev, int qt) | 832 | int 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 | ||