[SCSI] mpt fusion: Usage of high priority request FIFO to send task management commands
[deliverable/linux.git] / drivers / message / fusion / mptsas.c
CommitLineData
0c33b27d
CH
1/*
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 *
9f4203b3 6 * Copyright (c) 1999-2007 LSI Logic Corporation
16d20101 7 * (mailto:DL-MPTFusionLinux@lsi.com)
9f4203b3 8 * Copyright (c) 2005-2007 Dell
0c33b27d
CH
9 */
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>
cd354f1a 51#include <linux/jiffies.h>
0c33b27d 52#include <linux/workqueue.h>
547f9a21 53#include <linux/delay.h> /* for mdelay */
0c33b27d 54
547f9a21 55#include <scsi/scsi.h>
0c33b27d
CH
56#include <scsi/scsi_cmnd.h>
57#include <scsi/scsi_device.h>
58#include <scsi/scsi_host.h>
59#include <scsi/scsi_transport_sas.h>
547f9a21 60#include <scsi/scsi_dbg.h>
0c33b27d
CH
61
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
e8bf3941
JB
70/*
71 * Reserved channel for integrated raid
72 */
73#define MPTSAS_RAID_CHANNEL 1
74
0c33b27d
CH
75MODULE_AUTHOR(MODULEAUTHOR);
76MODULE_DESCRIPTION(my_NAME);
77MODULE_LICENSE("GPL");
9f4203b3 78MODULE_VERSION(my_VERSION);
0c33b27d 79
0c33b27d
CH
80static int mpt_pt_clear;
81module_param(mpt_pt_clear, int, 0);
82MODULE_PARM_DESC(mpt_pt_clear,
ba856d32 83 " Clear persistency table: enable=1 "
0c33b27d
CH
84 "(default=MPTSCSIH_PT_CLEAR=0)");
85
793955f5
EM
86/* 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
0c33b27d
CH
92static int mptsasDoneCtx = -1;
93static int mptsasTaskCtx = -1;
94static int mptsasInternalCtx = -1; /* Used only for internal commands */
da4fa655 95static int mptsasMgmtCtx = -1;
0c33b27d 96
b506ade9 97static void mptsas_hotplug_work(struct work_struct *work);
0c33b27d 98
df9e062a
EM
99struct mptsas_target_reset_event {
100 struct list_head list;
101 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE sas_event_data;
102 u8 target_reset_issued;
103};
104
9a28f49a
CH
105enum mptsas_hotplug_action {
106 MPTSAS_ADD_DEVICE,
107 MPTSAS_DEL_DEVICE,
c73787ee
ME
108 MPTSAS_ADD_RAID,
109 MPTSAS_DEL_RAID,
b506ade9 110 MPTSAS_ADD_INACTIVE_VOLUME,
bd23e94c 111 MPTSAS_IGNORE_EVENT,
9a28f49a
CH
112};
113
114struct mptsas_hotplug_event {
115 struct work_struct work;
116 MPT_ADAPTER *ioc;
117 enum mptsas_hotplug_action event_type;
118 u64 sas_address;
b506ade9
EM
119 u8 channel;
120 u8 id;
9a28f49a
CH
121 u32 device_info;
122 u16 handle;
123 u16 parent_handle;
124 u8 phy_id;
b506ade9
EM
125 u8 phys_disk_num_valid; /* hrc (hidden raid component) */
126 u8 phys_disk_num; /* hrc - unique index*/
127 u8 hidden_raid_component; /* hrc - don't expose*/
9a28f49a
CH
128};
129
e6b2d76a
ME
130struct mptsas_discovery_event {
131 struct work_struct work;
132 MPT_ADAPTER *ioc;
133};
134
0c33b27d
CH
135/*
136 * SAS topology structures
137 *
138 * The MPT Fusion firmware interface spreads information about the
139 * SAS topology over many manufacture pages, thus we need some data
140 * structure to collect it and process it for the SAS transport class.
141 */
142
143struct mptsas_devinfo {
144 u16 handle; /* unique id to address this device */
c73787ee 145 u16 handle_parent; /* unique id to address parent device */
e3094447
CH
146 u16 handle_enclosure; /* enclosure identifier of the enclosure */
147 u16 slot; /* physical slot in enclosure */
0c33b27d
CH
148 u8 phy_id; /* phy number of parent device */
149 u8 port_id; /* sas physical port this device
150 is assoc'd with */
9a28f49a 151 u8 id; /* logical target id of this device */
b506ade9 152 u32 phys_disk_num; /* phys disk id, for csmi-ioctls */
9a28f49a 153 u8 channel; /* logical bus number of this device */
0c33b27d
CH
154 u64 sas_address; /* WWN of this device,
155 SATA is assigned by HBA,expander */
156 u32 device_info; /* bitfield detailed info about this device */
157};
158
547f9a21
EM
159/*
160 * Specific details on ports, wide/narrow
161 */
162struct mptsas_portinfo_details{
547f9a21
EM
163 u16 num_phys; /* number of phys belong to this port */
164 u64 phy_bitmask; /* TODO, extend support for 255 phys */
165 struct sas_rphy *rphy; /* transport layer rphy object */
166 struct sas_port *port; /* transport layer port object */
167 struct scsi_target *starget;
168 struct mptsas_portinfo *port_info;
169};
170
0c33b27d 171struct mptsas_phyinfo {
2ecce492 172 u16 handle; /* unique id to address this */
0c33b27d 173 u8 phy_id; /* phy index */
547f9a21 174 u8 port_id; /* firmware port identifier */
0c33b27d
CH
175 u8 negotiated_link_rate; /* nego'd link rate for this phy */
176 u8 hw_link_rate; /* hardware max/min phys link rate */
177 u8 programmed_link_rate; /* programmed max/min phy link rate */
547f9a21 178 u8 sas_port_add_phy; /* flag to request sas_port_add_phy*/
0c33b27d
CH
179 struct mptsas_devinfo identify; /* point to phy device info */
180 struct mptsas_devinfo attached; /* point to attached device info */
547f9a21
EM
181 struct sas_phy *phy; /* transport layer phy object */
182 struct mptsas_portinfo *portinfo;
183 struct mptsas_portinfo_details * port_details;
0c33b27d
CH
184};
185
186struct mptsas_portinfo {
187 struct list_head list;
547f9a21 188 u16 num_phys; /* number of phys */
0c33b27d
CH
189 struct mptsas_phyinfo *phy_info;
190};
191
e3094447
CH
192struct mptsas_enclosure {
193 u64 enclosure_logical_id; /* The WWN for the enclosure */
194 u16 enclosure_handle; /* unique id to address this */
195 u16 flags; /* details enclosure management */
196 u16 num_slot; /* num slots */
197 u16 start_slot; /* first slot */
198 u8 start_id; /* starting logical target id */
199 u8 start_channel; /* starting logical channel id */
200 u8 sep_id; /* SEP device logical target id */
201 u8 sep_channel; /* SEP channel logical channel id */
202};
203
d6ecdd63
PS
204static void mptsas_print_phy_data(MPT_ADAPTER *ioc,
205 MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
206{
207 dsasprintk(ioc, printk(KERN_DEBUG "---- IO UNIT PAGE 0 ------------\n"));
208 dsasprintk(ioc, printk(KERN_DEBUG "Handle=0x%X\n",
209 le16_to_cpu(phy_data->AttachedDeviceHandle)));
210 dsasprintk(ioc, printk(KERN_DEBUG "Controller Handle=0x%X\n",
211 le16_to_cpu(phy_data->ControllerDevHandle)));
212 dsasprintk(ioc, printk(KERN_DEBUG "Port=0x%X\n", phy_data->Port));
213 dsasprintk(ioc, printk(KERN_DEBUG "Port Flags=0x%X\n", phy_data->PortFlags));
214 dsasprintk(ioc, printk(KERN_DEBUG "PHY Flags=0x%X\n", phy_data->PhyFlags));
215 dsasprintk(ioc, printk(KERN_DEBUG "Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate));
216 dsasprintk(ioc, printk(KERN_DEBUG "Controller PHY Device Info=0x%X\n",
217 le32_to_cpu(phy_data->ControllerPhyDeviceInfo)));
218 dsasprintk(ioc, printk(KERN_DEBUG "DiscoveryStatus=0x%X\n\n",
219 le32_to_cpu(phy_data->DiscoveryStatus)));
b5141128
CH
220}
221
d6ecdd63 222static void mptsas_print_phy_pg0(MPT_ADAPTER *ioc, SasPhyPage0_t *pg0)
b5141128
CH
223{
224 __le64 sas_address;
225
226 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
227
d6ecdd63
PS
228 dsasprintk(ioc, printk(KERN_DEBUG "---- SAS PHY PAGE 0 ------------\n"));
229 dsasprintk(ioc, printk(KERN_DEBUG "Attached Device Handle=0x%X\n",
230 le16_to_cpu(pg0->AttachedDevHandle)));
231 dsasprintk(ioc, printk(KERN_DEBUG "SAS Address=0x%llX\n",
232 (unsigned long long)le64_to_cpu(sas_address)));
233 dsasprintk(ioc, printk(KERN_DEBUG "Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier));
234 dsasprintk(ioc, printk(KERN_DEBUG "Attached Device Info=0x%X\n",
235 le32_to_cpu(pg0->AttachedDeviceInfo)));
236 dsasprintk(ioc, printk(KERN_DEBUG "Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate));
237 dsasprintk(ioc, printk(KERN_DEBUG "Change Count=0x%X\n", pg0->ChangeCount));
238 dsasprintk(ioc, printk(KERN_DEBUG "PHY Info=0x%X\n\n", le32_to_cpu(pg0->PhyInfo)));
b5141128
CH
239}
240
d6ecdd63 241static void mptsas_print_phy_pg1(MPT_ADAPTER *ioc, SasPhyPage1_t *pg1)
b5141128 242{
d6ecdd63
PS
243 dsasprintk(ioc, printk(KERN_DEBUG "---- SAS PHY PAGE 1 ------------\n"));
244 dsasprintk(ioc, printk(KERN_DEBUG "Invalid Dword Count=0x%x\n", pg1->InvalidDwordCount));
245 dsasprintk(ioc, printk(KERN_DEBUG "Running Disparity Error Count=0x%x\n",
246 pg1->RunningDisparityErrorCount));
247 dsasprintk(ioc, printk(KERN_DEBUG "Loss Dword Synch Count=0x%x\n", pg1->LossDwordSynchCount));
248 dsasprintk(ioc, printk(KERN_DEBUG "PHY Reset Problem Count=0x%x\n\n", pg1->PhyResetProblemCount));
b5141128
CH
249}
250
d6ecdd63 251static void mptsas_print_device_pg0(MPT_ADAPTER *ioc, SasDevicePage0_t *pg0)
b5141128
CH
252{
253 __le64 sas_address;
254
255 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
256
d6ecdd63
PS
257 dsasprintk(ioc, printk(KERN_DEBUG "---- SAS DEVICE PAGE 0 ---------\n"));
258 dsasprintk(ioc, printk(KERN_DEBUG "Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle)));
259 dsasprintk(ioc, printk(KERN_DEBUG "Parent Handle=0x%X\n" ,le16_to_cpu(pg0->ParentDevHandle)));
260 dsasprintk(ioc, printk(KERN_DEBUG "Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle)));
261 dsasprintk(ioc, printk(KERN_DEBUG "Slot=0x%X\n", le16_to_cpu(pg0->Slot)));
262 dsasprintk(ioc, printk(KERN_DEBUG "SAS Address=0x%llX\n", (unsigned long long)
263 le64_to_cpu(sas_address)));
264 dsasprintk(ioc, printk(KERN_DEBUG "Target ID=0x%X\n", pg0->TargetID));
265 dsasprintk(ioc, printk(KERN_DEBUG "Bus=0x%X\n", pg0->Bus));
f9a2d2e0
CH
266 /* The PhyNum field specifies the PHY number of the parent
267 * device this device is linked to
268 */
d6ecdd63
PS
269 dsasprintk(ioc, printk(KERN_DEBUG "Parent Phy Num=0x%X\n", pg0->PhyNum));
270 dsasprintk(ioc, printk(KERN_DEBUG "Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus)));
271 dsasprintk(ioc, printk(KERN_DEBUG "Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo)));
272 dsasprintk(ioc, printk(KERN_DEBUG "Flags=0x%X\n", le16_to_cpu(pg0->Flags)));
273 dsasprintk(ioc, printk(KERN_DEBUG "Physical Port=0x%X\n\n", pg0->PhysicalPort));
b5141128
CH
274}
275
d6ecdd63
PS
276static void mptsas_print_expander_pg1(MPT_ADAPTER *ioc, SasExpanderPage1_t *pg1)
277{
278 dsasprintk(ioc, printk(KERN_DEBUG "---- SAS EXPANDER PAGE 1 ------------\n"));
279 dsasprintk(ioc, printk(KERN_DEBUG "Physical Port=0x%X\n", pg1->PhysicalPort));
280 dsasprintk(ioc, printk(KERN_DEBUG "PHY Identifier=0x%X\n", pg1->PhyIdentifier));
281 dsasprintk(ioc, printk(KERN_DEBUG "Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate));
282 dsasprintk(ioc, printk(KERN_DEBUG "Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate));
283 dsasprintk(ioc, printk(KERN_DEBUG "Hardware Link Rate=0x%X\n", pg1->HwLinkRate));
284 dsasprintk(ioc, printk(KERN_DEBUG "Owner Device Handle=0x%X\n",
285 le16_to_cpu(pg1->OwnerDevHandle)));
286 dsasprintk(ioc, printk(KERN_DEBUG "Attached Device Handle=0x%X\n\n",
287 le16_to_cpu(pg1->AttachedDevHandle)));
b5141128 288}
b5141128 289
e3094447
CH
290static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
291{
292 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
293 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
294}
295
296static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
297{
298 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
299 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
300}
301
e6b2d76a
ME
302/*
303 * mptsas_find_portinfo_by_handle
304 *
305 * This function should be called with the sas_topology_mutex already held
306 */
307static struct mptsas_portinfo *
308mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
309{
310 struct mptsas_portinfo *port_info, *rc=NULL;
311 int i;
312
313 list_for_each_entry(port_info, &ioc->sas_topology, list)
314 for (i = 0; i < port_info->num_phys; i++)
315 if (port_info->phy_info[i].identify.handle == handle) {
316 rc = port_info;
317 goto out;
318 }
319 out:
320 return rc;
321}
322
bd23e94c
ME
323/*
324 * Returns true if there is a scsi end device
325 */
326static inline int
327mptsas_is_end_device(struct mptsas_devinfo * attached)
328{
547f9a21 329 if ((attached->sas_address) &&
bd23e94c
ME
330 (attached->device_info &
331 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
332 ((attached->device_info &
333 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
334 (attached->device_info &
335 MPI_SAS_DEVICE_INFO_STP_TARGET) |
336 (attached->device_info &
337 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
338 return 1;
339 else
340 return 0;
341}
342
547f9a21 343/* no mutex */
376ac830 344static void
d6ecdd63 345mptsas_port_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo_details * port_details)
547f9a21
EM
346{
347 struct mptsas_portinfo *port_info;
348 struct mptsas_phyinfo *phy_info;
349 u8 i;
350
351 if (!port_details)
352 return;
353
354 port_info = port_details->port_info;
355 phy_info = port_info->phy_info;
356
d6ecdd63 357 dsaswideprintk(ioc, printk(KERN_DEBUG "%s: [%p]: num_phys=%02d "
f99be43b
EM
358 "bitmask=0x%016llX\n", __FUNCTION__, port_details,
359 port_details->num_phys, (unsigned long long)
360 port_details->phy_bitmask));
547f9a21
EM
361
362 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
363 if(phy_info->port_details != port_details)
364 continue;
365 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
366 phy_info->port_details = NULL;
367 }
368 kfree(port_details);
369}
370
371static inline struct sas_rphy *
372mptsas_get_rphy(struct mptsas_phyinfo *phy_info)
373{
374 if (phy_info->port_details)
375 return phy_info->port_details->rphy;
376 else
377 return NULL;
378}
379
380static inline void
d6ecdd63 381mptsas_set_rphy(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
547f9a21
EM
382{
383 if (phy_info->port_details) {
384 phy_info->port_details->rphy = rphy;
d6ecdd63 385 dsaswideprintk(ioc, printk(KERN_DEBUG "sas_rphy_add: rphy=%p\n", rphy));
547f9a21
EM
386 }
387
547f9a21 388 if (rphy) {
d6ecdd63
PS
389 dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
390 &rphy->dev, "add:"));
391 dsaswideprintk(ioc, printk(KERN_DEBUG "rphy=%p release=%p\n",
392 rphy, rphy->dev.release));
547f9a21 393 }
547f9a21
EM
394}
395
396static inline struct sas_port *
397mptsas_get_port(struct mptsas_phyinfo *phy_info)
398{
399 if (phy_info->port_details)
400 return phy_info->port_details->port;
401 else
402 return NULL;
403}
404
405static inline void
d6ecdd63 406mptsas_set_port(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_port *port)
547f9a21
EM
407{
408 if (phy_info->port_details)
409 phy_info->port_details->port = port;
410
547f9a21 411 if (port) {
d6ecdd63
PS
412 dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
413 &port->dev, "add:"));
414 dsaswideprintk(ioc, printk(KERN_DEBUG "port=%p release=%p\n",
415 port, port->dev.release));
547f9a21 416 }
547f9a21
EM
417}
418
419static inline struct scsi_target *
420mptsas_get_starget(struct mptsas_phyinfo *phy_info)
421{
422 if (phy_info->port_details)
423 return phy_info->port_details->starget;
424 else
425 return NULL;
426}
427
428static inline void
429mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target *
430starget)
431{
432 if (phy_info->port_details)
433 phy_info->port_details->starget = starget;
434}
435
436
437/*
438 * mptsas_setup_wide_ports
439 *
440 * Updates for new and existing narrow/wide port configuration
441 * in the sas_topology
442 */
376ac830 443static void
547f9a21
EM
444mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
445{
446 struct mptsas_portinfo_details * port_details;
447 struct mptsas_phyinfo *phy_info, *phy_info_cmp;
448 u64 sas_address;
449 int i, j;
450
451 mutex_lock(&ioc->sas_topology_mutex);
452
453 phy_info = port_info->phy_info;
454 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
455 if (phy_info->attached.handle)
456 continue;
457 port_details = phy_info->port_details;
458 if (!port_details)
459 continue;
460 if (port_details->num_phys < 2)
461 continue;
462 /*
463 * Removing a phy from a port, letting the last
464 * phy be removed by firmware events.
465 */
d6ecdd63 466 dsaswideprintk(ioc, printk(KERN_DEBUG
dc22f16d
EM
467 "%s: [%p]: deleting phy = %d\n",
468 __FUNCTION__, port_details, i));
547f9a21
EM
469 port_details->num_phys--;
470 port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
471 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
472 sas_port_delete_phy(port_details->port, phy_info->phy);
473 phy_info->port_details = NULL;
474 }
475
476 /*
477 * Populate and refresh the tree
478 */
479 phy_info = port_info->phy_info;
480 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
481 sas_address = phy_info->attached.sas_address;
d6ecdd63 482 dsaswideprintk(ioc, printk(KERN_DEBUG "phy_id=%d sas_address=0x%018llX\n",
f99be43b 483 i, (unsigned long long)sas_address));
547f9a21
EM
484 if (!sas_address)
485 continue;
486 port_details = phy_info->port_details;
487 /*
488 * Forming a port
489 */
490 if (!port_details) {
491 port_details = kzalloc(sizeof(*port_details),
492 GFP_KERNEL);
493 if (!port_details)
494 goto out;
495 port_details->num_phys = 1;
496 port_details->port_info = port_info;
547f9a21
EM
497 if (phy_info->phy_id < 64 )
498 port_details->phy_bitmask |=
499 (1 << phy_info->phy_id);
500 phy_info->sas_port_add_phy=1;
d6ecdd63 501 dsaswideprintk(ioc, printk(KERN_DEBUG "\t\tForming port\n\t\t"
f99be43b
EM
502 "phy_id=%d sas_address=0x%018llX\n",
503 i, (unsigned long long)sas_address));
547f9a21
EM
504 phy_info->port_details = port_details;
505 }
506
507 if (i == port_info->num_phys - 1)
508 continue;
509 phy_info_cmp = &port_info->phy_info[i + 1];
510 for (j = i + 1 ; j < port_info->num_phys ; j++,
511 phy_info_cmp++) {
512 if (!phy_info_cmp->attached.sas_address)
513 continue;
514 if (sas_address != phy_info_cmp->attached.sas_address)
515 continue;
516 if (phy_info_cmp->port_details == port_details )
517 continue;
d6ecdd63 518 dsaswideprintk(ioc, printk(KERN_DEBUG
f99be43b
EM
519 "\t\tphy_id=%d sas_address=0x%018llX\n",
520 j, (unsigned long long)
521 phy_info_cmp->attached.sas_address));
547f9a21
EM
522 if (phy_info_cmp->port_details) {
523 port_details->rphy =
524 mptsas_get_rphy(phy_info_cmp);
525 port_details->port =
526 mptsas_get_port(phy_info_cmp);
527 port_details->starget =
528 mptsas_get_starget(phy_info_cmp);
547f9a21
EM
529 port_details->num_phys =
530 phy_info_cmp->port_details->num_phys;
547f9a21
EM
531 if (!phy_info_cmp->port_details->num_phys)
532 kfree(phy_info_cmp->port_details);
533 } else
534 phy_info_cmp->sas_port_add_phy=1;
535 /*
536 * Adding a phy to a port
537 */
538 phy_info_cmp->port_details = port_details;
539 if (phy_info_cmp->phy_id < 64 )
540 port_details->phy_bitmask |=
541 (1 << phy_info_cmp->phy_id);
542 port_details->num_phys++;
543 }
544 }
545
546 out:
547
547f9a21
EM
548 for (i = 0; i < port_info->num_phys; i++) {
549 port_details = port_info->phy_info[i].port_details;
550 if (!port_details)
551 continue;
d6ecdd63 552 dsaswideprintk(ioc, printk(KERN_DEBUG
f99be43b
EM
553 "%s: [%p]: phy_id=%02d num_phys=%02d "
554 "bitmask=0x%016llX\n", __FUNCTION__,
555 port_details, i, port_details->num_phys,
556 (unsigned long long)port_details->phy_bitmask));
d6ecdd63 557 dsaswideprintk(ioc, printk(KERN_DEBUG"\t\tport = %p rphy=%p\n",
547f9a21
EM
558 port_details->port, port_details->rphy));
559 }
d6ecdd63 560 dsaswideprintk(ioc, printk(KERN_DEBUG"\n"));
547f9a21
EM
561 mutex_unlock(&ioc->sas_topology_mutex);
562}
563
df9e062a
EM
564/**
565 * csmisas_find_vtarget
566 *
567 * @ioc
568 * @volume_id
569 * @volume_bus
570 *
571 **/
572static VirtTarget *
573mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
574{
575 struct scsi_device *sdev;
576 VirtDevice *vdev;
577 VirtTarget *vtarget = NULL;
578
579 shost_for_each_device(sdev, ioc->sh) {
580 if ((vdev = sdev->hostdata) == NULL)
581 continue;
582 if (vdev->vtarget->id == id &&
583 vdev->vtarget->channel == channel)
584 vtarget = vdev->vtarget;
585 }
586 return vtarget;
587}
588
589/**
590 * mptsas_target_reset
591 *
592 * Issues TARGET_RESET to end device using handshaking method
593 *
594 * @ioc
595 * @channel
596 * @id
597 *
598 * Returns (1) success
599 * (0) failure
600 *
601 **/
602static int
603mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
604{
605 MPT_FRAME_HDR *mf;
606 SCSITaskMgmt_t *pScsiTm;
607
608 if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) {
d6ecdd63 609 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, no msg frames @%d!!\n",
df9e062a
EM
610 ioc->name,__FUNCTION__, __LINE__));
611 return 0;
612 }
613
614 /* Format the Request
615 */
616 pScsiTm = (SCSITaskMgmt_t *) mf;
617 memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t));
618 pScsiTm->TargetID = id;
619 pScsiTm->Bus = channel;
620 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
621 pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
622 pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
623
d6ecdd63 624 DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf);
df9e062a 625
7a195f46 626 mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf);
df9e062a
EM
627
628 return 1;
629}
630
631/**
632 * mptsas_target_reset_queue
633 *
634 * Receive request for TARGET_RESET after recieving an firmware
635 * event NOT_RESPONDING_EVENT, then put command in link list
636 * and queue if task_queue already in use.
637 *
638 * @ioc
639 * @sas_event_data
640 *
641 **/
547f9a21 642static void
df9e062a
EM
643mptsas_target_reset_queue(MPT_ADAPTER *ioc,
644 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
547f9a21 645{
df9e062a
EM
646 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
647 VirtTarget *vtarget = NULL;
648 struct mptsas_target_reset_event *target_reset_list;
649 u8 id, channel;
547f9a21 650
df9e062a
EM
651 id = sas_event_data->TargetID;
652 channel = sas_event_data->Bus;
653
654 if (!(vtarget = mptsas_find_vtarget(ioc, channel, id)))
655 return;
656
657 vtarget->deleted = 1; /* block IO */
658
659 target_reset_list = kzalloc(sizeof(*target_reset_list),
660 GFP_ATOMIC);
661 if (!target_reset_list) {
d6ecdd63 662 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
df9e062a
EM
663 ioc->name,__FUNCTION__, __LINE__));
664 return;
665 }
666
667 memcpy(&target_reset_list->sas_event_data, sas_event_data,
668 sizeof(*sas_event_data));
669 list_add_tail(&target_reset_list->list, &hd->target_reset_list);
670
671 if (hd->resetPending)
672 return;
673
674 if (mptsas_target_reset(ioc, channel, id)) {
675 target_reset_list->target_reset_issued = 1;
676 hd->resetPending = 1;
677 }
678}
679
680/**
681 * mptsas_dev_reset_complete
682 *
683 * Completion for TARGET_RESET after NOT_RESPONDING_EVENT,
684 * enable work queue to finish off removing device from upper layers.
685 * then send next TARGET_RESET in the queue.
686 *
687 * @ioc
688 *
689 **/
690static void
691mptsas_dev_reset_complete(MPT_ADAPTER *ioc)
692{
693 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
694 struct list_head *head = &hd->target_reset_list;
695 struct mptsas_target_reset_event *target_reset_list;
696 struct mptsas_hotplug_event *ev;
697 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
698 u8 id, channel;
699 __le64 sas_address;
700
701 if (list_empty(head))
702 return;
703
704 target_reset_list = list_entry(head->next, struct mptsas_target_reset_event, list);
705
706 sas_event_data = &target_reset_list->sas_event_data;
707 id = sas_event_data->TargetID;
708 channel = sas_event_data->Bus;
709 hd->resetPending = 0;
710
711 /*
712 * retry target reset
713 */
714 if (!target_reset_list->target_reset_issued) {
715 if (mptsas_target_reset(ioc, channel, id)) {
716 target_reset_list->target_reset_issued = 1;
717 hd->resetPending = 1;
718 }
719 return;
720 }
721
722 /*
723 * enable work queue to remove device from upper layers
724 */
725 list_del(&target_reset_list->list);
726
727 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
728 if (!ev) {
d6ecdd63 729 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, failed to allocate mem @%d..!!\n",
df9e062a
EM
730 ioc->name,__FUNCTION__, __LINE__));
731 return;
732 }
733
734 INIT_WORK(&ev->work, mptsas_hotplug_work);
735 ev->ioc = ioc;
736 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
737 ev->parent_handle =
738 le16_to_cpu(sas_event_data->ParentDevHandle);
739 ev->channel = channel;
740 ev->id =id;
741 ev->phy_id = sas_event_data->PhyNum;
742 memcpy(&sas_address, &sas_event_data->SASAddress,
743 sizeof(__le64));
744 ev->sas_address = le64_to_cpu(sas_address);
745 ev->device_info = le32_to_cpu(sas_event_data->DeviceInfo);
746 ev->event_type = MPTSAS_DEL_DEVICE;
747 schedule_work(&ev->work);
748 kfree(target_reset_list);
749
750 /*
751 * issue target reset to next device in the queue
752 */
753
754 head = &hd->target_reset_list;
755 if (list_empty(head))
756 return;
757
758 target_reset_list = list_entry(head->next, struct mptsas_target_reset_event,
759 list);
760
761 sas_event_data = &target_reset_list->sas_event_data;
762 id = sas_event_data->TargetID;
763 channel = sas_event_data->Bus;
764
765 if (mptsas_target_reset(ioc, channel, id)) {
766 target_reset_list->target_reset_issued = 1;
767 hd->resetPending = 1;
768 }
769}
770
771/**
772 * mptsas_taskmgmt_complete
773 *
774 * @ioc
775 * @mf
776 * @mr
777 *
778 **/
779static int
780mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
781{
782 mptsas_dev_reset_complete(ioc);
783 return mptscsih_taskmgmt_complete(ioc, mf, mr);
784}
785
786/**
787 * mptscsih_ioc_reset
788 *
789 * @ioc
790 * @reset_phase
791 *
792 **/
793static int
794mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
795{
ba76ef24 796 MPT_SCSI_HOST *hd;
df9e062a
EM
797 struct mptsas_target_reset_event *target_reset_list, *n;
798 int rc;
799
800 rc = mptscsih_ioc_reset(ioc, reset_phase);
801
802 if (ioc->bus_type != SAS)
803 goto out;
804
805 if (reset_phase != MPT_IOC_POST_RESET)
806 goto out;
807
ba76ef24
JL
808 if (!ioc->sh || !ioc->sh->hostdata)
809 goto out;
810 hd = (MPT_SCSI_HOST *)ioc->sh->hostdata;
811 if (!hd->ioc)
df9e062a
EM
812 goto out;
813
814 if (list_empty(&hd->target_reset_list))
815 goto out;
816
817 /* flush the target_reset_list */
818 list_for_each_entry_safe(target_reset_list, n,
819 &hd->target_reset_list, list) {
820 list_del(&target_reset_list->list);
821 kfree(target_reset_list);
547f9a21 822 }
df9e062a
EM
823
824 out:
825 return rc;
547f9a21
EM
826}
827
e3094447 828static int
52435430 829mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
e3094447
CH
830 u32 form, u32 form_specific)
831{
832 ConfigExtendedPageHeader_t hdr;
833 CONFIGPARMS cfg;
834 SasEnclosurePage0_t *buffer;
835 dma_addr_t dma_handle;
836 int error;
837 __le64 le_identifier;
838
839 memset(&hdr, 0, sizeof(hdr));
840 hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
841 hdr.PageNumber = 0;
842 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
843 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
844
845 cfg.cfghdr.ehdr = &hdr;
846 cfg.physAddr = -1;
847 cfg.pageAddr = form + form_specific;
848 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
849 cfg.dir = 0; /* read */
850 cfg.timeout = 10;
851
852 error = mpt_config(ioc, &cfg);
853 if (error)
854 goto out;
855 if (!hdr.ExtPageLength) {
856 error = -ENXIO;
857 goto out;
858 }
859
860 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
861 &dma_handle);
862 if (!buffer) {
863 error = -ENOMEM;
864 goto out;
865 }
866
867 cfg.physAddr = dma_handle;
868 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
869
870 error = mpt_config(ioc, &cfg);
871 if (error)
872 goto out_free_consistent;
873
874 /* save config data */
875 memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
876 enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
877 enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
878 enclosure->flags = le16_to_cpu(buffer->Flags);
879 enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
880 enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
881 enclosure->start_id = buffer->StartTargetID;
882 enclosure->start_channel = buffer->StartBus;
883 enclosure->sep_id = buffer->SEPTargetID;
884 enclosure->sep_channel = buffer->SEPBus;
885
886 out_free_consistent:
887 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
888 buffer, dma_handle);
889 out:
890 return error;
891}
b5141128 892
f013db32
JB
893static int
894mptsas_slave_configure(struct scsi_device *sdev)
895{
3c0c25b9 896
e8bf3941
JB
897 if (sdev->channel == MPTSAS_RAID_CHANNEL)
898 goto out;
899
900 sas_read_port_mode_page(sdev);
f013db32 901
e8bf3941 902 out:
f013db32
JB
903 return mptscsih_slave_configure(sdev);
904}
905
547f9a21
EM
906static int
907mptsas_target_alloc(struct scsi_target *starget)
908{
909 struct Scsi_Host *host = dev_to_shost(&starget->dev);
910 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
911 VirtTarget *vtarget;
793955f5 912 u8 id, channel;
547f9a21
EM
913 struct sas_rphy *rphy;
914 struct mptsas_portinfo *p;
915 int i;
916
917 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
918 if (!vtarget)
919 return -ENOMEM;
920
921 vtarget->starget = starget;
922 vtarget->ioc_id = hd->ioc->id;
793955f5
EM
923 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
924 id = starget->id;
547f9a21
EM
925 channel = 0;
926
793955f5
EM
927 /*
928 * RAID volumes placed beyond the last expected port.
929 */
930 if (starget->channel == MPTSAS_RAID_CHANNEL) {
931 for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
932 if (id == hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID)
933 channel = hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus;
547f9a21 934 goto out;
793955f5 935 }
547f9a21
EM
936
937 rphy = dev_to_rphy(starget->dev.parent);
938 mutex_lock(&hd->ioc->sas_topology_mutex);
939 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
940 for (i = 0; i < p->num_phys; i++) {
941 if (p->phy_info[i].attached.sas_address !=
942 rphy->identify.sas_address)
943 continue;
793955f5 944 id = p->phy_info[i].attached.id;
547f9a21
EM
945 channel = p->phy_info[i].attached.channel;
946 mptsas_set_starget(&p->phy_info[i], starget);
947
948 /*
949 * Exposing hidden raid components
950 */
793955f5
EM
951 if (mptscsih_is_phys_disk(hd->ioc, channel, id)) {
952 id = mptscsih_raid_id_to_num(hd->ioc,
953 channel, id);
547f9a21
EM
954 vtarget->tflags |=
955 MPT_TARGET_FLAGS_RAID_COMPONENT;
b506ade9 956 p->phy_info[i].attached.phys_disk_num = id;
547f9a21
EM
957 }
958 mutex_unlock(&hd->ioc->sas_topology_mutex);
959 goto out;
960 }
961 }
962 mutex_unlock(&hd->ioc->sas_topology_mutex);
963
964 kfree(vtarget);
965 return -ENXIO;
966
967 out:
793955f5
EM
968 vtarget->id = id;
969 vtarget->channel = channel;
547f9a21
EM
970 starget->hostdata = vtarget;
971 return 0;
972}
973
974static void
975mptsas_target_destroy(struct scsi_target *starget)
976{
977 struct Scsi_Host *host = dev_to_shost(&starget->dev);
978 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
979 struct sas_rphy *rphy;
980 struct mptsas_portinfo *p;
981 int i;
982
983 if (!starget->hostdata)
984 return;
985
e8bf3941 986 if (starget->channel == MPTSAS_RAID_CHANNEL)
547f9a21
EM
987 goto out;
988
989 rphy = dev_to_rphy(starget->dev.parent);
990 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
991 for (i = 0; i < p->num_phys; i++) {
992 if (p->phy_info[i].attached.sas_address !=
993 rphy->identify.sas_address)
994 continue;
995 mptsas_set_starget(&p->phy_info[i], NULL);
996 goto out;
997 }
998 }
999
1000 out:
1001 kfree(starget->hostdata);
1002 starget->hostdata = NULL;
1003}
1004
1005
0c33b27d 1006static int
c7c82987 1007mptsas_slave_alloc(struct scsi_device *sdev)
0c33b27d 1008{
c7c82987 1009 struct Scsi_Host *host = sdev->host;
0c33b27d
CH
1010 MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata;
1011 struct sas_rphy *rphy;
1012 struct mptsas_portinfo *p;
1013 VirtDevice *vdev;
c7c82987 1014 struct scsi_target *starget;
547f9a21 1015 int i;
0c33b27d 1016
1ca00bb7 1017 vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
0c33b27d 1018 if (!vdev) {
547f9a21 1019 printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
0c33b27d
CH
1020 hd->ioc->name, sizeof(VirtDevice));
1021 return -ENOMEM;
1022 }
c7c82987 1023 starget = scsi_target(sdev);
547f9a21 1024 vdev->vtarget = starget->hostdata;
0c33b27d 1025
e8bf3941 1026 if (sdev->channel == MPTSAS_RAID_CHANNEL)
816aa907 1027 goto out;
816aa907 1028
c7c82987 1029 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
9a28f49a 1030 mutex_lock(&hd->ioc->sas_topology_mutex);
0c33b27d
CH
1031 list_for_each_entry(p, &hd->ioc->sas_topology, list) {
1032 for (i = 0; i < p->num_phys; i++) {
547f9a21
EM
1033 if (p->phy_info[i].attached.sas_address !=
1034 rphy->identify.sas_address)
1035 continue;
1036 vdev->lun = sdev->lun;
1037 /*
1038 * Exposing hidden raid components
1039 */
1040 if (mptscsih_is_phys_disk(hd->ioc,
793955f5
EM
1041 p->phy_info[i].attached.channel,
1042 p->phy_info[i].attached.id))
547f9a21
EM
1043 sdev->no_uld_attach = 1;
1044 mutex_unlock(&hd->ioc->sas_topology_mutex);
1045 goto out;
0c33b27d
CH
1046 }
1047 }
9a28f49a 1048 mutex_unlock(&hd->ioc->sas_topology_mutex);
0c33b27d 1049
0c33b27d 1050 kfree(vdev);
23f236ed 1051 return -ENXIO;
0c33b27d
CH
1052
1053 out:
547f9a21
EM
1054 vdev->vtarget->num_luns++;
1055 sdev->hostdata = vdev;
0c33b27d
CH
1056 return 0;
1057}
1058
547f9a21
EM
1059static int
1060mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
9a28f49a 1061{
547f9a21 1062 VirtDevice *vdev = SCpnt->device->hostdata;
7d3eecf7 1063
793955f5 1064 if (!vdev || !vdev->vtarget || vdev->vtarget->deleted) {
547f9a21
EM
1065 SCpnt->result = DID_NO_CONNECT << 16;
1066 done(SCpnt);
1067 return 0;
7d3eecf7 1068 }
547f9a21 1069
793955f5
EM
1070// scsi_print_command(SCpnt);
1071
547f9a21 1072 return mptscsih_qcmd(SCpnt,done);
9a28f49a
CH
1073}
1074
547f9a21 1075
0c33b27d 1076static struct scsi_host_template mptsas_driver_template = {
f78496da 1077 .module = THIS_MODULE,
0c33b27d
CH
1078 .proc_name = "mptsas",
1079 .proc_info = mptscsih_proc_info,
1080 .name = "MPT SPI Host",
1081 .info = mptscsih_info,
547f9a21
EM
1082 .queuecommand = mptsas_qcmd,
1083 .target_alloc = mptsas_target_alloc,
0c33b27d 1084 .slave_alloc = mptsas_slave_alloc,
f013db32 1085 .slave_configure = mptsas_slave_configure,
547f9a21
EM
1086 .target_destroy = mptsas_target_destroy,
1087 .slave_destroy = mptscsih_slave_destroy,
0c33b27d
CH
1088 .change_queue_depth = mptscsih_change_queue_depth,
1089 .eh_abort_handler = mptscsih_abort,
1090 .eh_device_reset_handler = mptscsih_dev_reset,
1091 .eh_bus_reset_handler = mptscsih_bus_reset,
1092 .eh_host_reset_handler = mptscsih_host_reset,
1093 .bios_param = mptscsih_bios_param,
1094 .can_queue = MPT_FC_CAN_QUEUE,
1095 .this_id = -1,
1096 .sg_tablesize = MPT_SCSI_SG_DEPTH,
1097 .max_sectors = 8192,
1098 .cmd_per_lun = 7,
1099 .use_clustering = ENABLE_CLUSTERING,
edb9068d 1100 .shost_attrs = mptscsih_host_attrs,
0c33b27d
CH
1101};
1102
b5141128 1103static int mptsas_get_linkerrors(struct sas_phy *phy)
0c33b27d 1104{
b5141128
CH
1105 MPT_ADAPTER *ioc = phy_to_ioc(phy);
1106 ConfigExtendedPageHeader_t hdr;
1107 CONFIGPARMS cfg;
1108 SasPhyPage1_t *buffer;
1109 dma_addr_t dma_handle;
1110 int error;
0c33b27d 1111
f4ad7b58
JB
1112 /* FIXME: only have link errors on local phys */
1113 if (!scsi_is_sas_phy_local(phy))
1114 return -EINVAL;
1115
b5141128
CH
1116 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
1117 hdr.ExtPageLength = 0;
1118 hdr.PageNumber = 1 /* page number 1*/;
1119 hdr.Reserved1 = 0;
1120 hdr.Reserved2 = 0;
1121 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1122 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
0c33b27d 1123
b5141128
CH
1124 cfg.cfghdr.ehdr = &hdr;
1125 cfg.physAddr = -1;
1126 cfg.pageAddr = phy->identify.phy_identifier;
1127 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1128 cfg.dir = 0; /* read */
1129 cfg.timeout = 10;
0c33b27d 1130
b5141128
CH
1131 error = mpt_config(ioc, &cfg);
1132 if (error)
1133 return error;
1134 if (!hdr.ExtPageLength)
1135 return -ENXIO;
0c33b27d 1136
b5141128
CH
1137 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1138 &dma_handle);
1139 if (!buffer)
1140 return -ENOMEM;
0c33b27d 1141
b5141128
CH
1142 cfg.physAddr = dma_handle;
1143 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1144
1145 error = mpt_config(ioc, &cfg);
1146 if (error)
1147 goto out_free_consistent;
1148
d6ecdd63 1149 mptsas_print_phy_pg1(ioc, buffer);
b5141128
CH
1150
1151 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
1152 phy->running_disparity_error_count =
1153 le32_to_cpu(buffer->RunningDisparityErrorCount);
1154 phy->loss_of_dword_sync_count =
1155 le32_to_cpu(buffer->LossDwordSynchCount);
1156 phy->phy_reset_problem_count =
1157 le32_to_cpu(buffer->PhyResetProblemCount);
1158
1159 out_free_consistent:
1160 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1161 buffer, dma_handle);
1162 return error;
0c33b27d
CH
1163}
1164
da4fa655
CH
1165static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
1166 MPT_FRAME_HDR *reply)
1167{
1168 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_COMMAND_GOOD;
1169 if (reply != NULL) {
1170 ioc->sas_mgmt.status |= MPT_SAS_MGMT_STATUS_RF_VALID;
1171 memcpy(ioc->sas_mgmt.reply, reply,
1172 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
1173 }
1174 complete(&ioc->sas_mgmt.done);
1175 return 1;
1176}
1177
1178static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
1179{
1180 MPT_ADAPTER *ioc = phy_to_ioc(phy);
1181 SasIoUnitControlRequest_t *req;
1182 SasIoUnitControlReply_t *reply;
1183 MPT_FRAME_HDR *mf;
1184 MPIHeader_t *hdr;
1185 unsigned long timeleft;
1186 int error = -ERESTARTSYS;
1187
f4ad7b58
JB
1188 /* FIXME: fusion doesn't allow non-local phy reset */
1189 if (!scsi_is_sas_phy_local(phy))
1190 return -EINVAL;
1191
da4fa655
CH
1192 /* not implemented for expanders */
1193 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
1194 return -ENXIO;
1195
eeb846ce 1196 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
da4fa655
CH
1197 goto out;
1198
1199 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
1200 if (!mf) {
1201 error = -ENOMEM;
1202 goto out_unlock;
1203 }
1204
1205 hdr = (MPIHeader_t *) mf;
1206 req = (SasIoUnitControlRequest_t *)mf;
1207 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
1208 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
1209 req->MsgContext = hdr->MsgContext;
1210 req->Operation = hard_reset ?
1211 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
1212 req->PhyNum = phy->identify.phy_identifier;
1213
1214 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
1215
1216 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
1217 10 * HZ);
1218 if (!timeleft) {
1219 /* On timeout reset the board */
1220 mpt_free_msg_frame(ioc, mf);
1221 mpt_HardResetHandler(ioc, CAN_SLEEP);
1222 error = -ETIMEDOUT;
1223 goto out_unlock;
1224 }
1225
1226 /* a reply frame is expected */
1227 if ((ioc->sas_mgmt.status &
1228 MPT_IOCTL_STATUS_RF_VALID) == 0) {
1229 error = -ENXIO;
1230 goto out_unlock;
1231 }
1232
1233 /* process the completed Reply Message Frame */
1234 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
1235 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
1236 printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
1237 __FUNCTION__,
1238 reply->IOCStatus,
1239 reply->IOCLogInfo);
1240 error = -ENXIO;
1241 goto out_unlock;
1242 }
1243
1244 error = 0;
1245
1246 out_unlock:
eeb846ce 1247 mutex_unlock(&ioc->sas_mgmt.mutex);
da4fa655
CH
1248 out:
1249 return error;
1250}
0c33b27d 1251
e3094447
CH
1252static int
1253mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
1254{
1255 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1256 int i, error;
1257 struct mptsas_portinfo *p;
1258 struct mptsas_enclosure enclosure_info;
1259 u64 enclosure_handle;
1260
1261 mutex_lock(&ioc->sas_topology_mutex);
1262 list_for_each_entry(p, &ioc->sas_topology, list) {
1263 for (i = 0; i < p->num_phys; i++) {
1264 if (p->phy_info[i].attached.sas_address ==
1265 rphy->identify.sas_address) {
1266 enclosure_handle = p->phy_info[i].
1267 attached.handle_enclosure;
1268 goto found_info;
1269 }
1270 }
1271 }
1272 mutex_unlock(&ioc->sas_topology_mutex);
1273 return -ENXIO;
1274
1275 found_info:
1276 mutex_unlock(&ioc->sas_topology_mutex);
1277 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
52435430 1278 error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
e3094447
CH
1279 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
1280 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
1281 if (!error)
1282 *identifier = enclosure_info.enclosure_logical_id;
1283 return error;
1284}
1285
1286static int
1287mptsas_get_bay_identifier(struct sas_rphy *rphy)
1288{
1289 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
1290 struct mptsas_portinfo *p;
1291 int i, rc;
1292
1293 mutex_lock(&ioc->sas_topology_mutex);
1294 list_for_each_entry(p, &ioc->sas_topology, list) {
1295 for (i = 0; i < p->num_phys; i++) {
1296 if (p->phy_info[i].attached.sas_address ==
1297 rphy->identify.sas_address) {
1298 rc = p->phy_info[i].attached.slot;
1299 goto out;
1300 }
1301 }
1302 }
1303 rc = -ENXIO;
1304 out:
1305 mutex_unlock(&ioc->sas_topology_mutex);
1306 return rc;
1307}
1308
159e36fe
FT
1309static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
1310 struct request *req)
1311{
1312 MPT_ADAPTER *ioc = ((MPT_SCSI_HOST *) shost->hostdata)->ioc;
1313 MPT_FRAME_HDR *mf;
1314 SmpPassthroughRequest_t *smpreq;
1315 struct request *rsp = req->next_rq;
1316 int ret;
1317 int flagsLength;
1318 unsigned long timeleft;
1319 char *psge;
1320 dma_addr_t dma_addr_in = 0;
1321 dma_addr_t dma_addr_out = 0;
1322 u64 sas_address = 0;
1323
1324 if (!rsp) {
1325 printk(KERN_ERR "%s: the smp response space is missing\n",
1326 __FUNCTION__);
1327 return -EINVAL;
1328 }
1329
1330 /* do we need to support multiple segments? */
1331 if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
1332 printk(KERN_ERR "%s: multiple segments req %u %u, rsp %u %u\n",
1333 __FUNCTION__, req->bio->bi_vcnt, req->data_len,
1334 rsp->bio->bi_vcnt, rsp->data_len);
1335 return -EINVAL;
1336 }
1337
1338 ret = mutex_lock_interruptible(&ioc->sas_mgmt.mutex);
1339 if (ret)
1340 goto out;
1341
1342 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
1343 if (!mf) {
1344 ret = -ENOMEM;
1345 goto out_unlock;
1346 }
1347
1348 smpreq = (SmpPassthroughRequest_t *)mf;
1349 memset(smpreq, 0, sizeof(*smpreq));
1350
1351 smpreq->RequestDataLength = cpu_to_le16(req->data_len - 4);
1352 smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
1353
1354 if (rphy)
1355 sas_address = rphy->identify.sas_address;
1356 else {
1357 struct mptsas_portinfo *port_info;
1358
1359 mutex_lock(&ioc->sas_topology_mutex);
1360 port_info = mptsas_find_portinfo_by_handle(ioc, ioc->handle);
1361 if (port_info && port_info->phy_info)
1362 sas_address =
1363 port_info->phy_info[0].phy->identify.sas_address;
1364 mutex_unlock(&ioc->sas_topology_mutex);
1365 }
1366
1367 *((u64 *)&smpreq->SASAddress) = cpu_to_le64(sas_address);
1368
1369 psge = (char *)
1370 (((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4));
1371
1372 /* request */
1373 flagsLength = (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
1374 MPI_SGE_FLAGS_END_OF_BUFFER |
1375 MPI_SGE_FLAGS_DIRECTION |
1376 mpt_addr_size()) << MPI_SGE_FLAGS_SHIFT;
1377 flagsLength |= (req->data_len - 4);
1378
1379 dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio),
1380 req->data_len, PCI_DMA_BIDIRECTIONAL);
1381 if (!dma_addr_out)
1382 goto put_mf;
1383 mpt_add_sge(psge, flagsLength, dma_addr_out);
1384 psge += (sizeof(u32) + sizeof(dma_addr_t));
1385
1386 /* response */
1387 flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ;
1388 flagsLength |= rsp->data_len + 4;
1389 dma_addr_in = pci_map_single(ioc->pcidev, bio_data(rsp->bio),
1390 rsp->data_len, PCI_DMA_BIDIRECTIONAL);
1391 if (!dma_addr_in)
1392 goto unmap;
1393 mpt_add_sge(psge, flagsLength, dma_addr_in);
1394
1395 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
1396
1397 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
1398 if (!timeleft) {
1399 printk(KERN_ERR "%s: smp timeout!\n", __FUNCTION__);
1400 /* On timeout reset the board */
1401 mpt_HardResetHandler(ioc, CAN_SLEEP);
1402 ret = -ETIMEDOUT;
1403 goto unmap;
1404 }
1405 mf = NULL;
1406
1407 if (ioc->sas_mgmt.status & MPT_IOCTL_STATUS_RF_VALID) {
1408 SmpPassthroughReply_t *smprep;
1409
1410 smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
1411 memcpy(req->sense, smprep, sizeof(*smprep));
1412 req->sense_len = sizeof(*smprep);
1413 } else {
1414 printk(KERN_ERR "%s: smp passthru reply failed to be returned\n",
1415 __FUNCTION__);
1416 ret = -ENXIO;
1417 }
1418unmap:
1419 if (dma_addr_out)
1420 pci_unmap_single(ioc->pcidev, dma_addr_out, req->data_len,
1421 PCI_DMA_BIDIRECTIONAL);
1422 if (dma_addr_in)
1423 pci_unmap_single(ioc->pcidev, dma_addr_in, rsp->data_len,
1424 PCI_DMA_BIDIRECTIONAL);
1425put_mf:
1426 if (mf)
1427 mpt_free_msg_frame(ioc, mf);
1428out_unlock:
1429 mutex_unlock(&ioc->sas_mgmt.mutex);
1430out:
1431 return ret;
1432}
1433
b5141128
CH
1434static struct sas_function_template mptsas_transport_functions = {
1435 .get_linkerrors = mptsas_get_linkerrors,
e3094447
CH
1436 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
1437 .get_bay_identifier = mptsas_get_bay_identifier,
da4fa655 1438 .phy_reset = mptsas_phy_reset,
159e36fe 1439 .smp_handler = mptsas_smp_handler,
b5141128
CH
1440};
1441
1442static struct scsi_transport_template *mptsas_transport_template;
0c33b27d
CH
1443
1444static int
1445mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
1446{
1447 ConfigExtendedPageHeader_t hdr;
1448 CONFIGPARMS cfg;
1449 SasIOUnitPage0_t *buffer;
1450 dma_addr_t dma_handle;
1451 int error, i;
1452
1453 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
1454 hdr.ExtPageLength = 0;
1455 hdr.PageNumber = 0;
1456 hdr.Reserved1 = 0;
1457 hdr.Reserved2 = 0;
1458 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1459 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1460
1461 cfg.cfghdr.ehdr = &hdr;
1462 cfg.physAddr = -1;
1463 cfg.pageAddr = 0;
1464 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1465 cfg.dir = 0; /* read */
1466 cfg.timeout = 10;
1467
1468 error = mpt_config(ioc, &cfg);
1469 if (error)
1470 goto out;
1471 if (!hdr.ExtPageLength) {
1472 error = -ENXIO;
1473 goto out;
1474 }
1475
1476 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1477 &dma_handle);
1478 if (!buffer) {
1479 error = -ENOMEM;
1480 goto out;
1481 }
1482
1483 cfg.physAddr = dma_handle;
1484 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1485
1486 error = mpt_config(ioc, &cfg);
1487 if (error)
1488 goto out_free_consistent;
1489
1490 port_info->num_phys = buffer->NumPhys;
1491 port_info->phy_info = kcalloc(port_info->num_phys,
547f9a21 1492 sizeof(*port_info->phy_info),GFP_KERNEL);
0c33b27d
CH
1493 if (!port_info->phy_info) {
1494 error = -ENOMEM;
1495 goto out_free_consistent;
1496 }
1497
edb9068d
PS
1498 ioc->nvdata_version_persistent =
1499 le16_to_cpu(buffer->NvdataVersionPersistent);
1500 ioc->nvdata_version_default =
1501 le16_to_cpu(buffer->NvdataVersionDefault);
1502
0c33b27d 1503 for (i = 0; i < port_info->num_phys; i++) {
d6ecdd63 1504 mptsas_print_phy_data(ioc, &buffer->PhyData[i]);
0c33b27d
CH
1505 port_info->phy_info[i].phy_id = i;
1506 port_info->phy_info[i].port_id =
1507 buffer->PhyData[i].Port;
1508 port_info->phy_info[i].negotiated_link_rate =
1509 buffer->PhyData[i].NegotiatedLinkRate;
547f9a21 1510 port_info->phy_info[i].portinfo = port_info;
2ecce492
EM
1511 port_info->phy_info[i].handle =
1512 le16_to_cpu(buffer->PhyData[i].ControllerDevHandle);
0c33b27d
CH
1513 }
1514
1515 out_free_consistent:
1516 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1517 buffer, dma_handle);
1518 out:
1519 return error;
1520}
1521
edb9068d
PS
1522static int
1523mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc)
1524{
1525 ConfigExtendedPageHeader_t hdr;
1526 CONFIGPARMS cfg;
1527 SasIOUnitPage1_t *buffer;
1528 dma_addr_t dma_handle;
1529 int error;
1530 u16 device_missing_delay;
1531
1532 memset(&hdr, 0, sizeof(ConfigExtendedPageHeader_t));
1533 memset(&cfg, 0, sizeof(CONFIGPARMS));
1534
1535 cfg.cfghdr.ehdr = &hdr;
1536 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1537 cfg.timeout = 10;
1538 cfg.cfghdr.ehdr->PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1539 cfg.cfghdr.ehdr->ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
1540 cfg.cfghdr.ehdr->PageVersion = MPI_SASIOUNITPAGE1_PAGEVERSION;
1541 cfg.cfghdr.ehdr->PageNumber = 1;
1542
1543 error = mpt_config(ioc, &cfg);
1544 if (error)
1545 goto out;
1546 if (!hdr.ExtPageLength) {
1547 error = -ENXIO;
1548 goto out;
1549 }
1550
1551 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1552 &dma_handle);
1553 if (!buffer) {
1554 error = -ENOMEM;
1555 goto out;
1556 }
1557
1558 cfg.physAddr = dma_handle;
1559 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1560
1561 error = mpt_config(ioc, &cfg);
1562 if (error)
1563 goto out_free_consistent;
1564
1565 ioc->io_missing_delay =
1566 le16_to_cpu(buffer->IODeviceMissingDelay);
1567 device_missing_delay = le16_to_cpu(buffer->ReportDeviceMissingDelay);
1568 ioc->device_missing_delay = (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16) ?
1569 (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16 :
1570 device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
1571
1572 out_free_consistent:
1573 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1574 buffer, dma_handle);
1575 out:
1576 return error;
1577}
1578
0c33b27d
CH
1579static int
1580mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1581 u32 form, u32 form_specific)
1582{
1583 ConfigExtendedPageHeader_t hdr;
1584 CONFIGPARMS cfg;
1585 SasPhyPage0_t *buffer;
1586 dma_addr_t dma_handle;
1587 int error;
1588
1589 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
1590 hdr.ExtPageLength = 0;
1591 hdr.PageNumber = 0;
1592 hdr.Reserved1 = 0;
1593 hdr.Reserved2 = 0;
1594 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1595 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
1596
1597 cfg.cfghdr.ehdr = &hdr;
1598 cfg.dir = 0; /* read */
1599 cfg.timeout = 10;
1600
1601 /* Get Phy Pg 0 for each Phy. */
1602 cfg.physAddr = -1;
1603 cfg.pageAddr = form + form_specific;
1604 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1605
1606 error = mpt_config(ioc, &cfg);
1607 if (error)
1608 goto out;
1609
1610 if (!hdr.ExtPageLength) {
1611 error = -ENXIO;
1612 goto out;
1613 }
1614
1615 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1616 &dma_handle);
1617 if (!buffer) {
1618 error = -ENOMEM;
1619 goto out;
1620 }
1621
1622 cfg.physAddr = dma_handle;
1623 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1624
1625 error = mpt_config(ioc, &cfg);
1626 if (error)
1627 goto out_free_consistent;
1628
d6ecdd63 1629 mptsas_print_phy_pg0(ioc, buffer);
0c33b27d
CH
1630
1631 phy_info->hw_link_rate = buffer->HwLinkRate;
1632 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1633 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1634 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1635
1636 out_free_consistent:
1637 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1638 buffer, dma_handle);
1639 out:
1640 return error;
1641}
1642
1643static int
1644mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
1645 u32 form, u32 form_specific)
1646{
1647 ConfigExtendedPageHeader_t hdr;
1648 CONFIGPARMS cfg;
1649 SasDevicePage0_t *buffer;
1650 dma_addr_t dma_handle;
1651 __le64 sas_address;
bd23e94c
ME
1652 int error=0;
1653
1654 if (ioc->sas_discovery_runtime &&
1655 mptsas_is_end_device(device_info))
1656 goto out;
0c33b27d
CH
1657
1658 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
1659 hdr.ExtPageLength = 0;
1660 hdr.PageNumber = 0;
1661 hdr.Reserved1 = 0;
1662 hdr.Reserved2 = 0;
1663 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1664 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
1665
1666 cfg.cfghdr.ehdr = &hdr;
1667 cfg.pageAddr = form + form_specific;
1668 cfg.physAddr = -1;
1669 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1670 cfg.dir = 0; /* read */
1671 cfg.timeout = 10;
1672
db9c9174 1673 memset(device_info, 0, sizeof(struct mptsas_devinfo));
0c33b27d
CH
1674 error = mpt_config(ioc, &cfg);
1675 if (error)
1676 goto out;
1677 if (!hdr.ExtPageLength) {
1678 error = -ENXIO;
1679 goto out;
1680 }
1681
1682 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1683 &dma_handle);
1684 if (!buffer) {
1685 error = -ENOMEM;
1686 goto out;
1687 }
1688
1689 cfg.physAddr = dma_handle;
1690 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1691
1692 error = mpt_config(ioc, &cfg);
1693 if (error)
1694 goto out_free_consistent;
1695
d6ecdd63 1696 mptsas_print_device_pg0(ioc, buffer);
0c33b27d
CH
1697
1698 device_info->handle = le16_to_cpu(buffer->DevHandle);
c73787ee 1699 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
e3094447
CH
1700 device_info->handle_enclosure =
1701 le16_to_cpu(buffer->EnclosureHandle);
1702 device_info->slot = le16_to_cpu(buffer->Slot);
0c33b27d
CH
1703 device_info->phy_id = buffer->PhyNum;
1704 device_info->port_id = buffer->PhysicalPort;
9a28f49a 1705 device_info->id = buffer->TargetID;
b506ade9 1706 device_info->phys_disk_num = ~0;
9a28f49a 1707 device_info->channel = buffer->Bus;
0c33b27d
CH
1708 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
1709 device_info->sas_address = le64_to_cpu(sas_address);
1710 device_info->device_info =
1711 le32_to_cpu(buffer->DeviceInfo);
1712
1713 out_free_consistent:
1714 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1715 buffer, dma_handle);
1716 out:
1717 return error;
1718}
1719
1720static int
1721mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
1722 u32 form, u32 form_specific)
1723{
1724 ConfigExtendedPageHeader_t hdr;
1725 CONFIGPARMS cfg;
1726 SasExpanderPage0_t *buffer;
1727 dma_addr_t dma_handle;
547f9a21 1728 int i, error;
0c33b27d
CH
1729
1730 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1731 hdr.ExtPageLength = 0;
1732 hdr.PageNumber = 0;
1733 hdr.Reserved1 = 0;
1734 hdr.Reserved2 = 0;
1735 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1736 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1737
1738 cfg.cfghdr.ehdr = &hdr;
1739 cfg.physAddr = -1;
1740 cfg.pageAddr = form + form_specific;
1741 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1742 cfg.dir = 0; /* read */
1743 cfg.timeout = 10;
1744
db9c9174 1745 memset(port_info, 0, sizeof(struct mptsas_portinfo));
0c33b27d
CH
1746 error = mpt_config(ioc, &cfg);
1747 if (error)
1748 goto out;
1749
1750 if (!hdr.ExtPageLength) {
1751 error = -ENXIO;
1752 goto out;
1753 }
1754
1755 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1756 &dma_handle);
1757 if (!buffer) {
1758 error = -ENOMEM;
1759 goto out;
1760 }
1761
1762 cfg.physAddr = dma_handle;
1763 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1764
1765 error = mpt_config(ioc, &cfg);
1766 if (error)
1767 goto out_free_consistent;
1768
1769 /* save config data */
1770 port_info->num_phys = buffer->NumPhys;
0c33b27d 1771 port_info->phy_info = kcalloc(port_info->num_phys,
547f9a21 1772 sizeof(*port_info->phy_info),GFP_KERNEL);
0c33b27d
CH
1773 if (!port_info->phy_info) {
1774 error = -ENOMEM;
1775 goto out_free_consistent;
1776 }
1777
2ecce492 1778 for (i = 0; i < port_info->num_phys; i++) {
547f9a21 1779 port_info->phy_info[i].portinfo = port_info;
2ecce492
EM
1780 port_info->phy_info[i].handle =
1781 le16_to_cpu(buffer->DevHandle);
1782 }
547f9a21 1783
0c33b27d
CH
1784 out_free_consistent:
1785 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1786 buffer, dma_handle);
1787 out:
1788 return error;
1789}
1790
1791static int
1792mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
1793 u32 form, u32 form_specific)
1794{
1795 ConfigExtendedPageHeader_t hdr;
1796 CONFIGPARMS cfg;
1797 SasExpanderPage1_t *buffer;
1798 dma_addr_t dma_handle;
bd23e94c
ME
1799 int error=0;
1800
1801 if (ioc->sas_discovery_runtime &&
1802 mptsas_is_end_device(&phy_info->attached))
1803 goto out;
0c33b27d
CH
1804
1805 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
1806 hdr.ExtPageLength = 0;
1807 hdr.PageNumber = 1;
1808 hdr.Reserved1 = 0;
1809 hdr.Reserved2 = 0;
1810 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1811 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
1812
1813 cfg.cfghdr.ehdr = &hdr;
1814 cfg.physAddr = -1;
1815 cfg.pageAddr = form + form_specific;
1816 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1817 cfg.dir = 0; /* read */
1818 cfg.timeout = 10;
1819
1820 error = mpt_config(ioc, &cfg);
1821 if (error)
1822 goto out;
1823
1824 if (!hdr.ExtPageLength) {
1825 error = -ENXIO;
1826 goto out;
1827 }
1828
1829 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1830 &dma_handle);
1831 if (!buffer) {
1832 error = -ENOMEM;
1833 goto out;
1834 }
1835
1836 cfg.physAddr = dma_handle;
1837 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1838
1839 error = mpt_config(ioc, &cfg);
1840 if (error)
1841 goto out_free_consistent;
1842
1843
d6ecdd63 1844 mptsas_print_expander_pg1(ioc, buffer);
0c33b27d
CH
1845
1846 /* save config data */
024358ee 1847 phy_info->phy_id = buffer->PhyIdentifier;
0c33b27d
CH
1848 phy_info->port_id = buffer->PhysicalPort;
1849 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
1850 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
1851 phy_info->hw_link_rate = buffer->HwLinkRate;
1852 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
1853 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
1854
0c33b27d
CH
1855 out_free_consistent:
1856 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1857 buffer, dma_handle);
1858 out:
1859 return error;
1860}
1861
1862static void
1863mptsas_parse_device_info(struct sas_identify *identify,
1864 struct mptsas_devinfo *device_info)
1865{
1866 u16 protocols;
1867
1868 identify->sas_address = device_info->sas_address;
1869 identify->phy_identifier = device_info->phy_id;
1870
1871 /*
1872 * Fill in Phy Initiator Port Protocol.
1873 * Bits 6:3, more than one bit can be set, fall through cases.
1874 */
1875 protocols = device_info->device_info & 0x78;
1876 identify->initiator_port_protocols = 0;
1877 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
1878 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
1879 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1880 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
1881 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
1882 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
1883 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
1884 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
1885
1886 /*
1887 * Fill in Phy Target Port Protocol.
1888 * Bits 10:7, more than one bit can be set, fall through cases.
1889 */
1890 protocols = device_info->device_info & 0x780;
1891 identify->target_port_protocols = 0;
1892 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
1893 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
1894 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
1895 identify->target_port_protocols |= SAS_PROTOCOL_STP;
1896 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
1897 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
1898 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1899 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
1900
1901 /*
1902 * Fill in Attached device type.
1903 */
1904 switch (device_info->device_info &
1905 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
1906 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
1907 identify->device_type = SAS_PHY_UNUSED;
1908 break;
1909 case MPI_SAS_DEVICE_INFO_END_DEVICE:
1910 identify->device_type = SAS_END_DEVICE;
1911 break;
1912 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
1913 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
1914 break;
1915 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
1916 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
1917 break;
1918 }
1919}
1920
1921static int mptsas_probe_one_phy(struct device *dev,
ac01bbbd 1922 struct mptsas_phyinfo *phy_info, int index, int local)
0c33b27d 1923{
e6b2d76a 1924 MPT_ADAPTER *ioc;
9a28f49a 1925 struct sas_phy *phy;
547f9a21
EM
1926 struct sas_port *port;
1927 int error = 0;
0c33b27d 1928
547f9a21
EM
1929 if (!dev) {
1930 error = -ENODEV;
1931 goto out;
1932 }
e6b2d76a
ME
1933
1934 if (!phy_info->phy) {
1935 phy = sas_phy_alloc(dev, index);
547f9a21
EM
1936 if (!phy) {
1937 error = -ENOMEM;
1938 goto out;
1939 }
e6b2d76a
ME
1940 } else
1941 phy = phy_info->phy;
0c33b27d 1942
9a28f49a 1943 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
0c33b27d
CH
1944
1945 /*
1946 * Set Negotiated link rate.
1947 */
1948 switch (phy_info->negotiated_link_rate) {
1949 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
9a28f49a 1950 phy->negotiated_linkrate = SAS_PHY_DISABLED;
0c33b27d
CH
1951 break;
1952 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
9a28f49a 1953 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
0c33b27d
CH
1954 break;
1955 case MPI_SAS_IOUNIT0_RATE_1_5:
9a28f49a 1956 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1957 break;
1958 case MPI_SAS_IOUNIT0_RATE_3_0:
9a28f49a 1959 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1960 break;
1961 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
1962 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
1963 default:
9a28f49a 1964 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
0c33b27d
CH
1965 break;
1966 }
1967
1968 /*
1969 * Set Max hardware link rate.
1970 */
1971 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1972 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
9a28f49a 1973 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1974 break;
1975 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
9a28f49a 1976 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1977 break;
1978 default:
1979 break;
1980 }
1981
1982 /*
1983 * Set Max programmed link rate.
1984 */
1985 switch (phy_info->programmed_link_rate &
1986 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
1987 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
9a28f49a 1988 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
1989 break;
1990 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
9a28f49a 1991 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
1992 break;
1993 default:
1994 break;
1995 }
1996
1997 /*
1998 * Set Min hardware link rate.
1999 */
2000 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
2001 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
9a28f49a 2002 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
2003 break;
2004 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
9a28f49a 2005 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
2006 break;
2007 default:
2008 break;
2009 }
2010
2011 /*
2012 * Set Min programmed link rate.
2013 */
2014 switch (phy_info->programmed_link_rate &
2015 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
2016 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
9a28f49a 2017 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
2018 break;
2019 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
9a28f49a 2020 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
2021 break;
2022 default:
2023 break;
2024 }
2025
e6b2d76a 2026 if (!phy_info->phy) {
ac01bbbd 2027
e6b2d76a
ME
2028 error = sas_phy_add(phy);
2029 if (error) {
2030 sas_phy_free(phy);
547f9a21 2031 goto out;
e6b2d76a
ME
2032 }
2033 phy_info->phy = phy;
0c33b27d
CH
2034 }
2035
547f9a21
EM
2036 if (!phy_info->attached.handle ||
2037 !phy_info->port_details)
2038 goto out;
2039
2040 port = mptsas_get_port(phy_info);
2041 ioc = phy_to_ioc(phy_info->phy);
2042
2043 if (phy_info->sas_port_add_phy) {
2044
2045 if (!port) {
dc22f16d 2046 port = sas_port_alloc_num(dev);
547f9a21
EM
2047 if (!port) {
2048 error = -ENOMEM;
2049 goto out;
2050 }
2051 error = sas_port_add(port);
2052 if (error) {
d6ecdd63 2053 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2054 "%s: exit at line=%d\n", ioc->name,
2055 __FUNCTION__, __LINE__));
2056 goto out;
2057 }
d6ecdd63
PS
2058 mptsas_set_port(ioc, phy_info, port);
2059 dsaswideprintk(ioc, printk(KERN_DEBUG
dc22f16d
EM
2060 "sas_port_alloc: port=%p dev=%p port_id=%d\n",
2061 port, dev, port->port_identifier));
547f9a21 2062 }
d6ecdd63 2063 dsaswideprintk(ioc, printk(KERN_DEBUG "sas_port_add_phy: phy_id=%d\n",
547f9a21
EM
2064 phy_info->phy_id));
2065 sas_port_add_phy(port, phy_info->phy);
2066 phy_info->sas_port_add_phy = 0;
2067 }
2068
2069 if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
e6b2d76a 2070
0c33b27d 2071 struct sas_rphy *rphy;
2686de27 2072 struct device *parent;
f013db32 2073 struct sas_identify identify;
0c33b27d 2074
2686de27 2075 parent = dev->parent->parent;
e6b2d76a
ME
2076 /*
2077 * Let the hotplug_work thread handle processing
2078 * the adding/removing of devices that occur
2079 * after start of day.
2080 */
2081 if (ioc->sas_discovery_runtime &&
2082 mptsas_is_end_device(&phy_info->attached))
547f9a21 2083 goto out;
e6b2d76a 2084
f013db32 2085 mptsas_parse_device_info(&identify, &phy_info->attached);
2686de27
JB
2086 if (scsi_is_host_device(parent)) {
2087 struct mptsas_portinfo *port_info;
2088 int i;
2089
2090 mutex_lock(&ioc->sas_topology_mutex);
2091 port_info = mptsas_find_portinfo_by_handle(ioc,
2092 ioc->handle);
2093 mutex_unlock(&ioc->sas_topology_mutex);
2094
2095 for (i = 0; i < port_info->num_phys; i++)
2096 if (port_info->phy_info[i].identify.sas_address ==
0c269e6d
JB
2097 identify.sas_address) {
2098 sas_port_mark_backlink(port);
2686de27 2099 goto out;
0c269e6d 2100 }
2686de27
JB
2101
2102 } else if (scsi_is_sas_rphy(parent)) {
2103 struct sas_rphy *parent_rphy = dev_to_rphy(parent);
2104 if (identify.sas_address ==
0c269e6d
JB
2105 parent_rphy->identify.sas_address) {
2106 sas_port_mark_backlink(port);
2686de27 2107 goto out;
0c269e6d 2108 }
2686de27
JB
2109 }
2110
f013db32
JB
2111 switch (identify.device_type) {
2112 case SAS_END_DEVICE:
547f9a21 2113 rphy = sas_end_device_alloc(port);
f013db32
JB
2114 break;
2115 case SAS_EDGE_EXPANDER_DEVICE:
2116 case SAS_FANOUT_EXPANDER_DEVICE:
547f9a21 2117 rphy = sas_expander_alloc(port, identify.device_type);
f013db32
JB
2118 break;
2119 default:
2120 rphy = NULL;
2121 break;
2122 }
547f9a21 2123 if (!rphy) {
d6ecdd63 2124 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2125 "%s: exit at line=%d\n", ioc->name,
2126 __FUNCTION__, __LINE__));
2127 goto out;
2128 }
0c33b27d 2129
f013db32 2130 rphy->identify = identify;
0c33b27d
CH
2131 error = sas_rphy_add(rphy);
2132 if (error) {
d6ecdd63 2133 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2134 "%s: exit at line=%d\n", ioc->name,
2135 __FUNCTION__, __LINE__));
0c33b27d 2136 sas_rphy_free(rphy);
547f9a21 2137 goto out;
0c33b27d 2138 }
d6ecdd63 2139 mptsas_set_rphy(ioc, phy_info, rphy);
0c33b27d
CH
2140 }
2141
547f9a21
EM
2142 out:
2143 return error;
0c33b27d
CH
2144}
2145
2146static int
e6b2d76a 2147mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
0c33b27d 2148{
e6b2d76a 2149 struct mptsas_portinfo *port_info, *hba;
0c33b27d
CH
2150 int error = -ENOMEM, i;
2151
e6b2d76a
ME
2152 hba = kzalloc(sizeof(*port_info), GFP_KERNEL);
2153 if (! hba)
0c33b27d 2154 goto out;
0c33b27d 2155
e6b2d76a 2156 error = mptsas_sas_io_unit_pg0(ioc, hba);
0c33b27d
CH
2157 if (error)
2158 goto out_free_port_info;
2159
edb9068d 2160 mptsas_sas_io_unit_pg1(ioc);
9a28f49a 2161 mutex_lock(&ioc->sas_topology_mutex);
2ecce492
EM
2162 ioc->handle = hba->phy_info[0].handle;
2163 port_info = mptsas_find_portinfo_by_handle(ioc, ioc->handle);
e6b2d76a
ME
2164 if (!port_info) {
2165 port_info = hba;
2166 list_add_tail(&port_info->list, &ioc->sas_topology);
2167 } else {
2ecce492 2168 for (i = 0; i < hba->num_phys; i++) {
e6b2d76a
ME
2169 port_info->phy_info[i].negotiated_link_rate =
2170 hba->phy_info[i].negotiated_link_rate;
2ecce492
EM
2171 port_info->phy_info[i].handle =
2172 hba->phy_info[i].handle;
2173 port_info->phy_info[i].port_id =
2174 hba->phy_info[i].port_id;
2175 }
547f9a21 2176 kfree(hba->phy_info);
e6b2d76a
ME
2177 kfree(hba);
2178 hba = NULL;
2179 }
9a28f49a 2180 mutex_unlock(&ioc->sas_topology_mutex);
0c33b27d
CH
2181 for (i = 0; i < port_info->num_phys; i++) {
2182 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
2183 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
2184 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
2185
2186 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
2ecce492
EM
2187 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2188 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2189 port_info->phy_info[i].handle);
024358ee 2190 port_info->phy_info[i].identify.phy_id =
2ecce492 2191 port_info->phy_info[i].phy_id = i;
547f9a21 2192 if (port_info->phy_info[i].attached.handle)
0c33b27d
CH
2193 mptsas_sas_device_pg0(ioc,
2194 &port_info->phy_info[i].attached,
2195 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2196 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2197 port_info->phy_info[i].attached.handle);
547f9a21 2198 }
0c33b27d 2199
547f9a21
EM
2200 mptsas_setup_wide_ports(ioc, port_info);
2201
2202 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
0c33b27d 2203 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
e6b2d76a 2204 &port_info->phy_info[i], ioc->sas_index, 1);
0c33b27d
CH
2205
2206 return 0;
2207
2208 out_free_port_info:
547f9a21 2209 kfree(hba);
0c33b27d
CH
2210 out:
2211 return error;
2212}
2213
2214static int
e6b2d76a 2215mptsas_probe_expander_phys(MPT_ADAPTER *ioc, u32 *handle)
0c33b27d 2216{
e6b2d76a 2217 struct mptsas_portinfo *port_info, *p, *ex;
547f9a21
EM
2218 struct device *parent;
2219 struct sas_rphy *rphy;
0c33b27d
CH
2220 int error = -ENOMEM, i, j;
2221
e6b2d76a
ME
2222 ex = kzalloc(sizeof(*port_info), GFP_KERNEL);
2223 if (!ex)
0c33b27d 2224 goto out;
0c33b27d 2225
e6b2d76a 2226 error = mptsas_sas_expander_pg0(ioc, ex,
2ecce492
EM
2227 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
2228 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), *handle);
0c33b27d
CH
2229 if (error)
2230 goto out_free_port_info;
2231
2ecce492 2232 *handle = ex->phy_info[0].handle;
0c33b27d 2233
9a28f49a 2234 mutex_lock(&ioc->sas_topology_mutex);
e6b2d76a
ME
2235 port_info = mptsas_find_portinfo_by_handle(ioc, *handle);
2236 if (!port_info) {
2237 port_info = ex;
2238 list_add_tail(&port_info->list, &ioc->sas_topology);
2239 } else {
2ecce492
EM
2240 for (i = 0; i < ex->num_phys; i++) {
2241 port_info->phy_info[i].handle =
2242 ex->phy_info[i].handle;
2243 port_info->phy_info[i].port_id =
2244 ex->phy_info[i].port_id;
2245 }
547f9a21 2246 kfree(ex->phy_info);
e6b2d76a
ME
2247 kfree(ex);
2248 ex = NULL;
2249 }
9a28f49a
CH
2250 mutex_unlock(&ioc->sas_topology_mutex);
2251
0c33b27d 2252 for (i = 0; i < port_info->num_phys; i++) {
0c33b27d
CH
2253 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
2254 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
2255 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + *handle);
2256
2257 if (port_info->phy_info[i].identify.handle) {
2258 mptsas_sas_device_pg0(ioc,
2259 &port_info->phy_info[i].identify,
2260 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2261 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2262 port_info->phy_info[i].identify.handle);
024358ee
EM
2263 port_info->phy_info[i].identify.phy_id =
2264 port_info->phy_info[i].phy_id;
0c33b27d
CH
2265 }
2266
2267 if (port_info->phy_info[i].attached.handle) {
2268 mptsas_sas_device_pg0(ioc,
2269 &port_info->phy_info[i].attached,
2270 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
2271 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2272 port_info->phy_info[i].attached.handle);
db9c9174
ME
2273 port_info->phy_info[i].attached.phy_id =
2274 port_info->phy_info[i].phy_id;
0c33b27d 2275 }
547f9a21 2276 }
0c33b27d 2277
547f9a21
EM
2278 parent = &ioc->sh->shost_gendev;
2279 for (i = 0; i < port_info->num_phys; i++) {
9a28f49a 2280 mutex_lock(&ioc->sas_topology_mutex);
0c33b27d
CH
2281 list_for_each_entry(p, &ioc->sas_topology, list) {
2282 for (j = 0; j < p->num_phys; j++) {
547f9a21 2283 if (port_info->phy_info[i].identify.handle !=
0c33b27d 2284 p->phy_info[j].attached.handle)
547f9a21
EM
2285 continue;
2286 rphy = mptsas_get_rphy(&p->phy_info[j]);
2287 parent = &rphy->dev;
0c33b27d
CH
2288 }
2289 }
9a28f49a 2290 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21
EM
2291 }
2292
2293 mptsas_setup_wide_ports(ioc, port_info);
0c33b27d 2294
547f9a21 2295 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
ac01bbbd 2296 mptsas_probe_one_phy(parent, &port_info->phy_info[i],
e6b2d76a 2297 ioc->sas_index, 0);
0c33b27d
CH
2298
2299 return 0;
2300
2301 out_free_port_info:
e6b2d76a 2302 if (ex) {
547f9a21 2303 kfree(ex->phy_info);
e6b2d76a
ME
2304 kfree(ex);
2305 }
0c33b27d
CH
2306 out:
2307 return error;
2308}
2309
e6b2d76a
ME
2310/*
2311 * mptsas_delete_expander_phys
2312 *
2313 *
2314 * This will traverse topology, and remove expanders
2315 * that are no longer present
2316 */
2317static void
2318mptsas_delete_expander_phys(MPT_ADAPTER *ioc)
2319{
2320 struct mptsas_portinfo buffer;
2321 struct mptsas_portinfo *port_info, *n, *parent;
547f9a21 2322 struct mptsas_phyinfo *phy_info;
547f9a21 2323 struct sas_port * port;
e6b2d76a 2324 int i;
547f9a21 2325 u64 expander_sas_address;
e6b2d76a
ME
2326
2327 mutex_lock(&ioc->sas_topology_mutex);
2328 list_for_each_entry_safe(port_info, n, &ioc->sas_topology, list) {
2329
2330 if (port_info->phy_info &&
2331 (!(port_info->phy_info[0].identify.device_info &
2332 MPI_SAS_DEVICE_INFO_SMP_TARGET)))
2333 continue;
2334
2335 if (mptsas_sas_expander_pg0(ioc, &buffer,
2336 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
2ecce492
EM
2337 MPI_SAS_EXPAND_PGAD_FORM_SHIFT),
2338 port_info->phy_info[0].handle)) {
e6b2d76a
ME
2339
2340 /*
2341 * Obtain the port_info instance to the parent port
2342 */
2343 parent = mptsas_find_portinfo_by_handle(ioc,
2344 port_info->phy_info[0].identify.handle_parent);
2345
2346 if (!parent)
2347 goto next_port;
2348
547f9a21
EM
2349 expander_sas_address =
2350 port_info->phy_info[0].identify.sas_address;
2351
e6b2d76a
ME
2352 /*
2353 * Delete rphys in the parent that point
2354 * to this expander. The transport layer will
2355 * cleanup all the children.
2356 */
547f9a21
EM
2357 phy_info = parent->phy_info;
2358 for (i = 0; i < parent->num_phys; i++, phy_info++) {
2359 port = mptsas_get_port(phy_info);
2360 if (!port)
2361 continue;
2362 if (phy_info->attached.sas_address !=
2363 expander_sas_address)
e6b2d76a 2364 continue;
d6ecdd63
PS
2365 dsaswideprintk(ioc,
2366 dev_printk(KERN_DEBUG, &port->dev,
2367 "delete port (%d)\n", port->port_identifier));
547f9a21 2368 sas_port_delete(port);
d6ecdd63 2369 mptsas_port_delete(ioc, phy_info->port_details);
e6b2d76a
ME
2370 }
2371 next_port:
547f9a21
EM
2372
2373 phy_info = port_info->phy_info;
2374 for (i = 0; i < port_info->num_phys; i++, phy_info++)
d6ecdd63 2375 mptsas_port_delete(ioc, phy_info->port_details);
547f9a21 2376
e6b2d76a 2377 list_del(&port_info->list);
547f9a21 2378 kfree(port_info->phy_info);
e6b2d76a
ME
2379 kfree(port_info);
2380 }
2381 /*
2382 * Free this memory allocated from inside
2383 * mptsas_sas_expander_pg0
2384 */
547f9a21 2385 kfree(buffer.phy_info);
e6b2d76a
ME
2386 }
2387 mutex_unlock(&ioc->sas_topology_mutex);
2388}
2389
2390/*
2391 * Start of day discovery
2392 */
0c33b27d
CH
2393static void
2394mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
2395{
2396 u32 handle = 0xFFFF;
f44e5461 2397 int i;
0c33b27d 2398
e6b2d76a
ME
2399 mutex_lock(&ioc->sas_discovery_mutex);
2400 mptsas_probe_hba_phys(ioc);
2401 while (!mptsas_probe_expander_phys(ioc, &handle))
0c33b27d 2402 ;
f44e5461
ME
2403 /*
2404 Reporting RAID volumes.
2405 */
b506ade9
EM
2406 if (!ioc->ir_firmware)
2407 goto out;
f44e5461
ME
2408 if (!ioc->raid_data.pIocPg2)
2409 goto out;
2410 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
2411 goto out;
793955f5 2412 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
e8bf3941 2413 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
f44e5461
ME
2414 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
2415 }
2416 out:
e6b2d76a
ME
2417 mutex_unlock(&ioc->sas_discovery_mutex);
2418}
2419
2420/*
2421 * Work queue thread to handle Runtime discovery
2422 * Mere purpose is the hot add/delete of expanders
547f9a21 2423 *(Mutex UNLOCKED)
e6b2d76a
ME
2424 */
2425static void
547f9a21 2426__mptsas_discovery_work(MPT_ADAPTER *ioc)
e6b2d76a 2427{
e6b2d76a
ME
2428 u32 handle = 0xFFFF;
2429
e6b2d76a
ME
2430 ioc->sas_discovery_runtime=1;
2431 mptsas_delete_expander_phys(ioc);
2432 mptsas_probe_hba_phys(ioc);
2433 while (!mptsas_probe_expander_phys(ioc, &handle))
2434 ;
e6b2d76a 2435 ioc->sas_discovery_runtime=0;
547f9a21
EM
2436}
2437
2438/*
2439 * Work queue thread to handle Runtime discovery
2440 * Mere purpose is the hot add/delete of expanders
2441 *(Mutex LOCKED)
2442 */
2443static void
c4028958 2444mptsas_discovery_work(struct work_struct *work)
547f9a21 2445{
c4028958
DH
2446 struct mptsas_discovery_event *ev =
2447 container_of(work, struct mptsas_discovery_event, work);
547f9a21
EM
2448 MPT_ADAPTER *ioc = ev->ioc;
2449
2450 mutex_lock(&ioc->sas_discovery_mutex);
2451 __mptsas_discovery_work(ioc);
e6b2d76a 2452 mutex_unlock(&ioc->sas_discovery_mutex);
547f9a21 2453 kfree(ev);
0c33b27d
CH
2454}
2455
9a28f49a 2456static struct mptsas_phyinfo *
547f9a21 2457mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
9a28f49a
CH
2458{
2459 struct mptsas_portinfo *port_info;
9a28f49a 2460 struct mptsas_phyinfo *phy_info = NULL;
547f9a21 2461 int i;
9a28f49a 2462
9a28f49a
CH
2463 mutex_lock(&ioc->sas_topology_mutex);
2464 list_for_each_entry(port_info, &ioc->sas_topology, list) {
2465 for (i = 0; i < port_info->num_phys; i++) {
b506ade9
EM
2466 if (!mptsas_is_end_device(
2467 &port_info->phy_info[i].attached))
2468 continue;
547f9a21
EM
2469 if (port_info->phy_info[i].attached.sas_address
2470 != sas_address)
2471 continue;
b506ade9
EM
2472 phy_info = &port_info->phy_info[i];
2473 break;
2474 }
2475 }
2476 mutex_unlock(&ioc->sas_topology_mutex);
2477 return phy_info;
2478}
2479
2480static struct mptsas_phyinfo *
2481mptsas_find_phyinfo_by_target(MPT_ADAPTER *ioc, u8 channel, u8 id)
2482{
2483 struct mptsas_portinfo *port_info;
2484 struct mptsas_phyinfo *phy_info = NULL;
2485 int i;
2486
2487 mutex_lock(&ioc->sas_topology_mutex);
2488 list_for_each_entry(port_info, &ioc->sas_topology, list) {
2489 for (i = 0; i < port_info->num_phys; i++) {
547f9a21
EM
2490 if (!mptsas_is_end_device(
2491 &port_info->phy_info[i].attached))
2492 continue;
b506ade9
EM
2493 if (port_info->phy_info[i].attached.id != id)
2494 continue;
2495 if (port_info->phy_info[i].attached.channel != channel)
2496 continue;
547f9a21
EM
2497 phy_info = &port_info->phy_info[i];
2498 break;
9a28f49a
CH
2499 }
2500 }
2501 mutex_unlock(&ioc->sas_topology_mutex);
9a28f49a
CH
2502 return phy_info;
2503}
2504
2505static struct mptsas_phyinfo *
b506ade9 2506mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 channel, u8 id)
9a28f49a
CH
2507{
2508 struct mptsas_portinfo *port_info;
2509 struct mptsas_phyinfo *phy_info = NULL;
2510 int i;
2511
9a28f49a
CH
2512 mutex_lock(&ioc->sas_topology_mutex);
2513 list_for_each_entry(port_info, &ioc->sas_topology, list) {
547f9a21 2514 for (i = 0; i < port_info->num_phys; i++) {
547f9a21
EM
2515 if (!mptsas_is_end_device(
2516 &port_info->phy_info[i].attached))
2517 continue;
b506ade9
EM
2518 if (port_info->phy_info[i].attached.phys_disk_num == ~0)
2519 continue;
2520 if (port_info->phy_info[i].attached.phys_disk_num != id)
2521 continue;
2522 if (port_info->phy_info[i].attached.channel != channel)
2523 continue;
547f9a21
EM
2524 phy_info = &port_info->phy_info[i];
2525 break;
2526 }
9a28f49a
CH
2527 }
2528 mutex_unlock(&ioc->sas_topology_mutex);
9a28f49a
CH
2529 return phy_info;
2530}
2531
4b766471
ME
2532/*
2533 * Work queue thread to clear the persitency table
2534 */
2535static void
c4028958 2536mptsas_persist_clear_table(struct work_struct *work)
4b766471 2537{
c4028958 2538 MPT_ADAPTER *ioc = container_of(work, MPT_ADAPTER, sas_persist_task);
4b766471
ME
2539
2540 mptbase_sas_persist_operation(ioc, MPI_SAS_OP_CLEAR_NOT_PRESENT);
2541}
2542
f44e5461
ME
2543static void
2544mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
2545{
f99be43b
EM
2546 int rc;
2547
f44e5461 2548 sdev->no_uld_attach = data ? 1 : 0;
f99be43b 2549 rc = scsi_device_reprobe(sdev);
f44e5461
ME
2550}
2551
2552static void
2553mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
2554{
2555 starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
2556 mptsas_reprobe_lun);
2557}
2558
b506ade9
EM
2559static void
2560mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
2561{
2562 CONFIGPARMS cfg;
2563 ConfigPageHeader_t hdr;
2564 dma_addr_t dma_handle;
2565 pRaidVolumePage0_t buffer = NULL;
2566 RaidPhysDiskPage0_t phys_disk;
2567 int i;
2568 struct mptsas_hotplug_event *ev;
2569
2570 memset(&cfg, 0 , sizeof(CONFIGPARMS));
2571 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
2572 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
2573 cfg.pageAddr = (channel << 8) + id;
2574 cfg.cfghdr.hdr = &hdr;
2575 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2576
2577 if (mpt_config(ioc, &cfg) != 0)
2578 goto out;
2579
2580 if (!hdr.PageLength)
2581 goto out;
2582
2583 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
2584 &dma_handle);
2585
2586 if (!buffer)
2587 goto out;
2588
2589 cfg.physAddr = dma_handle;
2590 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2591
2592 if (mpt_config(ioc, &cfg) != 0)
2593 goto out;
2594
2595 if (!(buffer->VolumeStatus.Flags &
2596 MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE))
2597 goto out;
2598
2599 if (!buffer->NumPhysDisks)
2600 goto out;
2601
2602 for (i = 0; i < buffer->NumPhysDisks; i++) {
2603
2604 if (mpt_raid_phys_disk_pg0(ioc,
2605 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
2606 continue;
2607
2608 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
2609 if (!ev) {
2610 printk(KERN_WARNING "mptsas: lost hotplug event\n");
2611 goto out;
2612 }
2613
2614 INIT_WORK(&ev->work, mptsas_hotplug_work);
2615 ev->ioc = ioc;
2616 ev->id = phys_disk.PhysDiskID;
2617 ev->channel = phys_disk.PhysDiskBus;
2618 ev->phys_disk_num_valid = 1;
2619 ev->phys_disk_num = phys_disk.PhysDiskNum;
2620 ev->event_type = MPTSAS_ADD_DEVICE;
2621 schedule_work(&ev->work);
2622 }
2623
2624 out:
2625 if (buffer)
2626 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
2627 dma_handle);
2628}
e6b2d76a
ME
2629/*
2630 * Work queue thread to handle SAS hotplug events
2631 */
9a28f49a 2632static void
c4028958 2633mptsas_hotplug_work(struct work_struct *work)
9a28f49a 2634{
c4028958
DH
2635 struct mptsas_hotplug_event *ev =
2636 container_of(work, struct mptsas_hotplug_event, work);
b506ade9 2637
9a28f49a
CH
2638 MPT_ADAPTER *ioc = ev->ioc;
2639 struct mptsas_phyinfo *phy_info;
2640 struct sas_rphy *rphy;
547f9a21 2641 struct sas_port *port;
c73787ee 2642 struct scsi_device *sdev;
547f9a21 2643 struct scsi_target * starget;
f013db32 2644 struct sas_identify identify;
9a28f49a 2645 char *ds = NULL;
c73787ee 2646 struct mptsas_devinfo sas_device;
f44e5461 2647 VirtTarget *vtarget;
547f9a21 2648 VirtDevice *vdevice;
9a28f49a 2649
547f9a21 2650 mutex_lock(&ioc->sas_discovery_mutex);
9a28f49a
CH
2651 switch (ev->event_type) {
2652 case MPTSAS_DEL_DEVICE:
9a28f49a 2653
b506ade9
EM
2654 phy_info = NULL;
2655 if (ev->phys_disk_num_valid) {
2656 if (ev->hidden_raid_component){
2657 if (mptsas_sas_device_pg0(ioc, &sas_device,
2658 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
2659 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2660 (ev->channel << 8) + ev->id)) {
d6ecdd63 2661 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
b506ade9
EM
2662 "%s: exit at line=%d\n", ioc->name,
2663 __FUNCTION__, __LINE__));
2664 break;
2665 }
2666 phy_info = mptsas_find_phyinfo_by_sas_address(
2667 ioc, sas_device.sas_address);
2668 }else
2669 phy_info = mptsas_find_phyinfo_by_phys_disk_num(
2670 ioc, ev->channel, ev->phys_disk_num);
2671 }
2672
2673 if (!phy_info)
2674 phy_info = mptsas_find_phyinfo_by_target(ioc,
2675 ev->channel, ev->id);
e6b2d76a 2676
f44e5461
ME
2677 /*
2678 * Sanity checks, for non-existing phys and remote rphys.
2679 */
b506ade9 2680 if (!phy_info){
d6ecdd63 2681 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
b506ade9
EM
2682 "%s: exit at line=%d\n", ioc->name,
2683 __FUNCTION__, __LINE__));
2684 break;
2685 }
2686 if (!phy_info->port_details) {
d6ecdd63 2687 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2688 "%s: exit at line=%d\n", ioc->name,
2689 __FUNCTION__, __LINE__));
9a28f49a 2690 break;
547f9a21
EM
2691 }
2692 rphy = mptsas_get_rphy(phy_info);
2693 if (!rphy) {
d6ecdd63 2694 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2695 "%s: exit at line=%d\n", ioc->name,
2696 __FUNCTION__, __LINE__));
2697 break;
2698 }
b506ade9 2699
547f9a21
EM
2700 port = mptsas_get_port(phy_info);
2701 if (!port) {
d6ecdd63 2702 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2703 "%s: exit at line=%d\n", ioc->name,
2704 __FUNCTION__, __LINE__));
f44e5461 2705 break;
547f9a21
EM
2706 }
2707
2708 starget = mptsas_get_starget(phy_info);
2709 if (starget) {
2710 vtarget = starget->hostdata;
f44e5461 2711
547f9a21 2712 if (!vtarget) {
d6ecdd63 2713 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2714 "%s: exit at line=%d\n", ioc->name,
2715 __FUNCTION__, __LINE__));
f44e5461 2716 break;
547f9a21
EM
2717 }
2718
f44e5461
ME
2719 /*
2720 * Handling RAID components
2721 */
b506ade9
EM
2722 if (ev->phys_disk_num_valid &&
2723 ev->hidden_raid_component) {
2724 printk(MYIOC_s_INFO_FMT
2725 "RAID Hidding: channel=%d, id=%d, "
2726 "physdsk %d \n", ioc->name, ev->channel,
2727 ev->id, ev->phys_disk_num);
793955f5 2728 vtarget->id = ev->phys_disk_num;
b506ade9
EM
2729 vtarget->tflags |=
2730 MPT_TARGET_FLAGS_RAID_COMPONENT;
547f9a21 2731 mptsas_reprobe_target(starget, 1);
b506ade9
EM
2732 phy_info->attached.phys_disk_num =
2733 ev->phys_disk_num;
2734 break;
f44e5461 2735 }
9a28f49a
CH
2736 }
2737
b506ade9
EM
2738 if (phy_info->attached.device_info &
2739 MPI_SAS_DEVICE_INFO_SSP_TARGET)
c73787ee 2740 ds = "ssp";
b506ade9
EM
2741 if (phy_info->attached.device_info &
2742 MPI_SAS_DEVICE_INFO_STP_TARGET)
c73787ee 2743 ds = "stp";
b506ade9
EM
2744 if (phy_info->attached.device_info &
2745 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
c73787ee
ME
2746 ds = "sata";
2747
2748 printk(MYIOC_s_INFO_FMT
2749 "removing %s device, channel %d, id %d, phy %d\n",
2750 ioc->name, ds, ev->channel, ev->id, phy_info->phy_id);
dc22f16d
EM
2751 dev_printk(KERN_DEBUG, &port->dev,
2752 "delete port (%d)\n", port->port_identifier);
547f9a21 2753 sas_port_delete(port);
d6ecdd63 2754 mptsas_port_delete(ioc, phy_info->port_details);
9a28f49a
CH
2755 break;
2756 case MPTSAS_ADD_DEVICE:
c73787ee 2757
bd23e94c
ME
2758 if (ev->phys_disk_num_valid)
2759 mpt_findImVolumes(ioc);
2760
c73787ee 2761 /*
e3094447 2762 * Refresh sas device pg0 data
c73787ee 2763 */
e3094447
CH
2764 if (mptsas_sas_device_pg0(ioc, &sas_device,
2765 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
b506ade9
EM
2766 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
2767 (ev->channel << 8) + ev->id)) {
d6ecdd63 2768 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2769 "%s: exit at line=%d\n", ioc->name,
2770 __FUNCTION__, __LINE__));
e3094447 2771 break;
547f9a21 2772 }
9a28f49a 2773
547f9a21 2774 __mptsas_discovery_work(ioc);
e6b2d76a 2775
547f9a21
EM
2776 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
2777 sas_device.sas_address);
e6b2d76a 2778
547f9a21 2779 if (!phy_info || !phy_info->port_details) {
d6ecdd63 2780 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2781 "%s: exit at line=%d\n", ioc->name,
2782 __FUNCTION__, __LINE__));
2783 break;
e6b2d76a
ME
2784 }
2785
547f9a21 2786 starget = mptsas_get_starget(phy_info);
b506ade9
EM
2787 if (starget && (!ev->hidden_raid_component)){
2788
547f9a21 2789 vtarget = starget->hostdata;
9a28f49a 2790
547f9a21 2791 if (!vtarget) {
d6ecdd63 2792 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2793 "%s: exit at line=%d\n", ioc->name,
2794 __FUNCTION__, __LINE__));
f44e5461 2795 break;
547f9a21 2796 }
f44e5461
ME
2797 /*
2798 * Handling RAID components
2799 */
2800 if (vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) {
b506ade9
EM
2801 printk(MYIOC_s_INFO_FMT
2802 "RAID Exposing: channel=%d, id=%d, "
2803 "physdsk %d \n", ioc->name, ev->channel,
2804 ev->id, ev->phys_disk_num);
2805 vtarget->tflags &=
2806 ~MPT_TARGET_FLAGS_RAID_COMPONENT;
793955f5 2807 vtarget->id = ev->id;
547f9a21 2808 mptsas_reprobe_target(starget, 0);
b506ade9 2809 phy_info->attached.phys_disk_num = ~0;
f44e5461 2810 }
9a28f49a
CH
2811 break;
2812 }
2813
547f9a21 2814 if (mptsas_get_rphy(phy_info)) {
d6ecdd63 2815 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2816 "%s: exit at line=%d\n", ioc->name,
2817 __FUNCTION__, __LINE__));
b506ade9 2818 if (ev->channel) printk("%d\n", __LINE__);
f44e5461 2819 break;
547f9a21 2820 }
b506ade9 2821
547f9a21
EM
2822 port = mptsas_get_port(phy_info);
2823 if (!port) {
d6ecdd63 2824 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2825 "%s: exit at line=%d\n", ioc->name,
2826 __FUNCTION__, __LINE__));
2827 break;
2828 }
e3094447
CH
2829 memcpy(&phy_info->attached, &sas_device,
2830 sizeof(struct mptsas_devinfo));
9a28f49a 2831
b506ade9
EM
2832 if (phy_info->attached.device_info &
2833 MPI_SAS_DEVICE_INFO_SSP_TARGET)
c73787ee 2834 ds = "ssp";
b506ade9
EM
2835 if (phy_info->attached.device_info &
2836 MPI_SAS_DEVICE_INFO_STP_TARGET)
c73787ee 2837 ds = "stp";
b506ade9
EM
2838 if (phy_info->attached.device_info &
2839 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
c73787ee
ME
2840 ds = "sata";
2841
2842 printk(MYIOC_s_INFO_FMT
2843 "attaching %s device, channel %d, id %d, phy %d\n",
2844 ioc->name, ds, ev->channel, ev->id, ev->phy_id);
2845
f013db32 2846 mptsas_parse_device_info(&identify, &phy_info->attached);
547f9a21
EM
2847 rphy = sas_end_device_alloc(port);
2848 if (!rphy) {
d6ecdd63 2849 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2850 "%s: exit at line=%d\n", ioc->name,
2851 __FUNCTION__, __LINE__));
9a28f49a 2852 break; /* non-fatal: an rphy can be added later */
547f9a21 2853 }
9a28f49a 2854
f013db32 2855 rphy->identify = identify;
9a28f49a 2856 if (sas_rphy_add(rphy)) {
d6ecdd63 2857 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21
EM
2858 "%s: exit at line=%d\n", ioc->name,
2859 __FUNCTION__, __LINE__));
9a28f49a
CH
2860 sas_rphy_free(rphy);
2861 break;
2862 }
d6ecdd63 2863 mptsas_set_rphy(ioc, phy_info, rphy);
9a28f49a 2864 break;
c73787ee 2865 case MPTSAS_ADD_RAID:
e8bf3941
JB
2866 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
2867 ev->id, 0);
c73787ee
ME
2868 if (sdev) {
2869 scsi_device_put(sdev);
2870 break;
2871 }
2872 printk(MYIOC_s_INFO_FMT
4b766471 2873 "attaching raid volume, channel %d, id %d\n",
e8bf3941
JB
2874 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
2875 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL, ev->id, 0);
c73787ee
ME
2876 mpt_findImVolumes(ioc);
2877 break;
2878 case MPTSAS_DEL_RAID:
e8bf3941 2879 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
b506ade9 2880 ev->id, 0);
c73787ee
ME
2881 if (!sdev)
2882 break;
2883 printk(MYIOC_s_INFO_FMT
4b766471 2884 "removing raid volume, channel %d, id %d\n",
e8bf3941 2885 ioc->name, MPTSAS_RAID_CHANNEL, ev->id);
b506ade9 2886 vdevice = sdev->hostdata;
c73787ee
ME
2887 scsi_remove_device(sdev);
2888 scsi_device_put(sdev);
2889 mpt_findImVolumes(ioc);
2890 break;
b506ade9
EM
2891 case MPTSAS_ADD_INACTIVE_VOLUME:
2892 mptsas_adding_inactive_raid_components(ioc,
2893 ev->channel, ev->id);
2894 break;
bd23e94c
ME
2895 case MPTSAS_IGNORE_EVENT:
2896 default:
2897 break;
9a28f49a
CH
2898 }
2899
e6b2d76a 2900 mutex_unlock(&ioc->sas_discovery_mutex);
547f9a21 2901 kfree(ev);
9a28f49a
CH
2902}
2903
2904static void
547f9a21 2905mptsas_send_sas_event(MPT_ADAPTER *ioc,
9a28f49a
CH
2906 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
2907{
2908 struct mptsas_hotplug_event *ev;
2909 u32 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
2910 __le64 sas_address;
2911
2912 if ((device_info &
2913 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
2914 MPI_SAS_DEVICE_INFO_STP_TARGET |
2915 MPI_SAS_DEVICE_INFO_SATA_DEVICE )) == 0)
2916 return;
2917
4b766471 2918 switch (sas_event_data->ReasonCode) {
4b766471 2919 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
df9e062a
EM
2920
2921 mptsas_target_reset_queue(ioc, sas_event_data);
2922 break;
2923
2924 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
547f9a21 2925 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
4b766471
ME
2926 if (!ev) {
2927 printk(KERN_WARNING "mptsas: lost hotplug event\n");
2928 break;
2929 }
9a28f49a 2930
c4028958 2931 INIT_WORK(&ev->work, mptsas_hotplug_work);
4b766471
ME
2932 ev->ioc = ioc;
2933 ev->handle = le16_to_cpu(sas_event_data->DevHandle);
2934 ev->parent_handle =
2935 le16_to_cpu(sas_event_data->ParentDevHandle);
2936 ev->channel = sas_event_data->Bus;
2937 ev->id = sas_event_data->TargetID;
2938 ev->phy_id = sas_event_data->PhyNum;
2939 memcpy(&sas_address, &sas_event_data->SASAddress,
2940 sizeof(__le64));
2941 ev->sas_address = le64_to_cpu(sas_address);
2942 ev->device_info = device_info;
2943
2944 if (sas_event_data->ReasonCode &
2945 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
2946 ev->event_type = MPTSAS_ADD_DEVICE;
2947 else
2948 ev->event_type = MPTSAS_DEL_DEVICE;
2949 schedule_work(&ev->work);
2950 break;
2951 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
2952 /*
2953 * Persistent table is full.
2954 */
547f9a21 2955 INIT_WORK(&ioc->sas_persist_task,
c4028958 2956 mptsas_persist_clear_table);
547f9a21 2957 schedule_work(&ioc->sas_persist_task);
4b766471 2958 break;
b506ade9
EM
2959 /*
2960 * TODO, handle other events
2961 */
4b766471 2962 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
b506ade9 2963 case MPI_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
4b766471 2964 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
b506ade9
EM
2965 case MPI_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
2966 case MPI_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
2967 case MPI_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
2968 case MPI_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
4b766471
ME
2969 default:
2970 break;
9a28f49a 2971 }
9a28f49a 2972}
c73787ee 2973static void
547f9a21 2974mptsas_send_raid_event(MPT_ADAPTER *ioc,
c73787ee
ME
2975 EVENT_DATA_RAID *raid_event_data)
2976{
2977 struct mptsas_hotplug_event *ev;
bd23e94c
ME
2978 int status = le32_to_cpu(raid_event_data->SettingsStatus);
2979 int state = (status >> 8) & 0xff;
c73787ee
ME
2980
2981 if (ioc->bus_type != SAS)
2982 return;
2983
547f9a21 2984 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
c73787ee
ME
2985 if (!ev) {
2986 printk(KERN_WARNING "mptsas: lost hotplug event\n");
2987 return;
2988 }
2989
c4028958 2990 INIT_WORK(&ev->work, mptsas_hotplug_work);
c73787ee
ME
2991 ev->ioc = ioc;
2992 ev->id = raid_event_data->VolumeID;
b506ade9 2993 ev->channel = raid_event_data->VolumeBus;
bd23e94c 2994 ev->event_type = MPTSAS_IGNORE_EVENT;
c73787ee
ME
2995
2996 switch (raid_event_data->ReasonCode) {
2997 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
b506ade9
EM
2998 ev->phys_disk_num_valid = 1;
2999 ev->phys_disk_num = raid_event_data->PhysDiskNum;
c73787ee
ME
3000 ev->event_type = MPTSAS_ADD_DEVICE;
3001 break;
3002 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
f44e5461
ME
3003 ev->phys_disk_num_valid = 1;
3004 ev->phys_disk_num = raid_event_data->PhysDiskNum;
b506ade9 3005 ev->hidden_raid_component = 1;
c73787ee
ME
3006 ev->event_type = MPTSAS_DEL_DEVICE;
3007 break;
bd23e94c
ME
3008 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
3009 switch (state) {
3010 case MPI_PD_STATE_ONLINE:
b506ade9 3011 case MPI_PD_STATE_NOT_COMPATIBLE:
bd23e94c
ME
3012 ev->phys_disk_num_valid = 1;
3013 ev->phys_disk_num = raid_event_data->PhysDiskNum;
b506ade9 3014 ev->hidden_raid_component = 1;
bd23e94c
ME
3015 ev->event_type = MPTSAS_ADD_DEVICE;
3016 break;
3017 case MPI_PD_STATE_MISSING:
bd23e94c
ME
3018 case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
3019 case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
3020 case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
b506ade9
EM
3021 ev->phys_disk_num_valid = 1;
3022 ev->phys_disk_num = raid_event_data->PhysDiskNum;
bd23e94c
ME
3023 ev->event_type = MPTSAS_DEL_DEVICE;
3024 break;
3025 default:
3026 break;
3027 }
3028 break;
c73787ee
ME
3029 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
3030 ev->event_type = MPTSAS_DEL_RAID;
3031 break;
3032 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
3033 ev->event_type = MPTSAS_ADD_RAID;
3034 break;
3035 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
bd23e94c
ME
3036 switch (state) {
3037 case MPI_RAIDVOL0_STATUS_STATE_FAILED:
3038 case MPI_RAIDVOL0_STATUS_STATE_MISSING:
3039 ev->event_type = MPTSAS_DEL_RAID;
3040 break;
3041 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
3042 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
3043 ev->event_type = MPTSAS_ADD_RAID;
3044 break;
3045 default:
3046 break;
3047 }
c73787ee
ME
3048 break;
3049 default:
3050 break;
3051 }
3052 schedule_work(&ev->work);
3053}
3054
e6b2d76a 3055static void
547f9a21 3056mptsas_send_discovery_event(MPT_ADAPTER *ioc,
e6b2d76a
ME
3057 EVENT_DATA_SAS_DISCOVERY *discovery_data)
3058{
3059 struct mptsas_discovery_event *ev;
3060
3061 /*
3062 * DiscoveryStatus
3063 *
3064 * This flag will be non-zero when firmware
3065 * kicks off discovery, and return to zero
3066 * once its completed.
3067 */
3068 if (discovery_data->DiscoveryStatus)
3069 return;
3070
547f9a21 3071 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
e6b2d76a
ME
3072 if (!ev)
3073 return;
c4028958 3074 INIT_WORK(&ev->work, mptsas_discovery_work);
e6b2d76a
ME
3075 ev->ioc = ioc;
3076 schedule_work(&ev->work);
3077};
3078
b506ade9
EM
3079/*
3080 * mptsas_send_ir2_event - handle exposing hidden disk when
3081 * an inactive raid volume is added
3082 *
3083 * @ioc: Pointer to MPT_ADAPTER structure
3084 * @ir2_data
3085 *
3086 */
3087static void
3088mptsas_send_ir2_event(MPT_ADAPTER *ioc, PTR_MPI_EVENT_DATA_IR2 ir2_data)
3089{
3090 struct mptsas_hotplug_event *ev;
3091
3092 if (ir2_data->ReasonCode !=
3093 MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED)
3094 return;
3095
3096 ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
3097 if (!ev)
3098 return;
3099
3100 INIT_WORK(&ev->work, mptsas_hotplug_work);
3101 ev->ioc = ioc;
3102 ev->id = ir2_data->TargetID;
3103 ev->channel = ir2_data->Bus;
3104 ev->event_type = MPTSAS_ADD_INACTIVE_VOLUME;
3105
3106 schedule_work(&ev->work);
3107};
e6b2d76a 3108
9a28f49a
CH
3109static int
3110mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
3111{
c73787ee 3112 int rc=1;
9a28f49a
CH
3113 u8 event = le32_to_cpu(reply->Event) & 0xFF;
3114
3115 if (!ioc->sh)
c73787ee 3116 goto out;
9a28f49a 3117
e6b2d76a
ME
3118 /*
3119 * sas_discovery_ignore_events
3120 *
3121 * This flag is to prevent anymore processing of
3122 * sas events once mptsas_remove function is called.
3123 */
3124 if (ioc->sas_discovery_ignore_events) {
3125 rc = mptscsih_event_process(ioc, reply);
3126 goto out;
3127 }
3128
9a28f49a
CH
3129 switch (event) {
3130 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
547f9a21 3131 mptsas_send_sas_event(ioc,
9a28f49a 3132 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data);
c73787ee
ME
3133 break;
3134 case MPI_EVENT_INTEGRATED_RAID:
547f9a21 3135 mptsas_send_raid_event(ioc,
c73787ee
ME
3136 (EVENT_DATA_RAID *)reply->Data);
3137 break;
79de278e 3138 case MPI_EVENT_PERSISTENT_TABLE_FULL:
547f9a21 3139 INIT_WORK(&ioc->sas_persist_task,
c4028958 3140 mptsas_persist_clear_table);
547f9a21 3141 schedule_work(&ioc->sas_persist_task);
79de278e 3142 break;
4b766471 3143 case MPI_EVENT_SAS_DISCOVERY:
547f9a21 3144 mptsas_send_discovery_event(ioc,
e6b2d76a
ME
3145 (EVENT_DATA_SAS_DISCOVERY *)reply->Data);
3146 break;
b506ade9
EM
3147 case MPI_EVENT_IR2:
3148 mptsas_send_ir2_event(ioc,
3149 (PTR_MPI_EVENT_DATA_IR2)reply->Data);
3150 break;
9a28f49a 3151 default:
c73787ee
ME
3152 rc = mptscsih_event_process(ioc, reply);
3153 break;
9a28f49a 3154 }
c73787ee
ME
3155 out:
3156
3157 return rc;
9a28f49a
CH
3158}
3159
0c33b27d
CH
3160static int
3161mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
3162{
3163 struct Scsi_Host *sh;
3164 MPT_SCSI_HOST *hd;
3165 MPT_ADAPTER *ioc;
3166 unsigned long flags;
1ca00bb7 3167 int ii;
0c33b27d
CH
3168 int numSGE = 0;
3169 int scale;
3170 int ioc_cap;
0c33b27d
CH
3171 int error=0;
3172 int r;
3173
3174 r = mpt_attach(pdev,id);
3175 if (r)
3176 return r;
3177
3178 ioc = pci_get_drvdata(pdev);
3179 ioc->DoneCtx = mptsasDoneCtx;
3180 ioc->TaskCtx = mptsasTaskCtx;
3181 ioc->InternalCtx = mptsasInternalCtx;
3182
3183 /* Added sanity check on readiness of the MPT adapter.
3184 */
3185 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
3186 printk(MYIOC_s_WARN_FMT
3187 "Skipping because it's not operational!\n",
3188 ioc->name);
7acec1e7
MED
3189 error = -ENODEV;
3190 goto out_mptsas_probe;
0c33b27d
CH
3191 }
3192
3193 if (!ioc->active) {
3194 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
3195 ioc->name);
7acec1e7
MED
3196 error = -ENODEV;
3197 goto out_mptsas_probe;
0c33b27d
CH
3198 }
3199
3200 /* Sanity check - ensure at least 1 port is INITIATOR capable
3201 */
3202 ioc_cap = 0;
3203 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
3204 if (ioc->pfacts[ii].ProtocolFlags &
3205 MPI_PORTFACTS_PROTOCOL_INITIATOR)
3206 ioc_cap++;
3207 }
3208
3209 if (!ioc_cap) {
3210 printk(MYIOC_s_WARN_FMT
3211 "Skipping ioc=%p because SCSI Initiator mode "
3212 "is NOT enabled!\n", ioc->name, ioc);
466544d8 3213 return 0;
0c33b27d
CH
3214 }
3215
3216 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
3217 if (!sh) {
3218 printk(MYIOC_s_WARN_FMT
3219 "Unable to register controller with SCSI subsystem\n",
3220 ioc->name);
7acec1e7
MED
3221 error = -1;
3222 goto out_mptsas_probe;
0c33b27d
CH
3223 }
3224
3225 spin_lock_irqsave(&ioc->FreeQlock, flags);
3226
3227 /* Attach the SCSI Host to the IOC structure
3228 */
3229 ioc->sh = sh;
3230
3231 sh->io_port = 0;
3232 sh->n_io_port = 0;
3233 sh->irq = 0;
3234
3235 /* set 16 byte cdb's */
3236 sh->max_cmd_len = 16;
3237
793955f5
EM
3238 sh->max_id = ioc->pfacts[0].PortSCSIID;
3239 sh->max_lun = max_lun;
0c33b27d
CH
3240
3241 sh->transportt = mptsas_transport_template;
3242
0c33b27d
CH
3243 sh->this_id = ioc->pfacts[0].PortSCSIID;
3244
3245 /* Required entry.
3246 */
3247 sh->unique_id = ioc->id;
3248
3249 INIT_LIST_HEAD(&ioc->sas_topology);
9a28f49a 3250 mutex_init(&ioc->sas_topology_mutex);
e6b2d76a 3251 mutex_init(&ioc->sas_discovery_mutex);
eeb846ce 3252 mutex_init(&ioc->sas_mgmt.mutex);
da4fa655 3253 init_completion(&ioc->sas_mgmt.done);
0c33b27d
CH
3254
3255 /* Verify that we won't exceed the maximum
3256 * number of chain buffers
3257 * We can optimize: ZZ = req_sz/sizeof(SGE)
3258 * For 32bit SGE's:
3259 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
3260 * + (req_sz - 64)/sizeof(SGE)
3261 * A slightly different algorithm is required for
3262 * 64bit SGEs.
3263 */
3264 scale = ioc->req_sz/(sizeof(dma_addr_t) + sizeof(u32));
3265 if (sizeof(dma_addr_t) == sizeof(u64)) {
3266 numSGE = (scale - 1) *
3267 (ioc->facts.MaxChainDepth-1) + scale +
3268 (ioc->req_sz - 60) / (sizeof(dma_addr_t) +
3269 sizeof(u32));
3270 } else {
3271 numSGE = 1 + (scale - 1) *
3272 (ioc->facts.MaxChainDepth-1) + scale +
3273 (ioc->req_sz - 64) / (sizeof(dma_addr_t) +
3274 sizeof(u32));
3275 }
3276
3277 if (numSGE < sh->sg_tablesize) {
3278 /* Reset this value */
d6ecdd63 3279 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
0c33b27d
CH
3280 "Resetting sg_tablesize to %d from %d\n",
3281 ioc->name, numSGE, sh->sg_tablesize));
3282 sh->sg_tablesize = numSGE;
3283 }
3284
0c33b27d
CH
3285 hd = (MPT_SCSI_HOST *) sh->hostdata;
3286 hd->ioc = ioc;
3287
3288 /* SCSI needs scsi_cmnd lookup table!
3289 * (with size equal to req_depth*PtrSz!)
3290 */
1ca00bb7
CH
3291 hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
3292 if (!hd->ScsiLookup) {
0c33b27d 3293 error = -ENOMEM;
7acec1e7 3294 goto out_mptsas_probe;
0c33b27d
CH
3295 }
3296
d6ecdd63 3297 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
1ca00bb7 3298 ioc->name, hd->ScsiLookup));
0c33b27d 3299
0c33b27d
CH
3300 /* Clear the TM flags
3301 */
3302 hd->tmPending = 0;
3303 hd->tmState = TM_STATE_NONE;
3304 hd->resetPending = 0;
3305 hd->abortSCpnt = NULL;
3306
3307 /* Clear the pointer used to store
3308 * single-threaded commands, i.e., those
3309 * issued during a bus scan, dv and
3310 * configuration pages.
3311 */
3312 hd->cmdPtr = NULL;
3313
3314 /* Initialize this SCSI Hosts' timers
3315 * To use, set the timer expires field
3316 * and add_timer
3317 */
3318 init_timer(&hd->timer);
3319 hd->timer.data = (unsigned long) hd;
3320 hd->timer.function = mptscsih_timer_expired;
3321
0c33b27d
CH
3322 ioc->sas_data.ptClear = mpt_pt_clear;
3323
df9e062a
EM
3324 init_waitqueue_head(&hd->scandv_waitq);
3325 hd->scandv_wait_done = 0;
3326 hd->last_queue_full = 0;
3327 INIT_LIST_HEAD(&hd->target_reset_list);
3328 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
3329
0c33b27d
CH
3330 if (ioc->sas_data.ptClear==1) {
3331 mptbase_sas_persist_operation(
3332 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
3333 }
3334
0c33b27d
CH
3335 error = scsi_add_host(sh, &ioc->pcidev->dev);
3336 if (error) {
d6ecdd63 3337 dprintk(ioc, printk(KERN_ERR MYNAM
0c33b27d 3338 "scsi_add_host failed\n"));
7acec1e7 3339 goto out_mptsas_probe;
0c33b27d
CH
3340 }
3341
3342 mptsas_scan_sas_topology(ioc);
3343
3344 return 0;
3345
547f9a21 3346 out_mptsas_probe:
0c33b27d
CH
3347
3348 mptscsih_remove(pdev);
3349 return error;
3350}
3351
3352static void __devexit mptsas_remove(struct pci_dev *pdev)
3353{
3354 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
3355 struct mptsas_portinfo *p, *n;
547f9a21 3356 int i;
0c33b27d 3357
b506ade9 3358 ioc->sas_discovery_ignore_events = 1;
0c33b27d
CH
3359 sas_remove_host(ioc->sh);
3360
9a28f49a 3361 mutex_lock(&ioc->sas_topology_mutex);
0c33b27d
CH
3362 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
3363 list_del(&p->list);
547f9a21 3364 for (i = 0 ; i < p->num_phys ; i++)
d6ecdd63 3365 mptsas_port_delete(ioc, p->phy_info[i].port_details);
547f9a21 3366 kfree(p->phy_info);
0c33b27d
CH
3367 kfree(p);
3368 }
9a28f49a 3369 mutex_unlock(&ioc->sas_topology_mutex);
0c33b27d
CH
3370
3371 mptscsih_remove(pdev);
3372}
3373
3374static struct pci_device_id mptsas_pci_table[] = {
87cf8986 3375 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
0c33b27d 3376 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 3377 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
0c33b27d 3378 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 3379 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E,
0c33b27d 3380 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 3381 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E,
0c33b27d 3382 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 3383 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
0c33b27d
CH
3384 PCI_ANY_ID, PCI_ANY_ID },
3385 {0} /* Terminating entry */
3386};
3387MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
3388
3389
3390static struct pci_driver mptsas_driver = {
3391 .name = "mptsas",
3392 .id_table = mptsas_pci_table,
3393 .probe = mptsas_probe,
3394 .remove = __devexit_p(mptsas_remove),
3395 .shutdown = mptscsih_shutdown,
3396#ifdef CONFIG_PM
3397 .suspend = mptscsih_suspend,
3398 .resume = mptscsih_resume,
3399#endif
3400};
3401
3402static int __init
3403mptsas_init(void)
3404{
57ce21bf
PS
3405 int error;
3406
0c33b27d
CH
3407 show_mptmod_ver(my_NAME, my_VERSION);
3408
3409 mptsas_transport_template =
3410 sas_attach_transport(&mptsas_transport_functions);
3411 if (!mptsas_transport_template)
3412 return -ENODEV;
3413
3414 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER);
df9e062a 3415 mptsasTaskCtx = mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER);
0c33b27d
CH
3416 mptsasInternalCtx =
3417 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER);
da4fa655 3418 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER);
0c33b27d 3419
d6ecdd63
PS
3420 mpt_event_register(mptsasDoneCtx, mptsas_event_process);
3421 mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset);
0c33b27d 3422
57ce21bf
PS
3423 error = pci_register_driver(&mptsas_driver);
3424 if (error)
3425 sas_release_transport(mptsas_transport_template);
3426
3427 return error;
0c33b27d
CH
3428}
3429
3430static void __exit
3431mptsas_exit(void)
3432{
3433 pci_unregister_driver(&mptsas_driver);
3434 sas_release_transport(mptsas_transport_template);
3435
3436 mpt_reset_deregister(mptsasDoneCtx);
3437 mpt_event_deregister(mptsasDoneCtx);
3438
da4fa655 3439 mpt_deregister(mptsasMgmtCtx);
0c33b27d
CH
3440 mpt_deregister(mptsasInternalCtx);
3441 mpt_deregister(mptsasTaskCtx);
3442 mpt_deregister(mptsasDoneCtx);
3443}
3444
3445module_init(mptsas_init);
3446module_exit(mptsas_exit);
This page took 2.530061 seconds and 5 git commands to generate.