1ca47bbd9SEd Cashin /* Copyright (c) 2013 Coraid, Inc. See COPYING for GPL terms. */ 23582dd29SJens Axboe #include <linux/blk-mq.h> 33582dd29SJens Axboe 4896dcd9aSEd Cashin #define VERSION "85" 51da177e4SLinus Torvalds #define AOE_MAJOR 152 61da177e4SLinus Torvalds #define DEVICE_NAME "aoe" 7fc458dcdSecashin@coraid.com 8fc458dcdSecashin@coraid.com /* set AOE_PARTITIONS to 1 to use whole-disks only 9fc458dcdSecashin@coraid.com * default is 16, which is 15 partitions plus the whole disk 10fc458dcdSecashin@coraid.com */ 111da177e4SLinus Torvalds #ifndef AOE_PARTITIONS 12e39526e6SEd L Cashin #define AOE_PARTITIONS (16) 131da177e4SLinus Torvalds #endif 14fc458dcdSecashin@coraid.com 154a6c9ee9SEd Cashin #define WHITESPACE " \t\v\f\n," 161da177e4SLinus Torvalds 171da177e4SLinus Torvalds enum { 181da177e4SLinus Torvalds AOECMD_ATA, 191da177e4SLinus Torvalds AOECMD_CFG, 20b6d6c517SEd Cashin AOECMD_VEND_MIN = 0xf0, 211da177e4SLinus Torvalds 221da177e4SLinus Torvalds AOEFL_RSP = (1<<3), 231da177e4SLinus Torvalds AOEFL_ERR = (1<<2), 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds AOEAFL_EXT = (1<<6), 261da177e4SLinus Torvalds AOEAFL_DEV = (1<<4), 271da177e4SLinus Torvalds AOEAFL_ASYNC = (1<<1), 281da177e4SLinus Torvalds AOEAFL_WRITE = (1<<0), 291da177e4SLinus Torvalds 301da177e4SLinus Torvalds AOECCMD_READ = 0, 311da177e4SLinus Torvalds AOECCMD_TEST, 321da177e4SLinus Torvalds AOECCMD_PTEST, 331da177e4SLinus Torvalds AOECCMD_SET, 341da177e4SLinus Torvalds AOECCMD_FSET, 351da177e4SLinus Torvalds 361da177e4SLinus Torvalds AOE_HVER = 0x10, 371da177e4SLinus Torvalds }; 381da177e4SLinus Torvalds 391da177e4SLinus Torvalds struct aoe_hdr { 401da177e4SLinus Torvalds unsigned char dst[6]; 411da177e4SLinus Torvalds unsigned char src[6]; 4263e9cc5dSecashin@coraid.com __be16 type; 431da177e4SLinus Torvalds unsigned char verfl; 441da177e4SLinus Torvalds unsigned char err; 4563e9cc5dSecashin@coraid.com __be16 major; 461da177e4SLinus Torvalds unsigned char minor; 471da177e4SLinus Torvalds unsigned char cmd; 4863e9cc5dSecashin@coraid.com __be32 tag; 491da177e4SLinus Torvalds }; 501da177e4SLinus Torvalds 511da177e4SLinus Torvalds struct aoe_atahdr { 521da177e4SLinus Torvalds unsigned char aflags; 531da177e4SLinus Torvalds unsigned char errfeat; 541da177e4SLinus Torvalds unsigned char scnt; 551da177e4SLinus Torvalds unsigned char cmdstat; 561da177e4SLinus Torvalds unsigned char lba0; 571da177e4SLinus Torvalds unsigned char lba1; 581da177e4SLinus Torvalds unsigned char lba2; 591da177e4SLinus Torvalds unsigned char lba3; 601da177e4SLinus Torvalds unsigned char lba4; 611da177e4SLinus Torvalds unsigned char lba5; 621da177e4SLinus Torvalds unsigned char res[2]; 631da177e4SLinus Torvalds }; 641da177e4SLinus Torvalds 651da177e4SLinus Torvalds struct aoe_cfghdr { 6663e9cc5dSecashin@coraid.com __be16 bufcnt; 6763e9cc5dSecashin@coraid.com __be16 fwver; 6819bf2635SEd L. Cashin unsigned char scnt; 691da177e4SLinus Torvalds unsigned char aoeccmd; 701da177e4SLinus Torvalds unsigned char cslen[2]; 711da177e4SLinus Torvalds }; 721da177e4SLinus Torvalds 731da177e4SLinus Torvalds enum { 741da177e4SLinus Torvalds DEVFL_UP = 1, /* device is installed in system and ready for AoE->ATA commands */ 751da177e4SLinus Torvalds DEVFL_TKILL = (1<<1), /* flag for timer to know when to kill self */ 761da177e4SLinus Torvalds DEVFL_EXT = (1<<2), /* device accepts lba48 commands */ 77b21faa25SEd Cashin DEVFL_GDALLOC = (1<<3), /* need to alloc gendisk */ 78e52a2932SEd Cashin DEVFL_GD_NOW = (1<<4), /* allocating gendisk */ 79e52a2932SEd Cashin DEVFL_KICKME = (1<<5), /* slow polling network card catch */ 80e52a2932SEd Cashin DEVFL_NEWSIZE = (1<<6), /* need to update dev size in block layer */ 81e52a2932SEd Cashin DEVFL_FREEING = (1<<7), /* set when device is being cleaned up */ 82e52a2932SEd Cashin DEVFL_FREED = (1<<8), /* device has been cleaned up */ 831da177e4SLinus Torvalds }; 841da177e4SLinus Torvalds 851da177e4SLinus Torvalds enum { 8619bf2635SEd L. Cashin DEFAULTBCNT = 2 * 512, /* 2 sectors */ 8768e0d42fSEd L. Cashin MIN_BUFS = 16, 8871114ec4SEd Cashin NTARGETS = 4, 8968e0d42fSEd L. Cashin NAOEIFS = 8, 9069cf2d85SEd Cashin NSKBPOOLMAX = 256, 9164a80f5aSEd Cashin NFACTIVE = 61, 9268e0d42fSEd L. Cashin 9368e0d42fSEd L. Cashin TIMERTICK = HZ / 10, 943a0c40d2SEd Cashin RTTSCALE = 8, 953a0c40d2SEd Cashin RTTDSCALE = 3, 965f0c9c48SEd Cashin RTTAVG_INIT = USEC_PER_SEC / 4 << RTTSCALE, 973a0c40d2SEd Cashin RTTDEV_INIT = RTTAVG_INIT / 4, 98bbb44e30SEd Cashin 99bbb44e30SEd Cashin HARD_SCORN_SECS = 10, /* try another remote port after this */ 100bbb44e30SEd Cashin MAX_TAINT = 1000, /* cap on aoetgt taint */ 1011da177e4SLinus Torvalds }; 1021da177e4SLinus Torvalds 10361e7712eSChristoph Hellwig struct aoe_req { 10461e7712eSChristoph Hellwig unsigned long nr_bios; 10561e7712eSChristoph Hellwig }; 10661e7712eSChristoph Hellwig 1071da177e4SLinus Torvalds struct buf { 1081da177e4SLinus Torvalds ulong nframesout; 1091da177e4SLinus Torvalds struct bio *bio; 110feb261e2SKent Overstreet struct bvec_iter iter; 11169cf2d85SEd Cashin struct request *rq; 1121da177e4SLinus Torvalds }; 1131da177e4SLinus Torvalds 114bbb44e30SEd Cashin enum frame_flags { 115bbb44e30SEd Cashin FFL_PROBE = 1, 116bbb44e30SEd Cashin }; 117bbb44e30SEd Cashin 1181da177e4SLinus Torvalds struct frame { 119896831f5SEd Cashin struct list_head head; 120896831f5SEd Cashin u32 tag; 12185cf955dSTina Ruchandani ktime_t sent; /* high-res time packet was sent */ 1221da177e4SLinus Torvalds ulong waited; 1233fc9b032SEd Cashin ulong waited_total; 124896831f5SEd Cashin struct aoetgt *t; /* parent target I belong to */ 125896831f5SEd Cashin struct sk_buff *skb; /* command skb freed on module exit */ 126896831f5SEd Cashin struct sk_buff *r_skb; /* response skb for async processing */ 12769cf2d85SEd Cashin struct buf *buf; 128feb261e2SKent Overstreet struct bvec_iter iter; 129bbb44e30SEd Cashin char flags; 1301da177e4SLinus Torvalds }; 1311da177e4SLinus Torvalds 13268e0d42fSEd L. Cashin struct aoeif { 13368e0d42fSEd L. Cashin struct net_device *nd; 1343f0f0133SEd Cashin ulong lost; 1353f0f0133SEd Cashin int bcnt; 13668e0d42fSEd L. Cashin }; 13768e0d42fSEd L. Cashin 13868e0d42fSEd L. Cashin struct aoetgt { 13968e0d42fSEd L. Cashin unsigned char addr[6]; 1401b8a1636SEd Cashin ushort nframes; /* cap on frames to use */ 141896831f5SEd Cashin struct aoedev *d; /* parent device I belong to */ 142896831f5SEd Cashin struct list_head ffree; /* list of free frames */ 14368e0d42fSEd L. Cashin struct aoeif ifs[NAOEIFS]; 14468e0d42fSEd L. Cashin struct aoeif *ifp; /* current aoeif in use */ 14572837600SEd Cashin ushort nout; /* number of AoE commands outstanding */ 1461b8a1636SEd Cashin ushort maxout; /* current value for max outstanding */ 1473a0c40d2SEd Cashin ushort next_cwnd; /* incr maxout after decrementing to zero */ 1483a0c40d2SEd Cashin ushort ssthresh; /* slow start threshold */ 1491b8a1636SEd Cashin ulong falloc; /* number of allocated frames */ 150bbb44e30SEd Cashin int taint; /* how much we want to avoid this aoetgt */ 1513f0f0133SEd Cashin int minbcnt; 15268e0d42fSEd L. Cashin int wpkts, rpkts; 153bbb44e30SEd Cashin char nout_probes; 15468e0d42fSEd L. Cashin }; 15568e0d42fSEd L. Cashin 1561da177e4SLinus Torvalds struct aoedev { 1571da177e4SLinus Torvalds struct aoedev *next; 1581da177e4SLinus Torvalds ulong sysminor; 1591da177e4SLinus Torvalds ulong aoemajor; 1605f0c9c48SEd Cashin u32 rttavg; /* scaled AoE round trip time average */ 1615f0c9c48SEd Cashin u32 rttdev; /* scaled round trip time mean deviation */ 16268e0d42fSEd L. Cashin u16 aoeminor; 16368e0d42fSEd L. Cashin u16 flags; 164dced3a05SEd L. Cashin u16 nopen; /* (bd_openers isn't available without sleeping) */ 1651da177e4SLinus Torvalds u16 fw_ver; /* version of blade's firmware */ 16664a80f5aSEd Cashin u16 lasttag; /* last tag sent */ 16764a80f5aSEd Cashin u16 useme; 16869cf2d85SEd Cashin ulong ref; 1691da177e4SLinus Torvalds struct work_struct work;/* disk create work struct */ 1701da177e4SLinus Torvalds struct gendisk *gd; 171e8866cf2SEd Cashin struct dentry *debugfs; 1727135a71bSEd Cashin struct request_queue *blkq; 1733582dd29SJens Axboe struct list_head rq_list; 1743582dd29SJens Axboe struct blk_mq_tag_set tag_set; 1751da177e4SLinus Torvalds struct hd_geometry geo; 1761da177e4SLinus Torvalds sector_t ssize; 1771da177e4SLinus Torvalds struct timer_list timer; 1781da177e4SLinus Torvalds spinlock_t lock; 179e9bb8fb0SDavid S. Miller struct sk_buff_head skbpool; 1801da177e4SLinus Torvalds mempool_t *bufpool; /* for deadlock-free Buf allocation */ 18169cf2d85SEd Cashin struct { /* pointers to work in progress */ 18269cf2d85SEd Cashin struct buf *buf; 18369cf2d85SEd Cashin struct bio *nxbio; 18469cf2d85SEd Cashin struct request *rq; 18569cf2d85SEd Cashin } ip; 1863f0f0133SEd Cashin ulong maxbcnt; 18764a80f5aSEd Cashin struct list_head factive[NFACTIVE]; /* hash of active frames */ 1883a0c40d2SEd Cashin struct list_head rexmitq; /* deferred retransmissions */ 18971114ec4SEd Cashin struct aoetgt **targets; 19071114ec4SEd Cashin ulong ntargets; /* number of allocated aoetgt pointers */ 19168e0d42fSEd L. Cashin struct aoetgt **tgt; /* target in use when working */ 192896831f5SEd Cashin ulong kicked; 193667be1e7SEd Cashin char ident[512]; 1941da177e4SLinus Torvalds }; 1951da177e4SLinus Torvalds 196896831f5SEd Cashin /* kthread tracking */ 197896831f5SEd Cashin struct ktstate { 198896831f5SEd Cashin struct completion rendez; 199896831f5SEd Cashin struct task_struct *task; 200896831f5SEd Cashin wait_queue_head_t *waitq; 2018030d343SEd Cashin int (*fn) (int); 2028030d343SEd Cashin char name[12]; 203896831f5SEd Cashin spinlock_t *lock; 2048030d343SEd Cashin int id; 2058030d343SEd Cashin int active; 206896831f5SEd Cashin }; 2071da177e4SLinus Torvalds 2081da177e4SLinus Torvalds int aoeblk_init(void); 2091da177e4SLinus Torvalds void aoeblk_exit(void); 2101da177e4SLinus Torvalds void aoeblk_gdalloc(void *); 211e8866cf2SEd Cashin void aoedisk_rm_debugfs(struct aoedev *d); 2121da177e4SLinus Torvalds 2131da177e4SLinus Torvalds int aoechr_init(void); 2141da177e4SLinus Torvalds void aoechr_exit(void); 2151da177e4SLinus Torvalds void aoechr_error(char *); 2161da177e4SLinus Torvalds 2171da177e4SLinus Torvalds void aoecmd_work(struct aoedev *d); 2183ae1c24eSEd L. Cashin void aoecmd_cfg(ushort aoemajor, unsigned char aoeminor); 219896831f5SEd Cashin struct sk_buff *aoecmd_ata_rsp(struct sk_buff *); 2201da177e4SLinus Torvalds void aoecmd_cfg_rsp(struct sk_buff *); 221c4028958SDavid Howells void aoecmd_sleepwork(struct work_struct *); 2223a0c40d2SEd Cashin void aoecmd_wreset(struct aoetgt *t); 22368e0d42fSEd L. Cashin void aoecmd_cleanslate(struct aoedev *); 224896831f5SEd Cashin void aoecmd_exit(void); 225896831f5SEd Cashin int aoecmd_init(void); 22668e0d42fSEd L. Cashin struct sk_buff *aoecmd_ata_id(struct aoedev *); 227896831f5SEd Cashin void aoe_freetframe(struct frame *); 22869cf2d85SEd Cashin void aoe_flush_iocq(void); 2298030d343SEd Cashin void aoe_flush_iocq_by_index(int); 23069cf2d85SEd Cashin void aoe_end_request(struct aoedev *, struct request *, int); 231eb086ec5SEd Cashin int aoe_ktstart(struct ktstate *k); 232eb086ec5SEd Cashin void aoe_ktstop(struct ktstate *k); 2331da177e4SLinus Torvalds 2341da177e4SLinus Torvalds int aoedev_init(void); 2351da177e4SLinus Torvalds void aoedev_exit(void); 2360c966214SEd Cashin struct aoedev *aoedev_by_aoeaddr(ulong maj, int min, int do_alloc); 2371da177e4SLinus Torvalds void aoedev_downdev(struct aoedev *d); 238262bf541SEd L. Cashin int aoedev_flush(const char __user *str, size_t size); 23969cf2d85SEd Cashin void aoe_failbuf(struct aoedev *, struct buf *); 24069cf2d85SEd Cashin void aoedev_put(struct aoedev *); 2411da177e4SLinus Torvalds 2421da177e4SLinus Torvalds int aoenet_init(void); 2431da177e4SLinus Torvalds void aoenet_exit(void); 244e9bb8fb0SDavid S. Miller void aoenet_xmit(struct sk_buff_head *); 2451da177e4SLinus Torvalds int is_aoe_netif(struct net_device *ifp); 2461da177e4SLinus Torvalds int set_aoe_iflist(const char __user *str, size_t size); 247*0b8d7622STetsuo Handa 248*0b8d7622STetsuo Handa extern struct workqueue_struct *aoe_wq; 249