blob: f49f12515c509398345aa868bec87d8a470397bb [file] [log] [blame]
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001/*
2 * linux/drivers/message/fusion/mptsas.c
3 * For use with LSI Logic PCI chip/adapter(s)
4 * running LSI Logic Fusion MPT (Message Passing Technology) firmware.
5 *
6 * Copyright (c) 1999-2005 LSI Logic Corporation
7 * (mailto:mpt_linux_developer@lsil.com)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01008 * Copyright (c) 2005-2006 Dell
Christoph Hellwig0c33b272005-09-09 16:27:19 +02009 */
10/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
11/*
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU General Public License as published by
14 the Free Software Foundation; version 2 of the License.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 NO WARRANTY
22 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
23 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
24 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
25 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
26 solely responsible for determining the appropriateness of using and
27 distributing the Program and assumes all risks associated with its
28 exercise of rights under this Agreement, including but not limited to
29 the risks and costs of program errors, damage to or loss of data,
30 programs or equipment, and unavailability or interruption of operations.
31
32 DISCLAIMER OF LIABILITY
33 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
34 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
36 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
37 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
38 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
39 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
40
41 You should have received a copy of the GNU General Public License
42 along with this program; if not, write to the Free Software
43 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
44*/
45/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
46
47#include <linux/module.h>
48#include <linux/kernel.h>
49#include <linux/init.h>
50#include <linux/errno.h>
51#include <linux/sched.h>
52#include <linux/workqueue.h>
Eric Moore547f9a22006-06-27 14:42:12 -060053#include <linux/delay.h> /* for mdelay */
Christoph Hellwig0c33b272005-09-09 16:27:19 +020054
Eric Moore547f9a22006-06-27 14:42:12 -060055#include <scsi/scsi.h>
Christoph Hellwig0c33b272005-09-09 16:27:19 +020056#include <scsi/scsi_cmnd.h>
57#include <scsi/scsi_device.h>
58#include <scsi/scsi_host.h>
59#include <scsi/scsi_transport_sas.h>
Eric Moore547f9a22006-06-27 14:42:12 -060060#include <scsi/scsi_dbg.h>
Christoph Hellwig0c33b272005-09-09 16:27:19 +020061
62#include "mptbase.h"
63#include "mptscsih.h"
64
65
66#define my_NAME "Fusion MPT SAS Host driver"
67#define my_VERSION MPT_LINUX_VERSION_COMMON
68#define MYNAM "mptsas"
69
James Bottomleye8bf3942006-07-11 17:49:34 -040070/*
71 * Reserved channel for integrated raid
72 */
73#define MPTSAS_RAID_CHANNEL 1
74
Christoph Hellwig0c33b272005-09-09 16:27:19 +020075MODULE_AUTHOR(MODULEAUTHOR);
76MODULE_DESCRIPTION(my_NAME);
77MODULE_LICENSE("GPL");
78
Christoph Hellwig0c33b272005-09-09 16:27:19 +020079static int mpt_pt_clear;
80module_param(mpt_pt_clear, int, 0);
81MODULE_PARM_DESC(mpt_pt_clear,
Eric Mooreba856d32006-07-11 17:34:01 -060082 " Clear persistency table: enable=1 "
Christoph Hellwig0c33b272005-09-09 16:27:19 +020083 "(default=MPTSCSIH_PT_CLEAR=0)");
84
85static int mptsasDoneCtx = -1;
86static int mptsasTaskCtx = -1;
87static int mptsasInternalCtx = -1; /* Used only for internal commands */
Christoph Hellwigda4fa652005-10-19 20:01:42 +020088static int mptsasMgmtCtx = -1;
Christoph Hellwig0c33b272005-09-09 16:27:19 +020089
90
Christoph Hellwig9a28f492006-01-13 18:04:41 +010091enum mptsas_hotplug_action {
92 MPTSAS_ADD_DEVICE,
93 MPTSAS_DEL_DEVICE,
Moore, Ericc73787ee2006-01-26 16:20:06 -070094 MPTSAS_ADD_RAID,
95 MPTSAS_DEL_RAID,
Moore, Ericbd23e942006-04-17 12:43:04 -060096 MPTSAS_IGNORE_EVENT,
Christoph Hellwig9a28f492006-01-13 18:04:41 +010097};
98
99struct mptsas_hotplug_event {
100 struct work_struct work;
101 MPT_ADAPTER *ioc;
102 enum mptsas_hotplug_action event_type;
103 u64 sas_address;
104 u32 channel;
105 u32 id;
106 u32 device_info;
107 u16 handle;
108 u16 parent_handle;
109 u8 phy_id;
Moore, Ericf44e5462006-03-14 09:14:21 -0700110 u8 phys_disk_num;
111 u8 phys_disk_num_valid;
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100112};
113
Moore, Erice6b2d762006-03-14 09:14:24 -0700114struct mptsas_discovery_event {
115 struct work_struct work;
116 MPT_ADAPTER *ioc;
117};
118
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200119/*
120 * SAS topology structures
121 *
122 * The MPT Fusion firmware interface spreads information about the
123 * SAS topology over many manufacture pages, thus we need some data
124 * structure to collect it and process it for the SAS transport class.
125 */
126
127struct mptsas_devinfo {
128 u16 handle; /* unique id to address this device */
Moore, Ericc73787ee2006-01-26 16:20:06 -0700129 u16 handle_parent; /* unique id to address parent device */
Christoph Hellwige3094442006-02-16 13:25:36 +0100130 u16 handle_enclosure; /* enclosure identifier of the enclosure */
131 u16 slot; /* physical slot in enclosure */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200132 u8 phy_id; /* phy number of parent device */
133 u8 port_id; /* sas physical port this device
134 is assoc'd with */
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100135 u8 id; /* logical target id of this device */
136 u8 channel; /* logical bus number of this device */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200137 u64 sas_address; /* WWN of this device,
138 SATA is assigned by HBA,expander */
139 u32 device_info; /* bitfield detailed info about this device */
140};
141
Eric Moore547f9a22006-06-27 14:42:12 -0600142/*
143 * Specific details on ports, wide/narrow
144 */
145struct mptsas_portinfo_details{
Eric Moore547f9a22006-06-27 14:42:12 -0600146 u16 num_phys; /* number of phys belong to this port */
147 u64 phy_bitmask; /* TODO, extend support for 255 phys */
148 struct sas_rphy *rphy; /* transport layer rphy object */
149 struct sas_port *port; /* transport layer port object */
150 struct scsi_target *starget;
151 struct mptsas_portinfo *port_info;
152};
153
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200154struct mptsas_phyinfo {
155 u8 phy_id; /* phy index */
Eric Moore547f9a22006-06-27 14:42:12 -0600156 u8 port_id; /* firmware port identifier */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200157 u8 negotiated_link_rate; /* nego'd link rate for this phy */
158 u8 hw_link_rate; /* hardware max/min phys link rate */
159 u8 programmed_link_rate; /* programmed max/min phy link rate */
Eric Moore547f9a22006-06-27 14:42:12 -0600160 u8 sas_port_add_phy; /* flag to request sas_port_add_phy*/
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200161 struct mptsas_devinfo identify; /* point to phy device info */
162 struct mptsas_devinfo attached; /* point to attached device info */
Eric Moore547f9a22006-06-27 14:42:12 -0600163 struct sas_phy *phy; /* transport layer phy object */
164 struct mptsas_portinfo *portinfo;
165 struct mptsas_portinfo_details * port_details;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200166};
167
168struct mptsas_portinfo {
169 struct list_head list;
170 u16 handle; /* unique id to address this */
Eric Moore547f9a22006-06-27 14:42:12 -0600171 u16 num_phys; /* number of phys */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200172 struct mptsas_phyinfo *phy_info;
173};
174
Christoph Hellwige3094442006-02-16 13:25:36 +0100175struct mptsas_enclosure {
176 u64 enclosure_logical_id; /* The WWN for the enclosure */
177 u16 enclosure_handle; /* unique id to address this */
178 u16 flags; /* details enclosure management */
179 u16 num_slot; /* num slots */
180 u16 start_slot; /* first slot */
181 u8 start_id; /* starting logical target id */
182 u8 start_channel; /* starting logical channel id */
183 u8 sep_id; /* SEP device logical target id */
184 u8 sep_channel; /* SEP channel logical channel id */
185};
186
Eric Moore547f9a22006-06-27 14:42:12 -0600187#ifdef MPT_DEBUG_SAS
Christoph Hellwigb5141122005-10-28 22:07:41 +0200188static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
189{
190 printk("---- IO UNIT PAGE 0 ------------\n");
191 printk("Handle=0x%X\n",
192 le16_to_cpu(phy_data->AttachedDeviceHandle));
193 printk("Controller Handle=0x%X\n",
194 le16_to_cpu(phy_data->ControllerDevHandle));
195 printk("Port=0x%X\n", phy_data->Port);
196 printk("Port Flags=0x%X\n", phy_data->PortFlags);
197 printk("PHY Flags=0x%X\n", phy_data->PhyFlags);
198 printk("Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate);
199 printk("Controller PHY Device Info=0x%X\n",
200 le32_to_cpu(phy_data->ControllerPhyDeviceInfo));
201 printk("DiscoveryStatus=0x%X\n",
202 le32_to_cpu(phy_data->DiscoveryStatus));
203 printk("\n");
204}
205
206static void mptsas_print_phy_pg0(SasPhyPage0_t *pg0)
207{
208 __le64 sas_address;
209
210 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
211
212 printk("---- SAS PHY PAGE 0 ------------\n");
213 printk("Attached Device Handle=0x%X\n",
214 le16_to_cpu(pg0->AttachedDevHandle));
215 printk("SAS Address=0x%llX\n",
216 (unsigned long long)le64_to_cpu(sas_address));
217 printk("Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier);
218 printk("Attached Device Info=0x%X\n",
219 le32_to_cpu(pg0->AttachedDeviceInfo));
220 printk("Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate);
221 printk("Change Count=0x%X\n", pg0->ChangeCount);
222 printk("PHY Info=0x%X\n", le32_to_cpu(pg0->PhyInfo));
223 printk("\n");
224}
225
226static void mptsas_print_phy_pg1(SasPhyPage1_t *pg1)
227{
228 printk("---- SAS PHY PAGE 1 ------------\n");
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200229 printk("Invalid Dword Count=0x%x\n", pg1->InvalidDwordCount);
230 printk("Running Disparity Error Count=0x%x\n",
Christoph Hellwigb5141122005-10-28 22:07:41 +0200231 pg1->RunningDisparityErrorCount);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200232 printk("Loss Dword Synch Count=0x%x\n", pg1->LossDwordSynchCount);
233 printk("PHY Reset Problem Count=0x%x\n", pg1->PhyResetProblemCount);
234 printk("\n");
Christoph Hellwigb5141122005-10-28 22:07:41 +0200235}
236
237static void mptsas_print_device_pg0(SasDevicePage0_t *pg0)
238{
239 __le64 sas_address;
240
241 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
242
243 printk("---- SAS DEVICE PAGE 0 ---------\n");
244 printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle));
Christoph Hellwige3094442006-02-16 13:25:36 +0100245 printk("Parent Handle=0x%X\n" ,le16_to_cpu(pg0->ParentDevHandle));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200246 printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle));
247 printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot));
Eric Mooref99be432007-01-04 20:46:54 -0700248 printk("SAS Address=0x%llX\n", (unsigned long long)
249 le64_to_cpu(sas_address));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200250 printk("Target ID=0x%X\n", pg0->TargetID);
251 printk("Bus=0x%X\n", pg0->Bus);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200252 /* The PhyNum field specifies the PHY number of the parent
253 * device this device is linked to
254 */
255 printk("Parent Phy Num=0x%X\n", pg0->PhyNum);
256 printk("Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200257 printk("Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo));
258 printk("Flags=0x%X\n", le16_to_cpu(pg0->Flags));
259 printk("Physical Port=0x%X\n", pg0->PhysicalPort);
260 printk("\n");
261}
262
263static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
264{
265 printk("---- SAS EXPANDER PAGE 1 ------------\n");
266
267 printk("Physical Port=0x%X\n", pg1->PhysicalPort);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200268 printk("PHY Identifier=0x%X\n", pg1->PhyIdentifier);
Christoph Hellwigb5141122005-10-28 22:07:41 +0200269 printk("Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate);
270 printk("Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate);
271 printk("Hardware Link Rate=0x%X\n", pg1->HwLinkRate);
272 printk("Owner Device Handle=0x%X\n",
273 le16_to_cpu(pg1->OwnerDevHandle));
274 printk("Attached Device Handle=0x%X\n",
275 le16_to_cpu(pg1->AttachedDevHandle));
276}
277#else
278#define mptsas_print_phy_data(phy_data) do { } while (0)
279#define mptsas_print_phy_pg0(pg0) do { } while (0)
280#define mptsas_print_phy_pg1(pg1) do { } while (0)
281#define mptsas_print_device_pg0(pg0) do { } while (0)
282#define mptsas_print_expander_pg1(pg1) do { } while (0)
283#endif
284
Christoph Hellwige3094442006-02-16 13:25:36 +0100285static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
286{
287 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
288 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
289}
290
291static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
292{
293 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
294 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
295}
296
Moore, Erice6b2d762006-03-14 09:14:24 -0700297/*
298 * mptsas_find_portinfo_by_handle
299 *
300 * This function should be called with the sas_topology_mutex already held
301 */
302static struct mptsas_portinfo *
303mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
304{
305 struct mptsas_portinfo *port_info, *rc=NULL;
306 int i;
307
308 list_for_each_entry(port_info, &ioc->sas_topology, list)
309 for (i = 0; i < port_info->num_phys; i++)
310 if (port_info->phy_info[i].identify.handle == handle) {
311 rc = port_info;
312 goto out;
313 }
314 out:
315 return rc;
316}
317
Moore, Ericbd23e942006-04-17 12:43:04 -0600318/*
319 * Returns true if there is a scsi end device
320 */
321static inline int
322mptsas_is_end_device(struct mptsas_devinfo * attached)
323{
Eric Moore547f9a22006-06-27 14:42:12 -0600324 if ((attached->sas_address) &&
Moore, Ericbd23e942006-04-17 12:43:04 -0600325 (attached->device_info &
326 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
327 ((attached->device_info &
328 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
329 (attached->device_info &
330 MPI_SAS_DEVICE_INFO_STP_TARGET) |
331 (attached->device_info &
332 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
333 return 1;
334 else
335 return 0;
336}
337
Eric Moore547f9a22006-06-27 14:42:12 -0600338/* no mutex */
Eric Moore376ac832006-06-29 17:36:26 -0600339static void
Eric Moore547f9a22006-06-27 14:42:12 -0600340mptsas_port_delete(struct mptsas_portinfo_details * port_details)
341{
342 struct mptsas_portinfo *port_info;
343 struct mptsas_phyinfo *phy_info;
344 u8 i;
345
346 if (!port_details)
347 return;
348
349 port_info = port_details->port_info;
350 phy_info = port_info->phy_info;
351
Eric Mooredc22f162006-07-06 11:23:14 -0600352 dsaswideprintk((KERN_DEBUG "%s: [%p]: num_phys=%02d "
Eric Mooref99be432007-01-04 20:46:54 -0700353 "bitmask=0x%016llX\n", __FUNCTION__, port_details,
354 port_details->num_phys, (unsigned long long)
355 port_details->phy_bitmask));
Eric Moore547f9a22006-06-27 14:42:12 -0600356
357 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
358 if(phy_info->port_details != port_details)
359 continue;
360 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
361 phy_info->port_details = NULL;
362 }
363 kfree(port_details);
364}
365
366static inline struct sas_rphy *
367mptsas_get_rphy(struct mptsas_phyinfo *phy_info)
368{
369 if (phy_info->port_details)
370 return phy_info->port_details->rphy;
371 else
372 return NULL;
373}
374
375static inline void
376mptsas_set_rphy(struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
377{
378 if (phy_info->port_details) {
379 phy_info->port_details->rphy = rphy;
380 dsaswideprintk((KERN_DEBUG "sas_rphy_add: rphy=%p\n", rphy));
381 }
382
383#ifdef MPT_DEBUG_SAS_WIDE
384 if (rphy) {
385 dev_printk(KERN_DEBUG, &rphy->dev, "add:");
386 printk("rphy=%p release=%p\n",
387 rphy, rphy->dev.release);
388 }
389#endif
390}
391
392static inline struct sas_port *
393mptsas_get_port(struct mptsas_phyinfo *phy_info)
394{
395 if (phy_info->port_details)
396 return phy_info->port_details->port;
397 else
398 return NULL;
399}
400
401static inline void
402mptsas_set_port(struct mptsas_phyinfo *phy_info, struct sas_port *port)
403{
404 if (phy_info->port_details)
405 phy_info->port_details->port = port;
406
407#ifdef MPT_DEBUG_SAS_WIDE
408 if (port) {
409 dev_printk(KERN_DEBUG, &port->dev, "add: ");
410 printk("port=%p release=%p\n",
411 port, port->dev.release);
412 }
413#endif
414}
415
416static inline struct scsi_target *
417mptsas_get_starget(struct mptsas_phyinfo *phy_info)
418{
419 if (phy_info->port_details)
420 return phy_info->port_details->starget;
421 else
422 return NULL;
423}
424
425static inline void
426mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target *
427starget)
428{
429 if (phy_info->port_details)
430 phy_info->port_details->starget = starget;
431}
432
433
434/*
435 * mptsas_setup_wide_ports
436 *
437 * Updates for new and existing narrow/wide port configuration
438 * in the sas_topology
439 */
Eric Moore376ac832006-06-29 17:36:26 -0600440static void
Eric Moore547f9a22006-06-27 14:42:12 -0600441mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
442{
443 struct mptsas_portinfo_details * port_details;
444 struct mptsas_phyinfo *phy_info, *phy_info_cmp;
445 u64 sas_address;
446 int i, j;
447
448 mutex_lock(&ioc->sas_topology_mutex);
449
450 phy_info = port_info->phy_info;
451 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
452 if (phy_info->attached.handle)
453 continue;
454 port_details = phy_info->port_details;
455 if (!port_details)
456 continue;
457 if (port_details->num_phys < 2)
458 continue;
459 /*
460 * Removing a phy from a port, letting the last
461 * phy be removed by firmware events.
462 */
463 dsaswideprintk((KERN_DEBUG
Eric Mooredc22f162006-07-06 11:23:14 -0600464 "%s: [%p]: deleting phy = %d\n",
465 __FUNCTION__, port_details, i));
Eric Moore547f9a22006-06-27 14:42:12 -0600466 port_details->num_phys--;
467 port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
468 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
469 sas_port_delete_phy(port_details->port, phy_info->phy);
470 phy_info->port_details = NULL;
471 }
472
473 /*
474 * Populate and refresh the tree
475 */
476 phy_info = port_info->phy_info;
477 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
478 sas_address = phy_info->attached.sas_address;
479 dsaswideprintk((KERN_DEBUG "phy_id=%d sas_address=0x%018llX\n",
Eric Mooref99be432007-01-04 20:46:54 -0700480 i, (unsigned long long)sas_address));
Eric Moore547f9a22006-06-27 14:42:12 -0600481 if (!sas_address)
482 continue;
483 port_details = phy_info->port_details;
484 /*
485 * Forming a port
486 */
487 if (!port_details) {
488 port_details = kzalloc(sizeof(*port_details),
489 GFP_KERNEL);
490 if (!port_details)
491 goto out;
492 port_details->num_phys = 1;
493 port_details->port_info = port_info;
Eric Moore547f9a22006-06-27 14:42:12 -0600494 if (phy_info->phy_id < 64 )
495 port_details->phy_bitmask |=
496 (1 << phy_info->phy_id);
497 phy_info->sas_port_add_phy=1;
498 dsaswideprintk((KERN_DEBUG "\t\tForming port\n\t\t"
Eric Mooref99be432007-01-04 20:46:54 -0700499 "phy_id=%d sas_address=0x%018llX\n",
500 i, (unsigned long long)sas_address));
Eric Moore547f9a22006-06-27 14:42:12 -0600501 phy_info->port_details = port_details;
502 }
503
504 if (i == port_info->num_phys - 1)
505 continue;
506 phy_info_cmp = &port_info->phy_info[i + 1];
507 for (j = i + 1 ; j < port_info->num_phys ; j++,
508 phy_info_cmp++) {
509 if (!phy_info_cmp->attached.sas_address)
510 continue;
511 if (sas_address != phy_info_cmp->attached.sas_address)
512 continue;
513 if (phy_info_cmp->port_details == port_details )
514 continue;
515 dsaswideprintk((KERN_DEBUG
Eric Mooref99be432007-01-04 20:46:54 -0700516 "\t\tphy_id=%d sas_address=0x%018llX\n",
517 j, (unsigned long long)
518 phy_info_cmp->attached.sas_address));
Eric Moore547f9a22006-06-27 14:42:12 -0600519 if (phy_info_cmp->port_details) {
520 port_details->rphy =
521 mptsas_get_rphy(phy_info_cmp);
522 port_details->port =
523 mptsas_get_port(phy_info_cmp);
524 port_details->starget =
525 mptsas_get_starget(phy_info_cmp);
Eric Moore547f9a22006-06-27 14:42:12 -0600526 port_details->num_phys =
527 phy_info_cmp->port_details->num_phys;
Eric Moore547f9a22006-06-27 14:42:12 -0600528 if (!phy_info_cmp->port_details->num_phys)
529 kfree(phy_info_cmp->port_details);
530 } else
531 phy_info_cmp->sas_port_add_phy=1;
532 /*
533 * Adding a phy to a port
534 */
535 phy_info_cmp->port_details = port_details;
536 if (phy_info_cmp->phy_id < 64 )
537 port_details->phy_bitmask |=
538 (1 << phy_info_cmp->phy_id);
539 port_details->num_phys++;
540 }
541 }
542
543 out:
544
545#ifdef MPT_DEBUG_SAS_WIDE
546 for (i = 0; i < port_info->num_phys; i++) {
547 port_details = port_info->phy_info[i].port_details;
548 if (!port_details)
549 continue;
550 dsaswideprintk((KERN_DEBUG
Eric Mooref99be432007-01-04 20:46:54 -0700551 "%s: [%p]: phy_id=%02d num_phys=%02d "
552 "bitmask=0x%016llX\n", __FUNCTION__,
553 port_details, i, port_details->num_phys,
554 (unsigned long long)port_details->phy_bitmask));
Eric Moore547f9a22006-06-27 14:42:12 -0600555 dsaswideprintk((KERN_DEBUG"\t\tport = %p rphy=%p\n",
556 port_details->port, port_details->rphy));
557 }
558 dsaswideprintk((KERN_DEBUG"\n"));
559#endif
560 mutex_unlock(&ioc->sas_topology_mutex);
561}
562
563static void
564mptsas_target_reset(MPT_ADAPTER *ioc, VirtTarget * vtarget)
565{
566 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
567
568 if (mptscsih_TMHandler(hd,
569 MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
570 vtarget->bus_id, vtarget->target_id, 0, 0, 5) < 0) {
571 hd->tmPending = 0;
572 hd->tmState = TM_STATE_NONE;
573 printk(MYIOC_s_WARN_FMT
574 "Error processing TaskMgmt id=%d TARGET_RESET\n",
575 ioc->name, vtarget->target_id);
576 }
577}
578
Christoph Hellwige3094442006-02-16 13:25:36 +0100579static int
Moore, Eric52435432006-03-14 09:14:15 -0700580mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
Christoph Hellwige3094442006-02-16 13:25:36 +0100581 u32 form, u32 form_specific)
582{
583 ConfigExtendedPageHeader_t hdr;
584 CONFIGPARMS cfg;
585 SasEnclosurePage0_t *buffer;
586 dma_addr_t dma_handle;
587 int error;
588 __le64 le_identifier;
589
590 memset(&hdr, 0, sizeof(hdr));
591 hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
592 hdr.PageNumber = 0;
593 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
594 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
595
596 cfg.cfghdr.ehdr = &hdr;
597 cfg.physAddr = -1;
598 cfg.pageAddr = form + form_specific;
599 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
600 cfg.dir = 0; /* read */
601 cfg.timeout = 10;
602
603 error = mpt_config(ioc, &cfg);
604 if (error)
605 goto out;
606 if (!hdr.ExtPageLength) {
607 error = -ENXIO;
608 goto out;
609 }
610
611 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
612 &dma_handle);
613 if (!buffer) {
614 error = -ENOMEM;
615 goto out;
616 }
617
618 cfg.physAddr = dma_handle;
619 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
620
621 error = mpt_config(ioc, &cfg);
622 if (error)
623 goto out_free_consistent;
624
625 /* save config data */
626 memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
627 enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
628 enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
629 enclosure->flags = le16_to_cpu(buffer->Flags);
630 enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
631 enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
632 enclosure->start_id = buffer->StartTargetID;
633 enclosure->start_channel = buffer->StartBus;
634 enclosure->sep_id = buffer->SEPTargetID;
635 enclosure->sep_channel = buffer->SEPBus;
636
637 out_free_consistent:
638 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
639 buffer, dma_handle);
640 out:
641 return error;
642}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200643
James Bottomleyf013db32006-03-18 14:54:36 -0600644static int
645mptsas_slave_configure(struct scsi_device *sdev)
646{
Moore, Eric3c0c25b2006-04-13 16:08:17 -0600647
James Bottomleye8bf3942006-07-11 17:49:34 -0400648 if (sdev->channel == MPTSAS_RAID_CHANNEL)
649 goto out;
James Bottomleyf013db32006-03-18 14:54:36 -0600650
James Bottomleye8bf3942006-07-11 17:49:34 -0400651 sas_read_port_mode_page(sdev);
652
653 out:
James Bottomleyf013db32006-03-18 14:54:36 -0600654 return mptscsih_slave_configure(sdev);
655}
656
Eric Moore547f9a22006-06-27 14:42:12 -0600657static int
658mptsas_target_alloc(struct scsi_target *starget)
659{
660 struct Scsi_Host *host = dev_to_shost(&starget->dev);
661 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
662 VirtTarget *vtarget;
663 u32 target_id;
664 u32 channel;
665 struct sas_rphy *rphy;
666 struct mptsas_portinfo *p;
667 int i;
668
669 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
670 if (!vtarget)
671 return -ENOMEM;
672
673 vtarget->starget = starget;
674 vtarget->ioc_id = hd->ioc->id;
675 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
676
677 target_id = starget->id;
678 channel = 0;
679
680 hd->Targets[target_id] = vtarget;
681
James Bottomleye8bf3942006-07-11 17:49:34 -0400682 if (starget->channel == MPTSAS_RAID_CHANNEL)
Eric Moore547f9a22006-06-27 14:42:12 -0600683 goto out;
684
685 rphy = dev_to_rphy(starget->dev.parent);
686 mutex_lock(&hd->ioc->sas_topology_mutex);
687 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
688 for (i = 0; i < p->num_phys; i++) {
689 if (p->phy_info[i].attached.sas_address !=
690 rphy->identify.sas_address)
691 continue;
692 target_id = p->phy_info[i].attached.id;
693 channel = p->phy_info[i].attached.channel;
694 mptsas_set_starget(&p->phy_info[i], starget);
695
696 /*
697 * Exposing hidden raid components
698 */
699 if (mptscsih_is_phys_disk(hd->ioc, target_id)) {
700 target_id = mptscsih_raid_id_to_num(hd,
701 target_id);
702 vtarget->tflags |=
703 MPT_TARGET_FLAGS_RAID_COMPONENT;
704 }
705 mutex_unlock(&hd->ioc->sas_topology_mutex);
706 goto out;
707 }
708 }
709 mutex_unlock(&hd->ioc->sas_topology_mutex);
710
711 kfree(vtarget);
712 return -ENXIO;
713
714 out:
715 vtarget->target_id = target_id;
716 vtarget->bus_id = channel;
717 starget->hostdata = vtarget;
718 return 0;
719}
720
721static void
722mptsas_target_destroy(struct scsi_target *starget)
723{
724 struct Scsi_Host *host = dev_to_shost(&starget->dev);
725 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
726 struct sas_rphy *rphy;
727 struct mptsas_portinfo *p;
728 int i;
729
730 if (!starget->hostdata)
731 return;
732
James Bottomleye8bf3942006-07-11 17:49:34 -0400733 if (starget->channel == MPTSAS_RAID_CHANNEL)
Eric Moore547f9a22006-06-27 14:42:12 -0600734 goto out;
735
736 rphy = dev_to_rphy(starget->dev.parent);
737 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
738 for (i = 0; i < p->num_phys; i++) {
739 if (p->phy_info[i].attached.sas_address !=
740 rphy->identify.sas_address)
741 continue;
742 mptsas_set_starget(&p->phy_info[i], NULL);
743 goto out;
744 }
745 }
746
747 out:
748 kfree(starget->hostdata);
749 starget->hostdata = NULL;
750}
751
752
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200753static int
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700754mptsas_slave_alloc(struct scsi_device *sdev)
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200755{
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700756 struct Scsi_Host *host = sdev->host;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200757 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
758 struct sas_rphy *rphy;
759 struct mptsas_portinfo *p;
760 VirtDevice *vdev;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700761 struct scsi_target *starget;
Eric Moore547f9a22006-06-27 14:42:12 -0600762 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200763
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +0100764 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200765 if (!vdev) {
Eric Moore547f9a22006-06-27 14:42:12 -0600766 printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200767 hd->ioc->name, sizeof(VirtDevice));
768 return -ENOMEM;
769 }
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700770 starget = scsi_target(sdev);
Eric Moore547f9a22006-06-27 14:42:12 -0600771 vdev->vtarget = starget->hostdata;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200772
James Bottomleye8bf3942006-07-11 17:49:34 -0400773 if (sdev->channel == MPTSAS_RAID_CHANNEL)
Moore, Eric816aa902006-01-13 16:25:20 -0700774 goto out;
Moore, Eric816aa902006-01-13 16:25:20 -0700775
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700776 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100777 mutex_lock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200778 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
779 for (i = 0; i < p->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -0600780 if (p->phy_info[i].attached.sas_address !=
781 rphy->identify.sas_address)
782 continue;
783 vdev->lun = sdev->lun;
784 /*
785 * Exposing hidden raid components
786 */
787 if (mptscsih_is_phys_disk(hd->ioc,
788 p->phy_info[i].attached.id))
789 sdev->no_uld_attach = 1;
790 mutex_unlock(&hd->ioc->sas_topology_mutex);
791 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200792 }
793 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100794 mutex_unlock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200795
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200796 kfree(vdev);
Christoph Hellwig23f236e2006-01-30 19:00:43 +0100797 return -ENXIO;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200798
799 out:
Eric Moore547f9a22006-06-27 14:42:12 -0600800 vdev->vtarget->num_luns++;
801 sdev->hostdata = vdev;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200802 return 0;
803}
804
Eric Moore547f9a22006-06-27 14:42:12 -0600805static int
806mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100807{
Eric Moore547f9a22006-06-27 14:42:12 -0600808 VirtDevice *vdev = SCpnt->device->hostdata;
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100809
Eric Moore547f9a22006-06-27 14:42:12 -0600810// scsi_print_command(SCpnt);
811 if (vdev->vtarget->deleted) {
812 SCpnt->result = DID_NO_CONNECT << 16;
813 done(SCpnt);
814 return 0;
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700815 }
Eric Moore547f9a22006-06-27 14:42:12 -0600816
817 return mptscsih_qcmd(SCpnt,done);
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100818}
819
Eric Moore547f9a22006-06-27 14:42:12 -0600820
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200821static struct scsi_host_template mptsas_driver_template = {
Moore, Eric Deanf78496d2005-11-16 18:54:14 -0700822 .module = THIS_MODULE,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200823 .proc_name = "mptsas",
824 .proc_info = mptscsih_proc_info,
825 .name = "MPT SPI Host",
826 .info = mptscsih_info,
Eric Moore547f9a22006-06-27 14:42:12 -0600827 .queuecommand = mptsas_qcmd,
828 .target_alloc = mptsas_target_alloc,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200829 .slave_alloc = mptsas_slave_alloc,
James Bottomleyf013db32006-03-18 14:54:36 -0600830 .slave_configure = mptsas_slave_configure,
Eric Moore547f9a22006-06-27 14:42:12 -0600831 .target_destroy = mptsas_target_destroy,
832 .slave_destroy = mptscsih_slave_destroy,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200833 .change_queue_depth = mptscsih_change_queue_depth,
834 .eh_abort_handler = mptscsih_abort,
835 .eh_device_reset_handler = mptscsih_dev_reset,
836 .eh_bus_reset_handler = mptscsih_bus_reset,
837 .eh_host_reset_handler = mptscsih_host_reset,
838 .bios_param = mptscsih_bios_param,
839 .can_queue = MPT_FC_CAN_QUEUE,
840 .this_id = -1,
841 .sg_tablesize = MPT_SCSI_SG_DEPTH,
842 .max_sectors = 8192,
843 .cmd_per_lun = 7,
844 .use_clustering = ENABLE_CLUSTERING,
845};
846
Christoph Hellwigb5141122005-10-28 22:07:41 +0200847static int mptsas_get_linkerrors(struct sas_phy *phy)
848{
849 MPT_ADAPTER *ioc = phy_to_ioc(phy);
850 ConfigExtendedPageHeader_t hdr;
851 CONFIGPARMS cfg;
852 SasPhyPage1_t *buffer;
853 dma_addr_t dma_handle;
854 int error;
855
James Bottomleyf4ad7b52006-08-25 13:48:18 -0500856 /* FIXME: only have link errors on local phys */
857 if (!scsi_is_sas_phy_local(phy))
858 return -EINVAL;
859
Christoph Hellwigb5141122005-10-28 22:07:41 +0200860 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
861 hdr.ExtPageLength = 0;
862 hdr.PageNumber = 1 /* page number 1*/;
863 hdr.Reserved1 = 0;
864 hdr.Reserved2 = 0;
865 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
866 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
867
868 cfg.cfghdr.ehdr = &hdr;
869 cfg.physAddr = -1;
870 cfg.pageAddr = phy->identify.phy_identifier;
871 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
872 cfg.dir = 0; /* read */
873 cfg.timeout = 10;
874
875 error = mpt_config(ioc, &cfg);
876 if (error)
877 return error;
878 if (!hdr.ExtPageLength)
879 return -ENXIO;
880
881 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
882 &dma_handle);
883 if (!buffer)
884 return -ENOMEM;
885
886 cfg.physAddr = dma_handle;
887 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
888
889 error = mpt_config(ioc, &cfg);
890 if (error)
891 goto out_free_consistent;
892
893 mptsas_print_phy_pg1(buffer);
894
895 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
896 phy->running_disparity_error_count =
897 le32_to_cpu(buffer->RunningDisparityErrorCount);
898 phy->loss_of_dword_sync_count =
899 le32_to_cpu(buffer->LossDwordSynchCount);
900 phy->phy_reset_problem_count =
901 le32_to_cpu(buffer->PhyResetProblemCount);
902
903 out_free_consistent:
904 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
905 buffer, dma_handle);
906 return error;
907}
908
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200909static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
910 MPT_FRAME_HDR *reply)
911{
912 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
913 if (reply != NULL) {
914 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
915 memcpy(ioc->sas_mgmt.reply, reply,
916 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
917 }
918 complete(&ioc->sas_mgmt.done);
919 return 1;
920}
921
922static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
923{
924 MPT_ADAPTER *ioc = phy_to_ioc(phy);
925 SasIoUnitControlRequest_t *req;
926 SasIoUnitControlReply_t *reply;
927 MPT_FRAME_HDR *mf;
928 MPIHeader_t *hdr;
929 unsigned long timeleft;
930 int error = -ERESTARTSYS;
931
James Bottomleyf4ad7b52006-08-25 13:48:18 -0500932 /* FIXME: fusion doesn't allow non-local phy reset */
933 if (!scsi_is_sas_phy_local(phy))
934 return -EINVAL;
935
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200936 /* not implemented for expanders */
937 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
938 return -ENXIO;
939
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100940 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200941 goto out;
942
943 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
944 if (!mf) {
945 error = -ENOMEM;
946 goto out_unlock;
947 }
948
949 hdr = (MPIHeader_t *) mf;
950 req = (SasIoUnitControlRequest_t *)mf;
951 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
952 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
953 req->MsgContext = hdr->MsgContext;
954 req->Operation = hard_reset ?
955 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
956 req->PhyNum = phy->identify.phy_identifier;
957
958 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
959
960 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
961 10 * HZ);
962 if (!timeleft) {
963 /* On timeout reset the board */
964 mpt_free_msg_frame(ioc, mf);
965 mpt_HardResetHandler(ioc, CAN_SLEEP);
966 error = -ETIMEDOUT;
967 goto out_unlock;
968 }
969
970 /* a reply frame is expected */
971 if ((ioc->sas_mgmt.status &
972 MPT_IOCTL_STATUS_RF_VALID) == 0) {
973 error = -ENXIO;
974 goto out_unlock;
975 }
976
977 /* process the completed Reply Message Frame */
978 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
979 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
980 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
981 __FUNCTION__,
982 reply->IOCStatus,
983 reply->IOCLogInfo);
984 error = -ENXIO;
985 goto out_unlock;
986 }
987
988 error = 0;
989
990 out_unlock:
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100991 mutex_unlock(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200992 out:
993 return error;
994}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200995
Christoph Hellwige3094442006-02-16 13:25:36 +0100996static int
997mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
998{
999 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1000 int i, error;
1001 struct mptsas_portinfo *p;
1002 struct mptsas_enclosure enclosure_info;
1003 u64 enclosure_handle;
1004
1005 mutex_lock(&ioc->sas_topology_mutex);
1006 list_for_each_entry(p, &ioc->sas_topology, list) {
1007 for (i = 0; i < p->num_phys; i++) {
1008 if (p->phy_info[i].attached.sas_address ==
1009 rphy->identify.sas_address) {
1010 enclosure_handle = p->phy_info[i].
1011 attached.handle_enclosure;
1012 goto found_info;
1013 }
1014 }
1015 }
1016 mutex_unlock(&ioc->sas_topology_mutex);
1017 return -ENXIO;
1018
1019 found_info:
1020 mutex_unlock(&ioc->sas_topology_mutex);
1021 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
Moore, Eric52435432006-03-14 09:14:15 -07001022 error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
Christoph Hellwige3094442006-02-16 13:25:36 +01001023 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
1024 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
1025 if (!error)
1026 *identifier = enclosure_info.enclosure_logical_id;
1027 return error;
1028}
1029
1030static int
1031mptsas_get_bay_identifier(struct sas_rphy *rphy)
1032{
1033 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1034 struct mptsas_portinfo *p;
1035 int i, rc;
1036
1037 mutex_lock(&ioc->sas_topology_mutex);
1038 list_for_each_entry(p, &ioc->sas_topology, list) {
1039 for (i = 0; i < p->num_phys; i++) {
1040 if (p->phy_info[i].attached.sas_address ==
1041 rphy->identify.sas_address) {
1042 rc = p->phy_info[i].attached.slot;
1043 goto out;
1044 }
1045 }
1046 }
1047 rc = -ENXIO;
1048 out:
1049 mutex_unlock(&ioc->sas_topology_mutex);
1050 return rc;
1051}
1052
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001053static struct sas_function_template mptsas_transport_functions = {
Christoph Hellwigb5141122005-10-28 22:07:41 +02001054 .get_linkerrors = mptsas_get_linkerrors,
Christoph Hellwige3094442006-02-16 13:25:36 +01001055 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
1056 .get_bay_identifier = mptsas_get_bay_identifier,
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001057 .phy_reset = mptsas_phy_reset,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001058};
1059
1060static struct scsi_transport_template *mptsas_transport_template;
1061
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001062static int
1063mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
1064{
1065 ConfigExtendedPageHeader_t hdr;
1066 CONFIGPARMS cfg;
1067 SasIOUnitPage0_t *buffer;
1068 dma_addr_t dma_handle;
1069 int error, i;
1070
1071 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
1072 hdr.ExtPageLength = 0;
1073 hdr.PageNumber = 0;
1074 hdr.Reserved1 = 0;
1075 hdr.Reserved2 = 0;
1076 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1077 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1078
1079 cfg.cfghdr.ehdr = &hdr;
1080 cfg.physAddr = -1;
1081 cfg.pageAddr = 0;
1082 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1083 cfg.dir = 0; /* read */
1084 cfg.timeout = 10;
1085
1086 error = mpt_config(ioc, &cfg);
1087 if (error)
1088 goto out;
1089 if (!hdr.ExtPageLength) {
1090 error = -ENXIO;
1091 goto out;
1092 }
1093
1094 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1095 &dma_handle);
1096 if (!buffer) {
1097 error = -ENOMEM;
1098 goto out;
1099 }
1100
1101 cfg.physAddr = dma_handle;
1102 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1103
1104 error = mpt_config(ioc, &cfg);
1105 if (error)
1106 goto out_free_consistent;
1107
1108 port_info->num_phys = buffer->NumPhys;
1109 port_info->phy_info = kcalloc(port_info->num_phys,
Eric Moore547f9a22006-06-27 14:42:12 -06001110 sizeof(*port_info->phy_info),GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001111 if (!port_info->phy_info) {
1112 error = -ENOMEM;
1113 goto out_free_consistent;
1114 }
1115
Moore, Ericdb9c9172006-03-14 09:14:18 -07001116 if (port_info->num_phys)
1117 port_info->handle =
1118 le16_to_cpu(buffer->PhyData[0].ControllerDevHandle);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001119 for (i = 0; i < port_info->num_phys; i++) {
1120 mptsas_print_phy_data(&buffer->PhyData[i]);
1121 port_info->phy_info[i].phy_id = i;
1122 port_info->phy_info[i].port_id =
1123 buffer->PhyData[i].Port;
1124 port_info->phy_info[i].negotiated_link_rate =
1125 buffer->PhyData[i].NegotiatedLinkRate;
Eric Moore547f9a22006-06-27 14:42:12 -06001126 port_info->phy_info[i].portinfo = port_info;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001127 }
1128
1129 out_free_consistent:
1130 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1131 buffer, dma_handle);
1132 out:
1133 return error;
1134}
1135
1136static int
1137mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1138 u32 form, u32 form_specific)
1139{
1140 ConfigExtendedPageHeader_t hdr;
1141 CONFIGPARMS cfg;
1142 SasPhyPage0_t *buffer;
1143 dma_addr_t dma_handle;
1144 int error;
1145
1146 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
1147 hdr.ExtPageLength = 0;
1148 hdr.PageNumber = 0;
1149 hdr.Reserved1 = 0;
1150 hdr.Reserved2 = 0;
1151 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1152 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
1153
1154 cfg.cfghdr.ehdr = &hdr;
1155 cfg.dir = 0; /* read */
1156 cfg.timeout = 10;
1157
1158 /* Get Phy Pg 0 for each Phy. */
1159 cfg.physAddr = -1;
1160 cfg.pageAddr = form + form_specific;
1161 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1162
1163 error = mpt_config(ioc, &cfg);
1164 if (error)
1165 goto out;
1166
1167 if (!hdr.ExtPageLength) {
1168 error = -ENXIO;
1169 goto out;
1170 }
1171
1172 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1173 &dma_handle);
1174 if (!buffer) {
1175 error = -ENOMEM;
1176 goto out;
1177 }
1178
1179 cfg.physAddr = dma_handle;
1180 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1181
1182 error = mpt_config(ioc, &cfg);
1183 if (error)
1184 goto out_free_consistent;
1185
1186 mptsas_print_phy_pg0(buffer);
1187
1188 phy_info->hw_link_rate = buffer->HwLinkRate;
1189 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1190 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1191 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1192
1193 out_free_consistent:
1194 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1195 buffer, dma_handle);
1196 out:
1197 return error;
1198}
1199
1200static int
1201mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
1202 u32 form, u32 form_specific)
1203{
1204 ConfigExtendedPageHeader_t hdr;
1205 CONFIGPARMS cfg;
1206 SasDevicePage0_t *buffer;
1207 dma_addr_t dma_handle;
1208 __le64 sas_address;
Moore, Ericbd23e942006-04-17 12:43:04 -06001209 int error=0;
1210
1211 if (ioc->sas_discovery_runtime &&
1212 mptsas_is_end_device(device_info))
1213 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001214
1215 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
1216 hdr.ExtPageLength = 0;
1217 hdr.PageNumber = 0;
1218 hdr.Reserved1 = 0;
1219 hdr.Reserved2 = 0;
1220 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1221 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1222
1223 cfg.cfghdr.ehdr = &hdr;
1224 cfg.pageAddr = form + form_specific;
1225 cfg.physAddr = -1;
1226 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1227 cfg.dir = 0; /* read */
1228 cfg.timeout = 10;
1229
Moore, Ericdb9c9172006-03-14 09:14:18 -07001230 memset(device_info, 0, sizeof(struct mptsas_devinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001231 error = mpt_config(ioc, &cfg);
1232 if (error)
1233 goto out;
1234 if (!hdr.ExtPageLength) {
1235 error = -ENXIO;
1236 goto out;
1237 }
1238
1239 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1240 &dma_handle);
1241 if (!buffer) {
1242 error = -ENOMEM;
1243 goto out;
1244 }
1245
1246 cfg.physAddr = dma_handle;
1247 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1248
1249 error = mpt_config(ioc, &cfg);
1250 if (error)
1251 goto out_free_consistent;
1252
1253 mptsas_print_device_pg0(buffer);
1254
1255 device_info->handle = le16_to_cpu(buffer->DevHandle);
Moore, Ericc73787ee2006-01-26 16:20:06 -07001256 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
Christoph Hellwige3094442006-02-16 13:25:36 +01001257 device_info->handle_enclosure =
1258 le16_to_cpu(buffer->EnclosureHandle);
1259 device_info->slot = le16_to_cpu(buffer->Slot);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001260 device_info->phy_id = buffer->PhyNum;
1261 device_info->port_id = buffer->PhysicalPort;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001262 device_info->id = buffer->TargetID;
1263 device_info->channel = buffer->Bus;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001264 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
1265 device_info->sas_address = le64_to_cpu(sas_address);
1266 device_info->device_info =
1267 le32_to_cpu(buffer->DeviceInfo);
1268
1269 out_free_consistent:
1270 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1271 buffer, dma_handle);
1272 out:
1273 return error;
1274}
1275
1276static int
1277mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
1278 u32 form, u32 form_specific)
1279{
1280 ConfigExtendedPageHeader_t hdr;
1281 CONFIGPARMS cfg;
1282 SasExpanderPage0_t *buffer;
1283 dma_addr_t dma_handle;
Eric Moore547f9a22006-06-27 14:42:12 -06001284 int i, error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001285
1286 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1287 hdr.ExtPageLength = 0;
1288 hdr.PageNumber = 0;
1289 hdr.Reserved1 = 0;
1290 hdr.Reserved2 = 0;
1291 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1292 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1293
1294 cfg.cfghdr.ehdr = &hdr;
1295 cfg.physAddr = -1;
1296 cfg.pageAddr = form + form_specific;
1297 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1298 cfg.dir = 0; /* read */
1299 cfg.timeout = 10;
1300
Moore, Ericdb9c9172006-03-14 09:14:18 -07001301 memset(port_info, 0, sizeof(struct mptsas_portinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001302 error = mpt_config(ioc, &cfg);
1303 if (error)
1304 goto out;
1305
1306 if (!hdr.ExtPageLength) {
1307 error = -ENXIO;
1308 goto out;
1309 }
1310
1311 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1312 &dma_handle);
1313 if (!buffer) {
1314 error = -ENOMEM;
1315 goto out;
1316 }
1317
1318 cfg.physAddr = dma_handle;
1319 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1320
1321 error = mpt_config(ioc, &cfg);
1322 if (error)
1323 goto out_free_consistent;
1324
1325 /* save config data */
1326 port_info->num_phys = buffer->NumPhys;
1327 port_info->handle = le16_to_cpu(buffer->DevHandle);
1328 port_info->phy_info = kcalloc(port_info->num_phys,
Eric Moore547f9a22006-06-27 14:42:12 -06001329 sizeof(*port_info->phy_info),GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001330 if (!port_info->phy_info) {
1331 error = -ENOMEM;
1332 goto out_free_consistent;
1333 }
1334
Eric Moore547f9a22006-06-27 14:42:12 -06001335 for (i = 0; i < port_info->num_phys; i++)
1336 port_info->phy_info[i].portinfo = port_info;
1337
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001338 out_free_consistent:
1339 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1340 buffer, dma_handle);
1341 out:
1342 return error;
1343}
1344
1345static int
1346mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1347 u32 form, u32 form_specific)
1348{
1349 ConfigExtendedPageHeader_t hdr;
1350 CONFIGPARMS cfg;
1351 SasExpanderPage1_t *buffer;
1352 dma_addr_t dma_handle;
Moore, Ericbd23e942006-04-17 12:43:04 -06001353 int error=0;
1354
1355 if (ioc->sas_discovery_runtime &&
1356 mptsas_is_end_device(&phy_info->attached))
1357 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001358
1359 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1360 hdr.ExtPageLength = 0;
1361 hdr.PageNumber = 1;
1362 hdr.Reserved1 = 0;
1363 hdr.Reserved2 = 0;
1364 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1365 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1366
1367 cfg.cfghdr.ehdr = &hdr;
1368 cfg.physAddr = -1;
1369 cfg.pageAddr = form + form_specific;
1370 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1371 cfg.dir = 0; /* read */
1372 cfg.timeout = 10;
1373
1374 error = mpt_config(ioc, &cfg);
1375 if (error)
1376 goto out;
1377
1378 if (!hdr.ExtPageLength) {
1379 error = -ENXIO;
1380 goto out;
1381 }
1382
1383 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1384 &dma_handle);
1385 if (!buffer) {
1386 error = -ENOMEM;
1387 goto out;
1388 }
1389
1390 cfg.physAddr = dma_handle;
1391 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1392
1393 error = mpt_config(ioc, &cfg);
1394 if (error)
1395 goto out_free_consistent;
1396
1397
1398 mptsas_print_expander_pg1(buffer);
1399
1400 /* save config data */
Eric Moore024358e2005-10-21 20:56:36 +02001401 phy_info->phy_id = buffer->PhyIdentifier;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001402 phy_info->port_id = buffer->PhysicalPort;
1403 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
1404 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1405 phy_info->hw_link_rate = buffer->HwLinkRate;
1406 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1407 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1408
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001409 out_free_consistent:
1410 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1411 buffer, dma_handle);
1412 out:
1413 return error;
1414}
1415
1416static void
1417mptsas_parse_device_info(struct sas_identify *identify,
1418 struct mptsas_devinfo *device_info)
1419{
1420 u16 protocols;
1421
1422 identify->sas_address = device_info->sas_address;
1423 identify->phy_identifier = device_info->phy_id;
1424
1425 /*
1426 * Fill in Phy Initiator Port Protocol.
1427 * Bits 6:3, more than one bit can be set, fall through cases.
1428 */
1429 protocols = device_info->device_info & 0x78;
1430 identify->initiator_port_protocols = 0;
1431 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
1432 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
1433 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1434 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
1435 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
1436 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
1437 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
1438 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
1439
1440 /*
1441 * Fill in Phy Target Port Protocol.
1442 * Bits 10:7, more than one bit can be set, fall through cases.
1443 */
1444 protocols = device_info->device_info & 0x780;
1445 identify->target_port_protocols = 0;
1446 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1447 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
1448 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
1449 identify->target_port_protocols |= SAS_PROTOCOL_STP;
1450 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
1451 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
1452 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1453 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
1454
1455 /*
1456 * Fill in Attached device type.
1457 */
1458 switch (device_info->device_info &
1459 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
1460 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
1461 identify->device_type = SAS_PHY_UNUSED;
1462 break;
1463 case MPI_SAS_DEVICE_INFO_END_DEVICE:
1464 identify->device_type = SAS_END_DEVICE;
1465 break;
1466 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
1467 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
1468 break;
1469 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
1470 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
1471 break;
1472 }
1473}
1474
1475static int mptsas_probe_one_phy(struct device *dev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001476 struct mptsas_phyinfo *phy_info, int index, int local)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001477{
Moore, Erice6b2d762006-03-14 09:14:24 -07001478 MPT_ADAPTER *ioc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001479 struct sas_phy *phy;
Eric Moore547f9a22006-06-27 14:42:12 -06001480 struct sas_port *port;
1481 int error = 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001482
Eric Moore547f9a22006-06-27 14:42:12 -06001483 if (!dev) {
1484 error = -ENODEV;
1485 goto out;
1486 }
Moore, Erice6b2d762006-03-14 09:14:24 -07001487
1488 if (!phy_info->phy) {
1489 phy = sas_phy_alloc(dev, index);
Eric Moore547f9a22006-06-27 14:42:12 -06001490 if (!phy) {
1491 error = -ENOMEM;
1492 goto out;
1493 }
Moore, Erice6b2d762006-03-14 09:14:24 -07001494 } else
1495 phy = phy_info->phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001496
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001497 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001498
1499 /*
1500 * Set Negotiated link rate.
1501 */
1502 switch (phy_info->negotiated_link_rate) {
1503 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001504 phy->negotiated_linkrate = SAS_PHY_DISABLED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001505 break;
1506 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001507 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001508 break;
1509 case MPI_SAS_IOUNIT0_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001510 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001511 break;
1512 case MPI_SAS_IOUNIT0_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001513 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001514 break;
1515 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
1516 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
1517 default:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001518 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001519 break;
1520 }
1521
1522 /*
1523 * Set Max hardware link rate.
1524 */
1525 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1526 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001527 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001528 break;
1529 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001530 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001531 break;
1532 default:
1533 break;
1534 }
1535
1536 /*
1537 * Set Max programmed link rate.
1538 */
1539 switch (phy_info->programmed_link_rate &
1540 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1541 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001542 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001543 break;
1544 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001545 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001546 break;
1547 default:
1548 break;
1549 }
1550
1551 /*
1552 * Set Min hardware link rate.
1553 */
1554 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
1555 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001556 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001557 break;
1558 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001559 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001560 break;
1561 default:
1562 break;
1563 }
1564
1565 /*
1566 * Set Min programmed link rate.
1567 */
1568 switch (phy_info->programmed_link_rate &
1569 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
1570 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001571 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001572 break;
1573 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001574 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001575 break;
1576 default:
1577 break;
1578 }
1579
Moore, Erice6b2d762006-03-14 09:14:24 -07001580 if (!phy_info->phy) {
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001581
Moore, Erice6b2d762006-03-14 09:14:24 -07001582 error = sas_phy_add(phy);
1583 if (error) {
1584 sas_phy_free(phy);
Eric Moore547f9a22006-06-27 14:42:12 -06001585 goto out;
Moore, Erice6b2d762006-03-14 09:14:24 -07001586 }
1587 phy_info->phy = phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001588 }
1589
Eric Moore547f9a22006-06-27 14:42:12 -06001590 if (!phy_info->attached.handle ||
1591 !phy_info->port_details)
1592 goto out;
1593
1594 port = mptsas_get_port(phy_info);
1595 ioc = phy_to_ioc(phy_info->phy);
1596
1597 if (phy_info->sas_port_add_phy) {
1598
1599 if (!port) {
Eric Mooredc22f162006-07-06 11:23:14 -06001600 port = sas_port_alloc_num(dev);
Eric Moore547f9a22006-06-27 14:42:12 -06001601 if (!port) {
1602 error = -ENOMEM;
1603 goto out;
1604 }
1605 error = sas_port_add(port);
1606 if (error) {
1607 dfailprintk((MYIOC_s_ERR_FMT
1608 "%s: exit at line=%d\n", ioc->name,
1609 __FUNCTION__, __LINE__));
1610 goto out;
1611 }
1612 mptsas_set_port(phy_info, port);
Eric Mooredc22f162006-07-06 11:23:14 -06001613 dsaswideprintk((KERN_DEBUG
1614 "sas_port_alloc: port=%p dev=%p port_id=%d\n",
1615 port, dev, port->port_identifier));
Eric Moore547f9a22006-06-27 14:42:12 -06001616 }
1617 dsaswideprintk((KERN_DEBUG "sas_port_add_phy: phy_id=%d\n",
1618 phy_info->phy_id));
1619 sas_port_add_phy(port, phy_info->phy);
1620 phy_info->sas_port_add_phy = 0;
1621 }
1622
1623 if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
Moore, Erice6b2d762006-03-14 09:14:24 -07001624
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001625 struct sas_rphy *rphy;
James Bottomley2686de22006-06-30 12:54:02 -05001626 struct device *parent;
James Bottomleyf013db32006-03-18 14:54:36 -06001627 struct sas_identify identify;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001628
James Bottomley2686de22006-06-30 12:54:02 -05001629 parent = dev->parent->parent;
Moore, Erice6b2d762006-03-14 09:14:24 -07001630 /*
1631 * Let the hotplug_work thread handle processing
1632 * the adding/removing of devices that occur
1633 * after start of day.
1634 */
1635 if (ioc->sas_discovery_runtime &&
1636 mptsas_is_end_device(&phy_info->attached))
Eric Moore547f9a22006-06-27 14:42:12 -06001637 goto out;
Moore, Erice6b2d762006-03-14 09:14:24 -07001638
James Bottomleyf013db32006-03-18 14:54:36 -06001639 mptsas_parse_device_info(&identify, &phy_info->attached);
James Bottomley2686de22006-06-30 12:54:02 -05001640 if (scsi_is_host_device(parent)) {
1641 struct mptsas_portinfo *port_info;
1642 int i;
1643
1644 mutex_lock(&ioc->sas_topology_mutex);
1645 port_info = mptsas_find_portinfo_by_handle(ioc,
1646 ioc->handle);
1647 mutex_unlock(&ioc->sas_topology_mutex);
1648
1649 for (i = 0; i < port_info->num_phys; i++)
1650 if (port_info->phy_info[i].identify.sas_address ==
James Bottomley0c269e62006-07-12 09:51:04 -04001651 identify.sas_address) {
1652 sas_port_mark_backlink(port);
James Bottomley2686de22006-06-30 12:54:02 -05001653 goto out;
James Bottomley0c269e62006-07-12 09:51:04 -04001654 }
James Bottomley2686de22006-06-30 12:54:02 -05001655
1656 } else if (scsi_is_sas_rphy(parent)) {
1657 struct sas_rphy *parent_rphy = dev_to_rphy(parent);
1658 if (identify.sas_address ==
James Bottomley0c269e62006-07-12 09:51:04 -04001659 parent_rphy->identify.sas_address) {
1660 sas_port_mark_backlink(port);
James Bottomley2686de22006-06-30 12:54:02 -05001661 goto out;
James Bottomley0c269e62006-07-12 09:51:04 -04001662 }
James Bottomley2686de22006-06-30 12:54:02 -05001663 }
1664
James Bottomleyf013db32006-03-18 14:54:36 -06001665 switch (identify.device_type) {
1666 case SAS_END_DEVICE:
Eric Moore547f9a22006-06-27 14:42:12 -06001667 rphy = sas_end_device_alloc(port);
James Bottomleyf013db32006-03-18 14:54:36 -06001668 break;
1669 case SAS_EDGE_EXPANDER_DEVICE:
1670 case SAS_FANOUT_EXPANDER_DEVICE:
Eric Moore547f9a22006-06-27 14:42:12 -06001671 rphy = sas_expander_alloc(port, identify.device_type);
James Bottomleyf013db32006-03-18 14:54:36 -06001672 break;
1673 default:
1674 rphy = NULL;
1675 break;
1676 }
Eric Moore547f9a22006-06-27 14:42:12 -06001677 if (!rphy) {
1678 dfailprintk((MYIOC_s_ERR_FMT
1679 "%s: exit at line=%d\n", ioc->name,
1680 __FUNCTION__, __LINE__));
1681 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001682 }
1683
Eric Moore547f9a22006-06-27 14:42:12 -06001684 rphy->identify = identify;
1685 error = sas_rphy_add(rphy);
1686 if (error) {
1687 dfailprintk((MYIOC_s_ERR_FMT
1688 "%s: exit at line=%d\n", ioc->name,
1689 __FUNCTION__, __LINE__));
1690 sas_rphy_free(rphy);
1691 goto out;
1692 }
1693 mptsas_set_rphy(phy_info, rphy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001694 }
1695
Eric Moore547f9a22006-06-27 14:42:12 -06001696 out:
1697 return error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001698}
1699
1700static int
Moore, Erice6b2d762006-03-14 09:14:24 -07001701mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001702{
Moore, Erice6b2d762006-03-14 09:14:24 -07001703 struct mptsas_portinfo *port_info, *hba;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001704 u32 handle = 0xFFFF;
1705 int error = -ENOMEM, i;
1706
Moore, Erice6b2d762006-03-14 09:14:24 -07001707 hba = kzalloc(sizeof(*port_info), GFP_KERNEL);
1708 if (! hba)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001709 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001710
Moore, Erice6b2d762006-03-14 09:14:24 -07001711 error = mptsas_sas_io_unit_pg0(ioc, hba);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001712 if (error)
1713 goto out_free_port_info;
1714
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001715 mutex_lock(&ioc->sas_topology_mutex);
James Bottomley2686de22006-06-30 12:54:02 -05001716 ioc->handle = hba->handle;
Moore, Erice6b2d762006-03-14 09:14:24 -07001717 port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle);
1718 if (!port_info) {
1719 port_info = hba;
1720 list_add_tail(&port_info->list, &ioc->sas_topology);
1721 } else {
1722 port_info->handle = hba->handle;
1723 for (i = 0; i < hba->num_phys; i++)
1724 port_info->phy_info[i].negotiated_link_rate =
1725 hba->phy_info[i].negotiated_link_rate;
Eric Moore547f9a22006-06-27 14:42:12 -06001726 kfree(hba->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001727 kfree(hba);
1728 hba = NULL;
1729 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001730 mutex_unlock(&ioc->sas_topology_mutex);
1731
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001732 for (i = 0; i < port_info->num_phys; i++) {
1733 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
1734 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
1735 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
1736
1737 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
1738 (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
1739 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
Eric Moore024358e2005-10-21 20:56:36 +02001740 port_info->phy_info[i].identify.phy_id =
1741 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001742 handle = port_info->phy_info[i].identify.handle;
1743
Eric Moore547f9a22006-06-27 14:42:12 -06001744 if (port_info->phy_info[i].attached.handle)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001745 mptsas_sas_device_pg0(ioc,
1746 &port_info->phy_info[i].attached,
1747 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1748 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1749 port_info->phy_info[i].attached.handle);
Eric Moore547f9a22006-06-27 14:42:12 -06001750 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001751
Eric Moore547f9a22006-06-27 14:42:12 -06001752 mptsas_setup_wide_ports(ioc, port_info);
1753
1754 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001755 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
Moore, Erice6b2d762006-03-14 09:14:24 -07001756 &port_info->phy_info[i], ioc->sas_index, 1);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001757
1758 return 0;
1759
1760 out_free_port_info:
Eric Moore547f9a22006-06-27 14:42:12 -06001761 kfree(hba);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001762 out:
1763 return error;
1764}
1765
1766static int
Moore, Erice6b2d762006-03-14 09:14:24 -07001767mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001768{
Moore, Erice6b2d762006-03-14 09:14:24 -07001769 struct mptsas_portinfo *port_info, *p, *ex;
Eric Moore547f9a22006-06-27 14:42:12 -06001770 struct device *parent;
1771 struct sas_rphy *rphy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001772 int error = -ENOMEM, i, j;
1773
Moore, Erice6b2d762006-03-14 09:14:24 -07001774 ex = kzalloc(sizeof(*port_info), GFP_KERNEL);
1775 if (!ex)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001776 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001777
Moore, Erice6b2d762006-03-14 09:14:24 -07001778 error = mptsas_sas_expander_pg0(ioc, ex,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001779 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
1780 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
1781 if (error)
1782 goto out_free_port_info;
1783
Moore, Erice6b2d762006-03-14 09:14:24 -07001784 *handle = ex->handle;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001785
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001786 mutex_lock(&ioc->sas_topology_mutex);
Moore, Erice6b2d762006-03-14 09:14:24 -07001787 port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
1788 if (!port_info) {
1789 port_info = ex;
1790 list_add_tail(&port_info->list, &ioc->sas_topology);
1791 } else {
1792 port_info->handle = ex->handle;
Eric Moore547f9a22006-06-27 14:42:12 -06001793 kfree(ex->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001794 kfree(ex);
1795 ex = NULL;
1796 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001797 mutex_unlock(&ioc->sas_topology_mutex);
1798
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001799 for (i = 0; i < port_info->num_phys; i++) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001800 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
1801 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
1802 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
1803
1804 if (port_info->phy_info[i].identify.handle) {
1805 mptsas_sas_device_pg0(ioc,
1806 &port_info->phy_info[i].identify,
1807 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1808 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1809 port_info->phy_info[i].identify.handle);
Eric Moore024358e2005-10-21 20:56:36 +02001810 port_info->phy_info[i].identify.phy_id =
1811 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001812 }
1813
1814 if (port_info->phy_info[i].attached.handle) {
1815 mptsas_sas_device_pg0(ioc,
1816 &port_info->phy_info[i].attached,
1817 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1818 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1819 port_info->phy_info[i].attached.handle);
Moore, Ericdb9c9172006-03-14 09:14:18 -07001820 port_info->phy_info[i].attached.phy_id =
1821 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001822 }
Eric Moore547f9a22006-06-27 14:42:12 -06001823 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001824
Eric Moore547f9a22006-06-27 14:42:12 -06001825 parent = &ioc->sh->shost_gendev;
1826 for (i = 0; i < port_info->num_phys; i++) {
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001827 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001828 list_for_each_entry(p, &ioc->sas_topology, list) {
1829 for (j = 0; j < p->num_phys; j++) {
Eric Moore547f9a22006-06-27 14:42:12 -06001830 if (port_info->phy_info[i].identify.handle !=
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001831 p->phy_info[j].attached.handle)
Eric Moore547f9a22006-06-27 14:42:12 -06001832 continue;
1833 rphy = mptsas_get_rphy(&p->phy_info[j]);
1834 parent = &rphy->dev;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001835 }
1836 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001837 mutex_unlock(&ioc->sas_topology_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06001838 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001839
Eric Moore547f9a22006-06-27 14:42:12 -06001840 mptsas_setup_wide_ports(ioc, port_info);
1841
1842 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001843 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
Moore, Erice6b2d762006-03-14 09:14:24 -07001844 ioc->sas_index, 0);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001845
1846 return 0;
1847
1848 out_free_port_info:
Moore, Erice6b2d762006-03-14 09:14:24 -07001849 if (ex) {
Eric Moore547f9a22006-06-27 14:42:12 -06001850 kfree(ex->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001851 kfree(ex);
1852 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001853 out:
1854 return error;
1855}
1856
Moore, Erice6b2d762006-03-14 09:14:24 -07001857/*
1858 * mptsas_delete_expander_phys
1859 *
1860 *
1861 * This will traverse topology, and remove expanders
1862 * that are no longer present
1863 */
1864static void
1865mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
1866{
1867 struct mptsas_portinfo buffer;
1868 struct mptsas_portinfo *port_info, *n, *parent;
Eric Moore547f9a22006-06-27 14:42:12 -06001869 struct mptsas_phyinfo *phy_info;
1870 struct scsi_target * starget;
1871 VirtTarget * vtarget;
1872 struct sas_port * port;
Moore, Erice6b2d762006-03-14 09:14:24 -07001873 int i;
Eric Moore547f9a22006-06-27 14:42:12 -06001874 u64 expander_sas_address;
Moore, Erice6b2d762006-03-14 09:14:24 -07001875
1876 mutex_lock(&ioc->sas_topology_mutex);
1877 list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {
1878
1879 if (port_info->phy_info &&
1880 (!(port_info->phy_info[0].identify.device_info &
1881 MPI_SAS_DEVICE_INFO_SMP_TARGET)))
1882 continue;
1883
1884 if (mptsas_sas_expander_pg0(ioc, &buffer,
1885 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
1886 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) {
1887
1888 /*
Eric Moore547f9a22006-06-27 14:42:12 -06001889 * Issue target reset to all child end devices
1890 * then mark them deleted to prevent further
1891 * IO going to them.
1892 */
1893 phy_info = port_info->phy_info;
1894 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
1895 starget = mptsas_get_starget(phy_info);
1896 if (!starget)
1897 continue;
1898 vtarget = starget->hostdata;
1899 if(vtarget->deleted)
1900 continue;
1901 vtarget->deleted = 1;
1902 mptsas_target_reset(ioc, vtarget);
1903 sas_port_delete(mptsas_get_port(phy_info));
1904 mptsas_port_delete(phy_info->port_details);
1905 }
1906
1907 /*
Moore, Erice6b2d762006-03-14 09:14:24 -07001908 * Obtain the port_info instance to the parent port
1909 */
1910 parent = mptsas_find_portinfo_by_handle(ioc,
1911 port_info->phy_info[0].identify.handle_parent);
1912
1913 if (!parent)
1914 goto next_port;
1915
Eric Moore547f9a22006-06-27 14:42:12 -06001916 expander_sas_address =
1917 port_info->phy_info[0].identify.sas_address;
1918
Moore, Erice6b2d762006-03-14 09:14:24 -07001919 /*
1920 * Delete rphys in the parent that point
1921 * to this expander. The transport layer will
1922 * cleanup all the children.
1923 */
Eric Moore547f9a22006-06-27 14:42:12 -06001924 phy_info = parent->phy_info;
1925 for (i = 0; i < parent->num_phys; i++, phy_info++) {
1926 port = mptsas_get_port(phy_info);
1927 if (!port)
Moore, Erice6b2d762006-03-14 09:14:24 -07001928 continue;
Eric Moore547f9a22006-06-27 14:42:12 -06001929 if (phy_info->attached.sas_address !=
1930 expander_sas_address)
1931 continue;
1932#ifdef MPT_DEBUG_SAS_WIDE
Eric Mooredc22f162006-07-06 11:23:14 -06001933 dev_printk(KERN_DEBUG, &port->dev,
1934 "delete port (%d)\n", port->port_identifier);
Eric Moore547f9a22006-06-27 14:42:12 -06001935#endif
1936 sas_port_delete(port);
1937 mptsas_port_delete(phy_info->port_details);
Moore, Erice6b2d762006-03-14 09:14:24 -07001938 }
1939 next_port:
Eric Moore547f9a22006-06-27 14:42:12 -06001940
1941 phy_info = port_info->phy_info;
1942 for (i = 0; i < port_info->num_phys; i++, phy_info++)
1943 mptsas_port_delete(phy_info->port_details);
1944
Moore, Erice6b2d762006-03-14 09:14:24 -07001945 list_del(&port_info->list);
Eric Moore547f9a22006-06-27 14:42:12 -06001946 kfree(port_info->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001947 kfree(port_info);
1948 }
1949 /*
1950 * Free this memory allocated from inside
1951 * mptsas_sas_expander_pg0
1952 */
Eric Moore547f9a22006-06-27 14:42:12 -06001953 kfree(buffer.phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001954 }
1955 mutex_unlock(&ioc->sas_topology_mutex);
1956}
1957
1958/*
1959 * Start of day discovery
1960 */
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001961static void
1962mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
1963{
1964 u32 handle = 0xFFFF;
Moore, Ericf44e5462006-03-14 09:14:21 -07001965 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001966
Moore, Erice6b2d762006-03-14 09:14:24 -07001967 mutex_lock(&ioc->sas_discovery_mutex);
1968 mptsas_probe_hba_phys(ioc);
1969 while (!mptsas_probe_expander_phys(ioc, &handle))
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001970 ;
Moore, Ericf44e5462006-03-14 09:14:21 -07001971 /*
1972 Reporting RAID volumes.
1973 */
1974 if (!ioc->raid_data.pIocPg2)
1975 goto out;
1976 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
1977 goto out;
1978 for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
James Bottomleye8bf3942006-07-11 17:49:34 -04001979 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
Moore, Ericf44e5462006-03-14 09:14:21 -07001980 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
1981 }
1982 out:
Moore, Erice6b2d762006-03-14 09:14:24 -07001983 mutex_unlock(&ioc->sas_discovery_mutex);
1984}
1985
1986/*
1987 * Work queue thread to handle Runtime discovery
1988 * Mere purpose is the hot add/delete of expanders
Eric Moore547f9a22006-06-27 14:42:12 -06001989 *(Mutex UNLOCKED)
Moore, Erice6b2d762006-03-14 09:14:24 -07001990 */
1991static void
Eric Moore547f9a22006-06-27 14:42:12 -06001992__mptsas_discovery_work(MPT_ADAPTER *ioc)
Moore, Erice6b2d762006-03-14 09:14:24 -07001993{
Moore, Erice6b2d762006-03-14 09:14:24 -07001994 u32 handle = 0xFFFF;
1995
Moore, Erice6b2d762006-03-14 09:14:24 -07001996 ioc->sas_discovery_runtime=1;
1997 mptsas_delete_expander_phys(ioc);
1998 mptsas_probe_hba_phys(ioc);
1999 while (!mptsas_probe_expander_phys(ioc, &handle))
2000 ;
Moore, Erice6b2d762006-03-14 09:14:24 -07002001 ioc->sas_discovery_runtime=0;
Eric Moore547f9a22006-06-27 14:42:12 -06002002}
2003
2004/*
2005 * Work queue thread to handle Runtime discovery
2006 * Mere purpose is the hot add/delete of expanders
2007 *(Mutex LOCKED)
2008 */
2009static void
David Howellsc4028952006-11-22 14:57:56 +00002010mptsas_discovery_work(struct work_struct *work)
Eric Moore547f9a22006-06-27 14:42:12 -06002011{
David Howellsc4028952006-11-22 14:57:56 +00002012 struct mptsas_discovery_event *ev =
2013 container_of(work, struct mptsas_discovery_event, work);
Eric Moore547f9a22006-06-27 14:42:12 -06002014 MPT_ADAPTER *ioc = ev->ioc;
2015
2016 mutex_lock(&ioc->sas_discovery_mutex);
2017 __mptsas_discovery_work(ioc);
Moore, Erice6b2d762006-03-14 09:14:24 -07002018 mutex_unlock(&ioc->sas_discovery_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002019 kfree(ev);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002020}
2021
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002022static struct mptsas_phyinfo *
Eric Moore547f9a22006-06-27 14:42:12 -06002023mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002024{
2025 struct mptsas_portinfo *port_info;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002026 struct mptsas_phyinfo *phy_info = NULL;
Eric Moore547f9a22006-06-27 14:42:12 -06002027 int i;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002028
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002029 mutex_lock(&ioc->sas_topology_mutex);
2030 list_for_each_entry(port_info, &ioc->sas_topology, list) {
2031 for (i = 0; i < port_info->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -06002032 if (port_info->phy_info[i].attached.sas_address
2033 != sas_address)
2034 continue;
2035 if (!mptsas_is_end_device(
2036 &port_info->phy_info[i].attached))
2037 continue;
2038 phy_info = &port_info->phy_info[i];
2039 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002040 }
2041 }
2042 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002043 return phy_info;
2044}
2045
2046static struct mptsas_phyinfo *
Moore, Ericc73787ee2006-01-26 16:20:06 -07002047mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002048{
2049 struct mptsas_portinfo *port_info;
2050 struct mptsas_phyinfo *phy_info = NULL;
2051 int i;
2052
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002053 mutex_lock(&ioc->sas_topology_mutex);
2054 list_for_each_entry(port_info, &ioc->sas_topology, list) {
Eric Moore547f9a22006-06-27 14:42:12 -06002055 for (i = 0; i < port_info->num_phys; i++) {
2056 if (port_info->phy_info[i].attached.id != id)
2057 continue;
2058 if (!mptsas_is_end_device(
2059 &port_info->phy_info[i].attached))
2060 continue;
2061 phy_info = &port_info->phy_info[i];
2062 break;
2063 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002064 }
2065 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002066 return phy_info;
2067}
2068
Moore, Eric4b766472006-03-14 09:14:12 -07002069/*
2070 * Work queue thread to clear the persitency table
2071 */
2072static void
David Howellsc4028952006-11-22 14:57:56 +00002073mptsas_persist_clear_table(struct work_struct *work)
Moore, Eric4b766472006-03-14 09:14:12 -07002074{
David Howellsc4028952006-11-22 14:57:56 +00002075 MPT_ADAPTER *ioc = container_of(work, MPT_ADAPTER, sas_persist_task);
Moore, Eric4b766472006-03-14 09:14:12 -07002076
2077 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
2078}
2079
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002080static void
Moore, Ericf44e5462006-03-14 09:14:21 -07002081mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
2082{
Eric Mooref99be432007-01-04 20:46:54 -07002083 int rc;
2084
Moore, Ericf44e5462006-03-14 09:14:21 -07002085 sdev->no_uld_attach = data ? 1 : 0;
Eric Mooref99be432007-01-04 20:46:54 -07002086 rc = scsi_device_reprobe(sdev);
Moore, Ericf44e5462006-03-14 09:14:21 -07002087}
2088
2089static void
2090mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
2091{
2092 starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
2093 mptsas_reprobe_lun);
2094}
2095
Moore, Erice6b2d762006-03-14 09:14:24 -07002096/*
2097 * Work queue thread to handle SAS hotplug events
2098 */
Moore, Ericf44e5462006-03-14 09:14:21 -07002099static void
David Howellsc4028952006-11-22 14:57:56 +00002100mptsas_hotplug_work(struct work_struct *work)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002101{
David Howellsc4028952006-11-22 14:57:56 +00002102 struct mptsas_hotplug_event *ev =
2103 container_of(work, struct mptsas_hotplug_event, work);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002104 MPT_ADAPTER *ioc = ev->ioc;
2105 struct mptsas_phyinfo *phy_info;
2106 struct sas_rphy *rphy;
Eric Moore547f9a22006-06-27 14:42:12 -06002107 struct sas_port *port;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002108 struct scsi_device *sdev;
Eric Moore547f9a22006-06-27 14:42:12 -06002109 struct scsi_target * starget;
James Bottomleyf013db32006-03-18 14:54:36 -06002110 struct sas_identify identify;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002111 char *ds = NULL;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002112 struct mptsas_devinfo sas_device;
Moore, Ericf44e5462006-03-14 09:14:21 -07002113 VirtTarget *vtarget;
Eric Moore547f9a22006-06-27 14:42:12 -06002114 VirtDevice *vdevice;
2115
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002116
Moore, Erice6b2d762006-03-14 09:14:24 -07002117 mutex_lock(&ioc->sas_discovery_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002118 switch (ev->event_type) {
2119 case MPTSAS_DEL_DEVICE:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002120
Moore, Ericc73787ee2006-01-26 16:20:06 -07002121 phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
Moore, Erice6b2d762006-03-14 09:14:24 -07002122
Moore, Ericf44e5462006-03-14 09:14:21 -07002123 /*
2124 * Sanity checks, for non-existing phys and remote rphys.
2125 */
Eric Moore547f9a22006-06-27 14:42:12 -06002126 if (!phy_info || !phy_info->port_details) {
2127 dfailprintk((MYIOC_s_ERR_FMT
2128 "%s: exit at line=%d\n", ioc->name,
2129 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002130 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002131 }
2132 rphy = mptsas_get_rphy(phy_info);
2133 if (!rphy) {
2134 dfailprintk((MYIOC_s_ERR_FMT
2135 "%s: exit at line=%d\n", ioc->name,
2136 __FUNCTION__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002137 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002138 }
2139 port = mptsas_get_port(phy_info);
2140 if (!port) {
2141 dfailprintk((MYIOC_s_ERR_FMT
2142 "%s: exit at line=%d\n", ioc->name,
2143 __FUNCTION__, __LINE__));
2144 break;
2145 }
Moore, Ericf44e5462006-03-14 09:14:21 -07002146
Eric Moore547f9a22006-06-27 14:42:12 -06002147 starget = mptsas_get_starget(phy_info);
2148 if (starget) {
2149 vtarget = starget->hostdata;
2150
2151 if (!vtarget) {
2152 dfailprintk((MYIOC_s_ERR_FMT
2153 "%s: exit at line=%d\n", ioc->name,
2154 __FUNCTION__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002155 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002156 }
2157
Moore, Ericf44e5462006-03-14 09:14:21 -07002158 /*
2159 * Handling RAID components
2160 */
2161 if (ev->phys_disk_num_valid) {
2162 vtarget->target_id = ev->phys_disk_num;
2163 vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
Eric Moore547f9a22006-06-27 14:42:12 -06002164 mptsas_reprobe_target(starget, 1);
Moore, Ericf44e5462006-03-14 09:14:21 -07002165 break;
2166 }
Eric Moore547f9a22006-06-27 14:42:12 -06002167
2168 vtarget->deleted = 1;
2169 mptsas_target_reset(ioc, vtarget);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002170 }
2171
Moore, Ericc73787ee2006-01-26 16:20:06 -07002172 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
2173 ds = "ssp";
2174 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
2175 ds = "stp";
2176 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
2177 ds = "sata";
2178
2179 printk(MYIOC_s_INFO_FMT
2180 "removing %s device, channel %d, id %d, phy %d\n",
2181 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
2182
Eric Moore547f9a22006-06-27 14:42:12 -06002183#ifdef MPT_DEBUG_SAS_WIDE
Eric Mooredc22f162006-07-06 11:23:14 -06002184 dev_printk(KERN_DEBUG, &port->dev,
2185 "delete port (%d)\n", port->port_identifier);
Eric Moore547f9a22006-06-27 14:42:12 -06002186#endif
2187 sas_port_delete(port);
2188 mptsas_port_delete(phy_info->port_details);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002189 break;
2190 case MPTSAS_ADD_DEVICE:
Moore, Ericc73787ee2006-01-26 16:20:06 -07002191
Moore, Ericbd23e942006-04-17 12:43:04 -06002192 if (ev->phys_disk_num_valid)
2193 mpt_findImVolumes(ioc);
2194
Moore, Ericc73787ee2006-01-26 16:20:06 -07002195 /*
Christoph Hellwige3094442006-02-16 13:25:36 +01002196 * Refresh sas device pg0 data
Moore, Ericc73787ee2006-01-26 16:20:06 -07002197 */
Christoph Hellwige3094442006-02-16 13:25:36 +01002198 if (mptsas_sas_device_pg0(ioc, &sas_device,
2199 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
Eric Moore547f9a22006-06-27 14:42:12 -06002200 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id)) {
2201 dfailprintk((MYIOC_s_ERR_FMT
2202 "%s: exit at line=%d\n", ioc->name,
2203 __FUNCTION__, __LINE__));
Christoph Hellwige3094442006-02-16 13:25:36 +01002204 break;
Moore, Erice6b2d762006-03-14 09:14:24 -07002205 }
2206
Eric Moore547f9a22006-06-27 14:42:12 -06002207 ssleep(2);
2208 __mptsas_discovery_work(ioc);
Moore, Ericf44e5462006-03-14 09:14:21 -07002209
Eric Moore547f9a22006-06-27 14:42:12 -06002210 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
2211 sas_device.sas_address);
2212
2213 if (!phy_info || !phy_info->port_details) {
2214 dfailprintk((MYIOC_s_ERR_FMT
2215 "%s: exit at line=%d\n", ioc->name,
2216 __FUNCTION__, __LINE__));
2217 break;
2218 }
2219
2220 starget = mptsas_get_starget(phy_info);
2221 if (starget) {
2222 vtarget = starget->hostdata;
2223
2224 if (!vtarget) {
2225 dfailprintk((MYIOC_s_ERR_FMT
2226 "%s: exit at line=%d\n", ioc->name,
2227 __FUNCTION__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002228 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002229 }
Moore, Ericf44e5462006-03-14 09:14:21 -07002230 /*
2231 * Handling RAID components
2232 */
2233 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
2234 vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
2235 vtarget->target_id = ev->id;
Eric Moore547f9a22006-06-27 14:42:12 -06002236 mptsas_reprobe_target(starget, 0);
Moore, Ericf44e5462006-03-14 09:14:21 -07002237 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002238 break;
2239 }
2240
Eric Moore547f9a22006-06-27 14:42:12 -06002241 if (mptsas_get_rphy(phy_info)) {
2242 dfailprintk((MYIOC_s_ERR_FMT
2243 "%s: exit at line=%d\n", ioc->name,
2244 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002245 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002246 }
2247 port = mptsas_get_port(phy_info);
2248 if (!port) {
2249 dfailprintk((MYIOC_s_ERR_FMT
2250 "%s: exit at line=%d\n", ioc->name,
2251 __FUNCTION__, __LINE__));
2252 break;
2253 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002254
Christoph Hellwige3094442006-02-16 13:25:36 +01002255 memcpy(&phy_info->attached, &sas_device,
2256 sizeof(struct mptsas_devinfo));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002257
Moore, Ericc73787ee2006-01-26 16:20:06 -07002258 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
2259 ds = "ssp";
2260 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
2261 ds = "stp";
2262 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
2263 ds = "sata";
2264
2265 printk(MYIOC_s_INFO_FMT
2266 "attaching %s device, channel %d, id %d, phy %d\n",
2267 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
2268
James Bottomleyf013db32006-03-18 14:54:36 -06002269 mptsas_parse_device_info(&identify, &phy_info->attached);
Eric Moore547f9a22006-06-27 14:42:12 -06002270 rphy = sas_end_device_alloc(port);
2271 if (!rphy) {
2272 dfailprintk((MYIOC_s_ERR_FMT
2273 "%s: exit at line=%d\n", ioc->name,
2274 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002275 break; /* non-fatal: an rphy can be added later */
Eric Moore547f9a22006-06-27 14:42:12 -06002276 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002277
James Bottomleyf013db32006-03-18 14:54:36 -06002278 rphy->identify = identify;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002279 if (sas_rphy_add(rphy)) {
Eric Moore547f9a22006-06-27 14:42:12 -06002280 dfailprintk((MYIOC_s_ERR_FMT
2281 "%s: exit at line=%d\n", ioc->name,
2282 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002283 sas_rphy_free(rphy);
2284 break;
2285 }
Eric Moore547f9a22006-06-27 14:42:12 -06002286 mptsas_set_rphy(phy_info, rphy);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002287 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002288 case MPTSAS_ADD_RAID:
James Bottomleye8bf3942006-07-11 17:49:34 -04002289 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
2290 ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002291 if (sdev) {
2292 scsi_device_put(sdev);
2293 break;
2294 }
2295 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07002296 "attaching raid volume, channel %d, id %d\n",
James Bottomleye8bf3942006-07-11 17:49:34 -04002297 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
2298 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002299 mpt_findImVolumes(ioc);
2300 break;
2301 case MPTSAS_DEL_RAID:
James Bottomleye8bf3942006-07-11 17:49:34 -04002302 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
2303 ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002304 if (!sdev)
2305 break;
2306 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07002307 "removing raid volume, channel %d, id %d\n",
James Bottomleye8bf3942006-07-11 17:49:34 -04002308 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
Eric Moore547f9a22006-06-27 14:42:12 -06002309 vdevice = sdev->hostdata;
2310 vdevice->vtarget->deleted = 1;
2311 mptsas_target_reset(ioc, vdevice->vtarget);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002312 scsi_remove_device(sdev);
2313 scsi_device_put(sdev);
2314 mpt_findImVolumes(ioc);
2315 break;
Moore, Ericbd23e942006-04-17 12:43:04 -06002316 case MPTSAS_IGNORE_EVENT:
2317 default:
2318 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002319 }
2320
Moore, Erice6b2d762006-03-14 09:14:24 -07002321 mutex_unlock(&ioc->sas_discovery_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002322 kfree(ev);
2323
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002324}
2325
2326static void
Eric Moore547f9a22006-06-27 14:42:12 -06002327mptsas_send_sas_event(MPT_ADAPTER *ioc,
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002328 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
2329{
2330 struct mptsas_hotplug_event *ev;
2331 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
2332 __le64 sas_address;
2333
2334 if ((device_info &
2335 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
2336 MPI_SAS_DEVICE_INFO_STP_TARGET |
2337 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
2338 return;
2339
Moore, Eric4b766472006-03-14 09:14:12 -07002340 switch (sas_event_data->ReasonCode) {
2341 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
2342 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
Eric Moore547f9a22006-06-27 14:42:12 -06002343 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Eric4b766472006-03-14 09:14:12 -07002344 if (!ev) {
2345 printk(KERN_WARNING "mptsas: lost hotplug event\n");
2346 break;
2347 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002348
David Howellsc4028952006-11-22 14:57:56 +00002349 INIT_WORK(&ev->work, mptsas_hotplug_work);
Moore, Eric4b766472006-03-14 09:14:12 -07002350 ev->ioc = ioc;
2351 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
2352 ev->parent_handle =
2353 le16_to_cpu(sas_event_data->ParentDevHandle);
2354 ev->channel = sas_event_data->Bus;
2355 ev->id = sas_event_data->TargetID;
2356 ev->phy_id = sas_event_data->PhyNum;
2357 memcpy(&sas_address, &sas_event_data->SASAddress,
2358 sizeof(__le64));
2359 ev->sas_address = le64_to_cpu(sas_address);
2360 ev->device_info = device_info;
2361
2362 if (sas_event_data->ReasonCode &
2363 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
2364 ev->event_type = MPTSAS_ADD_DEVICE;
2365 else
2366 ev->event_type = MPTSAS_DEL_DEVICE;
2367 schedule_work(&ev->work);
2368 break;
2369 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
2370 /*
2371 * Persistent table is full.
2372 */
Eric Moore547f9a22006-06-27 14:42:12 -06002373 INIT_WORK(&ioc->sas_persist_task,
David Howellsc4028952006-11-22 14:57:56 +00002374 mptsas_persist_clear_table);
Eric Moore547f9a22006-06-27 14:42:12 -06002375 schedule_work(&ioc->sas_persist_task);
Moore, Eric4b766472006-03-14 09:14:12 -07002376 break;
2377 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
2378 /* TODO */
2379 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
2380 /* TODO */
2381 default:
2382 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002383 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002384}
2385
Moore, Ericc73787ee2006-01-26 16:20:06 -07002386static void
Eric Moore547f9a22006-06-27 14:42:12 -06002387mptsas_send_raid_event(MPT_ADAPTER *ioc,
Moore, Ericc73787ee2006-01-26 16:20:06 -07002388 EVENT_DATA_RAID *raid_event_data)
2389{
2390 struct mptsas_hotplug_event *ev;
Moore, Ericbd23e942006-04-17 12:43:04 -06002391 int status = le32_to_cpu(raid_event_data->SettingsStatus);
2392 int state = (status >> 8) & 0xff;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002393
2394 if (ioc->bus_type != SAS)
2395 return;
2396
Eric Moore547f9a22006-06-27 14:42:12 -06002397 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002398 if (!ev) {
2399 printk(KERN_WARNING "mptsas: lost hotplug event\n");
2400 return;
2401 }
2402
David Howellsc4028952006-11-22 14:57:56 +00002403 INIT_WORK(&ev->work, mptsas_hotplug_work);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002404 ev->ioc = ioc;
2405 ev->id = raid_event_data->VolumeID;
Moore, Ericbd23e942006-04-17 12:43:04 -06002406 ev->event_type = MPTSAS_IGNORE_EVENT;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002407
2408 switch (raid_event_data->ReasonCode) {
2409 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
2410 ev->event_type = MPTSAS_ADD_DEVICE;
2411 break;
2412 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
Moore, Ericf44e5462006-03-14 09:14:21 -07002413 ioc->raid_data.isRaid = 1;
2414 ev->phys_disk_num_valid = 1;
2415 ev->phys_disk_num = raid_event_data->PhysDiskNum;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002416 ev->event_type = MPTSAS_DEL_DEVICE;
2417 break;
Moore, Ericbd23e942006-04-17 12:43:04 -06002418 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
2419 switch (state) {
2420 case MPI_PD_STATE_ONLINE:
2421 ioc->raid_data.isRaid = 1;
2422 ev->phys_disk_num_valid = 1;
2423 ev->phys_disk_num = raid_event_data->PhysDiskNum;
2424 ev->event_type = MPTSAS_ADD_DEVICE;
2425 break;
2426 case MPI_PD_STATE_MISSING:
2427 case MPI_PD_STATE_NOT_COMPATIBLE:
2428 case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
2429 case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
2430 case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
2431 ev->event_type = MPTSAS_DEL_DEVICE;
2432 break;
2433 default:
2434 break;
2435 }
2436 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002437 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
2438 ev->event_type = MPTSAS_DEL_RAID;
2439 break;
2440 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
2441 ev->event_type = MPTSAS_ADD_RAID;
2442 break;
2443 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
Moore, Ericbd23e942006-04-17 12:43:04 -06002444 switch (state) {
2445 case MPI_RAIDVOL0_STATUS_STATE_FAILED:
2446 case MPI_RAIDVOL0_STATUS_STATE_MISSING:
2447 ev->event_type = MPTSAS_DEL_RAID;
2448 break;
2449 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
2450 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
2451 ev->event_type = MPTSAS_ADD_RAID;
2452 break;
2453 default:
2454 break;
2455 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07002456 break;
2457 default:
2458 break;
2459 }
2460 schedule_work(&ev->work);
2461}
2462
Moore, Erice6b2d762006-03-14 09:14:24 -07002463static void
Eric Moore547f9a22006-06-27 14:42:12 -06002464mptsas_send_discovery_event(MPT_ADAPTER *ioc,
Moore, Erice6b2d762006-03-14 09:14:24 -07002465 EVENT_DATA_SAS_DISCOVERY *discovery_data)
2466{
2467 struct mptsas_discovery_event *ev;
2468
2469 /*
2470 * DiscoveryStatus
2471 *
2472 * This flag will be non-zero when firmware
2473 * kicks off discovery, and return to zero
2474 * once its completed.
2475 */
2476 if (discovery_data->DiscoveryStatus)
2477 return;
2478
Eric Moore547f9a22006-06-27 14:42:12 -06002479 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Erice6b2d762006-03-14 09:14:24 -07002480 if (!ev)
2481 return;
David Howellsc4028952006-11-22 14:57:56 +00002482 INIT_WORK(&ev->work, mptsas_discovery_work);
Moore, Erice6b2d762006-03-14 09:14:24 -07002483 ev->ioc = ioc;
2484 schedule_work(&ev->work);
2485};
2486
2487
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002488static int
2489mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
2490{
Moore, Ericc73787ee2006-01-26 16:20:06 -07002491 int rc=1;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002492 u8 event = le32_to_cpu(reply->Event) & 0xFF;
2493
2494 if (!ioc->sh)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002495 goto out;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002496
Moore, Erice6b2d762006-03-14 09:14:24 -07002497 /*
2498 * sas_discovery_ignore_events
2499 *
2500 * This flag is to prevent anymore processing of
2501 * sas events once mptsas_remove function is called.
2502 */
2503 if (ioc->sas_discovery_ignore_events) {
2504 rc = mptscsih_event_process(ioc, reply);
2505 goto out;
2506 }
2507
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002508 switch (event) {
2509 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
Eric Moore547f9a22006-06-27 14:42:12 -06002510 mptsas_send_sas_event(ioc,
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002511 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002512 break;
2513 case MPI_EVENT_INTEGRATED_RAID:
Eric Moore547f9a22006-06-27 14:42:12 -06002514 mptsas_send_raid_event(ioc,
Moore, Ericc73787ee2006-01-26 16:20:06 -07002515 (EVENT_DATA_RAID *)reply->Data);
2516 break;
Moore, Eric79de2782006-01-25 18:05:15 -07002517 case MPI_EVENT_PERSISTENT_TABLE_FULL:
Eric Moore547f9a22006-06-27 14:42:12 -06002518 INIT_WORK(&ioc->sas_persist_task,
David Howellsc4028952006-11-22 14:57:56 +00002519 mptsas_persist_clear_table);
Eric Moore547f9a22006-06-27 14:42:12 -06002520 schedule_work(&ioc->sas_persist_task);
Moore, Eric79de2782006-01-25 18:05:15 -07002521 break;
Moore, Eric4b766472006-03-14 09:14:12 -07002522 case MPI_EVENT_SAS_DISCOVERY:
Eric Moore547f9a22006-06-27 14:42:12 -06002523 mptsas_send_discovery_event(ioc,
Moore, Erice6b2d762006-03-14 09:14:24 -07002524 (EVENT_DATA_SAS_DISCOVERY *)reply->Data);
2525 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002526 default:
Moore, Ericc73787ee2006-01-26 16:20:06 -07002527 rc = mptscsih_event_process(ioc, reply);
2528 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002529 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07002530 out:
2531
2532 return rc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002533}
2534
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002535static int
2536mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2537{
2538 struct Scsi_Host *sh;
2539 MPT_SCSI_HOST *hd;
2540 MPT_ADAPTER *ioc;
2541 unsigned long flags;
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002542 int ii;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002543 int numSGE = 0;
2544 int scale;
2545 int ioc_cap;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002546 int error=0;
2547 int r;
2548
2549 r = mpt_attach(pdev,id);
2550 if (r)
2551 return r;
2552
2553 ioc = pci_get_drvdata(pdev);
2554 ioc->DoneCtx = mptsasDoneCtx;
2555 ioc->TaskCtx = mptsasTaskCtx;
2556 ioc->InternalCtx = mptsasInternalCtx;
2557
2558 /* Added sanity check on readiness of the MPT adapter.
2559 */
2560 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
2561 printk(MYIOC_s_WARN_FMT
2562 "Skipping because it's not operational!\n",
2563 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002564 error = -ENODEV;
2565 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002566 }
2567
2568 if (!ioc->active) {
2569 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
2570 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002571 error = -ENODEV;
2572 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002573 }
2574
2575 /* Sanity check - ensure at least 1 port is INITIATOR capable
2576 */
2577 ioc_cap = 0;
2578 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
2579 if (ioc->pfacts[ii].ProtocolFlags &
2580 MPI_PORTFACTS_PROTOCOL_INITIATOR)
2581 ioc_cap++;
2582 }
2583
2584 if (!ioc_cap) {
2585 printk(MYIOC_s_WARN_FMT
2586 "Skipping ioc=%p because SCSI Initiator mode "
2587 "is NOT enabled!\n", ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -06002588 return 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002589 }
2590
2591 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
2592 if (!sh) {
2593 printk(MYIOC_s_WARN_FMT
2594 "Unable to register controller with SCSI subsystem\n",
2595 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002596 error = -1;
2597 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002598 }
2599
2600 spin_lock_irqsave(&ioc->FreeQlock, flags);
2601
2602 /* Attach the SCSI Host to the IOC structure
2603 */
2604 ioc->sh = sh;
2605
2606 sh->io_port = 0;
2607 sh->n_io_port = 0;
2608 sh->irq = 0;
2609
2610 /* set 16 byte cdb's */
2611 sh->max_cmd_len = 16;
2612
2613 sh->max_id = ioc->pfacts->MaxDevices + 1;
2614
2615 sh->transportt = mptsas_transport_template;
2616
2617 sh->max_lun = MPT_LAST_LUN + 1;
2618 sh->max_channel = 0;
2619 sh->this_id = ioc->pfacts[0].PortSCSIID;
2620
2621 /* Required entry.
2622 */
2623 sh->unique_id = ioc->id;
2624
2625 INIT_LIST_HEAD(&ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002626 mutex_init(&ioc->sas_topology_mutex);
Moore, Erice6b2d762006-03-14 09:14:24 -07002627 mutex_init(&ioc->sas_discovery_mutex);
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01002628 mutex_init(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002629 init_completion(&ioc->sas_mgmt.done);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002630
2631 /* Verify that we won't exceed the maximum
2632 * number of chain buffers
2633 * We can optimize: ZZ = req_sz/sizeof(SGE)
2634 * For 32bit SGE's:
2635 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
2636 * + (req_sz - 64)/sizeof(SGE)
2637 * A slightly different algorithm is required for
2638 * 64bit SGEs.
2639 */
2640 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
2641 if (sizeof(dma_addr_t) == sizeof(u64)) {
2642 numSGE = (scale - 1) *
2643 (ioc->facts.MaxChainDepth-1) + scale +
2644 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
2645 sizeof(u32));
2646 } else {
2647 numSGE = 1 + (scale - 1) *
2648 (ioc->facts.MaxChainDepth-1) + scale +
2649 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
2650 sizeof(u32));
2651 }
2652
2653 if (numSGE < sh->sg_tablesize) {
2654 /* Reset this value */
2655 dprintk((MYIOC_s_INFO_FMT
2656 "Resetting sg_tablesize to %d from %d\n",
2657 ioc->name, numSGE, sh->sg_tablesize));
2658 sh->sg_tablesize = numSGE;
2659 }
2660
2661 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2662
2663 hd = (MPT_SCSI_HOST *) sh->hostdata;
2664 hd->ioc = ioc;
2665
2666 /* SCSI needs scsi_cmnd lookup table!
2667 * (with size equal to req_depth*PtrSz!)
2668 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002669 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
2670 if (!hd->ScsiLookup) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002671 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002672 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002673 }
2674
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002675 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
2676 ioc->name, hd->ScsiLookup));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002677
2678 /* Allocate memory for the device structures.
2679 * A non-Null pointer at an offset
2680 * indicates a device exists.
2681 * max_id = 1 + maximum id (hosts.h)
2682 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002683 hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
2684 if (!hd->Targets) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002685 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002686 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002687 }
2688
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002689 dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002690
2691 /* Clear the TM flags
2692 */
2693 hd->tmPending = 0;
2694 hd->tmState = TM_STATE_NONE;
2695 hd->resetPending = 0;
2696 hd->abortSCpnt = NULL;
2697
2698 /* Clear the pointer used to store
2699 * single-threaded commands, i.e., those
2700 * issued during a bus scan, dv and
2701 * configuration pages.
2702 */
2703 hd->cmdPtr = NULL;
2704
2705 /* Initialize this SCSI Hosts' timers
2706 * To use, set the timer expires field
2707 * and add_timer
2708 */
2709 init_timer(&hd->timer);
2710 hd->timer.data = (unsigned long) hd;
2711 hd->timer.function = mptscsih_timer_expired;
2712
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002713 ioc->sas_data.ptClear = mpt_pt_clear;
2714
2715 if (ioc->sas_data.ptClear==1) {
2716 mptbase_sas_persist_operation(
2717 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
2718 }
2719
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002720 init_waitqueue_head(&hd->scandv_waitq);
2721 hd->scandv_wait_done = 0;
2722 hd->last_queue_full = 0;
2723
2724 error = scsi_add_host(sh, &ioc->pcidev->dev);
2725 if (error) {
2726 dprintk((KERN_ERR MYNAM
2727 "scsi_add_host failed\n"));
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002728 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002729 }
2730
2731 mptsas_scan_sas_topology(ioc);
2732
2733 return 0;
2734
Eric Moore547f9a22006-06-27 14:42:12 -06002735 out_mptsas_probe:
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002736
2737 mptscsih_remove(pdev);
2738 return error;
2739}
2740
2741static void __devexit mptsas_remove(struct pci_dev *pdev)
2742{
2743 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
2744 struct mptsas_portinfo *p, *n;
Eric Moore547f9a22006-06-27 14:42:12 -06002745 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002746
Moore, Erice6b2d762006-03-14 09:14:24 -07002747 ioc->sas_discovery_ignore_events=1;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002748 sas_remove_host(ioc->sh);
2749
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002750 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002751 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
2752 list_del(&p->list);
Eric Moore547f9a22006-06-27 14:42:12 -06002753 for (i = 0 ; i < p->num_phys ; i++)
2754 mptsas_port_delete(p->phy_info[i].port_details);
2755 kfree(p->phy_info);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002756 kfree(p);
2757 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002758 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002759
2760 mptscsih_remove(pdev);
2761}
2762
2763static struct pci_device_id mptsas_pci_table[] = {
Eric Moore87cf8982006-06-27 16:09:26 -06002764 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002765 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002766 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002767 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002768 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002769 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002770 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002771 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002772 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002773 PCI_ANY_ID, PCI_ANY_ID },
2774 {0} /* Terminating entry */
2775};
2776MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
2777
2778
2779static struct pci_driver mptsas_driver = {
2780 .name = "mptsas",
2781 .id_table = mptsas_pci_table,
2782 .probe = mptsas_probe,
2783 .remove = __devexit_p(mptsas_remove),
2784 .shutdown = mptscsih_shutdown,
2785#ifdef CONFIG_PM
2786 .suspend = mptscsih_suspend,
2787 .resume = mptscsih_resume,
2788#endif
2789};
2790
2791static int __init
2792mptsas_init(void)
2793{
2794 show_mptmod_ver(my_NAME, my_VERSION);
2795
2796 mptsas_transport_template =
2797 sas_attach_transport(&mptsas_transport_functions);
2798 if (!mptsas_transport_template)
2799 return -ENODEV;
2800
2801 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
2802 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
2803 mptsasInternalCtx =
2804 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002805 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002806
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002807 if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
Moore, Eric3a892be2006-03-14 09:14:03 -07002808 devtverboseprintk((KERN_INFO MYNAM
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002809 ": Registered for IOC event notifications\n"));
2810 }
2811
2812 if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
2813 dprintk((KERN_INFO MYNAM
2814 ": Registered for IOC reset notifications\n"));
2815 }
2816
2817 return pci_register_driver(&mptsas_driver);
2818}
2819
2820static void __exit
2821mptsas_exit(void)
2822{
2823 pci_unregister_driver(&mptsas_driver);
2824 sas_release_transport(mptsas_transport_template);
2825
2826 mpt_reset_deregister(mptsasDoneCtx);
2827 mpt_event_deregister(mptsasDoneCtx);
2828
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002829 mpt_deregister(mptsasMgmtCtx);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002830 mpt_deregister(mptsasInternalCtx);
2831 mpt_deregister(mptsasTaskCtx);
2832 mpt_deregister(mptsasDoneCtx);
2833}
2834
2835module_init(mptsas_init);
2836module_exit(mptsas_exit);