blob: dfdd1e445768273a56b1b8105876d335a4008c7b [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));
248 printk("SAS Address=0x%llX\n", le64_to_cpu(sas_address));
249 printk("Target ID=0x%X\n", pg0->TargetID);
250 printk("Bus=0x%X\n", pg0->Bus);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200251 /* The PhyNum field specifies the PHY number of the parent
252 * device this device is linked to
253 */
254 printk("Parent Phy Num=0x%X\n", pg0->PhyNum);
255 printk("Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200256 printk("Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo));
257 printk("Flags=0x%X\n", le16_to_cpu(pg0->Flags));
258 printk("Physical Port=0x%X\n", pg0->PhysicalPort);
259 printk("\n");
260}
261
262static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
263{
264 printk("---- SAS EXPANDER PAGE 1 ------------\n");
265
266 printk("Physical Port=0x%X\n", pg1->PhysicalPort);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200267 printk("PHY Identifier=0x%X\n", pg1->PhyIdentifier);
Christoph Hellwigb5141122005-10-28 22:07:41 +0200268 printk("Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate);
269 printk("Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate);
270 printk("Hardware Link Rate=0x%X\n", pg1->HwLinkRate);
271 printk("Owner Device Handle=0x%X\n",
272 le16_to_cpu(pg1->OwnerDevHandle));
273 printk("Attached Device Handle=0x%X\n",
274 le16_to_cpu(pg1->AttachedDevHandle));
275}
276#else
277#define mptsas_print_phy_data(phy_data) do { } while (0)
278#define mptsas_print_phy_pg0(pg0) do { } while (0)
279#define mptsas_print_phy_pg1(pg1) do { } while (0)
280#define mptsas_print_device_pg0(pg0) do { } while (0)
281#define mptsas_print_expander_pg1(pg1) do { } while (0)
282#endif
283
Christoph Hellwige3094442006-02-16 13:25:36 +0100284static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
285{
286 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
287 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
288}
289
290static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
291{
292 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
293 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
294}
295
Moore, Erice6b2d762006-03-14 09:14:24 -0700296/*
297 * mptsas_find_portinfo_by_handle
298 *
299 * This function should be called with the sas_topology_mutex already held
300 */
301static struct mptsas_portinfo *
302mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
303{
304 struct mptsas_portinfo *port_info, *rc=NULL;
305 int i;
306
307 list_for_each_entry(port_info, &ioc->sas_topology, list)
308 for (i = 0; i < port_info->num_phys; i++)
309 if (port_info->phy_info[i].identify.handle == handle) {
310 rc = port_info;
311 goto out;
312 }
313 out:
314 return rc;
315}
316
Moore, Ericbd23e942006-04-17 12:43:04 -0600317/*
318 * Returns true if there is a scsi end device
319 */
320static inline int
321mptsas_is_end_device(struct mptsas_devinfo * attached)
322{
Eric Moore547f9a22006-06-27 14:42:12 -0600323 if ((attached->sas_address) &&
Moore, Ericbd23e942006-04-17 12:43:04 -0600324 (attached->device_info &
325 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
326 ((attached->device_info &
327 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
328 (attached->device_info &
329 MPI_SAS_DEVICE_INFO_STP_TARGET) |
330 (attached->device_info &
331 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
332 return 1;
333 else
334 return 0;
335}
336
Eric Moore547f9a22006-06-27 14:42:12 -0600337/* no mutex */
Eric Moore376ac832006-06-29 17:36:26 -0600338static void
Eric Moore547f9a22006-06-27 14:42:12 -0600339mptsas_port_delete(struct mptsas_portinfo_details * port_details)
340{
341 struct mptsas_portinfo *port_info;
342 struct mptsas_phyinfo *phy_info;
343 u8 i;
344
345 if (!port_details)
346 return;
347
348 port_info = port_details->port_info;
349 phy_info = port_info->phy_info;
350
Eric Mooredc22f162006-07-06 11:23:14 -0600351 dsaswideprintk((KERN_DEBUG "%s: [%p]: num_phys=%02d "
Eric Moore547f9a22006-06-27 14:42:12 -0600352 "bitmask=0x%016llX\n",
Eric Mooredc22f162006-07-06 11:23:14 -0600353 __FUNCTION__, port_details, port_details->num_phys,
354 port_details->phy_bitmask));
Eric Moore547f9a22006-06-27 14:42:12 -0600355
356 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
357 if(phy_info->port_details != port_details)
358 continue;
359 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
360 phy_info->port_details = NULL;
361 }
362 kfree(port_details);
363}
364
365static inline struct sas_rphy *
366mptsas_get_rphy(struct mptsas_phyinfo *phy_info)
367{
368 if (phy_info->port_details)
369 return phy_info->port_details->rphy;
370 else
371 return NULL;
372}
373
374static inline void
375mptsas_set_rphy(struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
376{
377 if (phy_info->port_details) {
378 phy_info->port_details->rphy = rphy;
379 dsaswideprintk((KERN_DEBUG "sas_rphy_add: rphy=%p\n", rphy));
380 }
381
382#ifdef MPT_DEBUG_SAS_WIDE
383 if (rphy) {
384 dev_printk(KERN_DEBUG, &rphy->dev, "add:");
385 printk("rphy=%p release=%p\n",
386 rphy, rphy->dev.release);
387 }
388#endif
389}
390
391static inline struct sas_port *
392mptsas_get_port(struct mptsas_phyinfo *phy_info)
393{
394 if (phy_info->port_details)
395 return phy_info->port_details->port;
396 else
397 return NULL;
398}
399
400static inline void
401mptsas_set_port(struct mptsas_phyinfo *phy_info, struct sas_port *port)
402{
403 if (phy_info->port_details)
404 phy_info->port_details->port = port;
405
406#ifdef MPT_DEBUG_SAS_WIDE
407 if (port) {
408 dev_printk(KERN_DEBUG, &port->dev, "add: ");
409 printk("port=%p release=%p\n",
410 port, port->dev.release);
411 }
412#endif
413}
414
415static inline struct scsi_target *
416mptsas_get_starget(struct mptsas_phyinfo *phy_info)
417{
418 if (phy_info->port_details)
419 return phy_info->port_details->starget;
420 else
421 return NULL;
422}
423
424static inline void
425mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target *
426starget)
427{
428 if (phy_info->port_details)
429 phy_info->port_details->starget = starget;
430}
431
432
433/*
434 * mptsas_setup_wide_ports
435 *
436 * Updates for new and existing narrow/wide port configuration
437 * in the sas_topology
438 */
Eric Moore376ac832006-06-29 17:36:26 -0600439static void
Eric Moore547f9a22006-06-27 14:42:12 -0600440mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
441{
442 struct mptsas_portinfo_details * port_details;
443 struct mptsas_phyinfo *phy_info, *phy_info_cmp;
444 u64 sas_address;
445 int i, j;
446
447 mutex_lock(&ioc->sas_topology_mutex);
448
449 phy_info = port_info->phy_info;
450 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
451 if (phy_info->attached.handle)
452 continue;
453 port_details = phy_info->port_details;
454 if (!port_details)
455 continue;
456 if (port_details->num_phys < 2)
457 continue;
458 /*
459 * Removing a phy from a port, letting the last
460 * phy be removed by firmware events.
461 */
462 dsaswideprintk((KERN_DEBUG
Eric Mooredc22f162006-07-06 11:23:14 -0600463 "%s: [%p]: deleting phy = %d\n",
464 __FUNCTION__, port_details, i));
Eric Moore547f9a22006-06-27 14:42:12 -0600465 port_details->num_phys--;
466 port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
467 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
468 sas_port_delete_phy(port_details->port, phy_info->phy);
469 phy_info->port_details = NULL;
470 }
471
472 /*
473 * Populate and refresh the tree
474 */
475 phy_info = port_info->phy_info;
476 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
477 sas_address = phy_info->attached.sas_address;
478 dsaswideprintk((KERN_DEBUG "phy_id=%d sas_address=0x%018llX\n",
479 i, sas_address));
480 if (!sas_address)
481 continue;
482 port_details = phy_info->port_details;
483 /*
484 * Forming a port
485 */
486 if (!port_details) {
487 port_details = kzalloc(sizeof(*port_details),
488 GFP_KERNEL);
489 if (!port_details)
490 goto out;
491 port_details->num_phys = 1;
492 port_details->port_info = port_info;
Eric Moore547f9a22006-06-27 14:42:12 -0600493 if (phy_info->phy_id < 64 )
494 port_details->phy_bitmask |=
495 (1 << phy_info->phy_id);
496 phy_info->sas_port_add_phy=1;
497 dsaswideprintk((KERN_DEBUG "\t\tForming port\n\t\t"
498 "phy_id=%d sas_address=0x%018llX\n",
499 i, sas_address));
500 phy_info->port_details = port_details;
501 }
502
503 if (i == port_info->num_phys - 1)
504 continue;
505 phy_info_cmp = &port_info->phy_info[i + 1];
506 for (j = i + 1 ; j < port_info->num_phys ; j++,
507 phy_info_cmp++) {
508 if (!phy_info_cmp->attached.sas_address)
509 continue;
510 if (sas_address != phy_info_cmp->attached.sas_address)
511 continue;
512 if (phy_info_cmp->port_details == port_details )
513 continue;
514 dsaswideprintk((KERN_DEBUG
515 "\t\tphy_id=%d sas_address=0x%018llX\n",
516 j, phy_info_cmp->attached.sas_address));
517 if (phy_info_cmp->port_details) {
518 port_details->rphy =
519 mptsas_get_rphy(phy_info_cmp);
520 port_details->port =
521 mptsas_get_port(phy_info_cmp);
522 port_details->starget =
523 mptsas_get_starget(phy_info_cmp);
Eric Moore547f9a22006-06-27 14:42:12 -0600524 port_details->num_phys =
525 phy_info_cmp->port_details->num_phys;
Eric Moore547f9a22006-06-27 14:42:12 -0600526 if (!phy_info_cmp->port_details->num_phys)
527 kfree(phy_info_cmp->port_details);
528 } else
529 phy_info_cmp->sas_port_add_phy=1;
530 /*
531 * Adding a phy to a port
532 */
533 phy_info_cmp->port_details = port_details;
534 if (phy_info_cmp->phy_id < 64 )
535 port_details->phy_bitmask |=
536 (1 << phy_info_cmp->phy_id);
537 port_details->num_phys++;
538 }
539 }
540
541 out:
542
543#ifdef MPT_DEBUG_SAS_WIDE
544 for (i = 0; i < port_info->num_phys; i++) {
545 port_details = port_info->phy_info[i].port_details;
546 if (!port_details)
547 continue;
548 dsaswideprintk((KERN_DEBUG
Eric Mooredc22f162006-07-06 11:23:14 -0600549 "%s: [%p]: phy_id=%02d num_phys=%02d "
Eric Moore547f9a22006-06-27 14:42:12 -0600550 "bitmask=0x%016llX\n",
551 __FUNCTION__,
Eric Mooredc22f162006-07-06 11:23:14 -0600552 port_details, i, port_details->num_phys,
553 port_details->phy_bitmask));
Eric Moore547f9a22006-06-27 14:42:12 -0600554 dsaswideprintk((KERN_DEBUG"\t\tport = %p rphy=%p\n",
555 port_details->port, port_details->rphy));
556 }
557 dsaswideprintk((KERN_DEBUG"\n"));
558#endif
559 mutex_unlock(&ioc->sas_topology_mutex);
560}
561
562static void
563mptsas_target_reset(MPT_ADAPTER *ioc, VirtTarget * vtarget)
564{
565 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
566
567 if (mptscsih_TMHandler(hd,
568 MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
569 vtarget->bus_id, vtarget->target_id, 0, 0, 5) < 0) {
570 hd->tmPending = 0;
571 hd->tmState = TM_STATE_NONE;
572 printk(MYIOC_s_WARN_FMT
573 "Error processing TaskMgmt id=%d TARGET_RESET\n",
574 ioc->name, vtarget->target_id);
575 }
576}
577
Christoph Hellwige3094442006-02-16 13:25:36 +0100578static int
Moore, Eric52435432006-03-14 09:14:15 -0700579mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
Christoph Hellwige3094442006-02-16 13:25:36 +0100580 u32 form, u32 form_specific)
581{
582 ConfigExtendedPageHeader_t hdr;
583 CONFIGPARMS cfg;
584 SasEnclosurePage0_t *buffer;
585 dma_addr_t dma_handle;
586 int error;
587 __le64 le_identifier;
588
589 memset(&hdr, 0, sizeof(hdr));
590 hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
591 hdr.PageNumber = 0;
592 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
593 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
594
595 cfg.cfghdr.ehdr = &hdr;
596 cfg.physAddr = -1;
597 cfg.pageAddr = form + form_specific;
598 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
599 cfg.dir = 0; /* read */
600 cfg.timeout = 10;
601
602 error = mpt_config(ioc, &cfg);
603 if (error)
604 goto out;
605 if (!hdr.ExtPageLength) {
606 error = -ENXIO;
607 goto out;
608 }
609
610 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
611 &dma_handle);
612 if (!buffer) {
613 error = -ENOMEM;
614 goto out;
615 }
616
617 cfg.physAddr = dma_handle;
618 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
619
620 error = mpt_config(ioc, &cfg);
621 if (error)
622 goto out_free_consistent;
623
624 /* save config data */
625 memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
626 enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
627 enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
628 enclosure->flags = le16_to_cpu(buffer->Flags);
629 enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
630 enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
631 enclosure->start_id = buffer->StartTargetID;
632 enclosure->start_channel = buffer->StartBus;
633 enclosure->sep_id = buffer->SEPTargetID;
634 enclosure->sep_channel = buffer->SEPBus;
635
636 out_free_consistent:
637 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
638 buffer, dma_handle);
639 out:
640 return error;
641}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200642
James Bottomleyf013db32006-03-18 14:54:36 -0600643static int
644mptsas_slave_configure(struct scsi_device *sdev)
645{
Moore, Eric3c0c25b2006-04-13 16:08:17 -0600646
James Bottomleye8bf3942006-07-11 17:49:34 -0400647 if (sdev->channel == MPTSAS_RAID_CHANNEL)
648 goto out;
James Bottomleyf013db32006-03-18 14:54:36 -0600649
James Bottomleye8bf3942006-07-11 17:49:34 -0400650 sas_read_port_mode_page(sdev);
651
652 out:
James Bottomleyf013db32006-03-18 14:54:36 -0600653 return mptscsih_slave_configure(sdev);
654}
655
Eric Moore547f9a22006-06-27 14:42:12 -0600656static int
657mptsas_target_alloc(struct scsi_target *starget)
658{
659 struct Scsi_Host *host = dev_to_shost(&starget->dev);
660 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
661 VirtTarget *vtarget;
662 u32 target_id;
663 u32 channel;
664 struct sas_rphy *rphy;
665 struct mptsas_portinfo *p;
666 int i;
667
668 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
669 if (!vtarget)
670 return -ENOMEM;
671
672 vtarget->starget = starget;
673 vtarget->ioc_id = hd->ioc->id;
674 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES|MPT_TARGET_FLAGS_VALID_INQUIRY;
675
676 target_id = starget->id;
677 channel = 0;
678
679 hd->Targets[target_id] = vtarget;
680
James Bottomleye8bf3942006-07-11 17:49:34 -0400681 if (starget->channel == MPTSAS_RAID_CHANNEL)
Eric Moore547f9a22006-06-27 14:42:12 -0600682 goto out;
683
684 rphy = dev_to_rphy(starget->dev.parent);
685 mutex_lock(&hd->ioc->sas_topology_mutex);
686 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
687 for (i = 0; i < p->num_phys; i++) {
688 if (p->phy_info[i].attached.sas_address !=
689 rphy->identify.sas_address)
690 continue;
691 target_id = p->phy_info[i].attached.id;
692 channel = p->phy_info[i].attached.channel;
693 mptsas_set_starget(&p->phy_info[i], starget);
694
695 /*
696 * Exposing hidden raid components
697 */
698 if (mptscsih_is_phys_disk(hd->ioc, target_id)) {
699 target_id = mptscsih_raid_id_to_num(hd,
700 target_id);
701 vtarget->tflags |=
702 MPT_TARGET_FLAGS_RAID_COMPONENT;
703 }
704 mutex_unlock(&hd->ioc->sas_topology_mutex);
705 goto out;
706 }
707 }
708 mutex_unlock(&hd->ioc->sas_topology_mutex);
709
710 kfree(vtarget);
711 return -ENXIO;
712
713 out:
714 vtarget->target_id = target_id;
715 vtarget->bus_id = channel;
716 starget->hostdata = vtarget;
717 return 0;
718}
719
720static void
721mptsas_target_destroy(struct scsi_target *starget)
722{
723 struct Scsi_Host *host = dev_to_shost(&starget->dev);
724 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
725 struct sas_rphy *rphy;
726 struct mptsas_portinfo *p;
727 int i;
728
729 if (!starget->hostdata)
730 return;
731
James Bottomleye8bf3942006-07-11 17:49:34 -0400732 if (starget->channel == MPTSAS_RAID_CHANNEL)
Eric Moore547f9a22006-06-27 14:42:12 -0600733 goto out;
734
735 rphy = dev_to_rphy(starget->dev.parent);
736 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
737 for (i = 0; i < p->num_phys; i++) {
738 if (p->phy_info[i].attached.sas_address !=
739 rphy->identify.sas_address)
740 continue;
741 mptsas_set_starget(&p->phy_info[i], NULL);
742 goto out;
743 }
744 }
745
746 out:
747 kfree(starget->hostdata);
748 starget->hostdata = NULL;
749}
750
751
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200752static int
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700753mptsas_slave_alloc(struct scsi_device *sdev)
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200754{
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700755 struct Scsi_Host *host = sdev->host;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200756 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
757 struct sas_rphy *rphy;
758 struct mptsas_portinfo *p;
759 VirtDevice *vdev;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700760 struct scsi_target *starget;
Eric Moore547f9a22006-06-27 14:42:12 -0600761 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200762
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +0100763 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200764 if (!vdev) {
Eric Moore547f9a22006-06-27 14:42:12 -0600765 printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200766 hd->ioc->name, sizeof(VirtDevice));
767 return -ENOMEM;
768 }
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700769 starget = scsi_target(sdev);
Eric Moore547f9a22006-06-27 14:42:12 -0600770 vdev->vtarget = starget->hostdata;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200771
James Bottomleye8bf3942006-07-11 17:49:34 -0400772 if (sdev->channel == MPTSAS_RAID_CHANNEL)
Moore, Eric816aa902006-01-13 16:25:20 -0700773 goto out;
Moore, Eric816aa902006-01-13 16:25:20 -0700774
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700775 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100776 mutex_lock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200777 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
778 for (i = 0; i < p->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -0600779 if (p->phy_info[i].attached.sas_address !=
780 rphy->identify.sas_address)
781 continue;
782 vdev->lun = sdev->lun;
783 /*
784 * Exposing hidden raid components
785 */
786 if (mptscsih_is_phys_disk(hd->ioc,
787 p->phy_info[i].attached.id))
788 sdev->no_uld_attach = 1;
789 mutex_unlock(&hd->ioc->sas_topology_mutex);
790 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200791 }
792 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100793 mutex_unlock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200794
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200795 kfree(vdev);
Christoph Hellwig23f236e2006-01-30 19:00:43 +0100796 return -ENXIO;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200797
798 out:
Eric Moore547f9a22006-06-27 14:42:12 -0600799 vdev->vtarget->num_luns++;
800 sdev->hostdata = vdev;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200801 return 0;
802}
803
Eric Moore547f9a22006-06-27 14:42:12 -0600804static int
805mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100806{
Eric Moore547f9a22006-06-27 14:42:12 -0600807 VirtDevice *vdev = SCpnt->device->hostdata;
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100808
Eric Moore547f9a22006-06-27 14:42:12 -0600809// scsi_print_command(SCpnt);
810 if (vdev->vtarget->deleted) {
811 SCpnt->result = DID_NO_CONNECT << 16;
812 done(SCpnt);
813 return 0;
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700814 }
Eric Moore547f9a22006-06-27 14:42:12 -0600815
816 return mptscsih_qcmd(SCpnt,done);
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100817}
818
Eric Moore547f9a22006-06-27 14:42:12 -0600819
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200820static struct scsi_host_template mptsas_driver_template = {
Moore, Eric Deanf78496d2005-11-16 18:54:14 -0700821 .module = THIS_MODULE,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200822 .proc_name = "mptsas",
823 .proc_info = mptscsih_proc_info,
824 .name = "MPT SPI Host",
825 .info = mptscsih_info,
Eric Moore547f9a22006-06-27 14:42:12 -0600826 .queuecommand = mptsas_qcmd,
827 .target_alloc = mptsas_target_alloc,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200828 .slave_alloc = mptsas_slave_alloc,
James Bottomleyf013db32006-03-18 14:54:36 -0600829 .slave_configure = mptsas_slave_configure,
Eric Moore547f9a22006-06-27 14:42:12 -0600830 .target_destroy = mptsas_target_destroy,
831 .slave_destroy = mptscsih_slave_destroy,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200832 .change_queue_depth = mptscsih_change_queue_depth,
833 .eh_abort_handler = mptscsih_abort,
834 .eh_device_reset_handler = mptscsih_dev_reset,
835 .eh_bus_reset_handler = mptscsih_bus_reset,
836 .eh_host_reset_handler = mptscsih_host_reset,
837 .bios_param = mptscsih_bios_param,
838 .can_queue = MPT_FC_CAN_QUEUE,
839 .this_id = -1,
840 .sg_tablesize = MPT_SCSI_SG_DEPTH,
841 .max_sectors = 8192,
842 .cmd_per_lun = 7,
843 .use_clustering = ENABLE_CLUSTERING,
844};
845
Christoph Hellwigb5141122005-10-28 22:07:41 +0200846static int mptsas_get_linkerrors(struct sas_phy *phy)
847{
848 MPT_ADAPTER *ioc = phy_to_ioc(phy);
849 ConfigExtendedPageHeader_t hdr;
850 CONFIGPARMS cfg;
851 SasPhyPage1_t *buffer;
852 dma_addr_t dma_handle;
853 int error;
854
855 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
856 hdr.ExtPageLength = 0;
857 hdr.PageNumber = 1 /* page number 1*/;
858 hdr.Reserved1 = 0;
859 hdr.Reserved2 = 0;
860 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
861 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
862
863 cfg.cfghdr.ehdr = &hdr;
864 cfg.physAddr = -1;
865 cfg.pageAddr = phy->identify.phy_identifier;
866 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
867 cfg.dir = 0; /* read */
868 cfg.timeout = 10;
869
870 error = mpt_config(ioc, &cfg);
871 if (error)
872 return error;
873 if (!hdr.ExtPageLength)
874 return -ENXIO;
875
876 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
877 &dma_handle);
878 if (!buffer)
879 return -ENOMEM;
880
881 cfg.physAddr = dma_handle;
882 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
883
884 error = mpt_config(ioc, &cfg);
885 if (error)
886 goto out_free_consistent;
887
888 mptsas_print_phy_pg1(buffer);
889
890 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
891 phy->running_disparity_error_count =
892 le32_to_cpu(buffer->RunningDisparityErrorCount);
893 phy->loss_of_dword_sync_count =
894 le32_to_cpu(buffer->LossDwordSynchCount);
895 phy->phy_reset_problem_count =
896 le32_to_cpu(buffer->PhyResetProblemCount);
897
898 out_free_consistent:
899 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
900 buffer, dma_handle);
901 return error;
902}
903
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200904static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
905 MPT_FRAME_HDR *reply)
906{
907 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
908 if (reply != NULL) {
909 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
910 memcpy(ioc->sas_mgmt.reply, reply,
911 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
912 }
913 complete(&ioc->sas_mgmt.done);
914 return 1;
915}
916
917static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
918{
919 MPT_ADAPTER *ioc = phy_to_ioc(phy);
920 SasIoUnitControlRequest_t *req;
921 SasIoUnitControlReply_t *reply;
922 MPT_FRAME_HDR *mf;
923 MPIHeader_t *hdr;
924 unsigned long timeleft;
925 int error = -ERESTARTSYS;
926
927 /* not implemented for expanders */
928 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
929 return -ENXIO;
930
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100931 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200932 goto out;
933
934 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
935 if (!mf) {
936 error = -ENOMEM;
937 goto out_unlock;
938 }
939
940 hdr = (MPIHeader_t *) mf;
941 req = (SasIoUnitControlRequest_t *)mf;
942 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
943 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
944 req->MsgContext = hdr->MsgContext;
945 req->Operation = hard_reset ?
946 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
947 req->PhyNum = phy->identify.phy_identifier;
948
949 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
950
951 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
952 10 * HZ);
953 if (!timeleft) {
954 /* On timeout reset the board */
955 mpt_free_msg_frame(ioc, mf);
956 mpt_HardResetHandler(ioc, CAN_SLEEP);
957 error = -ETIMEDOUT;
958 goto out_unlock;
959 }
960
961 /* a reply frame is expected */
962 if ((ioc->sas_mgmt.status &
963 MPT_IOCTL_STATUS_RF_VALID) == 0) {
964 error = -ENXIO;
965 goto out_unlock;
966 }
967
968 /* process the completed Reply Message Frame */
969 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
970 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
971 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
972 __FUNCTION__,
973 reply->IOCStatus,
974 reply->IOCLogInfo);
975 error = -ENXIO;
976 goto out_unlock;
977 }
978
979 error = 0;
980
981 out_unlock:
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100982 mutex_unlock(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200983 out:
984 return error;
985}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200986
Christoph Hellwige3094442006-02-16 13:25:36 +0100987static int
988mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
989{
990 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
991 int i, error;
992 struct mptsas_portinfo *p;
993 struct mptsas_enclosure enclosure_info;
994 u64 enclosure_handle;
995
996 mutex_lock(&ioc->sas_topology_mutex);
997 list_for_each_entry(p, &ioc->sas_topology, list) {
998 for (i = 0; i < p->num_phys; i++) {
999 if (p->phy_info[i].attached.sas_address ==
1000 rphy->identify.sas_address) {
1001 enclosure_handle = p->phy_info[i].
1002 attached.handle_enclosure;
1003 goto found_info;
1004 }
1005 }
1006 }
1007 mutex_unlock(&ioc->sas_topology_mutex);
1008 return -ENXIO;
1009
1010 found_info:
1011 mutex_unlock(&ioc->sas_topology_mutex);
1012 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
Moore, Eric52435432006-03-14 09:14:15 -07001013 error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
Christoph Hellwige3094442006-02-16 13:25:36 +01001014 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
1015 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
1016 if (!error)
1017 *identifier = enclosure_info.enclosure_logical_id;
1018 return error;
1019}
1020
1021static int
1022mptsas_get_bay_identifier(struct sas_rphy *rphy)
1023{
1024 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1025 struct mptsas_portinfo *p;
1026 int i, rc;
1027
1028 mutex_lock(&ioc->sas_topology_mutex);
1029 list_for_each_entry(p, &ioc->sas_topology, list) {
1030 for (i = 0; i < p->num_phys; i++) {
1031 if (p->phy_info[i].attached.sas_address ==
1032 rphy->identify.sas_address) {
1033 rc = p->phy_info[i].attached.slot;
1034 goto out;
1035 }
1036 }
1037 }
1038 rc = -ENXIO;
1039 out:
1040 mutex_unlock(&ioc->sas_topology_mutex);
1041 return rc;
1042}
1043
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001044static struct sas_function_template mptsas_transport_functions = {
Christoph Hellwigb5141122005-10-28 22:07:41 +02001045 .get_linkerrors = mptsas_get_linkerrors,
Christoph Hellwige3094442006-02-16 13:25:36 +01001046 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
1047 .get_bay_identifier = mptsas_get_bay_identifier,
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001048 .phy_reset = mptsas_phy_reset,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001049};
1050
1051static struct scsi_transport_template *mptsas_transport_template;
1052
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001053static int
1054mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
1055{
1056 ConfigExtendedPageHeader_t hdr;
1057 CONFIGPARMS cfg;
1058 SasIOUnitPage0_t *buffer;
1059 dma_addr_t dma_handle;
1060 int error, i;
1061
1062 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
1063 hdr.ExtPageLength = 0;
1064 hdr.PageNumber = 0;
1065 hdr.Reserved1 = 0;
1066 hdr.Reserved2 = 0;
1067 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1068 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1069
1070 cfg.cfghdr.ehdr = &hdr;
1071 cfg.physAddr = -1;
1072 cfg.pageAddr = 0;
1073 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1074 cfg.dir = 0; /* read */
1075 cfg.timeout = 10;
1076
1077 error = mpt_config(ioc, &cfg);
1078 if (error)
1079 goto out;
1080 if (!hdr.ExtPageLength) {
1081 error = -ENXIO;
1082 goto out;
1083 }
1084
1085 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1086 &dma_handle);
1087 if (!buffer) {
1088 error = -ENOMEM;
1089 goto out;
1090 }
1091
1092 cfg.physAddr = dma_handle;
1093 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1094
1095 error = mpt_config(ioc, &cfg);
1096 if (error)
1097 goto out_free_consistent;
1098
1099 port_info->num_phys = buffer->NumPhys;
1100 port_info->phy_info = kcalloc(port_info->num_phys,
Eric Moore547f9a22006-06-27 14:42:12 -06001101 sizeof(*port_info->phy_info),GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001102 if (!port_info->phy_info) {
1103 error = -ENOMEM;
1104 goto out_free_consistent;
1105 }
1106
Moore, Ericdb9c9172006-03-14 09:14:18 -07001107 if (port_info->num_phys)
1108 port_info->handle =
1109 le16_to_cpu(buffer->PhyData[0].ControllerDevHandle);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001110 for (i = 0; i < port_info->num_phys; i++) {
1111 mptsas_print_phy_data(&buffer->PhyData[i]);
1112 port_info->phy_info[i].phy_id = i;
1113 port_info->phy_info[i].port_id =
1114 buffer->PhyData[i].Port;
1115 port_info->phy_info[i].negotiated_link_rate =
1116 buffer->PhyData[i].NegotiatedLinkRate;
Eric Moore547f9a22006-06-27 14:42:12 -06001117 port_info->phy_info[i].portinfo = port_info;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001118 }
1119
1120 out_free_consistent:
1121 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1122 buffer, dma_handle);
1123 out:
1124 return error;
1125}
1126
1127static int
1128mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1129 u32 form, u32 form_specific)
1130{
1131 ConfigExtendedPageHeader_t hdr;
1132 CONFIGPARMS cfg;
1133 SasPhyPage0_t *buffer;
1134 dma_addr_t dma_handle;
1135 int error;
1136
1137 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
1138 hdr.ExtPageLength = 0;
1139 hdr.PageNumber = 0;
1140 hdr.Reserved1 = 0;
1141 hdr.Reserved2 = 0;
1142 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1143 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
1144
1145 cfg.cfghdr.ehdr = &hdr;
1146 cfg.dir = 0; /* read */
1147 cfg.timeout = 10;
1148
1149 /* Get Phy Pg 0 for each Phy. */
1150 cfg.physAddr = -1;
1151 cfg.pageAddr = form + form_specific;
1152 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1153
1154 error = mpt_config(ioc, &cfg);
1155 if (error)
1156 goto out;
1157
1158 if (!hdr.ExtPageLength) {
1159 error = -ENXIO;
1160 goto out;
1161 }
1162
1163 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1164 &dma_handle);
1165 if (!buffer) {
1166 error = -ENOMEM;
1167 goto out;
1168 }
1169
1170 cfg.physAddr = dma_handle;
1171 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1172
1173 error = mpt_config(ioc, &cfg);
1174 if (error)
1175 goto out_free_consistent;
1176
1177 mptsas_print_phy_pg0(buffer);
1178
1179 phy_info->hw_link_rate = buffer->HwLinkRate;
1180 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1181 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1182 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1183
1184 out_free_consistent:
1185 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1186 buffer, dma_handle);
1187 out:
1188 return error;
1189}
1190
1191static int
1192mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
1193 u32 form, u32 form_specific)
1194{
1195 ConfigExtendedPageHeader_t hdr;
1196 CONFIGPARMS cfg;
1197 SasDevicePage0_t *buffer;
1198 dma_addr_t dma_handle;
1199 __le64 sas_address;
Moore, Ericbd23e942006-04-17 12:43:04 -06001200 int error=0;
1201
1202 if (ioc->sas_discovery_runtime &&
1203 mptsas_is_end_device(device_info))
1204 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001205
1206 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
1207 hdr.ExtPageLength = 0;
1208 hdr.PageNumber = 0;
1209 hdr.Reserved1 = 0;
1210 hdr.Reserved2 = 0;
1211 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1212 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1213
1214 cfg.cfghdr.ehdr = &hdr;
1215 cfg.pageAddr = form + form_specific;
1216 cfg.physAddr = -1;
1217 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1218 cfg.dir = 0; /* read */
1219 cfg.timeout = 10;
1220
Moore, Ericdb9c9172006-03-14 09:14:18 -07001221 memset(device_info, 0, sizeof(struct mptsas_devinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001222 error = mpt_config(ioc, &cfg);
1223 if (error)
1224 goto out;
1225 if (!hdr.ExtPageLength) {
1226 error = -ENXIO;
1227 goto out;
1228 }
1229
1230 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1231 &dma_handle);
1232 if (!buffer) {
1233 error = -ENOMEM;
1234 goto out;
1235 }
1236
1237 cfg.physAddr = dma_handle;
1238 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1239
1240 error = mpt_config(ioc, &cfg);
1241 if (error)
1242 goto out_free_consistent;
1243
1244 mptsas_print_device_pg0(buffer);
1245
1246 device_info->handle = le16_to_cpu(buffer->DevHandle);
Moore, Ericc73787ee2006-01-26 16:20:06 -07001247 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
Christoph Hellwige3094442006-02-16 13:25:36 +01001248 device_info->handle_enclosure =
1249 le16_to_cpu(buffer->EnclosureHandle);
1250 device_info->slot = le16_to_cpu(buffer->Slot);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001251 device_info->phy_id = buffer->PhyNum;
1252 device_info->port_id = buffer->PhysicalPort;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001253 device_info->id = buffer->TargetID;
1254 device_info->channel = buffer->Bus;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001255 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
1256 device_info->sas_address = le64_to_cpu(sas_address);
1257 device_info->device_info =
1258 le32_to_cpu(buffer->DeviceInfo);
1259
1260 out_free_consistent:
1261 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1262 buffer, dma_handle);
1263 out:
1264 return error;
1265}
1266
1267static int
1268mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
1269 u32 form, u32 form_specific)
1270{
1271 ConfigExtendedPageHeader_t hdr;
1272 CONFIGPARMS cfg;
1273 SasExpanderPage0_t *buffer;
1274 dma_addr_t dma_handle;
Eric Moore547f9a22006-06-27 14:42:12 -06001275 int i, error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001276
1277 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1278 hdr.ExtPageLength = 0;
1279 hdr.PageNumber = 0;
1280 hdr.Reserved1 = 0;
1281 hdr.Reserved2 = 0;
1282 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1283 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1284
1285 cfg.cfghdr.ehdr = &hdr;
1286 cfg.physAddr = -1;
1287 cfg.pageAddr = form + form_specific;
1288 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1289 cfg.dir = 0; /* read */
1290 cfg.timeout = 10;
1291
Moore, Ericdb9c9172006-03-14 09:14:18 -07001292 memset(port_info, 0, sizeof(struct mptsas_portinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001293 error = mpt_config(ioc, &cfg);
1294 if (error)
1295 goto out;
1296
1297 if (!hdr.ExtPageLength) {
1298 error = -ENXIO;
1299 goto out;
1300 }
1301
1302 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1303 &dma_handle);
1304 if (!buffer) {
1305 error = -ENOMEM;
1306 goto out;
1307 }
1308
1309 cfg.physAddr = dma_handle;
1310 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1311
1312 error = mpt_config(ioc, &cfg);
1313 if (error)
1314 goto out_free_consistent;
1315
1316 /* save config data */
1317 port_info->num_phys = buffer->NumPhys;
1318 port_info->handle = le16_to_cpu(buffer->DevHandle);
1319 port_info->phy_info = kcalloc(port_info->num_phys,
Eric Moore547f9a22006-06-27 14:42:12 -06001320 sizeof(*port_info->phy_info),GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001321 if (!port_info->phy_info) {
1322 error = -ENOMEM;
1323 goto out_free_consistent;
1324 }
1325
Eric Moore547f9a22006-06-27 14:42:12 -06001326 for (i = 0; i < port_info->num_phys; i++)
1327 port_info->phy_info[i].portinfo = port_info;
1328
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001329 out_free_consistent:
1330 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1331 buffer, dma_handle);
1332 out:
1333 return error;
1334}
1335
1336static int
1337mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1338 u32 form, u32 form_specific)
1339{
1340 ConfigExtendedPageHeader_t hdr;
1341 CONFIGPARMS cfg;
1342 SasExpanderPage1_t *buffer;
1343 dma_addr_t dma_handle;
Moore, Ericbd23e942006-04-17 12:43:04 -06001344 int error=0;
1345
1346 if (ioc->sas_discovery_runtime &&
1347 mptsas_is_end_device(&phy_info->attached))
1348 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001349
1350 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1351 hdr.ExtPageLength = 0;
1352 hdr.PageNumber = 1;
1353 hdr.Reserved1 = 0;
1354 hdr.Reserved2 = 0;
1355 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1356 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1357
1358 cfg.cfghdr.ehdr = &hdr;
1359 cfg.physAddr = -1;
1360 cfg.pageAddr = form + form_specific;
1361 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1362 cfg.dir = 0; /* read */
1363 cfg.timeout = 10;
1364
1365 error = mpt_config(ioc, &cfg);
1366 if (error)
1367 goto out;
1368
1369 if (!hdr.ExtPageLength) {
1370 error = -ENXIO;
1371 goto out;
1372 }
1373
1374 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1375 &dma_handle);
1376 if (!buffer) {
1377 error = -ENOMEM;
1378 goto out;
1379 }
1380
1381 cfg.physAddr = dma_handle;
1382 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1383
1384 error = mpt_config(ioc, &cfg);
1385 if (error)
1386 goto out_free_consistent;
1387
1388
1389 mptsas_print_expander_pg1(buffer);
1390
1391 /* save config data */
Eric Moore024358e2005-10-21 20:56:36 +02001392 phy_info->phy_id = buffer->PhyIdentifier;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001393 phy_info->port_id = buffer->PhysicalPort;
1394 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
1395 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1396 phy_info->hw_link_rate = buffer->HwLinkRate;
1397 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1398 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1399
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001400 out_free_consistent:
1401 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1402 buffer, dma_handle);
1403 out:
1404 return error;
1405}
1406
1407static void
1408mptsas_parse_device_info(struct sas_identify *identify,
1409 struct mptsas_devinfo *device_info)
1410{
1411 u16 protocols;
1412
1413 identify->sas_address = device_info->sas_address;
1414 identify->phy_identifier = device_info->phy_id;
1415
1416 /*
1417 * Fill in Phy Initiator Port Protocol.
1418 * Bits 6:3, more than one bit can be set, fall through cases.
1419 */
1420 protocols = device_info->device_info & 0x78;
1421 identify->initiator_port_protocols = 0;
1422 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
1423 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
1424 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1425 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
1426 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
1427 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
1428 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
1429 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
1430
1431 /*
1432 * Fill in Phy Target Port Protocol.
1433 * Bits 10:7, more than one bit can be set, fall through cases.
1434 */
1435 protocols = device_info->device_info & 0x780;
1436 identify->target_port_protocols = 0;
1437 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1438 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
1439 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
1440 identify->target_port_protocols |= SAS_PROTOCOL_STP;
1441 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
1442 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
1443 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1444 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
1445
1446 /*
1447 * Fill in Attached device type.
1448 */
1449 switch (device_info->device_info &
1450 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
1451 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
1452 identify->device_type = SAS_PHY_UNUSED;
1453 break;
1454 case MPI_SAS_DEVICE_INFO_END_DEVICE:
1455 identify->device_type = SAS_END_DEVICE;
1456 break;
1457 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
1458 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
1459 break;
1460 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
1461 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
1462 break;
1463 }
1464}
1465
1466static int mptsas_probe_one_phy(struct device *dev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001467 struct mptsas_phyinfo *phy_info, int index, int local)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001468{
Moore, Erice6b2d762006-03-14 09:14:24 -07001469 MPT_ADAPTER *ioc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001470 struct sas_phy *phy;
Eric Moore547f9a22006-06-27 14:42:12 -06001471 struct sas_port *port;
1472 int error = 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001473
Eric Moore547f9a22006-06-27 14:42:12 -06001474 if (!dev) {
1475 error = -ENODEV;
1476 goto out;
1477 }
Moore, Erice6b2d762006-03-14 09:14:24 -07001478
1479 if (!phy_info->phy) {
1480 phy = sas_phy_alloc(dev, index);
Eric Moore547f9a22006-06-27 14:42:12 -06001481 if (!phy) {
1482 error = -ENOMEM;
1483 goto out;
1484 }
Moore, Erice6b2d762006-03-14 09:14:24 -07001485 } else
1486 phy = phy_info->phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001487
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001488 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001489
1490 /*
1491 * Set Negotiated link rate.
1492 */
1493 switch (phy_info->negotiated_link_rate) {
1494 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001495 phy->negotiated_linkrate = SAS_PHY_DISABLED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001496 break;
1497 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001498 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001499 break;
1500 case MPI_SAS_IOUNIT0_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001501 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001502 break;
1503 case MPI_SAS_IOUNIT0_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001504 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001505 break;
1506 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
1507 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
1508 default:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001509 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001510 break;
1511 }
1512
1513 /*
1514 * Set Max hardware link rate.
1515 */
1516 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1517 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001518 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001519 break;
1520 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001521 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001522 break;
1523 default:
1524 break;
1525 }
1526
1527 /*
1528 * Set Max programmed link rate.
1529 */
1530 switch (phy_info->programmed_link_rate &
1531 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1532 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001533 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001534 break;
1535 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001536 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001537 break;
1538 default:
1539 break;
1540 }
1541
1542 /*
1543 * Set Min hardware link rate.
1544 */
1545 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
1546 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001547 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001548 break;
1549 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001550 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001551 break;
1552 default:
1553 break;
1554 }
1555
1556 /*
1557 * Set Min programmed link rate.
1558 */
1559 switch (phy_info->programmed_link_rate &
1560 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
1561 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001562 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001563 break;
1564 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001565 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001566 break;
1567 default:
1568 break;
1569 }
1570
Moore, Erice6b2d762006-03-14 09:14:24 -07001571 if (!phy_info->phy) {
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001572
Moore, Erice6b2d762006-03-14 09:14:24 -07001573 if (local)
1574 phy->local_attached = 1;
1575
1576 error = sas_phy_add(phy);
1577 if (error) {
1578 sas_phy_free(phy);
Eric Moore547f9a22006-06-27 14:42:12 -06001579 goto out;
Moore, Erice6b2d762006-03-14 09:14:24 -07001580 }
1581 phy_info->phy = phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001582 }
1583
Eric Moore547f9a22006-06-27 14:42:12 -06001584 if (!phy_info->attached.handle ||
1585 !phy_info->port_details)
1586 goto out;
1587
1588 port = mptsas_get_port(phy_info);
1589 ioc = phy_to_ioc(phy_info->phy);
1590
1591 if (phy_info->sas_port_add_phy) {
1592
1593 if (!port) {
Eric Mooredc22f162006-07-06 11:23:14 -06001594 port = sas_port_alloc_num(dev);
Eric Moore547f9a22006-06-27 14:42:12 -06001595 if (!port) {
1596 error = -ENOMEM;
1597 goto out;
1598 }
1599 error = sas_port_add(port);
1600 if (error) {
1601 dfailprintk((MYIOC_s_ERR_FMT
1602 "%s: exit at line=%d\n", ioc->name,
1603 __FUNCTION__, __LINE__));
1604 goto out;
1605 }
1606 mptsas_set_port(phy_info, port);
Eric Mooredc22f162006-07-06 11:23:14 -06001607 dsaswideprintk((KERN_DEBUG
1608 "sas_port_alloc: port=%p dev=%p port_id=%d\n",
1609 port, dev, port->port_identifier));
Eric Moore547f9a22006-06-27 14:42:12 -06001610 }
1611 dsaswideprintk((KERN_DEBUG "sas_port_add_phy: phy_id=%d\n",
1612 phy_info->phy_id));
1613 sas_port_add_phy(port, phy_info->phy);
1614 phy_info->sas_port_add_phy = 0;
1615 }
1616
1617 if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
Moore, Erice6b2d762006-03-14 09:14:24 -07001618
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001619 struct sas_rphy *rphy;
James Bottomley2686de22006-06-30 12:54:02 -05001620 struct device *parent;
James Bottomleyf013db32006-03-18 14:54:36 -06001621 struct sas_identify identify;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001622
James Bottomley2686de22006-06-30 12:54:02 -05001623 parent = dev->parent->parent;
Moore, Erice6b2d762006-03-14 09:14:24 -07001624 /*
1625 * Let the hotplug_work thread handle processing
1626 * the adding/removing of devices that occur
1627 * after start of day.
1628 */
1629 if (ioc->sas_discovery_runtime &&
1630 mptsas_is_end_device(&phy_info->attached))
Eric Moore547f9a22006-06-27 14:42:12 -06001631 goto out;
Moore, Erice6b2d762006-03-14 09:14:24 -07001632
James Bottomleyf013db32006-03-18 14:54:36 -06001633 mptsas_parse_device_info(&identify, &phy_info->attached);
James Bottomley2686de22006-06-30 12:54:02 -05001634 if (scsi_is_host_device(parent)) {
1635 struct mptsas_portinfo *port_info;
1636 int i;
1637
1638 mutex_lock(&ioc->sas_topology_mutex);
1639 port_info = mptsas_find_portinfo_by_handle(ioc,
1640 ioc->handle);
1641 mutex_unlock(&ioc->sas_topology_mutex);
1642
1643 for (i = 0; i < port_info->num_phys; i++)
1644 if (port_info->phy_info[i].identify.sas_address ==
James Bottomley0c269e62006-07-12 09:51:04 -04001645 identify.sas_address) {
1646 sas_port_mark_backlink(port);
James Bottomley2686de22006-06-30 12:54:02 -05001647 goto out;
James Bottomley0c269e62006-07-12 09:51:04 -04001648 }
James Bottomley2686de22006-06-30 12:54:02 -05001649
1650 } else if (scsi_is_sas_rphy(parent)) {
1651 struct sas_rphy *parent_rphy = dev_to_rphy(parent);
1652 if (identify.sas_address ==
James Bottomley0c269e62006-07-12 09:51:04 -04001653 parent_rphy->identify.sas_address) {
1654 sas_port_mark_backlink(port);
James Bottomley2686de22006-06-30 12:54:02 -05001655 goto out;
James Bottomley0c269e62006-07-12 09:51:04 -04001656 }
James Bottomley2686de22006-06-30 12:54:02 -05001657 }
1658
James Bottomleyf013db32006-03-18 14:54:36 -06001659 switch (identify.device_type) {
1660 case SAS_END_DEVICE:
Eric Moore547f9a22006-06-27 14:42:12 -06001661 rphy = sas_end_device_alloc(port);
James Bottomleyf013db32006-03-18 14:54:36 -06001662 break;
1663 case SAS_EDGE_EXPANDER_DEVICE:
1664 case SAS_FANOUT_EXPANDER_DEVICE:
Eric Moore547f9a22006-06-27 14:42:12 -06001665 rphy = sas_expander_alloc(port, identify.device_type);
James Bottomleyf013db32006-03-18 14:54:36 -06001666 break;
1667 default:
1668 rphy = NULL;
1669 break;
1670 }
Eric Moore547f9a22006-06-27 14:42:12 -06001671 if (!rphy) {
1672 dfailprintk((MYIOC_s_ERR_FMT
1673 "%s: exit at line=%d\n", ioc->name,
1674 __FUNCTION__, __LINE__));
1675 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001676 }
1677
Eric Moore547f9a22006-06-27 14:42:12 -06001678 rphy->identify = identify;
1679 error = sas_rphy_add(rphy);
1680 if (error) {
1681 dfailprintk((MYIOC_s_ERR_FMT
1682 "%s: exit at line=%d\n", ioc->name,
1683 __FUNCTION__, __LINE__));
1684 sas_rphy_free(rphy);
1685 goto out;
1686 }
1687 mptsas_set_rphy(phy_info, rphy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001688 }
1689
Eric Moore547f9a22006-06-27 14:42:12 -06001690 out:
1691 return error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001692}
1693
1694static int
Moore, Erice6b2d762006-03-14 09:14:24 -07001695mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001696{
Moore, Erice6b2d762006-03-14 09:14:24 -07001697 struct mptsas_portinfo *port_info, *hba;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001698 u32 handle = 0xFFFF;
1699 int error = -ENOMEM, i;
1700
Moore, Erice6b2d762006-03-14 09:14:24 -07001701 hba = kzalloc(sizeof(*port_info), GFP_KERNEL);
1702 if (! hba)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001703 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001704
Moore, Erice6b2d762006-03-14 09:14:24 -07001705 error = mptsas_sas_io_unit_pg0(ioc, hba);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001706 if (error)
1707 goto out_free_port_info;
1708
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001709 mutex_lock(&ioc->sas_topology_mutex);
James Bottomley2686de22006-06-30 12:54:02 -05001710 ioc->handle = hba->handle;
Moore, Erice6b2d762006-03-14 09:14:24 -07001711 port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle);
1712 if (!port_info) {
1713 port_info = hba;
1714 list_add_tail(&port_info->list, &ioc->sas_topology);
1715 } else {
1716 port_info->handle = hba->handle;
1717 for (i = 0; i < hba->num_phys; i++)
1718 port_info->phy_info[i].negotiated_link_rate =
1719 hba->phy_info[i].negotiated_link_rate;
Eric Moore547f9a22006-06-27 14:42:12 -06001720 kfree(hba->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001721 kfree(hba);
1722 hba = NULL;
1723 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001724 mutex_unlock(&ioc->sas_topology_mutex);
1725
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001726 for (i = 0; i < port_info->num_phys; i++) {
1727 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
1728 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
1729 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
1730
1731 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
1732 (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
1733 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
Eric Moore024358e2005-10-21 20:56:36 +02001734 port_info->phy_info[i].identify.phy_id =
1735 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001736 handle = port_info->phy_info[i].identify.handle;
1737
Eric Moore547f9a22006-06-27 14:42:12 -06001738 if (port_info->phy_info[i].attached.handle)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001739 mptsas_sas_device_pg0(ioc,
1740 &port_info->phy_info[i].attached,
1741 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1742 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1743 port_info->phy_info[i].attached.handle);
Eric Moore547f9a22006-06-27 14:42:12 -06001744 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001745
Eric Moore547f9a22006-06-27 14:42:12 -06001746 mptsas_setup_wide_ports(ioc, port_info);
1747
1748 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001749 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
Moore, Erice6b2d762006-03-14 09:14:24 -07001750 &port_info->phy_info[i], ioc->sas_index, 1);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001751
1752 return 0;
1753
1754 out_free_port_info:
Eric Moore547f9a22006-06-27 14:42:12 -06001755 kfree(hba);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001756 out:
1757 return error;
1758}
1759
1760static int
Moore, Erice6b2d762006-03-14 09:14:24 -07001761mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001762{
Moore, Erice6b2d762006-03-14 09:14:24 -07001763 struct mptsas_portinfo *port_info, *p, *ex;
Eric Moore547f9a22006-06-27 14:42:12 -06001764 struct device *parent;
1765 struct sas_rphy *rphy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001766 int error = -ENOMEM, i, j;
1767
Moore, Erice6b2d762006-03-14 09:14:24 -07001768 ex = kzalloc(sizeof(*port_info), GFP_KERNEL);
1769 if (!ex)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001770 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001771
Moore, Erice6b2d762006-03-14 09:14:24 -07001772 error = mptsas_sas_expander_pg0(ioc, ex,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001773 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
1774 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
1775 if (error)
1776 goto out_free_port_info;
1777
Moore, Erice6b2d762006-03-14 09:14:24 -07001778 *handle = ex->handle;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001779
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001780 mutex_lock(&ioc->sas_topology_mutex);
Moore, Erice6b2d762006-03-14 09:14:24 -07001781 port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
1782 if (!port_info) {
1783 port_info = ex;
1784 list_add_tail(&port_info->list, &ioc->sas_topology);
1785 } else {
1786 port_info->handle = ex->handle;
Eric Moore547f9a22006-06-27 14:42:12 -06001787 kfree(ex->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001788 kfree(ex);
1789 ex = NULL;
1790 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001791 mutex_unlock(&ioc->sas_topology_mutex);
1792
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001793 for (i = 0; i < port_info->num_phys; i++) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001794 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
1795 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
1796 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
1797
1798 if (port_info->phy_info[i].identify.handle) {
1799 mptsas_sas_device_pg0(ioc,
1800 &port_info->phy_info[i].identify,
1801 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1802 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1803 port_info->phy_info[i].identify.handle);
Eric Moore024358e2005-10-21 20:56:36 +02001804 port_info->phy_info[i].identify.phy_id =
1805 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001806 }
1807
1808 if (port_info->phy_info[i].attached.handle) {
1809 mptsas_sas_device_pg0(ioc,
1810 &port_info->phy_info[i].attached,
1811 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1812 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1813 port_info->phy_info[i].attached.handle);
Moore, Ericdb9c9172006-03-14 09:14:18 -07001814 port_info->phy_info[i].attached.phy_id =
1815 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001816 }
Eric Moore547f9a22006-06-27 14:42:12 -06001817 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001818
Eric Moore547f9a22006-06-27 14:42:12 -06001819 parent = &ioc->sh->shost_gendev;
1820 for (i = 0; i < port_info->num_phys; i++) {
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001821 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001822 list_for_each_entry(p, &ioc->sas_topology, list) {
1823 for (j = 0; j < p->num_phys; j++) {
Eric Moore547f9a22006-06-27 14:42:12 -06001824 if (port_info->phy_info[i].identify.handle !=
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001825 p->phy_info[j].attached.handle)
Eric Moore547f9a22006-06-27 14:42:12 -06001826 continue;
1827 rphy = mptsas_get_rphy(&p->phy_info[j]);
1828 parent = &rphy->dev;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001829 }
1830 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001831 mutex_unlock(&ioc->sas_topology_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06001832 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001833
Eric Moore547f9a22006-06-27 14:42:12 -06001834 mptsas_setup_wide_ports(ioc, port_info);
1835
1836 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001837 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
Moore, Erice6b2d762006-03-14 09:14:24 -07001838 ioc->sas_index, 0);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001839
1840 return 0;
1841
1842 out_free_port_info:
Moore, Erice6b2d762006-03-14 09:14:24 -07001843 if (ex) {
Eric Moore547f9a22006-06-27 14:42:12 -06001844 kfree(ex->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001845 kfree(ex);
1846 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001847 out:
1848 return error;
1849}
1850
Moore, Erice6b2d762006-03-14 09:14:24 -07001851/*
1852 * mptsas_delete_expander_phys
1853 *
1854 *
1855 * This will traverse topology, and remove expanders
1856 * that are no longer present
1857 */
1858static void
1859mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
1860{
1861 struct mptsas_portinfo buffer;
1862 struct mptsas_portinfo *port_info, *n, *parent;
Eric Moore547f9a22006-06-27 14:42:12 -06001863 struct mptsas_phyinfo *phy_info;
1864 struct scsi_target * starget;
1865 VirtTarget * vtarget;
1866 struct sas_port * port;
Moore, Erice6b2d762006-03-14 09:14:24 -07001867 int i;
Eric Moore547f9a22006-06-27 14:42:12 -06001868 u64 expander_sas_address;
Moore, Erice6b2d762006-03-14 09:14:24 -07001869
1870 mutex_lock(&ioc->sas_topology_mutex);
1871 list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {
1872
1873 if (port_info->phy_info &&
1874 (!(port_info->phy_info[0].identify.device_info &
1875 MPI_SAS_DEVICE_INFO_SMP_TARGET)))
1876 continue;
1877
1878 if (mptsas_sas_expander_pg0(ioc, &buffer,
1879 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
1880 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) {
1881
1882 /*
Eric Moore547f9a22006-06-27 14:42:12 -06001883 * Issue target reset to all child end devices
1884 * then mark them deleted to prevent further
1885 * IO going to them.
1886 */
1887 phy_info = port_info->phy_info;
1888 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
1889 starget = mptsas_get_starget(phy_info);
1890 if (!starget)
1891 continue;
1892 vtarget = starget->hostdata;
1893 if(vtarget->deleted)
1894 continue;
1895 vtarget->deleted = 1;
1896 mptsas_target_reset(ioc, vtarget);
1897 sas_port_delete(mptsas_get_port(phy_info));
1898 mptsas_port_delete(phy_info->port_details);
1899 }
1900
1901 /*
Moore, Erice6b2d762006-03-14 09:14:24 -07001902 * Obtain the port_info instance to the parent port
1903 */
1904 parent = mptsas_find_portinfo_by_handle(ioc,
1905 port_info->phy_info[0].identify.handle_parent);
1906
1907 if (!parent)
1908 goto next_port;
1909
Eric Moore547f9a22006-06-27 14:42:12 -06001910 expander_sas_address =
1911 port_info->phy_info[0].identify.sas_address;
1912
Moore, Erice6b2d762006-03-14 09:14:24 -07001913 /*
1914 * Delete rphys in the parent that point
1915 * to this expander. The transport layer will
1916 * cleanup all the children.
1917 */
Eric Moore547f9a22006-06-27 14:42:12 -06001918 phy_info = parent->phy_info;
1919 for (i = 0; i < parent->num_phys; i++, phy_info++) {
1920 port = mptsas_get_port(phy_info);
1921 if (!port)
Moore, Erice6b2d762006-03-14 09:14:24 -07001922 continue;
Eric Moore547f9a22006-06-27 14:42:12 -06001923 if (phy_info->attached.sas_address !=
1924 expander_sas_address)
1925 continue;
1926#ifdef MPT_DEBUG_SAS_WIDE
Eric Mooredc22f162006-07-06 11:23:14 -06001927 dev_printk(KERN_DEBUG, &port->dev,
1928 "delete port (%d)\n", port->port_identifier);
Eric Moore547f9a22006-06-27 14:42:12 -06001929#endif
1930 sas_port_delete(port);
1931 mptsas_port_delete(phy_info->port_details);
Moore, Erice6b2d762006-03-14 09:14:24 -07001932 }
1933 next_port:
Eric Moore547f9a22006-06-27 14:42:12 -06001934
1935 phy_info = port_info->phy_info;
1936 for (i = 0; i < port_info->num_phys; i++, phy_info++)
1937 mptsas_port_delete(phy_info->port_details);
1938
Moore, Erice6b2d762006-03-14 09:14:24 -07001939 list_del(&port_info->list);
Eric Moore547f9a22006-06-27 14:42:12 -06001940 kfree(port_info->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001941 kfree(port_info);
1942 }
1943 /*
1944 * Free this memory allocated from inside
1945 * mptsas_sas_expander_pg0
1946 */
Eric Moore547f9a22006-06-27 14:42:12 -06001947 kfree(buffer.phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001948 }
1949 mutex_unlock(&ioc->sas_topology_mutex);
1950}
1951
1952/*
1953 * Start of day discovery
1954 */
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001955static void
1956mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
1957{
1958 u32 handle = 0xFFFF;
Moore, Ericf44e5462006-03-14 09:14:21 -07001959 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001960
Moore, Erice6b2d762006-03-14 09:14:24 -07001961 mutex_lock(&ioc->sas_discovery_mutex);
1962 mptsas_probe_hba_phys(ioc);
1963 while (!mptsas_probe_expander_phys(ioc, &handle))
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001964 ;
Moore, Ericf44e5462006-03-14 09:14:21 -07001965 /*
1966 Reporting RAID volumes.
1967 */
1968 if (!ioc->raid_data.pIocPg2)
1969 goto out;
1970 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
1971 goto out;
1972 for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
James Bottomleye8bf3942006-07-11 17:49:34 -04001973 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
Moore, Ericf44e5462006-03-14 09:14:21 -07001974 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
1975 }
1976 out:
Moore, Erice6b2d762006-03-14 09:14:24 -07001977 mutex_unlock(&ioc->sas_discovery_mutex);
1978}
1979
1980/*
1981 * Work queue thread to handle Runtime discovery
1982 * Mere purpose is the hot add/delete of expanders
Eric Moore547f9a22006-06-27 14:42:12 -06001983 *(Mutex UNLOCKED)
Moore, Erice6b2d762006-03-14 09:14:24 -07001984 */
1985static void
Eric Moore547f9a22006-06-27 14:42:12 -06001986__mptsas_discovery_work(MPT_ADAPTER *ioc)
Moore, Erice6b2d762006-03-14 09:14:24 -07001987{
Moore, Erice6b2d762006-03-14 09:14:24 -07001988 u32 handle = 0xFFFF;
1989
Moore, Erice6b2d762006-03-14 09:14:24 -07001990 ioc->sas_discovery_runtime=1;
1991 mptsas_delete_expander_phys(ioc);
1992 mptsas_probe_hba_phys(ioc);
1993 while (!mptsas_probe_expander_phys(ioc, &handle))
1994 ;
Moore, Erice6b2d762006-03-14 09:14:24 -07001995 ioc->sas_discovery_runtime=0;
Eric Moore547f9a22006-06-27 14:42:12 -06001996}
1997
1998/*
1999 * Work queue thread to handle Runtime discovery
2000 * Mere purpose is the hot add/delete of expanders
2001 *(Mutex LOCKED)
2002 */
2003static void
2004mptsas_discovery_work(void * arg)
2005{
2006 struct mptsas_discovery_event *ev = arg;
2007 MPT_ADAPTER *ioc = ev->ioc;
2008
2009 mutex_lock(&ioc->sas_discovery_mutex);
2010 __mptsas_discovery_work(ioc);
Moore, Erice6b2d762006-03-14 09:14:24 -07002011 mutex_unlock(&ioc->sas_discovery_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002012 kfree(ev);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002013}
2014
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002015static struct mptsas_phyinfo *
Eric Moore547f9a22006-06-27 14:42:12 -06002016mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002017{
2018 struct mptsas_portinfo *port_info;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002019 struct mptsas_phyinfo *phy_info = NULL;
Eric Moore547f9a22006-06-27 14:42:12 -06002020 int i;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002021
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002022 mutex_lock(&ioc->sas_topology_mutex);
2023 list_for_each_entry(port_info, &ioc->sas_topology, list) {
2024 for (i = 0; i < port_info->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -06002025 if (port_info->phy_info[i].attached.sas_address
2026 != sas_address)
2027 continue;
2028 if (!mptsas_is_end_device(
2029 &port_info->phy_info[i].attached))
2030 continue;
2031 phy_info = &port_info->phy_info[i];
2032 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002033 }
2034 }
2035 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002036 return phy_info;
2037}
2038
2039static struct mptsas_phyinfo *
Moore, Ericc73787ee2006-01-26 16:20:06 -07002040mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002041{
2042 struct mptsas_portinfo *port_info;
2043 struct mptsas_phyinfo *phy_info = NULL;
2044 int i;
2045
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002046 mutex_lock(&ioc->sas_topology_mutex);
2047 list_for_each_entry(port_info, &ioc->sas_topology, list) {
Eric Moore547f9a22006-06-27 14:42:12 -06002048 for (i = 0; i < port_info->num_phys; i++) {
2049 if (port_info->phy_info[i].attached.id != id)
2050 continue;
2051 if (!mptsas_is_end_device(
2052 &port_info->phy_info[i].attached))
2053 continue;
2054 phy_info = &port_info->phy_info[i];
2055 break;
2056 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002057 }
2058 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002059 return phy_info;
2060}
2061
Moore, Eric4b766472006-03-14 09:14:12 -07002062/*
2063 * Work queue thread to clear the persitency table
2064 */
2065static void
Eric Moore547f9a22006-06-27 14:42:12 -06002066mptsas_persist_clear_table(void * arg)
Moore, Eric4b766472006-03-14 09:14:12 -07002067{
2068 MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
2069
2070 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
2071}
2072
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002073static void
Moore, Ericf44e5462006-03-14 09:14:21 -07002074mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
2075{
2076 sdev->no_uld_attach = data ? 1 : 0;
2077 scsi_device_reprobe(sdev);
2078}
2079
2080static void
2081mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
2082{
2083 starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
2084 mptsas_reprobe_lun);
2085}
2086
Moore, Erice6b2d762006-03-14 09:14:24 -07002087/*
2088 * Work queue thread to handle SAS hotplug events
2089 */
Moore, Ericf44e5462006-03-14 09:14:21 -07002090static void
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002091mptsas_hotplug_work(void *arg)
2092{
2093 struct mptsas_hotplug_event *ev = arg;
2094 MPT_ADAPTER *ioc = ev->ioc;
2095 struct mptsas_phyinfo *phy_info;
2096 struct sas_rphy *rphy;
Eric Moore547f9a22006-06-27 14:42:12 -06002097 struct sas_port *port;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002098 struct scsi_device *sdev;
Eric Moore547f9a22006-06-27 14:42:12 -06002099 struct scsi_target * starget;
James Bottomleyf013db32006-03-18 14:54:36 -06002100 struct sas_identify identify;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002101 char *ds = NULL;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002102 struct mptsas_devinfo sas_device;
Moore, Ericf44e5462006-03-14 09:14:21 -07002103 VirtTarget *vtarget;
Eric Moore547f9a22006-06-27 14:42:12 -06002104 VirtDevice *vdevice;
2105
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002106
Moore, Erice6b2d762006-03-14 09:14:24 -07002107 mutex_lock(&ioc->sas_discovery_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002108 switch (ev->event_type) {
2109 case MPTSAS_DEL_DEVICE:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002110
Moore, Ericc73787ee2006-01-26 16:20:06 -07002111 phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
Moore, Erice6b2d762006-03-14 09:14:24 -07002112
Moore, Ericf44e5462006-03-14 09:14:21 -07002113 /*
2114 * Sanity checks, for non-existing phys and remote rphys.
2115 */
Eric Moore547f9a22006-06-27 14:42:12 -06002116 if (!phy_info || !phy_info->port_details) {
2117 dfailprintk((MYIOC_s_ERR_FMT
2118 "%s: exit at line=%d\n", ioc->name,
2119 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002120 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002121 }
2122 rphy = mptsas_get_rphy(phy_info);
2123 if (!rphy) {
2124 dfailprintk((MYIOC_s_ERR_FMT
2125 "%s: exit at line=%d\n", ioc->name,
2126 __FUNCTION__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002127 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002128 }
2129 port = mptsas_get_port(phy_info);
2130 if (!port) {
2131 dfailprintk((MYIOC_s_ERR_FMT
2132 "%s: exit at line=%d\n", ioc->name,
2133 __FUNCTION__, __LINE__));
2134 break;
2135 }
Moore, Ericf44e5462006-03-14 09:14:21 -07002136
Eric Moore547f9a22006-06-27 14:42:12 -06002137 starget = mptsas_get_starget(phy_info);
2138 if (starget) {
2139 vtarget = starget->hostdata;
2140
2141 if (!vtarget) {
2142 dfailprintk((MYIOC_s_ERR_FMT
2143 "%s: exit at line=%d\n", ioc->name,
2144 __FUNCTION__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002145 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002146 }
2147
Moore, Ericf44e5462006-03-14 09:14:21 -07002148 /*
2149 * Handling RAID components
2150 */
2151 if (ev->phys_disk_num_valid) {
2152 vtarget->target_id = ev->phys_disk_num;
2153 vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
Eric Moore547f9a22006-06-27 14:42:12 -06002154 mptsas_reprobe_target(starget, 1);
Moore, Ericf44e5462006-03-14 09:14:21 -07002155 break;
2156 }
Eric Moore547f9a22006-06-27 14:42:12 -06002157
2158 vtarget->deleted = 1;
2159 mptsas_target_reset(ioc, vtarget);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002160 }
2161
Moore, Ericc73787ee2006-01-26 16:20:06 -07002162 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
2163 ds = "ssp";
2164 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
2165 ds = "stp";
2166 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
2167 ds = "sata";
2168
2169 printk(MYIOC_s_INFO_FMT
2170 "removing %s device, channel %d, id %d, phy %d\n",
2171 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
2172
Eric Moore547f9a22006-06-27 14:42:12 -06002173#ifdef MPT_DEBUG_SAS_WIDE
Eric Mooredc22f162006-07-06 11:23:14 -06002174 dev_printk(KERN_DEBUG, &port->dev,
2175 "delete port (%d)\n", port->port_identifier);
Eric Moore547f9a22006-06-27 14:42:12 -06002176#endif
2177 sas_port_delete(port);
2178 mptsas_port_delete(phy_info->port_details);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002179 break;
2180 case MPTSAS_ADD_DEVICE:
Moore, Ericc73787ee2006-01-26 16:20:06 -07002181
Moore, Ericbd23e942006-04-17 12:43:04 -06002182 if (ev->phys_disk_num_valid)
2183 mpt_findImVolumes(ioc);
2184
Moore, Ericc73787ee2006-01-26 16:20:06 -07002185 /*
Christoph Hellwige3094442006-02-16 13:25:36 +01002186 * Refresh sas device pg0 data
Moore, Ericc73787ee2006-01-26 16:20:06 -07002187 */
Christoph Hellwige3094442006-02-16 13:25:36 +01002188 if (mptsas_sas_device_pg0(ioc, &sas_device,
2189 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
Eric Moore547f9a22006-06-27 14:42:12 -06002190 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id)) {
2191 dfailprintk((MYIOC_s_ERR_FMT
2192 "%s: exit at line=%d\n", ioc->name,
2193 __FUNCTION__, __LINE__));
Christoph Hellwige3094442006-02-16 13:25:36 +01002194 break;
Moore, Erice6b2d762006-03-14 09:14:24 -07002195 }
2196
Eric Moore547f9a22006-06-27 14:42:12 -06002197 ssleep(2);
2198 __mptsas_discovery_work(ioc);
Moore, Ericf44e5462006-03-14 09:14:21 -07002199
Eric Moore547f9a22006-06-27 14:42:12 -06002200 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
2201 sas_device.sas_address);
2202
2203 if (!phy_info || !phy_info->port_details) {
2204 dfailprintk((MYIOC_s_ERR_FMT
2205 "%s: exit at line=%d\n", ioc->name,
2206 __FUNCTION__, __LINE__));
2207 break;
2208 }
2209
2210 starget = mptsas_get_starget(phy_info);
2211 if (starget) {
2212 vtarget = starget->hostdata;
2213
2214 if (!vtarget) {
2215 dfailprintk((MYIOC_s_ERR_FMT
2216 "%s: exit at line=%d\n", ioc->name,
2217 __FUNCTION__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002218 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002219 }
Moore, Ericf44e5462006-03-14 09:14:21 -07002220 /*
2221 * Handling RAID components
2222 */
2223 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
2224 vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
2225 vtarget->target_id = ev->id;
Eric Moore547f9a22006-06-27 14:42:12 -06002226 mptsas_reprobe_target(starget, 0);
Moore, Ericf44e5462006-03-14 09:14:21 -07002227 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002228 break;
2229 }
2230
Eric Moore547f9a22006-06-27 14:42:12 -06002231 if (mptsas_get_rphy(phy_info)) {
2232 dfailprintk((MYIOC_s_ERR_FMT
2233 "%s: exit at line=%d\n", ioc->name,
2234 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002235 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002236 }
2237 port = mptsas_get_port(phy_info);
2238 if (!port) {
2239 dfailprintk((MYIOC_s_ERR_FMT
2240 "%s: exit at line=%d\n", ioc->name,
2241 __FUNCTION__, __LINE__));
2242 break;
2243 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002244
Christoph Hellwige3094442006-02-16 13:25:36 +01002245 memcpy(&phy_info->attached, &sas_device,
2246 sizeof(struct mptsas_devinfo));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002247
Moore, Ericc73787ee2006-01-26 16:20:06 -07002248 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
2249 ds = "ssp";
2250 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
2251 ds = "stp";
2252 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
2253 ds = "sata";
2254
2255 printk(MYIOC_s_INFO_FMT
2256 "attaching %s device, channel %d, id %d, phy %d\n",
2257 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
2258
James Bottomleyf013db32006-03-18 14:54:36 -06002259 mptsas_parse_device_info(&identify, &phy_info->attached);
Eric Moore547f9a22006-06-27 14:42:12 -06002260 rphy = sas_end_device_alloc(port);
2261 if (!rphy) {
2262 dfailprintk((MYIOC_s_ERR_FMT
2263 "%s: exit at line=%d\n", ioc->name,
2264 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002265 break; /* non-fatal: an rphy can be added later */
Eric Moore547f9a22006-06-27 14:42:12 -06002266 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002267
James Bottomleyf013db32006-03-18 14:54:36 -06002268 rphy->identify = identify;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002269 if (sas_rphy_add(rphy)) {
Eric Moore547f9a22006-06-27 14:42:12 -06002270 dfailprintk((MYIOC_s_ERR_FMT
2271 "%s: exit at line=%d\n", ioc->name,
2272 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002273 sas_rphy_free(rphy);
2274 break;
2275 }
Eric Moore547f9a22006-06-27 14:42:12 -06002276 mptsas_set_rphy(phy_info, rphy);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002277 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002278 case MPTSAS_ADD_RAID:
James Bottomleye8bf3942006-07-11 17:49:34 -04002279 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
2280 ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002281 if (sdev) {
2282 scsi_device_put(sdev);
2283 break;
2284 }
2285 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07002286 "attaching raid volume, channel %d, id %d\n",
James Bottomleye8bf3942006-07-11 17:49:34 -04002287 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
2288 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002289 mpt_findImVolumes(ioc);
2290 break;
2291 case MPTSAS_DEL_RAID:
James Bottomleye8bf3942006-07-11 17:49:34 -04002292 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
2293 ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002294 if (!sdev)
2295 break;
2296 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07002297 "removing raid volume, channel %d, id %d\n",
James Bottomleye8bf3942006-07-11 17:49:34 -04002298 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
Eric Moore547f9a22006-06-27 14:42:12 -06002299 vdevice = sdev->hostdata;
2300 vdevice->vtarget->deleted = 1;
2301 mptsas_target_reset(ioc, vdevice->vtarget);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002302 scsi_remove_device(sdev);
2303 scsi_device_put(sdev);
2304 mpt_findImVolumes(ioc);
2305 break;
Moore, Ericbd23e942006-04-17 12:43:04 -06002306 case MPTSAS_IGNORE_EVENT:
2307 default:
2308 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002309 }
2310
Moore, Erice6b2d762006-03-14 09:14:24 -07002311 mutex_unlock(&ioc->sas_discovery_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002312 kfree(ev);
2313
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002314}
2315
2316static void
Eric Moore547f9a22006-06-27 14:42:12 -06002317mptsas_send_sas_event(MPT_ADAPTER *ioc,
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002318 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
2319{
2320 struct mptsas_hotplug_event *ev;
2321 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
2322 __le64 sas_address;
2323
2324 if ((device_info &
2325 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
2326 MPI_SAS_DEVICE_INFO_STP_TARGET |
2327 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
2328 return;
2329
Moore, Eric4b766472006-03-14 09:14:12 -07002330 switch (sas_event_data->ReasonCode) {
2331 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
2332 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
Eric Moore547f9a22006-06-27 14:42:12 -06002333 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Eric4b766472006-03-14 09:14:12 -07002334 if (!ev) {
2335 printk(KERN_WARNING "mptsas: lost hotplug event\n");
2336 break;
2337 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002338
Moore, Eric4b766472006-03-14 09:14:12 -07002339 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
2340 ev->ioc = ioc;
2341 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
2342 ev->parent_handle =
2343 le16_to_cpu(sas_event_data->ParentDevHandle);
2344 ev->channel = sas_event_data->Bus;
2345 ev->id = sas_event_data->TargetID;
2346 ev->phy_id = sas_event_data->PhyNum;
2347 memcpy(&sas_address, &sas_event_data->SASAddress,
2348 sizeof(__le64));
2349 ev->sas_address = le64_to_cpu(sas_address);
2350 ev->device_info = device_info;
2351
2352 if (sas_event_data->ReasonCode &
2353 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
2354 ev->event_type = MPTSAS_ADD_DEVICE;
2355 else
2356 ev->event_type = MPTSAS_DEL_DEVICE;
2357 schedule_work(&ev->work);
2358 break;
2359 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
2360 /*
2361 * Persistent table is full.
2362 */
Eric Moore547f9a22006-06-27 14:42:12 -06002363 INIT_WORK(&ioc->sas_persist_task,
2364 mptsas_persist_clear_table, (void *)ioc);
2365 schedule_work(&ioc->sas_persist_task);
Moore, Eric4b766472006-03-14 09:14:12 -07002366 break;
2367 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
2368 /* TODO */
2369 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
2370 /* TODO */
2371 default:
2372 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002373 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002374}
2375
Moore, Ericc73787ee2006-01-26 16:20:06 -07002376static void
Eric Moore547f9a22006-06-27 14:42:12 -06002377mptsas_send_raid_event(MPT_ADAPTER *ioc,
Moore, Ericc73787ee2006-01-26 16:20:06 -07002378 EVENT_DATA_RAID *raid_event_data)
2379{
2380 struct mptsas_hotplug_event *ev;
Moore, Ericbd23e942006-04-17 12:43:04 -06002381 int status = le32_to_cpu(raid_event_data->SettingsStatus);
2382 int state = (status >> 8) & 0xff;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002383
2384 if (ioc->bus_type != SAS)
2385 return;
2386
Eric Moore547f9a22006-06-27 14:42:12 -06002387 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002388 if (!ev) {
2389 printk(KERN_WARNING "mptsas: lost hotplug event\n");
2390 return;
2391 }
2392
Moore, Ericc73787ee2006-01-26 16:20:06 -07002393 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
2394 ev->ioc = ioc;
2395 ev->id = raid_event_data->VolumeID;
Moore, Ericbd23e942006-04-17 12:43:04 -06002396 ev->event_type = MPTSAS_IGNORE_EVENT;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002397
2398 switch (raid_event_data->ReasonCode) {
2399 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
2400 ev->event_type = MPTSAS_ADD_DEVICE;
2401 break;
2402 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
Moore, Ericf44e5462006-03-14 09:14:21 -07002403 ioc->raid_data.isRaid = 1;
2404 ev->phys_disk_num_valid = 1;
2405 ev->phys_disk_num = raid_event_data->PhysDiskNum;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002406 ev->event_type = MPTSAS_DEL_DEVICE;
2407 break;
Moore, Ericbd23e942006-04-17 12:43:04 -06002408 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
2409 switch (state) {
2410 case MPI_PD_STATE_ONLINE:
2411 ioc->raid_data.isRaid = 1;
2412 ev->phys_disk_num_valid = 1;
2413 ev->phys_disk_num = raid_event_data->PhysDiskNum;
2414 ev->event_type = MPTSAS_ADD_DEVICE;
2415 break;
2416 case MPI_PD_STATE_MISSING:
2417 case MPI_PD_STATE_NOT_COMPATIBLE:
2418 case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
2419 case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
2420 case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
2421 ev->event_type = MPTSAS_DEL_DEVICE;
2422 break;
2423 default:
2424 break;
2425 }
2426 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002427 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
2428 ev->event_type = MPTSAS_DEL_RAID;
2429 break;
2430 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
2431 ev->event_type = MPTSAS_ADD_RAID;
2432 break;
2433 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
Moore, Ericbd23e942006-04-17 12:43:04 -06002434 switch (state) {
2435 case MPI_RAIDVOL0_STATUS_STATE_FAILED:
2436 case MPI_RAIDVOL0_STATUS_STATE_MISSING:
2437 ev->event_type = MPTSAS_DEL_RAID;
2438 break;
2439 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
2440 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
2441 ev->event_type = MPTSAS_ADD_RAID;
2442 break;
2443 default:
2444 break;
2445 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07002446 break;
2447 default:
2448 break;
2449 }
2450 schedule_work(&ev->work);
2451}
2452
Moore, Erice6b2d762006-03-14 09:14:24 -07002453static void
Eric Moore547f9a22006-06-27 14:42:12 -06002454mptsas_send_discovery_event(MPT_ADAPTER *ioc,
Moore, Erice6b2d762006-03-14 09:14:24 -07002455 EVENT_DATA_SAS_DISCOVERY *discovery_data)
2456{
2457 struct mptsas_discovery_event *ev;
2458
2459 /*
2460 * DiscoveryStatus
2461 *
2462 * This flag will be non-zero when firmware
2463 * kicks off discovery, and return to zero
2464 * once its completed.
2465 */
2466 if (discovery_data->DiscoveryStatus)
2467 return;
2468
Eric Moore547f9a22006-06-27 14:42:12 -06002469 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Erice6b2d762006-03-14 09:14:24 -07002470 if (!ev)
2471 return;
Eric Moore547f9a22006-06-27 14:42:12 -06002472 INIT_WORK(&ev->work, mptsas_discovery_work, ev);
Moore, Erice6b2d762006-03-14 09:14:24 -07002473 ev->ioc = ioc;
2474 schedule_work(&ev->work);
2475};
2476
2477
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002478static int
2479mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
2480{
Moore, Ericc73787ee2006-01-26 16:20:06 -07002481 int rc=1;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002482 u8 event = le32_to_cpu(reply->Event) & 0xFF;
2483
2484 if (!ioc->sh)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002485 goto out;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002486
Moore, Erice6b2d762006-03-14 09:14:24 -07002487 /*
2488 * sas_discovery_ignore_events
2489 *
2490 * This flag is to prevent anymore processing of
2491 * sas events once mptsas_remove function is called.
2492 */
2493 if (ioc->sas_discovery_ignore_events) {
2494 rc = mptscsih_event_process(ioc, reply);
2495 goto out;
2496 }
2497
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002498 switch (event) {
2499 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
Eric Moore547f9a22006-06-27 14:42:12 -06002500 mptsas_send_sas_event(ioc,
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002501 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002502 break;
2503 case MPI_EVENT_INTEGRATED_RAID:
Eric Moore547f9a22006-06-27 14:42:12 -06002504 mptsas_send_raid_event(ioc,
Moore, Ericc73787ee2006-01-26 16:20:06 -07002505 (EVENT_DATA_RAID *)reply->Data);
2506 break;
Moore, Eric79de2782006-01-25 18:05:15 -07002507 case MPI_EVENT_PERSISTENT_TABLE_FULL:
Eric Moore547f9a22006-06-27 14:42:12 -06002508 INIT_WORK(&ioc->sas_persist_task,
2509 mptsas_persist_clear_table,
Moore, Eric79de2782006-01-25 18:05:15 -07002510 (void *)ioc);
Eric Moore547f9a22006-06-27 14:42:12 -06002511 schedule_work(&ioc->sas_persist_task);
Moore, Eric79de2782006-01-25 18:05:15 -07002512 break;
Moore, Eric4b766472006-03-14 09:14:12 -07002513 case MPI_EVENT_SAS_DISCOVERY:
Eric Moore547f9a22006-06-27 14:42:12 -06002514 mptsas_send_discovery_event(ioc,
Moore, Erice6b2d762006-03-14 09:14:24 -07002515 (EVENT_DATA_SAS_DISCOVERY *)reply->Data);
2516 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002517 default:
Moore, Ericc73787ee2006-01-26 16:20:06 -07002518 rc = mptscsih_event_process(ioc, reply);
2519 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002520 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07002521 out:
2522
2523 return rc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002524}
2525
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002526static int
2527mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2528{
2529 struct Scsi_Host *sh;
2530 MPT_SCSI_HOST *hd;
2531 MPT_ADAPTER *ioc;
2532 unsigned long flags;
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002533 int ii;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002534 int numSGE = 0;
2535 int scale;
2536 int ioc_cap;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002537 int error=0;
2538 int r;
2539
2540 r = mpt_attach(pdev,id);
2541 if (r)
2542 return r;
2543
2544 ioc = pci_get_drvdata(pdev);
2545 ioc->DoneCtx = mptsasDoneCtx;
2546 ioc->TaskCtx = mptsasTaskCtx;
2547 ioc->InternalCtx = mptsasInternalCtx;
2548
2549 /* Added sanity check on readiness of the MPT adapter.
2550 */
2551 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
2552 printk(MYIOC_s_WARN_FMT
2553 "Skipping because it's not operational!\n",
2554 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002555 error = -ENODEV;
2556 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002557 }
2558
2559 if (!ioc->active) {
2560 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
2561 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002562 error = -ENODEV;
2563 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002564 }
2565
2566 /* Sanity check - ensure at least 1 port is INITIATOR capable
2567 */
2568 ioc_cap = 0;
2569 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
2570 if (ioc->pfacts[ii].ProtocolFlags &
2571 MPI_PORTFACTS_PROTOCOL_INITIATOR)
2572 ioc_cap++;
2573 }
2574
2575 if (!ioc_cap) {
2576 printk(MYIOC_s_WARN_FMT
2577 "Skipping ioc=%p because SCSI Initiator mode "
2578 "is NOT enabled!\n", ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -06002579 return 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002580 }
2581
2582 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
2583 if (!sh) {
2584 printk(MYIOC_s_WARN_FMT
2585 "Unable to register controller with SCSI subsystem\n",
2586 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002587 error = -1;
2588 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002589 }
2590
2591 spin_lock_irqsave(&ioc->FreeQlock, flags);
2592
2593 /* Attach the SCSI Host to the IOC structure
2594 */
2595 ioc->sh = sh;
2596
2597 sh->io_port = 0;
2598 sh->n_io_port = 0;
2599 sh->irq = 0;
2600
2601 /* set 16 byte cdb's */
2602 sh->max_cmd_len = 16;
2603
2604 sh->max_id = ioc->pfacts->MaxDevices + 1;
2605
2606 sh->transportt = mptsas_transport_template;
2607
2608 sh->max_lun = MPT_LAST_LUN + 1;
2609 sh->max_channel = 0;
2610 sh->this_id = ioc->pfacts[0].PortSCSIID;
2611
2612 /* Required entry.
2613 */
2614 sh->unique_id = ioc->id;
2615
2616 INIT_LIST_HEAD(&ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002617 mutex_init(&ioc->sas_topology_mutex);
Moore, Erice6b2d762006-03-14 09:14:24 -07002618 mutex_init(&ioc->sas_discovery_mutex);
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01002619 mutex_init(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002620 init_completion(&ioc->sas_mgmt.done);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002621
2622 /* Verify that we won't exceed the maximum
2623 * number of chain buffers
2624 * We can optimize: ZZ = req_sz/sizeof(SGE)
2625 * For 32bit SGE's:
2626 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
2627 * + (req_sz - 64)/sizeof(SGE)
2628 * A slightly different algorithm is required for
2629 * 64bit SGEs.
2630 */
2631 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
2632 if (sizeof(dma_addr_t) == sizeof(u64)) {
2633 numSGE = (scale - 1) *
2634 (ioc->facts.MaxChainDepth-1) + scale +
2635 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
2636 sizeof(u32));
2637 } else {
2638 numSGE = 1 + (scale - 1) *
2639 (ioc->facts.MaxChainDepth-1) + scale +
2640 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
2641 sizeof(u32));
2642 }
2643
2644 if (numSGE < sh->sg_tablesize) {
2645 /* Reset this value */
2646 dprintk((MYIOC_s_INFO_FMT
2647 "Resetting sg_tablesize to %d from %d\n",
2648 ioc->name, numSGE, sh->sg_tablesize));
2649 sh->sg_tablesize = numSGE;
2650 }
2651
2652 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2653
2654 hd = (MPT_SCSI_HOST *) sh->hostdata;
2655 hd->ioc = ioc;
2656
2657 /* SCSI needs scsi_cmnd lookup table!
2658 * (with size equal to req_depth*PtrSz!)
2659 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002660 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
2661 if (!hd->ScsiLookup) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002662 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002663 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002664 }
2665
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002666 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
2667 ioc->name, hd->ScsiLookup));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002668
2669 /* Allocate memory for the device structures.
2670 * A non-Null pointer at an offset
2671 * indicates a device exists.
2672 * max_id = 1 + maximum id (hosts.h)
2673 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002674 hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
2675 if (!hd->Targets) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002676 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002677 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002678 }
2679
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002680 dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002681
2682 /* Clear the TM flags
2683 */
2684 hd->tmPending = 0;
2685 hd->tmState = TM_STATE_NONE;
2686 hd->resetPending = 0;
2687 hd->abortSCpnt = NULL;
2688
2689 /* Clear the pointer used to store
2690 * single-threaded commands, i.e., those
2691 * issued during a bus scan, dv and
2692 * configuration pages.
2693 */
2694 hd->cmdPtr = NULL;
2695
2696 /* Initialize this SCSI Hosts' timers
2697 * To use, set the timer expires field
2698 * and add_timer
2699 */
2700 init_timer(&hd->timer);
2701 hd->timer.data = (unsigned long) hd;
2702 hd->timer.function = mptscsih_timer_expired;
2703
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002704 ioc->sas_data.ptClear = mpt_pt_clear;
2705
2706 if (ioc->sas_data.ptClear==1) {
2707 mptbase_sas_persist_operation(
2708 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
2709 }
2710
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002711 init_waitqueue_head(&hd->scandv_waitq);
2712 hd->scandv_wait_done = 0;
2713 hd->last_queue_full = 0;
2714
2715 error = scsi_add_host(sh, &ioc->pcidev->dev);
2716 if (error) {
2717 dprintk((KERN_ERR MYNAM
2718 "scsi_add_host failed\n"));
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002719 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002720 }
2721
2722 mptsas_scan_sas_topology(ioc);
2723
2724 return 0;
2725
Eric Moore547f9a22006-06-27 14:42:12 -06002726 out_mptsas_probe:
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002727
2728 mptscsih_remove(pdev);
2729 return error;
2730}
2731
2732static void __devexit mptsas_remove(struct pci_dev *pdev)
2733{
2734 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
2735 struct mptsas_portinfo *p, *n;
Eric Moore547f9a22006-06-27 14:42:12 -06002736 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002737
Moore, Erice6b2d762006-03-14 09:14:24 -07002738 ioc->sas_discovery_ignore_events=1;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002739 sas_remove_host(ioc->sh);
2740
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002741 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002742 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
2743 list_del(&p->list);
Eric Moore547f9a22006-06-27 14:42:12 -06002744 for (i = 0 ; i < p->num_phys ; i++)
2745 mptsas_port_delete(p->phy_info[i].port_details);
2746 kfree(p->phy_info);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002747 kfree(p);
2748 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002749 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002750
2751 mptscsih_remove(pdev);
2752}
2753
2754static struct pci_device_id mptsas_pci_table[] = {
Eric Moore87cf8982006-06-27 16:09:26 -06002755 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002756 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002757 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002758 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002759 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002760 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002761 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002762 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002763 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002764 PCI_ANY_ID, PCI_ANY_ID },
2765 {0} /* Terminating entry */
2766};
2767MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
2768
2769
2770static struct pci_driver mptsas_driver = {
2771 .name = "mptsas",
2772 .id_table = mptsas_pci_table,
2773 .probe = mptsas_probe,
2774 .remove = __devexit_p(mptsas_remove),
2775 .shutdown = mptscsih_shutdown,
2776#ifdef CONFIG_PM
2777 .suspend = mptscsih_suspend,
2778 .resume = mptscsih_resume,
2779#endif
2780};
2781
2782static int __init
2783mptsas_init(void)
2784{
2785 show_mptmod_ver(my_NAME, my_VERSION);
2786
2787 mptsas_transport_template =
2788 sas_attach_transport(&mptsas_transport_functions);
2789 if (!mptsas_transport_template)
2790 return -ENODEV;
2791
2792 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
2793 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
2794 mptsasInternalCtx =
2795 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002796 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002797
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002798 if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
Moore, Eric3a892be2006-03-14 09:14:03 -07002799 devtverboseprintk((KERN_INFO MYNAM
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002800 ": Registered for IOC event notifications\n"));
2801 }
2802
2803 if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
2804 dprintk((KERN_INFO MYNAM
2805 ": Registered for IOC reset notifications\n"));
2806 }
2807
2808 return pci_register_driver(&mptsas_driver);
2809}
2810
2811static void __exit
2812mptsas_exit(void)
2813{
2814 pci_unregister_driver(&mptsas_driver);
2815 sas_release_transport(mptsas_transport_template);
2816
2817 mpt_reset_deregister(mptsasDoneCtx);
2818 mpt_event_deregister(mptsasDoneCtx);
2819
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002820 mpt_deregister(mptsasMgmtCtx);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002821 mpt_deregister(mptsasInternalCtx);
2822 mpt_deregister(mptsasTaskCtx);
2823 mpt_deregister(mptsasDoneCtx);
2824}
2825
2826module_init(mptsas_init);
2827module_exit(mptsas_exit);