···6060 - short blurb on using SCSI support as a module.6161scsi_mid_low_api.txt6262 - info on API between SCSI layer and low level drivers6363+scsi_eh.txt6464+ - info on SCSI midlayer error handling infrastructure6365st.txt6466 - info on scsi tape driver6567sym53c500_cs.txt
+479
Documentation/scsi/scsi_eh.txt
···11+22+SCSI EH33+======================================44+55+ This document describes SCSI midlayer error handling infrastructure.66+Please refer to Documentation/scsi/scsi_mid_low_api.txt for more77+information regarding SCSI midlayer.88+99+TABLE OF CONTENTS1010+1111+[1] How SCSI commands travel through the midlayer and to EH1212+ [1-1] struct scsi_cmnd1313+ [1-2] How do scmd's get completed?1414+ [1-2-1] Completing a scmd w/ scsi_done1515+ [1-2-2] Completing a scmd w/ timeout1616+ [1-3] How EH takes over1717+[2] How SCSI EH works1818+ [2-1] EH through fine-grained callbacks1919+ [2-1-1] Overview2020+ [2-1-2] Flow of scmds through EH2121+ [2-1-3] Flow of control2222+ [2-2] EH through hostt->eh_strategy_handler()2323+ [2-2-1] Pre hostt->eh_strategy_handler() SCSI midlayer conditions2424+ [2-2-2] Post hostt->eh_strategy_handler() SCSI midlayer conditions2525+ [2-2-3] Things to consider2626+2727+2828+[1] How SCSI commands travel through the midlayer and to EH2929+3030+[1-1] struct scsi_cmnd3131+3232+ Each SCSI command is represented with struct scsi_cmnd (== scmd). A3333+scmd has two list_head's to link itself into lists. The two are3434+scmd->list and scmd->eh_entry. The former is used for free list or3535+per-device allocated scmd list and not of much interest to this EH3636+discussion. The latter is used for completion and EH lists and unless3737+otherwise stated scmds are always linked using scmd->eh_entry in this3838+discussion.3939+4040+4141+[1-2] How do scmd's get completed?4242+4343+ Once LLDD gets hold of a scmd, either the LLDD will complete the4444+command by calling scsi_done callback passed from midlayer when4545+invoking hostt->queuecommand() or SCSI midlayer will time it out.4646+4747+4848+[1-2-1] Completing a scmd w/ scsi_done4949+5050+ For all non-EH commands, scsi_done() is the completion callback. It5151+does the following.5252+5353+ 1. Delete timeout timer. If it fails, it means that timeout timer5454+ has expired and is going to finish the command. Just return.5555+5656+ 2. Link scmd to per-cpu scsi_done_q using scmd->en_entry5757+5858+ 3. Raise SCSI_SOFTIRQ5959+6060+ SCSI_SOFTIRQ handler scsi_softirq calls scsi_decide_disposition() to6161+determine what to do with the command. scsi_decide_disposition()6262+looks at the scmd->result value and sense data to determine what to do6363+with the command.6464+6565+ - SUCCESS6666+ scsi_finish_command() is invoked for the command. The6767+ function does some maintenance choirs and notify completion by6868+ calling scmd->done() callback, which, for fs requests, would6969+ be HLD completion callback - sd:sd_rw_intr, sr:rw_intr,7070+ st:st_intr.7171+7272+ - NEEDS_RETRY7373+ - ADD_TO_MLQUEUE7474+ scmd is requeued to blk queue.7575+7676+ - otherwise7777+ scsi_eh_scmd_add(scmd, 0) is invoked for the command. See7878+ [1-3] for details of this funciton.7979+8080+8181+[1-2-2] Completing a scmd w/ timeout8282+8383+ The timeout handler is scsi_times_out(). When a timeout occurs, this8484+function8585+8686+ 1. invokes optional hostt->eh_timedout() callback. Return value can8787+ be one of8888+8989+ - EH_HANDLED9090+ This indicates that eh_timedout() dealt with the timeout. The9191+ scmd is passed to __scsi_done() and thus linked into per-cpu9292+ scsi_done_q. Normal command completion described in [1-2-1]9393+ follows.9494+9595+ - EH_RESET_TIMER9696+ This indicates that more time is required to finish the9797+ command. Timer is restarted. This action is counted as a9898+ retry and only allowed scmd->allowed + 1(!) times. Once the9999+ limit is reached, action for EH_NOT_HANDLED is taken instead.100100+101101+ *NOTE* This action is racy as the LLDD could finish the scmd102102+ after the timeout has expired but before it's added back. In103103+ such cases, scsi_done() would think that timeout has occurred104104+ and return without doing anything. We lose completion and the105105+ command will time out again.106106+107107+ - EH_NOT_HANDLED108108+ This is the same as when eh_timedout() callback doesn't exist.109109+ Step #2 is taken.110110+111111+ 2. scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD) is invoked for the112112+ command. See [1-3] for more information.113113+114114+115115+[1-3] How EH takes over116116+117117+ scmds enter EH via scsi_eh_scmd_add(), which does the following.118118+119119+ 1. Turns on scmd->eh_eflags as requested. It's 0 for error120120+ completions and SCSI_EH_CANCEL_CMD for timeouts.121121+122122+ 2. Links scmd->eh_entry to shost->eh_cmd_q123123+124124+ 3. Sets SHOST_RECOVERY bit in shost->shost_state125125+126126+ 4. Increments shost->host_failed127127+128128+ 5. Wakes up SCSI EH thread if shost->host_busy == shost->host_failed129129+130130+ As can be seen above, once any scmd is added to shost->eh_cmd_q,131131+SHOST_RECOVERY shost_state bit is turned on. This prevents any new132132+scmd to be issued from blk queue to the host; eventually, all scmds on133133+the host either complete normally, fail and get added to eh_cmd_q, or134134+time out and get added to shost->eh_cmd_q.135135+136136+ If all scmds either complete or fail, the number of in-flight scmds137137+becomes equal to the number of failed scmds - i.e. shost->host_busy ==138138+shost->host_failed. This wakes up SCSI EH thread. So, once woken up,139139+SCSI EH thread can expect that all in-flight commands have failed and140140+are linked on shost->eh_cmd_q.141141+142142+ Note that this does not mean lower layers are quiescent. If a LLDD143143+completed a scmd with error status, the LLDD and lower layers are144144+assumed to forget about the scmd at that point. However, if a scmd145145+has timed out, unless hostt->eh_timedout() made lower layers forget146146+about the scmd, which currently no LLDD does, the command is still147147+active as long as lower layers are concerned and completion could148148+occur at any time. Of course, all such completions are ignored as the149149+timer has already expired.150150+151151+ We'll talk about how SCSI EH takes actions to abort - make LLDD152152+forget about - timed out scmds later.153153+154154+155155+[2] How SCSI EH works156156+157157+ LLDD's can implement SCSI EH actions in one of the following two158158+ways.159159+160160+ - Fine-grained EH callbacks161161+ LLDD can implement fine-grained EH callbacks and let SCSI162162+ midlayer drive error handling and call appropriate callbacks.163163+ This will be dicussed further in [2-1].164164+165165+ - eh_strategy_handler() callback166166+ This is one big callback which should perform whole error167167+ handling. As such, it should do all choirs SCSI midlayer168168+ performs during recovery. This will be discussed in [2-2].169169+170170+ Once recovery is complete, SCSI EH resumes normal operation by171171+calling scsi_restart_operations(), which172172+173173+ 1. Checks if door locking is needed and locks door.174174+175175+ 2. Clears SHOST_RECOVERY shost_state bit176176+177177+ 3. Wakes up waiters on shost->host_wait. This occurs if someone178178+ calls scsi_block_when_processing_errors() on the host.179179+ (*QUESTION* why is it needed? All operations will be blocked180180+ anyway after it reaches blk queue.)181181+182182+ 4. Kicks queues in all devices on the host in the asses183183+184184+185185+[2-1] EH through fine-grained callbacks186186+187187+[2-1-1] Overview188188+189189+ If eh_strategy_handler() is not present, SCSI midlayer takes charge190190+of driving error handling. EH's goals are two - make LLDD, host and191191+device forget about timed out scmds and make them ready for new192192+commands. A scmd is said to be recovered if the scmd is forgotten by193193+lower layers and lower layers are ready to process or fail the scmd194194+again.195195+196196+ To achieve these goals, EH performs recovery actions with increasing197197+severity. Some actions are performed by issueing SCSI commands and198198+others are performed by invoking one of the following fine-grained199199+hostt EH callbacks. Callbacks may be omitted and omitted ones are200200+considered to fail always.201201+202202+int (* eh_abort_handler)(struct scsi_cmnd *);203203+int (* eh_device_reset_handler)(struct scsi_cmnd *);204204+int (* eh_bus_reset_handler)(struct scsi_cmnd *);205205+int (* eh_host_reset_handler)(struct scsi_cmnd *);206206+207207+ Higher-severity actions are taken only when lower-severity actions208208+cannot recover some of failed scmds. Also, note that failure of the209209+highest-severity action means EH failure and results in offlining of210210+all unrecovered devices.211211+212212+ During recovery, the following rules are followed213213+214214+ - Recovery actions are performed on failed scmds on the to do list,215215+ eh_work_q. If a recovery action succeeds for a scmd, recovered216216+ scmds are removed from eh_work_q.217217+218218+ Note that single recovery action on a scmd can recover multiple219219+ scmds. e.g. resetting a device recovers all failed scmds on the220220+ device.221221+222222+ - Higher severity actions are taken iff eh_work_q is not empty after223223+ lower severity actions are complete.224224+225225+ - EH reuses failed scmds to issue commands for recovery. For226226+ timed-out scmds, SCSI EH ensures that LLDD forgets about a scmd227227+ before reusing it for EH commands.228228+229229+ When a scmd is recovered, the scmd is moved from eh_work_q to EH230230+local eh_done_q using scsi_eh_finish_cmd(). After all scmds are231231+recovered (eh_work_q is empty), scsi_eh_flush_done_q() is invoked to232232+either retry or error-finish (notify upper layer of failure) recovered233233+scmds.234234+235235+ scmds are retried iff its sdev is still online (not offlined during236236+EH), REQ_FAILFAST is not set and ++scmd->retries is less than237237+scmd->allowed.238238+239239+240240+[2-1-2] Flow of scmds through EH241241+242242+ 1. Error completion / time out243243+ ACTION: scsi_eh_scmd_add() is invoked for scmd244244+ - set scmd->eh_eflags245245+ - add scmd to shost->eh_cmd_q246246+ - set SHOST_RECOVERY247247+ - shost->host_failed++248248+ LOCKING: shost->host_lock249249+250250+ 2. EH starts251251+ ACTION: move all scmds to EH's local eh_work_q. shost->eh_cmd_q252252+ is cleared.253253+ LOCKING: shost->host_lock (not strictly necessary, just for254254+ consistency)255255+256256+ 3. scmd recovered257257+ ACTION: scsi_eh_finish_cmd() is invoked to EH-finish scmd258258+ - shost->host_failed--259259+ - clear scmd->eh_eflags260260+ - scsi_setup_cmd_retry()261261+ - move from local eh_work_q to local eh_done_q262262+ LOCKING: none263263+264264+ 4. EH completes265265+ ACTION: scsi_eh_flush_done_q() retries scmds or notifies upper266266+ layer of failure.267267+ - scmd is removed from eh_done_q and scmd->eh_entry is cleared268268+ - if retry is necessary, scmd is requeued using269269+ scsi_queue_insert()270270+ - otherwise, scsi_finish_command() is invoked for scmd271271+ LOCKING: queue or finish function performs appropriate locking272272+273273+274274+[2-1-3] Flow of control275275+276276+ EH through fine-grained callbacks start from scsi_unjam_host().277277+278278+<<scsi_unjam_host>>279279+280280+ 1. Lock shost->host_lock, splice_init shost->eh_cmd_q into local281281+ eh_work_q and unlock host_lock. Note that shost->eh_cmd_q is282282+ cleared by this action.283283+284284+ 2. Invoke scsi_eh_get_sense.285285+286286+ <<scsi_eh_get_sense>>287287+288288+ This action is taken for each error-completed289289+ (!SCSI_EH_CANCEL_CMD) commands without valid sense data. Most290290+ SCSI transports/LLDDs automatically acquire sense data on291291+ command failures (autosense). Autosense is recommended for292292+ performance reasons and as sense information could get out of293293+ sync inbetween occurrence of CHECK CONDITION and this action.294294+295295+ Note that if autosense is not supported, scmd->sense_buffer296296+ contains invalid sense data when error-completing the scmd297297+ with scsi_done(). scsi_decide_disposition() always returns298298+ FAILED in such cases thus invoking SCSI EH. When the scmd299299+ reaches here, sense data is acquired and300300+ scsi_decide_disposition() is called again.301301+302302+ 1. Invoke scsi_request_sense() which issues REQUEST_SENSE303303+ command. If fails, no action. Note that taking no action304304+ causes higher-severity recovery to be taken for the scmd.305305+306306+ 2. Invoke scsi_decide_disposition() on the scmd307307+308308+ - SUCCESS309309+ scmd->retries is set to scmd->allowed preventing310310+ scsi_eh_flush_done_q() from retrying the scmd and311311+ scsi_eh_finish_cmd() is invoked.312312+313313+ - NEEDS_RETRY314314+ scsi_eh_finish_cmd() invoked315315+316316+ - otherwise317317+ No action.318318+319319+ 3. If !list_empty(&eh_work_q), invoke scsi_eh_abort_cmds().320320+321321+ <<scsi_eh_abort_cmds>>322322+323323+ This action is taken for each timed out command.324324+ hostt->eh_abort_handler() is invoked for each scmd. The325325+ handler returns SUCCESS if it has succeeded to make LLDD and326326+ all related hardware forget about the scmd.327327+328328+ If a timedout scmd is successfully aborted and the sdev is329329+ either offline or ready, scsi_eh_finish_cmd() is invoked for330330+ the scmd. Otherwise, the scmd is left in eh_work_q for331331+ higher-severity actions.332332+333333+ Note that both offline and ready status mean that the sdev is334334+ ready to process new scmds, where processing also implies335335+ immediate failing; thus, if a sdev is in one of the two336336+ states, no further recovery action is needed.337337+338338+ Device readiness is tested using scsi_eh_tur() which issues339339+ TEST_UNIT_READY command. Note that the scmd must have been340340+ aborted successfully before reusing it for TEST_UNIT_READY.341341+342342+ 4. If !list_empty(&eh_work_q), invoke scsi_eh_ready_devs()343343+344344+ <<scsi_eh_ready_devs>>345345+346346+ This function takes four increasingly more severe measures to347347+ make failed sdevs ready for new commands.348348+349349+ 1. Invoke scsi_eh_stu()350350+351351+ <<scsi_eh_stu>>352352+353353+ For each sdev which has failed scmds with valid sense data354354+ of which scsi_check_sense()'s verdict is FAILED,355355+ START_STOP_UNIT command is issued w/ start=1. Note that356356+ as we explicitly choose error-completed scmds, it is known357357+ that lower layers have forgotten about the scmd and we can358358+ reuse it for STU.359359+360360+ If STU succeeds and the sdev is either offline or ready,361361+ all failed scmds on the sdev are EH-finished with362362+ scsi_eh_finish_cmd().363363+364364+ *NOTE* If hostt->eh_abort_handler() isn't implemented or365365+ failed, we may still have timed out scmds at this point366366+ and STU doesn't make lower layers forget about those367367+ scmds. Yet, this function EH-finish all scmds on the sdev368368+ if STU succeeds leaving lower layers in an inconsistent369369+ state. It seems that STU action should be taken only when370370+ a sdev has no timed out scmd.371371+372372+ 2. If !list_empty(&eh_work_q), invoke scsi_eh_bus_device_reset().373373+374374+ <<scsi_eh_bus_device_reset>>375375+376376+ This action is very similar to scsi_eh_stu() except that,377377+ instead of issuing STU, hostt->eh_device_reset_handler()378378+ is used. Also, as we're not issuing SCSI commands and379379+ resetting clears all scmds on the sdev, there is no need380380+ to choose error-completed scmds.381381+382382+ 3. If !list_empty(&eh_work_q), invoke scsi_eh_bus_reset()383383+384384+ <<scsi_eh_bus_reset>>385385+386386+ hostt->eh_bus_reset_handler() is invoked for each channel387387+ with failed scmds. If bus reset succeeds, all failed388388+ scmds on all ready or offline sdevs on the channel are389389+ EH-finished.390390+391391+ 4. If !list_empty(&eh_work_q), invoke scsi_eh_host_reset()392392+393393+ <<scsi_eh_host_reset>>394394+395395+ This is the last resort. hostt->eh_host_reset_handler()396396+ is invoked. If host reset succeeds, all failed scmds on397397+ all ready or offline sdevs on the host are EH-finished.398398+399399+ 5. If !list_empty(&eh_work_q), invoke scsi_eh_offline_sdevs()400400+401401+ <<scsi_eh_offline_sdevs>>402402+403403+ Take all sdevs which still have unrecovered scmds offline404404+ and EH-finish the scmds.405405+406406+ 5. Invoke scsi_eh_flush_done_q().407407+408408+ <<scsi_eh_flush_done_q>>409409+410410+ At this point all scmds are recovered (or given up) and411411+ put on eh_done_q by scsi_eh_finish_cmd(). This function412412+ flushes eh_done_q by either retrying or notifying upper413413+ layer of failure of the scmds.414414+415415+416416+[2-2] EH through hostt->eh_strategy_handler()417417+418418+ hostt->eh_strategy_handler() is invoked in the place of419419+scsi_unjam_host() and it is responsible for whole recovery process.420420+On completion, the handler should have made lower layers forget about421421+all failed scmds and either ready for new commands or offline. Also,422422+it should perform SCSI EH maintenance choirs to maintain integrity of423423+SCSI midlayer. IOW, of the steps described in [2-1-2], all steps424424+except for #1 must be implemented by eh_strategy_handler().425425+426426+427427+[2-2-1] Pre hostt->eh_strategy_handler() SCSI midlayer conditions428428+429429+ The following conditions are true on entry to the handler.430430+431431+ - Each failed scmd's eh_flags field is set appropriately.432432+433433+ - Each failed scmd is linked on scmd->eh_cmd_q by scmd->eh_entry.434434+435435+ - SHOST_RECOVERY is set.436436+437437+ - shost->host_failed == shost->host_busy438438+439439+440440+[2-2-2] Post hostt->eh_strategy_handler() SCSI midlayer conditions441441+442442+ The following conditions must be true on exit from the handler.443443+444444+ - shost->host_failed is zero.445445+446446+ - Each scmd's eh_eflags field is cleared.447447+448448+ - Each scmd is in such a state that scsi_setup_cmd_retry() on the449449+ scmd doesn't make any difference.450450+451451+ - shost->eh_cmd_q is cleared.452452+453453+ - Each scmd->eh_entry is cleared.454454+455455+ - Either scsi_queue_insert() or scsi_finish_command() is called on456456+ each scmd. Note that the handler is free to use scmd->retries and457457+ ->allowed to limit the number of retries.458458+459459+460460+[2-2-3] Things to consider461461+462462+ - Know that timed out scmds are still active on lower layers. Make463463+ lower layers forget about them before doing anything else with464464+ those scmds.465465+466466+ - For consistency, when accessing/modifying shost data structure,467467+ grab shost->host_lock.468468+469469+ - On completion, each failed sdev must have forgotten about all470470+ active scmds.471471+472472+ - On completion, each failed sdev must be ready for new commands or473473+ offline.474474+475475+476476+--477477+Tejun Heo478478+htejun@gmail.com479479+11th September 2005
···790790static int sbp2_start_device(struct scsi_id_instance_data *scsi_id)791791{792792 struct sbp2scsi_host_info *hi = scsi_id->hi;793793- struct scsi_device *sdev;793793+ int error;794794795795 SBP2_DEBUG("sbp2_start_device");796796···939939 sbp2_max_speed_and_size(scsi_id);940940941941 /* Add this device to the scsi layer now */942942- sdev = scsi_add_device(scsi_id->scsi_host, 0, scsi_id->ud->id, 0);943943- if (IS_ERR(sdev)) {942942+ error = scsi_add_device(scsi_id->scsi_host, 0, scsi_id->ud->id, 0);943943+ if (error) {944944 SBP2_ERR("scsi_add_device failed");945945- return PTR_ERR(sdev);945945+ return error;946946 }947947948948 return 0;
+24-6
drivers/scsi/3w-9xxx.c
···5959 Fix 'handled=1' ISR usage, remove bogus IRQ check.6060 Remove un-needed eh_abort handler.6161 Add support for embedded firmware error strings.6262+ 2.26.02.003 - Correctly handle single sgl's with use_sg=1.6263*/63646465#include <linux/module.h>···8281#include "3w-9xxx.h"83828483/* Globals */8585-#define TW_DRIVER_VERSION "2.26.02.002"8484+#define TW_DRIVER_VERSION "2.26.02.003"8685static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];8786static unsigned int twa_device_extension_count;8887static int twa_major = -1;···18061805 if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH) {18071806 command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id];18081807 command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH;18081808+ if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL)18091809+ memcpy(tw_dev->generic_buffer_virt[request_id], tw_dev->srb[request_id]->request_buffer, tw_dev->srb[request_id]->request_bufflen);18091810 } else {18101811 buffaddr = twa_map_scsi_single_data(tw_dev, request_id);18111812 if (buffaddr == 0)···1826182318271824 if (tw_dev->srb[request_id]->use_sg > 0) {18281825 if ((tw_dev->srb[request_id]->use_sg == 1) && (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH)) {18261826+ if (tw_dev->srb[request_id]->sc_data_direction == DMA_TO_DEVICE || tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL) {18271827+ struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;18281828+ char *buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;18291829+ memcpy(tw_dev->generic_buffer_virt[request_id], buf, sg->length);18301830+ kunmap_atomic(buf - sg->offset, KM_IRQ0);18311831+ }18291832 command_packet->sg_list[0].address = tw_dev->generic_buffer_phys[request_id];18301833 command_packet->sg_list[0].length = TW_MIN_SGL_LENGTH;18311834 } else {···18971888/* This function completes an execute scsi operation */18981889static void twa_scsiop_execute_scsi_complete(TW_Device_Extension *tw_dev, int request_id)18991890{19001900- /* Copy the response if too small */19011901- if ((tw_dev->srb[request_id]->request_buffer) && (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH)) {19021902- memcpy(tw_dev->srb[request_id]->request_buffer,19031903- tw_dev->generic_buffer_virt[request_id],19041904- tw_dev->srb[request_id]->request_bufflen);18911891+ if (tw_dev->srb[request_id]->request_bufflen < TW_MIN_SGL_LENGTH &&18921892+ (tw_dev->srb[request_id]->sc_data_direction == DMA_FROM_DEVICE ||18931893+ tw_dev->srb[request_id]->sc_data_direction == DMA_BIDIRECTIONAL)) {18941894+ if (tw_dev->srb[request_id]->use_sg == 0) {18951895+ memcpy(tw_dev->srb[request_id]->request_buffer,18961896+ tw_dev->generic_buffer_virt[request_id],18971897+ tw_dev->srb[request_id]->request_bufflen);18981898+ }18991899+ if (tw_dev->srb[request_id]->use_sg == 1) {19001900+ struct scatterlist *sg = (struct scatterlist *)tw_dev->srb[request_id]->request_buffer;19011901+ char *buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset;19021902+ memcpy(buf, tw_dev->generic_buffer_virt[request_id], sg->length);19031903+ kunmap_atomic(buf - sg->offset, KM_IRQ0);19041904+ }19051905 }19061906} /* End twa_scsiop_execute_scsi_complete() */19071907
+7
drivers/scsi/Kconfig
···235235 each attached iSCSI device to sysfs, say Y.236236 Otherwise, say N.237237238238+config SCSI_SAS_ATTRS239239+ tristate "SAS Transport Attributes"240240+ depends on SCSI241241+ help242242+ If you wish to export transport-specific information about243243+ each attached SAS device to sysfs, say Y.244244+238245endmenu239246240247menu "SCSI low-level drivers"
···966966lpfc_get_host_fabric_name (struct Scsi_Host *shost)967967{968968 struct lpfc_hba *phba = (struct lpfc_hba*)shost->hostdata[0];969969- u64 nodename;969969+ u64 node_name;970970971971 spin_lock_irq(shost->host_lock);972972973973 if ((phba->fc_flag & FC_FABRIC) ||974974 ((phba->fc_topology == TOPOLOGY_LOOP) &&975975 (phba->fc_flag & FC_PUBLIC_LOOP)))976976- memcpy(&nodename, &phba->fc_fabparam.nodeName, sizeof(u64));976976+ node_name = wwn_to_u64(phba->fc_fabparam.nodeName.wwn);977977 else978978 /* fabric is local port if there is no F/FL_Port */979979- memcpy(&nodename, &phba->fc_nodename, sizeof(u64));979979+ node_name = wwn_to_u64(phba->fc_nodename.wwn);980980981981 spin_unlock_irq(shost->host_lock);982982983983- fc_host_fabric_name(shost) = be64_to_cpu(nodename);983983+ fc_host_fabric_name(shost) = node_name;984984}985985986986···11031103{11041104 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);11051105 struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata[0];11061106- uint64_t node_name = 0;11061106+ u64 node_name = 0;11071107 struct lpfc_nodelist *ndlp = NULL;1108110811091109 spin_lock_irq(shost->host_lock);11101110 /* Search the mapped list for this target ID */11111111 list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) {11121112 if (starget->id == ndlp->nlp_sid) {11131113- memcpy(&node_name, &ndlp->nlp_nodename,11141114- sizeof(struct lpfc_name));11131113+ node_name = wwn_to_u64(ndlp->nlp_nodename.wwn);11151114 break;11161115 }11171116 }11181117 spin_unlock_irq(shost->host_lock);1119111811201120- fc_starget_node_name(starget) = be64_to_cpu(node_name);11191119+ fc_starget_node_name(starget) = node_name;11211120}1122112111231122static void···11241125{11251126 struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);11261127 struct lpfc_hba *phba = (struct lpfc_hba *) shost->hostdata[0];11271127- uint64_t port_name = 0;11281128+ u64 port_name = 0;11281129 struct lpfc_nodelist *ndlp = NULL;1129113011301131 spin_lock_irq(shost->host_lock);11311132 /* Search the mapped list for this target ID */11321133 list_for_each_entry(ndlp, &phba->fc_nlpmap_list, nlp_listp) {11331134 if (starget->id == ndlp->nlp_sid) {11341134- memcpy(&port_name, &ndlp->nlp_portname,11351135- sizeof(struct lpfc_name));11351135+ port_name = wwn_to_u64(ndlp->nlp_portname.wwn);11361136 break;11371137 }11381138 }11391139 spin_unlock_irq(shost->host_lock);1140114011411141- fc_starget_port_name(starget) = be64_to_cpu(port_name);11411141+ fc_starget_port_name(starget) = port_name;11421142}1143114311441144static void
+2-5
drivers/scsi/lpfc/lpfc_hbadisc.c
···10171017 struct fc_rport *rport;10181018 struct lpfc_rport_data *rdata;10191019 struct fc_rport_identifiers rport_ids;10201020- uint64_t wwn;1021102010221021 /* Remote port has reappeared. Re-register w/ FC transport */10231023- memcpy(&wwn, &ndlp->nlp_nodename, sizeof(uint64_t));10241024- rport_ids.node_name = be64_to_cpu(wwn);10251025- memcpy(&wwn, &ndlp->nlp_portname, sizeof(uint64_t));10261026- rport_ids.port_name = be64_to_cpu(wwn);10221022+ rport_ids.node_name = wwn_to_u64(ndlp->nlp_nodename.wwn);10231023+ rport_ids.port_name = wwn_to_u64(ndlp->nlp_portname.wwn);10271024 rport_ids.port_id = ndlp->nlp_DID;10281025 rport_ids.roles = FC_RPORT_ROLE_UNKNOWN;10291026 if (ndlp->nlp_type & NLP_FCP_TARGET)
+11-6
drivers/scsi/lpfc/lpfc_hw.h
···262262#define FF_FRAME_SIZE 2048263263264264struct lpfc_name {265265+ union {266266+ struct {265267#ifdef __BIG_ENDIAN_BITFIELD266266- uint8_t nameType:4; /* FC Word 0, bit 28:31 */267267- uint8_t IEEEextMsn:4; /* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */268268+ uint8_t nameType:4; /* FC Word 0, bit 28:31 */269269+ uint8_t IEEEextMsn:4; /* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */268270#else /* __LITTLE_ENDIAN_BITFIELD */269269- uint8_t IEEEextMsn:4; /* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */270270- uint8_t nameType:4; /* FC Word 0, bit 28:31 */271271+ uint8_t IEEEextMsn:4; /* FC Word 0, bit 24:27, bit 8:11 of IEEE ext */272272+ uint8_t nameType:4; /* FC Word 0, bit 28:31 */271273#endif272274273275#define NAME_IEEE 0x1 /* IEEE name - nameType */···278276#define NAME_IP_TYPE 0x4 /* IP address */279277#define NAME_CCITT_TYPE 0xC280278#define NAME_CCITT_GR_TYPE 0xE281281- uint8_t IEEEextLsb; /* FC Word 0, bit 16:23, IEEE extended Lsb */282282- uint8_t IEEE[6]; /* FC IEEE address */279279+ uint8_t IEEEextLsb; /* FC Word 0, bit 16:23, IEEE extended Lsb */280280+ uint8_t IEEE[6]; /* FC IEEE address */281281+ };282282+ uint8_t wwn[8];283283+ };283284};284285285286struct csp {
+2-5
drivers/scsi/lpfc/lpfc_init.c
···13331333 unsigned long bar0map_len, bar2map_len;13341334 int error = -ENODEV, retval;13351335 int i;13361336- u64 wwname;1337133613381337 if (pci_enable_device(pdev))13391338 goto out;···15231524 * Must done after lpfc_sli_hba_setup()15241525 */1525152615261526- memcpy(&wwname, &phba->fc_nodename, sizeof(u64));15271527- fc_host_node_name(host) = be64_to_cpu(wwname);15281528- memcpy(&wwname, &phba->fc_portname, sizeof(u64));15291529- fc_host_port_name(host) = be64_to_cpu(wwname);15271527+ fc_host_node_name(host) = wwn_to_u64(phba->fc_nodename.wwn);15281528+ fc_host_port_name(host) = wwn_to_u64(phba->fc_portname.wwn);15301529 fc_host_supported_classes(host) = FC_COS_CLASS3;1531153015321531 memset(fc_host_supported_fc4s(host), 0,
···9797}98989999static void scsi_run_queue(struct request_queue *q);100100+static void scsi_release_buffers(struct scsi_cmnd *cmd);101101+102102+/*103103+ * Function: scsi_unprep_request()104104+ *105105+ * Purpose: Remove all preparation done for a request, including its106106+ * associated scsi_cmnd, so that it can be requeued.107107+ *108108+ * Arguments: req - request to unprepare109109+ *110110+ * Lock status: Assumed that no locks are held upon entry.111111+ *112112+ * Returns: Nothing.113113+ */114114+static void scsi_unprep_request(struct request *req)115115+{116116+ struct scsi_cmnd *cmd = req->special;117117+118118+ req->flags &= ~REQ_DONTPREP;119119+ req->special = (req->flags & REQ_SPECIAL) ? cmd->sc_request : NULL;120120+121121+ scsi_release_buffers(cmd);122122+ scsi_put_command(cmd);123123+}100124101125/*102126 * Function: scsi_queue_insert()···140116 * commands.141117 * Notes: This could be called either from an interrupt context or a142118 * normal process context.119119+ * Notes: Upon return, cmd is a stale pointer.143120 */144121int scsi_queue_insert(struct scsi_cmnd *cmd, int reason)145122{146123 struct Scsi_Host *host = cmd->device->host;147124 struct scsi_device *device = cmd->device;148125 struct request_queue *q = device->request_queue;126126+ struct request *req = cmd->request;149127 unsigned long flags;150128151129 SCSI_LOG_MLQUEUE(1,···188162 * function. The SCSI request function detects the blocked condition189163 * and plugs the queue appropriately.190164 */165165+ scsi_unprep_request(req);191166 spin_lock_irqsave(q->queue_lock, flags);192192- blk_requeue_request(q, cmd->request);167167+ blk_requeue_request(q, req);193168 spin_unlock_irqrestore(q->queue_lock, flags);194169195170 scsi_run_queue(q);···366339 int result;367340368341 if (sshdr) {369369- sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL);342342+ sense = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO);370343 if (!sense)371344 return DRIVER_ERROR << 24;372345 memset(sense, 0, SCSI_SENSE_BUFFERSIZE);···579552 * I/O errors in the middle of the request, in which case580553 * we need to request the blocks that come after the bad581554 * sector.555555+ * Notes: Upon return, cmd is a stale pointer.582556 */583557static void scsi_requeue_command(struct request_queue *q, struct scsi_cmnd *cmd)584558{559559+ struct request *req = cmd->request;585560 unsigned long flags;586561587587- cmd->request->flags &= ~REQ_DONTPREP;588588-562562+ scsi_unprep_request(req);589563 spin_lock_irqsave(q->queue_lock, flags);590590- blk_requeue_request(q, cmd->request);564564+ blk_requeue_request(q, req);591565 spin_unlock_irqrestore(q->queue_lock, flags);592566593567 scsi_run_queue(q);···623595 *624596 * Lock status: Assumed that lock is not held upon entry.625597 *626626- * Returns: cmd if requeue done or required, NULL otherwise598598+ * Returns: cmd if requeue required, NULL otherwise.627599 *628600 * Notes: This is called for block device requests in order to629601 * mark some number of sectors as complete.630602 * 631603 * We are guaranteeing that the request queue will be goosed632604 * at some point during this call.605605+ * Notes: If cmd was requeued, upon return it will be a stale pointer.633606 */634607static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int uptodate,635608 int bytes, int requeue)···653624 if (!uptodate && blk_noretry_request(req))654625 end_that_request_chunk(req, 0, leftover);655626 else {656656- if (requeue)627627+ if (requeue) {657628 /*658629 * Bleah. Leftovers again. Stick the659630 * leftovers in the front of the660631 * queue, and goose the queue again.661632 */662633 scsi_requeue_command(q, cmd);663663-634634+ cmd = NULL;635635+ }664636 return cmd;665637 }666638 }···887857 * requeueing right here - we will requeue down below888858 * when we handle the bad sectors.889859 */890890- cmd = scsi_end_request(cmd, 1, good_bytes, result == 0);891860892861 /*893893- * If the command completed without error, then either finish off the894894- * rest of the command, or start a new one.862862+ * If the command completed without error, then either863863+ * finish off the rest of the command, or start a new one.895864 */896896- if (result == 0 || cmd == NULL ) {865865+ if (scsi_end_request(cmd, 1, good_bytes, result == 0) == NULL)897866 return;898898- }899867 }900868 /*901869 * Now, if we were good little boys and girls, Santa left us a request···908880 * and quietly refuse further access.909881 */910882 cmd->device->changed = 1;911911- cmd = scsi_end_request(cmd, 0,883883+ scsi_end_request(cmd, 0,912884 this_count, 1);913885 return;914886 } else {···942914 scsi_requeue_command(q, cmd);943915 result = 0;944916 } else {945945- cmd = scsi_end_request(cmd, 0, this_count, 1);917917+ scsi_end_request(cmd, 0, this_count, 1);946918 return;947919 }948920 break;···959931 dev_printk(KERN_INFO,960932 &cmd->device->sdev_gendev,961933 "Device not ready.\n");962962- cmd = scsi_end_request(cmd, 0, this_count, 1);934934+ scsi_end_request(cmd, 0, this_count, 1);963935 return;964936 case VOLUME_OVERFLOW:965937 if (!(req->flags & REQ_QUIET)) {···969941 __scsi_print_command(cmd->data_cmnd);970942 scsi_print_sense("", cmd);971943 }972972- cmd = scsi_end_request(cmd, 0, block_bytes, 1);944944+ scsi_end_request(cmd, 0, block_bytes, 1);973945 return;974946 default:975947 break;···1000972 block_bytes = req->hard_cur_sectors << 9;1001973 if (!block_bytes)1002974 block_bytes = req->data_len;10031003- cmd = scsi_end_request(cmd, 0, block_bytes, 1);975975+ scsi_end_request(cmd, 0, block_bytes, 1);1004976 }1005977}1006978EXPORT_SYMBOL(scsi_io_completion);···11461118 if (unlikely(!scsi_device_online(sdev))) {11471119 printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to offline device\n",11481120 sdev->host->host_no, sdev->id, sdev->lun);11491149- return BLKPREP_KILL;11211121+ goto kill;11501122 }11511123 if (unlikely(sdev->sdev_state != SDEV_RUNNING)) {11521124 /* OK, we're not in a running state don't prep···11561128 * at all allowed down */11571129 printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to dead device\n",11581130 sdev->host->host_no, sdev->id, sdev->lun);11591159- return BLKPREP_KILL;11311131+ goto kill;11601132 }11611133 /* OK, we only allow special commands (i.e. not11621134 * user initiated ones */···11881160 if(unlikely(specials_only) && !(req->flags & REQ_SPECIAL)) {11891161 if(specials_only == SDEV_QUIESCE ||11901162 specials_only == SDEV_BLOCK)11911191- return BLKPREP_DEFER;11631163+ goto defer;1192116411931165 printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to device being removed\n",11941166 sdev->host->host_no, sdev->id, sdev->lun);11951195- return BLKPREP_KILL;11671167+ goto kill;11961168 }1197116911981170···12101182 cmd->tag = req->tag;12111183 } else {12121184 blk_dump_rq_flags(req, "SCSI bad req");12131213- return BLKPREP_KILL;11851185+ goto kill;12141186 }1215118712161188 /* note the overloading of req->special. When the tag···12481220 * required).12491221 */12501222 ret = scsi_init_io(cmd);12511251- if (ret) /* BLKPREP_KILL return also releases the command */12521252- return ret;12231223+ switch(ret) {12241224+ case BLKPREP_KILL:12251225+ /* BLKPREP_KILL return also releases the command */12261226+ goto kill;12271227+ case BLKPREP_DEFER:12281228+ goto defer;12291229+ }1253123012541231 /*12551232 * Initialize the actual SCSI command for this request.···12641231 if (unlikely(!drv->init_command(cmd))) {12651232 scsi_release_buffers(cmd);12661233 scsi_put_command(cmd);12671267- return BLKPREP_KILL;12341234+ goto kill;12681235 }12691236 } else {12701237 memcpy(cmd->cmnd, req->cmd, sizeof(cmd->cmnd));···12951262 if (sdev->device_busy == 0)12961263 blk_plug_device(q);12971264 return BLKPREP_DEFER;12651265+ kill:12661266+ req->errors = DID_NO_CONNECT << 16;12671267+ return BLKPREP_KILL;12981268}1299126913001270/*···13721336}1373133713741338/*13751375- * Kill requests for a dead device13391339+ * Kill a request for a dead device13761340 */13771377-static void scsi_kill_requests(request_queue_t *q)13411341+static void scsi_kill_request(struct request *req, request_queue_t *q)13781342{13791379- struct request *req;13431343+ struct scsi_cmnd *cmd = req->special;1380134413811381- while ((req = elv_next_request(q)) != NULL) {13821382- blkdev_dequeue_request(req);13831383- req->flags |= REQ_QUIET;13841384- while (end_that_request_first(req, 0, req->nr_sectors))13851385- ;13861386- end_that_request_last(req);13451345+ blkdev_dequeue_request(req);13461346+13471347+ if (unlikely(cmd == NULL)) {13481348+ printk(KERN_CRIT "impossible request in %s.\n",13491349+ __FUNCTION__);13501350+ BUG();13871351 }13521352+13531353+ scsi_init_cmd_errh(cmd);13541354+ cmd->result = DID_NO_CONNECT << 16;13551355+ atomic_inc(&cmd->device->iorequest_cnt);13561356+ __scsi_done(cmd);13881357}1389135813901359/*···1412137114131372 if (!sdev) {14141373 printk("scsi: killing requests for dead queue\n");14151415- scsi_kill_requests(q);13741374+ while ((req = elv_next_request(q)) != NULL)13751375+ scsi_kill_request(req, q);14161376 return;14171377 }14181378···14401398 if (unlikely(!scsi_device_online(sdev))) {14411399 printk(KERN_ERR "scsi%d (%d:%d): rejecting I/O to offline device\n",14421400 sdev->host->host_no, sdev->id, sdev->lun);14431443- blkdev_dequeue_request(req);14441444- req->flags |= REQ_QUIET;14451445- while (end_that_request_first(req, 0, req->nr_sectors))14461446- ;14471447- end_that_request_last(req);14011401+ scsi_kill_request(req, q);14481402 continue;14491403 }14501404···14531415 sdev->device_busy++;1454141614551417 spin_unlock(q->queue_lock);14181418+ cmd = req->special;14191419+ if (unlikely(cmd == NULL)) {14201420+ printk(KERN_CRIT "impossible request in %s.\n"14211421+ "please mail a stack trace to "14221422+ "linux-scsi@vger.kernel.org",14231423+ __FUNCTION__);14241424+ BUG();14251425+ }14561426 spin_lock(shost->host_lock);1457142714581428 if (!scsi_host_queue_ready(q, shost, sdev))···14781432 * take the lock again.14791433 */14801434 spin_unlock_irq(shost->host_lock);14811481-14821482- cmd = req->special;14831483- if (unlikely(cmd == NULL)) {14841484- printk(KERN_CRIT "impossible request in %s.\n"14851485- "please mail a stack trace to "14861486- "linux-scsi@vger.kernel.org",14871487- __FUNCTION__);14881488- BUG();14891489- }1490143514911436 /*14921437 * Finally, initialize any error handling parameters, and set up···15141477 * cases (host limits or settings) should run the queue at some15151478 * later time.15161479 */14801480+ scsi_unprep_request(req);15171481 spin_lock_irq(q->queue_lock);15181482 blk_requeue_request(q, req);15191483 sdev->device_busy--;
···870870 out_free_sdev:871871 if (res == SCSI_SCAN_LUN_PRESENT) {872872 if (sdevp) {873873- scsi_device_get(sdev);874874- *sdevp = sdev;873873+ if (scsi_device_get(sdev) == 0) {874874+ *sdevp = sdev;875875+ } else {876876+ __scsi_remove_device(sdev);877877+ res = SCSI_SCAN_NO_RESPONSE;878878+ }875879 }876880 } else {877881 if (sdev->host->hostt->slave_destroy)···12641260}12651261EXPORT_SYMBOL(__scsi_add_device);1266126212631263+int scsi_add_device(struct Scsi_Host *host, uint channel,12641264+ uint target, uint lun)12651265+{12661266+ struct scsi_device *sdev = 12671267+ __scsi_add_device(host, channel, target, lun, NULL);12681268+ if (IS_ERR(sdev))12691269+ return PTR_ERR(sdev);12701270+12711271+ scsi_device_put(sdev);12721272+ return 0;12731273+}12741274+EXPORT_SYMBOL(scsi_add_device);12751275+12671276void scsi_rescan_device(struct device *dev)12681277{12691278 struct scsi_driver *drv;···12931276}12941277EXPORT_SYMBOL(scsi_rescan_device);1295127812961296-/**12971297- * scsi_scan_target - scan a target id, possibly including all LUNs on the12981298- * target.12991299- * @sdevsca: Scsi_Device handle for scanning13001300- * @shost: host to scan13011301- * @channel: channel to scan13021302- * @id: target id to scan13031303- *13041304- * Description:13051305- * Scan the target id on @shost, @channel, and @id. Scan at least LUN13061306- * 0, and possibly all LUNs on the target id.13071307- *13081308- * Use the pre-allocated @sdevscan as a handle for the scanning. This13091309- * function sets sdevscan->host, sdevscan->id and sdevscan->lun; the13101310- * scanning functions modify sdevscan->lun.13111311- *13121312- * First try a REPORT LUN scan, if that does not scan the target, do a13131313- * sequential scan of LUNs on the target id.13141314- **/13151315-void scsi_scan_target(struct device *parent, unsigned int channel,13161316- unsigned int id, unsigned int lun, int rescan)12791279+static void __scsi_scan_target(struct device *parent, unsigned int channel,12801280+ unsigned int id, unsigned int lun, int rescan)13171281{13181282 struct Scsi_Host *shost = dev_to_shost(parent);13191283 int bflags = 0;···13081310 */13091311 return;1310131213111311-13121313 starget = scsi_alloc_target(parent, channel, id);13131313-13141314 if (!starget)13151315 return;13161316···1354135813551359 put_device(&starget->dev);13561360}13611361+13621362+/**13631363+ * scsi_scan_target - scan a target id, possibly including all LUNs on the13641364+ * target.13651365+ * @parent: host to scan13661366+ * @channel: channel to scan13671367+ * @id: target id to scan13681368+ * @lun: Specific LUN to scan or SCAN_WILD_CARD13691369+ * @rescan: passed to LUN scanning routines13701370+ *13711371+ * Description:13721372+ * Scan the target id on @parent, @channel, and @id. Scan at least LUN 0,13731373+ * and possibly all LUNs on the target id.13741374+ *13751375+ * First try a REPORT LUN scan, if that does not scan the target, do a13761376+ * sequential scan of LUNs on the target id.13771377+ **/13781378+void scsi_scan_target(struct device *parent, unsigned int channel,13791379+ unsigned int id, unsigned int lun, int rescan)13801380+{13811381+ struct Scsi_Host *shost = dev_to_shost(parent);13821382+13831383+ down(&shost->scan_mutex);13841384+ if (scsi_host_scan_allowed(shost))13851385+ __scsi_scan_target(parent, channel, id, lun, rescan);13861386+ up(&shost->scan_mutex);13871387+}13571388EXPORT_SYMBOL(scsi_scan_target);1358138913591390static void scsi_scan_channel(struct Scsi_Host *shost, unsigned int channel,···14061383 order_id = shost->max_id - id - 1;14071384 else14081385 order_id = id;14091409- scsi_scan_target(&shost->shost_gendev, channel, order_id, lun, rescan);13861386+ __scsi_scan_target(&shost->shost_gendev, channel,13871387+ order_id, lun, rescan);14101388 }14111389 else14121412- scsi_scan_target(&shost->shost_gendev, channel, id, lun, rescan);13901390+ __scsi_scan_target(&shost->shost_gendev, channel,13911391+ id, lun, rescan);14131392}1414139314151394int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel,···15091484 */15101485struct scsi_device *scsi_get_host_dev(struct Scsi_Host *shost)15111486{15121512- struct scsi_device *sdev;14871487+ struct scsi_device *sdev = NULL;15131488 struct scsi_target *starget;1514148914901490+ down(&shost->scan_mutex);14911491+ if (!scsi_host_scan_allowed(shost))14921492+ goto out;15151493 starget = scsi_alloc_target(&shost->shost_gendev, 0, shost->this_id);15161494 if (!starget)15171517- return NULL;14951495+ goto out;1518149615191497 sdev = scsi_alloc_sdev(starget, 0, NULL);15201498 if (sdev) {···15251497 sdev->borken = 0;15261498 }15271499 put_device(&starget->dev);15001500+ out:15011501+ up(&shost->scan_mutex);15281502 return sdev;15291503}15301504EXPORT_SYMBOL(scsi_get_host_dev);
+15-13
drivers/scsi/scsi_sysfs.c
···653653 error = attr_add(&sdev->sdev_gendev,654654 sdev->host->hostt->sdev_attrs[i]);655655 if (error) {656656- scsi_remove_device(sdev);656656+ __scsi_remove_device(sdev);657657 goto out;658658 }659659 }···667667 scsi_sysfs_sdev_attrs[i]);668668 error = device_create_file(&sdev->sdev_gendev, attr);669669 if (error) {670670- scsi_remove_device(sdev);670670+ __scsi_remove_device(sdev);671671 goto out;672672 }673673 }···687687 return error;688688}689689690690-/**691691- * scsi_remove_device - unregister a device from the scsi bus692692- * @sdev: scsi_device to unregister693693- **/694694-void scsi_remove_device(struct scsi_device *sdev)690690+void __scsi_remove_device(struct scsi_device *sdev)695691{696696- struct Scsi_Host *shost = sdev->host;697697-698698- down(&shost->scan_mutex);699692 if (scsi_device_set_state(sdev, SDEV_CANCEL) != 0)700700- goto out;693693+ return;701694702695 class_device_unregister(&sdev->sdev_classdev);703696 device_del(&sdev->sdev_gendev);···699706 sdev->host->hostt->slave_destroy(sdev);700707 transport_unregister_device(&sdev->sdev_gendev);701708 put_device(&sdev->sdev_gendev);702702-out:703703- up(&shost->scan_mutex);709709+}710710+711711+/**712712+ * scsi_remove_device - unregister a device from the scsi bus713713+ * @sdev: scsi_device to unregister714714+ **/715715+void scsi_remove_device(struct scsi_device *sdev)716716+{717717+ down(&sdev->host->scan_mutex);718718+ __scsi_remove_device(sdev);719719+ up(&sdev->host->scan_mutex);704720}705721EXPORT_SYMBOL(scsi_remove_device);706722
+820
drivers/scsi/scsi_transport_sas.c
···11+/*22+ * Copyright (C) 2005 Dell Inc.33+ * Released under GPL v2.44+ *55+ * Serial Attached SCSI (SAS) transport class.66+ *77+ * The SAS transport class contains common code to deal with SAS HBAs,88+ * an aproximated representation of SAS topologies in the driver model,99+ * and various sysfs attributes to expose these topologies and managment1010+ * interfaces to userspace.1111+ *1212+ * In addition to the basic SCSI core objects this transport class1313+ * introduces two additional intermediate objects: The SAS PHY1414+ * as represented by struct sas_phy defines an "outgoing" PHY on1515+ * a SAS HBA or Expander, and the SAS remote PHY represented by1616+ * struct sas_rphy defines an "incoming" PHY on a SAS Expander or1717+ * end device. Note that this is purely a software concept, the1818+ * underlying hardware for a PHY and a remote PHY is the exactly1919+ * the same.2020+ *2121+ * There is no concept of a SAS port in this code, users can see2222+ * what PHYs form a wide port based on the port_identifier attribute,2323+ * which is the same for all PHYs in a port.2424+ */2525+2626+#include <linux/init.h>2727+#include <linux/module.h>2828+#include <linux/err.h>2929+3030+#include <scsi/scsi_device.h>3131+#include <scsi/scsi_host.h>3232+#include <scsi/scsi_transport.h>3333+#include <scsi/scsi_transport_sas.h>3434+3535+3636+#define SAS_HOST_ATTRS 03737+#define SAS_PORT_ATTRS 113838+#define SAS_RPORT_ATTRS 53939+4040+struct sas_internal {4141+ struct scsi_transport_template t;4242+ struct sas_function_template *f;4343+4444+ struct class_device_attribute private_host_attrs[SAS_HOST_ATTRS];4545+ struct class_device_attribute private_phy_attrs[SAS_PORT_ATTRS];4646+ struct class_device_attribute private_rphy_attrs[SAS_RPORT_ATTRS];4747+4848+ struct transport_container phy_attr_cont;4949+ struct transport_container rphy_attr_cont;5050+5151+ /*5252+ * The array of null terminated pointers to attributes5353+ * needed by scsi_sysfs.c5454+ */5555+ struct class_device_attribute *host_attrs[SAS_HOST_ATTRS + 1];5656+ struct class_device_attribute *phy_attrs[SAS_PORT_ATTRS + 1];5757+ struct class_device_attribute *rphy_attrs[SAS_RPORT_ATTRS + 1];5858+};5959+#define to_sas_internal(tmpl) container_of(tmpl, struct sas_internal, t)6060+6161+struct sas_host_attrs {6262+ struct list_head rphy_list;6363+ spinlock_t lock;6464+ u32 next_target_id;6565+};6666+#define to_sas_host_attrs(host) ((struct sas_host_attrs *)(host)->shost_data)6767+6868+6969+/*7070+ * Hack to allow attributes of the same name in different objects.7171+ */7272+#define SAS_CLASS_DEVICE_ATTR(_prefix,_name,_mode,_show,_store) \7373+ struct class_device_attribute class_device_attr_##_prefix##_##_name = \7474+ __ATTR(_name,_mode,_show,_store)7575+7676+7777+/*7878+ * Pretty printing helpers7979+ */8080+8181+#define sas_bitfield_name_match(title, table) \8282+static ssize_t \8383+get_sas_##title##_names(u32 table_key, char *buf) \8484+{ \8585+ char *prefix = ""; \8686+ ssize_t len = 0; \8787+ int i; \8888+ \8989+ for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \9090+ if (table[i].value & table_key) { \9191+ len += sprintf(buf + len, "%s%s", \9292+ prefix, table[i].name); \9393+ prefix = ", "; \9494+ } \9595+ } \9696+ len += sprintf(buf + len, "\n"); \9797+ return len; \9898+}9999+100100+#define sas_bitfield_name_search(title, table) \101101+static ssize_t \102102+get_sas_##title##_names(u32 table_key, char *buf) \103103+{ \104104+ ssize_t len = 0; \105105+ int i; \106106+ \107107+ for (i = 0; i < sizeof(table)/sizeof(table[0]); i++) { \108108+ if (table[i].value == table_key) { \109109+ len += sprintf(buf + len, "%s", \110110+ table[i].name); \111111+ break; \112112+ } \113113+ } \114114+ len += sprintf(buf + len, "\n"); \115115+ return len; \116116+}117117+118118+static struct {119119+ u32 value;120120+ char *name;121121+} sas_device_type_names[] = {122122+ { SAS_PHY_UNUSED, "unused" },123123+ { SAS_END_DEVICE, "end device" },124124+ { SAS_EDGE_EXPANDER_DEVICE, "edge expander" },125125+ { SAS_FANOUT_EXPANDER_DEVICE, "fanout expander" },126126+};127127+sas_bitfield_name_search(device_type, sas_device_type_names)128128+129129+130130+static struct {131131+ u32 value;132132+ char *name;133133+} sas_protocol_names[] = {134134+ { SAS_PROTOCOL_SATA, "sata" },135135+ { SAS_PROTOCOL_SMP, "smp" },136136+ { SAS_PROTOCOL_STP, "stp" },137137+ { SAS_PROTOCOL_SSP, "ssp" },138138+};139139+sas_bitfield_name_match(protocol, sas_protocol_names)140140+141141+static struct {142142+ u32 value;143143+ char *name;144144+} sas_linkspeed_names[] = {145145+ { SAS_LINK_RATE_UNKNOWN, "Unknown" },146146+ { SAS_PHY_DISABLED, "Phy disabled" },147147+ { SAS_LINK_RATE_FAILED, "Link Rate failed" },148148+ { SAS_SATA_SPINUP_HOLD, "Spin-up hold" },149149+ { SAS_LINK_RATE_1_5_GBPS, "1.5 Gbit" },150150+ { SAS_LINK_RATE_3_0_GBPS, "3.0 Gbit" },151151+};152152+sas_bitfield_name_search(linkspeed, sas_linkspeed_names)153153+154154+155155+/*156156+ * SAS host attributes157157+ */158158+159159+static int sas_host_setup(struct transport_container *tc, struct device *dev,160160+ struct class_device *cdev)161161+{162162+ struct Scsi_Host *shost = dev_to_shost(dev);163163+ struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);164164+165165+ INIT_LIST_HEAD(&sas_host->rphy_list);166166+ spin_lock_init(&sas_host->lock);167167+ sas_host->next_target_id = 0;168168+ return 0;169169+}170170+171171+static DECLARE_TRANSPORT_CLASS(sas_host_class,172172+ "sas_host", sas_host_setup, NULL, NULL);173173+174174+static int sas_host_match(struct attribute_container *cont,175175+ struct device *dev)176176+{177177+ struct Scsi_Host *shost;178178+ struct sas_internal *i;179179+180180+ if (!scsi_is_host_device(dev))181181+ return 0;182182+ shost = dev_to_shost(dev);183183+184184+ if (!shost->transportt)185185+ return 0;186186+ if (shost->transportt->host_attrs.ac.class !=187187+ &sas_host_class.class)188188+ return 0;189189+190190+ i = to_sas_internal(shost->transportt);191191+ return &i->t.host_attrs.ac == cont;192192+}193193+194194+static int do_sas_phy_delete(struct device *dev, void *data)195195+{196196+ if (scsi_is_sas_phy(dev))197197+ sas_phy_delete(dev_to_phy(dev));198198+ return 0;199199+}200200+201201+/**202202+ * sas_remove_host -- tear down a Scsi_Host's SAS data structures203203+ * @shost: Scsi Host that is torn down204204+ *205205+ * Removes all SAS PHYs and remote PHYs for a given Scsi_Host.206206+ * Must be called just before scsi_remove_host for SAS HBAs.207207+ */208208+void sas_remove_host(struct Scsi_Host *shost)209209+{210210+ device_for_each_child(&shost->shost_gendev, NULL, do_sas_phy_delete);211211+}212212+EXPORT_SYMBOL(sas_remove_host);213213+214214+215215+/*216216+ * SAS Port attributes217217+ */218218+219219+#define sas_phy_show_simple(field, name, format_string, cast) \220220+static ssize_t \221221+show_sas_phy_##name(struct class_device *cdev, char *buf) \222222+{ \223223+ struct sas_phy *phy = transport_class_to_phy(cdev); \224224+ \225225+ return snprintf(buf, 20, format_string, cast phy->field); \226226+}227227+228228+#define sas_phy_simple_attr(field, name, format_string, type) \229229+ sas_phy_show_simple(field, name, format_string, (type)) \230230+static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)231231+232232+#define sas_phy_show_protocol(field, name) \233233+static ssize_t \234234+show_sas_phy_##name(struct class_device *cdev, char *buf) \235235+{ \236236+ struct sas_phy *phy = transport_class_to_phy(cdev); \237237+ \238238+ if (!phy->field) \239239+ return snprintf(buf, 20, "none\n"); \240240+ return get_sas_protocol_names(phy->field, buf); \241241+}242242+243243+#define sas_phy_protocol_attr(field, name) \244244+ sas_phy_show_protocol(field, name) \245245+static CLASS_DEVICE_ATTR(name, S_IRUGO, show_sas_phy_##name, NULL)246246+247247+#define sas_phy_show_linkspeed(field) \248248+static ssize_t \249249+show_sas_phy_##field(struct class_device *cdev, char *buf) \250250+{ \251251+ struct sas_phy *phy = transport_class_to_phy(cdev); \252252+ \253253+ return get_sas_linkspeed_names(phy->field, buf); \254254+}255255+256256+#define sas_phy_linkspeed_attr(field) \257257+ sas_phy_show_linkspeed(field) \258258+static CLASS_DEVICE_ATTR(field, S_IRUGO, show_sas_phy_##field, NULL)259259+260260+static ssize_t261261+show_sas_device_type(struct class_device *cdev, char *buf)262262+{263263+ struct sas_phy *phy = transport_class_to_phy(cdev);264264+265265+ if (!phy->identify.device_type)266266+ return snprintf(buf, 20, "none\n");267267+ return get_sas_device_type_names(phy->identify.device_type, buf);268268+}269269+270270+static CLASS_DEVICE_ATTR(device_type, S_IRUGO, show_sas_device_type, NULL);271271+272272+sas_phy_protocol_attr(identify.initiator_port_protocols,273273+ initiator_port_protocols);274274+sas_phy_protocol_attr(identify.target_port_protocols,275275+ target_port_protocols);276276+sas_phy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n",277277+ unsigned long long);278278+sas_phy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);279279+sas_phy_simple_attr(port_identifier, port_identifier, "%d\n", u8);280280+sas_phy_linkspeed_attr(negotiated_linkrate);281281+sas_phy_linkspeed_attr(minimum_linkrate_hw);282282+sas_phy_linkspeed_attr(minimum_linkrate);283283+sas_phy_linkspeed_attr(maximum_linkrate_hw);284284+sas_phy_linkspeed_attr(maximum_linkrate);285285+286286+287287+static DECLARE_TRANSPORT_CLASS(sas_phy_class,288288+ "sas_phy", NULL, NULL, NULL);289289+290290+static int sas_phy_match(struct attribute_container *cont, struct device *dev)291291+{292292+ struct Scsi_Host *shost;293293+ struct sas_internal *i;294294+295295+ if (!scsi_is_sas_phy(dev))296296+ return 0;297297+ shost = dev_to_shost(dev->parent);298298+299299+ if (!shost->transportt)300300+ return 0;301301+ if (shost->transportt->host_attrs.ac.class !=302302+ &sas_host_class.class)303303+ return 0;304304+305305+ i = to_sas_internal(shost->transportt);306306+ return &i->phy_attr_cont.ac == cont;307307+}308308+309309+static void sas_phy_release(struct device *dev)310310+{311311+ struct sas_phy *phy = dev_to_phy(dev);312312+313313+ put_device(dev->parent);314314+ kfree(phy);315315+}316316+317317+/**318318+ * sas_phy_alloc -- allocates and initialize a SAS PHY structure319319+ * @parent: Parent device320320+ * @number: Port number321321+ *322322+ * Allocates an SAS PHY structure. It will be added in the device tree323323+ * below the device specified by @parent, which has to be either a Scsi_Host324324+ * or sas_rphy.325325+ *326326+ * Returns:327327+ * SAS PHY allocated or %NULL if the allocation failed.328328+ */329329+struct sas_phy *sas_phy_alloc(struct device *parent, int number)330330+{331331+ struct Scsi_Host *shost = dev_to_shost(parent);332332+ struct sas_phy *phy;333333+334334+ phy = kmalloc(sizeof(*phy), GFP_KERNEL);335335+ if (!phy)336336+ return NULL;337337+ memset(phy, 0, sizeof(*phy));338338+339339+ get_device(parent);340340+341341+ phy->number = number;342342+343343+ device_initialize(&phy->dev);344344+ phy->dev.parent = get_device(parent);345345+ phy->dev.release = sas_phy_release;346346+ sprintf(phy->dev.bus_id, "phy-%d:%d", shost->host_no, number);347347+348348+ transport_setup_device(&phy->dev);349349+350350+ return phy;351351+}352352+EXPORT_SYMBOL(sas_phy_alloc);353353+354354+/**355355+ * sas_phy_add -- add a SAS PHY to the device hierachy356356+ * @phy: The PHY to be added357357+ *358358+ * Publishes a SAS PHY to the rest of the system.359359+ */360360+int sas_phy_add(struct sas_phy *phy)361361+{362362+ int error;363363+364364+ error = device_add(&phy->dev);365365+ if (!error) {366366+ transport_add_device(&phy->dev);367367+ transport_configure_device(&phy->dev);368368+ }369369+370370+ return error;371371+}372372+EXPORT_SYMBOL(sas_phy_add);373373+374374+/**375375+ * sas_phy_free -- free a SAS PHY376376+ * @phy: SAS PHY to free377377+ *378378+ * Frees the specified SAS PHY.379379+ *380380+ * Note:381381+ * This function must only be called on a PHY that has not382382+ * sucessfully been added using sas_phy_add().383383+ */384384+void sas_phy_free(struct sas_phy *phy)385385+{386386+ transport_destroy_device(&phy->dev);387387+ put_device(phy->dev.parent);388388+ put_device(phy->dev.parent);389389+ put_device(phy->dev.parent);390390+ kfree(phy);391391+}392392+EXPORT_SYMBOL(sas_phy_free);393393+394394+/**395395+ * sas_phy_delete -- remove SAS PHY396396+ * @phy: SAS PHY to remove397397+ *398398+ * Removes the specified SAS PHY. If the SAS PHY has an399399+ * associated remote PHY it is removed before.400400+ */401401+void402402+sas_phy_delete(struct sas_phy *phy)403403+{404404+ struct device *dev = &phy->dev;405405+406406+ if (phy->rphy)407407+ sas_rphy_delete(phy->rphy);408408+409409+ transport_remove_device(dev);410410+ device_del(dev);411411+ transport_destroy_device(dev);412412+ put_device(dev->parent);413413+}414414+EXPORT_SYMBOL(sas_phy_delete);415415+416416+/**417417+ * scsi_is_sas_phy -- check if a struct device represents a SAS PHY418418+ * @dev: device to check419419+ *420420+ * Returns:421421+ * %1 if the device represents a SAS PHY, %0 else422422+ */423423+int scsi_is_sas_phy(const struct device *dev)424424+{425425+ return dev->release == sas_phy_release;426426+}427427+EXPORT_SYMBOL(scsi_is_sas_phy);428428+429429+/*430430+ * SAS remote PHY attributes.431431+ */432432+433433+#define sas_rphy_show_simple(field, name, format_string, cast) \434434+static ssize_t \435435+show_sas_rphy_##name(struct class_device *cdev, char *buf) \436436+{ \437437+ struct sas_rphy *rphy = transport_class_to_rphy(cdev); \438438+ \439439+ return snprintf(buf, 20, format_string, cast rphy->field); \440440+}441441+442442+#define sas_rphy_simple_attr(field, name, format_string, type) \443443+ sas_rphy_show_simple(field, name, format_string, (type)) \444444+static SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \445445+ show_sas_rphy_##name, NULL)446446+447447+#define sas_rphy_show_protocol(field, name) \448448+static ssize_t \449449+show_sas_rphy_##name(struct class_device *cdev, char *buf) \450450+{ \451451+ struct sas_rphy *rphy = transport_class_to_rphy(cdev); \452452+ \453453+ if (!rphy->field) \454454+ return snprintf(buf, 20, "none\n"); \455455+ return get_sas_protocol_names(rphy->field, buf); \456456+}457457+458458+#define sas_rphy_protocol_attr(field, name) \459459+ sas_rphy_show_protocol(field, name) \460460+static SAS_CLASS_DEVICE_ATTR(rphy, name, S_IRUGO, \461461+ show_sas_rphy_##name, NULL)462462+463463+static ssize_t464464+show_sas_rphy_device_type(struct class_device *cdev, char *buf)465465+{466466+ struct sas_rphy *rphy = transport_class_to_rphy(cdev);467467+468468+ if (!rphy->identify.device_type)469469+ return snprintf(buf, 20, "none\n");470470+ return get_sas_device_type_names(471471+ rphy->identify.device_type, buf);472472+}473473+474474+static SAS_CLASS_DEVICE_ATTR(rphy, device_type, S_IRUGO,475475+ show_sas_rphy_device_type, NULL);476476+477477+sas_rphy_protocol_attr(identify.initiator_port_protocols,478478+ initiator_port_protocols);479479+sas_rphy_protocol_attr(identify.target_port_protocols, target_port_protocols);480480+sas_rphy_simple_attr(identify.sas_address, sas_address, "0x%016llx\n",481481+ unsigned long long);482482+sas_rphy_simple_attr(identify.phy_identifier, phy_identifier, "%d\n", u8);483483+484484+static DECLARE_TRANSPORT_CLASS(sas_rphy_class,485485+ "sas_rphy", NULL, NULL, NULL);486486+487487+static int sas_rphy_match(struct attribute_container *cont, struct device *dev)488488+{489489+ struct Scsi_Host *shost;490490+ struct sas_internal *i;491491+492492+ if (!scsi_is_sas_rphy(dev))493493+ return 0;494494+ shost = dev_to_shost(dev->parent->parent);495495+496496+ if (!shost->transportt)497497+ return 0;498498+ if (shost->transportt->host_attrs.ac.class !=499499+ &sas_host_class.class)500500+ return 0;501501+502502+ i = to_sas_internal(shost->transportt);503503+ return &i->rphy_attr_cont.ac == cont;504504+}505505+506506+static void sas_rphy_release(struct device *dev)507507+{508508+ struct sas_rphy *rphy = dev_to_rphy(dev);509509+510510+ put_device(dev->parent);511511+ kfree(rphy);512512+}513513+514514+/**515515+ * sas_rphy_alloc -- allocates and initialize a SAS remote PHY structure516516+ * @parent: SAS PHY this remote PHY is conneted to517517+ *518518+ * Allocates an SAS remote PHY structure, connected to @parent.519519+ *520520+ * Returns:521521+ * SAS PHY allocated or %NULL if the allocation failed.522522+ */523523+struct sas_rphy *sas_rphy_alloc(struct sas_phy *parent)524524+{525525+ struct Scsi_Host *shost = dev_to_shost(&parent->dev);526526+ struct sas_rphy *rphy;527527+528528+ rphy = kmalloc(sizeof(*rphy), GFP_KERNEL);529529+ if (!rphy) {530530+ put_device(&parent->dev);531531+ return NULL;532532+ }533533+ memset(rphy, 0, sizeof(*rphy));534534+535535+ device_initialize(&rphy->dev);536536+ rphy->dev.parent = get_device(&parent->dev);537537+ rphy->dev.release = sas_rphy_release;538538+ sprintf(rphy->dev.bus_id, "rphy-%d:%d",539539+ shost->host_no, parent->number);540540+ transport_setup_device(&rphy->dev);541541+542542+ return rphy;543543+}544544+EXPORT_SYMBOL(sas_rphy_alloc);545545+546546+/**547547+ * sas_rphy_add -- add a SAS remote PHY to the device hierachy548548+ * @rphy: The remote PHY to be added549549+ *550550+ * Publishes a SAS remote PHY to the rest of the system.551551+ */552552+int sas_rphy_add(struct sas_rphy *rphy)553553+{554554+ struct sas_phy *parent = dev_to_phy(rphy->dev.parent);555555+ struct Scsi_Host *shost = dev_to_shost(parent->dev.parent);556556+ struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);557557+ struct sas_identify *identify = &rphy->identify;558558+ int error;559559+560560+ if (parent->rphy)561561+ return -ENXIO;562562+ parent->rphy = rphy;563563+564564+ error = device_add(&rphy->dev);565565+ if (error)566566+ return error;567567+ transport_add_device(&rphy->dev);568568+ transport_configure_device(&rphy->dev);569569+570570+ spin_lock(&sas_host->lock);571571+ list_add_tail(&rphy->list, &sas_host->rphy_list);572572+ if (identify->device_type == SAS_END_DEVICE &&573573+ (identify->target_port_protocols &574574+ (SAS_PROTOCOL_SSP|SAS_PROTOCOL_STP|SAS_PROTOCOL_SATA)))575575+ rphy->scsi_target_id = sas_host->next_target_id++;576576+ else577577+ rphy->scsi_target_id = -1;578578+ spin_unlock(&sas_host->lock);579579+580580+ if (rphy->scsi_target_id != -1) {581581+ scsi_scan_target(&rphy->dev, parent->number,582582+ rphy->scsi_target_id, ~0, 0);583583+ }584584+585585+ return 0;586586+}587587+EXPORT_SYMBOL(sas_rphy_add);588588+589589+/**590590+ * sas_rphy_free -- free a SAS remote PHY591591+ * @rphy SAS remote PHY to free592592+ *593593+ * Frees the specified SAS remote PHY.594594+ *595595+ * Note:596596+ * This function must only be called on a remote597597+ * PHY that has not sucessfully been added using598598+ * sas_rphy_add().599599+ */600600+void sas_rphy_free(struct sas_rphy *rphy)601601+{602602+ struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);603603+ struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);604604+605605+ spin_lock(&sas_host->lock);606606+ list_del(&rphy->list);607607+ spin_unlock(&sas_host->lock);608608+609609+ transport_destroy_device(&rphy->dev);610610+ put_device(rphy->dev.parent);611611+ put_device(rphy->dev.parent);612612+ put_device(rphy->dev.parent);613613+ kfree(rphy);614614+}615615+EXPORT_SYMBOL(sas_rphy_free);616616+617617+/**618618+ * sas_rphy_delete -- remove SAS remote PHY619619+ * @rphy: SAS remote PHY to remove620620+ *621621+ * Removes the specified SAS remote PHY.622622+ */623623+void624624+sas_rphy_delete(struct sas_rphy *rphy)625625+{626626+ struct device *dev = &rphy->dev;627627+ struct sas_phy *parent = dev_to_phy(dev->parent);628628+ struct Scsi_Host *shost = dev_to_shost(parent->dev.parent);629629+ struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);630630+631631+ transport_destroy_device(&rphy->dev);632632+633633+ scsi_remove_target(&rphy->dev);634634+635635+ spin_lock(&sas_host->lock);636636+ list_del(&rphy->list);637637+ spin_unlock(&sas_host->lock);638638+639639+ transport_remove_device(dev);640640+ device_del(dev);641641+ transport_destroy_device(dev);642642+ put_device(&parent->dev);643643+}644644+EXPORT_SYMBOL(sas_rphy_delete);645645+646646+/**647647+ * scsi_is_sas_rphy -- check if a struct device represents a SAS remote PHY648648+ * @dev: device to check649649+ *650650+ * Returns:651651+ * %1 if the device represents a SAS remote PHY, %0 else652652+ */653653+int scsi_is_sas_rphy(const struct device *dev)654654+{655655+ return dev->release == sas_rphy_release;656656+}657657+EXPORT_SYMBOL(scsi_is_sas_rphy);658658+659659+660660+/*661661+ * SCSI scan helper662662+ */663663+664664+static struct device *sas_target_parent(struct Scsi_Host *shost,665665+ int channel, uint id)666666+{667667+ struct sas_host_attrs *sas_host = to_sas_host_attrs(shost);668668+ struct sas_rphy *rphy;669669+ struct device *dev = NULL;670670+671671+ spin_lock(&sas_host->lock);672672+ list_for_each_entry(rphy, &sas_host->rphy_list, list) {673673+ struct sas_phy *parent = dev_to_phy(rphy->dev.parent);674674+ if (parent->number == channel &&675675+ rphy->scsi_target_id == id)676676+ dev = &rphy->dev;677677+ }678678+ spin_unlock(&sas_host->lock);679679+680680+ return dev;681681+}682682+683683+684684+/*685685+ * Setup / Teardown code686686+ */687687+688688+#define SETUP_RPORT_ATTRIBUTE(field) \689689+ i->private_rphy_attrs[count] = class_device_attr_##field; \690690+ i->private_rphy_attrs[count].attr.mode = S_IRUGO; \691691+ i->private_rphy_attrs[count].store = NULL; \692692+ i->rphy_attrs[count] = &i->private_rphy_attrs[count]; \693693+ count++694694+695695+#define SETUP_PORT_ATTRIBUTE(field) \696696+ i->private_phy_attrs[count] = class_device_attr_##field; \697697+ i->private_phy_attrs[count].attr.mode = S_IRUGO; \698698+ i->private_phy_attrs[count].store = NULL; \699699+ i->phy_attrs[count] = &i->private_phy_attrs[count]; \700700+ count++701701+702702+703703+/**704704+ * sas_attach_transport -- instantiate SAS transport template705705+ * @ft: SAS transport class function template706706+ */707707+struct scsi_transport_template *708708+sas_attach_transport(struct sas_function_template *ft)709709+{710710+ struct sas_internal *i;711711+ int count;712712+713713+ i = kmalloc(sizeof(struct sas_internal), GFP_KERNEL);714714+ if (!i)715715+ return NULL;716716+ memset(i, 0, sizeof(struct sas_internal));717717+718718+ i->t.target_parent = sas_target_parent;719719+720720+ i->t.host_attrs.ac.attrs = &i->host_attrs[0];721721+ i->t.host_attrs.ac.class = &sas_host_class.class;722722+ i->t.host_attrs.ac.match = sas_host_match;723723+ transport_container_register(&i->t.host_attrs);724724+ i->t.host_size = sizeof(struct sas_host_attrs);725725+726726+ i->phy_attr_cont.ac.class = &sas_phy_class.class;727727+ i->phy_attr_cont.ac.attrs = &i->phy_attrs[0];728728+ i->phy_attr_cont.ac.match = sas_phy_match;729729+ transport_container_register(&i->phy_attr_cont);730730+731731+ i->rphy_attr_cont.ac.class = &sas_rphy_class.class;732732+ i->rphy_attr_cont.ac.attrs = &i->rphy_attrs[0];733733+ i->rphy_attr_cont.ac.match = sas_rphy_match;734734+ transport_container_register(&i->rphy_attr_cont);735735+736736+ i->f = ft;737737+738738+ count = 0;739739+ i->host_attrs[count] = NULL;740740+741741+ count = 0;742742+ SETUP_PORT_ATTRIBUTE(initiator_port_protocols);743743+ SETUP_PORT_ATTRIBUTE(target_port_protocols);744744+ SETUP_PORT_ATTRIBUTE(device_type);745745+ SETUP_PORT_ATTRIBUTE(sas_address);746746+ SETUP_PORT_ATTRIBUTE(phy_identifier);747747+ SETUP_PORT_ATTRIBUTE(port_identifier);748748+ SETUP_PORT_ATTRIBUTE(negotiated_linkrate);749749+ SETUP_PORT_ATTRIBUTE(minimum_linkrate_hw);750750+ SETUP_PORT_ATTRIBUTE(minimum_linkrate);751751+ SETUP_PORT_ATTRIBUTE(maximum_linkrate_hw);752752+ SETUP_PORT_ATTRIBUTE(maximum_linkrate);753753+ i->phy_attrs[count] = NULL;754754+755755+ count = 0;756756+ SETUP_RPORT_ATTRIBUTE(rphy_initiator_port_protocols);757757+ SETUP_RPORT_ATTRIBUTE(rphy_target_port_protocols);758758+ SETUP_RPORT_ATTRIBUTE(rphy_device_type);759759+ SETUP_RPORT_ATTRIBUTE(rphy_sas_address);760760+ SETUP_RPORT_ATTRIBUTE(rphy_phy_identifier);761761+ i->rphy_attrs[count] = NULL;762762+763763+ return &i->t;764764+}765765+EXPORT_SYMBOL(sas_attach_transport);766766+767767+/**768768+ * sas_release_transport -- release SAS transport template instance769769+ * @t: transport template instance770770+ */771771+void sas_release_transport(struct scsi_transport_template *t)772772+{773773+ struct sas_internal *i = to_sas_internal(t);774774+775775+ transport_container_unregister(&i->t.host_attrs);776776+ transport_container_unregister(&i->phy_attr_cont);777777+ transport_container_unregister(&i->rphy_attr_cont);778778+779779+ kfree(i);780780+}781781+EXPORT_SYMBOL(sas_release_transport);782782+783783+static __init int sas_transport_init(void)784784+{785785+ int error;786786+787787+ error = transport_class_register(&sas_host_class);788788+ if (error)789789+ goto out;790790+ error = transport_class_register(&sas_phy_class);791791+ if (error)792792+ goto out_unregister_transport;793793+ error = transport_class_register(&sas_rphy_class);794794+ if (error)795795+ goto out_unregister_phy;796796+797797+ return 0;798798+799799+ out_unregister_phy:800800+ transport_class_unregister(&sas_phy_class);801801+ out_unregister_transport:802802+ transport_class_unregister(&sas_host_class);803803+ out:804804+ return error;805805+806806+}807807+808808+static void __exit sas_transport_exit(void)809809+{810810+ transport_class_unregister(&sas_host_class);811811+ transport_class_unregister(&sas_phy_class);812812+ transport_class_unregister(&sas_rphy_class);813813+}814814+815815+MODULE_AUTHOR("Christoph Hellwig");816816+MODULE_DESCRIPTION("SAS Transphy Attributes");817817+MODULE_LICENSE("GPL");818818+819819+module_init(sas_transport_init);820820+module_exit(sas_transport_exit);
+2-2
drivers/scsi/sg.c
···61616262#ifdef CONFIG_SCSI_PROC_FS6363#include <linux/proc_fs.h>6464-static char *sg_version_date = "20050901";6464+static char *sg_version_date = "20050908";65656666static int sg_proc_init(void);6767static void sg_proc_cleanup(void);···12991299 sg_rb_correct4mmap(rsv_schp, 1); /* do only once per fd lifetime */13001300 sfp->mmap_called = 1;13011301 }13021302- vma->vm_flags |= (VM_RESERVED | VM_IO);13021302+ vma->vm_flags |= VM_RESERVED;13031303 vma->vm_private_data = sfp;13041304 vma->vm_ops = &sg_mmap_vm_ops;13051305 return 0;