blob: f7c5e0d978904df784020de5958a33a8aaa56488 [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 *
Eric Moore9f4203b2007-01-04 20:47:47 -07006 * Copyright (c) 1999-2007 LSI Logic Corporation
Christoph Hellwig0c33b272005-09-09 16:27:19 +02007 * (mailto:mpt_linux_developer@lsil.com)
Eric Moore9f4203b2007-01-04 20:47:47 -07008 * Copyright (c) 2005-2007 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");
Eric Moore9f4203b2007-01-04 20:47:47 -070078MODULE_VERSION(my_VERSION);
Christoph Hellwig0c33b272005-09-09 16:27:19 +020079
Christoph Hellwig0c33b272005-09-09 16:27:19 +020080static int mpt_pt_clear;
81module_param(mpt_pt_clear, int, 0);
82MODULE_PARM_DESC(mpt_pt_clear,
Eric Mooreba856d32006-07-11 17:34:01 -060083 " Clear persistency table: enable=1 "
Christoph Hellwig0c33b272005-09-09 16:27:19 +020084 "(default=MPTSCSIH_PT_CLEAR=0)");
85
Eric Moore793955f2007-01-29 09:42:20 -070086/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
87#define MPTSAS_MAX_LUN (16895)
88static int max_lun = MPTSAS_MAX_LUN;
89module_param(max_lun, int, 0);
90MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
91
Christoph Hellwig0c33b272005-09-09 16:27:19 +020092static int mptsasDoneCtx = -1;
93static int mptsasTaskCtx = -1;
94static int mptsasInternalCtx = -1; /* Used only for internal commands */
Christoph Hellwigda4fa652005-10-19 20:01:42 +020095static int mptsasMgmtCtx = -1;
Christoph Hellwig0c33b272005-09-09 16:27:19 +020096
97
Christoph Hellwig9a28f492006-01-13 18:04:41 +010098enum mptsas_hotplug_action {
99 MPTSAS_ADD_DEVICE,
100 MPTSAS_DEL_DEVICE,
Moore, Ericc73787ee2006-01-26 16:20:06 -0700101 MPTSAS_ADD_RAID,
102 MPTSAS_DEL_RAID,
Moore, Ericbd23e942006-04-17 12:43:04 -0600103 MPTSAS_IGNORE_EVENT,
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100104};
105
106struct mptsas_hotplug_event {
107 struct work_struct work;
108 MPT_ADAPTER *ioc;
109 enum mptsas_hotplug_action event_type;
110 u64 sas_address;
111 u32 channel;
112 u32 id;
113 u32 device_info;
114 u16 handle;
115 u16 parent_handle;
116 u8 phy_id;
Moore, Ericf44e5462006-03-14 09:14:21 -0700117 u8 phys_disk_num;
118 u8 phys_disk_num_valid;
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100119};
120
Moore, Erice6b2d762006-03-14 09:14:24 -0700121struct mptsas_discovery_event {
122 struct work_struct work;
123 MPT_ADAPTER *ioc;
124};
125
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200126/*
127 * SAS topology structures
128 *
129 * The MPT Fusion firmware interface spreads information about the
130 * SAS topology over many manufacture pages, thus we need some data
131 * structure to collect it and process it for the SAS transport class.
132 */
133
134struct mptsas_devinfo {
135 u16 handle; /* unique id to address this device */
Moore, Ericc73787ee2006-01-26 16:20:06 -0700136 u16 handle_parent; /* unique id to address parent device */
Christoph Hellwige3094442006-02-16 13:25:36 +0100137 u16 handle_enclosure; /* enclosure identifier of the enclosure */
138 u16 slot; /* physical slot in enclosure */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200139 u8 phy_id; /* phy number of parent device */
140 u8 port_id; /* sas physical port this device
141 is assoc'd with */
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100142 u8 id; /* logical target id of this device */
143 u8 channel; /* logical bus number of this device */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200144 u64 sas_address; /* WWN of this device,
145 SATA is assigned by HBA,expander */
146 u32 device_info; /* bitfield detailed info about this device */
147};
148
Eric Moore547f9a22006-06-27 14:42:12 -0600149/*
150 * Specific details on ports, wide/narrow
151 */
152struct mptsas_portinfo_details{
Eric Moore547f9a22006-06-27 14:42:12 -0600153 u16 num_phys; /* number of phys belong to this port */
154 u64 phy_bitmask; /* TODO, extend support for 255 phys */
155 struct sas_rphy *rphy; /* transport layer rphy object */
156 struct sas_port *port; /* transport layer port object */
157 struct scsi_target *starget;
158 struct mptsas_portinfo *port_info;
159};
160
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200161struct mptsas_phyinfo {
162 u8 phy_id; /* phy index */
Eric Moore547f9a22006-06-27 14:42:12 -0600163 u8 port_id; /* firmware port identifier */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200164 u8 negotiated_link_rate; /* nego'd link rate for this phy */
165 u8 hw_link_rate; /* hardware max/min phys link rate */
166 u8 programmed_link_rate; /* programmed max/min phy link rate */
Eric Moore547f9a22006-06-27 14:42:12 -0600167 u8 sas_port_add_phy; /* flag to request sas_port_add_phy*/
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200168 struct mptsas_devinfo identify; /* point to phy device info */
169 struct mptsas_devinfo attached; /* point to attached device info */
Eric Moore547f9a22006-06-27 14:42:12 -0600170 struct sas_phy *phy; /* transport layer phy object */
171 struct mptsas_portinfo *portinfo;
172 struct mptsas_portinfo_details * port_details;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200173};
174
175struct mptsas_portinfo {
176 struct list_head list;
177 u16 handle; /* unique id to address this */
Eric Moore547f9a22006-06-27 14:42:12 -0600178 u16 num_phys; /* number of phys */
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200179 struct mptsas_phyinfo *phy_info;
180};
181
Christoph Hellwige3094442006-02-16 13:25:36 +0100182struct mptsas_enclosure {
183 u64 enclosure_logical_id; /* The WWN for the enclosure */
184 u16 enclosure_handle; /* unique id to address this */
185 u16 flags; /* details enclosure management */
186 u16 num_slot; /* num slots */
187 u16 start_slot; /* first slot */
188 u8 start_id; /* starting logical target id */
189 u8 start_channel; /* starting logical channel id */
190 u8 sep_id; /* SEP device logical target id */
191 u8 sep_channel; /* SEP channel logical channel id */
192};
193
Eric Moore547f9a22006-06-27 14:42:12 -0600194#ifdef MPT_DEBUG_SAS
Christoph Hellwigb5141122005-10-28 22:07:41 +0200195static void mptsas_print_phy_data(MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
196{
197 printk("---- IO UNIT PAGE 0 ------------\n");
198 printk("Handle=0x%X\n",
199 le16_to_cpu(phy_data->AttachedDeviceHandle));
200 printk("Controller Handle=0x%X\n",
201 le16_to_cpu(phy_data->ControllerDevHandle));
202 printk("Port=0x%X\n", phy_data->Port);
203 printk("Port Flags=0x%X\n", phy_data->PortFlags);
204 printk("PHY Flags=0x%X\n", phy_data->PhyFlags);
205 printk("Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate);
206 printk("Controller PHY Device Info=0x%X\n",
207 le32_to_cpu(phy_data->ControllerPhyDeviceInfo));
208 printk("DiscoveryStatus=0x%X\n",
209 le32_to_cpu(phy_data->DiscoveryStatus));
210 printk("\n");
211}
212
213static void mptsas_print_phy_pg0(SasPhyPage0_t *pg0)
214{
215 __le64 sas_address;
216
217 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
218
219 printk("---- SAS PHY PAGE 0 ------------\n");
220 printk("Attached Device Handle=0x%X\n",
221 le16_to_cpu(pg0->AttachedDevHandle));
222 printk("SAS Address=0x%llX\n",
223 (unsigned long long)le64_to_cpu(sas_address));
224 printk("Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier);
225 printk("Attached Device Info=0x%X\n",
226 le32_to_cpu(pg0->AttachedDeviceInfo));
227 printk("Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate);
228 printk("Change Count=0x%X\n", pg0->ChangeCount);
229 printk("PHY Info=0x%X\n", le32_to_cpu(pg0->PhyInfo));
230 printk("\n");
231}
232
233static void mptsas_print_phy_pg1(SasPhyPage1_t *pg1)
234{
235 printk("---- SAS PHY PAGE 1 ------------\n");
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200236 printk("Invalid Dword Count=0x%x\n", pg1->InvalidDwordCount);
237 printk("Running Disparity Error Count=0x%x\n",
Christoph Hellwigb5141122005-10-28 22:07:41 +0200238 pg1->RunningDisparityErrorCount);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200239 printk("Loss Dword Synch Count=0x%x\n", pg1->LossDwordSynchCount);
240 printk("PHY Reset Problem Count=0x%x\n", pg1->PhyResetProblemCount);
241 printk("\n");
Christoph Hellwigb5141122005-10-28 22:07:41 +0200242}
243
244static void mptsas_print_device_pg0(SasDevicePage0_t *pg0)
245{
246 __le64 sas_address;
247
248 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
249
250 printk("---- SAS DEVICE PAGE 0 ---------\n");
251 printk("Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle));
Christoph Hellwige3094442006-02-16 13:25:36 +0100252 printk("Parent Handle=0x%X\n" ,le16_to_cpu(pg0->ParentDevHandle));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200253 printk("Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle));
254 printk("Slot=0x%X\n", le16_to_cpu(pg0->Slot));
Eric Mooref99be432007-01-04 20:46:54 -0700255 printk("SAS Address=0x%llX\n", (unsigned long long)
256 le64_to_cpu(sas_address));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200257 printk("Target ID=0x%X\n", pg0->TargetID);
258 printk("Bus=0x%X\n", pg0->Bus);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200259 /* The PhyNum field specifies the PHY number of the parent
260 * device this device is linked to
261 */
262 printk("Parent Phy Num=0x%X\n", pg0->PhyNum);
263 printk("Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus));
Christoph Hellwigb5141122005-10-28 22:07:41 +0200264 printk("Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo));
265 printk("Flags=0x%X\n", le16_to_cpu(pg0->Flags));
266 printk("Physical Port=0x%X\n", pg0->PhysicalPort);
267 printk("\n");
268}
269
270static void mptsas_print_expander_pg1(SasExpanderPage1_t *pg1)
271{
272 printk("---- SAS EXPANDER PAGE 1 ------------\n");
273
274 printk("Physical Port=0x%X\n", pg1->PhysicalPort);
Christoph Hellwigf9a2d2e2005-10-19 20:01:47 +0200275 printk("PHY Identifier=0x%X\n", pg1->PhyIdentifier);
Christoph Hellwigb5141122005-10-28 22:07:41 +0200276 printk("Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate);
277 printk("Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate);
278 printk("Hardware Link Rate=0x%X\n", pg1->HwLinkRate);
279 printk("Owner Device Handle=0x%X\n",
280 le16_to_cpu(pg1->OwnerDevHandle));
281 printk("Attached Device Handle=0x%X\n",
282 le16_to_cpu(pg1->AttachedDevHandle));
283}
284#else
285#define mptsas_print_phy_data(phy_data) do { } while (0)
286#define mptsas_print_phy_pg0(pg0) do { } while (0)
287#define mptsas_print_phy_pg1(pg1) do { } while (0)
288#define mptsas_print_device_pg0(pg0) do { } while (0)
289#define mptsas_print_expander_pg1(pg1) do { } while (0)
290#endif
291
Christoph Hellwige3094442006-02-16 13:25:36 +0100292static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
293{
294 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
295 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
296}
297
298static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
299{
300 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
301 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
302}
303
Moore, Erice6b2d762006-03-14 09:14:24 -0700304/*
305 * mptsas_find_portinfo_by_handle
306 *
307 * This function should be called with the sas_topology_mutex already held
308 */
309static struct mptsas_portinfo *
310mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
311{
312 struct mptsas_portinfo *port_info, *rc=NULL;
313 int i;
314
315 list_for_each_entry(port_info, &ioc->sas_topology, list)
316 for (i = 0; i < port_info->num_phys; i++)
317 if (port_info->phy_info[i].identify.handle == handle) {
318 rc = port_info;
319 goto out;
320 }
321 out:
322 return rc;
323}
324
Moore, Ericbd23e942006-04-17 12:43:04 -0600325/*
326 * Returns true if there is a scsi end device
327 */
328static inline int
329mptsas_is_end_device(struct mptsas_devinfo * attached)
330{
Eric Moore547f9a22006-06-27 14:42:12 -0600331 if ((attached->sas_address) &&
Moore, Ericbd23e942006-04-17 12:43:04 -0600332 (attached->device_info &
333 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
334 ((attached->device_info &
335 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
336 (attached->device_info &
337 MPI_SAS_DEVICE_INFO_STP_TARGET) |
338 (attached->device_info &
339 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
340 return 1;
341 else
342 return 0;
343}
344
Eric Moore547f9a22006-06-27 14:42:12 -0600345/* no mutex */
Eric Moore376ac832006-06-29 17:36:26 -0600346static void
Eric Moore547f9a22006-06-27 14:42:12 -0600347mptsas_port_delete(struct mptsas_portinfo_details * port_details)
348{
349 struct mptsas_portinfo *port_info;
350 struct mptsas_phyinfo *phy_info;
351 u8 i;
352
353 if (!port_details)
354 return;
355
356 port_info = port_details->port_info;
357 phy_info = port_info->phy_info;
358
Eric Mooredc22f162006-07-06 11:23:14 -0600359 dsaswideprintk((KERN_DEBUG "%s: [%p]: num_phys=%02d "
Eric Mooref99be432007-01-04 20:46:54 -0700360 "bitmask=0x%016llX\n", __FUNCTION__, port_details,
361 port_details->num_phys, (unsigned long long)
362 port_details->phy_bitmask));
Eric Moore547f9a22006-06-27 14:42:12 -0600363
364 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
365 if(phy_info->port_details != port_details)
366 continue;
367 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
368 phy_info->port_details = NULL;
369 }
370 kfree(port_details);
371}
372
373static inline struct sas_rphy *
374mptsas_get_rphy(struct mptsas_phyinfo *phy_info)
375{
376 if (phy_info->port_details)
377 return phy_info->port_details->rphy;
378 else
379 return NULL;
380}
381
382static inline void
383mptsas_set_rphy(struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
384{
385 if (phy_info->port_details) {
386 phy_info->port_details->rphy = rphy;
387 dsaswideprintk((KERN_DEBUG "sas_rphy_add: rphy=%p\n", rphy));
388 }
389
390#ifdef MPT_DEBUG_SAS_WIDE
391 if (rphy) {
392 dev_printk(KERN_DEBUG, &rphy->dev, "add:");
393 printk("rphy=%p release=%p\n",
394 rphy, rphy->dev.release);
395 }
396#endif
397}
398
399static inline struct sas_port *
400mptsas_get_port(struct mptsas_phyinfo *phy_info)
401{
402 if (phy_info->port_details)
403 return phy_info->port_details->port;
404 else
405 return NULL;
406}
407
408static inline void
409mptsas_set_port(struct mptsas_phyinfo *phy_info, struct sas_port *port)
410{
411 if (phy_info->port_details)
412 phy_info->port_details->port = port;
413
414#ifdef MPT_DEBUG_SAS_WIDE
415 if (port) {
416 dev_printk(KERN_DEBUG, &port->dev, "add: ");
417 printk("port=%p release=%p\n",
418 port, port->dev.release);
419 }
420#endif
421}
422
423static inline struct scsi_target *
424mptsas_get_starget(struct mptsas_phyinfo *phy_info)
425{
426 if (phy_info->port_details)
427 return phy_info->port_details->starget;
428 else
429 return NULL;
430}
431
432static inline void
433mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target *
434starget)
435{
436 if (phy_info->port_details)
437 phy_info->port_details->starget = starget;
438}
439
440
441/*
442 * mptsas_setup_wide_ports
443 *
444 * Updates for new and existing narrow/wide port configuration
445 * in the sas_topology
446 */
Eric Moore376ac832006-06-29 17:36:26 -0600447static void
Eric Moore547f9a22006-06-27 14:42:12 -0600448mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
449{
450 struct mptsas_portinfo_details * port_details;
451 struct mptsas_phyinfo *phy_info, *phy_info_cmp;
452 u64 sas_address;
453 int i, j;
454
455 mutex_lock(&ioc->sas_topology_mutex);
456
457 phy_info = port_info->phy_info;
458 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
459 if (phy_info->attached.handle)
460 continue;
461 port_details = phy_info->port_details;
462 if (!port_details)
463 continue;
464 if (port_details->num_phys < 2)
465 continue;
466 /*
467 * Removing a phy from a port, letting the last
468 * phy be removed by firmware events.
469 */
470 dsaswideprintk((KERN_DEBUG
Eric Mooredc22f162006-07-06 11:23:14 -0600471 "%s: [%p]: deleting phy = %d\n",
472 __FUNCTION__, port_details, i));
Eric Moore547f9a22006-06-27 14:42:12 -0600473 port_details->num_phys--;
474 port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
475 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
476 sas_port_delete_phy(port_details->port, phy_info->phy);
477 phy_info->port_details = NULL;
478 }
479
480 /*
481 * Populate and refresh the tree
482 */
483 phy_info = port_info->phy_info;
484 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
485 sas_address = phy_info->attached.sas_address;
486 dsaswideprintk((KERN_DEBUG "phy_id=%d sas_address=0x%018llX\n",
Eric Mooref99be432007-01-04 20:46:54 -0700487 i, (unsigned long long)sas_address));
Eric Moore547f9a22006-06-27 14:42:12 -0600488 if (!sas_address)
489 continue;
490 port_details = phy_info->port_details;
491 /*
492 * Forming a port
493 */
494 if (!port_details) {
495 port_details = kzalloc(sizeof(*port_details),
496 GFP_KERNEL);
497 if (!port_details)
498 goto out;
499 port_details->num_phys = 1;
500 port_details->port_info = port_info;
Eric Moore547f9a22006-06-27 14:42:12 -0600501 if (phy_info->phy_id < 64 )
502 port_details->phy_bitmask |=
503 (1 << phy_info->phy_id);
504 phy_info->sas_port_add_phy=1;
505 dsaswideprintk((KERN_DEBUG "\t\tForming port\n\t\t"
Eric Mooref99be432007-01-04 20:46:54 -0700506 "phy_id=%d sas_address=0x%018llX\n",
507 i, (unsigned long long)sas_address));
Eric Moore547f9a22006-06-27 14:42:12 -0600508 phy_info->port_details = port_details;
509 }
510
511 if (i == port_info->num_phys - 1)
512 continue;
513 phy_info_cmp = &port_info->phy_info[i + 1];
514 for (j = i + 1 ; j < port_info->num_phys ; j++,
515 phy_info_cmp++) {
516 if (!phy_info_cmp->attached.sas_address)
517 continue;
518 if (sas_address != phy_info_cmp->attached.sas_address)
519 continue;
520 if (phy_info_cmp->port_details == port_details )
521 continue;
522 dsaswideprintk((KERN_DEBUG
Eric Mooref99be432007-01-04 20:46:54 -0700523 "\t\tphy_id=%d sas_address=0x%018llX\n",
524 j, (unsigned long long)
525 phy_info_cmp->attached.sas_address));
Eric Moore547f9a22006-06-27 14:42:12 -0600526 if (phy_info_cmp->port_details) {
527 port_details->rphy =
528 mptsas_get_rphy(phy_info_cmp);
529 port_details->port =
530 mptsas_get_port(phy_info_cmp);
531 port_details->starget =
532 mptsas_get_starget(phy_info_cmp);
Eric Moore547f9a22006-06-27 14:42:12 -0600533 port_details->num_phys =
534 phy_info_cmp->port_details->num_phys;
Eric Moore547f9a22006-06-27 14:42:12 -0600535 if (!phy_info_cmp->port_details->num_phys)
536 kfree(phy_info_cmp->port_details);
537 } else
538 phy_info_cmp->sas_port_add_phy=1;
539 /*
540 * Adding a phy to a port
541 */
542 phy_info_cmp->port_details = port_details;
543 if (phy_info_cmp->phy_id < 64 )
544 port_details->phy_bitmask |=
545 (1 << phy_info_cmp->phy_id);
546 port_details->num_phys++;
547 }
548 }
549
550 out:
551
552#ifdef MPT_DEBUG_SAS_WIDE
553 for (i = 0; i < port_info->num_phys; i++) {
554 port_details = port_info->phy_info[i].port_details;
555 if (!port_details)
556 continue;
557 dsaswideprintk((KERN_DEBUG
Eric Mooref99be432007-01-04 20:46:54 -0700558 "%s: [%p]: phy_id=%02d num_phys=%02d "
559 "bitmask=0x%016llX\n", __FUNCTION__,
560 port_details, i, port_details->num_phys,
561 (unsigned long long)port_details->phy_bitmask));
Eric Moore547f9a22006-06-27 14:42:12 -0600562 dsaswideprintk((KERN_DEBUG"\t\tport = %p rphy=%p\n",
563 port_details->port, port_details->rphy));
564 }
565 dsaswideprintk((KERN_DEBUG"\n"));
566#endif
567 mutex_unlock(&ioc->sas_topology_mutex);
568}
569
570static void
571mptsas_target_reset(MPT_ADAPTER *ioc, VirtTarget * vtarget)
572{
573 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
574
575 if (mptscsih_TMHandler(hd,
576 MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET,
Eric Moore793955f2007-01-29 09:42:20 -0700577 vtarget->channel, vtarget->id, 0, 0, 5) < 0) {
Eric Moore547f9a22006-06-27 14:42:12 -0600578 hd->tmPending = 0;
579 hd->tmState = TM_STATE_NONE;
580 printk(MYIOC_s_WARN_FMT
581 "Error processing TaskMgmt id=%d TARGET_RESET\n",
Eric Moore793955f2007-01-29 09:42:20 -0700582 ioc->name, vtarget->id);
Eric Moore547f9a22006-06-27 14:42:12 -0600583 }
584}
585
Christoph Hellwige3094442006-02-16 13:25:36 +0100586static int
Moore, Eric52435432006-03-14 09:14:15 -0700587mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
Christoph Hellwige3094442006-02-16 13:25:36 +0100588 u32 form, u32 form_specific)
589{
590 ConfigExtendedPageHeader_t hdr;
591 CONFIGPARMS cfg;
592 SasEnclosurePage0_t *buffer;
593 dma_addr_t dma_handle;
594 int error;
595 __le64 le_identifier;
596
597 memset(&hdr, 0, sizeof(hdr));
598 hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
599 hdr.PageNumber = 0;
600 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
601 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
602
603 cfg.cfghdr.ehdr = &hdr;
604 cfg.physAddr = -1;
605 cfg.pageAddr = form + form_specific;
606 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
607 cfg.dir = 0; /* read */
608 cfg.timeout = 10;
609
610 error = mpt_config(ioc, &cfg);
611 if (error)
612 goto out;
613 if (!hdr.ExtPageLength) {
614 error = -ENXIO;
615 goto out;
616 }
617
618 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
619 &dma_handle);
620 if (!buffer) {
621 error = -ENOMEM;
622 goto out;
623 }
624
625 cfg.physAddr = dma_handle;
626 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
627
628 error = mpt_config(ioc, &cfg);
629 if (error)
630 goto out_free_consistent;
631
632 /* save config data */
633 memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
634 enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
635 enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
636 enclosure->flags = le16_to_cpu(buffer->Flags);
637 enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
638 enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
639 enclosure->start_id = buffer->StartTargetID;
640 enclosure->start_channel = buffer->StartBus;
641 enclosure->sep_id = buffer->SEPTargetID;
642 enclosure->sep_channel = buffer->SEPBus;
643
644 out_free_consistent:
645 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
646 buffer, dma_handle);
647 out:
648 return error;
649}
Christoph Hellwigb5141122005-10-28 22:07:41 +0200650
James Bottomleyf013db32006-03-18 14:54:36 -0600651static int
652mptsas_slave_configure(struct scsi_device *sdev)
653{
Moore, Eric3c0c25b2006-04-13 16:08:17 -0600654
James Bottomleye8bf3942006-07-11 17:49:34 -0400655 if (sdev->channel == MPTSAS_RAID_CHANNEL)
656 goto out;
James Bottomleyf013db32006-03-18 14:54:36 -0600657
James Bottomleye8bf3942006-07-11 17:49:34 -0400658 sas_read_port_mode_page(sdev);
659
660 out:
James Bottomleyf013db32006-03-18 14:54:36 -0600661 return mptscsih_slave_configure(sdev);
662}
663
Eric Moore547f9a22006-06-27 14:42:12 -0600664static int
665mptsas_target_alloc(struct scsi_target *starget)
666{
667 struct Scsi_Host *host = dev_to_shost(&starget->dev);
668 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
669 VirtTarget *vtarget;
Eric Moore793955f2007-01-29 09:42:20 -0700670 u8 id, channel;
Eric Moore547f9a22006-06-27 14:42:12 -0600671 struct sas_rphy *rphy;
672 struct mptsas_portinfo *p;
673 int i;
674
675 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
676 if (!vtarget)
677 return -ENOMEM;
678
679 vtarget->starget = starget;
680 vtarget->ioc_id = hd->ioc->id;
Eric Moore793955f2007-01-29 09:42:20 -0700681 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
682 id = starget->id;
Eric Moore547f9a22006-06-27 14:42:12 -0600683 channel = 0;
684
Eric Moore793955f2007-01-29 09:42:20 -0700685 /*
686 * RAID volumes placed beyond the last expected port.
687 */
688 if (starget->channel == MPTSAS_RAID_CHANNEL) {
689 for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
690 if (id == hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID)
691 channel = hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus;
Eric Moore547f9a22006-06-27 14:42:12 -0600692 goto out;
Eric Moore793955f2007-01-29 09:42:20 -0700693 }
Eric Moore547f9a22006-06-27 14:42:12 -0600694
695 rphy = dev_to_rphy(starget->dev.parent);
696 mutex_lock(&hd->ioc->sas_topology_mutex);
697 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
698 for (i = 0; i < p->num_phys; i++) {
699 if (p->phy_info[i].attached.sas_address !=
700 rphy->identify.sas_address)
701 continue;
Eric Moore793955f2007-01-29 09:42:20 -0700702 id = p->phy_info[i].attached.id;
Eric Moore547f9a22006-06-27 14:42:12 -0600703 channel = p->phy_info[i].attached.channel;
704 mptsas_set_starget(&p->phy_info[i], starget);
705
706 /*
707 * Exposing hidden raid components
708 */
Eric Moore793955f2007-01-29 09:42:20 -0700709 if (mptscsih_is_phys_disk(hd->ioc, channel, id)) {
710 id = mptscsih_raid_id_to_num(hd->ioc,
711 channel, id);
Eric Moore547f9a22006-06-27 14:42:12 -0600712 vtarget->tflags |=
713 MPT_TARGET_FLAGS_RAID_COMPONENT;
714 }
715 mutex_unlock(&hd->ioc->sas_topology_mutex);
716 goto out;
717 }
718 }
719 mutex_unlock(&hd->ioc->sas_topology_mutex);
720
721 kfree(vtarget);
722 return -ENXIO;
723
724 out:
Eric Moore793955f2007-01-29 09:42:20 -0700725 vtarget->id = id;
726 vtarget->channel = channel;
Eric Moore547f9a22006-06-27 14:42:12 -0600727 starget->hostdata = vtarget;
728 return 0;
729}
730
731static void
732mptsas_target_destroy(struct scsi_target *starget)
733{
734 struct Scsi_Host *host = dev_to_shost(&starget->dev);
735 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
736 struct sas_rphy *rphy;
737 struct mptsas_portinfo *p;
738 int i;
739
740 if (!starget->hostdata)
741 return;
742
James Bottomleye8bf3942006-07-11 17:49:34 -0400743 if (starget->channel == MPTSAS_RAID_CHANNEL)
Eric Moore547f9a22006-06-27 14:42:12 -0600744 goto out;
745
746 rphy = dev_to_rphy(starget->dev.parent);
747 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
748 for (i = 0; i < p->num_phys; i++) {
749 if (p->phy_info[i].attached.sas_address !=
750 rphy->identify.sas_address)
751 continue;
752 mptsas_set_starget(&p->phy_info[i], NULL);
753 goto out;
754 }
755 }
756
757 out:
758 kfree(starget->hostdata);
759 starget->hostdata = NULL;
760}
761
762
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200763static int
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700764mptsas_slave_alloc(struct scsi_device *sdev)
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200765{
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700766 struct Scsi_Host *host = sdev->host;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200767 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
768 struct sas_rphy *rphy;
769 struct mptsas_portinfo *p;
770 VirtDevice *vdev;
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700771 struct scsi_target *starget;
Eric Moore547f9a22006-06-27 14:42:12 -0600772 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200773
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +0100774 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200775 if (!vdev) {
Eric Moore547f9a22006-06-27 14:42:12 -0600776 printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200777 hd->ioc->name, sizeof(VirtDevice));
778 return -ENOMEM;
779 }
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700780 starget = scsi_target(sdev);
Eric Moore547f9a22006-06-27 14:42:12 -0600781 vdev->vtarget = starget->hostdata;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200782
James Bottomleye8bf3942006-07-11 17:49:34 -0400783 if (sdev->channel == MPTSAS_RAID_CHANNEL)
Moore, Eric816aa902006-01-13 16:25:20 -0700784 goto out;
Moore, Eric816aa902006-01-13 16:25:20 -0700785
Moore, Eric Deanc7c82982005-11-16 18:54:25 -0700786 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100787 mutex_lock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200788 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
789 for (i = 0; i < p->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -0600790 if (p->phy_info[i].attached.sas_address !=
791 rphy->identify.sas_address)
792 continue;
793 vdev->lun = sdev->lun;
794 /*
795 * Exposing hidden raid components
796 */
797 if (mptscsih_is_phys_disk(hd->ioc,
Eric Moore793955f2007-01-29 09:42:20 -0700798 p->phy_info[i].attached.channel,
799 p->phy_info[i].attached.id))
Eric Moore547f9a22006-06-27 14:42:12 -0600800 sdev->no_uld_attach = 1;
801 mutex_unlock(&hd->ioc->sas_topology_mutex);
802 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200803 }
804 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100805 mutex_unlock(&hd->ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200806
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200807 kfree(vdev);
Christoph Hellwig23f236e2006-01-30 19:00:43 +0100808 return -ENXIO;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200809
810 out:
Eric Moore547f9a22006-06-27 14:42:12 -0600811 vdev->vtarget->num_luns++;
812 sdev->hostdata = vdev;
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200813 return 0;
814}
815
Eric Moore547f9a22006-06-27 14:42:12 -0600816static int
817mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100818{
Eric Moore547f9a22006-06-27 14:42:12 -0600819 VirtDevice *vdev = SCpnt->device->hostdata;
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100820
Eric Moore793955f2007-01-29 09:42:20 -0700821 if (!vdev || !vdev->vtarget || vdev->vtarget->deleted) {
Eric Moore547f9a22006-06-27 14:42:12 -0600822 SCpnt->result = DID_NO_CONNECT << 16;
823 done(SCpnt);
824 return 0;
Moore, Eric7d3eecf2006-01-25 18:05:12 -0700825 }
Eric Moore547f9a22006-06-27 14:42:12 -0600826
Eric Moore793955f2007-01-29 09:42:20 -0700827// scsi_print_command(SCpnt);
828
Eric Moore547f9a22006-06-27 14:42:12 -0600829 return mptscsih_qcmd(SCpnt,done);
Christoph Hellwig9a28f492006-01-13 18:04:41 +0100830}
831
Eric Moore547f9a22006-06-27 14:42:12 -0600832
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200833static struct scsi_host_template mptsas_driver_template = {
Moore, Eric Deanf78496d2005-11-16 18:54:14 -0700834 .module = THIS_MODULE,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200835 .proc_name = "mptsas",
836 .proc_info = mptscsih_proc_info,
837 .name = "MPT SPI Host",
838 .info = mptscsih_info,
Eric Moore547f9a22006-06-27 14:42:12 -0600839 .queuecommand = mptsas_qcmd,
840 .target_alloc = mptsas_target_alloc,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200841 .slave_alloc = mptsas_slave_alloc,
James Bottomleyf013db32006-03-18 14:54:36 -0600842 .slave_configure = mptsas_slave_configure,
Eric Moore547f9a22006-06-27 14:42:12 -0600843 .target_destroy = mptsas_target_destroy,
844 .slave_destroy = mptscsih_slave_destroy,
Christoph Hellwig0c33b272005-09-09 16:27:19 +0200845 .change_queue_depth = mptscsih_change_queue_depth,
846 .eh_abort_handler = mptscsih_abort,
847 .eh_device_reset_handler = mptscsih_dev_reset,
848 .eh_bus_reset_handler = mptscsih_bus_reset,
849 .eh_host_reset_handler = mptscsih_host_reset,
850 .bios_param = mptscsih_bios_param,
851 .can_queue = MPT_FC_CAN_QUEUE,
852 .this_id = -1,
853 .sg_tablesize = MPT_SCSI_SG_DEPTH,
854 .max_sectors = 8192,
855 .cmd_per_lun = 7,
856 .use_clustering = ENABLE_CLUSTERING,
857};
858
Christoph Hellwigb5141122005-10-28 22:07:41 +0200859static int mptsas_get_linkerrors(struct sas_phy *phy)
860{
861 MPT_ADAPTER *ioc = phy_to_ioc(phy);
862 ConfigExtendedPageHeader_t hdr;
863 CONFIGPARMS cfg;
864 SasPhyPage1_t *buffer;
865 dma_addr_t dma_handle;
866 int error;
867
James Bottomleyf4ad7b52006-08-25 13:48:18 -0500868 /* FIXME: only have link errors on local phys */
869 if (!scsi_is_sas_phy_local(phy))
870 return -EINVAL;
871
Christoph Hellwigb5141122005-10-28 22:07:41 +0200872 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
873 hdr.ExtPageLength = 0;
874 hdr.PageNumber = 1 /* page number 1*/;
875 hdr.Reserved1 = 0;
876 hdr.Reserved2 = 0;
877 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
878 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
879
880 cfg.cfghdr.ehdr = &hdr;
881 cfg.physAddr = -1;
882 cfg.pageAddr = phy->identify.phy_identifier;
883 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
884 cfg.dir = 0; /* read */
885 cfg.timeout = 10;
886
887 error = mpt_config(ioc, &cfg);
888 if (error)
889 return error;
890 if (!hdr.ExtPageLength)
891 return -ENXIO;
892
893 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
894 &dma_handle);
895 if (!buffer)
896 return -ENOMEM;
897
898 cfg.physAddr = dma_handle;
899 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
900
901 error = mpt_config(ioc, &cfg);
902 if (error)
903 goto out_free_consistent;
904
905 mptsas_print_phy_pg1(buffer);
906
907 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
908 phy->running_disparity_error_count =
909 le32_to_cpu(buffer->RunningDisparityErrorCount);
910 phy->loss_of_dword_sync_count =
911 le32_to_cpu(buffer->LossDwordSynchCount);
912 phy->phy_reset_problem_count =
913 le32_to_cpu(buffer->PhyResetProblemCount);
914
915 out_free_consistent:
916 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
917 buffer, dma_handle);
918 return error;
919}
920
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200921static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
922 MPT_FRAME_HDR *reply)
923{
924 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
925 if (reply != NULL) {
926 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
927 memcpy(ioc->sas_mgmt.reply, reply,
928 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
929 }
930 complete(&ioc->sas_mgmt.done);
931 return 1;
932}
933
934static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
935{
936 MPT_ADAPTER *ioc = phy_to_ioc(phy);
937 SasIoUnitControlRequest_t *req;
938 SasIoUnitControlReply_t *reply;
939 MPT_FRAME_HDR *mf;
940 MPIHeader_t *hdr;
941 unsigned long timeleft;
942 int error = -ERESTARTSYS;
943
James Bottomleyf4ad7b52006-08-25 13:48:18 -0500944 /* FIXME: fusion doesn't allow non-local phy reset */
945 if (!scsi_is_sas_phy_local(phy))
946 return -EINVAL;
947
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200948 /* not implemented for expanders */
949 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
950 return -ENXIO;
951
Christoph Hellwigeeb846c2006-01-13 18:27:11 +0100952 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
Christoph Hellwigda4fa652005-10-19 20:01:42 +0200953 goto out;
954
955 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
956 if (!mf) {
957 error = -ENOMEM;
958 goto out_unlock;
959 }
960
961 hdr = (MPIHeader_t *) mf;
962 req = (SasIoUnitControlRequest_t *)mf;
963 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
964 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
965 req->MsgContext = hdr->MsgContext;
966 req->Operation = hard_reset ?
967 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
968 req->PhyNum = phy->identify.phy_identifier;
969
970 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
971
972 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
973 10 * HZ);
974 if (!timeleft) {
975 /* On timeout reset the board */
976 mpt_free_msg_frame(ioc, mf);
977 mpt_HardResetHandler(ioc, CAN_SLEEP);
978 error = -ETIMEDOUT;
979 goto out_unlock;
980 }
981
982 /* a reply frame is expected */
983 if ((ioc->sas_mgmt.status &
984 MPT_IOCTL_STATUS_RF_VALID) == 0) {
985 error = -ENXIO;
986 goto out_unlock;
987 }
988
989 /* process the completed Reply Message Frame */
990 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
991 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
992 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
993 __FUNCTION__,
994 reply->IOCStatus,
995 reply->IOCLogInfo);
996 error = -ENXIO;
997 goto out_unlock;
998 }
999
1000 error = 0;
1001
1002 out_unlock:
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01001003 mutex_unlock(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001004 out:
1005 return error;
1006}
Christoph Hellwigb5141122005-10-28 22:07:41 +02001007
Christoph Hellwige3094442006-02-16 13:25:36 +01001008static int
1009mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
1010{
1011 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1012 int i, error;
1013 struct mptsas_portinfo *p;
1014 struct mptsas_enclosure enclosure_info;
1015 u64 enclosure_handle;
1016
1017 mutex_lock(&ioc->sas_topology_mutex);
1018 list_for_each_entry(p, &ioc->sas_topology, list) {
1019 for (i = 0; i < p->num_phys; i++) {
1020 if (p->phy_info[i].attached.sas_address ==
1021 rphy->identify.sas_address) {
1022 enclosure_handle = p->phy_info[i].
1023 attached.handle_enclosure;
1024 goto found_info;
1025 }
1026 }
1027 }
1028 mutex_unlock(&ioc->sas_topology_mutex);
1029 return -ENXIO;
1030
1031 found_info:
1032 mutex_unlock(&ioc->sas_topology_mutex);
1033 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
Moore, Eric52435432006-03-14 09:14:15 -07001034 error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
Christoph Hellwige3094442006-02-16 13:25:36 +01001035 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
1036 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
1037 if (!error)
1038 *identifier = enclosure_info.enclosure_logical_id;
1039 return error;
1040}
1041
1042static int
1043mptsas_get_bay_identifier(struct sas_rphy *rphy)
1044{
1045 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1046 struct mptsas_portinfo *p;
1047 int i, rc;
1048
1049 mutex_lock(&ioc->sas_topology_mutex);
1050 list_for_each_entry(p, &ioc->sas_topology, list) {
1051 for (i = 0; i < p->num_phys; i++) {
1052 if (p->phy_info[i].attached.sas_address ==
1053 rphy->identify.sas_address) {
1054 rc = p->phy_info[i].attached.slot;
1055 goto out;
1056 }
1057 }
1058 }
1059 rc = -ENXIO;
1060 out:
1061 mutex_unlock(&ioc->sas_topology_mutex);
1062 return rc;
1063}
1064
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001065static struct sas_function_template mptsas_transport_functions = {
Christoph Hellwigb5141122005-10-28 22:07:41 +02001066 .get_linkerrors = mptsas_get_linkerrors,
Christoph Hellwige3094442006-02-16 13:25:36 +01001067 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
1068 .get_bay_identifier = mptsas_get_bay_identifier,
Christoph Hellwigda4fa652005-10-19 20:01:42 +02001069 .phy_reset = mptsas_phy_reset,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001070};
1071
1072static struct scsi_transport_template *mptsas_transport_template;
1073
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001074static int
1075mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
1076{
1077 ConfigExtendedPageHeader_t hdr;
1078 CONFIGPARMS cfg;
1079 SasIOUnitPage0_t *buffer;
1080 dma_addr_t dma_handle;
1081 int error, i;
1082
1083 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
1084 hdr.ExtPageLength = 0;
1085 hdr.PageNumber = 0;
1086 hdr.Reserved1 = 0;
1087 hdr.Reserved2 = 0;
1088 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1089 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1090
1091 cfg.cfghdr.ehdr = &hdr;
1092 cfg.physAddr = -1;
1093 cfg.pageAddr = 0;
1094 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1095 cfg.dir = 0; /* read */
1096 cfg.timeout = 10;
1097
1098 error = mpt_config(ioc, &cfg);
1099 if (error)
1100 goto out;
1101 if (!hdr.ExtPageLength) {
1102 error = -ENXIO;
1103 goto out;
1104 }
1105
1106 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1107 &dma_handle);
1108 if (!buffer) {
1109 error = -ENOMEM;
1110 goto out;
1111 }
1112
1113 cfg.physAddr = dma_handle;
1114 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1115
1116 error = mpt_config(ioc, &cfg);
1117 if (error)
1118 goto out_free_consistent;
1119
1120 port_info->num_phys = buffer->NumPhys;
1121 port_info->phy_info = kcalloc(port_info->num_phys,
Eric Moore547f9a22006-06-27 14:42:12 -06001122 sizeof(*port_info->phy_info),GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001123 if (!port_info->phy_info) {
1124 error = -ENOMEM;
1125 goto out_free_consistent;
1126 }
1127
Moore, Ericdb9c9172006-03-14 09:14:18 -07001128 if (port_info->num_phys)
1129 port_info->handle =
1130 le16_to_cpu(buffer->PhyData[0].ControllerDevHandle);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001131 for (i = 0; i < port_info->num_phys; i++) {
1132 mptsas_print_phy_data(&buffer->PhyData[i]);
1133 port_info->phy_info[i].phy_id = i;
1134 port_info->phy_info[i].port_id =
1135 buffer->PhyData[i].Port;
1136 port_info->phy_info[i].negotiated_link_rate =
1137 buffer->PhyData[i].NegotiatedLinkRate;
Eric Moore547f9a22006-06-27 14:42:12 -06001138 port_info->phy_info[i].portinfo = port_info;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001139 }
1140
1141 out_free_consistent:
1142 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1143 buffer, dma_handle);
1144 out:
1145 return error;
1146}
1147
1148static int
1149mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1150 u32 form, u32 form_specific)
1151{
1152 ConfigExtendedPageHeader_t hdr;
1153 CONFIGPARMS cfg;
1154 SasPhyPage0_t *buffer;
1155 dma_addr_t dma_handle;
1156 int error;
1157
1158 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
1159 hdr.ExtPageLength = 0;
1160 hdr.PageNumber = 0;
1161 hdr.Reserved1 = 0;
1162 hdr.Reserved2 = 0;
1163 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1164 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
1165
1166 cfg.cfghdr.ehdr = &hdr;
1167 cfg.dir = 0; /* read */
1168 cfg.timeout = 10;
1169
1170 /* Get Phy Pg 0 for each Phy. */
1171 cfg.physAddr = -1;
1172 cfg.pageAddr = form + form_specific;
1173 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1174
1175 error = mpt_config(ioc, &cfg);
1176 if (error)
1177 goto out;
1178
1179 if (!hdr.ExtPageLength) {
1180 error = -ENXIO;
1181 goto out;
1182 }
1183
1184 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1185 &dma_handle);
1186 if (!buffer) {
1187 error = -ENOMEM;
1188 goto out;
1189 }
1190
1191 cfg.physAddr = dma_handle;
1192 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1193
1194 error = mpt_config(ioc, &cfg);
1195 if (error)
1196 goto out_free_consistent;
1197
1198 mptsas_print_phy_pg0(buffer);
1199
1200 phy_info->hw_link_rate = buffer->HwLinkRate;
1201 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1202 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1203 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1204
1205 out_free_consistent:
1206 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1207 buffer, dma_handle);
1208 out:
1209 return error;
1210}
1211
1212static int
1213mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
1214 u32 form, u32 form_specific)
1215{
1216 ConfigExtendedPageHeader_t hdr;
1217 CONFIGPARMS cfg;
1218 SasDevicePage0_t *buffer;
1219 dma_addr_t dma_handle;
1220 __le64 sas_address;
Moore, Ericbd23e942006-04-17 12:43:04 -06001221 int error=0;
1222
1223 if (ioc->sas_discovery_runtime &&
1224 mptsas_is_end_device(device_info))
1225 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001226
1227 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
1228 hdr.ExtPageLength = 0;
1229 hdr.PageNumber = 0;
1230 hdr.Reserved1 = 0;
1231 hdr.Reserved2 = 0;
1232 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1233 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1234
1235 cfg.cfghdr.ehdr = &hdr;
1236 cfg.pageAddr = form + form_specific;
1237 cfg.physAddr = -1;
1238 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1239 cfg.dir = 0; /* read */
1240 cfg.timeout = 10;
1241
Moore, Ericdb9c9172006-03-14 09:14:18 -07001242 memset(device_info, 0, sizeof(struct mptsas_devinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001243 error = mpt_config(ioc, &cfg);
1244 if (error)
1245 goto out;
1246 if (!hdr.ExtPageLength) {
1247 error = -ENXIO;
1248 goto out;
1249 }
1250
1251 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1252 &dma_handle);
1253 if (!buffer) {
1254 error = -ENOMEM;
1255 goto out;
1256 }
1257
1258 cfg.physAddr = dma_handle;
1259 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1260
1261 error = mpt_config(ioc, &cfg);
1262 if (error)
1263 goto out_free_consistent;
1264
1265 mptsas_print_device_pg0(buffer);
1266
1267 device_info->handle = le16_to_cpu(buffer->DevHandle);
Moore, Ericc73787ee2006-01-26 16:20:06 -07001268 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
Christoph Hellwige3094442006-02-16 13:25:36 +01001269 device_info->handle_enclosure =
1270 le16_to_cpu(buffer->EnclosureHandle);
1271 device_info->slot = le16_to_cpu(buffer->Slot);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001272 device_info->phy_id = buffer->PhyNum;
1273 device_info->port_id = buffer->PhysicalPort;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001274 device_info->id = buffer->TargetID;
1275 device_info->channel = buffer->Bus;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001276 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
1277 device_info->sas_address = le64_to_cpu(sas_address);
1278 device_info->device_info =
1279 le32_to_cpu(buffer->DeviceInfo);
1280
1281 out_free_consistent:
1282 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1283 buffer, dma_handle);
1284 out:
1285 return error;
1286}
1287
1288static int
1289mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
1290 u32 form, u32 form_specific)
1291{
1292 ConfigExtendedPageHeader_t hdr;
1293 CONFIGPARMS cfg;
1294 SasExpanderPage0_t *buffer;
1295 dma_addr_t dma_handle;
Eric Moore547f9a22006-06-27 14:42:12 -06001296 int i, error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001297
1298 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1299 hdr.ExtPageLength = 0;
1300 hdr.PageNumber = 0;
1301 hdr.Reserved1 = 0;
1302 hdr.Reserved2 = 0;
1303 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1304 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1305
1306 cfg.cfghdr.ehdr = &hdr;
1307 cfg.physAddr = -1;
1308 cfg.pageAddr = form + form_specific;
1309 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1310 cfg.dir = 0; /* read */
1311 cfg.timeout = 10;
1312
Moore, Ericdb9c9172006-03-14 09:14:18 -07001313 memset(port_info, 0, sizeof(struct mptsas_portinfo));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001314 error = mpt_config(ioc, &cfg);
1315 if (error)
1316 goto out;
1317
1318 if (!hdr.ExtPageLength) {
1319 error = -ENXIO;
1320 goto out;
1321 }
1322
1323 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1324 &dma_handle);
1325 if (!buffer) {
1326 error = -ENOMEM;
1327 goto out;
1328 }
1329
1330 cfg.physAddr = dma_handle;
1331 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1332
1333 error = mpt_config(ioc, &cfg);
1334 if (error)
1335 goto out_free_consistent;
1336
1337 /* save config data */
1338 port_info->num_phys = buffer->NumPhys;
1339 port_info->handle = le16_to_cpu(buffer->DevHandle);
1340 port_info->phy_info = kcalloc(port_info->num_phys,
Eric Moore547f9a22006-06-27 14:42:12 -06001341 sizeof(*port_info->phy_info),GFP_KERNEL);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001342 if (!port_info->phy_info) {
1343 error = -ENOMEM;
1344 goto out_free_consistent;
1345 }
1346
Eric Moore547f9a22006-06-27 14:42:12 -06001347 for (i = 0; i < port_info->num_phys; i++)
1348 port_info->phy_info[i].portinfo = port_info;
1349
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001350 out_free_consistent:
1351 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1352 buffer, dma_handle);
1353 out:
1354 return error;
1355}
1356
1357static int
1358mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1359 u32 form, u32 form_specific)
1360{
1361 ConfigExtendedPageHeader_t hdr;
1362 CONFIGPARMS cfg;
1363 SasExpanderPage1_t *buffer;
1364 dma_addr_t dma_handle;
Moore, Ericbd23e942006-04-17 12:43:04 -06001365 int error=0;
1366
1367 if (ioc->sas_discovery_runtime &&
1368 mptsas_is_end_device(&phy_info->attached))
1369 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001370
1371 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1372 hdr.ExtPageLength = 0;
1373 hdr.PageNumber = 1;
1374 hdr.Reserved1 = 0;
1375 hdr.Reserved2 = 0;
1376 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1377 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1378
1379 cfg.cfghdr.ehdr = &hdr;
1380 cfg.physAddr = -1;
1381 cfg.pageAddr = form + form_specific;
1382 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1383 cfg.dir = 0; /* read */
1384 cfg.timeout = 10;
1385
1386 error = mpt_config(ioc, &cfg);
1387 if (error)
1388 goto out;
1389
1390 if (!hdr.ExtPageLength) {
1391 error = -ENXIO;
1392 goto out;
1393 }
1394
1395 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1396 &dma_handle);
1397 if (!buffer) {
1398 error = -ENOMEM;
1399 goto out;
1400 }
1401
1402 cfg.physAddr = dma_handle;
1403 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1404
1405 error = mpt_config(ioc, &cfg);
1406 if (error)
1407 goto out_free_consistent;
1408
1409
1410 mptsas_print_expander_pg1(buffer);
1411
1412 /* save config data */
Eric Moore024358e2005-10-21 20:56:36 +02001413 phy_info->phy_id = buffer->PhyIdentifier;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001414 phy_info->port_id = buffer->PhysicalPort;
1415 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
1416 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1417 phy_info->hw_link_rate = buffer->HwLinkRate;
1418 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1419 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1420
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001421 out_free_consistent:
1422 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1423 buffer, dma_handle);
1424 out:
1425 return error;
1426}
1427
1428static void
1429mptsas_parse_device_info(struct sas_identify *identify,
1430 struct mptsas_devinfo *device_info)
1431{
1432 u16 protocols;
1433
1434 identify->sas_address = device_info->sas_address;
1435 identify->phy_identifier = device_info->phy_id;
1436
1437 /*
1438 * Fill in Phy Initiator Port Protocol.
1439 * Bits 6:3, more than one bit can be set, fall through cases.
1440 */
1441 protocols = device_info->device_info & 0x78;
1442 identify->initiator_port_protocols = 0;
1443 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
1444 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
1445 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1446 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
1447 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
1448 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
1449 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
1450 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
1451
1452 /*
1453 * Fill in Phy Target Port Protocol.
1454 * Bits 10:7, more than one bit can be set, fall through cases.
1455 */
1456 protocols = device_info->device_info & 0x780;
1457 identify->target_port_protocols = 0;
1458 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1459 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
1460 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
1461 identify->target_port_protocols |= SAS_PROTOCOL_STP;
1462 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
1463 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
1464 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1465 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
1466
1467 /*
1468 * Fill in Attached device type.
1469 */
1470 switch (device_info->device_info &
1471 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
1472 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
1473 identify->device_type = SAS_PHY_UNUSED;
1474 break;
1475 case MPI_SAS_DEVICE_INFO_END_DEVICE:
1476 identify->device_type = SAS_END_DEVICE;
1477 break;
1478 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
1479 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
1480 break;
1481 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
1482 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
1483 break;
1484 }
1485}
1486
1487static int mptsas_probe_one_phy(struct device *dev,
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001488 struct mptsas_phyinfo *phy_info, int index, int local)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001489{
Moore, Erice6b2d762006-03-14 09:14:24 -07001490 MPT_ADAPTER *ioc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001491 struct sas_phy *phy;
Eric Moore547f9a22006-06-27 14:42:12 -06001492 struct sas_port *port;
1493 int error = 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001494
Eric Moore547f9a22006-06-27 14:42:12 -06001495 if (!dev) {
1496 error = -ENODEV;
1497 goto out;
1498 }
Moore, Erice6b2d762006-03-14 09:14:24 -07001499
1500 if (!phy_info->phy) {
1501 phy = sas_phy_alloc(dev, index);
Eric Moore547f9a22006-06-27 14:42:12 -06001502 if (!phy) {
1503 error = -ENOMEM;
1504 goto out;
1505 }
Moore, Erice6b2d762006-03-14 09:14:24 -07001506 } else
1507 phy = phy_info->phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001508
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001509 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001510
1511 /*
1512 * Set Negotiated link rate.
1513 */
1514 switch (phy_info->negotiated_link_rate) {
1515 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001516 phy->negotiated_linkrate = SAS_PHY_DISABLED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001517 break;
1518 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001519 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001520 break;
1521 case MPI_SAS_IOUNIT0_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001522 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001523 break;
1524 case MPI_SAS_IOUNIT0_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001525 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001526 break;
1527 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
1528 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
1529 default:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001530 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001531 break;
1532 }
1533
1534 /*
1535 * Set Max hardware link rate.
1536 */
1537 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1538 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001539 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001540 break;
1541 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001542 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001543 break;
1544 default:
1545 break;
1546 }
1547
1548 /*
1549 * Set Max programmed link rate.
1550 */
1551 switch (phy_info->programmed_link_rate &
1552 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1553 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001554 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001555 break;
1556 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001557 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001558 break;
1559 default:
1560 break;
1561 }
1562
1563 /*
1564 * Set Min hardware link rate.
1565 */
1566 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
1567 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001568 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001569 break;
1570 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001571 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001572 break;
1573 default:
1574 break;
1575 }
1576
1577 /*
1578 * Set Min programmed link rate.
1579 */
1580 switch (phy_info->programmed_link_rate &
1581 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
1582 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001583 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001584 break;
1585 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001586 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001587 break;
1588 default:
1589 break;
1590 }
1591
Moore, Erice6b2d762006-03-14 09:14:24 -07001592 if (!phy_info->phy) {
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001593
Moore, Erice6b2d762006-03-14 09:14:24 -07001594 error = sas_phy_add(phy);
1595 if (error) {
1596 sas_phy_free(phy);
Eric Moore547f9a22006-06-27 14:42:12 -06001597 goto out;
Moore, Erice6b2d762006-03-14 09:14:24 -07001598 }
1599 phy_info->phy = phy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001600 }
1601
Eric Moore547f9a22006-06-27 14:42:12 -06001602 if (!phy_info->attached.handle ||
1603 !phy_info->port_details)
1604 goto out;
1605
1606 port = mptsas_get_port(phy_info);
1607 ioc = phy_to_ioc(phy_info->phy);
1608
1609 if (phy_info->sas_port_add_phy) {
1610
1611 if (!port) {
Eric Mooredc22f162006-07-06 11:23:14 -06001612 port = sas_port_alloc_num(dev);
Eric Moore547f9a22006-06-27 14:42:12 -06001613 if (!port) {
1614 error = -ENOMEM;
1615 goto out;
1616 }
1617 error = sas_port_add(port);
1618 if (error) {
1619 dfailprintk((MYIOC_s_ERR_FMT
1620 "%s: exit at line=%d\n", ioc->name,
1621 __FUNCTION__, __LINE__));
1622 goto out;
1623 }
1624 mptsas_set_port(phy_info, port);
Eric Mooredc22f162006-07-06 11:23:14 -06001625 dsaswideprintk((KERN_DEBUG
1626 "sas_port_alloc: port=%p dev=%p port_id=%d\n",
1627 port, dev, port->port_identifier));
Eric Moore547f9a22006-06-27 14:42:12 -06001628 }
1629 dsaswideprintk((KERN_DEBUG "sas_port_add_phy: phy_id=%d\n",
1630 phy_info->phy_id));
1631 sas_port_add_phy(port, phy_info->phy);
1632 phy_info->sas_port_add_phy = 0;
1633 }
1634
1635 if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
Moore, Erice6b2d762006-03-14 09:14:24 -07001636
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001637 struct sas_rphy *rphy;
James Bottomley2686de22006-06-30 12:54:02 -05001638 struct device *parent;
James Bottomleyf013db32006-03-18 14:54:36 -06001639 struct sas_identify identify;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001640
James Bottomley2686de22006-06-30 12:54:02 -05001641 parent = dev->parent->parent;
Moore, Erice6b2d762006-03-14 09:14:24 -07001642 /*
1643 * Let the hotplug_work thread handle processing
1644 * the adding/removing of devices that occur
1645 * after start of day.
1646 */
1647 if (ioc->sas_discovery_runtime &&
1648 mptsas_is_end_device(&phy_info->attached))
Eric Moore547f9a22006-06-27 14:42:12 -06001649 goto out;
Moore, Erice6b2d762006-03-14 09:14:24 -07001650
James Bottomleyf013db32006-03-18 14:54:36 -06001651 mptsas_parse_device_info(&identify, &phy_info->attached);
James Bottomley2686de22006-06-30 12:54:02 -05001652 if (scsi_is_host_device(parent)) {
1653 struct mptsas_portinfo *port_info;
1654 int i;
1655
1656 mutex_lock(&ioc->sas_topology_mutex);
1657 port_info = mptsas_find_portinfo_by_handle(ioc,
1658 ioc->handle);
1659 mutex_unlock(&ioc->sas_topology_mutex);
1660
1661 for (i = 0; i < port_info->num_phys; i++)
1662 if (port_info->phy_info[i].identify.sas_address ==
James Bottomley0c269e62006-07-12 09:51:04 -04001663 identify.sas_address) {
1664 sas_port_mark_backlink(port);
James Bottomley2686de22006-06-30 12:54:02 -05001665 goto out;
James Bottomley0c269e62006-07-12 09:51:04 -04001666 }
James Bottomley2686de22006-06-30 12:54:02 -05001667
1668 } else if (scsi_is_sas_rphy(parent)) {
1669 struct sas_rphy *parent_rphy = dev_to_rphy(parent);
1670 if (identify.sas_address ==
James Bottomley0c269e62006-07-12 09:51:04 -04001671 parent_rphy->identify.sas_address) {
1672 sas_port_mark_backlink(port);
James Bottomley2686de22006-06-30 12:54:02 -05001673 goto out;
James Bottomley0c269e62006-07-12 09:51:04 -04001674 }
James Bottomley2686de22006-06-30 12:54:02 -05001675 }
1676
James Bottomleyf013db32006-03-18 14:54:36 -06001677 switch (identify.device_type) {
1678 case SAS_END_DEVICE:
Eric Moore547f9a22006-06-27 14:42:12 -06001679 rphy = sas_end_device_alloc(port);
James Bottomleyf013db32006-03-18 14:54:36 -06001680 break;
1681 case SAS_EDGE_EXPANDER_DEVICE:
1682 case SAS_FANOUT_EXPANDER_DEVICE:
Eric Moore547f9a22006-06-27 14:42:12 -06001683 rphy = sas_expander_alloc(port, identify.device_type);
James Bottomleyf013db32006-03-18 14:54:36 -06001684 break;
1685 default:
1686 rphy = NULL;
1687 break;
1688 }
Eric Moore547f9a22006-06-27 14:42:12 -06001689 if (!rphy) {
1690 dfailprintk((MYIOC_s_ERR_FMT
1691 "%s: exit at line=%d\n", ioc->name,
1692 __FUNCTION__, __LINE__));
1693 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001694 }
1695
Eric Moore547f9a22006-06-27 14:42:12 -06001696 rphy->identify = identify;
1697 error = sas_rphy_add(rphy);
1698 if (error) {
1699 dfailprintk((MYIOC_s_ERR_FMT
1700 "%s: exit at line=%d\n", ioc->name,
1701 __FUNCTION__, __LINE__));
1702 sas_rphy_free(rphy);
1703 goto out;
1704 }
1705 mptsas_set_rphy(phy_info, rphy);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001706 }
1707
Eric Moore547f9a22006-06-27 14:42:12 -06001708 out:
1709 return error;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001710}
1711
1712static int
Moore, Erice6b2d762006-03-14 09:14:24 -07001713mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001714{
Moore, Erice6b2d762006-03-14 09:14:24 -07001715 struct mptsas_portinfo *port_info, *hba;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001716 u32 handle = 0xFFFF;
1717 int error = -ENOMEM, i;
1718
Moore, Erice6b2d762006-03-14 09:14:24 -07001719 hba = kzalloc(sizeof(*port_info), GFP_KERNEL);
1720 if (! hba)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001721 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001722
Moore, Erice6b2d762006-03-14 09:14:24 -07001723 error = mptsas_sas_io_unit_pg0(ioc, hba);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001724 if (error)
1725 goto out_free_port_info;
1726
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001727 mutex_lock(&ioc->sas_topology_mutex);
James Bottomley2686de22006-06-30 12:54:02 -05001728 ioc->handle = hba->handle;
Moore, Erice6b2d762006-03-14 09:14:24 -07001729 port_info = mptsas_find_portinfo_by_handle(ioc, hba->handle);
1730 if (!port_info) {
1731 port_info = hba;
1732 list_add_tail(&port_info->list, &ioc->sas_topology);
1733 } else {
1734 port_info->handle = hba->handle;
1735 for (i = 0; i < hba->num_phys; i++)
1736 port_info->phy_info[i].negotiated_link_rate =
1737 hba->phy_info[i].negotiated_link_rate;
Eric Moore547f9a22006-06-27 14:42:12 -06001738 kfree(hba->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001739 kfree(hba);
1740 hba = NULL;
1741 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001742 mutex_unlock(&ioc->sas_topology_mutex);
1743
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001744 for (i = 0; i < port_info->num_phys; i++) {
1745 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
1746 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
1747 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
1748
1749 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
1750 (MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE <<
1751 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), handle);
Eric Moore024358e2005-10-21 20:56:36 +02001752 port_info->phy_info[i].identify.phy_id =
1753 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001754 handle = port_info->phy_info[i].identify.handle;
1755
Eric Moore547f9a22006-06-27 14:42:12 -06001756 if (port_info->phy_info[i].attached.handle)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001757 mptsas_sas_device_pg0(ioc,
1758 &port_info->phy_info[i].attached,
1759 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1760 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1761 port_info->phy_info[i].attached.handle);
Eric Moore547f9a22006-06-27 14:42:12 -06001762 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001763
Eric Moore547f9a22006-06-27 14:42:12 -06001764 mptsas_setup_wide_ports(ioc, port_info);
1765
1766 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001767 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
Moore, Erice6b2d762006-03-14 09:14:24 -07001768 &port_info->phy_info[i], ioc->sas_index, 1);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001769
1770 return 0;
1771
1772 out_free_port_info:
Eric Moore547f9a22006-06-27 14:42:12 -06001773 kfree(hba);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001774 out:
1775 return error;
1776}
1777
1778static int
Moore, Erice6b2d762006-03-14 09:14:24 -07001779mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001780{
Moore, Erice6b2d762006-03-14 09:14:24 -07001781 struct mptsas_portinfo *port_info, *p, *ex;
Eric Moore547f9a22006-06-27 14:42:12 -06001782 struct device *parent;
1783 struct sas_rphy *rphy;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001784 int error = -ENOMEM, i, j;
1785
Moore, Erice6b2d762006-03-14 09:14:24 -07001786 ex = kzalloc(sizeof(*port_info), GFP_KERNEL);
1787 if (!ex)
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001788 goto out;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001789
Moore, Erice6b2d762006-03-14 09:14:24 -07001790 error = mptsas_sas_expander_pg0(ioc, ex,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001791 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
1792 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
1793 if (error)
1794 goto out_free_port_info;
1795
Moore, Erice6b2d762006-03-14 09:14:24 -07001796 *handle = ex->handle;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001797
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001798 mutex_lock(&ioc->sas_topology_mutex);
Moore, Erice6b2d762006-03-14 09:14:24 -07001799 port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
1800 if (!port_info) {
1801 port_info = ex;
1802 list_add_tail(&port_info->list, &ioc->sas_topology);
1803 } else {
1804 port_info->handle = ex->handle;
Eric Moore547f9a22006-06-27 14:42:12 -06001805 kfree(ex->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001806 kfree(ex);
1807 ex = NULL;
1808 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001809 mutex_unlock(&ioc->sas_topology_mutex);
1810
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001811 for (i = 0; i < port_info->num_phys; i++) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001812 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
1813 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
1814 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
1815
1816 if (port_info->phy_info[i].identify.handle) {
1817 mptsas_sas_device_pg0(ioc,
1818 &port_info->phy_info[i].identify,
1819 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1820 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1821 port_info->phy_info[i].identify.handle);
Eric Moore024358e2005-10-21 20:56:36 +02001822 port_info->phy_info[i].identify.phy_id =
1823 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001824 }
1825
1826 if (port_info->phy_info[i].attached.handle) {
1827 mptsas_sas_device_pg0(ioc,
1828 &port_info->phy_info[i].attached,
1829 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
1830 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
1831 port_info->phy_info[i].attached.handle);
Moore, Ericdb9c9172006-03-14 09:14:18 -07001832 port_info->phy_info[i].attached.phy_id =
1833 port_info->phy_info[i].phy_id;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001834 }
Eric Moore547f9a22006-06-27 14:42:12 -06001835 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001836
Eric Moore547f9a22006-06-27 14:42:12 -06001837 parent = &ioc->sh->shost_gendev;
1838 for (i = 0; i < port_info->num_phys; i++) {
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001839 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001840 list_for_each_entry(p, &ioc->sas_topology, list) {
1841 for (j = 0; j < p->num_phys; j++) {
Eric Moore547f9a22006-06-27 14:42:12 -06001842 if (port_info->phy_info[i].identify.handle !=
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001843 p->phy_info[j].attached.handle)
Eric Moore547f9a22006-06-27 14:42:12 -06001844 continue;
1845 rphy = mptsas_get_rphy(&p->phy_info[j]);
1846 parent = &rphy->dev;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001847 }
1848 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01001849 mutex_unlock(&ioc->sas_topology_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06001850 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001851
Eric Moore547f9a22006-06-27 14:42:12 -06001852 mptsas_setup_wide_ports(ioc, port_info);
1853
1854 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
Christoph Hellwigac01bbb2005-10-19 20:01:17 +02001855 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
Moore, Erice6b2d762006-03-14 09:14:24 -07001856 ioc->sas_index, 0);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001857
1858 return 0;
1859
1860 out_free_port_info:
Moore, Erice6b2d762006-03-14 09:14:24 -07001861 if (ex) {
Eric Moore547f9a22006-06-27 14:42:12 -06001862 kfree(ex->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001863 kfree(ex);
1864 }
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001865 out:
1866 return error;
1867}
1868
Moore, Erice6b2d762006-03-14 09:14:24 -07001869/*
1870 * mptsas_delete_expander_phys
1871 *
1872 *
1873 * This will traverse topology, and remove expanders
1874 * that are no longer present
1875 */
1876static void
1877mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
1878{
1879 struct mptsas_portinfo buffer;
1880 struct mptsas_portinfo *port_info, *n, *parent;
Eric Moore547f9a22006-06-27 14:42:12 -06001881 struct mptsas_phyinfo *phy_info;
1882 struct scsi_target * starget;
1883 VirtTarget * vtarget;
1884 struct sas_port * port;
Moore, Erice6b2d762006-03-14 09:14:24 -07001885 int i;
Eric Moore547f9a22006-06-27 14:42:12 -06001886 u64 expander_sas_address;
Moore, Erice6b2d762006-03-14 09:14:24 -07001887
1888 mutex_lock(&ioc->sas_topology_mutex);
1889 list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {
1890
1891 if (port_info->phy_info &&
1892 (!(port_info->phy_info[0].identify.device_info &
1893 MPI_SAS_DEVICE_INFO_SMP_TARGET)))
1894 continue;
1895
1896 if (mptsas_sas_expander_pg0(ioc, &buffer,
1897 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
1898 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), port_info->handle)) {
1899
1900 /*
Eric Moore547f9a22006-06-27 14:42:12 -06001901 * Issue target reset to all child end devices
1902 * then mark them deleted to prevent further
1903 * IO going to them.
1904 */
1905 phy_info = port_info->phy_info;
1906 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
1907 starget = mptsas_get_starget(phy_info);
1908 if (!starget)
1909 continue;
1910 vtarget = starget->hostdata;
1911 if(vtarget->deleted)
1912 continue;
1913 vtarget->deleted = 1;
1914 mptsas_target_reset(ioc, vtarget);
1915 sas_port_delete(mptsas_get_port(phy_info));
1916 mptsas_port_delete(phy_info->port_details);
1917 }
1918
1919 /*
Moore, Erice6b2d762006-03-14 09:14:24 -07001920 * Obtain the port_info instance to the parent port
1921 */
1922 parent = mptsas_find_portinfo_by_handle(ioc,
1923 port_info->phy_info[0].identify.handle_parent);
1924
1925 if (!parent)
1926 goto next_port;
1927
Eric Moore547f9a22006-06-27 14:42:12 -06001928 expander_sas_address =
1929 port_info->phy_info[0].identify.sas_address;
1930
Moore, Erice6b2d762006-03-14 09:14:24 -07001931 /*
1932 * Delete rphys in the parent that point
1933 * to this expander. The transport layer will
1934 * cleanup all the children.
1935 */
Eric Moore547f9a22006-06-27 14:42:12 -06001936 phy_info = parent->phy_info;
1937 for (i = 0; i < parent->num_phys; i++, phy_info++) {
1938 port = mptsas_get_port(phy_info);
1939 if (!port)
Moore, Erice6b2d762006-03-14 09:14:24 -07001940 continue;
Eric Moore547f9a22006-06-27 14:42:12 -06001941 if (phy_info->attached.sas_address !=
1942 expander_sas_address)
1943 continue;
1944#ifdef MPT_DEBUG_SAS_WIDE
Eric Mooredc22f162006-07-06 11:23:14 -06001945 dev_printk(KERN_DEBUG, &port->dev,
1946 "delete port (%d)\n", port->port_identifier);
Eric Moore547f9a22006-06-27 14:42:12 -06001947#endif
1948 sas_port_delete(port);
1949 mptsas_port_delete(phy_info->port_details);
Moore, Erice6b2d762006-03-14 09:14:24 -07001950 }
1951 next_port:
Eric Moore547f9a22006-06-27 14:42:12 -06001952
1953 phy_info = port_info->phy_info;
1954 for (i = 0; i < port_info->num_phys; i++, phy_info++)
1955 mptsas_port_delete(phy_info->port_details);
1956
Moore, Erice6b2d762006-03-14 09:14:24 -07001957 list_del(&port_info->list);
Eric Moore547f9a22006-06-27 14:42:12 -06001958 kfree(port_info->phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001959 kfree(port_info);
1960 }
1961 /*
1962 * Free this memory allocated from inside
1963 * mptsas_sas_expander_pg0
1964 */
Eric Moore547f9a22006-06-27 14:42:12 -06001965 kfree(buffer.phy_info);
Moore, Erice6b2d762006-03-14 09:14:24 -07001966 }
1967 mutex_unlock(&ioc->sas_topology_mutex);
1968}
1969
1970/*
1971 * Start of day discovery
1972 */
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001973static void
1974mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
1975{
1976 u32 handle = 0xFFFF;
Moore, Ericf44e5462006-03-14 09:14:21 -07001977 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001978
Moore, Erice6b2d762006-03-14 09:14:24 -07001979 mutex_lock(&ioc->sas_discovery_mutex);
1980 mptsas_probe_hba_phys(ioc);
1981 while (!mptsas_probe_expander_phys(ioc, &handle))
Christoph Hellwig0c33b272005-09-09 16:27:19 +02001982 ;
Moore, Ericf44e5462006-03-14 09:14:21 -07001983 /*
1984 Reporting RAID volumes.
1985 */
1986 if (!ioc->raid_data.pIocPg2)
1987 goto out;
1988 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
1989 goto out;
Eric Moore793955f2007-01-29 09:42:20 -07001990 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
James Bottomleye8bf3942006-07-11 17:49:34 -04001991 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
Moore, Ericf44e5462006-03-14 09:14:21 -07001992 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
1993 }
1994 out:
Moore, Erice6b2d762006-03-14 09:14:24 -07001995 mutex_unlock(&ioc->sas_discovery_mutex);
1996}
1997
1998/*
1999 * Work queue thread to handle Runtime discovery
2000 * Mere purpose is the hot add/delete of expanders
Eric Moore547f9a22006-06-27 14:42:12 -06002001 *(Mutex UNLOCKED)
Moore, Erice6b2d762006-03-14 09:14:24 -07002002 */
2003static void
Eric Moore547f9a22006-06-27 14:42:12 -06002004__mptsas_discovery_work(MPT_ADAPTER *ioc)
Moore, Erice6b2d762006-03-14 09:14:24 -07002005{
Moore, Erice6b2d762006-03-14 09:14:24 -07002006 u32 handle = 0xFFFF;
2007
Moore, Erice6b2d762006-03-14 09:14:24 -07002008 ioc->sas_discovery_runtime=1;
2009 mptsas_delete_expander_phys(ioc);
2010 mptsas_probe_hba_phys(ioc);
2011 while (!mptsas_probe_expander_phys(ioc, &handle))
2012 ;
Moore, Erice6b2d762006-03-14 09:14:24 -07002013 ioc->sas_discovery_runtime=0;
Eric Moore547f9a22006-06-27 14:42:12 -06002014}
2015
2016/*
2017 * Work queue thread to handle Runtime discovery
2018 * Mere purpose is the hot add/delete of expanders
2019 *(Mutex LOCKED)
2020 */
2021static void
David Howellsc4028952006-11-22 14:57:56 +00002022mptsas_discovery_work(struct work_struct *work)
Eric Moore547f9a22006-06-27 14:42:12 -06002023{
David Howellsc4028952006-11-22 14:57:56 +00002024 struct mptsas_discovery_event *ev =
2025 container_of(work, struct mptsas_discovery_event, work);
Eric Moore547f9a22006-06-27 14:42:12 -06002026 MPT_ADAPTER *ioc = ev->ioc;
2027
2028 mutex_lock(&ioc->sas_discovery_mutex);
2029 __mptsas_discovery_work(ioc);
Moore, Erice6b2d762006-03-14 09:14:24 -07002030 mutex_unlock(&ioc->sas_discovery_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002031 kfree(ev);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002032}
2033
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002034static struct mptsas_phyinfo *
Eric Moore547f9a22006-06-27 14:42:12 -06002035mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002036{
2037 struct mptsas_portinfo *port_info;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002038 struct mptsas_phyinfo *phy_info = NULL;
Eric Moore547f9a22006-06-27 14:42:12 -06002039 int i;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002040
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002041 mutex_lock(&ioc->sas_topology_mutex);
2042 list_for_each_entry(port_info, &ioc->sas_topology, list) {
2043 for (i = 0; i < port_info->num_phys; i++) {
Eric Moore547f9a22006-06-27 14:42:12 -06002044 if (port_info->phy_info[i].attached.sas_address
2045 != sas_address)
2046 continue;
2047 if (!mptsas_is_end_device(
2048 &port_info->phy_info[i].attached))
2049 continue;
2050 phy_info = &port_info->phy_info[i];
2051 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002052 }
2053 }
2054 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002055 return phy_info;
2056}
2057
2058static struct mptsas_phyinfo *
Moore, Ericc73787ee2006-01-26 16:20:06 -07002059mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u32 id)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002060{
2061 struct mptsas_portinfo *port_info;
2062 struct mptsas_phyinfo *phy_info = NULL;
2063 int i;
2064
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002065 mutex_lock(&ioc->sas_topology_mutex);
2066 list_for_each_entry(port_info, &ioc->sas_topology, list) {
Eric Moore547f9a22006-06-27 14:42:12 -06002067 for (i = 0; i < port_info->num_phys; i++) {
2068 if (port_info->phy_info[i].attached.id != id)
2069 continue;
2070 if (!mptsas_is_end_device(
2071 &port_info->phy_info[i].attached))
2072 continue;
2073 phy_info = &port_info->phy_info[i];
2074 break;
2075 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002076 }
2077 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002078 return phy_info;
2079}
2080
Moore, Eric4b766472006-03-14 09:14:12 -07002081/*
2082 * Work queue thread to clear the persitency table
2083 */
2084static void
David Howellsc4028952006-11-22 14:57:56 +00002085mptsas_persist_clear_table(struct work_struct *work)
Moore, Eric4b766472006-03-14 09:14:12 -07002086{
David Howellsc4028952006-11-22 14:57:56 +00002087 MPT_ADAPTER *ioc = container_of(work, MPT_ADAPTER, sas_persist_task);
Moore, Eric4b766472006-03-14 09:14:12 -07002088
2089 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
2090}
2091
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002092static void
Moore, Ericf44e5462006-03-14 09:14:21 -07002093mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
2094{
Eric Mooref99be432007-01-04 20:46:54 -07002095 int rc;
2096
Moore, Ericf44e5462006-03-14 09:14:21 -07002097 sdev->no_uld_attach = data ? 1 : 0;
Eric Mooref99be432007-01-04 20:46:54 -07002098 rc = scsi_device_reprobe(sdev);
Moore, Ericf44e5462006-03-14 09:14:21 -07002099}
2100
2101static void
2102mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
2103{
2104 starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
2105 mptsas_reprobe_lun);
2106}
2107
Moore, Erice6b2d762006-03-14 09:14:24 -07002108/*
2109 * Work queue thread to handle SAS hotplug events
2110 */
Moore, Ericf44e5462006-03-14 09:14:21 -07002111static void
David Howellsc4028952006-11-22 14:57:56 +00002112mptsas_hotplug_work(struct work_struct *work)
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002113{
David Howellsc4028952006-11-22 14:57:56 +00002114 struct mptsas_hotplug_event *ev =
2115 container_of(work, struct mptsas_hotplug_event, work);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002116 MPT_ADAPTER *ioc = ev->ioc;
2117 struct mptsas_phyinfo *phy_info;
2118 struct sas_rphy *rphy;
Eric Moore547f9a22006-06-27 14:42:12 -06002119 struct sas_port *port;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002120 struct scsi_device *sdev;
Eric Moore547f9a22006-06-27 14:42:12 -06002121 struct scsi_target * starget;
James Bottomleyf013db32006-03-18 14:54:36 -06002122 struct sas_identify identify;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002123 char *ds = NULL;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002124 struct mptsas_devinfo sas_device;
Moore, Ericf44e5462006-03-14 09:14:21 -07002125 VirtTarget *vtarget;
Eric Moore547f9a22006-06-27 14:42:12 -06002126 VirtDevice *vdevice;
2127
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002128
Moore, Erice6b2d762006-03-14 09:14:24 -07002129 mutex_lock(&ioc->sas_discovery_mutex);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002130 switch (ev->event_type) {
2131 case MPTSAS_DEL_DEVICE:
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002132
Moore, Ericc73787ee2006-01-26 16:20:06 -07002133 phy_info = mptsas_find_phyinfo_by_target(ioc, ev->id);
Moore, Erice6b2d762006-03-14 09:14:24 -07002134
Moore, Ericf44e5462006-03-14 09:14:21 -07002135 /*
2136 * Sanity checks, for non-existing phys and remote rphys.
2137 */
Eric Moore547f9a22006-06-27 14:42:12 -06002138 if (!phy_info || !phy_info->port_details) {
2139 dfailprintk((MYIOC_s_ERR_FMT
2140 "%s: exit at line=%d\n", ioc->name,
2141 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002142 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002143 }
2144 rphy = mptsas_get_rphy(phy_info);
2145 if (!rphy) {
2146 dfailprintk((MYIOC_s_ERR_FMT
2147 "%s: exit at line=%d\n", ioc->name,
2148 __FUNCTION__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002149 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002150 }
2151 port = mptsas_get_port(phy_info);
2152 if (!port) {
2153 dfailprintk((MYIOC_s_ERR_FMT
2154 "%s: exit at line=%d\n", ioc->name,
2155 __FUNCTION__, __LINE__));
2156 break;
2157 }
Moore, Ericf44e5462006-03-14 09:14:21 -07002158
Eric Moore547f9a22006-06-27 14:42:12 -06002159 starget = mptsas_get_starget(phy_info);
2160 if (starget) {
2161 vtarget = starget->hostdata;
2162
2163 if (!vtarget) {
2164 dfailprintk((MYIOC_s_ERR_FMT
2165 "%s: exit at line=%d\n", ioc->name,
2166 __FUNCTION__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002167 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002168 }
2169
Moore, Ericf44e5462006-03-14 09:14:21 -07002170 /*
2171 * Handling RAID components
2172 */
2173 if (ev->phys_disk_num_valid) {
Eric Moore793955f2007-01-29 09:42:20 -07002174 vtarget->id = ev->phys_disk_num;
Moore, Ericf44e5462006-03-14 09:14:21 -07002175 vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
Eric Moore547f9a22006-06-27 14:42:12 -06002176 mptsas_reprobe_target(starget, 1);
Moore, Ericf44e5462006-03-14 09:14:21 -07002177 break;
2178 }
Eric Moore547f9a22006-06-27 14:42:12 -06002179
2180 vtarget->deleted = 1;
2181 mptsas_target_reset(ioc, vtarget);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002182 }
2183
Moore, Ericc73787ee2006-01-26 16:20:06 -07002184 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
2185 ds = "ssp";
2186 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
2187 ds = "stp";
2188 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
2189 ds = "sata";
2190
2191 printk(MYIOC_s_INFO_FMT
2192 "removing %s device, channel %d, id %d, phy %d\n",
2193 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
2194
Eric Moore547f9a22006-06-27 14:42:12 -06002195#ifdef MPT_DEBUG_SAS_WIDE
Eric Mooredc22f162006-07-06 11:23:14 -06002196 dev_printk(KERN_DEBUG, &port->dev,
2197 "delete port (%d)\n", port->port_identifier);
Eric Moore547f9a22006-06-27 14:42:12 -06002198#endif
2199 sas_port_delete(port);
2200 mptsas_port_delete(phy_info->port_details);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002201 break;
2202 case MPTSAS_ADD_DEVICE:
Moore, Ericc73787ee2006-01-26 16:20:06 -07002203
Moore, Ericbd23e942006-04-17 12:43:04 -06002204 if (ev->phys_disk_num_valid)
2205 mpt_findImVolumes(ioc);
2206
Moore, Ericc73787ee2006-01-26 16:20:06 -07002207 /*
Christoph Hellwige3094442006-02-16 13:25:36 +01002208 * Refresh sas device pg0 data
Moore, Ericc73787ee2006-01-26 16:20:06 -07002209 */
Christoph Hellwige3094442006-02-16 13:25:36 +01002210 if (mptsas_sas_device_pg0(ioc, &sas_device,
2211 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
Eric Moore547f9a22006-06-27 14:42:12 -06002212 MPI_SAS_DEVICE_PGAD_FORM_SHIFT), ev->id)) {
2213 dfailprintk((MYIOC_s_ERR_FMT
2214 "%s: exit at line=%d\n", ioc->name,
2215 __FUNCTION__, __LINE__));
Christoph Hellwige3094442006-02-16 13:25:36 +01002216 break;
Moore, Erice6b2d762006-03-14 09:14:24 -07002217 }
2218
Eric Moore547f9a22006-06-27 14:42:12 -06002219 ssleep(2);
2220 __mptsas_discovery_work(ioc);
Moore, Ericf44e5462006-03-14 09:14:21 -07002221
Eric Moore547f9a22006-06-27 14:42:12 -06002222 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
2223 sas_device.sas_address);
2224
2225 if (!phy_info || !phy_info->port_details) {
2226 dfailprintk((MYIOC_s_ERR_FMT
2227 "%s: exit at line=%d\n", ioc->name,
2228 __FUNCTION__, __LINE__));
2229 break;
2230 }
2231
2232 starget = mptsas_get_starget(phy_info);
2233 if (starget) {
2234 vtarget = starget->hostdata;
2235
2236 if (!vtarget) {
2237 dfailprintk((MYIOC_s_ERR_FMT
2238 "%s: exit at line=%d\n", ioc->name,
2239 __FUNCTION__, __LINE__));
Moore, Ericf44e5462006-03-14 09:14:21 -07002240 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002241 }
Moore, Ericf44e5462006-03-14 09:14:21 -07002242 /*
2243 * Handling RAID components
2244 */
2245 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
2246 vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
Eric Moore793955f2007-01-29 09:42:20 -07002247 vtarget->id = ev->id;
Eric Moore547f9a22006-06-27 14:42:12 -06002248 mptsas_reprobe_target(starget, 0);
Moore, Ericf44e5462006-03-14 09:14:21 -07002249 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002250 break;
2251 }
2252
Eric Moore547f9a22006-06-27 14:42:12 -06002253 if (mptsas_get_rphy(phy_info)) {
2254 dfailprintk((MYIOC_s_ERR_FMT
2255 "%s: exit at line=%d\n", ioc->name,
2256 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002257 break;
Eric Moore547f9a22006-06-27 14:42:12 -06002258 }
2259 port = mptsas_get_port(phy_info);
2260 if (!port) {
2261 dfailprintk((MYIOC_s_ERR_FMT
2262 "%s: exit at line=%d\n", ioc->name,
2263 __FUNCTION__, __LINE__));
2264 break;
2265 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002266
Christoph Hellwige3094442006-02-16 13:25:36 +01002267 memcpy(&phy_info->attached, &sas_device,
2268 sizeof(struct mptsas_devinfo));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002269
Moore, Ericc73787ee2006-01-26 16:20:06 -07002270 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_TARGET)
2271 ds = "ssp";
2272 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_STP_TARGET)
2273 ds = "stp";
2274 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
2275 ds = "sata";
2276
2277 printk(MYIOC_s_INFO_FMT
2278 "attaching %s device, channel %d, id %d, phy %d\n",
2279 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
2280
James Bottomleyf013db32006-03-18 14:54:36 -06002281 mptsas_parse_device_info(&identify, &phy_info->attached);
Eric Moore547f9a22006-06-27 14:42:12 -06002282 rphy = sas_end_device_alloc(port);
2283 if (!rphy) {
2284 dfailprintk((MYIOC_s_ERR_FMT
2285 "%s: exit at line=%d\n", ioc->name,
2286 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002287 break; /* non-fatal: an rphy can be added later */
Eric Moore547f9a22006-06-27 14:42:12 -06002288 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002289
James Bottomleyf013db32006-03-18 14:54:36 -06002290 rphy->identify = identify;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002291 if (sas_rphy_add(rphy)) {
Eric Moore547f9a22006-06-27 14:42:12 -06002292 dfailprintk((MYIOC_s_ERR_FMT
2293 "%s: exit at line=%d\n", ioc->name,
2294 __FUNCTION__, __LINE__));
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002295 sas_rphy_free(rphy);
2296 break;
2297 }
Eric Moore547f9a22006-06-27 14:42:12 -06002298 mptsas_set_rphy(phy_info, rphy);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002299 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002300 case MPTSAS_ADD_RAID:
James Bottomleye8bf3942006-07-11 17:49:34 -04002301 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
2302 ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002303 if (sdev) {
2304 scsi_device_put(sdev);
2305 break;
2306 }
2307 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07002308 "attaching raid volume, channel %d, id %d\n",
James Bottomleye8bf3942006-07-11 17:49:34 -04002309 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
2310 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002311 mpt_findImVolumes(ioc);
2312 break;
2313 case MPTSAS_DEL_RAID:
James Bottomleye8bf3942006-07-11 17:49:34 -04002314 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
2315 ev->id, 0);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002316 if (!sdev)
2317 break;
2318 printk(MYIOC_s_INFO_FMT
Moore, Eric4b766472006-03-14 09:14:12 -07002319 "removing raid volume, channel %d, id %d\n",
James Bottomleye8bf3942006-07-11 17:49:34 -04002320 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
Eric Moore547f9a22006-06-27 14:42:12 -06002321 vdevice = sdev->hostdata;
2322 vdevice->vtarget->deleted = 1;
2323 mptsas_target_reset(ioc, vdevice->vtarget);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002324 scsi_remove_device(sdev);
2325 scsi_device_put(sdev);
2326 mpt_findImVolumes(ioc);
2327 break;
Moore, Ericbd23e942006-04-17 12:43:04 -06002328 case MPTSAS_IGNORE_EVENT:
2329 default:
2330 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002331 }
2332
Moore, Erice6b2d762006-03-14 09:14:24 -07002333 mutex_unlock(&ioc->sas_discovery_mutex);
Eric Moore547f9a22006-06-27 14:42:12 -06002334 kfree(ev);
2335
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002336}
2337
2338static void
Eric Moore547f9a22006-06-27 14:42:12 -06002339mptsas_send_sas_event(MPT_ADAPTER *ioc,
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002340 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
2341{
2342 struct mptsas_hotplug_event *ev;
2343 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
2344 __le64 sas_address;
2345
2346 if ((device_info &
2347 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
2348 MPI_SAS_DEVICE_INFO_STP_TARGET |
2349 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
2350 return;
2351
Moore, Eric4b766472006-03-14 09:14:12 -07002352 switch (sas_event_data->ReasonCode) {
2353 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
2354 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
Eric Moore547f9a22006-06-27 14:42:12 -06002355 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Eric4b766472006-03-14 09:14:12 -07002356 if (!ev) {
2357 printk(KERN_WARNING "mptsas: lost hotplug event\n");
2358 break;
2359 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002360
David Howellsc4028952006-11-22 14:57:56 +00002361 INIT_WORK(&ev->work, mptsas_hotplug_work);
Moore, Eric4b766472006-03-14 09:14:12 -07002362 ev->ioc = ioc;
2363 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
2364 ev->parent_handle =
2365 le16_to_cpu(sas_event_data->ParentDevHandle);
2366 ev->channel = sas_event_data->Bus;
2367 ev->id = sas_event_data->TargetID;
2368 ev->phy_id = sas_event_data->PhyNum;
2369 memcpy(&sas_address, &sas_event_data->SASAddress,
2370 sizeof(__le64));
2371 ev->sas_address = le64_to_cpu(sas_address);
2372 ev->device_info = device_info;
2373
2374 if (sas_event_data->ReasonCode &
2375 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
2376 ev->event_type = MPTSAS_ADD_DEVICE;
2377 else
2378 ev->event_type = MPTSAS_DEL_DEVICE;
2379 schedule_work(&ev->work);
2380 break;
2381 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
2382 /*
2383 * Persistent table is full.
2384 */
Eric Moore547f9a22006-06-27 14:42:12 -06002385 INIT_WORK(&ioc->sas_persist_task,
David Howellsc4028952006-11-22 14:57:56 +00002386 mptsas_persist_clear_table);
Eric Moore547f9a22006-06-27 14:42:12 -06002387 schedule_work(&ioc->sas_persist_task);
Moore, Eric4b766472006-03-14 09:14:12 -07002388 break;
2389 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
2390 /* TODO */
2391 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
2392 /* TODO */
2393 default:
2394 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002395 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002396}
2397
Moore, Ericc73787ee2006-01-26 16:20:06 -07002398static void
Eric Moore547f9a22006-06-27 14:42:12 -06002399mptsas_send_raid_event(MPT_ADAPTER *ioc,
Moore, Ericc73787ee2006-01-26 16:20:06 -07002400 EVENT_DATA_RAID *raid_event_data)
2401{
2402 struct mptsas_hotplug_event *ev;
Moore, Ericbd23e942006-04-17 12:43:04 -06002403 int status = le32_to_cpu(raid_event_data->SettingsStatus);
2404 int state = (status >> 8) & 0xff;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002405
2406 if (ioc->bus_type != SAS)
2407 return;
2408
Eric Moore547f9a22006-06-27 14:42:12 -06002409 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002410 if (!ev) {
2411 printk(KERN_WARNING "mptsas: lost hotplug event\n");
2412 return;
2413 }
2414
David Howellsc4028952006-11-22 14:57:56 +00002415 INIT_WORK(&ev->work, mptsas_hotplug_work);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002416 ev->ioc = ioc;
2417 ev->id = raid_event_data->VolumeID;
Moore, Ericbd23e942006-04-17 12:43:04 -06002418 ev->event_type = MPTSAS_IGNORE_EVENT;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002419
2420 switch (raid_event_data->ReasonCode) {
2421 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
2422 ev->event_type = MPTSAS_ADD_DEVICE;
2423 break;
2424 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
Moore, Ericf44e5462006-03-14 09:14:21 -07002425 ioc->raid_data.isRaid = 1;
2426 ev->phys_disk_num_valid = 1;
2427 ev->phys_disk_num = raid_event_data->PhysDiskNum;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002428 ev->event_type = MPTSAS_DEL_DEVICE;
2429 break;
Moore, Ericbd23e942006-04-17 12:43:04 -06002430 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
2431 switch (state) {
2432 case MPI_PD_STATE_ONLINE:
2433 ioc->raid_data.isRaid = 1;
2434 ev->phys_disk_num_valid = 1;
2435 ev->phys_disk_num = raid_event_data->PhysDiskNum;
2436 ev->event_type = MPTSAS_ADD_DEVICE;
2437 break;
2438 case MPI_PD_STATE_MISSING:
2439 case MPI_PD_STATE_NOT_COMPATIBLE:
2440 case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
2441 case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
2442 case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
2443 ev->event_type = MPTSAS_DEL_DEVICE;
2444 break;
2445 default:
2446 break;
2447 }
2448 break;
Moore, Ericc73787ee2006-01-26 16:20:06 -07002449 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
2450 ev->event_type = MPTSAS_DEL_RAID;
2451 break;
2452 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
2453 ev->event_type = MPTSAS_ADD_RAID;
2454 break;
2455 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
Moore, Ericbd23e942006-04-17 12:43:04 -06002456 switch (state) {
2457 case MPI_RAIDVOL0_STATUS_STATE_FAILED:
2458 case MPI_RAIDVOL0_STATUS_STATE_MISSING:
2459 ev->event_type = MPTSAS_DEL_RAID;
2460 break;
2461 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
2462 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
2463 ev->event_type = MPTSAS_ADD_RAID;
2464 break;
2465 default:
2466 break;
2467 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07002468 break;
2469 default:
2470 break;
2471 }
2472 schedule_work(&ev->work);
2473}
2474
Moore, Erice6b2d762006-03-14 09:14:24 -07002475static void
Eric Moore547f9a22006-06-27 14:42:12 -06002476mptsas_send_discovery_event(MPT_ADAPTER *ioc,
Moore, Erice6b2d762006-03-14 09:14:24 -07002477 EVENT_DATA_SAS_DISCOVERY *discovery_data)
2478{
2479 struct mptsas_discovery_event *ev;
2480
2481 /*
2482 * DiscoveryStatus
2483 *
2484 * This flag will be non-zero when firmware
2485 * kicks off discovery, and return to zero
2486 * once its completed.
2487 */
2488 if (discovery_data->DiscoveryStatus)
2489 return;
2490
Eric Moore547f9a22006-06-27 14:42:12 -06002491 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
Moore, Erice6b2d762006-03-14 09:14:24 -07002492 if (!ev)
2493 return;
David Howellsc4028952006-11-22 14:57:56 +00002494 INIT_WORK(&ev->work, mptsas_discovery_work);
Moore, Erice6b2d762006-03-14 09:14:24 -07002495 ev->ioc = ioc;
2496 schedule_work(&ev->work);
2497};
2498
2499
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002500static int
2501mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
2502{
Moore, Ericc73787ee2006-01-26 16:20:06 -07002503 int rc=1;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002504 u8 event = le32_to_cpu(reply->Event) & 0xFF;
2505
2506 if (!ioc->sh)
Moore, Ericc73787ee2006-01-26 16:20:06 -07002507 goto out;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002508
Moore, Erice6b2d762006-03-14 09:14:24 -07002509 /*
2510 * sas_discovery_ignore_events
2511 *
2512 * This flag is to prevent anymore processing of
2513 * sas events once mptsas_remove function is called.
2514 */
2515 if (ioc->sas_discovery_ignore_events) {
2516 rc = mptscsih_event_process(ioc, reply);
2517 goto out;
2518 }
2519
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002520 switch (event) {
2521 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
Eric Moore547f9a22006-06-27 14:42:12 -06002522 mptsas_send_sas_event(ioc,
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002523 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
Moore, Ericc73787ee2006-01-26 16:20:06 -07002524 break;
2525 case MPI_EVENT_INTEGRATED_RAID:
Eric Moore547f9a22006-06-27 14:42:12 -06002526 mptsas_send_raid_event(ioc,
Moore, Ericc73787ee2006-01-26 16:20:06 -07002527 (EVENT_DATA_RAID *)reply->Data);
2528 break;
Moore, Eric79de2782006-01-25 18:05:15 -07002529 case MPI_EVENT_PERSISTENT_TABLE_FULL:
Eric Moore547f9a22006-06-27 14:42:12 -06002530 INIT_WORK(&ioc->sas_persist_task,
David Howellsc4028952006-11-22 14:57:56 +00002531 mptsas_persist_clear_table);
Eric Moore547f9a22006-06-27 14:42:12 -06002532 schedule_work(&ioc->sas_persist_task);
Moore, Eric79de2782006-01-25 18:05:15 -07002533 break;
Moore, Eric4b766472006-03-14 09:14:12 -07002534 case MPI_EVENT_SAS_DISCOVERY:
Eric Moore547f9a22006-06-27 14:42:12 -06002535 mptsas_send_discovery_event(ioc,
Moore, Erice6b2d762006-03-14 09:14:24 -07002536 (EVENT_DATA_SAS_DISCOVERY *)reply->Data);
2537 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002538 default:
Moore, Ericc73787ee2006-01-26 16:20:06 -07002539 rc = mptscsih_event_process(ioc, reply);
2540 break;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002541 }
Moore, Ericc73787ee2006-01-26 16:20:06 -07002542 out:
2543
2544 return rc;
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002545}
2546
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002547static int
2548mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2549{
2550 struct Scsi_Host *sh;
2551 MPT_SCSI_HOST *hd;
2552 MPT_ADAPTER *ioc;
2553 unsigned long flags;
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002554 int ii;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002555 int numSGE = 0;
2556 int scale;
2557 int ioc_cap;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002558 int error=0;
2559 int r;
2560
2561 r = mpt_attach(pdev,id);
2562 if (r)
2563 return r;
2564
2565 ioc = pci_get_drvdata(pdev);
2566 ioc->DoneCtx = mptsasDoneCtx;
2567 ioc->TaskCtx = mptsasTaskCtx;
2568 ioc->InternalCtx = mptsasInternalCtx;
2569
2570 /* Added sanity check on readiness of the MPT adapter.
2571 */
2572 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
2573 printk(MYIOC_s_WARN_FMT
2574 "Skipping because it's not operational!\n",
2575 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002576 error = -ENODEV;
2577 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002578 }
2579
2580 if (!ioc->active) {
2581 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
2582 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002583 error = -ENODEV;
2584 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002585 }
2586
2587 /* Sanity check - ensure at least 1 port is INITIATOR capable
2588 */
2589 ioc_cap = 0;
2590 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
2591 if (ioc->pfacts[ii].ProtocolFlags &
2592 MPI_PORTFACTS_PROTOCOL_INITIATOR)
2593 ioc_cap++;
2594 }
2595
2596 if (!ioc_cap) {
2597 printk(MYIOC_s_WARN_FMT
2598 "Skipping ioc=%p because SCSI Initiator mode "
2599 "is NOT enabled!\n", ioc->name, ioc);
Moore, Eric Dean466544d2005-09-14 18:09:10 -06002600 return 0;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002601 }
2602
2603 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
2604 if (!sh) {
2605 printk(MYIOC_s_WARN_FMT
2606 "Unable to register controller with SCSI subsystem\n",
2607 ioc->name);
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002608 error = -1;
2609 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002610 }
2611
2612 spin_lock_irqsave(&ioc->FreeQlock, flags);
2613
2614 /* Attach the SCSI Host to the IOC structure
2615 */
2616 ioc->sh = sh;
2617
2618 sh->io_port = 0;
2619 sh->n_io_port = 0;
2620 sh->irq = 0;
2621
2622 /* set 16 byte cdb's */
2623 sh->max_cmd_len = 16;
2624
Eric Moore793955f2007-01-29 09:42:20 -07002625 sh->max_id = ioc->pfacts[0].PortSCSIID;
2626 sh->max_lun = max_lun;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002627
2628 sh->transportt = mptsas_transport_template;
2629
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002630 sh->this_id = ioc->pfacts[0].PortSCSIID;
2631
2632 /* Required entry.
2633 */
2634 sh->unique_id = ioc->id;
2635
2636 INIT_LIST_HEAD(&ioc->sas_topology);
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002637 mutex_init(&ioc->sas_topology_mutex);
Moore, Erice6b2d762006-03-14 09:14:24 -07002638 mutex_init(&ioc->sas_discovery_mutex);
Christoph Hellwigeeb846c2006-01-13 18:27:11 +01002639 mutex_init(&ioc->sas_mgmt.mutex);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002640 init_completion(&ioc->sas_mgmt.done);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002641
2642 /* Verify that we won't exceed the maximum
2643 * number of chain buffers
2644 * We can optimize: ZZ = req_sz/sizeof(SGE)
2645 * For 32bit SGE's:
2646 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
2647 * + (req_sz - 64)/sizeof(SGE)
2648 * A slightly different algorithm is required for
2649 * 64bit SGEs.
2650 */
2651 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
2652 if (sizeof(dma_addr_t) == sizeof(u64)) {
2653 numSGE = (scale - 1) *
2654 (ioc->facts.MaxChainDepth-1) + scale +
2655 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
2656 sizeof(u32));
2657 } else {
2658 numSGE = 1 + (scale - 1) *
2659 (ioc->facts.MaxChainDepth-1) + scale +
2660 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
2661 sizeof(u32));
2662 }
2663
2664 if (numSGE < sh->sg_tablesize) {
2665 /* Reset this value */
2666 dprintk((MYIOC_s_INFO_FMT
2667 "Resetting sg_tablesize to %d from %d\n",
2668 ioc->name, numSGE, sh->sg_tablesize));
2669 sh->sg_tablesize = numSGE;
2670 }
2671
2672 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
2673
2674 hd = (MPT_SCSI_HOST *) sh->hostdata;
2675 hd->ioc = ioc;
2676
2677 /* SCSI needs scsi_cmnd lookup table!
2678 * (with size equal to req_depth*PtrSz!)
2679 */
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002680 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
2681 if (!hd->ScsiLookup) {
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002682 error = -ENOMEM;
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002683 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002684 }
2685
Christoph Hellwig1ca00bb2006-01-13 18:27:50 +01002686 dprintk((MYIOC_s_INFO_FMT "ScsiLookup @ %p\n",
2687 ioc->name, hd->ScsiLookup));
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002688
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002689 /* Clear the TM flags
2690 */
2691 hd->tmPending = 0;
2692 hd->tmState = TM_STATE_NONE;
2693 hd->resetPending = 0;
2694 hd->abortSCpnt = NULL;
2695
2696 /* Clear the pointer used to store
2697 * single-threaded commands, i.e., those
2698 * issued during a bus scan, dv and
2699 * configuration pages.
2700 */
2701 hd->cmdPtr = NULL;
2702
2703 /* Initialize this SCSI Hosts' timers
2704 * To use, set the timer expires field
2705 * and add_timer
2706 */
2707 init_timer(&hd->timer);
2708 hd->timer.data = (unsigned long) hd;
2709 hd->timer.function = mptscsih_timer_expired;
2710
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002711 ioc->sas_data.ptClear = mpt_pt_clear;
2712
2713 if (ioc->sas_data.ptClear==1) {
2714 mptbase_sas_persist_operation(
2715 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
2716 }
2717
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002718 init_waitqueue_head(&hd->scandv_waitq);
2719 hd->scandv_wait_done = 0;
2720 hd->last_queue_full = 0;
2721
2722 error = scsi_add_host(sh, &ioc->pcidev->dev);
2723 if (error) {
2724 dprintk((KERN_ERR MYNAM
2725 "scsi_add_host failed\n"));
Moore, Eric Dean7acec1e2005-11-16 18:54:17 -07002726 goto out_mptsas_probe;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002727 }
2728
2729 mptsas_scan_sas_topology(ioc);
2730
2731 return 0;
2732
Eric Moore547f9a22006-06-27 14:42:12 -06002733 out_mptsas_probe:
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002734
2735 mptscsih_remove(pdev);
2736 return error;
2737}
2738
2739static void __devexit mptsas_remove(struct pci_dev *pdev)
2740{
2741 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
2742 struct mptsas_portinfo *p, *n;
Eric Moore547f9a22006-06-27 14:42:12 -06002743 int i;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002744
Moore, Erice6b2d762006-03-14 09:14:24 -07002745 ioc->sas_discovery_ignore_events=1;
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002746 sas_remove_host(ioc->sh);
2747
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002748 mutex_lock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002749 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
2750 list_del(&p->list);
Eric Moore547f9a22006-06-27 14:42:12 -06002751 for (i = 0 ; i < p->num_phys ; i++)
2752 mptsas_port_delete(p->phy_info[i].port_details);
2753 kfree(p->phy_info);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002754 kfree(p);
2755 }
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002756 mutex_unlock(&ioc->sas_topology_mutex);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002757
2758 mptscsih_remove(pdev);
2759}
2760
2761static struct pci_device_id mptsas_pci_table[] = {
Eric Moore87cf8982006-06-27 16:09:26 -06002762 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
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_SAS1068,
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_SAS1064E,
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_SAS1068E,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002769 PCI_ANY_ID, PCI_ANY_ID },
Eric Moore87cf8982006-06-27 16:09:26 -06002770 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002771 PCI_ANY_ID, PCI_ANY_ID },
2772 {0} /* Terminating entry */
2773};
2774MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
2775
2776
2777static struct pci_driver mptsas_driver = {
2778 .name = "mptsas",
2779 .id_table = mptsas_pci_table,
2780 .probe = mptsas_probe,
2781 .remove = __devexit_p(mptsas_remove),
2782 .shutdown = mptscsih_shutdown,
2783#ifdef CONFIG_PM
2784 .suspend = mptscsih_suspend,
2785 .resume = mptscsih_resume,
2786#endif
2787};
2788
2789static int __init
2790mptsas_init(void)
2791{
2792 show_mptmod_ver(my_NAME, my_VERSION);
2793
2794 mptsas_transport_template =
2795 sas_attach_transport(&mptsas_transport_functions);
2796 if (!mptsas_transport_template)
2797 return -ENODEV;
2798
2799 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
2800 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER);
2801 mptsasInternalCtx =
2802 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002803 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002804
Christoph Hellwig9a28f492006-01-13 18:04:41 +01002805 if (mpt_event_register(mptsasDoneCtx, mptsas_event_process) == 0) {
Moore, Eric3a892be2006-03-14 09:14:03 -07002806 devtverboseprintk((KERN_INFO MYNAM
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002807 ": Registered for IOC event notifications\n"));
2808 }
2809
2810 if (mpt_reset_register(mptsasDoneCtx, mptscsih_ioc_reset) == 0) {
2811 dprintk((KERN_INFO MYNAM
2812 ": Registered for IOC reset notifications\n"));
2813 }
2814
2815 return pci_register_driver(&mptsas_driver);
2816}
2817
2818static void __exit
2819mptsas_exit(void)
2820{
2821 pci_unregister_driver(&mptsas_driver);
2822 sas_release_transport(mptsas_transport_template);
2823
2824 mpt_reset_deregister(mptsasDoneCtx);
2825 mpt_event_deregister(mptsasDoneCtx);
2826
Christoph Hellwigda4fa652005-10-19 20:01:42 +02002827 mpt_deregister(mptsasMgmtCtx);
Christoph Hellwig0c33b272005-09-09 16:27:19 +02002828 mpt_deregister(mptsasInternalCtx);
2829 mpt_deregister(mptsasTaskCtx);
2830 mpt_deregister(mptsasDoneCtx);
2831}
2832
2833module_init(mptsas_init);
2834module_exit(mptsas_exit);