]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blame - drivers/message/fusion/mptsas.c
tree-wide: fix comment/printk typos
[mirror_ubuntu-eoan-kernel.git] / drivers / message / fusion / mptsas.c
CommitLineData
0c33b27d
CH
1/*
2 * linux/drivers/message/fusion/mptsas.c
f36789e2
PS
3 * For use with LSI PCI chip/adapter(s)
4 * running LSI Fusion MPT (Message Passing Technology) firmware.
0c33b27d 5 *
cddc0ab7 6 * Copyright (c) 1999-2008 LSI Corporation
16d20101 7 * (mailto:DL-MPTFusionLinux@lsi.com)
0c33b27d
CH
8 */
9/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
10/*
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; version 2 of the License.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 NO WARRANTY
21 THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
22 CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
23 LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
24 MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
25 solely responsible for determining the appropriateness of using and
26 distributing the Program and assumes all risks associated with its
27 exercise of rights under this Agreement, including but not limited to
28 the risks and costs of program errors, damage to or loss of data,
29 programs or equipment, and unavailability or interruption of operations.
30
31 DISCLAIMER OF LIABILITY
32 NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
33 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
35 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
36 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
37 USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
38 HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
39
40 You should have received a copy of the GNU General Public License
41 along with this program; if not, write to the Free Software
42 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
43*/
44/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/
45
46#include <linux/module.h>
47#include <linux/kernel.h>
5a0e3ad6 48#include <linux/slab.h>
0c33b27d
CH
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>
c9de7dc4 60#include <scsi/scsi_transport.h>
547f9a21 61#include <scsi/scsi_dbg.h>
0c33b27d
CH
62
63#include "mptbase.h"
64#include "mptscsih.h"
56af97ae 65#include "mptsas.h"
0c33b27d
CH
66
67
68#define my_NAME "Fusion MPT SAS Host driver"
69#define my_VERSION MPT_LINUX_VERSION_COMMON
70#define MYNAM "mptsas"
71
e8bf3941
JB
72/*
73 * Reserved channel for integrated raid
74 */
75#define MPTSAS_RAID_CHANNEL 1
76
4b97650b 77#define SAS_CONFIG_PAGE_TIMEOUT 30
0c33b27d
CH
78MODULE_AUTHOR(MODULEAUTHOR);
79MODULE_DESCRIPTION(my_NAME);
80MODULE_LICENSE("GPL");
9f4203b3 81MODULE_VERSION(my_VERSION);
0c33b27d 82
0c33b27d
CH
83static int mpt_pt_clear;
84module_param(mpt_pt_clear, int, 0);
85MODULE_PARM_DESC(mpt_pt_clear,
ba856d32 86 " Clear persistency table: enable=1 "
0c33b27d
CH
87 "(default=MPTSCSIH_PT_CLEAR=0)");
88
793955f5
EM
89/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
90#define MPTSAS_MAX_LUN (16895)
91static int max_lun = MPTSAS_MAX_LUN;
92module_param(max_lun, int, 0);
93MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
94
f606f571
PS
95static u8 mptsasDoneCtx = MPT_MAX_PROTOCOL_DRIVERS;
96static u8 mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS;
97static u8 mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */
98static u8 mptsasMgmtCtx = MPT_MAX_PROTOCOL_DRIVERS;
e7deff33 99static u8 mptsasDeviceResetCtx = MPT_MAX_PROTOCOL_DRIVERS;
0c33b27d 100
3eb0822c
KD
101static void mptsas_firmware_event_work(struct work_struct *work);
102static void mptsas_send_sas_event(struct fw_event_work *fw_event);
103static void mptsas_send_raid_event(struct fw_event_work *fw_event);
104static void mptsas_send_ir2_event(struct fw_event_work *fw_event);
105static void mptsas_parse_device_info(struct sas_identify *identify,
106 struct mptsas_devinfo *device_info);
107static inline void mptsas_set_rphy(MPT_ADAPTER *ioc,
108 struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy);
109static struct mptsas_phyinfo *mptsas_find_phyinfo_by_sas_address
110 (MPT_ADAPTER *ioc, u64 sas_address);
111static int mptsas_sas_device_pg0(MPT_ADAPTER *ioc,
112 struct mptsas_devinfo *device_info, u32 form, u32 form_specific);
113static int mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc,
114 struct mptsas_enclosure *enclosure, u32 form, u32 form_specific);
115static int mptsas_add_end_device(MPT_ADAPTER *ioc,
116 struct mptsas_phyinfo *phy_info);
117static void mptsas_del_end_device(MPT_ADAPTER *ioc,
118 struct mptsas_phyinfo *phy_info);
f9c34022
KD
119static void mptsas_send_link_status_event(struct fw_event_work *fw_event);
120static struct mptsas_portinfo *mptsas_find_portinfo_by_sas_address
121 (MPT_ADAPTER *ioc, u64 sas_address);
122static void mptsas_expander_delete(MPT_ADAPTER *ioc,
123 struct mptsas_portinfo *port_info, u8 force);
124static void mptsas_send_expander_event(struct fw_event_work *fw_event);
eedf92b9
KD
125static void mptsas_not_responding_devices(MPT_ADAPTER *ioc);
126static void mptsas_scan_sas_topology(MPT_ADAPTER *ioc);
db7051b2 127static void mptsas_broadcast_primative_work(struct fw_event_work *fw_event);
57e98513 128static void mptsas_handle_queue_full_event(struct fw_event_work *fw_event);
a7938b0b 129static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id);
b68bf096 130void mptsas_schedule_target_reset(void *ioc);
0c33b27d 131
d6ecdd63
PS
132static void mptsas_print_phy_data(MPT_ADAPTER *ioc,
133 MPI_SAS_IO_UNIT0_PHY_DATA *phy_data)
134{
29dd3609
EM
135 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
136 "---- IO UNIT PAGE 0 ------------\n", ioc->name));
137 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n",
138 ioc->name, le16_to_cpu(phy_data->AttachedDeviceHandle)));
139 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Controller Handle=0x%X\n",
140 ioc->name, le16_to_cpu(phy_data->ControllerDevHandle)));
141 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port=0x%X\n",
142 ioc->name, phy_data->Port));
143 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port Flags=0x%X\n",
144 ioc->name, phy_data->PortFlags));
145 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Flags=0x%X\n",
146 ioc->name, phy_data->PhyFlags));
147 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n",
148 ioc->name, phy_data->NegotiatedLinkRate));
149 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
150 "Controller PHY Device Info=0x%X\n", ioc->name,
151 le32_to_cpu(phy_data->ControllerPhyDeviceInfo)));
152 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DiscoveryStatus=0x%X\n\n",
153 ioc->name, le32_to_cpu(phy_data->DiscoveryStatus)));
b5141128
CH
154}
155
d6ecdd63 156static void mptsas_print_phy_pg0(MPT_ADAPTER *ioc, SasPhyPage0_t *pg0)
b5141128
CH
157{
158 __le64 sas_address;
159
160 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
161
29dd3609
EM
162 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
163 "---- SAS PHY PAGE 0 ------------\n", ioc->name));
164 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
165 "Attached Device Handle=0x%X\n", ioc->name,
166 le16_to_cpu(pg0->AttachedDevHandle)));
167 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n",
168 ioc->name, (unsigned long long)le64_to_cpu(sas_address)));
169 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
170 "Attached PHY Identifier=0x%X\n", ioc->name,
171 pg0->AttachedPhyIdentifier));
172 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Attached Device Info=0x%X\n",
173 ioc->name, le32_to_cpu(pg0->AttachedDeviceInfo)));
174 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n",
175 ioc->name, pg0->ProgrammedLinkRate));
176 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Change Count=0x%X\n",
177 ioc->name, pg0->ChangeCount));
178 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Info=0x%X\n\n",
179 ioc->name, le32_to_cpu(pg0->PhyInfo)));
b5141128
CH
180}
181
d6ecdd63 182static void mptsas_print_phy_pg1(MPT_ADAPTER *ioc, SasPhyPage1_t *pg1)
b5141128 183{
29dd3609
EM
184 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
185 "---- SAS PHY PAGE 1 ------------\n", ioc->name));
186 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Invalid Dword Count=0x%x\n",
187 ioc->name, pg1->InvalidDwordCount));
188 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
189 "Running Disparity Error Count=0x%x\n", ioc->name,
190 pg1->RunningDisparityErrorCount));
191 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
192 "Loss Dword Synch Count=0x%x\n", ioc->name,
193 pg1->LossDwordSynchCount));
194 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
195 "PHY Reset Problem Count=0x%x\n\n", ioc->name,
196 pg1->PhyResetProblemCount));
b5141128
CH
197}
198
d6ecdd63 199static void mptsas_print_device_pg0(MPT_ADAPTER *ioc, SasDevicePage0_t *pg0)
b5141128
CH
200{
201 __le64 sas_address;
202
203 memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64));
204
29dd3609
EM
205 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
206 "---- SAS DEVICE PAGE 0 ---------\n", ioc->name));
207 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n",
208 ioc->name, le16_to_cpu(pg0->DevHandle)));
209 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Handle=0x%X\n",
210 ioc->name, le16_to_cpu(pg0->ParentDevHandle)));
211 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Enclosure Handle=0x%X\n",
212 ioc->name, le16_to_cpu(pg0->EnclosureHandle)));
213 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Slot=0x%X\n",
214 ioc->name, le16_to_cpu(pg0->Slot)));
215 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n",
216 ioc->name, (unsigned long long)le64_to_cpu(sas_address)));
217 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Target ID=0x%X\n",
218 ioc->name, pg0->TargetID));
219 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Bus=0x%X\n",
220 ioc->name, pg0->Bus));
221 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Phy Num=0x%X\n",
222 ioc->name, pg0->PhyNum));
223 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Access Status=0x%X\n",
224 ioc->name, le16_to_cpu(pg0->AccessStatus)));
225 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Device Info=0x%X\n",
226 ioc->name, le32_to_cpu(pg0->DeviceInfo)));
227 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Flags=0x%X\n",
228 ioc->name, le16_to_cpu(pg0->Flags)));
229 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n\n",
230 ioc->name, pg0->PhysicalPort));
b5141128
CH
231}
232
d6ecdd63
PS
233static void mptsas_print_expander_pg1(MPT_ADAPTER *ioc, SasExpanderPage1_t *pg1)
234{
29dd3609
EM
235 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
236 "---- SAS EXPANDER PAGE 1 ------------\n", ioc->name));
237 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n",
238 ioc->name, pg1->PhysicalPort));
239 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Identifier=0x%X\n",
240 ioc->name, pg1->PhyIdentifier));
241 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n",
242 ioc->name, pg1->NegotiatedLinkRate));
243 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n",
244 ioc->name, pg1->ProgrammedLinkRate));
245 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Hardware Link Rate=0x%X\n",
246 ioc->name, pg1->HwLinkRate));
247 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Owner Device Handle=0x%X\n",
248 ioc->name, le16_to_cpu(pg1->OwnerDevHandle)));
249 dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT
250 "Attached Device Handle=0x%X\n\n", ioc->name,
251 le16_to_cpu(pg1->AttachedDevHandle)));
b5141128 252}
b5141128 253
3eb0822c
KD
254/* inhibit sas firmware event handling */
255static void
256mptsas_fw_event_off(MPT_ADAPTER *ioc)
257{
258 unsigned long flags;
259
260 spin_lock_irqsave(&ioc->fw_event_lock, flags);
261 ioc->fw_events_off = 1;
262 ioc->sas_discovery_quiesce_io = 0;
263 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
264
265}
266
267/* enable sas firmware event handling */
268static void
269mptsas_fw_event_on(MPT_ADAPTER *ioc)
270{
271 unsigned long flags;
272
273 spin_lock_irqsave(&ioc->fw_event_lock, flags);
274 ioc->fw_events_off = 0;
275 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
276}
277
278/* queue a sas firmware event */
279static void
280mptsas_add_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
281 unsigned long delay)
282{
283 unsigned long flags;
284
285 spin_lock_irqsave(&ioc->fw_event_lock, flags);
286 list_add_tail(&fw_event->list, &ioc->fw_event_list);
287 INIT_DELAYED_WORK(&fw_event->work, mptsas_firmware_event_work);
288 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: add (fw_event=0x%p)\n",
289 ioc->name, __func__, fw_event));
290 queue_delayed_work(ioc->fw_event_q, &fw_event->work,
291 delay);
292 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
293}
294
db7051b2
KD
295/* requeue a sas firmware event */
296static void
297mptsas_requeue_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
298 unsigned long delay)
299{
300 unsigned long flags;
301 spin_lock_irqsave(&ioc->fw_event_lock, flags);
302 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: reschedule task "
303 "(fw_event=0x%p)\n", ioc->name, __func__, fw_event));
304 fw_event->retries++;
305 queue_delayed_work(ioc->fw_event_q, &fw_event->work,
306 msecs_to_jiffies(delay));
307 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
308}
309
3eb0822c
KD
310/* free memory assoicated to a sas firmware event */
311static void
312mptsas_free_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event)
313{
314 unsigned long flags;
315
316 spin_lock_irqsave(&ioc->fw_event_lock, flags);
317 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: kfree (fw_event=0x%p)\n",
318 ioc->name, __func__, fw_event));
319 list_del(&fw_event->list);
320 kfree(fw_event);
321 spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
322}
323
324/* walk the firmware event queue, and either stop or wait for
325 * outstanding events to complete */
326static void
327mptsas_cleanup_fw_event_q(MPT_ADAPTER *ioc)
328{
329 struct fw_event_work *fw_event, *next;
330 struct mptsas_target_reset_event *target_reset_list, *n;
3eb0822c
KD
331 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
332
333 /* flush the target_reset_list */
334 if (!list_empty(&hd->target_reset_list)) {
335 list_for_each_entry_safe(target_reset_list, n,
336 &hd->target_reset_list, list) {
337 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
338 "%s: removing target reset for id=%d\n",
339 ioc->name, __func__,
340 target_reset_list->sas_event_data.TargetID));
341 list_del(&target_reset_list->list);
342 kfree(target_reset_list);
343 }
344 }
345
346 if (list_empty(&ioc->fw_event_list) ||
347 !ioc->fw_event_q || in_interrupt())
348 return;
349
3eb0822c
KD
350 list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) {
351 if (cancel_delayed_work(&fw_event->work))
352 mptsas_free_fw_event(ioc, fw_event);
3eb0822c 353 }
3eb0822c
KD
354}
355
356
e3094447
CH
357static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy)
358{
359 struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
360 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
361}
362
363static inline MPT_ADAPTER *rphy_to_ioc(struct sas_rphy *rphy)
364{
365 struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
366 return ((MPT_SCSI_HOST *)shost->hostdata)->ioc;
367}
368
e6b2d76a
ME
369/*
370 * mptsas_find_portinfo_by_handle
371 *
372 * This function should be called with the sas_topology_mutex already held
373 */
374static struct mptsas_portinfo *
375mptsas_find_portinfo_by_handle(MPT_ADAPTER *ioc, u16 handle)
376{
377 struct mptsas_portinfo *port_info, *rc=NULL;
378 int i;
379
380 list_for_each_entry(port_info, &ioc->sas_topology, list)
381 for (i = 0; i < port_info->num_phys; i++)
382 if (port_info->phy_info[i].identify.handle == handle) {
383 rc = port_info;
384 goto out;
385 }
386 out:
387 return rc;
388}
389
f9c34022
KD
390/**
391 * mptsas_find_portinfo_by_sas_address -
392 * @ioc: Pointer to MPT_ADAPTER structure
393 * @handle:
394 *
395 * This function should be called with the sas_topology_mutex already held
396 *
397 **/
398static struct mptsas_portinfo *
399mptsas_find_portinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
400{
401 struct mptsas_portinfo *port_info, *rc = NULL;
402 int i;
403
404 if (sas_address >= ioc->hba_port_sas_addr &&
405 sas_address < (ioc->hba_port_sas_addr +
406 ioc->hba_port_num_phy))
407 return ioc->hba_port_info;
408
409 mutex_lock(&ioc->sas_topology_mutex);
410 list_for_each_entry(port_info, &ioc->sas_topology, list)
411 for (i = 0; i < port_info->num_phys; i++)
412 if (port_info->phy_info[i].identify.sas_address ==
413 sas_address) {
414 rc = port_info;
415 goto out;
416 }
417 out:
418 mutex_unlock(&ioc->sas_topology_mutex);
419 return rc;
420}
421
bd23e94c
ME
422/*
423 * Returns true if there is a scsi end device
424 */
425static inline int
426mptsas_is_end_device(struct mptsas_devinfo * attached)
427{
547f9a21 428 if ((attached->sas_address) &&
bd23e94c
ME
429 (attached->device_info &
430 MPI_SAS_DEVICE_INFO_END_DEVICE) &&
431 ((attached->device_info &
432 MPI_SAS_DEVICE_INFO_SSP_TARGET) |
433 (attached->device_info &
434 MPI_SAS_DEVICE_INFO_STP_TARGET) |
435 (attached->device_info &
436 MPI_SAS_DEVICE_INFO_SATA_DEVICE)))
437 return 1;
438 else
439 return 0;
440}
441
547f9a21 442/* no mutex */
376ac830 443static void
d6ecdd63 444mptsas_port_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo_details * port_details)
547f9a21
EM
445{
446 struct mptsas_portinfo *port_info;
447 struct mptsas_phyinfo *phy_info;
448 u8 i;
449
450 if (!port_details)
451 return;
452
453 port_info = port_details->port_info;
454 phy_info = port_info->phy_info;
455
29dd3609 456 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: [%p]: num_phys=%02d "
cadbd4a5 457 "bitmask=0x%016llX\n", ioc->name, __func__, port_details,
f99be43b
EM
458 port_details->num_phys, (unsigned long long)
459 port_details->phy_bitmask));
547f9a21
EM
460
461 for (i = 0; i < port_info->num_phys; i++, phy_info++) {
462 if(phy_info->port_details != port_details)
463 continue;
464 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
3eb0822c 465 mptsas_set_rphy(ioc, phy_info, NULL);
547f9a21
EM
466 phy_info->port_details = NULL;
467 }
468 kfree(port_details);
469}
470
471static inline struct sas_rphy *
472mptsas_get_rphy(struct mptsas_phyinfo *phy_info)
473{
474 if (phy_info->port_details)
475 return phy_info->port_details->rphy;
476 else
477 return NULL;
478}
479
480static inline void
d6ecdd63 481mptsas_set_rphy(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_rphy *rphy)
547f9a21
EM
482{
483 if (phy_info->port_details) {
484 phy_info->port_details->rphy = rphy;
29dd3609
EM
485 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_rphy_add: rphy=%p\n",
486 ioc->name, rphy));
547f9a21
EM
487 }
488
547f9a21 489 if (rphy) {
c51d0bea
EM
490 dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
491 &rphy->dev, MYIOC_s_FMT "add:", ioc->name));
29dd3609
EM
492 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rphy=%p release=%p\n",
493 ioc->name, rphy, rphy->dev.release));
547f9a21 494 }
547f9a21
EM
495}
496
497static inline struct sas_port *
498mptsas_get_port(struct mptsas_phyinfo *phy_info)
499{
500 if (phy_info->port_details)
501 return phy_info->port_details->port;
502 else
503 return NULL;
504}
505
506static inline void
d6ecdd63 507mptsas_set_port(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_port *port)
547f9a21
EM
508{
509 if (phy_info->port_details)
510 phy_info->port_details->port = port;
511
547f9a21 512 if (port) {
c51d0bea
EM
513 dsaswideprintk(ioc, dev_printk(KERN_DEBUG,
514 &port->dev, MYIOC_s_FMT "add:", ioc->name));
29dd3609
EM
515 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "port=%p release=%p\n",
516 ioc->name, port, port->dev.release));
547f9a21 517 }
547f9a21
EM
518}
519
520static inline struct scsi_target *
521mptsas_get_starget(struct mptsas_phyinfo *phy_info)
522{
523 if (phy_info->port_details)
524 return phy_info->port_details->starget;
525 else
526 return NULL;
527}
528
529static inline void
530mptsas_set_starget(struct mptsas_phyinfo *phy_info, struct scsi_target *
531starget)
532{
533 if (phy_info->port_details)
534 phy_info->port_details->starget = starget;
535}
536
3eb0822c
KD
537/**
538 * mptsas_add_device_component -
539 * @ioc: Pointer to MPT_ADAPTER structure
540 * @channel: fw mapped id's
541 * @id:
542 * @sas_address:
543 * @device_info:
544 *
545 **/
546static void
547mptsas_add_device_component(MPT_ADAPTER *ioc, u8 channel, u8 id,
548 u64 sas_address, u32 device_info, u16 slot, u64 enclosure_logical_id)
549{
550 struct mptsas_device_info *sas_info, *next;
551 struct scsi_device *sdev;
552 struct scsi_target *starget;
553 struct sas_rphy *rphy;
554
555 /*
556 * Delete all matching devices out of the list
557 */
558 mutex_lock(&ioc->sas_device_info_mutex);
559 list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
560 list) {
a7938b0b
KD
561 if (!sas_info->is_logical_volume &&
562 (sas_info->sas_address == sas_address ||
563 (sas_info->fw.channel == channel &&
564 sas_info->fw.id == id))) {
3eb0822c
KD
565 list_del(&sas_info->list);
566 kfree(sas_info);
567 }
568 }
569
570 sas_info = kzalloc(sizeof(struct mptsas_device_info), GFP_KERNEL);
571 if (!sas_info)
572 goto out;
573
574 /*
575 * Set Firmware mapping
576 */
577 sas_info->fw.id = id;
578 sas_info->fw.channel = channel;
579
580 sas_info->sas_address = sas_address;
581 sas_info->device_info = device_info;
582 sas_info->slot = slot;
583 sas_info->enclosure_logical_id = enclosure_logical_id;
584 INIT_LIST_HEAD(&sas_info->list);
585 list_add_tail(&sas_info->list, &ioc->sas_device_info_list);
586
587 /*
588 * Set OS mapping
589 */
590 shost_for_each_device(sdev, ioc->sh) {
591 starget = scsi_target(sdev);
592 rphy = dev_to_rphy(starget->dev.parent);
593 if (rphy->identify.sas_address == sas_address) {
594 sas_info->os.id = starget->id;
595 sas_info->os.channel = starget->channel;
596 }
597 }
598
599 out:
600 mutex_unlock(&ioc->sas_device_info_mutex);
601 return;
602}
603
604/**
605 * mptsas_add_device_component_by_fw -
606 * @ioc: Pointer to MPT_ADAPTER structure
607 * @channel: fw mapped id's
608 * @id:
609 *
610 **/
611static void
612mptsas_add_device_component_by_fw(MPT_ADAPTER *ioc, u8 channel, u8 id)
613{
614 struct mptsas_devinfo sas_device;
615 struct mptsas_enclosure enclosure_info;
616 int rc;
617
618 rc = mptsas_sas_device_pg0(ioc, &sas_device,
619 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
620 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
621 (channel << 8) + id);
622 if (rc)
623 return;
624
625 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
626 mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
627 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
628 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT),
629 sas_device.handle_enclosure);
630
631 mptsas_add_device_component(ioc, sas_device.channel,
632 sas_device.id, sas_device.sas_address, sas_device.device_info,
633 sas_device.slot, enclosure_info.enclosure_logical_id);
634}
635
a7938b0b 636/**
fc847ab4 637 * mptsas_add_device_component_starget_ir - Handle Integrated RAID, adding each individual device to list
a7938b0b
KD
638 * @ioc: Pointer to MPT_ADAPTER structure
639 * @channel: fw mapped id's
640 * @id:
641 *
642 **/
643static void
644mptsas_add_device_component_starget_ir(MPT_ADAPTER *ioc,
645 struct scsi_target *starget)
646{
647 CONFIGPARMS cfg;
648 ConfigPageHeader_t hdr;
649 dma_addr_t dma_handle;
650 pRaidVolumePage0_t buffer = NULL;
651 int i;
652 RaidPhysDiskPage0_t phys_disk;
653 struct mptsas_device_info *sas_info, *next;
654
655 memset(&cfg, 0 , sizeof(CONFIGPARMS));
656 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
657 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
658 /* assumption that all volumes on channel = 0 */
659 cfg.pageAddr = starget->id;
660 cfg.cfghdr.hdr = &hdr;
661 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4b97650b 662 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
a7938b0b
KD
663
664 if (mpt_config(ioc, &cfg) != 0)
665 goto out;
666
667 if (!hdr.PageLength)
668 goto out;
669
670 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
671 &dma_handle);
672
673 if (!buffer)
674 goto out;
675
676 cfg.physAddr = dma_handle;
677 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
678
679 if (mpt_config(ioc, &cfg) != 0)
680 goto out;
681
682 if (!buffer->NumPhysDisks)
683 goto out;
684
685 /*
686 * Adding entry for hidden components
687 */
688 for (i = 0; i < buffer->NumPhysDisks; i++) {
689
690 if (mpt_raid_phys_disk_pg0(ioc,
691 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
692 continue;
693
694 mptsas_add_device_component_by_fw(ioc, phys_disk.PhysDiskBus,
695 phys_disk.PhysDiskID);
696
57e98513
KD
697 mutex_lock(&ioc->sas_device_info_mutex);
698 list_for_each_entry(sas_info, &ioc->sas_device_info_list,
699 list) {
700 if (!sas_info->is_logical_volume &&
701 (sas_info->fw.channel == phys_disk.PhysDiskBus &&
702 sas_info->fw.id == phys_disk.PhysDiskID)) {
703 sas_info->is_hidden_raid_component = 1;
704 sas_info->volume_id = starget->id;
705 }
706 }
707 mutex_unlock(&ioc->sas_device_info_mutex);
708
a7938b0b
KD
709 }
710
711 /*
712 * Delete all matching devices out of the list
713 */
714 mutex_lock(&ioc->sas_device_info_mutex);
715 list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
716 list) {
717 if (sas_info->is_logical_volume && sas_info->fw.id ==
718 starget->id) {
719 list_del(&sas_info->list);
720 kfree(sas_info);
721 }
722 }
723
724 sas_info = kzalloc(sizeof(struct mptsas_device_info), GFP_KERNEL);
725 if (sas_info) {
726 sas_info->fw.id = starget->id;
727 sas_info->os.id = starget->id;
728 sas_info->os.channel = starget->channel;
729 sas_info->is_logical_volume = 1;
730 INIT_LIST_HEAD(&sas_info->list);
731 list_add_tail(&sas_info->list, &ioc->sas_device_info_list);
732 }
733 mutex_unlock(&ioc->sas_device_info_mutex);
734
735 out:
736 if (buffer)
737 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
738 dma_handle);
739}
740
3eb0822c
KD
741/**
742 * mptsas_add_device_component_starget -
743 * @ioc: Pointer to MPT_ADAPTER structure
744 * @starget:
745 *
746 **/
747static void
748mptsas_add_device_component_starget(MPT_ADAPTER *ioc,
749 struct scsi_target *starget)
750{
751 VirtTarget *vtarget;
752 struct sas_rphy *rphy;
753 struct mptsas_phyinfo *phy_info = NULL;
754 struct mptsas_enclosure enclosure_info;
755
756 rphy = dev_to_rphy(starget->dev.parent);
757 vtarget = starget->hostdata;
758 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
759 rphy->identify.sas_address);
760 if (!phy_info)
761 return;
762
763 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
764 mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
765 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
766 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT),
767 phy_info->attached.handle_enclosure);
768
769 mptsas_add_device_component(ioc, phy_info->attached.channel,
770 phy_info->attached.id, phy_info->attached.sas_address,
771 phy_info->attached.device_info,
772 phy_info->attached.slot, enclosure_info.enclosure_logical_id);
773}
774
57e98513 775/**
fc847ab4 776 * mptsas_del_device_component_by_os - Once a device has been removed, we mark the entry in the list as being cached
57e98513
KD
777 * @ioc: Pointer to MPT_ADAPTER structure
778 * @channel: os mapped id's
779 * @id:
780 *
781 **/
782static void
783mptsas_del_device_component_by_os(MPT_ADAPTER *ioc, u8 channel, u8 id)
784{
785 struct mptsas_device_info *sas_info, *next;
786
787 /*
788 * Set is_cached flag
789 */
790 list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
791 list) {
792 if (sas_info->os.channel == channel && sas_info->os.id == id)
793 sas_info->is_cached = 1;
794 }
795}
796
3eb0822c
KD
797/**
798 * mptsas_del_device_components - Cleaning the list
799 * @ioc: Pointer to MPT_ADAPTER structure
800 *
801 **/
802static void
803mptsas_del_device_components(MPT_ADAPTER *ioc)
804{
805 struct mptsas_device_info *sas_info, *next;
806
807 mutex_lock(&ioc->sas_device_info_mutex);
808 list_for_each_entry_safe(sas_info, next, &ioc->sas_device_info_list,
809 list) {
810 list_del(&sas_info->list);
811 kfree(sas_info);
812 }
813 mutex_unlock(&ioc->sas_device_info_mutex);
814}
815
547f9a21
EM
816
817/*
818 * mptsas_setup_wide_ports
819 *
820 * Updates for new and existing narrow/wide port configuration
821 * in the sas_topology
822 */
376ac830 823static void
547f9a21
EM
824mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
825{
826 struct mptsas_portinfo_details * port_details;
827 struct mptsas_phyinfo *phy_info, *phy_info_cmp;
828 u64 sas_address;
829 int i, j;
830
831 mutex_lock(&ioc->sas_topology_mutex);
832
833 phy_info = port_info->phy_info;
834 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
835 if (phy_info->attached.handle)
836 continue;
837 port_details = phy_info->port_details;
838 if (!port_details)
839 continue;
840 if (port_details->num_phys < 2)
841 continue;
842 /*
843 * Removing a phy from a port, letting the last
844 * phy be removed by firmware events.
845 */
29dd3609
EM
846 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
847 "%s: [%p]: deleting phy = %d\n",
cadbd4a5 848 ioc->name, __func__, port_details, i));
547f9a21
EM
849 port_details->num_phys--;
850 port_details->phy_bitmask &= ~ (1 << phy_info->phy_id);
851 memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo));
9e39089b
KD
852 if (phy_info->phy) {
853 devtprintk(ioc, dev_printk(KERN_DEBUG,
854 &phy_info->phy->dev, MYIOC_s_FMT
855 "delete phy %d, phy-obj (0x%p)\n", ioc->name,
856 phy_info->phy_id, phy_info->phy));
857 sas_port_delete_phy(port_details->port, phy_info->phy);
858 }
547f9a21
EM
859 phy_info->port_details = NULL;
860 }
861
862 /*
863 * Populate and refresh the tree
864 */
865 phy_info = port_info->phy_info;
866 for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) {
867 sas_address = phy_info->attached.sas_address;
29dd3609
EM
868 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "phy_id=%d sas_address=0x%018llX\n",
869 ioc->name, i, (unsigned long long)sas_address));
547f9a21
EM
870 if (!sas_address)
871 continue;
872 port_details = phy_info->port_details;
873 /*
874 * Forming a port
875 */
876 if (!port_details) {
2f187862
KD
877 port_details = kzalloc(sizeof(struct
878 mptsas_portinfo_details), GFP_KERNEL);
547f9a21
EM
879 if (!port_details)
880 goto out;
881 port_details->num_phys = 1;
882 port_details->port_info = port_info;
547f9a21
EM
883 if (phy_info->phy_id < 64 )
884 port_details->phy_bitmask |=
885 (1 << phy_info->phy_id);
886 phy_info->sas_port_add_phy=1;
29dd3609 887 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tForming port\n\t\t"
f99be43b 888 "phy_id=%d sas_address=0x%018llX\n",
29dd3609 889 ioc->name, i, (unsigned long long)sas_address));
547f9a21
EM
890 phy_info->port_details = port_details;
891 }
892
893 if (i == port_info->num_phys - 1)
894 continue;
895 phy_info_cmp = &port_info->phy_info[i + 1];
896 for (j = i + 1 ; j < port_info->num_phys ; j++,
897 phy_info_cmp++) {
898 if (!phy_info_cmp->attached.sas_address)
899 continue;
900 if (sas_address != phy_info_cmp->attached.sas_address)
901 continue;
902 if (phy_info_cmp->port_details == port_details )
903 continue;
29dd3609 904 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
f99be43b 905 "\t\tphy_id=%d sas_address=0x%018llX\n",
29dd3609 906 ioc->name, j, (unsigned long long)
f99be43b 907 phy_info_cmp->attached.sas_address));
547f9a21
EM
908 if (phy_info_cmp->port_details) {
909 port_details->rphy =
910 mptsas_get_rphy(phy_info_cmp);
911 port_details->port =
912 mptsas_get_port(phy_info_cmp);
913 port_details->starget =
914 mptsas_get_starget(phy_info_cmp);
547f9a21
EM
915 port_details->num_phys =
916 phy_info_cmp->port_details->num_phys;
547f9a21
EM
917 if (!phy_info_cmp->port_details->num_phys)
918 kfree(phy_info_cmp->port_details);
919 } else
920 phy_info_cmp->sas_port_add_phy=1;
921 /*
922 * Adding a phy to a port
923 */
924 phy_info_cmp->port_details = port_details;
925 if (phy_info_cmp->phy_id < 64 )
926 port_details->phy_bitmask |=
927 (1 << phy_info_cmp->phy_id);
928 port_details->num_phys++;
929 }
930 }
931
932 out:
933
547f9a21
EM
934 for (i = 0; i < port_info->num_phys; i++) {
935 port_details = port_info->phy_info[i].port_details;
936 if (!port_details)
937 continue;
29dd3609 938 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
f99be43b 939 "%s: [%p]: phy_id=%02d num_phys=%02d "
cadbd4a5 940 "bitmask=0x%016llX\n", ioc->name, __func__,
f99be43b
EM
941 port_details, i, port_details->num_phys,
942 (unsigned long long)port_details->phy_bitmask));
29dd3609
EM
943 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tport = %p rphy=%p\n",
944 ioc->name, port_details->port, port_details->rphy));
547f9a21 945 }
29dd3609 946 dsaswideprintk(ioc, printk("\n"));
547f9a21
EM
947 mutex_unlock(&ioc->sas_topology_mutex);
948}
949
df9e062a
EM
950/**
951 * csmisas_find_vtarget
952 *
953 * @ioc
954 * @volume_id
955 * @volume_bus
956 *
957 **/
958static VirtTarget *
959mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id)
960{
961 struct scsi_device *sdev;
a69de507 962 VirtDevice *vdevice;
df9e062a
EM
963 VirtTarget *vtarget = NULL;
964
965 shost_for_each_device(sdev, ioc->sh) {
e7deff33
KD
966 vdevice = sdev->hostdata;
967 if ((vdevice == NULL) ||
968 (vdevice->vtarget == NULL))
df9e062a 969 continue;
a7938b0b
KD
970 if ((vdevice->vtarget->tflags &
971 MPT_TARGET_FLAGS_RAID_COMPONENT ||
972 vdevice->vtarget->raidVolume))
973 continue;
a69de507 974 if (vdevice->vtarget->id == id &&
e7deff33 975 vdevice->vtarget->channel == channel)
a69de507 976 vtarget = vdevice->vtarget;
df9e062a
EM
977 }
978 return vtarget;
979}
980
3eb0822c
KD
981static void
982mptsas_queue_device_delete(MPT_ADAPTER *ioc,
983 MpiEventDataSasDeviceStatusChange_t *sas_event_data)
984{
985 struct fw_event_work *fw_event;
986 int sz;
987
988 sz = offsetof(struct fw_event_work, event_data) +
989 sizeof(MpiEventDataSasDeviceStatusChange_t);
990 fw_event = kzalloc(sz, GFP_ATOMIC);
991 if (!fw_event) {
992 printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
993 ioc->name, __func__, __LINE__);
994 return;
995 }
996 memcpy(fw_event->event_data, sas_event_data,
997 sizeof(MpiEventDataSasDeviceStatusChange_t));
998 fw_event->event = MPI_EVENT_SAS_DEVICE_STATUS_CHANGE;
999 fw_event->ioc = ioc;
1000 mptsas_add_fw_event(ioc, fw_event, msecs_to_jiffies(1));
1001}
1002
eedf92b9
KD
1003static void
1004mptsas_queue_rescan(MPT_ADAPTER *ioc)
1005{
1006 struct fw_event_work *fw_event;
1007 int sz;
1008
1009 sz = offsetof(struct fw_event_work, event_data);
1010 fw_event = kzalloc(sz, GFP_ATOMIC);
1011 if (!fw_event) {
1012 printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n",
1013 ioc->name, __func__, __LINE__);
1014 return;
1015 }
1016 fw_event->event = -1;
1017 fw_event->ioc = ioc;
1018 mptsas_add_fw_event(ioc, fw_event, msecs_to_jiffies(1));
1019}
1020
3eb0822c 1021
df9e062a
EM
1022/**
1023 * mptsas_target_reset
1024 *
1025 * Issues TARGET_RESET to end device using handshaking method
1026 *
1027 * @ioc
1028 * @channel
1029 * @id
1030 *
1031 * Returns (1) success
1032 * (0) failure
1033 *
1034 **/
1035static int
1036mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id)
1037{
1038 MPT_FRAME_HDR *mf;
1039 SCSITaskMgmt_t *pScsiTm;
ea2a788d
KD
1040 if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0)
1041 return 0;
1042
df9e062a 1043
e7deff33
KD
1044 mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc);
1045 if (mf == NULL) {
1046 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
ea2a788d
KD
1047 "%s, no msg frames @%d!!\n", ioc->name,
1048 __func__, __LINE__));
1049 goto out_fail;
df9e062a
EM
1050 }
1051
ea2a788d
KD
1052 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request (mf=%p)\n",
1053 ioc->name, mf));
1054
df9e062a
EM
1055 /* Format the Request
1056 */
1057 pScsiTm = (SCSITaskMgmt_t *) mf;
1058 memset (pScsiTm, 0, sizeof(SCSITaskMgmt_t));
1059 pScsiTm->TargetID = id;
1060 pScsiTm->Bus = channel;
1061 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
1062 pScsiTm->TaskType = MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET;
1063 pScsiTm->MsgFlags = MPI_SCSITASKMGMT_MSGFLAGS_LIPRESET_RESET_OPTION;
1064
d6ecdd63 1065 DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf);
df9e062a 1066
ea2a788d
KD
1067 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1068 "TaskMgmt type=%d (sas device delete) fw_channel = %d fw_id = %d)\n",
1069 ioc->name, MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET, channel, id));
1070
e7deff33 1071 mpt_put_msg_frame_hi_pri(mptsasDeviceResetCtx, ioc, mf);
df9e062a
EM
1072
1073 return 1;
ea2a788d
KD
1074
1075 out_fail:
1076
1077 mpt_clear_taskmgmt_in_progress_flag(ioc);
1078 return 0;
df9e062a
EM
1079}
1080
64e155ad
KD
1081static void
1082mptsas_block_io_sdev(struct scsi_device *sdev, void *data)
1083{
1084 scsi_device_set_state(sdev, SDEV_BLOCK);
1085}
1086
1087static void
1088mptsas_block_io_starget(struct scsi_target *starget)
1089{
1090 if (starget)
1091 starget_for_each_device(starget, NULL, mptsas_block_io_sdev);
1092}
1093
df9e062a
EM
1094/**
1095 * mptsas_target_reset_queue
1096 *
1097 * Receive request for TARGET_RESET after recieving an firmware
1098 * event NOT_RESPONDING_EVENT, then put command in link list
1099 * and queue if task_queue already in use.
1100 *
1101 * @ioc
1102 * @sas_event_data
1103 *
1104 **/
547f9a21 1105static void
df9e062a
EM
1106mptsas_target_reset_queue(MPT_ADAPTER *ioc,
1107 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data)
547f9a21 1108{
e7eae9f6 1109 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
df9e062a
EM
1110 VirtTarget *vtarget = NULL;
1111 struct mptsas_target_reset_event *target_reset_list;
1112 u8 id, channel;
547f9a21 1113
df9e062a
EM
1114 id = sas_event_data->TargetID;
1115 channel = sas_event_data->Bus;
1116
64e155ad
KD
1117 vtarget = mptsas_find_vtarget(ioc, channel, id);
1118 if (vtarget) {
1119 mptsas_block_io_starget(vtarget->starget);
1120 vtarget->deleted = 1; /* block IO */
1121 }
df9e062a 1122
2f187862 1123 target_reset_list = kzalloc(sizeof(struct mptsas_target_reset_event),
df9e062a
EM
1124 GFP_ATOMIC);
1125 if (!target_reset_list) {
e7deff33
KD
1126 dfailprintk(ioc, printk(MYIOC_s_WARN_FMT
1127 "%s, failed to allocate mem @%d..!!\n",
1128 ioc->name, __func__, __LINE__));
df9e062a
EM
1129 return;
1130 }
1131
1132 memcpy(&target_reset_list->sas_event_data, sas_event_data,
1133 sizeof(*sas_event_data));
1134 list_add_tail(&target_reset_list->list, &hd->target_reset_list);
1135
e7deff33 1136 target_reset_list->time_count = jiffies;
df9e062a
EM
1137
1138 if (mptsas_target_reset(ioc, channel, id)) {
1139 target_reset_list->target_reset_issued = 1;
df9e062a
EM
1140 }
1141}
1142
b68bf096
KD
1143/**
1144 * mptsas_schedule_target_reset- send pending target reset
1145 * @iocp: per adapter object
1146 *
1147 * This function will delete scheduled target reset from the list and
1148 * try to send next target reset. This will be called from completion
b595076a 1149 * context of any Task management command.
b68bf096
KD
1150 */
1151
1152void
1153mptsas_schedule_target_reset(void *iocp)
1154{
1155 MPT_ADAPTER *ioc = (MPT_ADAPTER *)(iocp);
1156 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
1157 struct list_head *head = &hd->target_reset_list;
1158 struct mptsas_target_reset_event *target_reset_list;
1159 u8 id, channel;
1160 /*
1161 * issue target reset to next device in the queue
1162 */
1163
1164 head = &hd->target_reset_list;
1165 if (list_empty(head))
1166 return;
1167
1168 target_reset_list = list_entry(head->next,
1169 struct mptsas_target_reset_event, list);
1170
1171 id = target_reset_list->sas_event_data.TargetID;
1172 channel = target_reset_list->sas_event_data.Bus;
1173 target_reset_list->time_count = jiffies;
1174
1175 if (mptsas_target_reset(ioc, channel, id))
1176 target_reset_list->target_reset_issued = 1;
1177 return;
1178}
1179
1180
df9e062a 1181/**
fc847ab4 1182 * mptsas_taskmgmt_complete - complete SAS task management function
e7deff33 1183 * @ioc: Pointer to MPT_ADAPTER structure
df9e062a 1184 *
fc847ab4
JB
1185 * Completion for TARGET_RESET after NOT_RESPONDING_EVENT, enable work
1186 * queue to finish off removing device from upper layers. then send next
1187 * TARGET_RESET in the queue.
df9e062a 1188 **/
e7deff33
KD
1189static int
1190mptsas_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr)
df9e062a 1191{
e7eae9f6 1192 MPT_SCSI_HOST *hd = shost_priv(ioc->sh);
df9e062a 1193 struct list_head *head = &hd->target_reset_list;
df9e062a 1194 u8 id, channel;
e7deff33
KD
1195 struct mptsas_target_reset_event *target_reset_list;
1196 SCSITaskMgmtReply_t *pScsiTmReply;
1197
1198 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt completed: "
1199 "(mf = %p, mr = %p)\n", ioc->name, mf, mr));
1200
1201 pScsiTmReply = (SCSITaskMgmtReply_t *)mr;
1202 if (pScsiTmReply) {
1203 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1204 "\tTaskMgmt completed: fw_channel = %d, fw_id = %d,\n"
1205 "\ttask_type = 0x%02X, iocstatus = 0x%04X "
1206 "loginfo = 0x%08X,\n\tresponse_code = 0x%02X, "
1207 "term_cmnds = %d\n", ioc->name,
1208 pScsiTmReply->Bus, pScsiTmReply->TargetID,
1209 pScsiTmReply->TaskType,
1210 le16_to_cpu(pScsiTmReply->IOCStatus),
1211 le32_to_cpu(pScsiTmReply->IOCLogInfo),
1212 pScsiTmReply->ResponseCode,
1213 le32_to_cpu(pScsiTmReply->TerminationCount)));
1214
1215 if (pScsiTmReply->ResponseCode)
1216 mptscsih_taskmgmt_response_code(ioc,
1217 pScsiTmReply->ResponseCode);
1218 }
1219
1220 if (pScsiTmReply && (pScsiTmReply->TaskType ==
1221 MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK || pScsiTmReply->TaskType ==
1222 MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET)) {
1223 ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
1224 ioc->taskmgmt_cmds.status |= MPT_MGMT_STATUS_RF_VALID;
1225 memcpy(ioc->taskmgmt_cmds.reply, mr,
1226 min(MPT_DEFAULT_FRAME_SIZE, 4 * mr->u.reply.MsgLength));
1227 if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_PENDING) {
1228 ioc->taskmgmt_cmds.status &= ~MPT_MGMT_STATUS_PENDING;
1229 complete(&ioc->taskmgmt_cmds.done);
1230 return 1;
1231 }
1232 return 0;
1233 }
1234
1235 mpt_clear_taskmgmt_in_progress_flag(ioc);
df9e062a
EM
1236
1237 if (list_empty(head))
e7deff33
KD
1238 return 1;
1239
1240 target_reset_list = list_entry(head->next,
1241 struct mptsas_target_reset_event, list);
df9e062a 1242
e7deff33
KD
1243 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1244 "TaskMgmt: completed (%d seconds)\n",
1245 ioc->name, jiffies_to_msecs(jiffies -
1246 target_reset_list->time_count)/1000));
df9e062a 1247
e7deff33
KD
1248 id = pScsiTmReply->TargetID;
1249 channel = pScsiTmReply->Bus;
1250 target_reset_list->time_count = jiffies;
df9e062a
EM
1251
1252 /*
1253 * retry target reset
1254 */
1255 if (!target_reset_list->target_reset_issued) {
e7deff33 1256 if (mptsas_target_reset(ioc, channel, id))
df9e062a 1257 target_reset_list->target_reset_issued = 1;
e7deff33 1258 return 1;
df9e062a
EM
1259 }
1260
1261 /*
1262 * enable work queue to remove device from upper layers
1263 */
1264 list_del(&target_reset_list->list);
3e84beba 1265 if (!ioc->fw_events_off)
3eb0822c
KD
1266 mptsas_queue_device_delete(ioc,
1267 &target_reset_list->sas_event_data);
ea2a788d 1268
e7deff33 1269
b68bf096 1270 ioc->schedule_target_reset(ioc);
df9e062a 1271
e7deff33 1272 return 1;
df9e062a
EM
1273}
1274
1275/**
1276 * mptscsih_ioc_reset
1277 *
1278 * @ioc
1279 * @reset_phase
1280 *
1281 **/
1282static int
1283mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase)
1284{
ba76ef24 1285 MPT_SCSI_HOST *hd;
df9e062a
EM
1286 int rc;
1287
1288 rc = mptscsih_ioc_reset(ioc, reset_phase);
3eb0822c
KD
1289 if ((ioc->bus_type != SAS) || (!rc))
1290 return rc;
df9e062a 1291
e7eae9f6 1292 hd = shost_priv(ioc->sh);
ba76ef24 1293 if (!hd->ioc)
df9e062a
EM
1294 goto out;
1295
3eb0822c
KD
1296 switch (reset_phase) {
1297 case MPT_IOC_SETUP_RESET:
1298 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1299 "%s: MPT_IOC_SETUP_RESET\n", ioc->name, __func__));
1300 mptsas_fw_event_off(ioc);
1301 break;
1302 case MPT_IOC_PRE_RESET:
1303 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1304 "%s: MPT_IOC_PRE_RESET\n", ioc->name, __func__));
1305 break;
1306 case MPT_IOC_POST_RESET:
1307 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1308 "%s: MPT_IOC_POST_RESET\n", ioc->name, __func__));
1309 if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_PENDING) {
1310 ioc->sas_mgmt.status |= MPT_MGMT_STATUS_DID_IOCRESET;
1311 complete(&ioc->sas_mgmt.done);
1312 }
1313 mptsas_cleanup_fw_event_q(ioc);
eedf92b9 1314 mptsas_queue_rescan(ioc);
3eb0822c
KD
1315 break;
1316 default:
1317 break;
547f9a21 1318 }
df9e062a
EM
1319
1320 out:
1321 return rc;
547f9a21
EM
1322}
1323
3eb0822c
KD
1324
1325/**
1326 * enum device_state -
1327 * @DEVICE_RETRY: need to retry the TUR
1328 * @DEVICE_ERROR: TUR return error, don't add device
1329 * @DEVICE_READY: device can be added
1330 *
1331 */
1332enum device_state{
1333 DEVICE_RETRY,
1334 DEVICE_ERROR,
1335 DEVICE_READY,
1336};
1337
e3094447 1338static int
52435430 1339mptsas_sas_enclosure_pg0(MPT_ADAPTER *ioc, struct mptsas_enclosure *enclosure,
e3094447
CH
1340 u32 form, u32 form_specific)
1341{
1342 ConfigExtendedPageHeader_t hdr;
1343 CONFIGPARMS cfg;
1344 SasEnclosurePage0_t *buffer;
1345 dma_addr_t dma_handle;
1346 int error;
1347 __le64 le_identifier;
1348
1349 memset(&hdr, 0, sizeof(hdr));
1350 hdr.PageVersion = MPI_SASENCLOSURE0_PAGEVERSION;
1351 hdr.PageNumber = 0;
1352 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
1353 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_ENCLOSURE;
1354
1355 cfg.cfghdr.ehdr = &hdr;
1356 cfg.physAddr = -1;
1357 cfg.pageAddr = form + form_specific;
1358 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
1359 cfg.dir = 0; /* read */
4b97650b 1360 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
e3094447
CH
1361
1362 error = mpt_config(ioc, &cfg);
1363 if (error)
1364 goto out;
1365 if (!hdr.ExtPageLength) {
1366 error = -ENXIO;
1367 goto out;
1368 }
1369
1370 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1371 &dma_handle);
1372 if (!buffer) {
1373 error = -ENOMEM;
1374 goto out;
1375 }
1376
1377 cfg.physAddr = dma_handle;
1378 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
1379
1380 error = mpt_config(ioc, &cfg);
1381 if (error)
1382 goto out_free_consistent;
1383
1384 /* save config data */
1385 memcpy(&le_identifier, &buffer->EnclosureLogicalID, sizeof(__le64));
1386 enclosure->enclosure_logical_id = le64_to_cpu(le_identifier);
1387 enclosure->enclosure_handle = le16_to_cpu(buffer->EnclosureHandle);
1388 enclosure->flags = le16_to_cpu(buffer->Flags);
1389 enclosure->num_slot = le16_to_cpu(buffer->NumSlots);
1390 enclosure->start_slot = le16_to_cpu(buffer->StartSlot);
1391 enclosure->start_id = buffer->StartTargetID;
1392 enclosure->start_channel = buffer->StartBus;
1393 enclosure->sep_id = buffer->SEPTargetID;
1394 enclosure->sep_channel = buffer->SEPBus;
1395
1396 out_free_consistent:
1397 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
1398 buffer, dma_handle);
1399 out:
1400 return error;
1401}
b5141128 1402
3eb0822c
KD
1403/**
1404 * mptsas_add_end_device - report a new end device to sas transport layer
1405 * @ioc: Pointer to MPT_ADAPTER structure
1406 * @phy_info: decribes attached device
1407 *
1408 * return (0) success (1) failure
1409 *
1410 **/
1411static int
1412mptsas_add_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info)
1413{
1414 struct sas_rphy *rphy;
1415 struct sas_port *port;
1416 struct sas_identify identify;
1417 char *ds = NULL;
1418 u8 fw_id;
1419
1420 if (!phy_info) {
1421 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1422 "%s: exit at line=%d\n", ioc->name,
1423 __func__, __LINE__));
1424 return 1;
1425 }
1426
1427 fw_id = phy_info->attached.id;
1428
1429 if (mptsas_get_rphy(phy_info)) {
1430 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1431 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1432 __func__, fw_id, __LINE__));
1433 return 2;
1434 }
1435
1436 port = mptsas_get_port(phy_info);
1437 if (!port) {
1438 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1439 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1440 __func__, fw_id, __LINE__));
1441 return 3;
1442 }
1443
1444 if (phy_info->attached.device_info &
1445 MPI_SAS_DEVICE_INFO_SSP_TARGET)
1446 ds = "ssp";
1447 if (phy_info->attached.device_info &
1448 MPI_SAS_DEVICE_INFO_STP_TARGET)
1449 ds = "stp";
1450 if (phy_info->attached.device_info &
1451 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1452 ds = "sata";
1453
1454 printk(MYIOC_s_INFO_FMT "attaching %s device: fw_channel %d, fw_id %d,"
1455 " phy %d, sas_addr 0x%llx\n", ioc->name, ds,
1456 phy_info->attached.channel, phy_info->attached.id,
1457 phy_info->attached.phy_id, (unsigned long long)
1458 phy_info->attached.sas_address);
1459
1460 mptsas_parse_device_info(&identify, &phy_info->attached);
1461 rphy = sas_end_device_alloc(port);
1462 if (!rphy) {
1463 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1464 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1465 __func__, fw_id, __LINE__));
1466 return 5; /* non-fatal: an rphy can be added later */
1467 }
1468
1469 rphy->identify = identify;
1470 if (sas_rphy_add(rphy)) {
1471 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1472 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1473 __func__, fw_id, __LINE__));
1474 sas_rphy_free(rphy);
1475 return 6;
1476 }
1477 mptsas_set_rphy(ioc, phy_info, rphy);
1478 return 0;
1479}
1480
1481/**
fc847ab4 1482 * mptsas_del_end_device - report a deleted end device to sas transport layer
3eb0822c
KD
1483 * @ioc: Pointer to MPT_ADAPTER structure
1484 * @phy_info: decribes attached device
1485 *
1486 **/
1487static void
1488mptsas_del_end_device(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info)
1489{
1490 struct sas_rphy *rphy;
1491 struct sas_port *port;
1492 struct mptsas_portinfo *port_info;
1493 struct mptsas_phyinfo *phy_info_parent;
1494 int i;
1495 char *ds = NULL;
1496 u8 fw_id;
1497 u64 sas_address;
1498
1499 if (!phy_info)
1500 return;
1501
1502 fw_id = phy_info->attached.id;
1503 sas_address = phy_info->attached.sas_address;
1504
1505 if (!phy_info->port_details) {
1506 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1507 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1508 __func__, fw_id, __LINE__));
1509 return;
1510 }
1511 rphy = mptsas_get_rphy(phy_info);
1512 if (!rphy) {
1513 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1514 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1515 __func__, fw_id, __LINE__));
1516 return;
1517 }
1518
1519 if (phy_info->attached.device_info & MPI_SAS_DEVICE_INFO_SSP_INITIATOR
1520 || phy_info->attached.device_info
1521 & MPI_SAS_DEVICE_INFO_SMP_INITIATOR
1522 || phy_info->attached.device_info
1523 & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
1524 ds = "initiator";
1525 if (phy_info->attached.device_info &
1526 MPI_SAS_DEVICE_INFO_SSP_TARGET)
1527 ds = "ssp";
1528 if (phy_info->attached.device_info &
1529 MPI_SAS_DEVICE_INFO_STP_TARGET)
1530 ds = "stp";
1531 if (phy_info->attached.device_info &
1532 MPI_SAS_DEVICE_INFO_SATA_DEVICE)
1533 ds = "sata";
1534
1535 dev_printk(KERN_DEBUG, &rphy->dev, MYIOC_s_FMT
1536 "removing %s device: fw_channel %d, fw_id %d, phy %d,"
1537 "sas_addr 0x%llx\n", ioc->name, ds, phy_info->attached.channel,
1538 phy_info->attached.id, phy_info->attached.phy_id,
1539 (unsigned long long) sas_address);
1540
1541 port = mptsas_get_port(phy_info);
1542 if (!port) {
1543 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
1544 "%s: fw_id=%d exit at line=%d\n", ioc->name,
1545 __func__, fw_id, __LINE__));
1546 return;
1547 }
1548 port_info = phy_info->portinfo;
1549 phy_info_parent = port_info->phy_info;
1550 for (i = 0; i < port_info->num_phys; i++, phy_info_parent++) {
1551 if (!phy_info_parent->phy)
1552 continue;
1553 if (phy_info_parent->attached.sas_address !=
1554 sas_address)
1555 continue;
1556 dev_printk(KERN_DEBUG, &phy_info_parent->phy->dev,
1557 MYIOC_s_FMT "delete phy %d, phy-obj (0x%p)\n",
1558 ioc->name, phy_info_parent->phy_id,
1559 phy_info_parent->phy);
1560 sas_port_delete_phy(port, phy_info_parent->phy);
1561 }
1562
1563 dev_printk(KERN_DEBUG, &port->dev, MYIOC_s_FMT
1564 "delete port %d, sas_addr (0x%llx)\n", ioc->name,
1565 port->port_identifier, (unsigned long long)sas_address);
1566 sas_port_delete(port);
1567 mptsas_set_port(ioc, phy_info, NULL);
1568 mptsas_port_delete(ioc, phy_info->port_details);
1569}
1570
1571struct mptsas_phyinfo *
1572mptsas_refreshing_device_handles(MPT_ADAPTER *ioc,
1573 struct mptsas_devinfo *sas_device)
1574{
1575 struct mptsas_phyinfo *phy_info;
1576 struct mptsas_portinfo *port_info;
1577 int i;
1578
1579 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
1580 sas_device->sas_address);
1581 if (!phy_info)
1582 goto out;
1583 port_info = phy_info->portinfo;
1584 if (!port_info)
1585 goto out;
1586 mutex_lock(&ioc->sas_topology_mutex);
1587 for (i = 0; i < port_info->num_phys; i++) {
1588 if (port_info->phy_info[i].attached.sas_address !=
1589 sas_device->sas_address)
1590 continue;
1591 port_info->phy_info[i].attached.channel = sas_device->channel;
1592 port_info->phy_info[i].attached.id = sas_device->id;
1593 port_info->phy_info[i].attached.sas_address =
1594 sas_device->sas_address;
1595 port_info->phy_info[i].attached.handle = sas_device->handle;
1596 port_info->phy_info[i].attached.handle_parent =
1597 sas_device->handle_parent;
1598 port_info->phy_info[i].attached.handle_enclosure =
1599 sas_device->handle_enclosure;
1600 }
1601 mutex_unlock(&ioc->sas_topology_mutex);
1602 out:
1603 return phy_info;
1604}
1605
1606/**
1607 * mptsas_firmware_event_work - work thread for processing fw events
1608 * @work: work queue payload containing info describing the event
1609 * Context: user
1610 *
1611 */
1612static void
1613mptsas_firmware_event_work(struct work_struct *work)
1614{
1615 struct fw_event_work *fw_event =
1616 container_of(work, struct fw_event_work, work.work);
1617 MPT_ADAPTER *ioc = fw_event->ioc;
1618
eedf92b9
KD
1619 /* special rescan topology handling */
1620 if (fw_event->event == -1) {
1621 if (ioc->in_rescan) {
1622 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
1623 "%s: rescan ignored as it is in progress\n",
1624 ioc->name, __func__));
1625 return;
1626 }
1627 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: rescan after "
1628 "reset\n", ioc->name, __func__));
1629 ioc->in_rescan = 1;
1630 mptsas_not_responding_devices(ioc);
1631 mptsas_scan_sas_topology(ioc);
1632 ioc->in_rescan = 0;
1633 mptsas_free_fw_event(ioc, fw_event);
9766096d 1634 mptsas_fw_event_on(ioc);
eedf92b9
KD
1635 return;
1636 }
3eb0822c
KD
1637
1638 /* events handling turned off during host reset */
1639 if (ioc->fw_events_off) {
1640 mptsas_free_fw_event(ioc, fw_event);
1641 return;
1642 }
1643
1644 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: fw_event=(0x%p), "
1645 "event = (0x%02x)\n", ioc->name, __func__, fw_event,
1646 (fw_event->event & 0xFF)));
1647
1648 switch (fw_event->event) {
1649 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
1650 mptsas_send_sas_event(fw_event);
1651 break;
1652 case MPI_EVENT_INTEGRATED_RAID:
1653 mptsas_send_raid_event(fw_event);
1654 break;
1655 case MPI_EVENT_IR2:
1656 mptsas_send_ir2_event(fw_event);
1657 break;
1658 case MPI_EVENT_PERSISTENT_TABLE_FULL:
1659 mptbase_sas_persist_operation(ioc,
1660 MPI_SAS_OP_CLEAR_NOT_PRESENT);
1661 mptsas_free_fw_event(ioc, fw_event);
1662 break;
db7051b2
KD
1663 case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
1664 mptsas_broadcast_primative_work(fw_event);
1665 break;
f9c34022
KD
1666 case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
1667 mptsas_send_expander_event(fw_event);
1668 break;
1669 case MPI_EVENT_SAS_PHY_LINK_STATUS:
1670 mptsas_send_link_status_event(fw_event);
1671 break;
57e98513
KD
1672 case MPI_EVENT_QUEUE_FULL:
1673 mptsas_handle_queue_full_event(fw_event);
1674 break;
3eb0822c
KD
1675 }
1676}
1677
1678
1679
f013db32
JB
1680static int
1681mptsas_slave_configure(struct scsi_device *sdev)
1682{
3eb0822c
KD
1683 struct Scsi_Host *host = sdev->host;
1684 MPT_SCSI_HOST *hd = shost_priv(host);
1685 MPT_ADAPTER *ioc = hd->ioc;
a7938b0b 1686 VirtDevice *vdevice = sdev->hostdata;
3c0c25b9 1687
a7938b0b
KD
1688 if (vdevice->vtarget->deleted) {
1689 sdev_printk(KERN_INFO, sdev, "clearing deleted flag\n");
1690 vdevice->vtarget->deleted = 0;
1691 }
1692
1693 /*
1694 * RAID volumes placed beyond the last expected port.
1695 * Ignore sending sas mode pages in that case..
1696 */
1697 if (sdev->channel == MPTSAS_RAID_CHANNEL) {
1698 mptsas_add_device_component_starget_ir(ioc, scsi_target(sdev));
e8bf3941 1699 goto out;
a7938b0b 1700 }
e8bf3941
JB
1701
1702 sas_read_port_mode_page(sdev);
f013db32 1703
3eb0822c
KD
1704 mptsas_add_device_component_starget(ioc, scsi_target(sdev));
1705
e8bf3941 1706 out:
f013db32
JB
1707 return mptscsih_slave_configure(sdev);
1708}
1709
547f9a21
EM
1710static int
1711mptsas_target_alloc(struct scsi_target *starget)
1712{
1713 struct Scsi_Host *host = dev_to_shost(&starget->dev);
e7eae9f6 1714 MPT_SCSI_HOST *hd = shost_priv(host);
547f9a21 1715 VirtTarget *vtarget;
793955f5 1716 u8 id, channel;
547f9a21
EM
1717 struct sas_rphy *rphy;
1718 struct mptsas_portinfo *p;
1719 int i;
e80b002b 1720 MPT_ADAPTER *ioc = hd->ioc;
547f9a21
EM
1721
1722 vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL);
1723 if (!vtarget)
1724 return -ENOMEM;
1725
1726 vtarget->starget = starget;
e80b002b 1727 vtarget->ioc_id = ioc->id;
793955f5
EM
1728 vtarget->tflags = MPT_TARGET_FLAGS_Q_YES;
1729 id = starget->id;
547f9a21
EM
1730 channel = 0;
1731
793955f5
EM
1732 /*
1733 * RAID volumes placed beyond the last expected port.
1734 */
1735 if (starget->channel == MPTSAS_RAID_CHANNEL) {
a7938b0b
KD
1736 if (!ioc->raid_data.pIocPg2) {
1737 kfree(vtarget);
1738 return -ENXIO;
1739 }
1740 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
1741 if (id == ioc->raid_data.pIocPg2->
1742 RaidVolume[i].VolumeID) {
1743 channel = ioc->raid_data.pIocPg2->
1744 RaidVolume[i].VolumeBus;
1745 }
1746 }
1747 vtarget->raidVolume = 1;
547f9a21 1748 goto out;
793955f5 1749 }
547f9a21
EM
1750
1751 rphy = dev_to_rphy(starget->dev.parent);
e80b002b
EM
1752 mutex_lock(&ioc->sas_topology_mutex);
1753 list_for_each_entry(p, &ioc->sas_topology, list) {
547f9a21
EM
1754 for (i = 0; i < p->num_phys; i++) {
1755 if (p->phy_info[i].attached.sas_address !=
1756 rphy->identify.sas_address)
1757 continue;
793955f5 1758 id = p->phy_info[i].attached.id;
547f9a21
EM
1759 channel = p->phy_info[i].attached.channel;
1760 mptsas_set_starget(&p->phy_info[i], starget);
1761
1762 /*
1763 * Exposing hidden raid components
1764 */
e80b002b
EM
1765 if (mptscsih_is_phys_disk(ioc, channel, id)) {
1766 id = mptscsih_raid_id_to_num(ioc,
793955f5 1767 channel, id);
547f9a21
EM
1768 vtarget->tflags |=
1769 MPT_TARGET_FLAGS_RAID_COMPONENT;
b506ade9 1770 p->phy_info[i].attached.phys_disk_num = id;
547f9a21 1771 }
e80b002b 1772 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21
EM
1773 goto out;
1774 }
1775 }
e80b002b 1776 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21
EM
1777
1778 kfree(vtarget);
1779 return -ENXIO;
1780
1781 out:
793955f5
EM
1782 vtarget->id = id;
1783 vtarget->channel = channel;
547f9a21
EM
1784 starget->hostdata = vtarget;
1785 return 0;
1786}
1787
1788static void
1789mptsas_target_destroy(struct scsi_target *starget)
1790{
1791 struct Scsi_Host *host = dev_to_shost(&starget->dev);
e7eae9f6 1792 MPT_SCSI_HOST *hd = shost_priv(host);
547f9a21
EM
1793 struct sas_rphy *rphy;
1794 struct mptsas_portinfo *p;
1795 int i;
3eb0822c
KD
1796 MPT_ADAPTER *ioc = hd->ioc;
1797 VirtTarget *vtarget;
547f9a21
EM
1798
1799 if (!starget->hostdata)
1800 return;
1801
3eb0822c
KD
1802 vtarget = starget->hostdata;
1803
57e98513
KD
1804 mptsas_del_device_component_by_os(ioc, starget->channel,
1805 starget->id);
1806
3eb0822c 1807
e8bf3941 1808 if (starget->channel == MPTSAS_RAID_CHANNEL)
547f9a21
EM
1809 goto out;
1810
1811 rphy = dev_to_rphy(starget->dev.parent);
e80b002b 1812 list_for_each_entry(p, &ioc->sas_topology, list) {
547f9a21
EM
1813 for (i = 0; i < p->num_phys; i++) {
1814 if (p->phy_info[i].attached.sas_address !=
1815 rphy->identify.sas_address)
1816 continue;
3eb0822c
KD
1817
1818 starget_printk(KERN_INFO, starget, MYIOC_s_FMT
1819 "delete device: fw_channel %d, fw_id %d, phy %d, "
1820 "sas_addr 0x%llx\n", ioc->name,
1821 p->phy_info[i].attached.channel,
1822 p->phy_info[i].attached.id,
1823 p->phy_info[i].attached.phy_id, (unsigned long long)
1824 p->phy_info[i].attached.sas_address);
1825
547f9a21 1826 mptsas_set_starget(&p->phy_info[i], NULL);
547f9a21
EM
1827 }
1828 }
1829
1830 out:
3eb0822c 1831 vtarget->starget = NULL;
547f9a21
EM
1832 kfree(starget->hostdata);
1833 starget->hostdata = NULL;
1834}
1835
1836
0c33b27d 1837static int
c7c82987 1838mptsas_slave_alloc(struct scsi_device *sdev)
0c33b27d 1839{
c7c82987 1840 struct Scsi_Host *host = sdev->host;
e7eae9f6 1841 MPT_SCSI_HOST *hd = shost_priv(host);
0c33b27d
CH
1842 struct sas_rphy *rphy;
1843 struct mptsas_portinfo *p;
a69de507 1844 VirtDevice *vdevice;
c7c82987 1845 struct scsi_target *starget;
547f9a21 1846 int i;
e80b002b 1847 MPT_ADAPTER *ioc = hd->ioc;
0c33b27d 1848
a69de507
EM
1849 vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL);
1850 if (!vdevice) {
547f9a21 1851 printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n",
e80b002b 1852 ioc->name, sizeof(VirtDevice));
0c33b27d
CH
1853 return -ENOMEM;
1854 }
c7c82987 1855 starget = scsi_target(sdev);
a69de507 1856 vdevice->vtarget = starget->hostdata;
0c33b27d 1857
e8bf3941 1858 if (sdev->channel == MPTSAS_RAID_CHANNEL)
816aa907 1859 goto out;
816aa907 1860
c7c82987 1861 rphy = dev_to_rphy(sdev->sdev_target->dev.parent);
e80b002b
EM
1862 mutex_lock(&ioc->sas_topology_mutex);
1863 list_for_each_entry(p, &ioc->sas_topology, list) {
0c33b27d 1864 for (i = 0; i < p->num_phys; i++) {
547f9a21
EM
1865 if (p->phy_info[i].attached.sas_address !=
1866 rphy->identify.sas_address)
1867 continue;
a69de507 1868 vdevice->lun = sdev->lun;
547f9a21
EM
1869 /*
1870 * Exposing hidden raid components
1871 */
e80b002b 1872 if (mptscsih_is_phys_disk(ioc,
793955f5
EM
1873 p->phy_info[i].attached.channel,
1874 p->phy_info[i].attached.id))
547f9a21 1875 sdev->no_uld_attach = 1;
e80b002b 1876 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21 1877 goto out;
0c33b27d
CH
1878 }
1879 }
e80b002b 1880 mutex_unlock(&ioc->sas_topology_mutex);
0c33b27d 1881
a69de507 1882 kfree(vdevice);
23f236ed 1883 return -ENXIO;
0c33b27d
CH
1884
1885 out:
a69de507
EM
1886 vdevice->vtarget->num_luns++;
1887 sdev->hostdata = vdevice;
0c33b27d
CH
1888 return 0;
1889}
1890
547f9a21
EM
1891static int
1892mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *))
9a28f49a 1893{
7b5a65b9
KD
1894 MPT_SCSI_HOST *hd;
1895 MPT_ADAPTER *ioc;
a69de507 1896 VirtDevice *vdevice = SCpnt->device->hostdata;
7d3eecf7 1897
a69de507 1898 if (!vdevice || !vdevice->vtarget || vdevice->vtarget->deleted) {
547f9a21
EM
1899 SCpnt->result = DID_NO_CONNECT << 16;
1900 done(SCpnt);
1901 return 0;
7d3eecf7 1902 }
547f9a21 1903
7b5a65b9
KD
1904 hd = shost_priv(SCpnt->device->host);
1905 ioc = hd->ioc;
1906
1907 if (ioc->sas_discovery_quiesce_io)
1908 return SCSI_MLQUEUE_HOST_BUSY;
1909
64e155ad
KD
1910 if (ioc->debug_level & MPT_DEBUG_SCSI)
1911 scsi_print_command(SCpnt);
793955f5 1912
547f9a21 1913 return mptscsih_qcmd(SCpnt,done);
9a28f49a
CH
1914}
1915
c9de7dc4
KD
1916/**
1917 * mptsas_mptsas_eh_timed_out - resets the scsi_cmnd timeout
1918 * if the device under question is currently in the
1919 * device removal delay.
1920 * @sc: scsi command that the midlayer is about to time out
1921 *
1922 **/
1923static enum blk_eh_timer_return mptsas_eh_timed_out(struct scsi_cmnd *sc)
1924{
1925 MPT_SCSI_HOST *hd;
1926 MPT_ADAPTER *ioc;
1927 VirtDevice *vdevice;
1928 enum blk_eh_timer_return rc = BLK_EH_NOT_HANDLED;
1929
1930 hd = shost_priv(sc->device->host);
1931 if (hd == NULL) {
1932 printk(KERN_ERR MYNAM ": %s: Can't locate host! (sc=%p)\n",
1933 __func__, sc);
1934 goto done;
1935 }
1936
1937 ioc = hd->ioc;
1938 if (ioc->bus_type != SAS) {
1939 printk(KERN_ERR MYNAM ": %s: Wrong bus type (sc=%p)\n",
1940 __func__, sc);
1941 goto done;
1942 }
1943
1944 vdevice = sc->device->hostdata;
1945 if (vdevice && vdevice->vtarget && (vdevice->vtarget->inDMD
1946 || vdevice->vtarget->deleted)) {
1947 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT ": %s: target removed "
1948 "or in device removal delay (sc=%p)\n",
1949 ioc->name, __func__, sc));
1950 rc = BLK_EH_RESET_TIMER;
1951 goto done;
1952 }
1953
1954done:
1955 return rc;
1956}
1957
547f9a21 1958
0c33b27d 1959static struct scsi_host_template mptsas_driver_template = {
f78496da 1960 .module = THIS_MODULE,
0c33b27d
CH
1961 .proc_name = "mptsas",
1962 .proc_info = mptscsih_proc_info,
568da769 1963 .name = "MPT SAS Host",
0c33b27d 1964 .info = mptscsih_info,
547f9a21
EM
1965 .queuecommand = mptsas_qcmd,
1966 .target_alloc = mptsas_target_alloc,
0c33b27d 1967 .slave_alloc = mptsas_slave_alloc,
f013db32 1968 .slave_configure = mptsas_slave_configure,
547f9a21
EM
1969 .target_destroy = mptsas_target_destroy,
1970 .slave_destroy = mptscsih_slave_destroy,
0c33b27d
CH
1971 .change_queue_depth = mptscsih_change_queue_depth,
1972 .eh_abort_handler = mptscsih_abort,
1973 .eh_device_reset_handler = mptscsih_dev_reset,
1974 .eh_bus_reset_handler = mptscsih_bus_reset,
1975 .eh_host_reset_handler = mptscsih_host_reset,
1976 .bios_param = mptscsih_bios_param,
9d2e9d66 1977 .can_queue = MPT_SAS_CAN_QUEUE,
0c33b27d
CH
1978 .this_id = -1,
1979 .sg_tablesize = MPT_SCSI_SG_DEPTH,
1980 .max_sectors = 8192,
1981 .cmd_per_lun = 7,
1982 .use_clustering = ENABLE_CLUSTERING,
edb9068d 1983 .shost_attrs = mptscsih_host_attrs,
0c33b27d
CH
1984};
1985
b5141128 1986static int mptsas_get_linkerrors(struct sas_phy *phy)
0c33b27d 1987{
b5141128
CH
1988 MPT_ADAPTER *ioc = phy_to_ioc(phy);
1989 ConfigExtendedPageHeader_t hdr;
1990 CONFIGPARMS cfg;
1991 SasPhyPage1_t *buffer;
1992 dma_addr_t dma_handle;
1993 int error;
0c33b27d 1994
f4ad7b58
JB
1995 /* FIXME: only have link errors on local phys */
1996 if (!scsi_is_sas_phy_local(phy))
1997 return -EINVAL;
1998
b5141128
CH
1999 hdr.PageVersion = MPI_SASPHY1_PAGEVERSION;
2000 hdr.ExtPageLength = 0;
2001 hdr.PageNumber = 1 /* page number 1*/;
2002 hdr.Reserved1 = 0;
2003 hdr.Reserved2 = 0;
2004 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2005 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
0c33b27d 2006
b5141128
CH
2007 cfg.cfghdr.ehdr = &hdr;
2008 cfg.physAddr = -1;
2009 cfg.pageAddr = phy->identify.phy_identifier;
2010 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2011 cfg.dir = 0; /* read */
4b97650b 2012 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
0c33b27d 2013
b5141128
CH
2014 error = mpt_config(ioc, &cfg);
2015 if (error)
2016 return error;
2017 if (!hdr.ExtPageLength)
2018 return -ENXIO;
0c33b27d 2019
b5141128
CH
2020 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2021 &dma_handle);
2022 if (!buffer)
2023 return -ENOMEM;
0c33b27d 2024
b5141128
CH
2025 cfg.physAddr = dma_handle;
2026 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2027
2028 error = mpt_config(ioc, &cfg);
2029 if (error)
2030 goto out_free_consistent;
2031
d6ecdd63 2032 mptsas_print_phy_pg1(ioc, buffer);
b5141128
CH
2033
2034 phy->invalid_dword_count = le32_to_cpu(buffer->InvalidDwordCount);
2035 phy->running_disparity_error_count =
2036 le32_to_cpu(buffer->RunningDisparityErrorCount);
2037 phy->loss_of_dword_sync_count =
2038 le32_to_cpu(buffer->LossDwordSynchCount);
2039 phy->phy_reset_problem_count =
2040 le32_to_cpu(buffer->PhyResetProblemCount);
2041
2042 out_free_consistent:
2043 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2044 buffer, dma_handle);
2045 return error;
0c33b27d
CH
2046}
2047
da4fa655
CH
2048static int mptsas_mgmt_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *req,
2049 MPT_FRAME_HDR *reply)
2050{
f0f09d3b 2051 ioc->sas_mgmt.status |= MPT_MGMT_STATUS_COMMAND_GOOD;
da4fa655 2052 if (reply != NULL) {
f0f09d3b 2053 ioc->sas_mgmt.status |= MPT_MGMT_STATUS_RF_VALID;
da4fa655
CH
2054 memcpy(ioc->sas_mgmt.reply, reply,
2055 min(ioc->reply_sz, 4 * reply->u.reply.MsgLength));
2056 }
2f187862
KD
2057
2058 if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_PENDING) {
2059 ioc->sas_mgmt.status &= ~MPT_MGMT_STATUS_PENDING;
2060 complete(&ioc->sas_mgmt.done);
2061 return 1;
2062 }
2063 return 0;
da4fa655
CH
2064}
2065
2066static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset)
2067{
2068 MPT_ADAPTER *ioc = phy_to_ioc(phy);
2069 SasIoUnitControlRequest_t *req;
2070 SasIoUnitControlReply_t *reply;
2071 MPT_FRAME_HDR *mf;
2072 MPIHeader_t *hdr;
2073 unsigned long timeleft;
2074 int error = -ERESTARTSYS;
2075
f4ad7b58
JB
2076 /* FIXME: fusion doesn't allow non-local phy reset */
2077 if (!scsi_is_sas_phy_local(phy))
2078 return -EINVAL;
2079
da4fa655
CH
2080 /* not implemented for expanders */
2081 if (phy->identify.target_port_protocols & SAS_PROTOCOL_SMP)
2082 return -ENXIO;
2083
eeb846ce 2084 if (mutex_lock_interruptible(&ioc->sas_mgmt.mutex))
da4fa655
CH
2085 goto out;
2086
2087 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
2088 if (!mf) {
2089 error = -ENOMEM;
2090 goto out_unlock;
2091 }
2092
2093 hdr = (MPIHeader_t *) mf;
2094 req = (SasIoUnitControlRequest_t *)mf;
2095 memset(req, 0, sizeof(SasIoUnitControlRequest_t));
2096 req->Function = MPI_FUNCTION_SAS_IO_UNIT_CONTROL;
2097 req->MsgContext = hdr->MsgContext;
2098 req->Operation = hard_reset ?
2099 MPI_SAS_OP_PHY_HARD_RESET : MPI_SAS_OP_PHY_LINK_RESET;
2100 req->PhyNum = phy->identify.phy_identifier;
2101
2f187862 2102 INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
da4fa655
CH
2103 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
2104
2105 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done,
2106 10 * HZ);
568da769
KD
2107 if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
2108 error = -ETIME;
da4fa655 2109 mpt_free_msg_frame(ioc, mf);
568da769
KD
2110 if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET)
2111 goto out_unlock;
2112 if (!timeleft)
2113 mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
da4fa655
CH
2114 goto out_unlock;
2115 }
2116
2117 /* a reply frame is expected */
2118 if ((ioc->sas_mgmt.status &
f0f09d3b 2119 MPT_MGMT_STATUS_RF_VALID) == 0) {
da4fa655
CH
2120 error = -ENXIO;
2121 goto out_unlock;
2122 }
2123
2124 /* process the completed Reply Message Frame */
2125 reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply;
2126 if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) {
29dd3609 2127 printk(MYIOC_s_INFO_FMT "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n",
cadbd4a5 2128 ioc->name, __func__, reply->IOCStatus, reply->IOCLogInfo);
da4fa655
CH
2129 error = -ENXIO;
2130 goto out_unlock;
2131 }
2132
2133 error = 0;
2134
2135 out_unlock:
2f187862 2136 CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
eeb846ce 2137 mutex_unlock(&ioc->sas_mgmt.mutex);
da4fa655
CH
2138 out:
2139 return error;
2140}
0c33b27d 2141
e3094447
CH
2142static int
2143mptsas_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
2144{
2145 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
2146 int i, error;
2147 struct mptsas_portinfo *p;
2148 struct mptsas_enclosure enclosure_info;
2149 u64 enclosure_handle;
2150
2151 mutex_lock(&ioc->sas_topology_mutex);
2152 list_for_each_entry(p, &ioc->sas_topology, list) {
2153 for (i = 0; i < p->num_phys; i++) {
2154 if (p->phy_info[i].attached.sas_address ==
2155 rphy->identify.sas_address) {
2156 enclosure_handle = p->phy_info[i].
2157 attached.handle_enclosure;
2158 goto found_info;
2159 }
2160 }
2161 }
2162 mutex_unlock(&ioc->sas_topology_mutex);
2163 return -ENXIO;
2164
2165 found_info:
2166 mutex_unlock(&ioc->sas_topology_mutex);
2167 memset(&enclosure_info, 0, sizeof(struct mptsas_enclosure));
52435430 2168 error = mptsas_sas_enclosure_pg0(ioc, &enclosure_info,
e3094447
CH
2169 (MPI_SAS_ENCLOS_PGAD_FORM_HANDLE <<
2170 MPI_SAS_ENCLOS_PGAD_FORM_SHIFT), enclosure_handle);
2171 if (!error)
2172 *identifier = enclosure_info.enclosure_logical_id;
2173 return error;
2174}
2175
2176static int
2177mptsas_get_bay_identifier(struct sas_rphy *rphy)
2178{
2179 MPT_ADAPTER *ioc = rphy_to_ioc(rphy);
2180 struct mptsas_portinfo *p;
2181 int i, rc;
2182
2183 mutex_lock(&ioc->sas_topology_mutex);
2184 list_for_each_entry(p, &ioc->sas_topology, list) {
2185 for (i = 0; i < p->num_phys; i++) {
2186 if (p->phy_info[i].attached.sas_address ==
2187 rphy->identify.sas_address) {
2188 rc = p->phy_info[i].attached.slot;
2189 goto out;
2190 }
2191 }
2192 }
2193 rc = -ENXIO;
2194 out:
2195 mutex_unlock(&ioc->sas_topology_mutex);
2196 return rc;
2197}
2198
159e36fe
FT
2199static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
2200 struct request *req)
2201{
2202 MPT_ADAPTER *ioc = ((MPT_SCSI_HOST *) shost->hostdata)->ioc;
2203 MPT_FRAME_HDR *mf;
2204 SmpPassthroughRequest_t *smpreq;
2205 struct request *rsp = req->next_rq;
2206 int ret;
2207 int flagsLength;
2208 unsigned long timeleft;
2209 char *psge;
2210 dma_addr_t dma_addr_in = 0;
2211 dma_addr_t dma_addr_out = 0;
2212 u64 sas_address = 0;
2213
2214 if (!rsp) {
29dd3609 2215 printk(MYIOC_s_ERR_FMT "%s: the smp response space is missing\n",
cadbd4a5 2216 ioc->name, __func__);
159e36fe
FT
2217 return -EINVAL;
2218 }
2219
2220 /* do we need to support multiple segments? */
2221 if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
29dd3609 2222 printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n",
b0790410
TH
2223 ioc->name, __func__, req->bio->bi_vcnt, blk_rq_bytes(req),
2224 rsp->bio->bi_vcnt, blk_rq_bytes(rsp));
159e36fe
FT
2225 return -EINVAL;
2226 }
2227
2228 ret = mutex_lock_interruptible(&ioc->sas_mgmt.mutex);
2229 if (ret)
2230 goto out;
2231
2232 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
2233 if (!mf) {
2234 ret = -ENOMEM;
2235 goto out_unlock;
2236 }
2237
2238 smpreq = (SmpPassthroughRequest_t *)mf;
2239 memset(smpreq, 0, sizeof(*smpreq));
2240
b0790410 2241 smpreq->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4);
159e36fe
FT
2242 smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
2243
2244 if (rphy)
2245 sas_address = rphy->identify.sas_address;
2246 else {
2247 struct mptsas_portinfo *port_info;
2248
2249 mutex_lock(&ioc->sas_topology_mutex);
f9c34022 2250 port_info = ioc->hba_port_info;
159e36fe
FT
2251 if (port_info && port_info->phy_info)
2252 sas_address =
2253 port_info->phy_info[0].phy->identify.sas_address;
2254 mutex_unlock(&ioc->sas_topology_mutex);
2255 }
2256
2257 *((u64 *)&smpreq->SASAddress) = cpu_to_le64(sas_address);
2258
2259 psge = (char *)
2260 (((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4));
2261
2262 /* request */
2263 flagsLength = (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2264 MPI_SGE_FLAGS_END_OF_BUFFER |
14d0f0b0
KD
2265 MPI_SGE_FLAGS_DIRECTION)
2266 << MPI_SGE_FLAGS_SHIFT;
b0790410 2267 flagsLength |= (blk_rq_bytes(req) - 4);
159e36fe
FT
2268
2269 dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio),
b0790410 2270 blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL);
159e36fe
FT
2271 if (!dma_addr_out)
2272 goto put_mf;
14d0f0b0 2273 ioc->add_sge(psge, flagsLength, dma_addr_out);
2f187862 2274 psge += ioc->SGE_size;
159e36fe
FT
2275
2276 /* response */
2f187862
KD
2277 flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2278 MPI_SGE_FLAGS_SYSTEM_ADDRESS |
2279 MPI_SGE_FLAGS_IOC_TO_HOST |
2280 MPI_SGE_FLAGS_END_OF_BUFFER;
2281
2282 flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
b0790410 2283 flagsLength |= blk_rq_bytes(rsp) + 4;
159e36fe 2284 dma_addr_in = pci_map_single(ioc->pcidev, bio_data(rsp->bio),
b0790410 2285 blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL);
159e36fe
FT
2286 if (!dma_addr_in)
2287 goto unmap;
14d0f0b0 2288 ioc->add_sge(psge, flagsLength, dma_addr_in);
159e36fe 2289
2f187862 2290 INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
159e36fe
FT
2291 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
2292
2293 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
568da769
KD
2294 if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
2295 ret = -ETIME;
2296 mpt_free_msg_frame(ioc, mf);
2297 mf = NULL;
2298 if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET)
2299 goto unmap;
2300 if (!timeleft)
2301 mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
159e36fe
FT
2302 goto unmap;
2303 }
2304 mf = NULL;
2305
f0f09d3b 2306 if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_RF_VALID) {
159e36fe
FT
2307 SmpPassthroughReply_t *smprep;
2308
2309 smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
2310 memcpy(req->sense, smprep, sizeof(*smprep));
2311 req->sense_len = sizeof(*smprep);
5f49f631
TH
2312 req->resid_len = 0;
2313 rsp->resid_len -= smprep->ResponseDataLength;
159e36fe 2314 } else {
2f187862
KD
2315 printk(MYIOC_s_ERR_FMT
2316 "%s: smp passthru reply failed to be returned\n",
cadbd4a5 2317 ioc->name, __func__);
159e36fe
FT
2318 ret = -ENXIO;
2319 }
2320unmap:
2321 if (dma_addr_out)
b0790410 2322 pci_unmap_single(ioc->pcidev, dma_addr_out, blk_rq_bytes(req),
159e36fe
FT
2323 PCI_DMA_BIDIRECTIONAL);
2324 if (dma_addr_in)
b0790410 2325 pci_unmap_single(ioc->pcidev, dma_addr_in, blk_rq_bytes(rsp),
159e36fe
FT
2326 PCI_DMA_BIDIRECTIONAL);
2327put_mf:
2328 if (mf)
2329 mpt_free_msg_frame(ioc, mf);
2330out_unlock:
2f187862 2331 CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
159e36fe
FT
2332 mutex_unlock(&ioc->sas_mgmt.mutex);
2333out:
2334 return ret;
2335}
2336
b5141128
CH
2337static struct sas_function_template mptsas_transport_functions = {
2338 .get_linkerrors = mptsas_get_linkerrors,
e3094447
CH
2339 .get_enclosure_identifier = mptsas_get_enclosure_identifier,
2340 .get_bay_identifier = mptsas_get_bay_identifier,
da4fa655 2341 .phy_reset = mptsas_phy_reset,
159e36fe 2342 .smp_handler = mptsas_smp_handler,
b5141128
CH
2343};
2344
2345static struct scsi_transport_template *mptsas_transport_template;
0c33b27d
CH
2346
2347static int
2348mptsas_sas_io_unit_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
2349{
2350 ConfigExtendedPageHeader_t hdr;
2351 CONFIGPARMS cfg;
2352 SasIOUnitPage0_t *buffer;
2353 dma_addr_t dma_handle;
2354 int error, i;
2355
2356 hdr.PageVersion = MPI_SASIOUNITPAGE0_PAGEVERSION;
2357 hdr.ExtPageLength = 0;
2358 hdr.PageNumber = 0;
2359 hdr.Reserved1 = 0;
2360 hdr.Reserved2 = 0;
2361 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2362 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
2363
2364 cfg.cfghdr.ehdr = &hdr;
2365 cfg.physAddr = -1;
2366 cfg.pageAddr = 0;
2367 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2368 cfg.dir = 0; /* read */
4b97650b 2369 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
0c33b27d
CH
2370
2371 error = mpt_config(ioc, &cfg);
2372 if (error)
2373 goto out;
2374 if (!hdr.ExtPageLength) {
2375 error = -ENXIO;
2376 goto out;
2377 }
2378
2379 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2380 &dma_handle);
2381 if (!buffer) {
2382 error = -ENOMEM;
2383 goto out;
2384 }
2385
2386 cfg.physAddr = dma_handle;
2387 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2388
2389 error = mpt_config(ioc, &cfg);
2390 if (error)
2391 goto out_free_consistent;
2392
2393 port_info->num_phys = buffer->NumPhys;
2394 port_info->phy_info = kcalloc(port_info->num_phys,
2f187862 2395 sizeof(struct mptsas_phyinfo), GFP_KERNEL);
0c33b27d
CH
2396 if (!port_info->phy_info) {
2397 error = -ENOMEM;
2398 goto out_free_consistent;
2399 }
2400
edb9068d
PS
2401 ioc->nvdata_version_persistent =
2402 le16_to_cpu(buffer->NvdataVersionPersistent);
2403 ioc->nvdata_version_default =
2404 le16_to_cpu(buffer->NvdataVersionDefault);
2405
0c33b27d 2406 for (i = 0; i < port_info->num_phys; i++) {
d6ecdd63 2407 mptsas_print_phy_data(ioc, &buffer->PhyData[i]);
0c33b27d
CH
2408 port_info->phy_info[i].phy_id = i;
2409 port_info->phy_info[i].port_id =
2410 buffer->PhyData[i].Port;
2411 port_info->phy_info[i].negotiated_link_rate =
2412 buffer->PhyData[i].NegotiatedLinkRate;
547f9a21 2413 port_info->phy_info[i].portinfo = port_info;
2ecce492
EM
2414 port_info->phy_info[i].handle =
2415 le16_to_cpu(buffer->PhyData[i].ControllerDevHandle);
0c33b27d
CH
2416 }
2417
2418 out_free_consistent:
2419 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2420 buffer, dma_handle);
2421 out:
2422 return error;
2423}
2424
edb9068d
PS
2425static int
2426mptsas_sas_io_unit_pg1(MPT_ADAPTER *ioc)
2427{
2428 ConfigExtendedPageHeader_t hdr;
2429 CONFIGPARMS cfg;
2430 SasIOUnitPage1_t *buffer;
2431 dma_addr_t dma_handle;
2432 int error;
aca794dd 2433 u8 device_missing_delay;
edb9068d
PS
2434
2435 memset(&hdr, 0, sizeof(ConfigExtendedPageHeader_t));
2436 memset(&cfg, 0, sizeof(CONFIGPARMS));
2437
2438 cfg.cfghdr.ehdr = &hdr;
2439 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
4b97650b 2440 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
edb9068d
PS
2441 cfg.cfghdr.ehdr->PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2442 cfg.cfghdr.ehdr->ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
2443 cfg.cfghdr.ehdr->PageVersion = MPI_SASIOUNITPAGE1_PAGEVERSION;
2444 cfg.cfghdr.ehdr->PageNumber = 1;
2445
2446 error = mpt_config(ioc, &cfg);
2447 if (error)
2448 goto out;
2449 if (!hdr.ExtPageLength) {
2450 error = -ENXIO;
2451 goto out;
2452 }
2453
2454 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2455 &dma_handle);
2456 if (!buffer) {
2457 error = -ENOMEM;
2458 goto out;
2459 }
2460
2461 cfg.physAddr = dma_handle;
2462 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2463
2464 error = mpt_config(ioc, &cfg);
2465 if (error)
2466 goto out_free_consistent;
2467
2468 ioc->io_missing_delay =
2469 le16_to_cpu(buffer->IODeviceMissingDelay);
aca794dd 2470 device_missing_delay = buffer->ReportDeviceMissingDelay;
edb9068d
PS
2471 ioc->device_missing_delay = (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_UNIT_16) ?
2472 (device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16 :
2473 device_missing_delay & MPI_SAS_IOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
2474
2475 out_free_consistent:
2476 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2477 buffer, dma_handle);
2478 out:
2479 return error;
2480}
2481
0c33b27d
CH
2482static int
2483mptsas_sas_phy_pg0(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
2484 u32 form, u32 form_specific)
2485{
2486 ConfigExtendedPageHeader_t hdr;
2487 CONFIGPARMS cfg;
2488 SasPhyPage0_t *buffer;
2489 dma_addr_t dma_handle;
2490 int error;
2491
2492 hdr.PageVersion = MPI_SASPHY0_PAGEVERSION;
2493 hdr.ExtPageLength = 0;
2494 hdr.PageNumber = 0;
2495 hdr.Reserved1 = 0;
2496 hdr.Reserved2 = 0;
2497 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2498 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_PHY;
2499
2500 cfg.cfghdr.ehdr = &hdr;
2501 cfg.dir = 0; /* read */
4b97650b 2502 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
0c33b27d
CH
2503
2504 /* Get Phy Pg 0 for each Phy. */
2505 cfg.physAddr = -1;
2506 cfg.pageAddr = form + form_specific;
2507 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2508
2509 error = mpt_config(ioc, &cfg);
2510 if (error)
2511 goto out;
2512
2513 if (!hdr.ExtPageLength) {
2514 error = -ENXIO;
2515 goto out;
2516 }
2517
2518 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2519 &dma_handle);
2520 if (!buffer) {
2521 error = -ENOMEM;
2522 goto out;
2523 }
2524
2525 cfg.physAddr = dma_handle;
2526 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2527
2528 error = mpt_config(ioc, &cfg);
2529 if (error)
2530 goto out_free_consistent;
2531
d6ecdd63 2532 mptsas_print_phy_pg0(ioc, buffer);
0c33b27d
CH
2533
2534 phy_info->hw_link_rate = buffer->HwLinkRate;
2535 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
2536 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
2537 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
2538
2539 out_free_consistent:
2540 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2541 buffer, dma_handle);
2542 out:
2543 return error;
2544}
2545
2546static int
2547mptsas_sas_device_pg0(MPT_ADAPTER *ioc, struct mptsas_devinfo *device_info,
2548 u32 form, u32 form_specific)
2549{
2550 ConfigExtendedPageHeader_t hdr;
2551 CONFIGPARMS cfg;
2552 SasDevicePage0_t *buffer;
2553 dma_addr_t dma_handle;
2554 __le64 sas_address;
bd23e94c
ME
2555 int error=0;
2556
0c33b27d
CH
2557 hdr.PageVersion = MPI_SASDEVICE0_PAGEVERSION;
2558 hdr.ExtPageLength = 0;
2559 hdr.PageNumber = 0;
2560 hdr.Reserved1 = 0;
2561 hdr.Reserved2 = 0;
2562 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2563 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_DEVICE;
2564
2565 cfg.cfghdr.ehdr = &hdr;
2566 cfg.pageAddr = form + form_specific;
2567 cfg.physAddr = -1;
2568 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2569 cfg.dir = 0; /* read */
4b97650b 2570 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
0c33b27d 2571
db9c9174 2572 memset(device_info, 0, sizeof(struct mptsas_devinfo));
0c33b27d
CH
2573 error = mpt_config(ioc, &cfg);
2574 if (error)
2575 goto out;
2576 if (!hdr.ExtPageLength) {
2577 error = -ENXIO;
2578 goto out;
2579 }
2580
2581 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2582 &dma_handle);
2583 if (!buffer) {
2584 error = -ENOMEM;
2585 goto out;
2586 }
2587
2588 cfg.physAddr = dma_handle;
2589 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2590
2591 error = mpt_config(ioc, &cfg);
0cf0f23c
KD
2592
2593 if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
2594 error = -ENODEV;
2595 goto out_free_consistent;
2596 }
2597
0c33b27d
CH
2598 if (error)
2599 goto out_free_consistent;
2600
d6ecdd63 2601 mptsas_print_device_pg0(ioc, buffer);
0c33b27d 2602
2f187862 2603 memset(device_info, 0, sizeof(struct mptsas_devinfo));
0c33b27d 2604 device_info->handle = le16_to_cpu(buffer->DevHandle);
c73787ee 2605 device_info->handle_parent = le16_to_cpu(buffer->ParentDevHandle);
e3094447
CH
2606 device_info->handle_enclosure =
2607 le16_to_cpu(buffer->EnclosureHandle);
2608 device_info->slot = le16_to_cpu(buffer->Slot);
0c33b27d
CH
2609 device_info->phy_id = buffer->PhyNum;
2610 device_info->port_id = buffer->PhysicalPort;
9a28f49a 2611 device_info->id = buffer->TargetID;
b506ade9 2612 device_info->phys_disk_num = ~0;
9a28f49a 2613 device_info->channel = buffer->Bus;
0c33b27d
CH
2614 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
2615 device_info->sas_address = le64_to_cpu(sas_address);
2616 device_info->device_info =
2617 le32_to_cpu(buffer->DeviceInfo);
51106ab5 2618 device_info->flags = le16_to_cpu(buffer->Flags);
0c33b27d
CH
2619
2620 out_free_consistent:
2621 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2622 buffer, dma_handle);
2623 out:
2624 return error;
2625}
2626
2627static int
2628mptsas_sas_expander_pg0(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info,
2629 u32 form, u32 form_specific)
2630{
2631 ConfigExtendedPageHeader_t hdr;
2632 CONFIGPARMS cfg;
2633 SasExpanderPage0_t *buffer;
2634 dma_addr_t dma_handle;
547f9a21 2635 int i, error;
2f187862 2636 __le64 sas_address;
0c33b27d 2637
2f187862 2638 memset(port_info, 0, sizeof(struct mptsas_portinfo));
0c33b27d
CH
2639 hdr.PageVersion = MPI_SASEXPANDER0_PAGEVERSION;
2640 hdr.ExtPageLength = 0;
2641 hdr.PageNumber = 0;
2642 hdr.Reserved1 = 0;
2643 hdr.Reserved2 = 0;
2644 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2645 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
2646
2647 cfg.cfghdr.ehdr = &hdr;
2648 cfg.physAddr = -1;
2649 cfg.pageAddr = form + form_specific;
2650 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2651 cfg.dir = 0; /* read */
4b97650b 2652 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
0c33b27d 2653
db9c9174 2654 memset(port_info, 0, sizeof(struct mptsas_portinfo));
0c33b27d
CH
2655 error = mpt_config(ioc, &cfg);
2656 if (error)
2657 goto out;
2658
2659 if (!hdr.ExtPageLength) {
2660 error = -ENXIO;
2661 goto out;
2662 }
2663
2664 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2665 &dma_handle);
2666 if (!buffer) {
2667 error = -ENOMEM;
2668 goto out;
2669 }
2670
2671 cfg.physAddr = dma_handle;
2672 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2673
2674 error = mpt_config(ioc, &cfg);
0cf0f23c 2675 if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
51f39eae
KO
2676 error = -ENODEV;
2677 goto out_free_consistent;
2678 }
2679
0cf0f23c
KD
2680 if (error)
2681 goto out_free_consistent;
2682
0c33b27d 2683 /* save config data */
2f187862 2684 port_info->num_phys = (buffer->NumPhys) ? buffer->NumPhys : 1;
0c33b27d 2685 port_info->phy_info = kcalloc(port_info->num_phys,
2f187862 2686 sizeof(struct mptsas_phyinfo), GFP_KERNEL);
0c33b27d
CH
2687 if (!port_info->phy_info) {
2688 error = -ENOMEM;
2689 goto out_free_consistent;
2690 }
2691
2f187862 2692 memcpy(&sas_address, &buffer->SASAddress, sizeof(__le64));
2ecce492 2693 for (i = 0; i < port_info->num_phys; i++) {
547f9a21 2694 port_info->phy_info[i].portinfo = port_info;
2ecce492
EM
2695 port_info->phy_info[i].handle =
2696 le16_to_cpu(buffer->DevHandle);
2f187862
KD
2697 port_info->phy_info[i].identify.sas_address =
2698 le64_to_cpu(sas_address);
2699 port_info->phy_info[i].identify.handle_parent =
2700 le16_to_cpu(buffer->ParentDevHandle);
2ecce492 2701 }
547f9a21 2702
0c33b27d
CH
2703 out_free_consistent:
2704 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2705 buffer, dma_handle);
2706 out:
2707 return error;
2708}
2709
2710static int
2711mptsas_sas_expander_pg1(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info,
2712 u32 form, u32 form_specific)
2713{
2714 ConfigExtendedPageHeader_t hdr;
2715 CONFIGPARMS cfg;
2716 SasExpanderPage1_t *buffer;
2717 dma_addr_t dma_handle;
bd23e94c
ME
2718 int error=0;
2719
2f187862 2720 hdr.PageVersion = MPI_SASEXPANDER1_PAGEVERSION;
0c33b27d
CH
2721 hdr.ExtPageLength = 0;
2722 hdr.PageNumber = 1;
2723 hdr.Reserved1 = 0;
2724 hdr.Reserved2 = 0;
2725 hdr.PageType = MPI_CONFIG_PAGETYPE_EXTENDED;
2726 hdr.ExtPageType = MPI_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
2727
2728 cfg.cfghdr.ehdr = &hdr;
2729 cfg.physAddr = -1;
2730 cfg.pageAddr = form + form_specific;
2731 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
2732 cfg.dir = 0; /* read */
4b97650b 2733 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
0c33b27d
CH
2734
2735 error = mpt_config(ioc, &cfg);
2736 if (error)
2737 goto out;
2738
2739 if (!hdr.ExtPageLength) {
2740 error = -ENXIO;
2741 goto out;
2742 }
2743
2744 buffer = pci_alloc_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2745 &dma_handle);
2746 if (!buffer) {
2747 error = -ENOMEM;
2748 goto out;
2749 }
2750
2751 cfg.physAddr = dma_handle;
2752 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
2753
2754 error = mpt_config(ioc, &cfg);
2f187862
KD
2755
2756 if (error == MPI_IOCSTATUS_CONFIG_INVALID_PAGE) {
2757 error = -ENODEV;
0cf0f23c 2758 goto out_free_consistent;
2f187862
KD
2759 }
2760
0c33b27d
CH
2761 if (error)
2762 goto out_free_consistent;
2763
2764
d6ecdd63 2765 mptsas_print_expander_pg1(ioc, buffer);
0c33b27d
CH
2766
2767 /* save config data */
024358ee 2768 phy_info->phy_id = buffer->PhyIdentifier;
0c33b27d
CH
2769 phy_info->port_id = buffer->PhysicalPort;
2770 phy_info->negotiated_link_rate = buffer->NegotiatedLinkRate;
2771 phy_info->programmed_link_rate = buffer->ProgrammedLinkRate;
2772 phy_info->hw_link_rate = buffer->HwLinkRate;
2773 phy_info->identify.handle = le16_to_cpu(buffer->OwnerDevHandle);
2774 phy_info->attached.handle = le16_to_cpu(buffer->AttachedDevHandle);
2775
0c33b27d
CH
2776 out_free_consistent:
2777 pci_free_consistent(ioc->pcidev, hdr.ExtPageLength * 4,
2778 buffer, dma_handle);
2779 out:
2780 return error;
2781}
2782
e0f553ab
KD
2783struct rep_manu_request{
2784 u8 smp_frame_type;
2785 u8 function;
2786 u8 reserved;
2787 u8 request_length;
2788};
2789
2790struct rep_manu_reply{
2791 u8 smp_frame_type; /* 0x41 */
2792 u8 function; /* 0x01 */
2793 u8 function_result;
2794 u8 response_length;
2795 u16 expander_change_count;
2796 u8 reserved0[2];
2797 u8 sas_format:1;
2798 u8 reserved1:7;
2799 u8 reserved2[3];
2800 u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
2801 u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
2802 u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
2803 u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
2804 u16 component_id;
2805 u8 component_revision_id;
2806 u8 reserved3;
2807 u8 vendor_specific[8];
2808};
2809
2810/**
2811 * mptsas_exp_repmanufacture_info -
2812 * @ioc: per adapter object
2813 * @sas_address: expander sas address
2814 * @edev: the sas_expander_device object
2815 *
2816 * Fills in the sas_expander_device object when SMP port is created.
2817 *
2818 * Returns 0 for success, non-zero for failure.
2819 */
2820static int
2821mptsas_exp_repmanufacture_info(MPT_ADAPTER *ioc,
2822 u64 sas_address, struct sas_expander_device *edev)
2823{
2824 MPT_FRAME_HDR *mf;
2825 SmpPassthroughRequest_t *smpreq;
2826 SmpPassthroughReply_t *smprep;
2827 struct rep_manu_reply *manufacture_reply;
2828 struct rep_manu_request *manufacture_request;
2829 int ret;
2830 int flagsLength;
2831 unsigned long timeleft;
2832 char *psge;
2833 unsigned long flags;
2834 void *data_out = NULL;
2835 dma_addr_t data_out_dma = 0;
2836 u32 sz;
2837
2838 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
2839 if (ioc->ioc_reset_in_progress) {
2840 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
2841 printk(MYIOC_s_INFO_FMT "%s: host reset in progress!\n",
2842 __func__, ioc->name);
2843 return -EFAULT;
2844 }
2845 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
2846
2847 ret = mutex_lock_interruptible(&ioc->sas_mgmt.mutex);
2848 if (ret)
2849 goto out;
2850
2851 mf = mpt_get_msg_frame(mptsasMgmtCtx, ioc);
2852 if (!mf) {
2853 ret = -ENOMEM;
2854 goto out_unlock;
2855 }
2856
2857 smpreq = (SmpPassthroughRequest_t *)mf;
2858 memset(smpreq, 0, sizeof(*smpreq));
2859
2860 sz = sizeof(struct rep_manu_request) + sizeof(struct rep_manu_reply);
2861
2862 data_out = pci_alloc_consistent(ioc->pcidev, sz, &data_out_dma);
2863 if (!data_out) {
2864 printk(KERN_ERR "Memory allocation failure at %s:%d/%s()!\n",
2865 __FILE__, __LINE__, __func__);
2866 ret = -ENOMEM;
2867 goto put_mf;
2868 }
2869
2870 manufacture_request = data_out;
2871 manufacture_request->smp_frame_type = 0x40;
2872 manufacture_request->function = 1;
2873 manufacture_request->reserved = 0;
2874 manufacture_request->request_length = 0;
2875
2876 smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH;
2877 smpreq->PhysicalPort = 0xFF;
2878 *((u64 *)&smpreq->SASAddress) = cpu_to_le64(sas_address);
2879 smpreq->RequestDataLength = sizeof(struct rep_manu_request);
2880
2881 psge = (char *)
2882 (((int *) mf) + (offsetof(SmpPassthroughRequest_t, SGL) / 4));
2883
2884 flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2885 MPI_SGE_FLAGS_SYSTEM_ADDRESS |
2886 MPI_SGE_FLAGS_HOST_TO_IOC |
2887 MPI_SGE_FLAGS_END_OF_BUFFER;
2888 flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
2889 flagsLength |= sizeof(struct rep_manu_request);
2890
2891 ioc->add_sge(psge, flagsLength, data_out_dma);
2892 psge += ioc->SGE_size;
2893
2894 flagsLength = MPI_SGE_FLAGS_SIMPLE_ELEMENT |
2895 MPI_SGE_FLAGS_SYSTEM_ADDRESS |
2896 MPI_SGE_FLAGS_IOC_TO_HOST |
2897 MPI_SGE_FLAGS_END_OF_BUFFER;
2898 flagsLength = flagsLength << MPI_SGE_FLAGS_SHIFT;
2899 flagsLength |= sizeof(struct rep_manu_reply);
2900 ioc->add_sge(psge, flagsLength, data_out_dma +
2901 sizeof(struct rep_manu_request));
2902
2903 INITIALIZE_MGMT_STATUS(ioc->sas_mgmt.status)
2904 mpt_put_msg_frame(mptsasMgmtCtx, ioc, mf);
2905
2906 timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ);
2907 if (!(ioc->sas_mgmt.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
2908 ret = -ETIME;
2909 mpt_free_msg_frame(ioc, mf);
2910 mf = NULL;
2911 if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_DID_IOCRESET)
2912 goto out_free;
2913 if (!timeleft)
d0f698c4 2914 mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
e0f553ab
KD
2915 goto out_free;
2916 }
2917
2918 mf = NULL;
2919
2920 if (ioc->sas_mgmt.status & MPT_MGMT_STATUS_RF_VALID) {
2921 u8 *tmp;
2922
2923 smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply;
2924 if (le16_to_cpu(smprep->ResponseDataLength) !=
2925 sizeof(struct rep_manu_reply))
2926 goto out_free;
2927
2928 manufacture_reply = data_out + sizeof(struct rep_manu_request);
2929 strncpy(edev->vendor_id, manufacture_reply->vendor_id,
2930 SAS_EXPANDER_VENDOR_ID_LEN);
2931 strncpy(edev->product_id, manufacture_reply->product_id,
2932 SAS_EXPANDER_PRODUCT_ID_LEN);
2933 strncpy(edev->product_rev, manufacture_reply->product_rev,
2934 SAS_EXPANDER_PRODUCT_REV_LEN);
2935 edev->level = manufacture_reply->sas_format;
2936 if (manufacture_reply->sas_format) {
2937 strncpy(edev->component_vendor_id,
2938 manufacture_reply->component_vendor_id,
2939 SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
2940 tmp = (u8 *)&manufacture_reply->component_id;
2941 edev->component_id = tmp[0] << 8 | tmp[1];
2942 edev->component_revision_id =
2943 manufacture_reply->component_revision_id;
2944 }
2945 } else {
2946 printk(MYIOC_s_ERR_FMT
2947 "%s: smp passthru reply failed to be returned\n",
2948 ioc->name, __func__);
2949 ret = -ENXIO;
2950 }
2951out_free:
2952 if (data_out_dma)
2953 pci_free_consistent(ioc->pcidev, sz, data_out, data_out_dma);
2954put_mf:
2955 if (mf)
2956 mpt_free_msg_frame(ioc, mf);
2957out_unlock:
2958 CLEAR_MGMT_STATUS(ioc->sas_mgmt.status)
2959 mutex_unlock(&ioc->sas_mgmt.mutex);
2960out:
2961 return ret;
2962 }
2963
0c33b27d
CH
2964static void
2965mptsas_parse_device_info(struct sas_identify *identify,
2966 struct mptsas_devinfo *device_info)
2967{
2968 u16 protocols;
2969
2970 identify->sas_address = device_info->sas_address;
2971 identify->phy_identifier = device_info->phy_id;
2972
2973 /*
2974 * Fill in Phy Initiator Port Protocol.
2975 * Bits 6:3, more than one bit can be set, fall through cases.
2976 */
2977 protocols = device_info->device_info & 0x78;
2978 identify->initiator_port_protocols = 0;
2979 if (protocols & MPI_SAS_DEVICE_INFO_SSP_INITIATOR)
2980 identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
2981 if (protocols & MPI_SAS_DEVICE_INFO_STP_INITIATOR)
2982 identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
2983 if (protocols & MPI_SAS_DEVICE_INFO_SMP_INITIATOR)
2984 identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
2985 if (protocols & MPI_SAS_DEVICE_INFO_SATA_HOST)
2986 identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
2987
2988 /*
2989 * Fill in Phy Target Port Protocol.
2990 * Bits 10:7, more than one bit can be set, fall through cases.
2991 */
2992 protocols = device_info->device_info & 0x780;
2993 identify->target_port_protocols = 0;
2994 if (protocols & MPI_SAS_DEVICE_INFO_SSP_TARGET)
2995 identify->target_port_protocols |= SAS_PROTOCOL_SSP;
2996 if (protocols & MPI_SAS_DEVICE_INFO_STP_TARGET)
2997 identify->target_port_protocols |= SAS_PROTOCOL_STP;
2998 if (protocols & MPI_SAS_DEVICE_INFO_SMP_TARGET)
2999 identify->target_port_protocols |= SAS_PROTOCOL_SMP;
3000 if (protocols & MPI_SAS_DEVICE_INFO_SATA_DEVICE)
3001 identify->target_port_protocols |= SAS_PROTOCOL_SATA;
3002
3003 /*
3004 * Fill in Attached device type.
3005 */
3006 switch (device_info->device_info &
3007 MPI_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
3008 case MPI_SAS_DEVICE_INFO_NO_DEVICE:
3009 identify->device_type = SAS_PHY_UNUSED;
3010 break;
3011 case MPI_SAS_DEVICE_INFO_END_DEVICE:
3012 identify->device_type = SAS_END_DEVICE;
3013 break;
3014 case MPI_SAS_DEVICE_INFO_EDGE_EXPANDER:
3015 identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
3016 break;
3017 case MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER:
3018 identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
3019 break;
3020 }
3021}
3022
3023static int mptsas_probe_one_phy(struct device *dev,
ac01bbbd 3024 struct mptsas_phyinfo *phy_info, int index, int local)
0c33b27d 3025{
e6b2d76a 3026 MPT_ADAPTER *ioc;
9a28f49a 3027 struct sas_phy *phy;
547f9a21
EM
3028 struct sas_port *port;
3029 int error = 0;
c9de7dc4 3030 VirtTarget *vtarget;
0c33b27d 3031
547f9a21
EM
3032 if (!dev) {
3033 error = -ENODEV;
3034 goto out;
3035 }
e6b2d76a
ME
3036
3037 if (!phy_info->phy) {
3038 phy = sas_phy_alloc(dev, index);
547f9a21
EM
3039 if (!phy) {
3040 error = -ENOMEM;
3041 goto out;
3042 }
e6b2d76a
ME
3043 } else
3044 phy = phy_info->phy;
0c33b27d 3045
9a28f49a 3046 mptsas_parse_device_info(&phy->identify, &phy_info->identify);
0c33b27d
CH
3047
3048 /*
3049 * Set Negotiated link rate.
3050 */
3051 switch (phy_info->negotiated_link_rate) {
3052 case MPI_SAS_IOUNIT0_RATE_PHY_DISABLED:
9a28f49a 3053 phy->negotiated_linkrate = SAS_PHY_DISABLED;
0c33b27d
CH
3054 break;
3055 case MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION:
9a28f49a 3056 phy->negotiated_linkrate = SAS_LINK_RATE_FAILED;
0c33b27d
CH
3057 break;
3058 case MPI_SAS_IOUNIT0_RATE_1_5:
9a28f49a 3059 phy->negotiated_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
3060 break;
3061 case MPI_SAS_IOUNIT0_RATE_3_0:
9a28f49a 3062 phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
3063 break;
3064 case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
3065 case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
3066 default:
9a28f49a 3067 phy->negotiated_linkrate = SAS_LINK_RATE_UNKNOWN;
0c33b27d
CH
3068 break;
3069 }
3070
3071 /*
3072 * Set Max hardware link rate.
3073 */
3074 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
3075 case MPI_SAS_PHY0_HWRATE_MAX_RATE_1_5:
9a28f49a 3076 phy->maximum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
3077 break;
3078 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
9a28f49a 3079 phy->maximum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
3080 break;
3081 default:
3082 break;
3083 }
3084
3085 /*
3086 * Set Max programmed link rate.
3087 */
3088 switch (phy_info->programmed_link_rate &
3089 MPI_SAS_PHY0_PRATE_MAX_RATE_MASK) {
3090 case MPI_SAS_PHY0_PRATE_MAX_RATE_1_5:
9a28f49a 3091 phy->maximum_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
3092 break;
3093 case MPI_SAS_PHY0_PRATE_MAX_RATE_3_0:
9a28f49a 3094 phy->maximum_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
3095 break;
3096 default:
3097 break;
3098 }
3099
3100 /*
3101 * Set Min hardware link rate.
3102 */
3103 switch (phy_info->hw_link_rate & MPI_SAS_PHY0_HWRATE_MIN_RATE_MASK) {
3104 case MPI_SAS_PHY0_HWRATE_MIN_RATE_1_5:
9a28f49a 3105 phy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
3106 break;
3107 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
9a28f49a 3108 phy->minimum_linkrate_hw = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
3109 break;
3110 default:
3111 break;
3112 }
3113
3114 /*
3115 * Set Min programmed link rate.
3116 */
3117 switch (phy_info->programmed_link_rate &
3118 MPI_SAS_PHY0_PRATE_MIN_RATE_MASK) {
3119 case MPI_SAS_PHY0_PRATE_MIN_RATE_1_5:
9a28f49a 3120 phy->minimum_linkrate = SAS_LINK_RATE_1_5_GBPS;
0c33b27d
CH
3121 break;
3122 case MPI_SAS_PHY0_PRATE_MIN_RATE_3_0:
9a28f49a 3123 phy->minimum_linkrate = SAS_LINK_RATE_3_0_GBPS;
0c33b27d
CH
3124 break;
3125 default:
3126 break;
3127 }
3128
e6b2d76a 3129 if (!phy_info->phy) {
ac01bbbd 3130
e6b2d76a
ME
3131 error = sas_phy_add(phy);
3132 if (error) {
3133 sas_phy_free(phy);
547f9a21 3134 goto out;
e6b2d76a
ME
3135 }
3136 phy_info->phy = phy;
0c33b27d
CH
3137 }
3138
547f9a21
EM
3139 if (!phy_info->attached.handle ||
3140 !phy_info->port_details)
3141 goto out;
3142
3143 port = mptsas_get_port(phy_info);
3144 ioc = phy_to_ioc(phy_info->phy);
3145
3146 if (phy_info->sas_port_add_phy) {
3147
3148 if (!port) {
dc22f16d 3149 port = sas_port_alloc_num(dev);
547f9a21
EM
3150 if (!port) {
3151 error = -ENOMEM;
3152 goto out;
3153 }
3154 error = sas_port_add(port);
3155 if (error) {
d6ecdd63 3156 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21 3157 "%s: exit at line=%d\n", ioc->name,
cadbd4a5 3158 __func__, __LINE__));
547f9a21
EM
3159 goto out;
3160 }
d6ecdd63 3161 mptsas_set_port(ioc, phy_info, port);
2f187862
KD
3162 devtprintk(ioc, dev_printk(KERN_DEBUG, &port->dev,
3163 MYIOC_s_FMT "add port %d, sas_addr (0x%llx)\n",
3164 ioc->name, port->port_identifier,
3165 (unsigned long long)phy_info->
3166 attached.sas_address));
547f9a21 3167 }
2f187862
KD
3168 dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3169 "sas_port_add_phy: phy_id=%d\n",
3170 ioc->name, phy_info->phy_id));
547f9a21
EM
3171 sas_port_add_phy(port, phy_info->phy);
3172 phy_info->sas_port_add_phy = 0;
2f187862
KD
3173 devtprintk(ioc, dev_printk(KERN_DEBUG, &phy_info->phy->dev,
3174 MYIOC_s_FMT "add phy %d, phy-obj (0x%p)\n", ioc->name,
3175 phy_info->phy_id, phy_info->phy));
547f9a21 3176 }
547f9a21 3177 if (!mptsas_get_rphy(phy_info) && port && !port->rphy) {
e6b2d76a 3178
0c33b27d 3179 struct sas_rphy *rphy;
2686de27 3180 struct device *parent;
f013db32 3181 struct sas_identify identify;
0c33b27d 3182
2686de27 3183 parent = dev->parent->parent;
e6b2d76a
ME
3184 /*
3185 * Let the hotplug_work thread handle processing
3186 * the adding/removing of devices that occur
3187 * after start of day.
3188 */
2f187862
KD
3189 if (mptsas_is_end_device(&phy_info->attached) &&
3190 phy_info->attached.handle_parent) {
3191 goto out;
3192 }
e6b2d76a 3193
f013db32 3194 mptsas_parse_device_info(&identify, &phy_info->attached);
2686de27
JB
3195 if (scsi_is_host_device(parent)) {
3196 struct mptsas_portinfo *port_info;
3197 int i;
3198
f9c34022 3199 port_info = ioc->hba_port_info;
2686de27
JB
3200
3201 for (i = 0; i < port_info->num_phys; i++)
3202 if (port_info->phy_info[i].identify.sas_address ==
0c269e6d
JB
3203 identify.sas_address) {
3204 sas_port_mark_backlink(port);
2686de27 3205 goto out;
0c269e6d 3206 }
2686de27
JB
3207
3208 } else if (scsi_is_sas_rphy(parent)) {
3209 struct sas_rphy *parent_rphy = dev_to_rphy(parent);
3210 if (identify.sas_address ==
0c269e6d
JB
3211 parent_rphy->identify.sas_address) {
3212 sas_port_mark_backlink(port);
2686de27 3213 goto out;
0c269e6d 3214 }
2686de27
JB
3215 }
3216
f013db32
JB
3217 switch (identify.device_type) {
3218 case SAS_END_DEVICE:
547f9a21 3219 rphy = sas_end_device_alloc(port);
f013db32
JB
3220 break;
3221 case SAS_EDGE_EXPANDER_DEVICE:
3222 case SAS_FANOUT_EXPANDER_DEVICE:
547f9a21 3223 rphy = sas_expander_alloc(port, identify.device_type);
f013db32
JB
3224 break;
3225 default:
3226 rphy = NULL;
3227 break;
3228 }
547f9a21 3229 if (!rphy) {
d6ecdd63 3230 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21 3231 "%s: exit at line=%d\n", ioc->name,
cadbd4a5 3232 __func__, __LINE__));
547f9a21
EM
3233 goto out;
3234 }
0c33b27d 3235
f013db32 3236 rphy->identify = identify;
0c33b27d
CH
3237 error = sas_rphy_add(rphy);
3238 if (error) {
d6ecdd63 3239 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
547f9a21 3240 "%s: exit at line=%d\n", ioc->name,
cadbd4a5 3241 __func__, __LINE__));
0c33b27d 3242 sas_rphy_free(rphy);
547f9a21 3243 goto out;
0c33b27d 3244 }
d6ecdd63 3245 mptsas_set_rphy(ioc, phy_info, rphy);
e0f553ab
KD
3246 if (identify.device_type == SAS_EDGE_EXPANDER_DEVICE ||
3247 identify.device_type == SAS_FANOUT_EXPANDER_DEVICE)
3248 mptsas_exp_repmanufacture_info(ioc,
3249 identify.sas_address,
3250 rphy_to_expander_device(rphy));
0c33b27d
CH
3251 }
3252
c9de7dc4
KD
3253 /* If the device exists,verify it wasn't previously flagged
3254 as a missing device. If so, clear it */
3255 vtarget = mptsas_find_vtarget(ioc,
3256 phy_info->attached.channel,
3257 phy_info->attached.id);
3258 if (vtarget && vtarget->inDMD) {
3259 printk(KERN_INFO "Device returned, unsetting inDMD\n");
3260 vtarget->inDMD = 0;
3261 }
3262
547f9a21
EM
3263 out:
3264 return error;
0c33b27d
CH
3265}
3266
3267static int
e6b2d76a 3268mptsas_probe_hba_phys(MPT_ADAPTER *ioc)
0c33b27d 3269{
e6b2d76a 3270 struct mptsas_portinfo *port_info, *hba;
0c33b27d
CH
3271 int error = -ENOMEM, i;
3272
f9c34022 3273 hba = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
e6b2d76a 3274 if (! hba)
0c33b27d 3275 goto out;
0c33b27d 3276
e6b2d76a 3277 error = mptsas_sas_io_unit_pg0(ioc, hba);
0c33b27d
CH
3278 if (error)
3279 goto out_free_port_info;
3280
edb9068d 3281 mptsas_sas_io_unit_pg1(ioc);
9a28f49a 3282 mutex_lock(&ioc->sas_topology_mutex);
f9c34022 3283 port_info = ioc->hba_port_info;
e6b2d76a 3284 if (!port_info) {
f9c34022
KD
3285 ioc->hba_port_info = port_info = hba;
3286 ioc->hba_port_num_phy = port_info->num_phys;
e6b2d76a
ME
3287 list_add_tail(&port_info->list, &ioc->sas_topology);
3288 } else {
2ecce492 3289 for (i = 0; i < hba->num_phys; i++) {
e6b2d76a
ME
3290 port_info->phy_info[i].negotiated_link_rate =
3291 hba->phy_info[i].negotiated_link_rate;
2ecce492
EM
3292 port_info->phy_info[i].handle =
3293 hba->phy_info[i].handle;
3294 port_info->phy_info[i].port_id =
3295 hba->phy_info[i].port_id;
3296 }
547f9a21 3297 kfree(hba->phy_info);
e6b2d76a
ME
3298 kfree(hba);
3299 hba = NULL;
3300 }
9a28f49a 3301 mutex_unlock(&ioc->sas_topology_mutex);
f9c34022
KD
3302#if defined(CPQ_CIM)
3303 ioc->num_ports = port_info->num_phys;
3304#endif
0c33b27d
CH
3305 for (i = 0; i < port_info->num_phys; i++) {
3306 mptsas_sas_phy_pg0(ioc, &port_info->phy_info[i],
3307 (MPI_SAS_PHY_PGAD_FORM_PHY_NUMBER <<
3308 MPI_SAS_PHY_PGAD_FORM_SHIFT), i);
f9c34022
KD
3309 port_info->phy_info[i].identify.handle =
3310 port_info->phy_info[i].handle;
0c33b27d 3311 mptsas_sas_device_pg0(ioc, &port_info->phy_info[i].identify,
2ecce492
EM
3312 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
3313 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
f9c34022
KD
3314 port_info->phy_info[i].identify.handle);
3315 if (!ioc->hba_port_sas_addr)
3316 ioc->hba_port_sas_addr =
3317 port_info->phy_info[i].identify.sas_address;
024358ee 3318 port_info->phy_info[i].identify.phy_id =
2ecce492 3319 port_info->phy_info[i].phy_id = i;
547f9a21 3320 if (port_info->phy_info[i].attached.handle)
0c33b27d
CH
3321 mptsas_sas_device_pg0(ioc,
3322 &port_info->phy_info[i].attached,
3323 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
3324 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3325 port_info->phy_info[i].attached.handle);
547f9a21 3326 }
0c33b27d 3327
547f9a21
EM
3328 mptsas_setup_wide_ports(ioc, port_info);
3329
3330 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
0c33b27d 3331 mptsas_probe_one_phy(&ioc->sh->shost_gendev,
e6b2d76a 3332 &port_info->phy_info[i], ioc->sas_index, 1);
0c33b27d
CH
3333
3334 return 0;
3335
3336 out_free_port_info:
547f9a21 3337 kfree(hba);
0c33b27d
CH
3338 out:
3339 return error;
3340}
3341
f9c34022
KD
3342static void
3343mptsas_expander_refresh(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info)
0c33b27d 3344{
f9c34022
KD
3345 struct mptsas_portinfo *parent;
3346 struct device *parent_dev;
3347 struct sas_rphy *rphy;
3348 int i;
3349 u64 sas_address; /* expander sas address */
3350 u32 handle;
9a28f49a 3351
f9c34022
KD
3352 handle = port_info->phy_info[0].handle;
3353 sas_address = port_info->phy_info[0].identify.sas_address;
0c33b27d 3354 for (i = 0; i < port_info->num_phys; i++) {
0c33b27d 3355 mptsas_sas_expander_pg1(ioc, &port_info->phy_info[i],
f9c34022
KD
3356 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE_PHY_NUM <<
3357 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), (i << 16) + handle);
0c33b27d 3358
f9c34022
KD
3359 mptsas_sas_device_pg0(ioc,
3360 &port_info->phy_info[i].identify,
3361 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
3362 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3363 port_info->phy_info[i].identify.handle);
3364 port_info->phy_info[i].identify.phy_id =
3365 port_info->phy_info[i].phy_id;
0c33b27d
CH
3366
3367 if (port_info->phy_info[i].attached.handle) {
3368 mptsas_sas_device_pg0(ioc,
f9c34022
KD
3369 &port_info->phy_info[i].attached,
3370 (MPI_SAS_DEVICE_PGAD_FORM_HANDLE <<
3371 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3372 port_info->phy_info[i].attached.handle);
db9c9174
ME
3373 port_info->phy_info[i].attached.phy_id =
3374 port_info->phy_info[i].phy_id;
0c33b27d 3375 }
547f9a21 3376 }
0c33b27d 3377
f9c34022
KD
3378 mutex_lock(&ioc->sas_topology_mutex);
3379 parent = mptsas_find_portinfo_by_handle(ioc,
3380 port_info->phy_info[0].identify.handle_parent);
3381 if (!parent) {
9a28f49a 3382 mutex_unlock(&ioc->sas_topology_mutex);
f9c34022
KD
3383 return;
3384 }
3385 for (i = 0, parent_dev = NULL; i < parent->num_phys && !parent_dev;
3386 i++) {
3387 if (parent->phy_info[i].attached.sas_address == sas_address) {
3388 rphy = mptsas_get_rphy(&parent->phy_info[i]);
3389 parent_dev = &rphy->dev;
3390 }
547f9a21 3391 }
f9c34022 3392 mutex_unlock(&ioc->sas_topology_mutex);
547f9a21
EM
3393
3394 mptsas_setup_wide_ports(ioc, port_info);
547f9a21 3395 for (i = 0; i < port_info->num_phys; i++, ioc->sas_index++)
f9c34022 3396 mptsas_probe_one_phy(parent_dev, &port_info->phy_info[i],
e6b2d76a 3397 ioc->sas_index, 0);
f9c34022 3398}
0c33b27d 3399
f9c34022
KD
3400static void
3401mptsas_expander_event_add(MPT_ADAPTER *ioc,
3402 MpiEventDataSasExpanderStatusChange_t *expander_data)
3403{
3404 struct mptsas_portinfo *port_info;
3405 int i;
3406 __le64 sas_address;
0c33b27d 3407
f9c34022
KD
3408 port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
3409 if (!port_info)
3410 BUG();
3411 port_info->num_phys = (expander_data->NumPhys) ?
3412 expander_data->NumPhys : 1;
3413 port_info->phy_info = kcalloc(port_info->num_phys,
3414 sizeof(struct mptsas_phyinfo), GFP_KERNEL);
3415 if (!port_info->phy_info)
3416 BUG();
3417 memcpy(&sas_address, &expander_data->SASAddress, sizeof(__le64));
3418 for (i = 0; i < port_info->num_phys; i++) {
3419 port_info->phy_info[i].portinfo = port_info;
3420 port_info->phy_info[i].handle =
3421 le16_to_cpu(expander_data->DevHandle);
3422 port_info->phy_info[i].identify.sas_address =
3423 le64_to_cpu(sas_address);
3424 port_info->phy_info[i].identify.handle_parent =
3425 le16_to_cpu(expander_data->ParentDevHandle);
e6b2d76a 3426 }
f9c34022
KD
3427
3428 mutex_lock(&ioc->sas_topology_mutex);
3429 list_add_tail(&port_info->list, &ioc->sas_topology);
3430 mutex_unlock(&ioc->sas_topology_mutex);
3431
3432 printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
3433 "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3434 (unsigned long long)sas_address);
3435
3436 mptsas_expander_refresh(ioc, port_info);
0c33b27d
CH
3437}
3438
f9c34022
KD
3439/**
3440 * mptsas_delete_expander_siblings - remove siblings attached to expander
3441 * @ioc: Pointer to MPT_ADAPTER structure
3442 * @parent: the parent port_info object
3443 * @expander: the expander port_info object
3444 **/
e6b2d76a 3445static void
f9c34022
KD
3446mptsas_delete_expander_siblings(MPT_ADAPTER *ioc, struct mptsas_portinfo
3447 *parent, struct mptsas_portinfo *expander)
e6b2d76a 3448{
547f9a21 3449 struct mptsas_phyinfo *phy_info;
f9c34022
KD
3450 struct mptsas_portinfo *port_info;
3451 struct sas_rphy *rphy;
e6b2d76a
ME
3452 int i;
3453
f9c34022
KD
3454 phy_info = expander->phy_info;
3455 for (i = 0; i < expander->num_phys; i++, phy_info++) {
3456 rphy = mptsas_get_rphy(phy_info);
3457 if (!rphy)
3458 continue;
3459 if (rphy->identify.device_type == SAS_END_DEVICE)
3460 mptsas_del_end_device(ioc, phy_info);
3461 }
e6b2d76a 3462
f9c34022
KD
3463 phy_info = expander->phy_info;
3464 for (i = 0; i < expander->num_phys; i++, phy_info++) {
3465 rphy = mptsas_get_rphy(phy_info);
3466 if (!rphy)
e6b2d76a 3467 continue;
f9c34022
KD
3468 if (rphy->identify.device_type ==
3469 MPI_SAS_DEVICE_INFO_EDGE_EXPANDER ||
3470 rphy->identify.device_type ==
3471 MPI_SAS_DEVICE_INFO_FANOUT_EXPANDER) {
3472 port_info = mptsas_find_portinfo_by_sas_address(ioc,
3473 rphy->identify.sas_address);
3474 if (!port_info)
3475 continue;
3476 if (port_info == parent) /* backlink rphy */
3477 continue;
3478 /*
3479 Delete this expander even if the expdevpage is exists
3480 because the parent expander is already deleted
3481 */
3482 mptsas_expander_delete(ioc, port_info, 1);
3483 }
3484 }
3485}
e6b2d76a 3486
e6b2d76a 3487
f9c34022
KD
3488/**
3489 * mptsas_expander_delete - remove this expander
3490 * @ioc: Pointer to MPT_ADAPTER structure
3491 * @port_info: expander port_info struct
3492 * @force: Flag to forcefully delete the expander
3493 *
3494 **/
e6b2d76a 3495
f9c34022
KD
3496static void mptsas_expander_delete(MPT_ADAPTER *ioc,
3497 struct mptsas_portinfo *port_info, u8 force)
3498{
e6b2d76a 3499
f9c34022
KD
3500 struct mptsas_portinfo *parent;
3501 int i;
3502 u64 expander_sas_address;
3503 struct mptsas_phyinfo *phy_info;
3504 struct mptsas_portinfo buffer;
3505 struct mptsas_portinfo_details *port_details;
3506 struct sas_port *port;
547f9a21 3507
f9c34022
KD
3508 if (!port_info)
3509 return;
547f9a21 3510
f9c34022
KD
3511 /* see if expander is still there before deleting */
3512 mptsas_sas_expander_pg0(ioc, &buffer,
3513 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
3514 MPI_SAS_EXPAND_PGAD_FORM_SHIFT),
3515 port_info->phy_info[0].identify.handle);
547f9a21 3516
f9c34022 3517 if (buffer.num_phys) {
547f9a21 3518 kfree(buffer.phy_info);
f9c34022
KD
3519 if (!force)
3520 return;
e6b2d76a 3521 }
f9c34022
KD
3522
3523
3524 /*
3525 * Obtain the port_info instance to the parent port
3526 */
3527 port_details = NULL;
3528 expander_sas_address =
3529 port_info->phy_info[0].identify.sas_address;
3530 parent = mptsas_find_portinfo_by_handle(ioc,
3531 port_info->phy_info[0].identify.handle_parent);
3532 mptsas_delete_expander_siblings(ioc, parent, port_info);
3533 if (!parent)
3534 goto out;
3535
3536 /*
3537 * Delete rphys in the parent that point
3538 * to this expander.
3539 */
3540 phy_info = parent->phy_info;
3541 port = NULL;
3542 for (i = 0; i < parent->num_phys; i++, phy_info++) {
3543 if (!phy_info->phy)
3544 continue;
3545 if (phy_info->attached.sas_address !=
3546 expander_sas_address)
3547 continue;
3548 if (!port) {
3549 port = mptsas_get_port(phy_info);
3550 port_details = phy_info->port_details;
3551 }
3552 dev_printk(KERN_DEBUG, &phy_info->phy->dev,
3553 MYIOC_s_FMT "delete phy %d, phy-obj (0x%p)\n", ioc->name,
3554 phy_info->phy_id, phy_info->phy);
3555 sas_port_delete_phy(port, phy_info->phy);
3556 }
3557 if (port) {
3558 dev_printk(KERN_DEBUG, &port->dev,
3559 MYIOC_s_FMT "delete port %d, sas_addr (0x%llx)\n",
3560 ioc->name, port->port_identifier,
3561 (unsigned long long)expander_sas_address);
3562 sas_port_delete(port);
3563 mptsas_port_delete(ioc, port_details);
3564 }
3565 out:
3566
3567 printk(MYIOC_s_INFO_FMT "delete expander: num_phys %d, "
3568 "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3569 (unsigned long long)expander_sas_address);
3570
3571 /*
3572 * free link
3573 */
3574 list_del(&port_info->list);
3575 kfree(port_info->phy_info);
3576 kfree(port_info);
e6b2d76a
ME
3577}
3578
f9c34022
KD
3579
3580/**
3581 * mptsas_send_expander_event - expanders events
3582 * @ioc: Pointer to MPT_ADAPTER structure
3583 * @expander_data: event data
3584 *
3585 *
3586 * This function handles adding, removing, and refreshing
3587 * device handles within the expander objects.
e6b2d76a 3588 */
0c33b27d 3589static void
f9c34022 3590mptsas_send_expander_event(struct fw_event_work *fw_event)
0c33b27d 3591{
f9c34022
KD
3592 MPT_ADAPTER *ioc;
3593 MpiEventDataSasExpanderStatusChange_t *expander_data;
3594 struct mptsas_portinfo *port_info;
3595 __le64 sas_address;
f44e5461 3596 int i;
0c33b27d 3597
f9c34022
KD
3598 ioc = fw_event->ioc;
3599 expander_data = (MpiEventDataSasExpanderStatusChange_t *)
3600 fw_event->event_data;
3601 memcpy(&sas_address, &expander_data->SASAddress, sizeof(__le64));
f44fd181 3602 sas_address = le64_to_cpu(sas_address);
f9c34022
KD
3603 port_info = mptsas_find_portinfo_by_sas_address(ioc, sas_address);
3604
3605 if (expander_data->ReasonCode == MPI_EVENT_SAS_EXP_RC_ADDED) {
3606 if (port_info) {
3607 for (i = 0; i < port_info->num_phys; i++) {
3608 port_info->phy_info[i].portinfo = port_info;
3609 port_info->phy_info[i].handle =
3610 le16_to_cpu(expander_data->DevHandle);
3611 port_info->phy_info[i].identify.sas_address =
3612 le64_to_cpu(sas_address);
3613 port_info->phy_info[i].identify.handle_parent =
3614 le16_to_cpu(expander_data->ParentDevHandle);
3615 }
3616 mptsas_expander_refresh(ioc, port_info);
3617 } else if (!port_info && expander_data->NumPhys)
3618 mptsas_expander_event_add(ioc, expander_data);
3619 } else if (expander_data->ReasonCode ==
3620 MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING)
3621 mptsas_expander_delete(ioc, port_info, 0);
3622
3623 mptsas_free_fw_event(ioc, fw_event);
3624}
3625
3626
3627/**
3628 * mptsas_expander_add -
3629 * @ioc: Pointer to MPT_ADAPTER structure
3630 * @handle:
3631 *
3632 */
3633struct mptsas_portinfo *
3634mptsas_expander_add(MPT_ADAPTER *ioc, u16 handle)
3635{
3636 struct mptsas_portinfo buffer, *port_info;
3637 int i;
3638
3639 if ((mptsas_sas_expander_pg0(ioc, &buffer,
3640 (MPI_SAS_EXPAND_PGAD_FORM_HANDLE <<
3641 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle)))
3642 return NULL;
3643
3644 port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_ATOMIC);
3645 if (!port_info) {
3646 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3647 "%s: exit at line=%d\n", ioc->name,
3648 __func__, __LINE__));
3649 return NULL;
3650 }
3651 port_info->num_phys = buffer.num_phys;
3652 port_info->phy_info = buffer.phy_info;
3653 for (i = 0; i < port_info->num_phys; i++)
3654 port_info->phy_info[i].portinfo = port_info;
3655 mutex_lock(&ioc->sas_topology_mutex);
3656 list_add_tail(&port_info->list, &ioc->sas_topology);
3657 mutex_unlock(&ioc->sas_topology_mutex);
3658 printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
3659 "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3660 (unsigned long long)buffer.phy_info[0].identify.sas_address);
3661 mptsas_expander_refresh(ioc, port_info);
3662 return port_info;
3663}
3664
3665static void
3666mptsas_send_link_status_event(struct fw_event_work *fw_event)
3667{
3668 MPT_ADAPTER *ioc;
3669 MpiEventDataSasPhyLinkStatus_t *link_data;
3670 struct mptsas_portinfo *port_info;
3671 struct mptsas_phyinfo *phy_info = NULL;
3672 __le64 sas_address;
3673 u8 phy_num;
3674 u8 link_rate;
3675
3676 ioc = fw_event->ioc;
3677 link_data = (MpiEventDataSasPhyLinkStatus_t *)fw_event->event_data;
3678
3679 memcpy(&sas_address, &link_data->SASAddress, sizeof(__le64));
3680 sas_address = le64_to_cpu(sas_address);
3681 link_rate = link_data->LinkRates >> 4;
3682 phy_num = link_data->PhyNum;
3683
3684 port_info = mptsas_find_portinfo_by_sas_address(ioc, sas_address);
3685 if (port_info) {
3686 phy_info = &port_info->phy_info[phy_num];
3687 if (phy_info)
3688 phy_info->negotiated_link_rate = link_rate;
3689 }
3690
3691 if (link_rate == MPI_SAS_IOUNIT0_RATE_1_5 ||
3692 link_rate == MPI_SAS_IOUNIT0_RATE_3_0) {
3693
eedf92b9
KD
3694 if (!port_info) {
3695 if (ioc->old_sas_discovery_protocal) {
3696 port_info = mptsas_expander_add(ioc,
3697 le16_to_cpu(link_data->DevHandle));
3698 if (port_info)
3699 goto out;
3700 }
f9c34022 3701 goto out;
eedf92b9 3702 }
f9c34022
KD
3703
3704 if (port_info == ioc->hba_port_info)
3705 mptsas_probe_hba_phys(ioc);
3706 else
3707 mptsas_expander_refresh(ioc, port_info);
3708 } else if (phy_info && phy_info->phy) {
3709 if (link_rate == MPI_SAS_IOUNIT0_RATE_PHY_DISABLED)
3710 phy_info->phy->negotiated_linkrate =
3711 SAS_PHY_DISABLED;
3712 else if (link_rate ==
3713 MPI_SAS_IOUNIT0_RATE_FAILED_SPEED_NEGOTIATION)
3714 phy_info->phy->negotiated_linkrate =
3715 SAS_LINK_RATE_FAILED;
c9de7dc4 3716 else {
f9c34022
KD
3717 phy_info->phy->negotiated_linkrate =
3718 SAS_LINK_RATE_UNKNOWN;
c9de7dc4
KD
3719 if (ioc->device_missing_delay &&
3720 mptsas_is_end_device(&phy_info->attached)) {
3721 struct scsi_device *sdev;
3722 VirtDevice *vdevice;
3723 u8 channel, id;
3724 id = phy_info->attached.id;
3725 channel = phy_info->attached.channel;
3726 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3727 "Link down for fw_id %d:fw_channel %d\n",
3728 ioc->name, phy_info->attached.id,
3729 phy_info->attached.channel));
3730
3731 shost_for_each_device(sdev, ioc->sh) {
3732 vdevice = sdev->hostdata;
3733 if ((vdevice == NULL) ||
3734 (vdevice->vtarget == NULL))
3735 continue;
3736 if ((vdevice->vtarget->tflags &
3737 MPT_TARGET_FLAGS_RAID_COMPONENT ||
3738 vdevice->vtarget->raidVolume))
3739 continue;
3740 if (vdevice->vtarget->id == id &&
3741 vdevice->vtarget->channel ==
3742 channel)
3743 devtprintk(ioc,
3744 printk(MYIOC_s_DEBUG_FMT
3745 "SDEV OUTSTANDING CMDS"
3746 "%d\n", ioc->name,
3747 sdev->device_busy));
3748 }
3749
3750 }
3751 }
f44e5461
ME
3752 }
3753 out:
f9c34022 3754 mptsas_free_fw_event(ioc, fw_event);
e6b2d76a
ME
3755}
3756
eedf92b9
KD
3757static void
3758mptsas_not_responding_devices(MPT_ADAPTER *ioc)
3759{
3760 struct mptsas_portinfo buffer, *port_info;
3761 struct mptsas_device_info *sas_info;
3762 struct mptsas_devinfo sas_device;
3763 u32 handle;
3764 VirtTarget *vtarget = NULL;
3765 struct mptsas_phyinfo *phy_info;
3766 u8 found_expander;
3767 int retval, retry_count;
3768 unsigned long flags;
3769
3770 mpt_findImVolumes(ioc);
3771
3772 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
3773 if (ioc->ioc_reset_in_progress) {
3774 dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3775 "%s: exiting due to a parallel reset \n", ioc->name,
3776 __func__));
3777 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
3778 return;
3779 }
3780 spin_unlock_irqrestore(&ioc->taskmgmt_lock, flags);
3781
3782 /* devices, logical volumes */
3783 mutex_lock(&ioc->sas_device_info_mutex);
3784 redo_device_scan:
3785 list_for_each_entry(sas_info, &ioc->sas_device_info_list, list) {
57e98513
KD
3786 if (sas_info->is_cached)
3787 continue;
a7938b0b
KD
3788 if (!sas_info->is_logical_volume) {
3789 sas_device.handle = 0;
3790 retry_count = 0;
eedf92b9 3791retry_page:
a7938b0b 3792 retval = mptsas_sas_device_pg0(ioc, &sas_device,
eedf92b9
KD
3793 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID
3794 << MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3795 (sas_info->fw.channel << 8) +
3796 sas_info->fw.id);
3797
a7938b0b
KD
3798 if (sas_device.handle)
3799 continue;
3800 if (retval == -EBUSY) {
3801 spin_lock_irqsave(&ioc->taskmgmt_lock, flags);
3802 if (ioc->ioc_reset_in_progress) {
3803 dfailprintk(ioc,
3804 printk(MYIOC_s_DEBUG_FMT
3805 "%s: exiting due to reset\n",
3806 ioc->name, __func__));
3807 spin_unlock_irqrestore
3808 (&ioc->taskmgmt_lock, flags);
3809 mutex_unlock(&ioc->
3810 sas_device_info_mutex);
3811 return;
3812 }
3813 spin_unlock_irqrestore(&ioc->taskmgmt_lock,
3814 flags);
eedf92b9 3815 }
eedf92b9 3816
a7938b0b
KD
3817 if (retval && (retval != -ENODEV)) {
3818 if (retry_count < 10) {
3819 retry_count++;
3820 goto retry_page;
3821 } else {
3822 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
3823 "%s: Config page retry exceeded retry "
3824 "count deleting device 0x%llx\n",
3825 ioc->name, __func__,
3826 sas_info->sas_address));
3827 }
eedf92b9 3828 }
eedf92b9 3829
a7938b0b
KD
3830 /* delete device */
3831 vtarget = mptsas_find_vtarget(ioc,
eedf92b9 3832 sas_info->fw.channel, sas_info->fw.id);
a7938b0b
KD
3833
3834 if (vtarget)
3835 vtarget->deleted = 1;
3836
3837 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
3838 sas_info->sas_address);
3839
3840 if (phy_info) {
3841 mptsas_del_end_device(ioc, phy_info);
3842 goto redo_device_scan;
3843 }
3844 } else
3845 mptsas_volume_delete(ioc, sas_info->fw.id);
eedf92b9 3846 }
129dd981 3847 mutex_unlock(&ioc->sas_device_info_mutex);
eedf92b9
KD
3848
3849 /* expanders */
3850 mutex_lock(&ioc->sas_topology_mutex);
3851 redo_expander_scan:
3852 list_for_each_entry(port_info, &ioc->sas_topology, list) {
3853
3854 if (port_info->phy_info &&
3855 (!(port_info->phy_info[0].identify.device_info &
3856 MPI_SAS_DEVICE_INFO_SMP_TARGET)))
3857 continue;
3858 found_expander = 0;
3859 handle = 0xFFFF;
3860 while (!mptsas_sas_expander_pg0(ioc, &buffer,
3861 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
3862 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle) &&
3863 !found_expander) {
3864
3865 handle = buffer.phy_info[0].handle;
3866 if (buffer.phy_info[0].identify.sas_address ==
3867 port_info->phy_info[0].identify.sas_address) {
3868 found_expander = 1;
3869 }
3870 kfree(buffer.phy_info);
3871 }
3872
3873 if (!found_expander) {
3874 mptsas_expander_delete(ioc, port_info, 0);
3875 goto redo_expander_scan;
3876 }
3877 }
129dd981 3878 mutex_unlock(&ioc->sas_topology_mutex);
eedf92b9
KD
3879}
3880
f9c34022
KD
3881/**
3882 * mptsas_probe_expanders - adding expanders
3883 * @ioc: Pointer to MPT_ADAPTER structure
3884 *
3885 **/
e6b2d76a 3886static void
f9c34022 3887mptsas_probe_expanders(MPT_ADAPTER *ioc)
e6b2d76a 3888{
f9c34022
KD
3889 struct mptsas_portinfo buffer, *port_info;
3890 u32 handle;
3891 int i;
e6b2d76a 3892
f9c34022
KD
3893 handle = 0xFFFF;
3894 while (!mptsas_sas_expander_pg0(ioc, &buffer,
3895 (MPI_SAS_EXPAND_PGAD_FORM_GET_NEXT_HANDLE <<
3896 MPI_SAS_EXPAND_PGAD_FORM_SHIFT), handle)) {
3897
3898 handle = buffer.phy_info[0].handle;
3899 port_info = mptsas_find_portinfo_by_sas_address(ioc,
3900 buffer.phy_info[0].identify.sas_address);
3901
3902 if (port_info) {
3903 /* refreshing handles */
3904 for (i = 0; i < buffer.num_phys; i++) {
3905 port_info->phy_info[i].handle = handle;
3906 port_info->phy_info[i].identify.handle_parent =
3907 buffer.phy_info[0].identify.handle_parent;
3908 }
3909 mptsas_expander_refresh(ioc, port_info);
3910 kfree(buffer.phy_info);
3911 continue;
3912 }
3913
3914 port_info = kzalloc(sizeof(struct mptsas_portinfo), GFP_KERNEL);
3915 if (!port_info) {
3916 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3917 "%s: exit at line=%d\n", ioc->name,
3918 __func__, __LINE__));
3919 return;
3920 }
3921 port_info->num_phys = buffer.num_phys;
3922 port_info->phy_info = buffer.phy_info;
3923 for (i = 0; i < port_info->num_phys; i++)
3924 port_info->phy_info[i].portinfo = port_info;
3925 mutex_lock(&ioc->sas_topology_mutex);
3926 list_add_tail(&port_info->list, &ioc->sas_topology);
3927 mutex_unlock(&ioc->sas_topology_mutex);
3928 printk(MYIOC_s_INFO_FMT "add expander: num_phys %d, "
3929 "sas_addr (0x%llx)\n", ioc->name, port_info->num_phys,
3930 (unsigned long long)buffer.phy_info[0].identify.sas_address);
3931 mptsas_expander_refresh(ioc, port_info);
3932 }
3933}
3934
3935static void
3936mptsas_probe_devices(MPT_ADAPTER *ioc)
3937{
3938 u16 handle;
3939 struct mptsas_devinfo sas_device;
3940 struct mptsas_phyinfo *phy_info;
3941
3942 handle = 0xFFFF;
3943 while (!(mptsas_sas_device_pg0(ioc, &sas_device,
3944 MPI_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
3945
3946 handle = sas_device.handle;
3947
3948 if ((sas_device.device_info &
3949 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
3950 MPI_SAS_DEVICE_INFO_STP_TARGET |
3951 MPI_SAS_DEVICE_INFO_SATA_DEVICE)) == 0)
3952 continue;
3953
51106ab5
KD
3954 /* If there is no FW B_T mapping for this device then continue
3955 * */
3956 if (!(sas_device.flags & MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)
3957 || !(sas_device.flags &
3958 MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED))
3959 continue;
3960
f9c34022
KD
3961 phy_info = mptsas_refreshing_device_handles(ioc, &sas_device);
3962 if (!phy_info)
3963 continue;
3964
3965 if (mptsas_get_rphy(phy_info))
3966 continue;
3967
3968 mptsas_add_end_device(ioc, phy_info);
3969 }
547f9a21
EM
3970}
3971
2f187862
KD
3972/**
3973 * mptsas_scan_sas_topology -
3974 * @ioc: Pointer to MPT_ADAPTER structure
3975 * @sas_address:
3976 *
3977 **/
547f9a21 3978static void
f9c34022 3979mptsas_scan_sas_topology(MPT_ADAPTER *ioc)
547f9a21 3980{
f9c34022
KD
3981 struct scsi_device *sdev;
3982 int i;
547f9a21 3983
f9c34022
KD
3984 mptsas_probe_hba_phys(ioc);
3985 mptsas_probe_expanders(ioc);
3986 mptsas_probe_devices(ioc);
0c33b27d 3987
f9c34022
KD
3988 /*
3989 Reporting RAID volumes.
3990 */
3991 if (!ioc->ir_firmware || !ioc->raid_data.pIocPg2 ||
3992 !ioc->raid_data.pIocPg2->NumActiveVolumes)
3993 return;
3994 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
3995 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
3996 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
3997 if (sdev) {
3998 scsi_device_put(sdev);
3999 continue;
4000 }
4001 printk(MYIOC_s_INFO_FMT "attaching raid volume, channel %d, "
4002 "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
4003 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID);
4004 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
4005 ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID, 0);
4006 }
4007}
3eb0822c 4008
57e98513
KD
4009
4010static void
4011mptsas_handle_queue_full_event(struct fw_event_work *fw_event)
4012{
4013 MPT_ADAPTER *ioc;
4014 EventDataQueueFull_t *qfull_data;
4015 struct mptsas_device_info *sas_info;
4016 struct scsi_device *sdev;
4017 int depth;
4018 int id = -1;
4019 int channel = -1;
4020 int fw_id, fw_channel;
4021 u16 current_depth;
4022
4023
4024 ioc = fw_event->ioc;
4025 qfull_data = (EventDataQueueFull_t *)fw_event->event_data;
4026 fw_id = qfull_data->TargetID;
4027 fw_channel = qfull_data->Bus;
4028 current_depth = le16_to_cpu(qfull_data->CurrentDepth);
4029
4030 /* if hidden raid component, look for the volume id */
4031 mutex_lock(&ioc->sas_device_info_mutex);
4032 if (mptscsih_is_phys_disk(ioc, fw_channel, fw_id)) {
4033 list_for_each_entry(sas_info, &ioc->sas_device_info_list,
4034 list) {
4035 if (sas_info->is_cached ||
4036 sas_info->is_logical_volume)
4037 continue;
4038 if (sas_info->is_hidden_raid_component &&
4039 (sas_info->fw.channel == fw_channel &&
4040 sas_info->fw.id == fw_id)) {
4041 id = sas_info->volume_id;
4042 channel = MPTSAS_RAID_CHANNEL;
4043 goto out;
4044 }
4045 }
4046 } else {
4047 list_for_each_entry(sas_info, &ioc->sas_device_info_list,
4048 list) {
4049 if (sas_info->is_cached ||
4050 sas_info->is_hidden_raid_component ||
4051 sas_info->is_logical_volume)
4052 continue;
4053 if (sas_info->fw.channel == fw_channel &&
4054 sas_info->fw.id == fw_id) {
4055 id = sas_info->os.id;
4056 channel = sas_info->os.channel;
4057 goto out;
4058 }
4059 }
4060
4061 }
4062
4063 out:
4064 mutex_unlock(&ioc->sas_device_info_mutex);
4065
4066 if (id != -1) {
4067 shost_for_each_device(sdev, ioc->sh) {
4068 if (sdev->id == id && sdev->channel == channel) {
4069 if (current_depth > sdev->queue_depth) {
4070 sdev_printk(KERN_INFO, sdev,
4071 "strange observation, the queue "
4072 "depth is (%d) meanwhile fw queue "
4073 "depth (%d)\n", sdev->queue_depth,
4074 current_depth);
4075 continue;
4076 }
4077 depth = scsi_track_queue_full(sdev,
4078 current_depth - 1);
4079 if (depth > 0)
4080 sdev_printk(KERN_INFO, sdev,
4081 "Queue depth reduced to (%d)\n",
4082 depth);
4083 else if (depth < 0)
4084 sdev_printk(KERN_INFO, sdev,
4085 "Tagged Command Queueing is being "
4086 "disabled\n");
4087 else if (depth == 0)
4088 sdev_printk(KERN_INFO, sdev,
4089 "Queue depth not changed yet\n");
4090 }
4091 }
4092 }
4093
4094 mptsas_free_fw_event(ioc, fw_event);
4095}
4096
4097
9a28f49a 4098static struct mptsas_phyinfo *
547f9a21 4099mptsas_find_phyinfo_by_sas_address(MPT_ADAPTER *ioc, u64 sas_address)
9a28f49a
CH
4100{
4101 struct mptsas_portinfo *port_info;
9a28f49a 4102 struct mptsas_phyinfo *phy_info = NULL;
547f9a21 4103 int i;
9a28f49a 4104
9a28f49a
CH
4105 mutex_lock(&ioc->sas_topology_mutex);
4106 list_for_each_entry(port_info, &ioc->sas_topology, list) {
4107 for (i = 0; i < port_info->num_phys; i++) {
b506ade9
EM
4108 if (!mptsas_is_end_device(
4109 &port_info->phy_info[i].attached))
4110 continue;
547f9a21
EM
4111 if (port_info->phy_info[i].attached.sas_address
4112 != sas_address)
4113 continue;
b506ade9
EM
4114 phy_info = &port_info->phy_info[i];
4115 break;
4116 }
4117 }
4118 mutex_unlock(&ioc->sas_topology_mutex);
4119 return phy_info;
4120}
4121
a7938b0b
KD
4122/**
4123 * mptsas_find_phyinfo_by_phys_disk_num -
4124 * @ioc: Pointer to MPT_ADAPTER structure
4125 * @phys_disk_num:
4126 * @channel:
4127 * @id:
4128 *
4129 **/
9a28f49a 4130static struct mptsas_phyinfo *
a7938b0b
KD
4131mptsas_find_phyinfo_by_phys_disk_num(MPT_ADAPTER *ioc, u8 phys_disk_num,
4132 u8 channel, u8 id)
9a28f49a 4133{
9a28f49a 4134 struct mptsas_phyinfo *phy_info = NULL;
a7938b0b
KD
4135 struct mptsas_portinfo *port_info;
4136 RaidPhysDiskPage1_t *phys_disk = NULL;
4137 int num_paths;
4138 u64 sas_address = 0;
9a28f49a
CH
4139 int i;
4140
a7938b0b
KD
4141 phy_info = NULL;
4142 if (!ioc->raid_data.pIocPg3)
4143 return NULL;
4144 /* dual port support */
4145 num_paths = mpt_raid_phys_disk_get_num_paths(ioc, phys_disk_num);
4146 if (!num_paths)
4147 goto out;
4148 phys_disk = kzalloc(offsetof(RaidPhysDiskPage1_t, Path) +
4149 (num_paths * sizeof(RAID_PHYS_DISK1_PATH)), GFP_KERNEL);
4150 if (!phys_disk)
4151 goto out;
4152 mpt_raid_phys_disk_pg1(ioc, phys_disk_num, phys_disk);
4153 for (i = 0; i < num_paths; i++) {
4154 if ((phys_disk->Path[i].Flags & 1) != 0)
4155 /* entry no longer valid */
4156 continue;
4157 if ((id == phys_disk->Path[i].PhysDiskID) &&
4158 (channel == phys_disk->Path[i].PhysDiskBus)) {
4159 memcpy(&sas_address, &phys_disk->Path[i].WWID,
4160 sizeof(u64));
4161 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
4162 sas_address);
4163 goto out;
4164 }
4165 }
4166
4167 out:
4168 kfree(phys_disk);
4169 if (phy_info)
4170 return phy_info;
4171
4172 /*
4173 * Extra code to handle RAID0 case, where the sas_address is not updated
4174 * in phys_disk_page_1 when hotswapped
4175 */
9a28f49a
CH
4176 mutex_lock(&ioc->sas_topology_mutex);
4177 list_for_each_entry(port_info, &ioc->sas_topology, list) {
a7938b0b 4178 for (i = 0; i < port_info->num_phys && !phy_info; i++) {
547f9a21
EM
4179 if (!mptsas_is_end_device(
4180 &port_info->phy_info[i].attached))
4181 continue;
b506ade9
EM
4182 if (port_info->phy_info[i].attached.phys_disk_num == ~0)
4183 continue;
a7938b0b
KD
4184 if ((port_info->phy_info[i].attached.phys_disk_num ==
4185 phys_disk_num) &&
4186 (port_info->phy_info[i].attached.id == id) &&
4187 (port_info->phy_info[i].attached.channel ==
4188 channel))
4189 phy_info = &port_info->phy_info[i];
547f9a21 4190 }
9a28f49a
CH
4191 }
4192 mutex_unlock(&ioc->sas_topology_mutex);
9a28f49a
CH
4193 return phy_info;
4194}
4195
f44e5461
ME
4196static void
4197mptsas_reprobe_lun(struct scsi_device *sdev, void *data)
4198{
f99be43b
EM
4199 int rc;
4200
f44e5461 4201 sdev->no_uld_attach = data ? 1 : 0;
f99be43b 4202 rc = scsi_device_reprobe(sdev);
f44e5461
ME
4203}
4204
4205static void
4206mptsas_reprobe_target(struct scsi_target *starget, int uld_attach)
4207{
4208 starget_for_each_device(starget, uld_attach ? (void *)1 : NULL,
4209 mptsas_reprobe_lun);
4210}
4211
b506ade9
EM
4212static void
4213mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id)
4214{
4215 CONFIGPARMS cfg;
4216 ConfigPageHeader_t hdr;
4217 dma_addr_t dma_handle;
4218 pRaidVolumePage0_t buffer = NULL;
4219 RaidPhysDiskPage0_t phys_disk;
4220 int i;
3eb0822c
KD
4221 struct mptsas_phyinfo *phy_info;
4222 struct mptsas_devinfo sas_device;
b506ade9
EM
4223
4224 memset(&cfg, 0 , sizeof(CONFIGPARMS));
4225 memset(&hdr, 0 , sizeof(ConfigPageHeader_t));
4226 hdr.PageType = MPI_CONFIG_PAGETYPE_RAID_VOLUME;
4227 cfg.pageAddr = (channel << 8) + id;
4228 cfg.cfghdr.hdr = &hdr;
4229 cfg.action = MPI_CONFIG_ACTION_PAGE_HEADER;
568da769 4230 cfg.timeout = SAS_CONFIG_PAGE_TIMEOUT;
b506ade9
EM
4231
4232 if (mpt_config(ioc, &cfg) != 0)
4233 goto out;
4234
4235 if (!hdr.PageLength)
4236 goto out;
4237
4238 buffer = pci_alloc_consistent(ioc->pcidev, hdr.PageLength * 4,
4239 &dma_handle);
4240
4241 if (!buffer)
4242 goto out;
4243
4244 cfg.physAddr = dma_handle;
4245 cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
4246
4247 if (mpt_config(ioc, &cfg) != 0)
4248 goto out;
4249
4250 if (!(buffer->VolumeStatus.Flags &
4251 MPI_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE))
4252 goto out;
4253
4254 if (!buffer->NumPhysDisks)
4255 goto out;
4256
4257 for (i = 0; i < buffer->NumPhysDisks; i++) {
4258
4259 if (mpt_raid_phys_disk_pg0(ioc,
4260 buffer->PhysDisk[i].PhysDiskNum, &phys_disk) != 0)
4261 continue;
4262
3eb0822c
KD
4263 if (mptsas_sas_device_pg0(ioc, &sas_device,
4264 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
4265 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
4266 (phys_disk.PhysDiskBus << 8) +
4267 phys_disk.PhysDiskID))
4268 continue;
b506ade9 4269
51106ab5
KD
4270 /* If there is no FW B_T mapping for this device then continue
4271 * */
4272 if (!(sas_device.flags & MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)
4273 || !(sas_device.flags &
4274 MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED))
4275 continue;
4276
4277
3eb0822c
KD
4278 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
4279 sas_device.sas_address);
4280 mptsas_add_end_device(ioc, phy_info);
b506ade9
EM
4281 }
4282
4283 out:
4284 if (buffer)
4285 pci_free_consistent(ioc->pcidev, hdr.PageLength * 4, buffer,
4286 dma_handle);
4287}
e6b2d76a
ME
4288/*
4289 * Work queue thread to handle SAS hotplug events
4290 */
9a28f49a 4291static void
3eb0822c
KD
4292mptsas_hotplug_work(MPT_ADAPTER *ioc, struct fw_event_work *fw_event,
4293 struct mptsas_hotplug_event *hot_plug_info)
9a28f49a 4294{
9a28f49a 4295 struct mptsas_phyinfo *phy_info;
547f9a21 4296 struct scsi_target * starget;
c73787ee 4297 struct mptsas_devinfo sas_device;
f44e5461 4298 VirtTarget *vtarget;
3eb0822c 4299 int i;
cc7e9f5f 4300 struct mptsas_portinfo *port_info;
9a28f49a 4301
3eb0822c 4302 switch (hot_plug_info->event_type) {
9a28f49a 4303
3eb0822c
KD
4304 case MPTSAS_ADD_PHYSDISK:
4305
4306 if (!ioc->raid_data.pIocPg2)
4307 break;
4308
4309 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) {
4310 if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID ==
4311 hot_plug_info->id) {
4312 printk(MYIOC_s_WARN_FMT "firmware bug: unable "
4313 "to add hidden disk - target_id matchs "
4314 "volume_id\n", ioc->name);
4315 mptsas_free_fw_event(ioc, fw_event);
4316 return;
4317 }
b506ade9 4318 }
3eb0822c 4319 mpt_findImVolumes(ioc);
b506ade9 4320
3eb0822c
KD
4321 case MPTSAS_ADD_DEVICE:
4322 memset(&sas_device, 0, sizeof(struct mptsas_devinfo));
4323 mptsas_sas_device_pg0(ioc, &sas_device,
4324 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
4325 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
4326 (hot_plug_info->channel << 8) +
4327 hot_plug_info->id);
4328
51106ab5
KD
4329 /* If there is no FW B_T mapping for this device then break
4330 * */
4331 if (!(sas_device.flags & MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)
4332 || !(sas_device.flags &
4333 MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED))
4334 break;
4335
3eb0822c
KD
4336 if (!sas_device.handle)
4337 return;
4338
4339 phy_info = mptsas_refreshing_device_handles(ioc, &sas_device);
cc7e9f5f
KD
4340 /* Only For SATA Device ADD */
4341 if (!phy_info && (sas_device.device_info &
4342 MPI_SAS_DEVICE_INFO_SATA_DEVICE)) {
4343 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4344 "%s %d SATA HOT PLUG: "
4345 "parent handle of device %x\n", ioc->name,
4346 __func__, __LINE__, sas_device.handle_parent));
4347 port_info = mptsas_find_portinfo_by_handle(ioc,
4348 sas_device.handle_parent);
4349
4350 if (port_info == ioc->hba_port_info)
4351 mptsas_probe_hba_phys(ioc);
4352 else if (port_info)
4353 mptsas_expander_refresh(ioc, port_info);
4354 else {
4355 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4356 "%s %d port info is NULL\n",
4357 ioc->name, __func__, __LINE__));
4358 break;
4359 }
4360 phy_info = mptsas_refreshing_device_handles
4361 (ioc, &sas_device);
4362 }
4363
4364 if (!phy_info) {
4365 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4366 "%s %d phy info is NULL\n",
4367 ioc->name, __func__, __LINE__));
3eb0822c 4368 break;
cc7e9f5f 4369 }
e6b2d76a 4370
3eb0822c
KD
4371 if (mptsas_get_rphy(phy_info))
4372 break;
4373
4374 mptsas_add_end_device(ioc, phy_info);
4375 break;
4376
4377 case MPTSAS_DEL_DEVICE:
4378 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
4379 hot_plug_info->sas_address);
4380 mptsas_del_end_device(ioc, phy_info);
4381 break;
4382
4383 case MPTSAS_DEL_PHYSDISK:
4384
4385 mpt_findImVolumes(ioc);
4386
4387 phy_info = mptsas_find_phyinfo_by_phys_disk_num(
a7938b0b
KD
4388 ioc, hot_plug_info->phys_disk_num,
4389 hot_plug_info->channel,
4390 hot_plug_info->id);
3eb0822c
KD
4391 mptsas_del_end_device(ioc, phy_info);
4392 break;
4393
4394 case MPTSAS_ADD_PHYSDISK_REPROBE:
4395
4396 if (mptsas_sas_device_pg0(ioc, &sas_device,
4397 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
4398 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
4399 (hot_plug_info->channel << 8) + hot_plug_info->id)) {
d6ecdd63 4400 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
4401 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4402 __func__, hot_plug_info->id, __LINE__));
b506ade9
EM
4403 break;
4404 }
3eb0822c 4405
51106ab5
KD
4406 /* If there is no FW B_T mapping for this device then break
4407 * */
4408 if (!(sas_device.flags & MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)
4409 || !(sas_device.flags &
4410 MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED))
4411 break;
4412
3eb0822c
KD
4413 phy_info = mptsas_find_phyinfo_by_sas_address(
4414 ioc, sas_device.sas_address);
4415
4416 if (!phy_info) {
d6ecdd63 4417 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
4418 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4419 __func__, hot_plug_info->id, __LINE__));
9a28f49a 4420 break;
547f9a21 4421 }
3eb0822c
KD
4422
4423 starget = mptsas_get_starget(phy_info);
4424 if (!starget) {
d6ecdd63 4425 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
4426 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4427 __func__, hot_plug_info->id, __LINE__));
547f9a21
EM
4428 break;
4429 }
b506ade9 4430
3eb0822c
KD
4431 vtarget = starget->hostdata;
4432 if (!vtarget) {
d6ecdd63 4433 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
4434 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4435 __func__, hot_plug_info->id, __LINE__));
f44e5461 4436 break;
547f9a21
EM
4437 }
4438
3eb0822c 4439 mpt_findImVolumes(ioc);
547f9a21 4440
3eb0822c
KD
4441 starget_printk(KERN_INFO, starget, MYIOC_s_FMT "RAID Hidding: "
4442 "fw_channel=%d, fw_id=%d, physdsk %d, sas_addr 0x%llx\n",
4443 ioc->name, hot_plug_info->channel, hot_plug_info->id,
4444 hot_plug_info->phys_disk_num, (unsigned long long)
4445 sas_device.sas_address);
9a28f49a 4446
3eb0822c
KD
4447 vtarget->id = hot_plug_info->phys_disk_num;
4448 vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
4449 phy_info->attached.phys_disk_num = hot_plug_info->phys_disk_num;
4450 mptsas_reprobe_target(starget, 1);
9a28f49a 4451 break;
c73787ee 4452
3eb0822c 4453 case MPTSAS_DEL_PHYSDISK_REPROBE:
bd23e94c 4454
e3094447
CH
4455 if (mptsas_sas_device_pg0(ioc, &sas_device,
4456 (MPI_SAS_DEVICE_PGAD_FORM_BUS_TARGET_ID <<
b506ade9 4457 MPI_SAS_DEVICE_PGAD_FORM_SHIFT),
3eb0822c 4458 (hot_plug_info->channel << 8) + hot_plug_info->id)) {
d6ecdd63 4459 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
4460 "%s: fw_id=%d exit at line=%d\n",
4461 ioc->name, __func__,
4462 hot_plug_info->id, __LINE__));
e3094447 4463 break;
547f9a21 4464 }
9a28f49a 4465
51106ab5
KD
4466 /* If there is no FW B_T mapping for this device then break
4467 * */
4468 if (!(sas_device.flags & MPI_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)
4469 || !(sas_device.flags &
4470 MPI_SAS_DEVICE0_FLAGS_DEVICE_MAPPED))
4471 break;
4472
547f9a21
EM
4473 phy_info = mptsas_find_phyinfo_by_sas_address(ioc,
4474 sas_device.sas_address);
3eb0822c 4475 if (!phy_info) {
d6ecdd63 4476 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
4477 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4478 __func__, hot_plug_info->id, __LINE__));
547f9a21 4479 break;
e6b2d76a
ME
4480 }
4481
547f9a21 4482 starget = mptsas_get_starget(phy_info);
3eb0822c
KD
4483 if (!starget) {
4484 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
4485 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4486 __func__, hot_plug_info->id, __LINE__));
9a28f49a
CH
4487 break;
4488 }
4489
3eb0822c
KD
4490 vtarget = starget->hostdata;
4491 if (!vtarget) {
d6ecdd63 4492 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
4493 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4494 __func__, hot_plug_info->id, __LINE__));
f44e5461 4495 break;
547f9a21 4496 }
b506ade9 4497
3eb0822c 4498 if (!(vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)) {
d6ecdd63 4499 dfailprintk(ioc, printk(MYIOC_s_ERR_FMT
3eb0822c
KD
4500 "%s: fw_id=%d exit at line=%d\n", ioc->name,
4501 __func__, hot_plug_info->id, __LINE__));
547f9a21
EM
4502 break;
4503 }
c73787ee 4504
3eb0822c 4505 mpt_findImVolumes(ioc);
9a28f49a 4506
3eb0822c
KD
4507 starget_printk(KERN_INFO, starget, MYIOC_s_FMT "RAID Exposing:"
4508 " fw_channel=%d, fw_id=%d, physdsk %d, sas_addr 0x%llx\n",
4509 ioc->name, hot_plug_info->channel, hot_plug_info->id,
4510 hot_plug_info->phys_disk_num, (unsigned long long)
4511 sas_device.sas_address);
4512
4513 vtarget->tflags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
4514 vtarget->id = hot_plug_info->id;
4515 phy_info->attached.phys_disk_num = ~0;
4516 mptsas_reprobe_target(starget, 0);
4517 mptsas_add_device_component_by_fw(ioc,
4518 hot_plug_info->channel, hot_plug_info->id);
9a28f49a 4519 break;
3eb0822c 4520
c73787ee 4521 case MPTSAS_ADD_RAID:
3eb0822c 4522
c73787ee 4523 mpt_findImVolumes(ioc);
3eb0822c
KD
4524 printk(MYIOC_s_INFO_FMT "attaching raid volume, channel %d, "
4525 "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
4526 hot_plug_info->id);
4527 scsi_add_device(ioc->sh, MPTSAS_RAID_CHANNEL,
4528 hot_plug_info->id, 0);
c73787ee 4529 break;
3eb0822c 4530
c73787ee 4531 case MPTSAS_DEL_RAID:
3eb0822c 4532
c73787ee 4533 mpt_findImVolumes(ioc);
3eb0822c
KD
4534 printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, "
4535 "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL,
4536 hot_plug_info->id);
4537 scsi_remove_device(hot_plug_info->sdev);
4538 scsi_device_put(hot_plug_info->sdev);
c73787ee 4539 break;
3eb0822c 4540
b506ade9 4541 case MPTSAS_ADD_INACTIVE_VOLUME:
3eb0822c
KD
4542
4543 mpt_findImVolumes(ioc);
b506ade9 4544 mptsas_adding_inactive_raid_components(ioc,
3eb0822c 4545 hot_plug_info->channel, hot_plug_info->id);
b506ade9 4546 break;
3eb0822c 4547
bd23e94c
ME
4548 default:
4549 break;
9a28f49a
CH
4550 }
4551
3eb0822c 4552 mptsas_free_fw_event(ioc, fw_event);
9a28f49a
CH
4553}
4554
4555static void
3eb0822c 4556mptsas_send_sas_event(struct fw_event_work *fw_event)
9a28f49a 4557{
3eb0822c
KD
4558 MPT_ADAPTER *ioc;
4559 struct mptsas_hotplug_event hot_plug_info;
4560 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data;
4561 u32 device_info;
4562 u64 sas_address;
4563
4564 ioc = fw_event->ioc;
4565 sas_event_data = (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)
4566 fw_event->event_data;
4567 device_info = le32_to_cpu(sas_event_data->DeviceInfo);
9a28f49a
CH
4568
4569 if ((device_info &
3eb0822c
KD
4570 (MPI_SAS_DEVICE_INFO_SSP_TARGET |
4571 MPI_SAS_DEVICE_INFO_STP_TARGET |
4572 MPI_SAS_DEVICE_INFO_SATA_DEVICE)) == 0) {
4573 mptsas_free_fw_event(ioc, fw_event);
9a28f49a 4574 return;
3eb0822c
KD
4575 }
4576
4577 if (sas_event_data->ReasonCode ==
4578 MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED) {
4579 mptbase_sas_persist_operation(ioc,
4580 MPI_SAS_OP_CLEAR_NOT_PRESENT);
4581 mptsas_free_fw_event(ioc, fw_event);
4582 return;
4583 }
9a28f49a 4584
4b766471 4585 switch (sas_event_data->ReasonCode) {
4b766471 4586 case MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING:
df9e062a 4587 case MPI_EVENT_SAS_DEV_STAT_RC_ADDED:
3eb0822c
KD
4588 memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
4589 hot_plug_info.handle = le16_to_cpu(sas_event_data->DevHandle);
4590 hot_plug_info.channel = sas_event_data->Bus;
4591 hot_plug_info.id = sas_event_data->TargetID;
4592 hot_plug_info.phy_id = sas_event_data->PhyNum;
4b766471 4593 memcpy(&sas_address, &sas_event_data->SASAddress,
3eb0822c
KD
4594 sizeof(u64));
4595 hot_plug_info.sas_address = le64_to_cpu(sas_address);
4596 hot_plug_info.device_info = device_info;
4b766471
ME
4597 if (sas_event_data->ReasonCode &
4598 MPI_EVENT_SAS_DEV_STAT_RC_ADDED)
3eb0822c 4599 hot_plug_info.event_type = MPTSAS_ADD_DEVICE;
4b766471 4600 else
3eb0822c
KD
4601 hot_plug_info.event_type = MPTSAS_DEL_DEVICE;
4602 mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
4b766471 4603 break;
3eb0822c 4604
4b766471 4605 case MPI_EVENT_SAS_DEV_STAT_RC_NO_PERSIST_ADDED:
3eb0822c
KD
4606 mptbase_sas_persist_operation(ioc,
4607 MPI_SAS_OP_CLEAR_NOT_PRESENT);
4608 mptsas_free_fw_event(ioc, fw_event);
4b766471 4609 break;
3eb0822c 4610
4b766471 4611 case MPI_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
3eb0822c 4612 /* TODO */
4b766471 4613 case MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
3eb0822c 4614 /* TODO */
4b766471 4615 default:
3eb0822c 4616 mptsas_free_fw_event(ioc, fw_event);
4b766471 4617 break;
9a28f49a 4618 }
9a28f49a 4619}
3eb0822c 4620
c73787ee 4621static void
3eb0822c 4622mptsas_send_raid_event(struct fw_event_work *fw_event)
c73787ee 4623{
3eb0822c
KD
4624 MPT_ADAPTER *ioc;
4625 EVENT_DATA_RAID *raid_event_data;
4626 struct mptsas_hotplug_event hot_plug_info;
4627 int status;
4628 int state;
4629 struct scsi_device *sdev = NULL;
4630 VirtDevice *vdevice = NULL;
4631 RaidPhysDiskPage0_t phys_disk;
4632
4633 ioc = fw_event->ioc;
4634 raid_event_data = (EVENT_DATA_RAID *)fw_event->event_data;
4635 status = le32_to_cpu(raid_event_data->SettingsStatus);
4636 state = (status >> 8) & 0xff;
4637
4638 memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
4639 hot_plug_info.id = raid_event_data->VolumeID;
4640 hot_plug_info.channel = raid_event_data->VolumeBus;
4641 hot_plug_info.phys_disk_num = raid_event_data->PhysDiskNum;
4642
4643 if (raid_event_data->ReasonCode == MPI_EVENT_RAID_RC_VOLUME_DELETED ||
4644 raid_event_data->ReasonCode == MPI_EVENT_RAID_RC_VOLUME_CREATED ||
4645 raid_event_data->ReasonCode ==
4646 MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED) {
4647 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL,
4648 hot_plug_info.id, 0);
4649 hot_plug_info.sdev = sdev;
4650 if (sdev)
4651 vdevice = sdev->hostdata;
c73787ee
ME
4652 }
4653
3eb0822c
KD
4654 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Entering %s: "
4655 "ReasonCode=%02x\n", ioc->name, __func__,
4656 raid_event_data->ReasonCode));
c73787ee
ME
4657
4658 switch (raid_event_data->ReasonCode) {
4659 case MPI_EVENT_RAID_RC_PHYSDISK_DELETED:
3eb0822c 4660 hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK_REPROBE;
c73787ee
ME
4661 break;
4662 case MPI_EVENT_RAID_RC_PHYSDISK_CREATED:
3eb0822c 4663 hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK_REPROBE;
c73787ee 4664 break;
bd23e94c
ME
4665 case MPI_EVENT_RAID_RC_PHYSDISK_STATUS_CHANGED:
4666 switch (state) {
4667 case MPI_PD_STATE_ONLINE:
b506ade9 4668 case MPI_PD_STATE_NOT_COMPATIBLE:
3eb0822c
KD
4669 mpt_raid_phys_disk_pg0(ioc,
4670 raid_event_data->PhysDiskNum, &phys_disk);
4671 hot_plug_info.id = phys_disk.PhysDiskID;
4672 hot_plug_info.channel = phys_disk.PhysDiskBus;
4673 hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK;
bd23e94c 4674 break;
3eb0822c 4675 case MPI_PD_STATE_FAILED:
bd23e94c 4676 case MPI_PD_STATE_MISSING:
bd23e94c
ME
4677 case MPI_PD_STATE_OFFLINE_AT_HOST_REQUEST:
4678 case MPI_PD_STATE_FAILED_AT_HOST_REQUEST:
4679 case MPI_PD_STATE_OFFLINE_FOR_ANOTHER_REASON:
3eb0822c 4680 hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK;
bd23e94c
ME
4681 break;
4682 default:
4683 break;
4684 }
4685 break;
c73787ee 4686 case MPI_EVENT_RAID_RC_VOLUME_DELETED:
3eb0822c
KD
4687 if (!sdev)
4688 break;
4689 vdevice->vtarget->deleted = 1; /* block IO */
4690 hot_plug_info.event_type = MPTSAS_DEL_RAID;
c73787ee
ME
4691 break;
4692 case MPI_EVENT_RAID_RC_VOLUME_CREATED:
3eb0822c
KD
4693 if (sdev) {
4694 scsi_device_put(sdev);
4695 break;
4696 }
4697 hot_plug_info.event_type = MPTSAS_ADD_RAID;
c73787ee
ME
4698 break;
4699 case MPI_EVENT_RAID_RC_VOLUME_STATUS_CHANGED:
3eb0822c
KD
4700 if (!(status & MPI_RAIDVOL0_STATUS_FLAG_ENABLED)) {
4701 if (!sdev)
4702 break;
4703 vdevice->vtarget->deleted = 1; /* block IO */
4704 hot_plug_info.event_type = MPTSAS_DEL_RAID;
4705 break;
4706 }
bd23e94c
ME
4707 switch (state) {
4708 case MPI_RAIDVOL0_STATUS_STATE_FAILED:
4709 case MPI_RAIDVOL0_STATUS_STATE_MISSING:
3eb0822c
KD
4710 if (!sdev)
4711 break;
4712 vdevice->vtarget->deleted = 1; /* block IO */
4713 hot_plug_info.event_type = MPTSAS_DEL_RAID;
bd23e94c
ME
4714 break;
4715 case MPI_RAIDVOL0_STATUS_STATE_OPTIMAL:
4716 case MPI_RAIDVOL0_STATUS_STATE_DEGRADED:
3eb0822c
KD
4717 if (sdev) {
4718 scsi_device_put(sdev);
4719 break;
4720 }
4721 hot_plug_info.event_type = MPTSAS_ADD_RAID;
bd23e94c
ME
4722 break;
4723 default:
4724 break;
4725 }
c73787ee
ME
4726 break;
4727 default:
4728 break;
4729 }
3eb0822c
KD
4730
4731 if (hot_plug_info.event_type != MPTSAS_IGNORE_EVENT)
4732 mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
4733 else
4734 mptsas_free_fw_event(ioc, fw_event);
c73787ee
ME
4735}
4736
db7051b2
KD
4737/**
4738 * mptsas_issue_tm - send mptsas internal tm request
4739 * @ioc: Pointer to MPT_ADAPTER structure
4740 * @type: Task Management type
4741 * @channel: channel number for task management
4742 * @id: Logical Target ID for reset (if appropriate)
4743 * @lun: Logical unit for reset (if appropriate)
4744 * @task_context: Context for the task to be aborted
4745 * @timeout: timeout for task management control
4746 *
4747 * return 0 on success and -1 on failure:
4748 *
4749 */
4750static int
4751mptsas_issue_tm(MPT_ADAPTER *ioc, u8 type, u8 channel, u8 id, u64 lun,
4752 int task_context, ulong timeout, u8 *issue_reset)
4753{
4754 MPT_FRAME_HDR *mf;
4755 SCSITaskMgmt_t *pScsiTm;
4756 int retval;
4757 unsigned long timeleft;
4758
4759 *issue_reset = 0;
4760 mf = mpt_get_msg_frame(mptsasDeviceResetCtx, ioc);
4761 if (mf == NULL) {
4762 retval = -1; /* return failure */
4763 dtmprintk(ioc, printk(MYIOC_s_WARN_FMT "TaskMgmt request: no "
4764 "msg frames!!\n", ioc->name));
4765 goto out;
4766 }
4767
4768 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TaskMgmt request: mr = %p, "
4769 "task_type = 0x%02X,\n\t timeout = %ld, fw_channel = %d, "
4770 "fw_id = %d, lun = %lld,\n\t task_context = 0x%x\n", ioc->name, mf,
4771 type, timeout, channel, id, (unsigned long long)lun,
4772 task_context));
4773
4774 pScsiTm = (SCSITaskMgmt_t *) mf;
4775 memset(pScsiTm, 0, sizeof(SCSITaskMgmt_t));
4776 pScsiTm->Function = MPI_FUNCTION_SCSI_TASK_MGMT;
4777 pScsiTm->TaskType = type;
4778 pScsiTm->MsgFlags = 0;
4779 pScsiTm->TargetID = id;
4780 pScsiTm->Bus = channel;
4781 pScsiTm->ChainOffset = 0;
4782 pScsiTm->Reserved = 0;
4783 pScsiTm->Reserved1 = 0;
4784 pScsiTm->TaskMsgContext = task_context;
4785 int_to_scsilun(lun, (struct scsi_lun *)pScsiTm->LUN);
4786
4787 INITIALIZE_MGMT_STATUS(ioc->taskmgmt_cmds.status)
4788 CLEAR_MGMT_STATUS(ioc->internal_cmds.status)
4789 retval = 0;
4790 mpt_put_msg_frame_hi_pri(mptsasDeviceResetCtx, ioc, mf);
4791
4792 /* Now wait for the command to complete */
4793 timeleft = wait_for_completion_timeout(&ioc->taskmgmt_cmds.done,
4794 timeout*HZ);
4795 if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_COMMAND_GOOD)) {
4796 retval = -1; /* return failure */
4797 dtmprintk(ioc, printk(MYIOC_s_ERR_FMT
4798 "TaskMgmt request: TIMED OUT!(mr=%p)\n", ioc->name, mf));
4799 mpt_free_msg_frame(ioc, mf);
4800 if (ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_DID_IOCRESET)
4801 goto out;
4802 *issue_reset = 1;
4803 goto out;
4804 }
4805
4806 if (!(ioc->taskmgmt_cmds.status & MPT_MGMT_STATUS_RF_VALID)) {
4807 retval = -1; /* return failure */
4808 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4809 "TaskMgmt request: failed with no reply\n", ioc->name));
4810 goto out;
4811 }
4812
4813 out:
4814 CLEAR_MGMT_STATUS(ioc->taskmgmt_cmds.status)
4815 return retval;
4816}
4817
4818/**
4819 * mptsas_broadcast_primative_work - Handle broadcast primitives
4820 * @work: work queue payload containing info describing the event
4821 *
4822 * this will be handled in workqueue context.
4823 */
4824static void
4825mptsas_broadcast_primative_work(struct fw_event_work *fw_event)
4826{
4827 MPT_ADAPTER *ioc = fw_event->ioc;
4828 MPT_FRAME_HDR *mf;
4829 VirtDevice *vdevice;
4830 int ii;
4831 struct scsi_cmnd *sc;
4832 SCSITaskMgmtReply_t *pScsiTmReply;
4833 u8 issue_reset;
4834 int task_context;
4835 u8 channel, id;
4836 int lun;
4837 u32 termination_count;
4838 u32 query_count;
4839
4840 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4841 "%s - enter\n", ioc->name, __func__));
4842
4843 mutex_lock(&ioc->taskmgmt_cmds.mutex);
4844 if (mpt_set_taskmgmt_in_progress_flag(ioc) != 0) {
4845 mutex_unlock(&ioc->taskmgmt_cmds.mutex);
4846 mptsas_requeue_fw_event(ioc, fw_event, 1000);
4847 return;
4848 }
4849
4850 issue_reset = 0;
4851 termination_count = 0;
4852 query_count = 0;
4853 mpt_findImVolumes(ioc);
4854 pScsiTmReply = (SCSITaskMgmtReply_t *) ioc->taskmgmt_cmds.reply;
4855
4856 for (ii = 0; ii < ioc->req_depth; ii++) {
4857 if (ioc->fw_events_off)
4858 goto out;
4859 sc = mptscsih_get_scsi_lookup(ioc, ii);
4860 if (!sc)
4861 continue;
4862 mf = MPT_INDEX_2_MFPTR(ioc, ii);
4863 if (!mf)
4864 continue;
4865 task_context = mf->u.frame.hwhdr.msgctxu.MsgContext;
4866 vdevice = sc->device->hostdata;
4867 if (!vdevice || !vdevice->vtarget)
4868 continue;
4869 if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT)
4870 continue; /* skip hidden raid components */
4871 if (vdevice->vtarget->raidVolume)
4872 continue; /* skip hidden raid components */
4873 channel = vdevice->vtarget->channel;
4874 id = vdevice->vtarget->id;
4875 lun = vdevice->lun;
4876 if (mptsas_issue_tm(ioc, MPI_SCSITASKMGMT_TASKTYPE_QUERY_TASK,
4877 channel, id, (u64)lun, task_context, 30, &issue_reset))
4878 goto out;
4879 query_count++;
4880 termination_count +=
4881 le32_to_cpu(pScsiTmReply->TerminationCount);
4882 if ((pScsiTmReply->IOCStatus == MPI_IOCSTATUS_SUCCESS) &&
4883 (pScsiTmReply->ResponseCode ==
4884 MPI_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
4885 pScsiTmReply->ResponseCode ==
4886 MPI_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC))
4887 continue;
4888 if (mptsas_issue_tm(ioc,
4889 MPI_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET,
4890 channel, id, (u64)lun, 0, 30, &issue_reset))
4891 goto out;
4892 termination_count +=
4893 le32_to_cpu(pScsiTmReply->TerminationCount);
4894 }
4895
4896 out:
4897 dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT
4898 "%s - exit, query_count = %d termination_count = %d\n",
4899 ioc->name, __func__, query_count, termination_count));
4900
4901 ioc->broadcast_aen_busy = 0;
4902 mpt_clear_taskmgmt_in_progress_flag(ioc);
4903 mutex_unlock(&ioc->taskmgmt_cmds.mutex);
4904
4905 if (issue_reset) {
97009a29
KT
4906 printk(MYIOC_s_WARN_FMT
4907 "Issuing Reset from %s!! doorbell=0x%08x\n",
4908 ioc->name, __func__, mpt_GetIocState(ioc, 0));
d0f698c4 4909 mpt_Soft_Hard_ResetHandler(ioc, CAN_SLEEP);
db7051b2
KD
4910 }
4911 mptsas_free_fw_event(ioc, fw_event);
4912}
4913
b506ade9
EM
4914/*
4915 * mptsas_send_ir2_event - handle exposing hidden disk when
4916 * an inactive raid volume is added
4917 *
4918 * @ioc: Pointer to MPT_ADAPTER structure
4919 * @ir2_data
4920 *
4921 */
4922static void
3eb0822c 4923mptsas_send_ir2_event(struct fw_event_work *fw_event)
b506ade9 4924{
3eb0822c
KD
4925 MPT_ADAPTER *ioc;
4926 struct mptsas_hotplug_event hot_plug_info;
4927 MPI_EVENT_DATA_IR2 *ir2_data;
4928 u8 reasonCode;
a7938b0b 4929 RaidPhysDiskPage0_t phys_disk;
3eb0822c
KD
4930
4931 ioc = fw_event->ioc;
4932 ir2_data = (MPI_EVENT_DATA_IR2 *)fw_event->event_data;
4933 reasonCode = ir2_data->ReasonCode;
4934
4935 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Entering %s: "
4936 "ReasonCode=%02x\n", ioc->name, __func__, reasonCode));
4937
4938 memset(&hot_plug_info, 0, sizeof(struct mptsas_hotplug_event));
4939 hot_plug_info.id = ir2_data->TargetID;
4940 hot_plug_info.channel = ir2_data->Bus;
4941 switch (reasonCode) {
4942 case MPI_EVENT_IR2_RC_FOREIGN_CFG_DETECTED:
4943 hot_plug_info.event_type = MPTSAS_ADD_INACTIVE_VOLUME;
4944 break;
a7938b0b
KD
4945 case MPI_EVENT_IR2_RC_DUAL_PORT_REMOVED:
4946 hot_plug_info.phys_disk_num = ir2_data->PhysDiskNum;
4947 hot_plug_info.event_type = MPTSAS_DEL_PHYSDISK;
4948 break;
4949 case MPI_EVENT_IR2_RC_DUAL_PORT_ADDED:
4950 hot_plug_info.phys_disk_num = ir2_data->PhysDiskNum;
4951 mpt_raid_phys_disk_pg0(ioc,
4952 ir2_data->PhysDiskNum, &phys_disk);
4953 hot_plug_info.id = phys_disk.PhysDiskID;
4954 hot_plug_info.event_type = MPTSAS_ADD_PHYSDISK;
4955 break;
3eb0822c
KD
4956 default:
4957 mptsas_free_fw_event(ioc, fw_event);
b506ade9 4958 return;
3eb0822c
KD
4959 }
4960 mptsas_hotplug_work(ioc, fw_event, &hot_plug_info);
4961}
e6b2d76a 4962
9a28f49a
CH
4963static int
4964mptsas_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *reply)
4965{
3eb0822c
KD
4966 u32 event = le32_to_cpu(reply->Event);
4967 int sz, event_data_sz;
4968 struct fw_event_work *fw_event;
4969 unsigned long delay;
9a28f49a 4970
ffb7fef3
KD
4971 if (ioc->bus_type != SAS)
4972 return 0;
4973
3eb0822c
KD
4974 /* events turned off due to host reset or driver unloading */
4975 if (ioc->fw_events_off)
4976 return 0;
e6b2d76a 4977
3eb0822c 4978 delay = msecs_to_jiffies(1);
9a28f49a 4979 switch (event) {
db7051b2
KD
4980 case MPI_EVENT_SAS_BROADCAST_PRIMITIVE:
4981 {
4982 EVENT_DATA_SAS_BROADCAST_PRIMITIVE *broadcast_event_data =
4983 (EVENT_DATA_SAS_BROADCAST_PRIMITIVE *)reply->Data;
4984 if (broadcast_event_data->Primitive !=
4985 MPI_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT)
4986 return 0;
4987 if (ioc->broadcast_aen_busy)
4988 return 0;
4989 ioc->broadcast_aen_busy = 1;
4990 break;
4991 }
9a28f49a 4992 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE:
3eb0822c
KD
4993 {
4994 EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data =
4995 (EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *)reply->Data;
c9de7dc4
KD
4996 u16 ioc_stat;
4997 ioc_stat = le16_to_cpu(reply->IOCStatus);
3eb0822c
KD
4998
4999 if (sas_event_data->ReasonCode ==
5000 MPI_EVENT_SAS_DEV_STAT_RC_NOT_RESPONDING) {
5001 mptsas_target_reset_queue(ioc, sas_event_data);
5002 return 0;
5003 }
c9de7dc4
KD
5004 if (sas_event_data->ReasonCode ==
5005 MPI_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET &&
5006 ioc->device_missing_delay &&
5007 (ioc_stat & MPI_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)) {
5008 VirtTarget *vtarget = NULL;
5009 u8 id, channel;
5010 u32 log_info = le32_to_cpu(reply->IOCLogInfo);
5011
5012 id = sas_event_data->TargetID;
5013 channel = sas_event_data->Bus;
5014
5015 vtarget = mptsas_find_vtarget(ioc, channel, id);
5016 if (vtarget) {
5017 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5018 "LogInfo (0x%x) available for "
5019 "INTERNAL_DEVICE_RESET"
5020 "fw_id %d fw_channel %d\n", ioc->name,
5021 log_info, id, channel));
5022 if (vtarget->raidVolume) {
5023 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5024 "Skipping Raid Volume for inDMD\n",
5025 ioc->name));
5026 } else {
5027 devtprintk(ioc, printk(MYIOC_s_DEBUG_FMT
5028 "Setting device flag inDMD\n",
5029 ioc->name));
5030 vtarget->inDMD = 1;
5031 }
5032
5033 }
5034
5035 }
5036
79de278e 5037 break;
3eb0822c 5038 }
f9c34022
KD
5039 case MPI_EVENT_SAS_EXPANDER_STATUS_CHANGE:
5040 {
5041 MpiEventDataSasExpanderStatusChange_t *expander_data =
5042 (MpiEventDataSasExpanderStatusChange_t *)reply->Data;
5043
eedf92b9
KD
5044 if (ioc->old_sas_discovery_protocal)
5045 return 0;
f9c34022
KD
5046
5047 if (expander_data->ReasonCode ==
5048 MPI_EVENT_SAS_EXP_RC_NOT_RESPONDING &&
5049 ioc->device_missing_delay)
5050 delay = HZ * ioc->device_missing_delay;
e6b2d76a 5051 break;
f9c34022
KD
5052 }
5053 case MPI_EVENT_SAS_DISCOVERY:
5054 {
5055 u32 discovery_status;
5056 EventDataSasDiscovery_t *discovery_data =
5057 (EventDataSasDiscovery_t *)reply->Data;
5058
5059 discovery_status = le32_to_cpu(discovery_data->DiscoveryStatus);
5060 ioc->sas_discovery_quiesce_io = discovery_status ? 1 : 0;
eedf92b9
KD
5061 if (ioc->old_sas_discovery_protocal && !discovery_status)
5062 mptsas_queue_rescan(ioc);
f9c34022
KD
5063 return 0;
5064 }
3eb0822c
KD
5065 case MPI_EVENT_INTEGRATED_RAID:
5066 case MPI_EVENT_PERSISTENT_TABLE_FULL:
b506ade9 5067 case MPI_EVENT_IR2:
3eb0822c
KD
5068 case MPI_EVENT_SAS_PHY_LINK_STATUS:
5069 case MPI_EVENT_QUEUE_FULL:
b506ade9 5070 break;
9a28f49a 5071 default:
3eb0822c 5072 return 0;
9a28f49a 5073 }
c73787ee 5074
3eb0822c
KD
5075 event_data_sz = ((reply->MsgLength * 4) -
5076 offsetof(EventNotificationReply_t, Data));
5077 sz = offsetof(struct fw_event_work, event_data) + event_data_sz;
5078 fw_event = kzalloc(sz, GFP_ATOMIC);
5079 if (!fw_event) {
5080 printk(MYIOC_s_WARN_FMT "%s: failed at (line=%d)\n", ioc->name,
5081 __func__, __LINE__);
5082 return 0;
5083 }
5084 memcpy(fw_event->event_data, reply->Data, event_data_sz);
5085 fw_event->event = event;
5086 fw_event->ioc = ioc;
5087 mptsas_add_fw_event(ioc, fw_event, delay);
5088 return 0;
9a28f49a
CH
5089}
5090
a7938b0b
KD
5091/* Delete a volume when no longer listed in ioc pg2
5092 */
5093static void mptsas_volume_delete(MPT_ADAPTER *ioc, u8 id)
5094{
5095 struct scsi_device *sdev;
5096 int i;
5097
5098 sdev = scsi_device_lookup(ioc->sh, MPTSAS_RAID_CHANNEL, id, 0);
5099 if (!sdev)
5100 return;
5101 if (!ioc->raid_data.pIocPg2)
5102 goto out;
5103 if (!ioc->raid_data.pIocPg2->NumActiveVolumes)
5104 goto out;
5105 for (i = 0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++)
5106 if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id)
5107 goto release_sdev;
5108 out:
5109 printk(MYIOC_s_INFO_FMT "removing raid volume, channel %d, "
5110 "id %d\n", ioc->name, MPTSAS_RAID_CHANNEL, id);
5111 scsi_remove_device(sdev);
5112 release_sdev:
5113 scsi_device_put(sdev);
5114}
5115
0c33b27d
CH
5116static int
5117mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id)
5118{
5119 struct Scsi_Host *sh;
5120 MPT_SCSI_HOST *hd;
5121 MPT_ADAPTER *ioc;
5122 unsigned long flags;
1ca00bb7 5123 int ii;
0c33b27d
CH
5124 int numSGE = 0;
5125 int scale;
5126 int ioc_cap;
0c33b27d
CH
5127 int error=0;
5128 int r;
5129
5130 r = mpt_attach(pdev,id);
5131 if (r)
5132 return r;
5133
5134 ioc = pci_get_drvdata(pdev);
3eb0822c 5135 mptsas_fw_event_off(ioc);
0c33b27d
CH
5136 ioc->DoneCtx = mptsasDoneCtx;
5137 ioc->TaskCtx = mptsasTaskCtx;
5138 ioc->InternalCtx = mptsasInternalCtx;
b68bf096 5139 ioc->schedule_target_reset = &mptsas_schedule_target_reset;
0c33b27d
CH
5140 /* Added sanity check on readiness of the MPT adapter.
5141 */
5142 if (ioc->last_state != MPI_IOC_STATE_OPERATIONAL) {
5143 printk(MYIOC_s_WARN_FMT
5144 "Skipping because it's not operational!\n",
5145 ioc->name);
7acec1e7
MED
5146 error = -ENODEV;
5147 goto out_mptsas_probe;
0c33b27d
CH
5148 }
5149
5150 if (!ioc->active) {
5151 printk(MYIOC_s_WARN_FMT "Skipping because it's disabled!\n",
5152 ioc->name);
7acec1e7
MED
5153 error = -ENODEV;
5154 goto out_mptsas_probe;
0c33b27d
CH
5155 }
5156
5157 /* Sanity check - ensure at least 1 port is INITIATOR capable
5158 */
5159 ioc_cap = 0;
5160 for (ii = 0; ii < ioc->facts.NumberOfPorts; ii++) {
5161 if (ioc->pfacts[ii].ProtocolFlags &
5162 MPI_PORTFACTS_PROTOCOL_INITIATOR)
5163 ioc_cap++;
5164 }
5165
5166 if (!ioc_cap) {
5167 printk(MYIOC_s_WARN_FMT
5168 "Skipping ioc=%p because SCSI Initiator mode "
5169 "is NOT enabled!\n", ioc->name, ioc);
466544d8 5170 return 0;
0c33b27d
CH
5171 }
5172
5173 sh = scsi_host_alloc(&mptsas_driver_template, sizeof(MPT_SCSI_HOST));
5174 if (!sh) {
5175 printk(MYIOC_s_WARN_FMT
5176 "Unable to register controller with SCSI subsystem\n",
5177 ioc->name);
7acec1e7
MED
5178 error = -1;
5179 goto out_mptsas_probe;
0c33b27d
CH
5180 }
5181
5182 spin_lock_irqsave(&ioc->FreeQlock, flags);
5183
5184 /* Attach the SCSI Host to the IOC structure
5185 */
5186 ioc->sh = sh;
5187
5188 sh->io_port = 0;
5189 sh->n_io_port = 0;
5190 sh->irq = 0;
5191
5192 /* set 16 byte cdb's */
5193 sh->max_cmd_len = 16;
79a3ec1a
KD
5194 sh->can_queue = min_t(int, ioc->req_depth - 10, sh->can_queue);
5195 sh->max_id = -1;
793955f5 5196 sh->max_lun = max_lun;
0c33b27d
CH
5197 sh->transportt = mptsas_transport_template;
5198
0c33b27d
CH
5199 /* Required entry.
5200 */
5201 sh->unique_id = ioc->id;
5202
5203 INIT_LIST_HEAD(&ioc->sas_topology);
9a28f49a 5204 mutex_init(&ioc->sas_topology_mutex);
e6b2d76a 5205 mutex_init(&ioc->sas_discovery_mutex);
eeb846ce 5206 mutex_init(&ioc->sas_mgmt.mutex);
da4fa655 5207 init_completion(&ioc->sas_mgmt.done);
0c33b27d
CH
5208
5209 /* Verify that we won't exceed the maximum
5210 * number of chain buffers
5211 * We can optimize: ZZ = req_sz/sizeof(SGE)
5212 * For 32bit SGE's:
5213 * numSGE = 1 + (ZZ-1)*(maxChain -1) + ZZ
5214 * + (req_sz - 64)/sizeof(SGE)
5215 * A slightly different algorithm is required for
5216 * 64bit SGEs.
5217 */
14d0f0b0
KD
5218 scale = ioc->req_sz/ioc->SGE_size;
5219 if (ioc->sg_addr_size == sizeof(u64)) {
0c33b27d
CH
5220 numSGE = (scale - 1) *
5221 (ioc->facts.MaxChainDepth-1) + scale +
14d0f0b0 5222 (ioc->req_sz - 60) / ioc->SGE_size;
0c33b27d
CH
5223 } else {
5224 numSGE = 1 + (scale - 1) *
5225 (ioc->facts.MaxChainDepth-1) + scale +
14d0f0b0 5226 (ioc->req_sz - 64) / ioc->SGE_size;
0c33b27d
CH
5227 }
5228
5229 if (numSGE < sh->sg_tablesize) {
5230 /* Reset this value */
d6ecdd63 5231 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT
0c33b27d
CH
5232 "Resetting sg_tablesize to %d from %d\n",
5233 ioc->name, numSGE, sh->sg_tablesize));
5234 sh->sg_tablesize = numSGE;
5235 }
5236
e7eae9f6 5237 hd = shost_priv(sh);
0c33b27d
CH
5238 hd->ioc = ioc;
5239
5240 /* SCSI needs scsi_cmnd lookup table!
5241 * (with size equal to req_depth*PtrSz!)
5242 */
e8206381
EM
5243 ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC);
5244 if (!ioc->ScsiLookup) {
0c33b27d 5245 error = -ENOMEM;
bc6e089a 5246 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
7acec1e7 5247 goto out_mptsas_probe;
0c33b27d 5248 }
e8206381 5249 spin_lock_init(&ioc->scsi_lookup_lock);
0c33b27d 5250
d6ecdd63 5251 dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n",
e8206381 5252 ioc->name, ioc->ScsiLookup));
0c33b27d 5253
0c33b27d
CH
5254 ioc->sas_data.ptClear = mpt_pt_clear;
5255
df9e062a
EM
5256 hd->last_queue_full = 0;
5257 INIT_LIST_HEAD(&hd->target_reset_list);
3eb0822c
KD
5258 INIT_LIST_HEAD(&ioc->sas_device_info_list);
5259 mutex_init(&ioc->sas_device_info_mutex);
5260
df9e062a
EM
5261 spin_unlock_irqrestore(&ioc->FreeQlock, flags);
5262
0c33b27d
CH
5263 if (ioc->sas_data.ptClear==1) {
5264 mptbase_sas_persist_operation(
5265 ioc, MPI_SAS_OP_CLEAR_ALL_PERSISTENT);
5266 }
5267
0c33b27d
CH
5268 error = scsi_add_host(sh, &ioc->pcidev->dev);
5269 if (error) {
29dd3609
EM
5270 dprintk(ioc, printk(MYIOC_s_ERR_FMT
5271 "scsi_add_host failed\n", ioc->name));
7acec1e7 5272 goto out_mptsas_probe;
0c33b27d
CH
5273 }
5274
eedf92b9
KD
5275 /* older firmware doesn't support expander events */
5276 if ((ioc->facts.HeaderVersion >> 8) < 0xE)
5277 ioc->old_sas_discovery_protocal = 1;
0c33b27d 5278 mptsas_scan_sas_topology(ioc);
3eb0822c 5279 mptsas_fw_event_on(ioc);
0c33b27d
CH
5280 return 0;
5281
547f9a21 5282 out_mptsas_probe:
0c33b27d
CH
5283
5284 mptscsih_remove(pdev);
5285 return error;
5286}
5287
7b5a65b9
KD
5288void
5289mptsas_shutdown(struct pci_dev *pdev)
5290{
5291 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
5292
3eb0822c
KD
5293 mptsas_fw_event_off(ioc);
5294 mptsas_cleanup_fw_event_q(ioc);
7b5a65b9
KD
5295}
5296
0c33b27d
CH
5297static void __devexit mptsas_remove(struct pci_dev *pdev)
5298{
5299 MPT_ADAPTER *ioc = pci_get_drvdata(pdev);
5300 struct mptsas_portinfo *p, *n;
547f9a21 5301 int i;
0c33b27d 5302
48959f1e
KD
5303 if (!ioc->sh) {
5304 printk(MYIOC_s_INFO_FMT "IOC is in Target mode\n", ioc->name);
5305 mpt_detach(pdev);
5306 return;
5307 }
5308
7b5a65b9
KD
5309 mptsas_shutdown(pdev);
5310
3eb0822c
KD
5311 mptsas_del_device_components(ioc);
5312
b506ade9 5313 ioc->sas_discovery_ignore_events = 1;
0c33b27d
CH
5314 sas_remove_host(ioc->sh);
5315
9a28f49a 5316 mutex_lock(&ioc->sas_topology_mutex);
0c33b27d
CH
5317 list_for_each_entry_safe(p, n, &ioc->sas_topology, list) {
5318 list_del(&p->list);
547f9a21 5319 for (i = 0 ; i < p->num_phys ; i++)
d6ecdd63 5320 mptsas_port_delete(ioc, p->phy_info[i].port_details);
3eb0822c 5321
547f9a21 5322 kfree(p->phy_info);
0c33b27d
CH
5323 kfree(p);
5324 }
9a28f49a 5325 mutex_unlock(&ioc->sas_topology_mutex);
f9c34022 5326 ioc->hba_port_info = NULL;
0c33b27d
CH
5327 mptscsih_remove(pdev);
5328}
5329
5330static struct pci_device_id mptsas_pci_table[] = {
87cf8986 5331 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
0c33b27d 5332 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 5333 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
0c33b27d 5334 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 5335 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064E,
0c33b27d 5336 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 5337 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068E,
0c33b27d 5338 PCI_ANY_ID, PCI_ANY_ID },
87cf8986 5339 { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1078,
0c33b27d
CH
5340 PCI_ANY_ID, PCI_ANY_ID },
5341 {0} /* Terminating entry */
5342};
5343MODULE_DEVICE_TABLE(pci, mptsas_pci_table);
5344
5345
5346static struct pci_driver mptsas_driver = {
5347 .name = "mptsas",
5348 .id_table = mptsas_pci_table,
5349 .probe = mptsas_probe,
5350 .remove = __devexit_p(mptsas_remove),
7b5a65b9 5351 .shutdown = mptsas_shutdown,
0c33b27d
CH
5352#ifdef CONFIG_PM
5353 .suspend = mptscsih_suspend,
5354 .resume = mptscsih_resume,
5355#endif
5356};
5357
5358static int __init
5359mptsas_init(void)
5360{
57ce21bf
PS
5361 int error;
5362
0c33b27d
CH
5363 show_mptmod_ver(my_NAME, my_VERSION);
5364
5365 mptsas_transport_template =
5366 sas_attach_transport(&mptsas_transport_functions);
5367 if (!mptsas_transport_template)
5368 return -ENODEV;
c9de7dc4 5369 mptsas_transport_template->eh_timed_out = mptsas_eh_timed_out;
0c33b27d 5370
213aaca3
KD
5371 mptsasDoneCtx = mpt_register(mptscsih_io_done, MPTSAS_DRIVER,
5372 "mptscsih_io_done");
5373 mptsasTaskCtx = mpt_register(mptscsih_taskmgmt_complete, MPTSAS_DRIVER,
5374 "mptscsih_taskmgmt_complete");
0c33b27d 5375 mptsasInternalCtx =
213aaca3
KD
5376 mpt_register(mptscsih_scandv_complete, MPTSAS_DRIVER,
5377 "mptscsih_scandv_complete");
5378 mptsasMgmtCtx = mpt_register(mptsas_mgmt_done, MPTSAS_DRIVER,
5379 "mptsas_mgmt_done");
e7deff33 5380 mptsasDeviceResetCtx =
213aaca3
KD
5381 mpt_register(mptsas_taskmgmt_complete, MPTSAS_DRIVER,
5382 "mptsas_taskmgmt_complete");
0c33b27d 5383
d6ecdd63
PS
5384 mpt_event_register(mptsasDoneCtx, mptsas_event_process);
5385 mpt_reset_register(mptsasDoneCtx, mptsas_ioc_reset);
0c33b27d 5386
57ce21bf
PS
5387 error = pci_register_driver(&mptsas_driver);
5388 if (error)
5389 sas_release_transport(mptsas_transport_template);
5390
5391 return error;
0c33b27d
CH
5392}
5393
5394static void __exit
5395mptsas_exit(void)
5396{
5397 pci_unregister_driver(&mptsas_driver);
5398 sas_release_transport(mptsas_transport_template);
5399
5400 mpt_reset_deregister(mptsasDoneCtx);
5401 mpt_event_deregister(mptsasDoneCtx);
5402
da4fa655 5403 mpt_deregister(mptsasMgmtCtx);
0c33b27d
CH
5404 mpt_deregister(mptsasInternalCtx);
5405 mpt_deregister(mptsasTaskCtx);
5406 mpt_deregister(mptsasDoneCtx);
e7deff33 5407 mpt_deregister(mptsasDeviceResetCtx);
0c33b27d
CH
5408}
5409
5410module_init(mptsas_init);
5411module_exit(mptsas_exit);