Commit 899fcf40f3177697ccfb029d0484cb8ec09a51ca

Authored by Dan Williams
Committed by James Bottomley
1 parent 9a10b33caf

[SCSI] libsas: set attached device type and target protocols for local phys

Before:
$ cat /sys/class/sas_phy/phy-6\:3/device_type
none
$ cat /sys/class/sas_phy/phy-6\:3/target_port_protocols
none

After:
$ cat /sys/class/sas_phy/phy-6\:3/device_type
end device
$ cat /sys/class/sas_phy/phy-6\:3/target_port_protocols
sata

Also downgrade the phy_list_lock to _irq instead of _irqsave since
libsas will never call sas_get_port_device with interrupts disbled.

Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>

Showing 3 changed files with 27 additions and 4 deletions Inline Diff

drivers/scsi/libsas/sas_discover.c
1 /* 1 /*
2 * Serial Attached SCSI (SAS) Discover process 2 * Serial Attached SCSI (SAS) Discover process
3 * 3 *
4 * Copyright (C) 2005 Adaptec, Inc. All rights reserved. 4 * Copyright (C) 2005 Adaptec, Inc. All rights reserved.
5 * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com> 5 * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com>
6 * 6 *
7 * This file is licensed under GPLv2. 7 * This file is licensed under GPLv2.
8 * 8 *
9 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as 10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of the 11 * published by the Free Software Foundation; either version 2 of the
12 * License, or (at your option) any later version. 12 * License, or (at your option) any later version.
13 * 13 *
14 * This program is distributed in the hope that it will be useful, but 14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details. 17 * General Public License for more details.
18 * 18 *
19 * You should have received a copy of the GNU General Public License 19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software 20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 * 22 *
23 */ 23 */
24 24
25 #include <linux/scatterlist.h> 25 #include <linux/scatterlist.h>
26 #include <linux/slab.h> 26 #include <linux/slab.h>
27 #include <scsi/scsi_host.h> 27 #include <scsi/scsi_host.h>
28 #include <scsi/scsi_eh.h> 28 #include <scsi/scsi_eh.h>
29 #include "sas_internal.h" 29 #include "sas_internal.h"
30 30
31 #include <scsi/scsi_transport.h> 31 #include <scsi/scsi_transport.h>
32 #include <scsi/scsi_transport_sas.h> 32 #include <scsi/scsi_transport_sas.h>
33 #include <scsi/sas_ata.h> 33 #include <scsi/sas_ata.h>
34 #include "../scsi_sas_internal.h" 34 #include "../scsi_sas_internal.h"
35 35
36 /* ---------- Basic task processing for discovery purposes ---------- */ 36 /* ---------- Basic task processing for discovery purposes ---------- */
37 37
38 void sas_init_dev(struct domain_device *dev) 38 void sas_init_dev(struct domain_device *dev)
39 { 39 {
40 switch (dev->dev_type) { 40 switch (dev->dev_type) {
41 case SAS_END_DEV: 41 case SAS_END_DEV:
42 break; 42 break;
43 case EDGE_DEV: 43 case EDGE_DEV:
44 case FANOUT_DEV: 44 case FANOUT_DEV:
45 INIT_LIST_HEAD(&dev->ex_dev.children); 45 INIT_LIST_HEAD(&dev->ex_dev.children);
46 mutex_init(&dev->ex_dev.cmd_mutex); 46 mutex_init(&dev->ex_dev.cmd_mutex);
47 break; 47 break;
48 case SATA_DEV: 48 case SATA_DEV:
49 case SATA_PM: 49 case SATA_PM:
50 case SATA_PM_PORT: 50 case SATA_PM_PORT:
51 case SATA_PENDING: 51 case SATA_PENDING:
52 INIT_LIST_HEAD(&dev->sata_dev.children); 52 INIT_LIST_HEAD(&dev->sata_dev.children);
53 break; 53 break;
54 default: 54 default:
55 break; 55 break;
56 } 56 }
57 } 57 }
58 58
59 /* ---------- Domain device discovery ---------- */ 59 /* ---------- Domain device discovery ---------- */
60 60
61 /** 61 /**
62 * sas_get_port_device -- Discover devices which caused port creation 62 * sas_get_port_device -- Discover devices which caused port creation
63 * @port: pointer to struct sas_port of interest 63 * @port: pointer to struct sas_port of interest
64 * 64 *
65 * Devices directly attached to a HA port, have no parent. This is 65 * Devices directly attached to a HA port, have no parent. This is
66 * how we know they are (domain) "root" devices. All other devices 66 * how we know they are (domain) "root" devices. All other devices
67 * do, and should have their "parent" pointer set appropriately as 67 * do, and should have their "parent" pointer set appropriately as
68 * soon as a child device is discovered. 68 * soon as a child device is discovered.
69 */ 69 */
70 static int sas_get_port_device(struct asd_sas_port *port) 70 static int sas_get_port_device(struct asd_sas_port *port)
71 { 71 {
72 unsigned long flags;
73 struct asd_sas_phy *phy; 72 struct asd_sas_phy *phy;
74 struct sas_rphy *rphy; 73 struct sas_rphy *rphy;
75 struct domain_device *dev; 74 struct domain_device *dev;
76 75
77 dev = sas_alloc_device(); 76 dev = sas_alloc_device();
78 if (!dev) 77 if (!dev)
79 return -ENOMEM; 78 return -ENOMEM;
80 79
81 spin_lock_irqsave(&port->phy_list_lock, flags); 80 spin_lock_irq(&port->phy_list_lock);
82 if (list_empty(&port->phy_list)) { 81 if (list_empty(&port->phy_list)) {
83 spin_unlock_irqrestore(&port->phy_list_lock, flags); 82 spin_unlock_irq(&port->phy_list_lock);
84 sas_put_device(dev); 83 sas_put_device(dev);
85 return -ENODEV; 84 return -ENODEV;
86 } 85 }
87 phy = container_of(port->phy_list.next, struct asd_sas_phy, port_phy_el); 86 phy = container_of(port->phy_list.next, struct asd_sas_phy, port_phy_el);
88 spin_lock(&phy->frame_rcvd_lock); 87 spin_lock(&phy->frame_rcvd_lock);
89 memcpy(dev->frame_rcvd, phy->frame_rcvd, min(sizeof(dev->frame_rcvd), 88 memcpy(dev->frame_rcvd, phy->frame_rcvd, min(sizeof(dev->frame_rcvd),
90 (size_t)phy->frame_rcvd_size)); 89 (size_t)phy->frame_rcvd_size));
91 spin_unlock(&phy->frame_rcvd_lock); 90 spin_unlock(&phy->frame_rcvd_lock);
92 spin_unlock_irqrestore(&port->phy_list_lock, flags); 91 spin_unlock_irq(&port->phy_list_lock);
93 92
94 if (dev->frame_rcvd[0] == 0x34 && port->oob_mode == SATA_OOB_MODE) { 93 if (dev->frame_rcvd[0] == 0x34 && port->oob_mode == SATA_OOB_MODE) {
95 struct dev_to_host_fis *fis = 94 struct dev_to_host_fis *fis =
96 (struct dev_to_host_fis *) dev->frame_rcvd; 95 (struct dev_to_host_fis *) dev->frame_rcvd;
97 if (fis->interrupt_reason == 1 && fis->lbal == 1 && 96 if (fis->interrupt_reason == 1 && fis->lbal == 1 &&
98 fis->byte_count_low==0x69 && fis->byte_count_high == 0x96 97 fis->byte_count_low==0x69 && fis->byte_count_high == 0x96
99 && (fis->device & ~0x10) == 0) 98 && (fis->device & ~0x10) == 0)
100 dev->dev_type = SATA_PM; 99 dev->dev_type = SATA_PM;
101 else 100 else
102 dev->dev_type = SATA_DEV; 101 dev->dev_type = SATA_DEV;
103 dev->tproto = SAS_PROTOCOL_SATA; 102 dev->tproto = SAS_PROTOCOL_SATA;
104 } else { 103 } else {
105 struct sas_identify_frame *id = 104 struct sas_identify_frame *id =
106 (struct sas_identify_frame *) dev->frame_rcvd; 105 (struct sas_identify_frame *) dev->frame_rcvd;
107 dev->dev_type = id->dev_type; 106 dev->dev_type = id->dev_type;
108 dev->iproto = id->initiator_bits; 107 dev->iproto = id->initiator_bits;
109 dev->tproto = id->target_bits; 108 dev->tproto = id->target_bits;
110 } 109 }
111 110
112 sas_init_dev(dev); 111 sas_init_dev(dev);
113 112
114 switch (dev->dev_type) { 113 switch (dev->dev_type) {
115 case SAS_END_DEV: 114 case SAS_END_DEV:
116 case SATA_DEV: 115 case SATA_DEV:
117 rphy = sas_end_device_alloc(port->port); 116 rphy = sas_end_device_alloc(port->port);
118 break; 117 break;
119 case EDGE_DEV: 118 case EDGE_DEV:
120 rphy = sas_expander_alloc(port->port, 119 rphy = sas_expander_alloc(port->port,
121 SAS_EDGE_EXPANDER_DEVICE); 120 SAS_EDGE_EXPANDER_DEVICE);
122 break; 121 break;
123 case FANOUT_DEV: 122 case FANOUT_DEV:
124 rphy = sas_expander_alloc(port->port, 123 rphy = sas_expander_alloc(port->port,
125 SAS_FANOUT_EXPANDER_DEVICE); 124 SAS_FANOUT_EXPANDER_DEVICE);
126 break; 125 break;
127 default: 126 default:
128 printk("ERROR: Unidentified device type %d\n", dev->dev_type); 127 printk("ERROR: Unidentified device type %d\n", dev->dev_type);
129 rphy = NULL; 128 rphy = NULL;
130 break; 129 break;
131 } 130 }
132 131
133 if (!rphy) { 132 if (!rphy) {
134 sas_put_device(dev); 133 sas_put_device(dev);
135 return -ENODEV; 134 return -ENODEV;
136 } 135 }
136
137 spin_lock_irq(&port->phy_list_lock);
138 list_for_each_entry(phy, &port->phy_list, port_phy_el)
139 sas_phy_set_target(phy, dev);
140 spin_unlock_irq(&port->phy_list_lock);
137 rphy->identify.phy_identifier = phy->phy->identify.phy_identifier; 141 rphy->identify.phy_identifier = phy->phy->identify.phy_identifier;
138 memcpy(dev->sas_addr, port->attached_sas_addr, SAS_ADDR_SIZE); 142 memcpy(dev->sas_addr, port->attached_sas_addr, SAS_ADDR_SIZE);
139 sas_fill_in_rphy(dev, rphy); 143 sas_fill_in_rphy(dev, rphy);
140 sas_hash_addr(dev->hashed_sas_addr, dev->sas_addr); 144 sas_hash_addr(dev->hashed_sas_addr, dev->sas_addr);
141 port->port_dev = dev; 145 port->port_dev = dev;
142 dev->port = port; 146 dev->port = port;
143 dev->linkrate = port->linkrate; 147 dev->linkrate = port->linkrate;
144 dev->min_linkrate = port->linkrate; 148 dev->min_linkrate = port->linkrate;
145 dev->max_linkrate = port->linkrate; 149 dev->max_linkrate = port->linkrate;
146 dev->pathways = port->num_phys; 150 dev->pathways = port->num_phys;
147 memset(port->disc.fanout_sas_addr, 0, SAS_ADDR_SIZE); 151 memset(port->disc.fanout_sas_addr, 0, SAS_ADDR_SIZE);
148 memset(port->disc.eeds_a, 0, SAS_ADDR_SIZE); 152 memset(port->disc.eeds_a, 0, SAS_ADDR_SIZE);
149 memset(port->disc.eeds_b, 0, SAS_ADDR_SIZE); 153 memset(port->disc.eeds_b, 0, SAS_ADDR_SIZE);
150 port->disc.max_level = 0; 154 port->disc.max_level = 0;
151 sas_device_set_phy(dev, port->port); 155 sas_device_set_phy(dev, port->port);
152 156
153 dev->rphy = rphy; 157 dev->rphy = rphy;
154 158
155 if (dev_is_sata(dev) || dev->dev_type == SAS_END_DEV) 159 if (dev_is_sata(dev) || dev->dev_type == SAS_END_DEV)
156 list_add_tail(&dev->disco_list_node, &port->disco_list); 160 list_add_tail(&dev->disco_list_node, &port->disco_list);
157 else { 161 else {
158 spin_lock_irq(&port->dev_list_lock); 162 spin_lock_irq(&port->dev_list_lock);
159 list_add_tail(&dev->dev_list_node, &port->dev_list); 163 list_add_tail(&dev->dev_list_node, &port->dev_list);
160 spin_unlock_irq(&port->dev_list_lock); 164 spin_unlock_irq(&port->dev_list_lock);
161 } 165 }
162 166
163 return 0; 167 return 0;
164 } 168 }
165 169
166 /* ---------- Discover and Revalidate ---------- */ 170 /* ---------- Discover and Revalidate ---------- */
167 171
168 int sas_notify_lldd_dev_found(struct domain_device *dev) 172 int sas_notify_lldd_dev_found(struct domain_device *dev)
169 { 173 {
170 int res = 0; 174 int res = 0;
171 struct sas_ha_struct *sas_ha = dev->port->ha; 175 struct sas_ha_struct *sas_ha = dev->port->ha;
172 struct Scsi_Host *shost = sas_ha->core.shost; 176 struct Scsi_Host *shost = sas_ha->core.shost;
173 struct sas_internal *i = to_sas_internal(shost->transportt); 177 struct sas_internal *i = to_sas_internal(shost->transportt);
174 178
175 if (i->dft->lldd_dev_found) { 179 if (i->dft->lldd_dev_found) {
176 res = i->dft->lldd_dev_found(dev); 180 res = i->dft->lldd_dev_found(dev);
177 if (res) { 181 if (res) {
178 printk("sas: driver on pcidev %s cannot handle " 182 printk("sas: driver on pcidev %s cannot handle "
179 "device %llx, error:%d\n", 183 "device %llx, error:%d\n",
180 dev_name(sas_ha->dev), 184 dev_name(sas_ha->dev),
181 SAS_ADDR(dev->sas_addr), res); 185 SAS_ADDR(dev->sas_addr), res);
182 } 186 }
183 kref_get(&dev->kref); 187 kref_get(&dev->kref);
184 } 188 }
185 return res; 189 return res;
186 } 190 }
187 191
188 192
189 void sas_notify_lldd_dev_gone(struct domain_device *dev) 193 void sas_notify_lldd_dev_gone(struct domain_device *dev)
190 { 194 {
191 struct sas_ha_struct *sas_ha = dev->port->ha; 195 struct sas_ha_struct *sas_ha = dev->port->ha;
192 struct Scsi_Host *shost = sas_ha->core.shost; 196 struct Scsi_Host *shost = sas_ha->core.shost;
193 struct sas_internal *i = to_sas_internal(shost->transportt); 197 struct sas_internal *i = to_sas_internal(shost->transportt);
194 198
195 if (i->dft->lldd_dev_gone) { 199 if (i->dft->lldd_dev_gone) {
196 i->dft->lldd_dev_gone(dev); 200 i->dft->lldd_dev_gone(dev);
197 sas_put_device(dev); 201 sas_put_device(dev);
198 } 202 }
199 } 203 }
200 204
201 static void sas_probe_devices(struct work_struct *work) 205 static void sas_probe_devices(struct work_struct *work)
202 { 206 {
203 struct domain_device *dev, *n; 207 struct domain_device *dev, *n;
204 struct sas_discovery_event *ev = 208 struct sas_discovery_event *ev =
205 container_of(work, struct sas_discovery_event, work); 209 container_of(work, struct sas_discovery_event, work);
206 struct asd_sas_port *port = ev->port; 210 struct asd_sas_port *port = ev->port;
207 211
208 clear_bit(DISCE_PROBE, &port->disc.pending); 212 clear_bit(DISCE_PROBE, &port->disc.pending);
209 213
210 /* devices must be domain members before link recovery and probe */ 214 /* devices must be domain members before link recovery and probe */
211 list_for_each_entry(dev, &port->disco_list, disco_list_node) { 215 list_for_each_entry(dev, &port->disco_list, disco_list_node) {
212 spin_lock_irq(&port->dev_list_lock); 216 spin_lock_irq(&port->dev_list_lock);
213 list_add_tail(&dev->dev_list_node, &port->dev_list); 217 list_add_tail(&dev->dev_list_node, &port->dev_list);
214 spin_unlock_irq(&port->dev_list_lock); 218 spin_unlock_irq(&port->dev_list_lock);
215 } 219 }
216 220
217 sas_probe_sata(port); 221 sas_probe_sata(port);
218 222
219 list_for_each_entry_safe(dev, n, &port->disco_list, disco_list_node) { 223 list_for_each_entry_safe(dev, n, &port->disco_list, disco_list_node) {
220 int err; 224 int err;
221 225
222 err = sas_rphy_add(dev->rphy); 226 err = sas_rphy_add(dev->rphy);
223 if (err) 227 if (err)
224 sas_fail_probe(dev, __func__, err); 228 sas_fail_probe(dev, __func__, err);
225 else 229 else
226 list_del_init(&dev->disco_list_node); 230 list_del_init(&dev->disco_list_node);
227 } 231 }
228 } 232 }
229 233
230 /** 234 /**
231 * sas_discover_end_dev -- discover an end device (SSP, etc) 235 * sas_discover_end_dev -- discover an end device (SSP, etc)
232 * @end: pointer to domain device of interest 236 * @end: pointer to domain device of interest
233 * 237 *
234 * See comment in sas_discover_sata(). 238 * See comment in sas_discover_sata().
235 */ 239 */
236 int sas_discover_end_dev(struct domain_device *dev) 240 int sas_discover_end_dev(struct domain_device *dev)
237 { 241 {
238 int res; 242 int res;
239 243
240 res = sas_notify_lldd_dev_found(dev); 244 res = sas_notify_lldd_dev_found(dev);
241 if (res) 245 if (res)
242 return res; 246 return res;
243 sas_discover_event(dev->port, DISCE_PROBE); 247 sas_discover_event(dev->port, DISCE_PROBE);
244 248
245 return 0; 249 return 0;
246 } 250 }
247 251
248 /* ---------- Device registration and unregistration ---------- */ 252 /* ---------- Device registration and unregistration ---------- */
249 253
250 void sas_free_device(struct kref *kref) 254 void sas_free_device(struct kref *kref)
251 { 255 {
252 struct domain_device *dev = container_of(kref, typeof(*dev), kref); 256 struct domain_device *dev = container_of(kref, typeof(*dev), kref);
253 257
254 if (dev->parent) 258 if (dev->parent)
255 sas_put_device(dev->parent); 259 sas_put_device(dev->parent);
256 260
257 sas_port_put_phy(dev->phy); 261 sas_port_put_phy(dev->phy);
258 dev->phy = NULL; 262 dev->phy = NULL;
259 263
260 /* remove the phys and ports, everything else should be gone */ 264 /* remove the phys and ports, everything else should be gone */
261 if (dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV) 265 if (dev->dev_type == EDGE_DEV || dev->dev_type == FANOUT_DEV)
262 kfree(dev->ex_dev.ex_phy); 266 kfree(dev->ex_dev.ex_phy);
263 267
264 if (dev_is_sata(dev) && dev->sata_dev.ap) { 268 if (dev_is_sata(dev) && dev->sata_dev.ap) {
265 ata_sas_port_destroy(dev->sata_dev.ap); 269 ata_sas_port_destroy(dev->sata_dev.ap);
266 dev->sata_dev.ap = NULL; 270 dev->sata_dev.ap = NULL;
267 } 271 }
268 272
269 kfree(dev); 273 kfree(dev);
270 } 274 }
271 275
272 static void sas_unregister_common_dev(struct asd_sas_port *port, struct domain_device *dev) 276 static void sas_unregister_common_dev(struct asd_sas_port *port, struct domain_device *dev)
273 { 277 {
274 sas_notify_lldd_dev_gone(dev); 278 sas_notify_lldd_dev_gone(dev);
275 if (!dev->parent) 279 if (!dev->parent)
276 dev->port->port_dev = NULL; 280 dev->port->port_dev = NULL;
277 else 281 else
278 list_del_init(&dev->siblings); 282 list_del_init(&dev->siblings);
279 283
280 spin_lock_irq(&port->dev_list_lock); 284 spin_lock_irq(&port->dev_list_lock);
281 list_del_init(&dev->dev_list_node); 285 list_del_init(&dev->dev_list_node);
282 spin_unlock_irq(&port->dev_list_lock); 286 spin_unlock_irq(&port->dev_list_lock);
283 287
284 sas_put_device(dev); 288 sas_put_device(dev);
285 } 289 }
286 290
287 static void sas_destruct_devices(struct work_struct *work) 291 static void sas_destruct_devices(struct work_struct *work)
288 { 292 {
289 struct domain_device *dev, *n; 293 struct domain_device *dev, *n;
290 struct sas_discovery_event *ev = 294 struct sas_discovery_event *ev =
291 container_of(work, struct sas_discovery_event, work); 295 container_of(work, struct sas_discovery_event, work);
292 struct asd_sas_port *port = ev->port; 296 struct asd_sas_port *port = ev->port;
293 297
294 clear_bit(DISCE_DESTRUCT, &port->disc.pending); 298 clear_bit(DISCE_DESTRUCT, &port->disc.pending);
295 299
296 list_for_each_entry_safe(dev, n, &port->destroy_list, disco_list_node) { 300 list_for_each_entry_safe(dev, n, &port->destroy_list, disco_list_node) {
297 list_del_init(&dev->disco_list_node); 301 list_del_init(&dev->disco_list_node);
298 302
299 sas_remove_children(&dev->rphy->dev); 303 sas_remove_children(&dev->rphy->dev);
300 sas_rphy_delete(dev->rphy); 304 sas_rphy_delete(dev->rphy);
301 dev->rphy = NULL; 305 dev->rphy = NULL;
302 sas_unregister_common_dev(port, dev); 306 sas_unregister_common_dev(port, dev);
303 } 307 }
304 } 308 }
305 309
306 void sas_unregister_dev(struct asd_sas_port *port, struct domain_device *dev) 310 void sas_unregister_dev(struct asd_sas_port *port, struct domain_device *dev)
307 { 311 {
308 if (!test_bit(SAS_DEV_DESTROY, &dev->state) && 312 if (!test_bit(SAS_DEV_DESTROY, &dev->state) &&
309 !list_empty(&dev->disco_list_node)) { 313 !list_empty(&dev->disco_list_node)) {
310 /* this rphy never saw sas_rphy_add */ 314 /* this rphy never saw sas_rphy_add */
311 list_del_init(&dev->disco_list_node); 315 list_del_init(&dev->disco_list_node);
312 sas_rphy_free(dev->rphy); 316 sas_rphy_free(dev->rphy);
313 dev->rphy = NULL; 317 dev->rphy = NULL;
314 sas_unregister_common_dev(port, dev); 318 sas_unregister_common_dev(port, dev);
315 } 319 }
316 320
317 if (dev->rphy && !test_and_set_bit(SAS_DEV_DESTROY, &dev->state)) { 321 if (dev->rphy && !test_and_set_bit(SAS_DEV_DESTROY, &dev->state)) {
318 sas_rphy_unlink(dev->rphy); 322 sas_rphy_unlink(dev->rphy);
319 list_move_tail(&dev->disco_list_node, &port->destroy_list); 323 list_move_tail(&dev->disco_list_node, &port->destroy_list);
320 sas_discover_event(dev->port, DISCE_DESTRUCT); 324 sas_discover_event(dev->port, DISCE_DESTRUCT);
321 } 325 }
322 } 326 }
323 327
324 void sas_unregister_domain_devices(struct asd_sas_port *port, int gone) 328 void sas_unregister_domain_devices(struct asd_sas_port *port, int gone)
325 { 329 {
326 struct domain_device *dev, *n; 330 struct domain_device *dev, *n;
327 331
328 list_for_each_entry_safe_reverse(dev, n, &port->dev_list, dev_list_node) { 332 list_for_each_entry_safe_reverse(dev, n, &port->dev_list, dev_list_node) {
329 if (gone) 333 if (gone)
330 set_bit(SAS_DEV_GONE, &dev->state); 334 set_bit(SAS_DEV_GONE, &dev->state);
331 sas_unregister_dev(port, dev); 335 sas_unregister_dev(port, dev);
332 } 336 }
333 337
334 list_for_each_entry_safe(dev, n, &port->disco_list, disco_list_node) 338 list_for_each_entry_safe(dev, n, &port->disco_list, disco_list_node)
335 sas_unregister_dev(port, dev); 339 sas_unregister_dev(port, dev);
336 340
337 port->port->rphy = NULL; 341 port->port->rphy = NULL;
338 342
339 } 343 }
340 344
341 void sas_device_set_phy(struct domain_device *dev, struct sas_port *port) 345 void sas_device_set_phy(struct domain_device *dev, struct sas_port *port)
342 { 346 {
343 struct sas_ha_struct *ha; 347 struct sas_ha_struct *ha;
344 struct sas_phy *new_phy; 348 struct sas_phy *new_phy;
345 349
346 if (!dev) 350 if (!dev)
347 return; 351 return;
348 352
349 ha = dev->port->ha; 353 ha = dev->port->ha;
350 new_phy = sas_port_get_phy(port); 354 new_phy = sas_port_get_phy(port);
351 355
352 /* pin and record last seen phy */ 356 /* pin and record last seen phy */
353 spin_lock_irq(&ha->phy_port_lock); 357 spin_lock_irq(&ha->phy_port_lock);
354 if (new_phy) { 358 if (new_phy) {
355 sas_port_put_phy(dev->phy); 359 sas_port_put_phy(dev->phy);
356 dev->phy = new_phy; 360 dev->phy = new_phy;
357 } 361 }
358 spin_unlock_irq(&ha->phy_port_lock); 362 spin_unlock_irq(&ha->phy_port_lock);
359 } 363 }
360 364
361 /* ---------- Discovery and Revalidation ---------- */ 365 /* ---------- Discovery and Revalidation ---------- */
362 366
363 /** 367 /**
364 * sas_discover_domain -- discover the domain 368 * sas_discover_domain -- discover the domain
365 * @port: port to the domain of interest 369 * @port: port to the domain of interest
366 * 370 *
367 * NOTE: this process _must_ quit (return) as soon as any connection 371 * NOTE: this process _must_ quit (return) as soon as any connection
368 * errors are encountered. Connection recovery is done elsewhere. 372 * errors are encountered. Connection recovery is done elsewhere.
369 * Discover process only interrogates devices in order to discover the 373 * Discover process only interrogates devices in order to discover the
370 * domain. 374 * domain.
371 */ 375 */
372 static void sas_discover_domain(struct work_struct *work) 376 static void sas_discover_domain(struct work_struct *work)
373 { 377 {
374 struct domain_device *dev; 378 struct domain_device *dev;
375 int error = 0; 379 int error = 0;
376 struct sas_discovery_event *ev = 380 struct sas_discovery_event *ev =
377 container_of(work, struct sas_discovery_event, work); 381 container_of(work, struct sas_discovery_event, work);
378 struct asd_sas_port *port = ev->port; 382 struct asd_sas_port *port = ev->port;
379 383
380 clear_bit(DISCE_DISCOVER_DOMAIN, &port->disc.pending); 384 clear_bit(DISCE_DISCOVER_DOMAIN, &port->disc.pending);
381 385
382 if (port->port_dev) 386 if (port->port_dev)
383 return; 387 return;
384 388
385 error = sas_get_port_device(port); 389 error = sas_get_port_device(port);
386 if (error) 390 if (error)
387 return; 391 return;
388 dev = port->port_dev; 392 dev = port->port_dev;
389 393
390 SAS_DPRINTK("DOING DISCOVERY on port %d, pid:%d\n", port->id, 394 SAS_DPRINTK("DOING DISCOVERY on port %d, pid:%d\n", port->id,
391 task_pid_nr(current)); 395 task_pid_nr(current));
392 396
393 switch (dev->dev_type) { 397 switch (dev->dev_type) {
394 case SAS_END_DEV: 398 case SAS_END_DEV:
395 error = sas_discover_end_dev(dev); 399 error = sas_discover_end_dev(dev);
396 break; 400 break;
397 case EDGE_DEV: 401 case EDGE_DEV:
398 case FANOUT_DEV: 402 case FANOUT_DEV:
399 error = sas_discover_root_expander(dev); 403 error = sas_discover_root_expander(dev);
400 break; 404 break;
401 case SATA_DEV: 405 case SATA_DEV:
402 case SATA_PM: 406 case SATA_PM:
403 #ifdef CONFIG_SCSI_SAS_ATA 407 #ifdef CONFIG_SCSI_SAS_ATA
404 error = sas_discover_sata(dev); 408 error = sas_discover_sata(dev);
405 break; 409 break;
406 #else 410 #else
407 SAS_DPRINTK("ATA device seen but CONFIG_SCSI_SAS_ATA=N so cannot attach\n"); 411 SAS_DPRINTK("ATA device seen but CONFIG_SCSI_SAS_ATA=N so cannot attach\n");
408 /* Fall through */ 412 /* Fall through */
409 #endif 413 #endif
410 default: 414 default:
411 error = -ENXIO; 415 error = -ENXIO;
412 SAS_DPRINTK("unhandled device %d\n", dev->dev_type); 416 SAS_DPRINTK("unhandled device %d\n", dev->dev_type);
413 break; 417 break;
414 } 418 }
415 419
416 if (error) { 420 if (error) {
417 sas_rphy_free(dev->rphy); 421 sas_rphy_free(dev->rphy);
418 dev->rphy = NULL; 422 dev->rphy = NULL;
419 423
420 list_del_init(&dev->disco_list_node); 424 list_del_init(&dev->disco_list_node);
421 spin_lock_irq(&port->dev_list_lock); 425 spin_lock_irq(&port->dev_list_lock);
422 list_del_init(&dev->dev_list_node); 426 list_del_init(&dev->dev_list_node);
423 spin_unlock_irq(&port->dev_list_lock); 427 spin_unlock_irq(&port->dev_list_lock);
424 428
425 sas_put_device(dev); 429 sas_put_device(dev);
426 port->port_dev = NULL; 430 port->port_dev = NULL;
427 } 431 }
428 432
429 SAS_DPRINTK("DONE DISCOVERY on port %d, pid:%d, result:%d\n", port->id, 433 SAS_DPRINTK("DONE DISCOVERY on port %d, pid:%d, result:%d\n", port->id,
430 task_pid_nr(current), error); 434 task_pid_nr(current), error);
431 } 435 }
432 436
433 static void sas_revalidate_domain(struct work_struct *work) 437 static void sas_revalidate_domain(struct work_struct *work)
434 { 438 {
435 int res = 0; 439 int res = 0;
436 struct sas_discovery_event *ev = 440 struct sas_discovery_event *ev =
437 container_of(work, struct sas_discovery_event, work); 441 container_of(work, struct sas_discovery_event, work);
438 struct asd_sas_port *port = ev->port; 442 struct asd_sas_port *port = ev->port;
439 struct sas_ha_struct *ha = port->ha; 443 struct sas_ha_struct *ha = port->ha;
440 444
441 /* prevent revalidation from finding sata links in recovery */ 445 /* prevent revalidation from finding sata links in recovery */
442 mutex_lock(&ha->disco_mutex); 446 mutex_lock(&ha->disco_mutex);
443 if (test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)) { 447 if (test_bit(SAS_HA_ATA_EH_ACTIVE, &ha->state)) {
444 SAS_DPRINTK("REVALIDATION DEFERRED on port %d, pid:%d\n", 448 SAS_DPRINTK("REVALIDATION DEFERRED on port %d, pid:%d\n",
445 port->id, task_pid_nr(current)); 449 port->id, task_pid_nr(current));
446 goto out; 450 goto out;
447 } 451 }
448 452
449 clear_bit(DISCE_REVALIDATE_DOMAIN, &port->disc.pending); 453 clear_bit(DISCE_REVALIDATE_DOMAIN, &port->disc.pending);
450 454
451 SAS_DPRINTK("REVALIDATING DOMAIN on port %d, pid:%d\n", port->id, 455 SAS_DPRINTK("REVALIDATING DOMAIN on port %d, pid:%d\n", port->id,
452 task_pid_nr(current)); 456 task_pid_nr(current));
453 457
454 if (port->port_dev) 458 if (port->port_dev)
455 res = sas_ex_revalidate_domain(port->port_dev); 459 res = sas_ex_revalidate_domain(port->port_dev);
456 460
457 SAS_DPRINTK("done REVALIDATING DOMAIN on port %d, pid:%d, res 0x%x\n", 461 SAS_DPRINTK("done REVALIDATING DOMAIN on port %d, pid:%d, res 0x%x\n",
458 port->id, task_pid_nr(current), res); 462 port->id, task_pid_nr(current), res);
459 out: 463 out:
460 mutex_unlock(&ha->disco_mutex); 464 mutex_unlock(&ha->disco_mutex);
461 } 465 }
462 466
463 /* ---------- Events ---------- */ 467 /* ---------- Events ---------- */
464 468
465 static void sas_chain_work(struct sas_ha_struct *ha, struct work_struct *work) 469 static void sas_chain_work(struct sas_ha_struct *ha, struct work_struct *work)
466 { 470 {
467 /* chained work is not subject to SA_HA_DRAINING or SAS_HA_REGISTERED */ 471 /* chained work is not subject to SA_HA_DRAINING or SAS_HA_REGISTERED */
468 scsi_queue_work(ha->core.shost, work); 472 scsi_queue_work(ha->core.shost, work);
469 } 473 }
470 474
471 static void sas_chain_event(int event, unsigned long *pending, 475 static void sas_chain_event(int event, unsigned long *pending,
472 struct work_struct *work, 476 struct work_struct *work,
473 struct sas_ha_struct *ha) 477 struct sas_ha_struct *ha)
474 { 478 {
475 if (!test_and_set_bit(event, pending)) { 479 if (!test_and_set_bit(event, pending)) {
476 unsigned long flags; 480 unsigned long flags;
477 481
478 spin_lock_irqsave(&ha->state_lock, flags); 482 spin_lock_irqsave(&ha->state_lock, flags);
479 sas_chain_work(ha, work); 483 sas_chain_work(ha, work);
480 spin_unlock_irqrestore(&ha->state_lock, flags); 484 spin_unlock_irqrestore(&ha->state_lock, flags);
481 } 485 }
482 } 486 }
483 487
484 int sas_discover_event(struct asd_sas_port *port, enum discover_event ev) 488 int sas_discover_event(struct asd_sas_port *port, enum discover_event ev)
485 { 489 {
486 struct sas_discovery *disc; 490 struct sas_discovery *disc;
487 491
488 if (!port) 492 if (!port)
489 return 0; 493 return 0;
490 disc = &port->disc; 494 disc = &port->disc;
491 495
492 BUG_ON(ev >= DISC_NUM_EVENTS); 496 BUG_ON(ev >= DISC_NUM_EVENTS);
493 497
494 sas_chain_event(ev, &disc->pending, &disc->disc_work[ev].work, port->ha); 498 sas_chain_event(ev, &disc->pending, &disc->disc_work[ev].work, port->ha);
495 499
496 return 0; 500 return 0;
497 } 501 }
498 502
499 /** 503 /**
500 * sas_init_disc -- initialize the discovery struct in the port 504 * sas_init_disc -- initialize the discovery struct in the port
501 * @port: pointer to struct port 505 * @port: pointer to struct port
502 * 506 *
503 * Called when the ports are being initialized. 507 * Called when the ports are being initialized.
504 */ 508 */
505 void sas_init_disc(struct sas_discovery *disc, struct asd_sas_port *port) 509 void sas_init_disc(struct sas_discovery *disc, struct asd_sas_port *port)
506 { 510 {
507 int i; 511 int i;
508 512
509 static const work_func_t sas_event_fns[DISC_NUM_EVENTS] = { 513 static const work_func_t sas_event_fns[DISC_NUM_EVENTS] = {
510 [DISCE_DISCOVER_DOMAIN] = sas_discover_domain, 514 [DISCE_DISCOVER_DOMAIN] = sas_discover_domain,
511 [DISCE_REVALIDATE_DOMAIN] = sas_revalidate_domain, 515 [DISCE_REVALIDATE_DOMAIN] = sas_revalidate_domain,
512 [DISCE_PROBE] = sas_probe_devices, 516 [DISCE_PROBE] = sas_probe_devices,
513 [DISCE_DESTRUCT] = sas_destruct_devices, 517 [DISCE_DESTRUCT] = sas_destruct_devices,
514 }; 518 };
515 519
516 disc->pending = 0; 520 disc->pending = 0;
517 for (i = 0; i < DISC_NUM_EVENTS; i++) { 521 for (i = 0; i < DISC_NUM_EVENTS; i++) {
518 INIT_WORK(&disc->disc_work[i].work, sas_event_fns[i]); 522 INIT_WORK(&disc->disc_work[i].work, sas_event_fns[i]);
519 disc->disc_work[i].port = port; 523 disc->disc_work[i].port = port;
520 } 524 }
521 } 525 }
drivers/scsi/libsas/sas_internal.h
1 /* 1 /*
2 * Serial Attached SCSI (SAS) class internal header file 2 * Serial Attached SCSI (SAS) class internal header file
3 * 3 *
4 * Copyright (C) 2005 Adaptec, Inc. All rights reserved. 4 * Copyright (C) 2005 Adaptec, Inc. All rights reserved.
5 * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com> 5 * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com>
6 * 6 *
7 * This file is licensed under GPLv2. 7 * This file is licensed under GPLv2.
8 * 8 *
9 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as 10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of the 11 * published by the Free Software Foundation; either version 2 of the
12 * License, or (at your option) any later version. 12 * License, or (at your option) any later version.
13 * 13 *
14 * This program is distributed in the hope that it will be useful, but 14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details. 17 * General Public License for more details.
18 * 18 *
19 * You should have received a copy of the GNU General Public License 19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software 20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 * USA 22 * USA
23 * 23 *
24 */ 24 */
25 25
26 #ifndef _SAS_INTERNAL_H_ 26 #ifndef _SAS_INTERNAL_H_
27 #define _SAS_INTERNAL_H_ 27 #define _SAS_INTERNAL_H_
28 28
29 #include <scsi/scsi.h> 29 #include <scsi/scsi.h>
30 #include <scsi/scsi_host.h> 30 #include <scsi/scsi_host.h>
31 #include <scsi/scsi_transport_sas.h> 31 #include <scsi/scsi_transport_sas.h>
32 #include <scsi/libsas.h> 32 #include <scsi/libsas.h>
33 #include <scsi/sas_ata.h>
33 34
34 #define sas_printk(fmt, ...) printk(KERN_NOTICE "sas: " fmt, ## __VA_ARGS__) 35 #define sas_printk(fmt, ...) printk(KERN_NOTICE "sas: " fmt, ## __VA_ARGS__)
35 36
36 #define SAS_DPRINTK(fmt, ...) printk(KERN_DEBUG "sas: " fmt, ## __VA_ARGS__) 37 #define SAS_DPRINTK(fmt, ...) printk(KERN_DEBUG "sas: " fmt, ## __VA_ARGS__)
37 38
38 #define TO_SAS_TASK(_scsi_cmd) ((void *)(_scsi_cmd)->host_scribble) 39 #define TO_SAS_TASK(_scsi_cmd) ((void *)(_scsi_cmd)->host_scribble)
39 #define ASSIGN_SAS_TASK(_sc, _t) do { (_sc)->host_scribble = (void *) _t; } while (0) 40 #define ASSIGN_SAS_TASK(_sc, _t) do { (_sc)->host_scribble = (void *) _t; } while (0)
40 41
41 struct sas_phy_data { 42 struct sas_phy_data {
42 /* let reset be performed in sas_queue_work() context */ 43 /* let reset be performed in sas_queue_work() context */
43 struct sas_phy *phy; 44 struct sas_phy *phy;
44 struct mutex event_lock; 45 struct mutex event_lock;
45 int hard_reset; 46 int hard_reset;
46 int reset_result; 47 int reset_result;
47 struct work_struct reset_work; 48 struct work_struct reset_work;
48 int enable; 49 int enable;
49 int enable_result; 50 int enable_result;
50 struct work_struct enable_work; 51 struct work_struct enable_work;
51 }; 52 };
52 53
53 void sas_scsi_recover_host(struct Scsi_Host *shost); 54 void sas_scsi_recover_host(struct Scsi_Host *shost);
54 55
55 int sas_show_class(enum sas_class class, char *buf); 56 int sas_show_class(enum sas_class class, char *buf);
56 int sas_show_proto(enum sas_protocol proto, char *buf); 57 int sas_show_proto(enum sas_protocol proto, char *buf);
57 int sas_show_linkrate(enum sas_linkrate linkrate, char *buf); 58 int sas_show_linkrate(enum sas_linkrate linkrate, char *buf);
58 int sas_show_oob_mode(enum sas_oob_mode oob_mode, char *buf); 59 int sas_show_oob_mode(enum sas_oob_mode oob_mode, char *buf);
59 60
60 int sas_register_phys(struct sas_ha_struct *sas_ha); 61 int sas_register_phys(struct sas_ha_struct *sas_ha);
61 void sas_unregister_phys(struct sas_ha_struct *sas_ha); 62 void sas_unregister_phys(struct sas_ha_struct *sas_ha);
62 63
63 int sas_register_ports(struct sas_ha_struct *sas_ha); 64 int sas_register_ports(struct sas_ha_struct *sas_ha);
64 void sas_unregister_ports(struct sas_ha_struct *sas_ha); 65 void sas_unregister_ports(struct sas_ha_struct *sas_ha);
65 66
66 enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *); 67 enum blk_eh_timer_return sas_scsi_timed_out(struct scsi_cmnd *);
67 68
68 int sas_init_queue(struct sas_ha_struct *sas_ha); 69 int sas_init_queue(struct sas_ha_struct *sas_ha);
69 int sas_init_events(struct sas_ha_struct *sas_ha); 70 int sas_init_events(struct sas_ha_struct *sas_ha);
70 void sas_shutdown_queue(struct sas_ha_struct *sas_ha); 71 void sas_shutdown_queue(struct sas_ha_struct *sas_ha);
71 void sas_disable_revalidation(struct sas_ha_struct *ha); 72 void sas_disable_revalidation(struct sas_ha_struct *ha);
72 void sas_enable_revalidation(struct sas_ha_struct *ha); 73 void sas_enable_revalidation(struct sas_ha_struct *ha);
73 void __sas_drain_work(struct sas_ha_struct *ha); 74 void __sas_drain_work(struct sas_ha_struct *ha);
74 75
75 void sas_deform_port(struct asd_sas_phy *phy, int gone); 76 void sas_deform_port(struct asd_sas_phy *phy, int gone);
76 77
77 void sas_porte_bytes_dmaed(struct work_struct *work); 78 void sas_porte_bytes_dmaed(struct work_struct *work);
78 void sas_porte_broadcast_rcvd(struct work_struct *work); 79 void sas_porte_broadcast_rcvd(struct work_struct *work);
79 void sas_porte_link_reset_err(struct work_struct *work); 80 void sas_porte_link_reset_err(struct work_struct *work);
80 void sas_porte_timer_event(struct work_struct *work); 81 void sas_porte_timer_event(struct work_struct *work);
81 void sas_porte_hard_reset(struct work_struct *work); 82 void sas_porte_hard_reset(struct work_struct *work);
82 void sas_queue_work(struct sas_ha_struct *ha, struct work_struct *work); 83 void sas_queue_work(struct sas_ha_struct *ha, struct work_struct *work);
83 84
84 int sas_notify_lldd_dev_found(struct domain_device *); 85 int sas_notify_lldd_dev_found(struct domain_device *);
85 void sas_notify_lldd_dev_gone(struct domain_device *); 86 void sas_notify_lldd_dev_gone(struct domain_device *);
86 87
87 int sas_smp_phy_control(struct domain_device *dev, int phy_id, 88 int sas_smp_phy_control(struct domain_device *dev, int phy_id,
88 enum phy_func phy_func, struct sas_phy_linkrates *); 89 enum phy_func phy_func, struct sas_phy_linkrates *);
89 int sas_smp_get_phy_events(struct sas_phy *phy); 90 int sas_smp_get_phy_events(struct sas_phy *phy);
90 91
91 void sas_device_set_phy(struct domain_device *dev, struct sas_port *port); 92 void sas_device_set_phy(struct domain_device *dev, struct sas_port *port);
92 struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy); 93 struct domain_device *sas_find_dev_by_rphy(struct sas_rphy *rphy);
93 struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id); 94 struct domain_device *sas_ex_to_ata(struct domain_device *ex_dev, int phy_id);
94 int sas_ex_phy_discover(struct domain_device *dev, int single); 95 int sas_ex_phy_discover(struct domain_device *dev, int single);
95 int sas_get_report_phy_sata(struct domain_device *dev, int phy_id, 96 int sas_get_report_phy_sata(struct domain_device *dev, int phy_id,
96 struct smp_resp *rps_resp); 97 struct smp_resp *rps_resp);
97 int sas_try_ata_reset(struct asd_sas_phy *phy); 98 int sas_try_ata_reset(struct asd_sas_phy *phy);
98 void sas_hae_reset(struct work_struct *work); 99 void sas_hae_reset(struct work_struct *work);
99 100
100 void sas_free_device(struct kref *kref); 101 void sas_free_device(struct kref *kref);
101 102
102 #ifdef CONFIG_SCSI_SAS_HOST_SMP 103 #ifdef CONFIG_SCSI_SAS_HOST_SMP
103 extern int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req, 104 extern int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req,
104 struct request *rsp); 105 struct request *rsp);
105 #else 106 #else
106 static inline int sas_smp_host_handler(struct Scsi_Host *shost, 107 static inline int sas_smp_host_handler(struct Scsi_Host *shost,
107 struct request *req, 108 struct request *req,
108 struct request *rsp) 109 struct request *rsp)
109 { 110 {
110 shost_printk(KERN_ERR, shost, 111 shost_printk(KERN_ERR, shost,
111 "Cannot send SMP to a sas host (not enabled in CONFIG)\n"); 112 "Cannot send SMP to a sas host (not enabled in CONFIG)\n");
112 return -EINVAL; 113 return -EINVAL;
113 } 114 }
114 #endif 115 #endif
115 116
116 static inline void sas_fail_probe(struct domain_device *dev, const char *func, int err) 117 static inline void sas_fail_probe(struct domain_device *dev, const char *func, int err)
117 { 118 {
118 SAS_DPRINTK("%s: for %s device %16llx returned %d\n", 119 SAS_DPRINTK("%s: for %s device %16llx returned %d\n",
119 func, dev->parent ? "exp-attached" : 120 func, dev->parent ? "exp-attached" :
120 "direct-attached", 121 "direct-attached",
121 SAS_ADDR(dev->sas_addr), err); 122 SAS_ADDR(dev->sas_addr), err);
122 sas_unregister_dev(dev->port, dev); 123 sas_unregister_dev(dev->port, dev);
123 } 124 }
124 125
125 static inline void sas_fill_in_rphy(struct domain_device *dev, 126 static inline void sas_fill_in_rphy(struct domain_device *dev,
126 struct sas_rphy *rphy) 127 struct sas_rphy *rphy)
127 { 128 {
128 rphy->identify.sas_address = SAS_ADDR(dev->sas_addr); 129 rphy->identify.sas_address = SAS_ADDR(dev->sas_addr);
129 rphy->identify.initiator_port_protocols = dev->iproto; 130 rphy->identify.initiator_port_protocols = dev->iproto;
130 rphy->identify.target_port_protocols = dev->tproto; 131 rphy->identify.target_port_protocols = dev->tproto;
131 switch (dev->dev_type) { 132 switch (dev->dev_type) {
132 case SATA_DEV: 133 case SATA_DEV:
133 /* FIXME: need sata device type */ 134 /* FIXME: need sata device type */
134 case SAS_END_DEV: 135 case SAS_END_DEV:
135 case SATA_PENDING: 136 case SATA_PENDING:
136 rphy->identify.device_type = SAS_END_DEVICE; 137 rphy->identify.device_type = SAS_END_DEVICE;
137 break; 138 break;
138 case EDGE_DEV: 139 case EDGE_DEV:
139 rphy->identify.device_type = SAS_EDGE_EXPANDER_DEVICE; 140 rphy->identify.device_type = SAS_EDGE_EXPANDER_DEVICE;
140 break; 141 break;
141 case FANOUT_DEV: 142 case FANOUT_DEV:
142 rphy->identify.device_type = SAS_FANOUT_EXPANDER_DEVICE; 143 rphy->identify.device_type = SAS_FANOUT_EXPANDER_DEVICE;
143 break; 144 break;
144 default: 145 default:
145 rphy->identify.device_type = SAS_PHY_UNUSED; 146 rphy->identify.device_type = SAS_PHY_UNUSED;
146 break; 147 break;
148 }
149 }
150
151 static inline void sas_phy_set_target(struct asd_sas_phy *p, struct domain_device *dev)
152 {
153 struct sas_phy *phy = p->phy;
154
155 if (dev) {
156 if (dev_is_sata(dev))
157 phy->identify.device_type = SAS_END_DEVICE;
158 else
159 phy->identify.device_type = dev->dev_type;
160 phy->identify.target_port_protocols = dev->tproto;
161 } else {
162 phy->identify.device_type = SAS_PHY_UNUSED;
163 phy->identify.target_port_protocols = 0;
147 } 164 }
148 } 165 }
149 166
150 static inline void sas_add_parent_port(struct domain_device *dev, int phy_id) 167 static inline void sas_add_parent_port(struct domain_device *dev, int phy_id)
151 { 168 {
152 struct expander_device *ex = &dev->ex_dev; 169 struct expander_device *ex = &dev->ex_dev;
153 struct ex_phy *ex_phy = &ex->ex_phy[phy_id]; 170 struct ex_phy *ex_phy = &ex->ex_phy[phy_id];
154 171
155 if (!ex->parent_port) { 172 if (!ex->parent_port) {
156 ex->parent_port = sas_port_alloc(&dev->rphy->dev, phy_id); 173 ex->parent_port = sas_port_alloc(&dev->rphy->dev, phy_id);
157 /* FIXME: error handling */ 174 /* FIXME: error handling */
158 BUG_ON(!ex->parent_port); 175 BUG_ON(!ex->parent_port);
159 BUG_ON(sas_port_add(ex->parent_port)); 176 BUG_ON(sas_port_add(ex->parent_port));
160 sas_port_mark_backlink(ex->parent_port); 177 sas_port_mark_backlink(ex->parent_port);
161 } 178 }
162 sas_port_add_phy(ex->parent_port, ex_phy->phy); 179 sas_port_add_phy(ex->parent_port, ex_phy->phy);
163 } 180 }
164 181
165 static inline struct domain_device *sas_alloc_device(void) 182 static inline struct domain_device *sas_alloc_device(void)
166 { 183 {
167 struct domain_device *dev = kzalloc(sizeof(*dev), GFP_KERNEL); 184 struct domain_device *dev = kzalloc(sizeof(*dev), GFP_KERNEL);
168 185
169 if (dev) { 186 if (dev) {
170 INIT_LIST_HEAD(&dev->siblings); 187 INIT_LIST_HEAD(&dev->siblings);
171 INIT_LIST_HEAD(&dev->dev_list_node); 188 INIT_LIST_HEAD(&dev->dev_list_node);
172 INIT_LIST_HEAD(&dev->disco_list_node); 189 INIT_LIST_HEAD(&dev->disco_list_node);
173 kref_init(&dev->kref); 190 kref_init(&dev->kref);
174 spin_lock_init(&dev->done_lock); 191 spin_lock_init(&dev->done_lock);
175 } 192 }
176 return dev; 193 return dev;
177 } 194 }
178 195
179 static inline void sas_put_device(struct domain_device *dev) 196 static inline void sas_put_device(struct domain_device *dev)
180 { 197 {
181 kref_put(&dev->kref, sas_free_device); 198 kref_put(&dev->kref, sas_free_device);
182 } 199 }
183 200
184 #endif /* _SAS_INTERNAL_H_ */ 201 #endif /* _SAS_INTERNAL_H_ */
185 202
drivers/scsi/libsas/sas_port.c
1 /* 1 /*
2 * Serial Attached SCSI (SAS) Port class 2 * Serial Attached SCSI (SAS) Port class
3 * 3 *
4 * Copyright (C) 2005 Adaptec, Inc. All rights reserved. 4 * Copyright (C) 2005 Adaptec, Inc. All rights reserved.
5 * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com> 5 * Copyright (C) 2005 Luben Tuikov <luben_tuikov@adaptec.com>
6 * 6 *
7 * This file is licensed under GPLv2. 7 * This file is licensed under GPLv2.
8 * 8 *
9 * This program is free software; you can redistribute it and/or 9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as 10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation; either version 2 of the 11 * published by the Free Software Foundation; either version 2 of the
12 * License, or (at your option) any later version. 12 * License, or (at your option) any later version.
13 * 13 *
14 * This program is distributed in the hope that it will be useful, but 14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of 15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details. 17 * General Public License for more details.
18 * 18 *
19 * You should have received a copy of the GNU General Public License 19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software 20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 21 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 * 22 *
23 */ 23 */
24 24
25 #include "sas_internal.h" 25 #include "sas_internal.h"
26 26
27 #include <scsi/scsi_transport.h> 27 #include <scsi/scsi_transport.h>
28 #include <scsi/scsi_transport_sas.h> 28 #include <scsi/scsi_transport_sas.h>
29 #include "../scsi_sas_internal.h" 29 #include "../scsi_sas_internal.h"
30 30
31 static bool phy_is_wideport_member(struct asd_sas_port *port, struct asd_sas_phy *phy) 31 static bool phy_is_wideport_member(struct asd_sas_port *port, struct asd_sas_phy *phy)
32 { 32 {
33 struct sas_ha_struct *sas_ha = phy->ha; 33 struct sas_ha_struct *sas_ha = phy->ha;
34 34
35 if (memcmp(port->attached_sas_addr, phy->attached_sas_addr, 35 if (memcmp(port->attached_sas_addr, phy->attached_sas_addr,
36 SAS_ADDR_SIZE) != 0 || (sas_ha->strict_wide_ports && 36 SAS_ADDR_SIZE) != 0 || (sas_ha->strict_wide_ports &&
37 memcmp(port->sas_addr, phy->sas_addr, SAS_ADDR_SIZE) != 0)) 37 memcmp(port->sas_addr, phy->sas_addr, SAS_ADDR_SIZE) != 0))
38 return false; 38 return false;
39 return true; 39 return true;
40 } 40 }
41 41
42 /** 42 /**
43 * sas_form_port -- add this phy to a port 43 * sas_form_port -- add this phy to a port
44 * @phy: the phy of interest 44 * @phy: the phy of interest
45 * 45 *
46 * This function adds this phy to an existing port, thus creating a wide 46 * This function adds this phy to an existing port, thus creating a wide
47 * port, or it creates a port and adds the phy to the port. 47 * port, or it creates a port and adds the phy to the port.
48 */ 48 */
49 static void sas_form_port(struct asd_sas_phy *phy) 49 static void sas_form_port(struct asd_sas_phy *phy)
50 { 50 {
51 int i; 51 int i;
52 struct sas_ha_struct *sas_ha = phy->ha; 52 struct sas_ha_struct *sas_ha = phy->ha;
53 struct asd_sas_port *port = phy->port; 53 struct asd_sas_port *port = phy->port;
54 struct sas_internal *si = 54 struct sas_internal *si =
55 to_sas_internal(sas_ha->core.shost->transportt); 55 to_sas_internal(sas_ha->core.shost->transportt);
56 unsigned long flags; 56 unsigned long flags;
57 57
58 if (port) { 58 if (port) {
59 if (!phy_is_wideport_member(port, phy)) 59 if (!phy_is_wideport_member(port, phy))
60 sas_deform_port(phy, 0); 60 sas_deform_port(phy, 0);
61 else { 61 else {
62 SAS_DPRINTK("%s: phy%d belongs to port%d already(%d)!\n", 62 SAS_DPRINTK("%s: phy%d belongs to port%d already(%d)!\n",
63 __func__, phy->id, phy->port->id, 63 __func__, phy->id, phy->port->id,
64 phy->port->num_phys); 64 phy->port->num_phys);
65 return; 65 return;
66 } 66 }
67 } 67 }
68 68
69 /* see if the phy should be part of a wide port */ 69 /* see if the phy should be part of a wide port */
70 spin_lock_irqsave(&sas_ha->phy_port_lock, flags); 70 spin_lock_irqsave(&sas_ha->phy_port_lock, flags);
71 for (i = 0; i < sas_ha->num_phys; i++) { 71 for (i = 0; i < sas_ha->num_phys; i++) {
72 port = sas_ha->sas_port[i]; 72 port = sas_ha->sas_port[i];
73 spin_lock(&port->phy_list_lock); 73 spin_lock(&port->phy_list_lock);
74 if (*(u64 *) port->sas_addr && 74 if (*(u64 *) port->sas_addr &&
75 phy_is_wideport_member(port, phy) && port->num_phys > 0) { 75 phy_is_wideport_member(port, phy) && port->num_phys > 0) {
76 /* wide port */ 76 /* wide port */
77 SAS_DPRINTK("phy%d matched wide port%d\n", phy->id, 77 SAS_DPRINTK("phy%d matched wide port%d\n", phy->id,
78 port->id); 78 port->id);
79 break; 79 break;
80 } 80 }
81 spin_unlock(&port->phy_list_lock); 81 spin_unlock(&port->phy_list_lock);
82 } 82 }
83 /* The phy does not match any existing port, create a new one */ 83 /* The phy does not match any existing port, create a new one */
84 if (i == sas_ha->num_phys) { 84 if (i == sas_ha->num_phys) {
85 for (i = 0; i < sas_ha->num_phys; i++) { 85 for (i = 0; i < sas_ha->num_phys; i++) {
86 port = sas_ha->sas_port[i]; 86 port = sas_ha->sas_port[i];
87 spin_lock(&port->phy_list_lock); 87 spin_lock(&port->phy_list_lock);
88 if (*(u64 *)port->sas_addr == 0 88 if (*(u64 *)port->sas_addr == 0
89 && port->num_phys == 0) { 89 && port->num_phys == 0) {
90 memcpy(port->sas_addr, phy->sas_addr, 90 memcpy(port->sas_addr, phy->sas_addr,
91 SAS_ADDR_SIZE); 91 SAS_ADDR_SIZE);
92 break; 92 break;
93 } 93 }
94 spin_unlock(&port->phy_list_lock); 94 spin_unlock(&port->phy_list_lock);
95 } 95 }
96 } 96 }
97 97
98 if (i >= sas_ha->num_phys) { 98 if (i >= sas_ha->num_phys) {
99 printk(KERN_NOTICE "%s: couldn't find a free port, bug?\n", 99 printk(KERN_NOTICE "%s: couldn't find a free port, bug?\n",
100 __func__); 100 __func__);
101 spin_unlock_irqrestore(&sas_ha->phy_port_lock, flags); 101 spin_unlock_irqrestore(&sas_ha->phy_port_lock, flags);
102 return; 102 return;
103 } 103 }
104 104
105 /* add the phy to the port */ 105 /* add the phy to the port */
106 list_add_tail(&phy->port_phy_el, &port->phy_list); 106 list_add_tail(&phy->port_phy_el, &port->phy_list);
107 sas_phy_set_target(phy, port->port_dev);
107 phy->port = port; 108 phy->port = port;
108 port->num_phys++; 109 port->num_phys++;
109 port->phy_mask |= (1U << phy->id); 110 port->phy_mask |= (1U << phy->id);
110 111
111 if (*(u64 *)port->attached_sas_addr == 0) { 112 if (*(u64 *)port->attached_sas_addr == 0) {
112 port->class = phy->class; 113 port->class = phy->class;
113 memcpy(port->attached_sas_addr, phy->attached_sas_addr, 114 memcpy(port->attached_sas_addr, phy->attached_sas_addr,
114 SAS_ADDR_SIZE); 115 SAS_ADDR_SIZE);
115 port->iproto = phy->iproto; 116 port->iproto = phy->iproto;
116 port->tproto = phy->tproto; 117 port->tproto = phy->tproto;
117 port->oob_mode = phy->oob_mode; 118 port->oob_mode = phy->oob_mode;
118 port->linkrate = phy->linkrate; 119 port->linkrate = phy->linkrate;
119 } else 120 } else
120 port->linkrate = max(port->linkrate, phy->linkrate); 121 port->linkrate = max(port->linkrate, phy->linkrate);
121 spin_unlock(&port->phy_list_lock); 122 spin_unlock(&port->phy_list_lock);
122 spin_unlock_irqrestore(&sas_ha->phy_port_lock, flags); 123 spin_unlock_irqrestore(&sas_ha->phy_port_lock, flags);
123 124
124 if (!port->port) { 125 if (!port->port) {
125 port->port = sas_port_alloc(phy->phy->dev.parent, phy->id); 126 port->port = sas_port_alloc(phy->phy->dev.parent, phy->id);
126 BUG_ON(!port->port); 127 BUG_ON(!port->port);
127 sas_port_add(port->port); 128 sas_port_add(port->port);
128 } 129 }
129 sas_port_add_phy(port->port, phy->phy); 130 sas_port_add_phy(port->port, phy->phy);
130 131
131 SAS_DPRINTK("%s added to %s, phy_mask:0x%x (%16llx)\n", 132 SAS_DPRINTK("%s added to %s, phy_mask:0x%x (%16llx)\n",
132 dev_name(&phy->phy->dev), dev_name(&port->port->dev), 133 dev_name(&phy->phy->dev), dev_name(&port->port->dev),
133 port->phy_mask, 134 port->phy_mask,
134 SAS_ADDR(port->attached_sas_addr)); 135 SAS_ADDR(port->attached_sas_addr));
135 136
136 if (port->port_dev) 137 if (port->port_dev)
137 port->port_dev->pathways = port->num_phys; 138 port->port_dev->pathways = port->num_phys;
138 139
139 /* Tell the LLDD about this port formation. */ 140 /* Tell the LLDD about this port formation. */
140 if (si->dft->lldd_port_formed) 141 if (si->dft->lldd_port_formed)
141 si->dft->lldd_port_formed(phy); 142 si->dft->lldd_port_formed(phy);
142 143
143 sas_discover_event(phy->port, DISCE_DISCOVER_DOMAIN); 144 sas_discover_event(phy->port, DISCE_DISCOVER_DOMAIN);
144 } 145 }
145 146
146 /** 147 /**
147 * sas_deform_port -- remove this phy from the port it belongs to 148 * sas_deform_port -- remove this phy from the port it belongs to
148 * @phy: the phy of interest 149 * @phy: the phy of interest
149 * 150 *
150 * This is called when the physical link to the other phy has been 151 * This is called when the physical link to the other phy has been
151 * lost (on this phy), in Event thread context. We cannot delay here. 152 * lost (on this phy), in Event thread context. We cannot delay here.
152 */ 153 */
153 void sas_deform_port(struct asd_sas_phy *phy, int gone) 154 void sas_deform_port(struct asd_sas_phy *phy, int gone)
154 { 155 {
155 struct sas_ha_struct *sas_ha = phy->ha; 156 struct sas_ha_struct *sas_ha = phy->ha;
156 struct asd_sas_port *port = phy->port; 157 struct asd_sas_port *port = phy->port;
157 struct sas_internal *si = 158 struct sas_internal *si =
158 to_sas_internal(sas_ha->core.shost->transportt); 159 to_sas_internal(sas_ha->core.shost->transportt);
159 struct domain_device *dev; 160 struct domain_device *dev;
160 unsigned long flags; 161 unsigned long flags;
161 162
162 if (!port) 163 if (!port)
163 return; /* done by a phy event */ 164 return; /* done by a phy event */
164 165
165 dev = port->port_dev; 166 dev = port->port_dev;
166 if (dev) 167 if (dev)
167 dev->pathways--; 168 dev->pathways--;
168 169
169 if (port->num_phys == 1) { 170 if (port->num_phys == 1) {
170 sas_unregister_domain_devices(port, gone); 171 sas_unregister_domain_devices(port, gone);
171 sas_port_delete(port->port); 172 sas_port_delete(port->port);
172 port->port = NULL; 173 port->port = NULL;
173 } else { 174 } else {
174 sas_port_delete_phy(port->port, phy->phy); 175 sas_port_delete_phy(port->port, phy->phy);
175 sas_device_set_phy(dev, port->port); 176 sas_device_set_phy(dev, port->port);
176 } 177 }
177 178
178 if (si->dft->lldd_port_deformed) 179 if (si->dft->lldd_port_deformed)
179 si->dft->lldd_port_deformed(phy); 180 si->dft->lldd_port_deformed(phy);
180 181
181 spin_lock_irqsave(&sas_ha->phy_port_lock, flags); 182 spin_lock_irqsave(&sas_ha->phy_port_lock, flags);
182 spin_lock(&port->phy_list_lock); 183 spin_lock(&port->phy_list_lock);
183 184
184 list_del_init(&phy->port_phy_el); 185 list_del_init(&phy->port_phy_el);
186 sas_phy_set_target(phy, NULL);
185 phy->port = NULL; 187 phy->port = NULL;
186 port->num_phys--; 188 port->num_phys--;
187 port->phy_mask &= ~(1U << phy->id); 189 port->phy_mask &= ~(1U << phy->id);
188 190
189 if (port->num_phys == 0) { 191 if (port->num_phys == 0) {
190 INIT_LIST_HEAD(&port->phy_list); 192 INIT_LIST_HEAD(&port->phy_list);
191 memset(port->sas_addr, 0, SAS_ADDR_SIZE); 193 memset(port->sas_addr, 0, SAS_ADDR_SIZE);
192 memset(port->attached_sas_addr, 0, SAS_ADDR_SIZE); 194 memset(port->attached_sas_addr, 0, SAS_ADDR_SIZE);
193 port->class = 0; 195 port->class = 0;
194 port->iproto = 0; 196 port->iproto = 0;
195 port->tproto = 0; 197 port->tproto = 0;
196 port->oob_mode = 0; 198 port->oob_mode = 0;
197 port->phy_mask = 0; 199 port->phy_mask = 0;
198 } 200 }
199 spin_unlock(&port->phy_list_lock); 201 spin_unlock(&port->phy_list_lock);
200 spin_unlock_irqrestore(&sas_ha->phy_port_lock, flags); 202 spin_unlock_irqrestore(&sas_ha->phy_port_lock, flags);
201 203
202 return; 204 return;
203 } 205 }
204 206
205 /* ---------- SAS port events ---------- */ 207 /* ---------- SAS port events ---------- */
206 208
207 void sas_porte_bytes_dmaed(struct work_struct *work) 209 void sas_porte_bytes_dmaed(struct work_struct *work)
208 { 210 {
209 struct asd_sas_event *ev = 211 struct asd_sas_event *ev =
210 container_of(work, struct asd_sas_event, work); 212 container_of(work, struct asd_sas_event, work);
211 struct asd_sas_phy *phy = ev->phy; 213 struct asd_sas_phy *phy = ev->phy;
212 214
213 clear_bit(PORTE_BYTES_DMAED, &phy->port_events_pending); 215 clear_bit(PORTE_BYTES_DMAED, &phy->port_events_pending);
214 216
215 sas_form_port(phy); 217 sas_form_port(phy);
216 } 218 }
217 219
218 void sas_porte_broadcast_rcvd(struct work_struct *work) 220 void sas_porte_broadcast_rcvd(struct work_struct *work)
219 { 221 {
220 struct asd_sas_event *ev = 222 struct asd_sas_event *ev =
221 container_of(work, struct asd_sas_event, work); 223 container_of(work, struct asd_sas_event, work);
222 struct asd_sas_phy *phy = ev->phy; 224 struct asd_sas_phy *phy = ev->phy;
223 unsigned long flags; 225 unsigned long flags;
224 u32 prim; 226 u32 prim;
225 227
226 clear_bit(PORTE_BROADCAST_RCVD, &phy->port_events_pending); 228 clear_bit(PORTE_BROADCAST_RCVD, &phy->port_events_pending);
227 229
228 spin_lock_irqsave(&phy->sas_prim_lock, flags); 230 spin_lock_irqsave(&phy->sas_prim_lock, flags);
229 prim = phy->sas_prim; 231 prim = phy->sas_prim;
230 spin_unlock_irqrestore(&phy->sas_prim_lock, flags); 232 spin_unlock_irqrestore(&phy->sas_prim_lock, flags);
231 233
232 SAS_DPRINTK("broadcast received: %d\n", prim); 234 SAS_DPRINTK("broadcast received: %d\n", prim);
233 sas_discover_event(phy->port, DISCE_REVALIDATE_DOMAIN); 235 sas_discover_event(phy->port, DISCE_REVALIDATE_DOMAIN);
234 } 236 }
235 237
236 void sas_porte_link_reset_err(struct work_struct *work) 238 void sas_porte_link_reset_err(struct work_struct *work)
237 { 239 {
238 struct asd_sas_event *ev = 240 struct asd_sas_event *ev =
239 container_of(work, struct asd_sas_event, work); 241 container_of(work, struct asd_sas_event, work);
240 struct asd_sas_phy *phy = ev->phy; 242 struct asd_sas_phy *phy = ev->phy;
241 243
242 clear_bit(PORTE_LINK_RESET_ERR, &phy->port_events_pending); 244 clear_bit(PORTE_LINK_RESET_ERR, &phy->port_events_pending);
243 245
244 sas_deform_port(phy, 1); 246 sas_deform_port(phy, 1);
245 } 247 }
246 248
247 void sas_porte_timer_event(struct work_struct *work) 249 void sas_porte_timer_event(struct work_struct *work)
248 { 250 {
249 struct asd_sas_event *ev = 251 struct asd_sas_event *ev =
250 container_of(work, struct asd_sas_event, work); 252 container_of(work, struct asd_sas_event, work);
251 struct asd_sas_phy *phy = ev->phy; 253 struct asd_sas_phy *phy = ev->phy;
252 254
253 clear_bit(PORTE_TIMER_EVENT, &phy->port_events_pending); 255 clear_bit(PORTE_TIMER_EVENT, &phy->port_events_pending);
254 256
255 sas_deform_port(phy, 1); 257 sas_deform_port(phy, 1);
256 } 258 }
257 259
258 void sas_porte_hard_reset(struct work_struct *work) 260 void sas_porte_hard_reset(struct work_struct *work)
259 { 261 {
260 struct asd_sas_event *ev = 262 struct asd_sas_event *ev =
261 container_of(work, struct asd_sas_event, work); 263 container_of(work, struct asd_sas_event, work);
262 struct asd_sas_phy *phy = ev->phy; 264 struct asd_sas_phy *phy = ev->phy;
263 265
264 clear_bit(PORTE_HARD_RESET, &phy->port_events_pending); 266 clear_bit(PORTE_HARD_RESET, &phy->port_events_pending);
265 267
266 sas_deform_port(phy, 1); 268 sas_deform_port(phy, 1);
267 } 269 }
268 270
269 /* ---------- SAS port registration ---------- */ 271 /* ---------- SAS port registration ---------- */
270 272
271 static void sas_init_port(struct asd_sas_port *port, 273 static void sas_init_port(struct asd_sas_port *port,
272 struct sas_ha_struct *sas_ha, int i) 274 struct sas_ha_struct *sas_ha, int i)
273 { 275 {
274 memset(port, 0, sizeof(*port)); 276 memset(port, 0, sizeof(*port));
275 port->id = i; 277 port->id = i;
276 INIT_LIST_HEAD(&port->dev_list); 278 INIT_LIST_HEAD(&port->dev_list);
277 INIT_LIST_HEAD(&port->disco_list); 279 INIT_LIST_HEAD(&port->disco_list);
278 INIT_LIST_HEAD(&port->destroy_list); 280 INIT_LIST_HEAD(&port->destroy_list);
279 spin_lock_init(&port->phy_list_lock); 281 spin_lock_init(&port->phy_list_lock);
280 INIT_LIST_HEAD(&port->phy_list); 282 INIT_LIST_HEAD(&port->phy_list);
281 port->ha = sas_ha; 283 port->ha = sas_ha;
282 284
283 spin_lock_init(&port->dev_list_lock); 285 spin_lock_init(&port->dev_list_lock);
284 } 286 }
285 287
286 int sas_register_ports(struct sas_ha_struct *sas_ha) 288 int sas_register_ports(struct sas_ha_struct *sas_ha)
287 { 289 {
288 int i; 290 int i;
289 291
290 /* initialize the ports and discovery */ 292 /* initialize the ports and discovery */
291 for (i = 0; i < sas_ha->num_phys; i++) { 293 for (i = 0; i < sas_ha->num_phys; i++) {
292 struct asd_sas_port *port = sas_ha->sas_port[i]; 294 struct asd_sas_port *port = sas_ha->sas_port[i];
293 295
294 sas_init_port(port, sas_ha, i); 296 sas_init_port(port, sas_ha, i);
295 sas_init_disc(&port->disc, port); 297 sas_init_disc(&port->disc, port);
296 } 298 }
297 return 0; 299 return 0;
298 } 300 }
299 301
300 void sas_unregister_ports(struct sas_ha_struct *sas_ha) 302 void sas_unregister_ports(struct sas_ha_struct *sas_ha)
301 { 303 {
302 int i; 304 int i;
303 305
304 for (i = 0; i < sas_ha->num_phys; i++) 306 for (i = 0; i < sas_ha->num_phys; i++)
305 if (sas_ha->sas_phy[i]->port) 307 if (sas_ha->sas_phy[i]->port)
306 sas_deform_port(sas_ha->sas_phy[i], 0); 308 sas_deform_port(sas_ha->sas_phy[i], 0);
307 309
308 } 310 }
309 311