blob: b752a479f6dbb01a43cc31d5b7d62f736c9f2d84 [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
James Bottomleyf4ad7b52006-08-25 13:48:18 -0500855 /* FIXME: only have link errors on local phys */
856 if (!scsi_is_sas_phy_local(phy))
857 return -EINVAL;
858
Christoph Hellwigb5141122005-10-28 22:07:41 +0200859 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
860 hdr.ExtPageLength = 0;
861 hdr.PageNumber = 1 /* page number 1*/;
862 hdr.Reserved1 = 0;
863 hdr.Reserved2 = 0;
864 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
865 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
866
867 cfg.cfghdr.ehdr = &hdr;
868 cfg.physAddr = -1;
869 cfg.pageAddr = phy->identify.phy_identifier;
870 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
871 cfg.dir = 0; /* read */
872 cfg.timeout = 10;
873
874 error = mpt_config(ioc, &cfg);
875 if (error)
876 return error;
877 if (!hdr.ExtPageLength)
878 return -ENXIO;
879
880 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
881 &dma_handle);
882 if (!buffer)
883 return -ENOMEM;
884
885 cfg.physAddr = dma_handle;
886 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
887
888 error = mpt_config(ioc, &cfg);
889 if (error)
890 goto out_free_consistent;
891
892 mptsas_print_phy_pg1(buffer);
893
894 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
895 phy->running_disparity_error_count =
896 le32_to_cpu(buffer->RunningDisparityErrorCount);
897 phy->loss_of_dword_sync_count =
898 le32_to_cpu(buffer->LossDwordSynchCount);
899 phy->phy_reset_problem_count =
900 le32_to_cpu(buffer->PhyResetProblemCount);
901
902 out_free_consistent:
903 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
904 buffer, dma_handle);
905 return error;
906}
907
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200908static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
909 MPT_FRAME_HDR *reply)
910{
911 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
912 if (reply != NULL) {
913 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
914 memcpy(ioc->sas_mgmt.reply, reply,
915 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
916 }
917 complete(&ioc->sas_mgmt.done);
918 return 1;
919}
920
921static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
922{
923 MPT_ADAPTER *ioc = phy_to_ioc(phy);
924 SasIoUnitControlRequest_t *req;
925 SasIoUnitControlReply_t *reply;
926 MPT_FRAME_HDR *mf;
927 MPIHeader_t *hdr;
928 unsigned long timeleft;
929 int error = -ERESTARTSYS;
930
James Bottomleyf4ad7b52006-08-25 13:48:18 -0500931 /* FIXME: fusion doesn't allow non-local phy reset */
932 if (!scsi_is_sas_phy_local(phy))
933 return -EINVAL;
934
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200935 /* not implemented for expanders */
936 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
937 return -ENXIO;
938
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100939 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200940 goto out;
941
942 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
943 if (!mf) {
944 error = -ENOMEM;
945 goto out_unlock;
946 }
947
948 hdr = (MPIHeader_t *) mf;
949 req = (SasIoUnitControlRequest_t *)mf;
950 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
951 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
952 req->MsgContext = hdr->MsgContext;
953 req->Operation = hard_reset ?
954 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
955 req->PhyNum = phy->identify.phy_identifier;
956
957 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
958
959 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
960 10 * HZ);
961 if (!timeleft) {
962 /* On timeout reset the board */
963 mpt_free_msg_frame(ioc, mf);
964 mpt_HardResetHandler(ioc, CAN_SLEEP);
965 error = -ETIMEDOUT;
966 goto out_unlock;
967 }
968
969 /* a reply frame is expected */
970 if ((ioc->sas_mgmt.status &
971 MPT_IOCTL_STATUS_RF_VALID) == 0) {
972 error = -ENXIO;
973 goto out_unlock;
974 }
975
976 /* process the completed Reply Message Frame */
977 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
978 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
979 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
980 __FUNCTION__,
981 reply->IOCStatus,
982 reply->IOCLogInfo);
983 error = -ENXIO;
984 goto out_unlock;
985 }
986
987 error = 0;
988
989 out_unlock:
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100990 mutex_unlock(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200991 out:
992 return error;
993}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200994
Christoph Hellwige3094442006-02-16 13:25:36 +0100995static int
996mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
997{
998 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
999 int i, error;
1000 struct mptsas_portinfo *p;
1001 struct mptsas_enclosure enclosure_info;
1002 u64 enclosure_handle;
1003
1004 mutex_lock(&ioc->sas_topology_mutex);
1005 list_for_each_entry(p, &ioc->sas_topology, list) {
1006 for (i = 0; i < p->num_phys; i++) {
1007 if (p->phy_info[i].attached.sas_address ==
1008 rphy->identify.sas_address) {
1009 enclosure_handle = p->phy_info[i].
1010 attached.handle_enclosure;
1011 goto found_info;
1012 }
1013 }
1014 }
1015 mutex_unlock(&ioc->sas_topology_mutex);
1016 return -ENXIO;
1017
1018 found_info:
1019 mutex_unlock(&ioc->sas_topology_mutex);
1020 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
Moore, Eric52435432006-03-14 09:14:15 -07001021 error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
Christoph Hellwige3094442006-02-16 13:25:36 +01001022 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
1023 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
1024 if (!error)
1025 *identifier = enclosure_info.enclosure_logical_id;
1026 return error;
1027}
1028
1029static int
1030mptsas_get_bay_identifier(struct sas_rphy *rphy)
1031{
1032 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1033 struct mptsas_portinfo *p;
1034 int i, rc;
1035
1036 mutex_lock(&ioc->sas_topology_mutex);
1037 list_for_each_entry(p, &ioc->sas_topology, list) {
1038 for (i = 0; i < p->num_phys; i++) {
1039 if (p->phy_info[i].attached.sas_address ==
1040 rphy->identify.sas_address) {
1041 rc = p->phy_info[i].attached.slot;
1042 goto out;
1043 }
1044 }
1045 }
1046 rc = -ENXIO;
1047 out:
1048 mutex_unlock(&ioc->sas_topology_mutex);
1049 return rc;
1050}
1051
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001052static struct sas_function_template mptsas_transport_functions = {
Christoph Hellwigb5141122005-10-28 22:07:41 +02001053 .get_linkerrors = mptsas_get_linkerrors,
Christoph Hellwige3094442006-02-16 13:25:36 +01001054 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
1055 .get_bay_identifier = mptsas_get_bay_identifier,
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001056 .phy_reset = mptsas_phy_reset,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001057};
1058
1059static struct scsi_transport_template *mptsas_transport_template;
1060
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001061static int
1062mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
1063{
1064 ConfigExtendedPageHeader_t hdr;
1065 CONFIGPARMS cfg;
1066 SasIOUnitPage0_t *buffer;
1067 dma_addr_t dma_handle;
1068 int error, i;
1069
1070 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
1071 hdr.ExtPageLength = 0;
1072 hdr.PageNumber = 0;
1073 hdr.Reserved1 = 0;
1074 hdr.Reserved2 = 0;
1075 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1076 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1077
1078 cfg.cfghdr.ehdr = &hdr;
1079 cfg.physAddr = -1;
1080 cfg.pageAddr = 0;
1081 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1082 cfg.dir = 0; /* read */
1083 cfg.timeout = 10;
1084
1085 error = mpt_config(ioc, &cfg);
1086 if (error)
1087 goto out;
1088 if (!hdr.ExtPageLength) {
1089 error = -ENXIO;
1090 goto out;
1091 }
1092
1093 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1094 &dma_handle);
1095 if (!buffer) {
1096 error = -ENOMEM;
1097 goto out;
1098 }
1099
1100 cfg.physAddr = dma_handle;
1101 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1102
1103 error = mpt_config(ioc, &cfg);
1104 if (error)
1105 goto out_free_consistent;
1106
1107 port_info->num_phys = buffer->NumPhys;
1108 port_info->phy_info = kcalloc(port_info->num_phys,
Eric Moore547f9a22006-06-27 14:42:12 -06001109 sizeof(*port_info->phy_info),GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001110 if (!port_info->phy_info) {
1111 error = -ENOMEM;
1112 goto out_free_consistent;
1113 }
1114
Moore, Ericdb9c9172006-03-14 09:14:18 -07001115 if (port_info->num_phys)
1116 port_info->handle =
1117 le16_to_cpu(buffer->PhyData[0].ControllerDevHandle);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001118 for (i = 0; i < port_info->num_phys; i++) {
1119 mptsas_print_phy_data(&buffer->PhyData[i]);
1120 port_info->phy_info[i].phy_id = i;
1121 port_info->phy_info[i].port_id =
1122 buffer->PhyData[i].Port;
1123 port_info->phy_info[i].negotiated_link_rate =
1124 buffer->PhyData[i].NegotiatedLinkRate;
Eric Moore547f9a22006-06-27 14:42:12 -06001125 port_info->phy_info[i].portinfo = port_info;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001126 }
1127
1128 out_free_consistent:
1129 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1130 buffer, dma_handle);
1131 out:
1132 return error;
1133}
1134
1135static int
1136mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1137 u32 form, u32 form_specific)
1138{
1139 ConfigExtendedPageHeader_t hdr;
1140 CONFIGPARMS cfg;
1141 SasPhyPage0_t *buffer;
1142 dma_addr_t dma_handle;
1143 int error;
1144
1145 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
1146 hdr.ExtPageLength = 0;
1147 hdr.PageNumber = 0;
1148 hdr.Reserved1 = 0;
1149 hdr.Reserved2 = 0;
1150 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1151 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
1152
1153 cfg.cfghdr.ehdr = &hdr;
1154 cfg.dir = 0; /* read */
1155 cfg.timeout = 10;
1156
1157 /* Get Phy Pg 0 for each Phy. */
1158 cfg.physAddr = -1;
1159 cfg.pageAddr = form + form_specific;
1160 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1161
1162 error = mpt_config(ioc, &cfg);
1163 if (error)
1164 goto out;
1165
1166 if (!hdr.ExtPageLength) {
1167 error = -ENXIO;
1168 goto out;
1169 }
1170
1171 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1172 &dma_handle);
1173 if (!buffer) {
1174 error = -ENOMEM;
1175 goto out;
1176 }
1177
1178 cfg.physAddr = dma_handle;
1179 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1180
1181 error = mpt_config(ioc, &cfg);
1182 if (error)
1183 goto out_free_consistent;
1184
1185 mptsas_print_phy_pg0(buffer);
1186
1187 phy_info->hw_link_rate = buffer->HwLinkRate;
1188 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1189 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1190 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1191
1192 out_free_consistent:
1193 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1194 buffer, dma_handle);
1195 out:
1196 return error;
1197}
1198
1199static int
1200mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
1201 u32 form, u32 form_specific)
1202{
1203 ConfigExtendedPageHeader_t hdr;
1204 CONFIGPARMS cfg;
1205 SasDevicePage0_t *buffer;
1206 dma_addr_t dma_handle;
1207 __le64 sas_address;
Moore, Ericbd23e942006-04-17 12:43:04 -06001208 int error=0;
1209
1210 if (ioc->sas_discovery_runtime &&
1211 mptsas_is_end_device(device_info))
1212 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001213
1214 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
1215 hdr.ExtPageLength = 0;
1216 hdr.PageNumber = 0;
1217 hdr.Reserved1 = 0;
1218 hdr.Reserved2 = 0;
1219 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1220 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1221
1222 cfg.cfghdr.ehdr = &hdr;
1223 cfg.pageAddr = form + form_specific;
1224 cfg.physAddr = -1;
1225 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1226 cfg.dir = 0; /* read */
1227 cfg.timeout = 10;
1228
Moore, Ericdb9c9172006-03-14 09:14:18 -07001229 memset(device_info, 0, sizeof(struct mptsas_devinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001230 error = mpt_config(ioc, &cfg);
1231 if (error)
1232 goto out;
1233 if (!hdr.ExtPageLength) {
1234 error = -ENXIO;
1235 goto out;
1236 }
1237
1238 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1239 &dma_handle);
1240 if (!buffer) {
1241 error = -ENOMEM;
1242 goto out;
1243 }
1244
1245 cfg.physAddr = dma_handle;
1246 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1247
1248 error = mpt_config(ioc, &cfg);
1249 if (error)
1250 goto out_free_consistent;
1251
1252 mptsas_print_device_pg0(buffer);
1253
1254 device_info->handle = le16_to_cpu(buffer->DevHandle);
Moore, Ericc73787ee2006-01-26 16:20:06 -07001255 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
Christoph Hellwige3094442006-02-16 13:25:36 +01001256 device_info->handle_enclosure =
1257 le16_to_cpu(buffer->EnclosureHandle);
1258 device_info->slot = le16_to_cpu(buffer->Slot);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001259 device_info->phy_id = buffer->PhyNum;
1260 device_info->port_id = buffer->PhysicalPort;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001261 device_info->id = buffer->TargetID;
1262 device_info->channel = buffer->Bus;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001263 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
1264 device_info->sas_address = le64_to_cpu(sas_address);
1265 device_info->device_info =
1266 le32_to_cpu(buffer->DeviceInfo);
1267
1268 out_free_consistent:
1269 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1270 buffer, dma_handle);
1271 out:
1272 return error;
1273}
1274
1275static int
1276mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
1277 u32 form, u32 form_specific)
1278{
1279 ConfigExtendedPageHeader_t hdr;
1280 CONFIGPARMS cfg;
1281 SasExpanderPage0_t *buffer;
1282 dma_addr_t dma_handle;
Eric Moore547f9a22006-06-27 14:42:12 -06001283 int i, error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001284
1285 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1286 hdr.ExtPageLength = 0;
1287 hdr.PageNumber = 0;
1288 hdr.Reserved1 = 0;
1289 hdr.Reserved2 = 0;
1290 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1291 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1292
1293 cfg.cfghdr.ehdr = &hdr;
1294 cfg.physAddr = -1;
1295 cfg.pageAddr = form + form_specific;
1296 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1297 cfg.dir = 0; /* read */
1298 cfg.timeout = 10;
1299
Moore, Ericdb9c9172006-03-14 09:14:18 -07001300 memset(port_info, 0, sizeof(struct mptsas_portinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001301 error = mpt_config(ioc, &cfg);
1302 if (error)
1303 goto out;
1304
1305 if (!hdr.ExtPageLength) {
1306 error = -ENXIO;
1307 goto out;
1308 }
1309
1310 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1311 &dma_handle);
1312 if (!buffer) {
1313 error = -ENOMEM;
1314 goto out;
1315 }
1316
1317 cfg.physAddr = dma_handle;
1318 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1319
1320 error = mpt_config(ioc, &cfg);
1321 if (error)
1322 goto out_free_consistent;
1323
1324 /* save config data */
1325 port_info->num_phys = buffer->NumPhys;
1326 port_info->handle = le16_to_cpu(buffer->DevHandle);
1327 port_info->phy_info = kcalloc(port_info->num_phys,
Eric Moore547f9a22006-06-27 14:42:12 -06001328 sizeof(*port_info->phy_info),GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001329 if (!port_info->phy_info) {
1330 error = -ENOMEM;
1331 goto out_free_consistent;
1332 }
1333
Eric Moore547f9a22006-06-27 14:42:12 -06001334 for (i = 0; i < port_info->num_phys; i++)
1335 port_info->phy_info[i].portinfo = port_info;
1336
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001337 out_free_consistent:
1338 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1339 buffer, dma_handle);
1340 out:
1341 return error;
1342}
1343
1344static int
1345mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1346 u32 form, u32 form_specific)
1347{
1348 ConfigExtendedPageHeader_t hdr;
1349 CONFIGPARMS cfg;
1350 SasExpanderPage1_t *buffer;
1351 dma_addr_t dma_handle;
Moore, Ericbd23e942006-04-17 12:43:04 -06001352 int error=0;
1353
1354 if (ioc->sas_discovery_runtime &&
1355 mptsas_is_end_device(&phy_info->attached))
1356 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001357
1358 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1359 hdr.ExtPageLength = 0;
1360 hdr.PageNumber = 1;
1361 hdr.Reserved1 = 0;
1362 hdr.Reserved2 = 0;
1363 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1364 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1365
1366 cfg.cfghdr.ehdr = &hdr;
1367 cfg.physAddr = -1;
1368 cfg.pageAddr = form + form_specific;
1369 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1370 cfg.dir = 0; /* read */
1371 cfg.timeout = 10;
1372
1373 error = mpt_config(ioc, &cfg);
1374 if (error)
1375 goto out;
1376
1377 if (!hdr.ExtPageLength) {
1378 error = -ENXIO;
1379 goto out;
1380 }
1381
1382 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1383 &dma_handle);
1384 if (!buffer) {
1385 error = -ENOMEM;
1386 goto out;
1387 }
1388
1389 cfg.physAddr = dma_handle;
1390 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1391
1392 error = mpt_config(ioc, &cfg);
1393 if (error)
1394 goto out_free_consistent;
1395
1396
1397 mptsas_print_expander_pg1(buffer);
1398
1399 /* save config data */
Eric Moore024358e2005-10-21 20:56:36 +02001400 phy_info->phy_id = buffer->PhyIdentifier;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001401 phy_info->port_id = buffer->PhysicalPort;
1402 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
1403 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1404 phy_info->hw_link_rate = buffer->HwLinkRate;
1405 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1406 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1407
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001408 out_free_consistent:
1409 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1410 buffer, dma_handle);
1411 out:
1412 return error;
1413}
1414
1415static void
1416mptsas_parse_device_info(struct sas_identify *identify,
1417 struct mptsas_devinfo *device_info)
1418{
1419 u16 protocols;
1420
1421 identify->sas_address = device_info->sas_address;
1422 identify->phy_identifier = device_info->phy_id;
1423
1424 /*
1425 * Fill in Phy Initiator Port Protocol.
1426 * Bits 6:3, more than one bit can be set, fall through cases.
1427 */
1428 protocols = device_info->device_info & 0x78;
1429 identify->initiator_port_protocols = 0;
1430 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
1431 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
1432 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1433 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
1434 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
1435 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
1436 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
1437 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
1438
1439 /*
1440 * Fill in Phy Target Port Protocol.
1441 * Bits 10:7, more than one bit can be set, fall through cases.
1442 */
1443 protocols = device_info->device_info & 0x780;
1444 identify->target_port_protocols = 0;
1445 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1446 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
1447 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
1448 identify->target_port_protocols |= SAS_PROTOCOL_STP;
1449 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
1450 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
1451 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1452 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
1453
1454 /*
1455 * Fill in Attached device type.
1456 */
1457 switch (device_info->device_info &
1458 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
1459 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
1460 identify->device_type = SAS_PHY_UNUSED;
1461 break;
1462 case MPI_SAS_DEVICE_INFO_END_DEVICE:
1463 identify->device_type = SAS_END_DEVICE;
1464 break;
1465 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
1466 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
1467 break;
1468 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
1469 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
1470 break;
1471 }
1472}
1473
1474static int mptsas_probe_one_phy(struct device *dev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001475 struct mptsas_phyinfo *phy_info, int index, int local)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001476{
Moore, Erice6b2d762006-03-14 09:14:24 -07001477 MPT_ADAPTER *ioc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001478 struct sas_phy *phy;
Eric Moore547f9a22006-06-27 14:42:12 -06001479 struct sas_port *port;
1480 int error = 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001481
Eric Moore547f9a22006-06-27 14:42:12 -06001482 if (!dev) {
1483 error = -ENODEV;
1484 goto out;
1485 }
Moore, Erice6b2d762006-03-14 09:14:24 -07001486
1487 if (!phy_info->phy) {
1488 phy = sas_phy_alloc(dev, index);
Eric Moore547f9a22006-06-27 14:42:12 -06001489 if (!phy) {
1490 error = -ENOMEM;
1491 goto out;
1492 }
Moore, Erice6b2d762006-03-14 09:14:24 -07001493 } else
1494 phy = phy_info->phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001495
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001496 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001497
1498 /*
1499 * Set Negotiated link rate.
1500 */
1501 switch (phy_info->negotiated_link_rate) {
1502 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001503 phy->negotiated_linkrate = SAS_PHY_DISABLED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001504 break;
1505 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001506 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001507 break;
1508 case MPI_SAS_IOUNIT0_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001509 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001510 break;
1511 case MPI_SAS_IOUNIT0_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001512 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001513 break;
1514 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
1515 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
1516 default:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001517 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001518 break;
1519 }
1520
1521 /*
1522 * Set Max hardware link rate.
1523 */
1524 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1525 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001526 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001527 break;
1528 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001529 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001530 break;
1531 default:
1532 break;
1533 }
1534
1535 /*
1536 * Set Max programmed link rate.
1537 */
1538 switch (phy_info->programmed_link_rate &
1539 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1540 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001541 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001542 break;
1543 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001544 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001545 break;
1546 default:
1547 break;
1548 }
1549
1550 /*
1551 * Set Min hardware link rate.
1552 */
1553 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
1554 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001555 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001556 break;
1557 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001558 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001559 break;
1560 default:
1561 break;
1562 }
1563
1564 /*
1565 * Set Min programmed link rate.
1566 */
1567 switch (phy_info->programmed_link_rate &
1568 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
1569 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001570 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001571 break;
1572 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001573 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001574 break;
1575 default:
1576 break;
1577 }
1578
Moore, Erice6b2d762006-03-14 09:14:24 -07001579 if (!phy_info->phy) {
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001580
Moore, Erice6b2d762006-03-14 09:14:24 -07001581 error = sas_phy_add(phy);
1582 if (error) {
1583 sas_phy_free(phy);
Eric Moore547f9a22006-06-27 14:42:12 -06001584 goto out;
Moore, Erice6b2d762006-03-14 09:14:24 -07001585 }
1586 phy_info->phy = phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001587 }
1588
Eric Moore547f9a22006-06-27 14:42:12 -06001589 if (!phy_info->attached.handle ||
1590 !phy_info->port_details)
1591 goto out;
1592
1593 port = mptsas_get_port(phy_info);
1594 ioc = phy_to_ioc(phy_info->phy);
1595
1596 if (phy_info->sas_port_add_phy) {
1597
1598 if (!port) {
Eric Mooredc22f162006-07-06 11:23:14 -06001599 port = sas_port_alloc_num(dev);
Eric Moore547f9a22006-06-27 14:42:12 -06001600 if (!port) {
1601 error = -ENOMEM;
1602 goto out;
1603 }
1604 error = sas_port_add(port);
1605 if (error) {
1606 dfailprintk((MYIOC_s_ERR_FMT
1607 "%s: exit at line=%d\n", ioc->name,
1608 __FUNCTION__, __LINE__));
1609 goto out;
1610 }
1611 mptsas_set_port(phy_info, port);
Eric Mooredc22f162006-07-06 11:23:14 -06001612 dsaswideprintk((KERN_DEBUG
1613 "sas_port_alloc: port=%p dev=%p port_id=%d\n",
1614 port, dev, port->port_identifier));
Eric Moore547f9a22006-06-27 14:42:12 -06001615 }
1616 dsaswideprintk((KERN_DEBUG "sas_port_add_phy: phy_id=%d\n",
1617 phy_info->phy_id));
1618 sas_port_add_phy(port, phy_info->phy);
1619 phy_info->sas_port_add_phy = 0;
1620 }
1621
1622 if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
Moore, Erice6b2d762006-03-14 09:14:24 -07001623
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001624 struct sas_rphy *rphy;
James Bottomley2686de22006-06-30 12:54:02 -05001625 struct device *parent;
James Bottomleyf013db32006-03-18 14:54:36 -06001626 struct sas_identify identify;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001627
James Bottomley2686de22006-06-30 12:54:02 -05001628 parent = dev->parent->parent;
Moore, Erice6b2d762006-03-14 09:14:24 -07001629 /*
1630 * Let the hotplug_work thread handle processing
1631 * the adding/removing of devices that occur
1632 * after start of day.
1633 */
1634 if (ioc->sas_discovery_runtime &&
1635 mptsas_is_end_device(&phy_info->attached))
Eric Moore547f9a22006-06-27 14:42:12 -06001636 goto out;
Moore, Erice6b2d762006-03-14 09:14:24 -07001637
James Bottomleyf013db32006-03-18 14:54:36 -06001638 mptsas_parse_device_info(&identify, &phy_info->attached);
James Bottomley2686de22006-06-30 12:54:02 -05001639 if (scsi_is_host_device(parent)) {
1640 struct mptsas_portinfo *port_info;
1641 int i;
1642
1643 mutex_lock(&ioc->sas_topology_mutex);
1644 port_info = mptsas_find_portinfo_by_handle(ioc,
1645 ioc->handle);
1646 mutex_unlock(&ioc->sas_topology_mutex);
1647
1648 for (i = 0; i < port_info->num_phys; i++)
1649 if (port_info->phy_info[i].identify.sas_address ==
James Bottomley0c269e62006-07-12 09:51:04 -04001650 identify.sas_address) {
1651 sas_port_mark_backlink(port);
James Bottomley2686de22006-06-30 12:54:02 -05001652 goto out;
James Bottomley0c269e62006-07-12 09:51:04 -04001653 }
James Bottomley2686de22006-06-30 12:54:02 -05001654
1655 } else if (scsi_is_sas_rphy(parent)) {
1656 struct sas_rphy *parent_rphy = dev_to_rphy(parent);
1657 if (identify.sas_address ==
James Bottomley0c269e62006-07-12 09:51:04 -04001658 parent_rphy->identify.sas_address) {
1659 sas_port_mark_backlink(port);
James Bottomley2686de22006-06-30 12:54:02 -05001660 goto out;
James Bottomley0c269e62006-07-12 09:51:04 -04001661 }
James Bottomley2686de22006-06-30 12:54:02 -05001662 }
1663
James Bottomleyf013db32006-03-18 14:54:36 -06001664 switch (identify.device_type) {
1665 case SAS_END_DEVICE:
Eric Moore547f9a22006-06-27 14:42:12 -06001666 rphy = sas_end_device_alloc(port);
James Bottomleyf013db32006-03-18 14:54:36 -06001667 break;
1668 case SAS_EDGE_EXPANDER_DEVICE:
1669 case SAS_FANOUT_EXPANDER_DEVICE:
Eric Moore547f9a22006-06-27 14:42:12 -06001670 rphy = sas_expander_alloc(port, identify.device_type);
James Bottomleyf013db32006-03-18 14:54:36 -06001671 break;
1672 default:
1673 rphy = NULL;
1674 break;
1675 }
Eric Moore547f9a22006-06-27 14:42:12 -06001676 if (!rphy) {
1677 dfailprintk((MYIOC_s_ERR_FMT
1678 "%s: exit at line=%d\n", ioc->name,
1679 __FUNCTION__, __LINE__));
1680 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001681 }
1682
Eric Moore547f9a22006-06-27 14:42:12 -06001683 rphy->identify = identify;
1684 error = sas_rphy_add(rphy);
1685 if (error) {
1686 dfailprintk((MYIOC_s_ERR_FMT
1687 "%s: exit at line=%d\n", ioc->name,
1688 __FUNCTION__, __LINE__));
1689 sas_rphy_free(rphy);
1690 goto out;
1691 }
1692 mptsas_set_rphy(phy_info, rphy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001693 }
1694
Eric Moore547f9a22006-06-27 14:42:12 -06001695 out:
1696 return error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001697}
1698
1699static int
Moore, Erice6b2d762006-03-14 09:14:24 -07001700mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001701{
Moore, Erice6b2d762006-03-14 09:14:24 -07001702 struct mptsas_portinfo *port_info, *hba;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001703 u32 handle = 0xFFFF;
1704 int error = -ENOMEM, i;
1705
Moore, Erice6b2d762006-03-14 09:14:24 -07001706 hba = kzalloc(sizeof(*port_info), GFP_KERNEL);
1707 if (! hba)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001708 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001709
Moore, Erice6b2d762006-03-14 09:14:24 -07001710 error = mptsas_sas_io_unit_pg0(ioc, hba);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001711 if (error)
1712 goto out_free_port_info;
1713
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001714 mutex_lock(&ioc->sas_topology_mutex);
James Bottomley2686de22006-06-30 12:54:02 -05001715 ioc->handle = hba->handle;
Moore, Erice6b2d762006-03-14 09:14:24 -07001716 port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle);
1717 if (!port_info) {
1718 port_info = hba;
1719 list_add_tail(&port_info->list, &ioc->sas_topology);
1720 } else {
1721 port_info->handle = hba->handle;
1722 for (i = 0; i < hba->num_phys; i++)
1723 port_info->phy_info[i].negotiated_link_rate =
1724 hba->phy_info[i].negotiated_link_rate;
Eric Moore547f9a22006-06-27 14:42:12 -06001725 kfree(hba->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001726 kfree(hba);
1727 hba = NULL;
1728 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001729 mutex_unlock(&ioc->sas_topology_mutex);
1730
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001731 for (i = 0; i < port_info->num_phys; i++) {
1732 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
1733 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
1734 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
1735
1736 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
1737 (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
1738 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
Eric Moore024358e2005-10-21 20:56:36 +02001739 port_info->phy_info[i].identify.phy_id =
1740 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001741 handle = port_info->phy_info[i].identify.handle;
1742
Eric Moore547f9a22006-06-27 14:42:12 -06001743 if (port_info->phy_info[i].attached.handle)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001744 mptsas_sas_device_pg0(ioc,
1745 &port_info->phy_info[i].attached,
1746 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1747 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1748 port_info->phy_info[i].attached.handle);
Eric Moore547f9a22006-06-27 14:42:12 -06001749 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001750
Eric Moore547f9a22006-06-27 14:42:12 -06001751 mptsas_setup_wide_ports(ioc, port_info);
1752
1753 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001754 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
Moore, Erice6b2d762006-03-14 09:14:24 -07001755 &port_info->phy_info[i], ioc->sas_index, 1);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001756
1757 return 0;
1758
1759 out_free_port_info:
Eric Moore547f9a22006-06-27 14:42:12 -06001760 kfree(hba);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001761 out:
1762 return error;
1763}
1764
1765static int
Moore, Erice6b2d762006-03-14 09:14:24 -07001766mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001767{
Moore, Erice6b2d762006-03-14 09:14:24 -07001768 struct mptsas_portinfo *port_info, *p, *ex;
Eric Moore547f9a22006-06-27 14:42:12 -06001769 struct device *parent;
1770 struct sas_rphy *rphy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001771 int error = -ENOMEM, i, j;
1772
Moore, Erice6b2d762006-03-14 09:14:24 -07001773 ex = kzalloc(sizeof(*port_info), GFP_KERNEL);
1774 if (!ex)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001775 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001776
Moore, Erice6b2d762006-03-14 09:14:24 -07001777 error = mptsas_sas_expander_pg0(ioc, ex,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001778 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
1779 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
1780 if (error)
1781 goto out_free_port_info;
1782
Moore, Erice6b2d762006-03-14 09:14:24 -07001783 *handle = ex->handle;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001784
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001785 mutex_lock(&ioc->sas_topology_mutex);
Moore, Erice6b2d762006-03-14 09:14:24 -07001786 port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
1787 if (!port_info) {
1788 port_info = ex;
1789 list_add_tail(&port_info->list, &ioc->sas_topology);
1790 } else {
1791 port_info->handle = ex->handle;
Eric Moore547f9a22006-06-27 14:42:12 -06001792 kfree(ex->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001793 kfree(ex);
1794 ex = NULL;
1795 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001796 mutex_unlock(&ioc->sas_topology_mutex);
1797
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001798 for (i = 0; i < port_info->num_phys; i++) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001799 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
1800 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
1801 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
1802
1803 if (port_info->phy_info[i].identify.handle) {
1804 mptsas_sas_device_pg0(ioc,
1805 &port_info->phy_info[i].identify,
1806 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1807 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1808 port_info->phy_info[i].identify.handle);
Eric Moore024358e2005-10-21 20:56:36 +02001809 port_info->phy_info[i].identify.phy_id =
1810 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001811 }
1812
1813 if (port_info->phy_info[i].attached.handle) {
1814 mptsas_sas_device_pg0(ioc,
1815 &port_info->phy_info[i].attached,
1816 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1817 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1818 port_info->phy_info[i].attached.handle);
Moore, Ericdb9c9172006-03-14 09:14:18 -07001819 port_info->phy_info[i].attached.phy_id =
1820 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001821 }
Eric Moore547f9a22006-06-27 14:42:12 -06001822 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001823
Eric Moore547f9a22006-06-27 14:42:12 -06001824 parent = &ioc->sh->shost_gendev;
1825 for (i = 0; i < port_info->num_phys; i++) {
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001826 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001827 list_for_each_entry(p, &ioc->sas_topology, list) {
1828 for (j = 0; j < p->num_phys; j++) {
Eric Moore547f9a22006-06-27 14:42:12 -06001829 if (port_info->phy_info[i].identify.handle !=
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001830 p->phy_info[j].attached.handle)
Eric Moore547f9a22006-06-27 14:42:12 -06001831 continue;
1832 rphy = mptsas_get_rphy(&p->phy_info[j]);
1833 parent = &rphy->dev;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001834 }
1835 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001836 mutex_unlock(&ioc->sas_topology_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06001837 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001838
Eric Moore547f9a22006-06-27 14:42:12 -06001839 mptsas_setup_wide_ports(ioc, port_info);
1840
1841 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001842 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
Moore, Erice6b2d762006-03-14 09:14:24 -07001843 ioc->sas_index, 0);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001844
1845 return 0;
1846
1847 out_free_port_info:
Moore, Erice6b2d762006-03-14 09:14:24 -07001848 if (ex) {
Eric Moore547f9a22006-06-27 14:42:12 -06001849 kfree(ex->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001850 kfree(ex);
1851 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001852 out:
1853 return error;
1854}
1855
Moore, Erice6b2d762006-03-14 09:14:24 -07001856/*
1857 * mptsas_delete_expander_phys
1858 *
1859 *
1860 * This will traverse topology, and remove expanders
1861 * that are no longer present
1862 */
1863static void
1864mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
1865{
1866 struct mptsas_portinfo buffer;
1867 struct mptsas_portinfo *port_info, *n, *parent;
Eric Moore547f9a22006-06-27 14:42:12 -06001868 struct mptsas_phyinfo *phy_info;
1869 struct scsi_target * starget;
1870 VirtTarget * vtarget;
1871 struct sas_port * port;
Moore, Erice6b2d762006-03-14 09:14:24 -07001872 int i;
Eric Moore547f9a22006-06-27 14:42:12 -06001873 u64 expander_sas_address;
Moore, Erice6b2d762006-03-14 09:14:24 -07001874
1875 mutex_lock(&ioc->sas_topology_mutex);
1876 list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {
1877
1878 if (port_info->phy_info &&
1879 (!(port_info->phy_info[0].identify.device_info &
1880 MPI_SAS_DEVICE_INFO_SMP_TARGET)))
1881 continue;
1882
1883 if (mptsas_sas_expander_pg0(ioc, &buffer,
1884 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
1885 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) {
1886
1887 /*
Eric Moore547f9a22006-06-27 14:42:12 -06001888 * Issue target reset to all child end devices
1889 * then mark them deleted to prevent further
1890 * IO going to them.
1891 */
1892 phy_info = port_info->phy_info;
1893 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
1894 starget = mptsas_get_starget(phy_info);
1895 if (!starget)
1896 continue;
1897 vtarget = starget->hostdata;
1898 if(vtarget->deleted)
1899 continue;
1900 vtarget->deleted = 1;
1901 mptsas_target_reset(ioc, vtarget);
1902 sas_port_delete(mptsas_get_port(phy_info));
1903 mptsas_port_delete(phy_info->port_details);
1904 }
1905
1906 /*
Moore, Erice6b2d762006-03-14 09:14:24 -07001907 * Obtain the port_info instance to the parent port
1908 */
1909 parent = mptsas_find_portinfo_by_handle(ioc,
1910 port_info->phy_info[0].identify.handle_parent);
1911
1912 if (!parent)
1913 goto next_port;
1914
Eric Moore547f9a22006-06-27 14:42:12 -06001915 expander_sas_address =
1916 port_info->phy_info[0].identify.sas_address;
1917
Moore, Erice6b2d762006-03-14 09:14:24 -07001918 /*
1919 * Delete rphys in the parent that point
1920 * to this expander. The transport layer will
1921 * cleanup all the children.
1922 */
Eric Moore547f9a22006-06-27 14:42:12 -06001923 phy_info = parent->phy_info;
1924 for (i = 0; i < parent->num_phys; i++, phy_info++) {
1925 port = mptsas_get_port(phy_info);
1926 if (!port)
Moore, Erice6b2d762006-03-14 09:14:24 -07001927 continue;
Eric Moore547f9a22006-06-27 14:42:12 -06001928 if (phy_info->attached.sas_address !=
1929 expander_sas_address)
1930 continue;
1931#ifdef MPT_DEBUG_SAS_WIDE
Eric Mooredc22f162006-07-06 11:23:14 -06001932 dev_printk(KERN_DEBUG, &port->dev,
1933 "delete port (%d)\n", port->port_identifier);
Eric Moore547f9a22006-06-27 14:42:12 -06001934#endif
1935 sas_port_delete(port);
1936 mptsas_port_delete(phy_info->port_details);
Moore, Erice6b2d762006-03-14 09:14:24 -07001937 }
1938 next_port:
Eric Moore547f9a22006-06-27 14:42:12 -06001939
1940 phy_info = port_info->phy_info;
1941 for (i = 0; i < port_info->num_phys; i++, phy_info++)
1942 mptsas_port_delete(phy_info->port_details);
1943
Moore, Erice6b2d762006-03-14 09:14:24 -07001944 list_del(&port_info->list);
Eric Moore547f9a22006-06-27 14:42:12 -06001945 kfree(port_info->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001946 kfree(port_info);
1947 }
1948 /*
1949 * Free this memory allocated from inside
1950 * mptsas_sas_expander_pg0
1951 */
Eric Moore547f9a22006-06-27 14:42:12 -06001952 kfree(buffer.phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001953 }
1954 mutex_unlock(&ioc->sas_topology_mutex);
1955}
1956
1957/*
1958 * Start of day discovery
1959 */
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001960static void
1961mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
1962{
1963 u32 handle = 0xFFFF;
Moore, Ericf44e5462006-03-14 09:14:21 -07001964 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001965
Moore, Erice6b2d762006-03-14 09:14:24 -07001966 mutex_lock(&ioc->sas_discovery_mutex);
1967 mptsas_probe_hba_phys(ioc);
1968 while (!mptsas_probe_expander_phys(ioc, &handle))
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001969 ;
Moore, Ericf44e5462006-03-14 09:14:21 -07001970 /*
1971 Reporting RAID volumes.
1972 */
1973 if (!ioc->raid_data.pIocPg2)
1974 goto out;
1975 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
1976 goto out;
1977 for (i=0; i<ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
James Bottomleye8bf3942006-07-11 17:49:34 -04001978 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
Moore, Ericf44e5462006-03-14 09:14:21 -07001979 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
1980 }
1981 out:
Moore, Erice6b2d762006-03-14 09:14:24 -07001982 mutex_unlock(&ioc->sas_discovery_mutex);
1983}
1984
1985/*
1986 * Work queue thread to handle Runtime discovery
1987 * Mere purpose is the hot add/delete of expanders
Eric Moore547f9a22006-06-27 14:42:12 -06001988 *(Mutex UNLOCKED)
Moore, Erice6b2d762006-03-14 09:14:24 -07001989 */
1990static void
Eric Moore547f9a22006-06-27 14:42:12 -06001991__mptsas_discovery_work(MPT_ADAPTER *ioc)
Moore, Erice6b2d762006-03-14 09:14:24 -07001992{
Moore, Erice6b2d762006-03-14 09:14:24 -07001993 u32 handle = 0xFFFF;
1994
Moore, Erice6b2d762006-03-14 09:14:24 -07001995 ioc->sas_discovery_runtime=1;
1996 mptsas_delete_expander_phys(ioc);
1997 mptsas_probe_hba_phys(ioc);
1998 while (!mptsas_probe_expander_phys(ioc, &handle))
1999 ;
Moore, Erice6b2d762006-03-14 09:14:24 -07002000 ioc->sas_discovery_runtime=0;
Eric Moore547f9a22006-06-27 14:42:12 -06002001}
2002
2003/*
2004 * Work queue thread to handle Runtime discovery
2005 * Mere purpose is the hot add/delete of expanders
2006 *(Mutex LOCKED)
2007 */
2008static void
2009mptsas_discovery_work(void * arg)
2010{
2011 struct mptsas_discovery_event *ev = arg;
2012 MPT_ADAPTER *ioc = ev->ioc;
2013
2014 mutex_lock(&ioc->sas_discovery_mutex);
2015 __mptsas_discovery_work(ioc);
Moore, Erice6b2d762006-03-14 09:14:24 -07002016 mutex_unlock(&ioc->sas_discovery_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002017 kfree(ev);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002018}
2019
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002020static struct mptsas_phyinfo *
Eric Moore547f9a22006-06-27 14:42:12 -06002021mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002022{
2023 struct mptsas_portinfo *port_info;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002024 struct mptsas_phyinfo *phy_info = NULL;
Eric Moore547f9a22006-06-27 14:42:12 -06002025 int i;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002026
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002027 mutex_lock(&ioc->sas_topology_mutex);
2028 list_for_each_entry(port_info, &ioc->sas_topology, list) {
2029 for (i = 0; i < port_info->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -06002030 if (port_info->phy_info[i].attached.sas_address
2031 != sas_address)
2032 continue;
2033 if (!mptsas_is_end_device(
2034 &port_info->phy_info[i].attached))
2035 continue;
2036 phy_info = &port_info->phy_info[i];
2037 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002038 }
2039 }
2040 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002041 return phy_info;
2042}
2043
2044static struct mptsas_phyinfo *
Moore, Ericc73787ee2006-01-26 16:20:06 -07002045mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002046{
2047 struct mptsas_portinfo *port_info;
2048 struct mptsas_phyinfo *phy_info = NULL;
2049 int i;
2050
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002051 mutex_lock(&ioc->sas_topology_mutex);
2052 list_for_each_entry(port_info, &ioc->sas_topology, list) {
Eric Moore547f9a22006-06-27 14:42:12 -06002053 for (i = 0; i < port_info->num_phys; i++) {
2054 if (port_info->phy_info[i].attached.id != id)
2055 continue;
2056 if (!mptsas_is_end_device(
2057 &port_info->phy_info[i].attached))
2058 continue;
2059 phy_info = &port_info->phy_info[i];
2060 break;
2061 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002062 }
2063 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002064 return phy_info;
2065}
2066
Moore, Eric4b766472006-03-14 09:14:12 -07002067/*
2068 * Work queue thread to clear the persitency table
2069 */
2070static void
Eric Moore547f9a22006-06-27 14:42:12 -06002071mptsas_persist_clear_table(void * arg)
Moore, Eric4b766472006-03-14 09:14:12 -07002072{
2073 MPT_ADAPTER *ioc = (MPT_ADAPTER *)arg;
2074
2075 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
2076}
2077
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002078static void
Moore, Ericf44e5462006-03-14 09:14:21 -07002079mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
2080{
2081 sdev->no_uld_attach = data ? 1 : 0;
2082 scsi_device_reprobe(sdev);
2083}
2084
2085static void
2086mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
2087{
2088 starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
2089 mptsas_reprobe_lun);
2090}
2091
Moore, Erice6b2d762006-03-14 09:14:24 -07002092/*
2093 * Work queue thread to handle SAS hotplug events
2094 */
Moore, Ericf44e5462006-03-14 09:14:21 -07002095static void
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002096mptsas_hotplug_work(void *arg)
2097{
2098 struct mptsas_hotplug_event *ev = arg;
2099 MPT_ADAPTER *ioc = ev->ioc;
2100 struct mptsas_phyinfo *phy_info;
2101 struct sas_rphy *rphy;
Eric Moore547f9a22006-06-27 14:42:12 -06002102 struct sas_port *port;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002103 struct scsi_device *sdev;
Eric Moore547f9a22006-06-27 14:42:12 -06002104 struct scsi_target * starget;
James Bottomleyf013db32006-03-18 14:54:36 -06002105 struct sas_identify identify;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002106 char *ds = NULL;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002107 struct mptsas_devinfo sas_device;
Moore, Ericf44e5462006-03-14 09:14:21 -07002108 VirtTarget *vtarget;
Eric Moore547f9a22006-06-27 14:42:12 -06002109 VirtDevice *vdevice;
2110
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002111
Moore, Erice6b2d762006-03-14 09:14:24 -07002112 mutex_lock(&ioc->sas_discovery_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002113 switch (ev->event_type) {
2114 case MPTSAS_DEL_DEVICE:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002115
Moore, Ericc73787ee2006-01-26 16:20:06 -07002116 phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
Moore, Erice6b2d762006-03-14 09:14:24 -07002117
Moore, Ericf44e5462006-03-14 09:14:21 -07002118 /*
2119 * Sanity checks, for non-existing phys and remote rphys.
2120 */
Eric Moore547f9a22006-06-27 14:42:12 -06002121 if (!phy_info || !phy_info->port_details) {
2122 dfailprintk((MYIOC_s_ERR_FMT
2123 "%s: exit at line=%d\n", ioc->name,
2124 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002125 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002126 }
2127 rphy = mptsas_get_rphy(phy_info);
2128 if (!rphy) {
2129 dfailprintk((MYIOC_s_ERR_FMT
2130 "%s: exit at line=%d\n", ioc->name,
2131 __FUNCTION__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002132 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002133 }
2134 port = mptsas_get_port(phy_info);
2135 if (!port) {
2136 dfailprintk((MYIOC_s_ERR_FMT
2137 "%s: exit at line=%d\n", ioc->name,
2138 __FUNCTION__, __LINE__));
2139 break;
2140 }
Moore, Ericf44e5462006-03-14 09:14:21 -07002141
Eric Moore547f9a22006-06-27 14:42:12 -06002142 starget = mptsas_get_starget(phy_info);
2143 if (starget) {
2144 vtarget = starget->hostdata;
2145
2146 if (!vtarget) {
2147 dfailprintk((MYIOC_s_ERR_FMT
2148 "%s: exit at line=%d\n", ioc->name,
2149 __FUNCTION__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002150 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002151 }
2152
Moore, Ericf44e5462006-03-14 09:14:21 -07002153 /*
2154 * Handling RAID components
2155 */
2156 if (ev->phys_disk_num_valid) {
2157 vtarget->target_id = ev->phys_disk_num;
2158 vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
Eric Moore547f9a22006-06-27 14:42:12 -06002159 mptsas_reprobe_target(starget, 1);
Moore, Ericf44e5462006-03-14 09:14:21 -07002160 break;
2161 }
Eric Moore547f9a22006-06-27 14:42:12 -06002162
2163 vtarget->deleted = 1;
2164 mptsas_target_reset(ioc, vtarget);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002165 }
2166
Moore, Ericc73787ee2006-01-26 16:20:06 -07002167 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
2168 ds = "ssp";
2169 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
2170 ds = "stp";
2171 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
2172 ds = "sata";
2173
2174 printk(MYIOC_s_INFO_FMT
2175 "removing %s device, channel %d, id %d, phy %d\n",
2176 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
2177
Eric Moore547f9a22006-06-27 14:42:12 -06002178#ifdef MPT_DEBUG_SAS_WIDE
Eric Mooredc22f162006-07-06 11:23:14 -06002179 dev_printk(KERN_DEBUG, &port->dev,
2180 "delete port (%d)\n", port->port_identifier);
Eric Moore547f9a22006-06-27 14:42:12 -06002181#endif
2182 sas_port_delete(port);
2183 mptsas_port_delete(phy_info->port_details);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002184 break;
2185 case MPTSAS_ADD_DEVICE:
Moore, Ericc73787ee2006-01-26 16:20:06 -07002186
Moore, Ericbd23e942006-04-17 12:43:04 -06002187 if (ev->phys_disk_num_valid)
2188 mpt_findImVolumes(ioc);
2189
Moore, Ericc73787ee2006-01-26 16:20:06 -07002190 /*
Christoph Hellwige3094442006-02-16 13:25:36 +01002191 * Refresh sas device pg0 data
Moore, Ericc73787ee2006-01-26 16:20:06 -07002192 */
Christoph Hellwige3094442006-02-16 13:25:36 +01002193 if (mptsas_sas_device_pg0(ioc, &sas_device,
2194 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
Eric Moore547f9a22006-06-27 14:42:12 -06002195 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id)) {
2196 dfailprintk((MYIOC_s_ERR_FMT
2197 "%s: exit at line=%d\n", ioc->name,
2198 __FUNCTION__, __LINE__));
Christoph Hellwige3094442006-02-16 13:25:36 +01002199 break;
Moore, Erice6b2d762006-03-14 09:14:24 -07002200 }
2201
Eric Moore547f9a22006-06-27 14:42:12 -06002202 ssleep(2);
2203 __mptsas_discovery_work(ioc);
Moore, Ericf44e5462006-03-14 09:14:21 -07002204
Eric Moore547f9a22006-06-27 14:42:12 -06002205 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
2206 sas_device.sas_address);
2207
2208 if (!phy_info || !phy_info->port_details) {
2209 dfailprintk((MYIOC_s_ERR_FMT
2210 "%s: exit at line=%d\n", ioc->name,
2211 __FUNCTION__, __LINE__));
2212 break;
2213 }
2214
2215 starget = mptsas_get_starget(phy_info);
2216 if (starget) {
2217 vtarget = starget->hostdata;
2218
2219 if (!vtarget) {
2220 dfailprintk((MYIOC_s_ERR_FMT
2221 "%s: exit at line=%d\n", ioc->name,
2222 __FUNCTION__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002223 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002224 }
Moore, Ericf44e5462006-03-14 09:14:21 -07002225 /*
2226 * Handling RAID components
2227 */
2228 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
2229 vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
2230 vtarget->target_id = ev->id;
Eric Moore547f9a22006-06-27 14:42:12 -06002231 mptsas_reprobe_target(starget, 0);
Moore, Ericf44e5462006-03-14 09:14:21 -07002232 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002233 break;
2234 }
2235
Eric Moore547f9a22006-06-27 14:42:12 -06002236 if (mptsas_get_rphy(phy_info)) {
2237 dfailprintk((MYIOC_s_ERR_FMT
2238 "%s: exit at line=%d\n", ioc->name,
2239 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002240 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002241 }
2242 port = mptsas_get_port(phy_info);
2243 if (!port) {
2244 dfailprintk((MYIOC_s_ERR_FMT
2245 "%s: exit at line=%d\n", ioc->name,
2246 __FUNCTION__, __LINE__));
2247 break;
2248 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002249
Christoph Hellwige3094442006-02-16 13:25:36 +01002250 memcpy(&phy_info->attached, &sas_device,
2251 sizeof(struct mptsas_devinfo));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002252
Moore, Ericc73787ee2006-01-26 16:20:06 -07002253 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
2254 ds = "ssp";
2255 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
2256 ds = "stp";
2257 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
2258 ds = "sata";
2259
2260 printk(MYIOC_s_INFO_FMT
2261 "attaching %s device, channel %d, id %d, phy %d\n",
2262 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
2263
James Bottomleyf013db32006-03-18 14:54:36 -06002264 mptsas_parse_device_info(&identify, &phy_info->attached);
Eric Moore547f9a22006-06-27 14:42:12 -06002265 rphy = sas_end_device_alloc(port);
2266 if (!rphy) {
2267 dfailprintk((MYIOC_s_ERR_FMT
2268 "%s: exit at line=%d\n", ioc->name,
2269 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002270 break; /* non-fatal: an rphy can be added later */
Eric Moore547f9a22006-06-27 14:42:12 -06002271 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002272
James Bottomleyf013db32006-03-18 14:54:36 -06002273 rphy->identify = identify;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002274 if (sas_rphy_add(rphy)) {
Eric Moore547f9a22006-06-27 14:42:12 -06002275 dfailprintk((MYIOC_s_ERR_FMT
2276 "%s: exit at line=%d\n", ioc->name,
2277 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002278 sas_rphy_free(rphy);
2279 break;
2280 }
Eric Moore547f9a22006-06-27 14:42:12 -06002281 mptsas_set_rphy(phy_info, rphy);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002282 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002283 case MPTSAS_ADD_RAID:
James Bottomleye8bf3942006-07-11 17:49:34 -04002284 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
2285 ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002286 if (sdev) {
2287 scsi_device_put(sdev);
2288 break;
2289 }
2290 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07002291 "attaching raid volume, channel %d, id %d\n",
James Bottomleye8bf3942006-07-11 17:49:34 -04002292 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
2293 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002294 mpt_findImVolumes(ioc);
2295 break;
2296 case MPTSAS_DEL_RAID:
James Bottomleye8bf3942006-07-11 17:49:34 -04002297 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
2298 ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002299 if (!sdev)
2300 break;
2301 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07002302 "removing raid volume, channel %d, id %d\n",
James Bottomleye8bf3942006-07-11 17:49:34 -04002303 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
Eric Moore547f9a22006-06-27 14:42:12 -06002304 vdevice = sdev->hostdata;
2305 vdevice->vtarget->deleted = 1;
2306 mptsas_target_reset(ioc, vdevice->vtarget);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002307 scsi_remove_device(sdev);
2308 scsi_device_put(sdev);
2309 mpt_findImVolumes(ioc);
2310 break;
Moore, Ericbd23e942006-04-17 12:43:04 -06002311 case MPTSAS_IGNORE_EVENT:
2312 default:
2313 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002314 }
2315
Moore, Erice6b2d762006-03-14 09:14:24 -07002316 mutex_unlock(&ioc->sas_discovery_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002317 kfree(ev);
2318
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002319}
2320
2321static void
Eric Moore547f9a22006-06-27 14:42:12 -06002322mptsas_send_sas_event(MPT_ADAPTER *ioc,
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002323 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
2324{
2325 struct mptsas_hotplug_event *ev;
2326 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
2327 __le64 sas_address;
2328
2329 if ((device_info &
2330 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
2331 MPI_SAS_DEVICE_INFO_STP_TARGET |
2332 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
2333 return;
2334
Moore, Eric4b766472006-03-14 09:14:12 -07002335 switch (sas_event_data->ReasonCode) {
2336 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
2337 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
Eric Moore547f9a22006-06-27 14:42:12 -06002338 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Eric4b766472006-03-14 09:14:12 -07002339 if (!ev) {
2340 printk(KERN_WARNING "mptsas: lost hotplug event\n");
2341 break;
2342 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002343
Moore, Eric4b766472006-03-14 09:14:12 -07002344 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
2345 ev->ioc = ioc;
2346 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
2347 ev->parent_handle =
2348 le16_to_cpu(sas_event_data->ParentDevHandle);
2349 ev->channel = sas_event_data->Bus;
2350 ev->id = sas_event_data->TargetID;
2351 ev->phy_id = sas_event_data->PhyNum;
2352 memcpy(&sas_address, &sas_event_data->SASAddress,
2353 sizeof(__le64));
2354 ev->sas_address = le64_to_cpu(sas_address);
2355 ev->device_info = device_info;
2356
2357 if (sas_event_data->ReasonCode &
2358 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
2359 ev->event_type = MPTSAS_ADD_DEVICE;
2360 else
2361 ev->event_type = MPTSAS_DEL_DEVICE;
2362 schedule_work(&ev->work);
2363 break;
2364 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
2365 /*
2366 * Persistent table is full.
2367 */
Eric Moore547f9a22006-06-27 14:42:12 -06002368 INIT_WORK(&ioc->sas_persist_task,
2369 mptsas_persist_clear_table, (void *)ioc);
2370 schedule_work(&ioc->sas_persist_task);
Moore, Eric4b766472006-03-14 09:14:12 -07002371 break;
2372 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
2373 /* TODO */
2374 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
2375 /* TODO */
2376 default:
2377 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002378 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002379}
2380
Moore, Ericc73787ee2006-01-26 16:20:06 -07002381static void
Eric Moore547f9a22006-06-27 14:42:12 -06002382mptsas_send_raid_event(MPT_ADAPTER *ioc,
Moore, Ericc73787ee2006-01-26 16:20:06 -07002383 EVENT_DATA_RAID *raid_event_data)
2384{
2385 struct mptsas_hotplug_event *ev;
Moore, Ericbd23e942006-04-17 12:43:04 -06002386 int status = le32_to_cpu(raid_event_data->SettingsStatus);
2387 int state = (status >> 8) & 0xff;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002388
2389 if (ioc->bus_type != SAS)
2390 return;
2391
Eric Moore547f9a22006-06-27 14:42:12 -06002392 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002393 if (!ev) {
2394 printk(KERN_WARNING "mptsas: lost hotplug event\n");
2395 return;
2396 }
2397
Moore, Ericc73787ee2006-01-26 16:20:06 -07002398 INIT_WORK(&ev->work, mptsas_hotplug_work, ev);
2399 ev->ioc = ioc;
2400 ev->id = raid_event_data->VolumeID;
Moore, Ericbd23e942006-04-17 12:43:04 -06002401 ev->event_type = MPTSAS_IGNORE_EVENT;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002402
2403 switch (raid_event_data->ReasonCode) {
2404 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
2405 ev->event_type = MPTSAS_ADD_DEVICE;
2406 break;
2407 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
Moore, Ericf44e5462006-03-14 09:14:21 -07002408 ioc->raid_data.isRaid = 1;
2409 ev->phys_disk_num_valid = 1;
2410 ev->phys_disk_num = raid_event_data->PhysDiskNum;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002411 ev->event_type = MPTSAS_DEL_DEVICE;
2412 break;
Moore, Ericbd23e942006-04-17 12:43:04 -06002413 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
2414 switch (state) {
2415 case MPI_PD_STATE_ONLINE:
2416 ioc->raid_data.isRaid = 1;
2417 ev->phys_disk_num_valid = 1;
2418 ev->phys_disk_num = raid_event_data->PhysDiskNum;
2419 ev->event_type = MPTSAS_ADD_DEVICE;
2420 break;
2421 case MPI_PD_STATE_MISSING:
2422 case MPI_PD_STATE_NOT_COMPATIBLE:
2423 case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
2424 case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
2425 case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
2426 ev->event_type = MPTSAS_DEL_DEVICE;
2427 break;
2428 default:
2429 break;
2430 }
2431 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002432 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
2433 ev->event_type = MPTSAS_DEL_RAID;
2434 break;
2435 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
2436 ev->event_type = MPTSAS_ADD_RAID;
2437 break;
2438 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
Moore, Ericbd23e942006-04-17 12:43:04 -06002439 switch (state) {
2440 case MPI_RAIDVOL0_STATUS_STATE_FAILED:
2441 case MPI_RAIDVOL0_STATUS_STATE_MISSING:
2442 ev->event_type = MPTSAS_DEL_RAID;
2443 break;
2444 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
2445 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
2446 ev->event_type = MPTSAS_ADD_RAID;
2447 break;
2448 default:
2449 break;
2450 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07002451 break;
2452 default:
2453 break;
2454 }
2455 schedule_work(&ev->work);
2456}
2457
Moore, Erice6b2d762006-03-14 09:14:24 -07002458static void
Eric Moore547f9a22006-06-27 14:42:12 -06002459mptsas_send_discovery_event(MPT_ADAPTER *ioc,
Moore, Erice6b2d762006-03-14 09:14:24 -07002460 EVENT_DATA_SAS_DISCOVERY *discovery_data)
2461{
2462 struct mptsas_discovery_event *ev;
2463
2464 /*
2465 * DiscoveryStatus
2466 *
2467 * This flag will be non-zero when firmware
2468 * kicks off discovery, and return to zero
2469 * once its completed.
2470 */
2471 if (discovery_data->DiscoveryStatus)
2472 return;
2473
Eric Moore547f9a22006-06-27 14:42:12 -06002474 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Erice6b2d762006-03-14 09:14:24 -07002475 if (!ev)
2476 return;
Eric Moore547f9a22006-06-27 14:42:12 -06002477 INIT_WORK(&ev->work, mptsas_discovery_work, ev);
Moore, Erice6b2d762006-03-14 09:14:24 -07002478 ev->ioc = ioc;
2479 schedule_work(&ev->work);
2480};
2481
2482
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002483static int
2484mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
2485{
Moore, Ericc73787ee2006-01-26 16:20:06 -07002486 int rc=1;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002487 u8 event = le32_to_cpu(reply->Event) & 0xFF;
2488
2489 if (!ioc->sh)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002490 goto out;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002491
Moore, Erice6b2d762006-03-14 09:14:24 -07002492 /*
2493 * sas_discovery_ignore_events
2494 *
2495 * This flag is to prevent anymore processing of
2496 * sas events once mptsas_remove function is called.
2497 */
2498 if (ioc->sas_discovery_ignore_events) {
2499 rc = mptscsih_event_process(ioc, reply);
2500 goto out;
2501 }
2502
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002503 switch (event) {
2504 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
Eric Moore547f9a22006-06-27 14:42:12 -06002505 mptsas_send_sas_event(ioc,
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002506 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002507 break;
2508 case MPI_EVENT_INTEGRATED_RAID:
Eric Moore547f9a22006-06-27 14:42:12 -06002509 mptsas_send_raid_event(ioc,
Moore, Ericc73787ee2006-01-26 16:20:06 -07002510 (EVENT_DATA_RAID *)reply->Data);
2511 break;
Moore, Eric79de2782006-01-25 18:05:15 -07002512 case MPI_EVENT_PERSISTENT_TABLE_FULL:
Eric Moore547f9a22006-06-27 14:42:12 -06002513 INIT_WORK(&ioc->sas_persist_task,
2514 mptsas_persist_clear_table,
Moore, Eric79de2782006-01-25 18:05:15 -07002515 (void *)ioc);
Eric Moore547f9a22006-06-27 14:42:12 -06002516 schedule_work(&ioc->sas_persist_task);
Moore, Eric79de2782006-01-25 18:05:15 -07002517 break;
Moore, Eric4b766472006-03-14 09:14:12 -07002518 case MPI_EVENT_SAS_DISCOVERY:
Eric Moore547f9a22006-06-27 14:42:12 -06002519 mptsas_send_discovery_event(ioc,
Moore, Erice6b2d762006-03-14 09:14:24 -07002520 (EVENT_DATA_SAS_DISCOVERY *)reply->Data);
2521 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002522 default:
Moore, Ericc73787ee2006-01-26 16:20:06 -07002523 rc = mptscsih_event_process(ioc, reply);
2524 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002525 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07002526 out:
2527
2528 return rc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002529}
2530
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002531static int
2532mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2533{
2534 struct Scsi_Host *sh;
2535 MPT_SCSI_HOST *hd;
2536 MPT_ADAPTER *ioc;
2537 unsigned long flags;
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002538 int ii;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002539 int numSGE = 0;
2540 int scale;
2541 int ioc_cap;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002542 int error=0;
2543 int r;
2544
2545 r = mpt_attach(pdev,id);
2546 if (r)
2547 return r;
2548
2549 ioc = pci_get_drvdata(pdev);
2550 ioc->DoneCtx = mptsasDoneCtx;
2551 ioc->TaskCtx = mptsasTaskCtx;
2552 ioc->InternalCtx = mptsasInternalCtx;
2553
2554 /* Added sanity check on readiness of the MPT adapter.
2555 */
2556 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
2557 printk(MYIOC_s_WARN_FMT
2558 "Skipping because it's not operational!\n",
2559 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002560 error = -ENODEV;
2561 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002562 }
2563
2564 if (!ioc->active) {
2565 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
2566 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002567 error = -ENODEV;
2568 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002569 }
2570
2571 /* Sanity check - ensure at least 1 port is INITIATOR capable
2572 */
2573 ioc_cap = 0;
2574 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
2575 if (ioc->pfacts[ii].ProtocolFlags &
2576 MPI_PORTFACTS_PROTOCOL_INITIATOR)
2577 ioc_cap++;
2578 }
2579
2580 if (!ioc_cap) {
2581 printk(MYIOC_s_WARN_FMT
2582 "Skipping ioc=%p because SCSI Initiator mode "
2583 "is NOT enabled!\n", ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -06002584 return 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002585 }
2586
2587 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
2588 if (!sh) {
2589 printk(MYIOC_s_WARN_FMT
2590 "Unable to register controller with SCSI subsystem\n",
2591 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002592 error = -1;
2593 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002594 }
2595
2596 spin_lock_irqsave(&ioc->FreeQlock, flags);
2597
2598 /* Attach the SCSI Host to the IOC structure
2599 */
2600 ioc->sh = sh;
2601
2602 sh->io_port = 0;
2603 sh->n_io_port = 0;
2604 sh->irq = 0;
2605
2606 /* set 16 byte cdb's */
2607 sh->max_cmd_len = 16;
2608
2609 sh->max_id = ioc->pfacts->MaxDevices + 1;
2610
2611 sh->transportt = mptsas_transport_template;
2612
2613 sh->max_lun = MPT_LAST_LUN + 1;
2614 sh->max_channel = 0;
2615 sh->this_id = ioc->pfacts[0].PortSCSIID;
2616
2617 /* Required entry.
2618 */
2619 sh->unique_id = ioc->id;
2620
2621 INIT_LIST_HEAD(&ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002622 mutex_init(&ioc->sas_topology_mutex);
Moore, Erice6b2d762006-03-14 09:14:24 -07002623 mutex_init(&ioc->sas_discovery_mutex);
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01002624 mutex_init(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002625 init_completion(&ioc->sas_mgmt.done);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002626
2627 /* Verify that we won't exceed the maximum
2628 * number of chain buffers
2629 * We can optimize: ZZ = req_sz/sizeof(SGE)
2630 * For 32bit SGE's:
2631 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
2632 * + (req_sz - 64)/sizeof(SGE)
2633 * A slightly different algorithm is required for
2634 * 64bit SGEs.
2635 */
2636 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
2637 if (sizeof(dma_addr_t) == sizeof(u64)) {
2638 numSGE = (scale - 1) *
2639 (ioc->facts.MaxChainDepth-1) + scale +
2640 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
2641 sizeof(u32));
2642 } else {
2643 numSGE = 1 + (scale - 1) *
2644 (ioc->facts.MaxChainDepth-1) + scale +
2645 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
2646 sizeof(u32));
2647 }
2648
2649 if (numSGE < sh->sg_tablesize) {
2650 /* Reset this value */
2651 dprintk((MYIOC_s_INFO_FMT
2652 "Resetting sg_tablesize to %d from %d\n",
2653 ioc->name, numSGE, sh->sg_tablesize));
2654 sh->sg_tablesize = numSGE;
2655 }
2656
2657 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2658
2659 hd = (MPT_SCSI_HOST *) sh->hostdata;
2660 hd->ioc = ioc;
2661
2662 /* SCSI needs scsi_cmnd lookup table!
2663 * (with size equal to req_depth*PtrSz!)
2664 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002665 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
2666 if (!hd->ScsiLookup) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002667 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002668 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002669 }
2670
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002671 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
2672 ioc->name, hd->ScsiLookup));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002673
2674 /* Allocate memory for the device structures.
2675 * A non-Null pointer at an offset
2676 * indicates a device exists.
2677 * max_id = 1 + maximum id (hosts.h)
2678 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002679 hd->Targets = kcalloc(sh->max_id, sizeof(void *), GFP_ATOMIC);
2680 if (!hd->Targets) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002681 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002682 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002683 }
2684
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002685 dprintk((KERN_INFO " vtarget @ %p\n", hd->Targets));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002686
2687 /* Clear the TM flags
2688 */
2689 hd->tmPending = 0;
2690 hd->tmState = TM_STATE_NONE;
2691 hd->resetPending = 0;
2692 hd->abortSCpnt = NULL;
2693
2694 /* Clear the pointer used to store
2695 * single-threaded commands, i.e., those
2696 * issued during a bus scan, dv and
2697 * configuration pages.
2698 */
2699 hd->cmdPtr = NULL;
2700
2701 /* Initialize this SCSI Hosts' timers
2702 * To use, set the timer expires field
2703 * and add_timer
2704 */
2705 init_timer(&hd->timer);
2706 hd->timer.data = (unsigned long) hd;
2707 hd->timer.function = mptscsih_timer_expired;
2708
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002709 ioc->sas_data.ptClear = mpt_pt_clear;
2710
2711 if (ioc->sas_data.ptClear==1) {
2712 mptbase_sas_persist_operation(
2713 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
2714 }
2715
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002716 init_waitqueue_head(&hd->scandv_waitq);
2717 hd->scandv_wait_done = 0;
2718 hd->last_queue_full = 0;
2719
2720 error = scsi_add_host(sh, &ioc->pcidev->dev);
2721 if (error) {
2722 dprintk((KERN_ERR MYNAM
2723 "scsi_add_host failed\n"));
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002724 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002725 }
2726
2727 mptsas_scan_sas_topology(ioc);
2728
2729 return 0;
2730
Eric Moore547f9a22006-06-27 14:42:12 -06002731 out_mptsas_probe:
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002732
2733 mptscsih_remove(pdev);
2734 return error;
2735}
2736
2737static void __devexit mptsas_remove(struct pci_dev *pdev)
2738{
2739 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
2740 struct mptsas_portinfo *p, *n;
Eric Moore547f9a22006-06-27 14:42:12 -06002741 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002742
Moore, Erice6b2d762006-03-14 09:14:24 -07002743 ioc->sas_discovery_ignore_events=1;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002744 sas_remove_host(ioc->sh);
2745
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002746 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002747 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
2748 list_del(&p->list);
Eric Moore547f9a22006-06-27 14:42:12 -06002749 for (i = 0 ; i < p->num_phys ; i++)
2750 mptsas_port_delete(p->phy_info[i].port_details);
2751 kfree(p->phy_info);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002752 kfree(p);
2753 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002754 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002755
2756 mptscsih_remove(pdev);
2757}
2758
2759static struct pci_device_id mptsas_pci_table[] = {
Eric Moore87cf8982006-06-27 16:09:26 -06002760 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002761 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002762 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002763 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002764 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002765 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002766 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002767 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002768 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002769 PCI_ANY_ID, PCI_ANY_ID },
2770 {0} /* Terminating entry */
2771};
2772MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
2773
2774
2775static struct pci_driver mptsas_driver = {
2776 .name = "mptsas",
2777 .id_table = mptsas_pci_table,
2778 .probe = mptsas_probe,
2779 .remove = __devexit_p(mptsas_remove),
2780 .shutdown = mptscsih_shutdown,
2781#ifdef CONFIG_PM
2782 .suspend = mptscsih_suspend,
2783 .resume = mptscsih_resume,
2784#endif
2785};
2786
2787static int __init
2788mptsas_init(void)
2789{
2790 show_mptmod_ver(my_NAME, my_VERSION);
2791
2792 mptsas_transport_template =
2793 sas_attach_transport(&mptsas_transport_functions);
2794 if (!mptsas_transport_template)
2795 return -ENODEV;
2796
2797 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
2798 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
2799 mptsasInternalCtx =
2800 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002801 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002802
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002803 if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
Moore, Eric3a892be2006-03-14 09:14:03 -07002804 devtverboseprintk((KERN_INFO MYNAM
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002805 ": Registered for IOC event notifications\n"));
2806 }
2807
2808 if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
2809 dprintk((KERN_INFO MYNAM
2810 ": Registered for IOC reset notifications\n"));
2811 }
2812
2813 return pci_register_driver(&mptsas_driver);
2814}
2815
2816static void __exit
2817mptsas_exit(void)
2818{
2819 pci_unregister_driver(&mptsas_driver);
2820 sas_release_transport(mptsas_transport_template);
2821
2822 mpt_reset_deregister(mptsasDoneCtx);
2823 mpt_event_deregister(mptsasDoneCtx);
2824
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002825 mpt_deregister(mptsasMgmtCtx);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002826 mpt_deregister(mptsasInternalCtx);
2827 mpt_deregister(mptsasTaskCtx);
2828 mpt_deregister(mptsasDoneCtx);
2829}
2830
2831module_init(mptsas_init);
2832module_exit(mptsas_exit);