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