1*4882a593Smuzhiyun /* Copyright (c) 2013 Coraid, Inc. See COPYING for GPL terms. */ 2*4882a593Smuzhiyun #include <linux/blk-mq.h> 3*4882a593Smuzhiyun 4*4882a593Smuzhiyun #define VERSION "85" 5*4882a593Smuzhiyun #define AOE_MAJOR 152 6*4882a593Smuzhiyun #define DEVICE_NAME "aoe" 7*4882a593Smuzhiyun 8*4882a593Smuzhiyun /* set AOE_PARTITIONS to 1 to use whole-disks only 9*4882a593Smuzhiyun * default is 16, which is 15 partitions plus the whole disk 10*4882a593Smuzhiyun */ 11*4882a593Smuzhiyun #ifndef AOE_PARTITIONS 12*4882a593Smuzhiyun #define AOE_PARTITIONS (16) 13*4882a593Smuzhiyun #endif 14*4882a593Smuzhiyun 15*4882a593Smuzhiyun #define WHITESPACE " \t\v\f\n," 16*4882a593Smuzhiyun 17*4882a593Smuzhiyun enum { 18*4882a593Smuzhiyun AOECMD_ATA, 19*4882a593Smuzhiyun AOECMD_CFG, 20*4882a593Smuzhiyun AOECMD_VEND_MIN = 0xf0, 21*4882a593Smuzhiyun 22*4882a593Smuzhiyun AOEFL_RSP = (1<<3), 23*4882a593Smuzhiyun AOEFL_ERR = (1<<2), 24*4882a593Smuzhiyun 25*4882a593Smuzhiyun AOEAFL_EXT = (1<<6), 26*4882a593Smuzhiyun AOEAFL_DEV = (1<<4), 27*4882a593Smuzhiyun AOEAFL_ASYNC = (1<<1), 28*4882a593Smuzhiyun AOEAFL_WRITE = (1<<0), 29*4882a593Smuzhiyun 30*4882a593Smuzhiyun AOECCMD_READ = 0, 31*4882a593Smuzhiyun AOECCMD_TEST, 32*4882a593Smuzhiyun AOECCMD_PTEST, 33*4882a593Smuzhiyun AOECCMD_SET, 34*4882a593Smuzhiyun AOECCMD_FSET, 35*4882a593Smuzhiyun 36*4882a593Smuzhiyun AOE_HVER = 0x10, 37*4882a593Smuzhiyun }; 38*4882a593Smuzhiyun 39*4882a593Smuzhiyun struct aoe_hdr { 40*4882a593Smuzhiyun unsigned char dst[6]; 41*4882a593Smuzhiyun unsigned char src[6]; 42*4882a593Smuzhiyun __be16 type; 43*4882a593Smuzhiyun unsigned char verfl; 44*4882a593Smuzhiyun unsigned char err; 45*4882a593Smuzhiyun __be16 major; 46*4882a593Smuzhiyun unsigned char minor; 47*4882a593Smuzhiyun unsigned char cmd; 48*4882a593Smuzhiyun __be32 tag; 49*4882a593Smuzhiyun }; 50*4882a593Smuzhiyun 51*4882a593Smuzhiyun struct aoe_atahdr { 52*4882a593Smuzhiyun unsigned char aflags; 53*4882a593Smuzhiyun unsigned char errfeat; 54*4882a593Smuzhiyun unsigned char scnt; 55*4882a593Smuzhiyun unsigned char cmdstat; 56*4882a593Smuzhiyun unsigned char lba0; 57*4882a593Smuzhiyun unsigned char lba1; 58*4882a593Smuzhiyun unsigned char lba2; 59*4882a593Smuzhiyun unsigned char lba3; 60*4882a593Smuzhiyun unsigned char lba4; 61*4882a593Smuzhiyun unsigned char lba5; 62*4882a593Smuzhiyun unsigned char res[2]; 63*4882a593Smuzhiyun }; 64*4882a593Smuzhiyun 65*4882a593Smuzhiyun struct aoe_cfghdr { 66*4882a593Smuzhiyun __be16 bufcnt; 67*4882a593Smuzhiyun __be16 fwver; 68*4882a593Smuzhiyun unsigned char scnt; 69*4882a593Smuzhiyun unsigned char aoeccmd; 70*4882a593Smuzhiyun unsigned char cslen[2]; 71*4882a593Smuzhiyun }; 72*4882a593Smuzhiyun 73*4882a593Smuzhiyun enum { 74*4882a593Smuzhiyun DEVFL_UP = 1, /* device is installed in system and ready for AoE->ATA commands */ 75*4882a593Smuzhiyun DEVFL_TKILL = (1<<1), /* flag for timer to know when to kill self */ 76*4882a593Smuzhiyun DEVFL_EXT = (1<<2), /* device accepts lba48 commands */ 77*4882a593Smuzhiyun DEVFL_GDALLOC = (1<<3), /* need to alloc gendisk */ 78*4882a593Smuzhiyun DEVFL_GD_NOW = (1<<4), /* allocating gendisk */ 79*4882a593Smuzhiyun DEVFL_KICKME = (1<<5), /* slow polling network card catch */ 80*4882a593Smuzhiyun DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */ 81*4882a593Smuzhiyun DEVFL_FREEING = (1<<7), /* set when device is being cleaned up */ 82*4882a593Smuzhiyun DEVFL_FREED = (1<<8), /* device has been cleaned up */ 83*4882a593Smuzhiyun }; 84*4882a593Smuzhiyun 85*4882a593Smuzhiyun enum { 86*4882a593Smuzhiyun DEFAULTBCNT = 2 * 512, /* 2 sectors */ 87*4882a593Smuzhiyun MIN_BUFS = 16, 88*4882a593Smuzhiyun NTARGETS = 4, 89*4882a593Smuzhiyun NAOEIFS = 8, 90*4882a593Smuzhiyun NSKBPOOLMAX = 256, 91*4882a593Smuzhiyun NFACTIVE = 61, 92*4882a593Smuzhiyun 93*4882a593Smuzhiyun TIMERTICK = HZ / 10, 94*4882a593Smuzhiyun RTTSCALE = 8, 95*4882a593Smuzhiyun RTTDSCALE = 3, 96*4882a593Smuzhiyun RTTAVG_INIT = USEC_PER_SEC / 4 << RTTSCALE, 97*4882a593Smuzhiyun RTTDEV_INIT = RTTAVG_INIT / 4, 98*4882a593Smuzhiyun 99*4882a593Smuzhiyun HARD_SCORN_SECS = 10, /* try another remote port after this */ 100*4882a593Smuzhiyun MAX_TAINT = 1000, /* cap on aoetgt taint */ 101*4882a593Smuzhiyun }; 102*4882a593Smuzhiyun 103*4882a593Smuzhiyun struct aoe_req { 104*4882a593Smuzhiyun unsigned long nr_bios; 105*4882a593Smuzhiyun }; 106*4882a593Smuzhiyun 107*4882a593Smuzhiyun struct buf { 108*4882a593Smuzhiyun ulong nframesout; 109*4882a593Smuzhiyun struct bio *bio; 110*4882a593Smuzhiyun struct bvec_iter iter; 111*4882a593Smuzhiyun struct request *rq; 112*4882a593Smuzhiyun }; 113*4882a593Smuzhiyun 114*4882a593Smuzhiyun enum frame_flags { 115*4882a593Smuzhiyun FFL_PROBE = 1, 116*4882a593Smuzhiyun }; 117*4882a593Smuzhiyun 118*4882a593Smuzhiyun struct frame { 119*4882a593Smuzhiyun struct list_head head; 120*4882a593Smuzhiyun u32 tag; 121*4882a593Smuzhiyun ktime_t sent; /* high-res time packet was sent */ 122*4882a593Smuzhiyun ulong waited; 123*4882a593Smuzhiyun ulong waited_total; 124*4882a593Smuzhiyun struct aoetgt *t; /* parent target I belong to */ 125*4882a593Smuzhiyun struct sk_buff *skb; /* command skb freed on module exit */ 126*4882a593Smuzhiyun struct sk_buff *r_skb; /* response skb for async processing */ 127*4882a593Smuzhiyun struct buf *buf; 128*4882a593Smuzhiyun struct bvec_iter iter; 129*4882a593Smuzhiyun char flags; 130*4882a593Smuzhiyun }; 131*4882a593Smuzhiyun 132*4882a593Smuzhiyun struct aoeif { 133*4882a593Smuzhiyun struct net_device *nd; 134*4882a593Smuzhiyun ulong lost; 135*4882a593Smuzhiyun int bcnt; 136*4882a593Smuzhiyun }; 137*4882a593Smuzhiyun 138*4882a593Smuzhiyun struct aoetgt { 139*4882a593Smuzhiyun unsigned char addr[6]; 140*4882a593Smuzhiyun ushort nframes; /* cap on frames to use */ 141*4882a593Smuzhiyun struct aoedev *d; /* parent device I belong to */ 142*4882a593Smuzhiyun struct list_head ffree; /* list of free frames */ 143*4882a593Smuzhiyun struct aoeif ifs[NAOEIFS]; 144*4882a593Smuzhiyun struct aoeif *ifp; /* current aoeif in use */ 145*4882a593Smuzhiyun ushort nout; /* number of AoE commands outstanding */ 146*4882a593Smuzhiyun ushort maxout; /* current value for max outstanding */ 147*4882a593Smuzhiyun ushort next_cwnd; /* incr maxout after decrementing to zero */ 148*4882a593Smuzhiyun ushort ssthresh; /* slow start threshold */ 149*4882a593Smuzhiyun ulong falloc; /* number of allocated frames */ 150*4882a593Smuzhiyun int taint; /* how much we want to avoid this aoetgt */ 151*4882a593Smuzhiyun int minbcnt; 152*4882a593Smuzhiyun int wpkts, rpkts; 153*4882a593Smuzhiyun char nout_probes; 154*4882a593Smuzhiyun }; 155*4882a593Smuzhiyun 156*4882a593Smuzhiyun struct aoedev { 157*4882a593Smuzhiyun struct aoedev *next; 158*4882a593Smuzhiyun ulong sysminor; 159*4882a593Smuzhiyun ulong aoemajor; 160*4882a593Smuzhiyun u32 rttavg; /* scaled AoE round trip time average */ 161*4882a593Smuzhiyun u32 rttdev; /* scaled round trip time mean deviation */ 162*4882a593Smuzhiyun u16 aoeminor; 163*4882a593Smuzhiyun u16 flags; 164*4882a593Smuzhiyun u16 nopen; /* (bd_openers isn't available without sleeping) */ 165*4882a593Smuzhiyun u16 fw_ver; /* version of blade's firmware */ 166*4882a593Smuzhiyun u16 lasttag; /* last tag sent */ 167*4882a593Smuzhiyun u16 useme; 168*4882a593Smuzhiyun ulong ref; 169*4882a593Smuzhiyun struct work_struct work;/* disk create work struct */ 170*4882a593Smuzhiyun struct gendisk *gd; 171*4882a593Smuzhiyun struct dentry *debugfs; 172*4882a593Smuzhiyun struct request_queue *blkq; 173*4882a593Smuzhiyun struct list_head rq_list; 174*4882a593Smuzhiyun struct blk_mq_tag_set tag_set; 175*4882a593Smuzhiyun struct hd_geometry geo; 176*4882a593Smuzhiyun sector_t ssize; 177*4882a593Smuzhiyun struct timer_list timer; 178*4882a593Smuzhiyun spinlock_t lock; 179*4882a593Smuzhiyun struct sk_buff_head skbpool; 180*4882a593Smuzhiyun mempool_t *bufpool; /* for deadlock-free Buf allocation */ 181*4882a593Smuzhiyun struct { /* pointers to work in progress */ 182*4882a593Smuzhiyun struct buf *buf; 183*4882a593Smuzhiyun struct bio *nxbio; 184*4882a593Smuzhiyun struct request *rq; 185*4882a593Smuzhiyun } ip; 186*4882a593Smuzhiyun ulong maxbcnt; 187*4882a593Smuzhiyun struct list_head factive[NFACTIVE]; /* hash of active frames */ 188*4882a593Smuzhiyun struct list_head rexmitq; /* deferred retransmissions */ 189*4882a593Smuzhiyun struct aoetgt **targets; 190*4882a593Smuzhiyun ulong ntargets; /* number of allocated aoetgt pointers */ 191*4882a593Smuzhiyun struct aoetgt **tgt; /* target in use when working */ 192*4882a593Smuzhiyun ulong kicked; 193*4882a593Smuzhiyun char ident[512]; 194*4882a593Smuzhiyun }; 195*4882a593Smuzhiyun 196*4882a593Smuzhiyun /* kthread tracking */ 197*4882a593Smuzhiyun struct ktstate { 198*4882a593Smuzhiyun struct completion rendez; 199*4882a593Smuzhiyun struct task_struct *task; 200*4882a593Smuzhiyun wait_queue_head_t *waitq; 201*4882a593Smuzhiyun int (*fn) (int); 202*4882a593Smuzhiyun char name[12]; 203*4882a593Smuzhiyun spinlock_t *lock; 204*4882a593Smuzhiyun int id; 205*4882a593Smuzhiyun int active; 206*4882a593Smuzhiyun }; 207*4882a593Smuzhiyun 208*4882a593Smuzhiyun int aoeblk_init(void); 209*4882a593Smuzhiyun void aoeblk_exit(void); 210*4882a593Smuzhiyun void aoeblk_gdalloc(void *); 211*4882a593Smuzhiyun void aoedisk_rm_debugfs(struct aoedev *d); 212*4882a593Smuzhiyun 213*4882a593Smuzhiyun int aoechr_init(void); 214*4882a593Smuzhiyun void aoechr_exit(void); 215*4882a593Smuzhiyun void aoechr_error(char *); 216*4882a593Smuzhiyun 217*4882a593Smuzhiyun void aoecmd_work(struct aoedev *d); 218*4882a593Smuzhiyun void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor); 219*4882a593Smuzhiyun struct sk_buff *aoecmd_ata_rsp(struct sk_buff *); 220*4882a593Smuzhiyun void aoecmd_cfg_rsp(struct sk_buff *); 221*4882a593Smuzhiyun void aoecmd_sleepwork(struct work_struct *); 222*4882a593Smuzhiyun void aoecmd_wreset(struct aoetgt *t); 223*4882a593Smuzhiyun void aoecmd_cleanslate(struct aoedev *); 224*4882a593Smuzhiyun void aoecmd_exit(void); 225*4882a593Smuzhiyun int aoecmd_init(void); 226*4882a593Smuzhiyun struct sk_buff *aoecmd_ata_id(struct aoedev *); 227*4882a593Smuzhiyun void aoe_freetframe(struct frame *); 228*4882a593Smuzhiyun void aoe_flush_iocq(void); 229*4882a593Smuzhiyun void aoe_flush_iocq_by_index(int); 230*4882a593Smuzhiyun void aoe_end_request(struct aoedev *, struct request *, int); 231*4882a593Smuzhiyun int aoe_ktstart(struct ktstate *k); 232*4882a593Smuzhiyun void aoe_ktstop(struct ktstate *k); 233*4882a593Smuzhiyun 234*4882a593Smuzhiyun int aoedev_init(void); 235*4882a593Smuzhiyun void aoedev_exit(void); 236*4882a593Smuzhiyun struct aoedev *aoedev_by_aoeaddr(ulong maj, int min, int do_alloc); 237*4882a593Smuzhiyun void aoedev_downdev(struct aoedev *d); 238*4882a593Smuzhiyun int aoedev_flush(const char __user *str, size_t size); 239*4882a593Smuzhiyun void aoe_failbuf(struct aoedev *, struct buf *); 240*4882a593Smuzhiyun void aoedev_put(struct aoedev *); 241*4882a593Smuzhiyun 242*4882a593Smuzhiyun int aoenet_init(void); 243*4882a593Smuzhiyun void aoenet_exit(void); 244*4882a593Smuzhiyun void aoenet_xmit(struct sk_buff_head *); 245*4882a593Smuzhiyun int is_aoe_netif(struct net_device *ifp); 246*4882a593Smuzhiyun int set_aoe_iflist(const char __user *str, size_t size); 247